I have set up a CMake project whose directory structure looks as follows:
src/
--CMakeLists.txt
--libA/
----CMakeLists.txt
----foo.h
----foo.cpp
--main/
----CMakeLists.txt
----main.cpp
src/CMakeLists.txt
uses add_subdirectory
to pull in libA
and main
. libA/CMakeLists.txt
uses add_library
to define a library called libA
, which exports foo.h
via target_include_directories
. If I now link against libA
in main
using target_link_library
, I can include foo.h
via #include <foo.h>
in main.cpp
.
Question: Is it possible to provide the public interface of libA
with a prefix, so that I can (and have to) write #include <libA/foo.h>
in main.cpp
instead?
This is an old question but I was having exactly the same issue. I ended up getting around this by adding an export_headers()
function that creates symbolic links to the headers within the binary:
function(export_headers TARGET HEADER_SOURCE_DIR HEADER_DEST_DIR)
# Put all headers that are in the source directory into EXPORT_HEADERS variable
file(GLOB_RECURSE EXPORT_HEADERS CONFIGURE_DEPENDS
RELATIVE "${HEADER_SOURCE_DIR}"
"${HEADER_SOURCE_DIR}/*.h"
)
# For each header that will be exported
foreach(HEADER ${EXPORT_HEADERS})
# Get the directory portion that needs to be created
get_filename_component(HEADER_DIRECTORY "${HEADER}" DIRECTORY)
# Create the directory
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${HEADER_DEST_DIR}/${HEADER_DIRECTORY}"
)
if (MSVC)
# Make a hard link to the file
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND if not exist "${HEADER_DEST_DIR}/${HEADER}" \( mklink /h "${HEADER_DEST_DIR}/${HEADER}" "${HEADER_SOURCE_DIR}/${HEADER}" \)
)
else()
# Make a symbolic link to the file
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ln -sf "${HEADER_SOURCE_DIR}/${HEADER}" "${HEADER_DEST_DIR}/${HEADER}"
)
endif()
endforeach(HEADER)
endfunction()
You would call this with something like:
add_library(libA STATIC ${LIBA_SOURCES}
export_headers(libA ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include/libA)
target_include_directories(libA INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/include)
Then, if you link to libA
, you will be able to #include <libA/foo.h>
.
You can use the root source directory (or some other directory which is a parent to libA
) in the target_include_directories()
call. This will allow the INTERFACE_INCLUDE_DIRECTORIES
target property to be defined with respect to another directory (in this example, the CMAKE_SOURCE_DIR
). So it would look something like this:
In libA/CMakeLists.txt
:
add_library(libA foo.cpp)
# Define the include files with respect to the directory above this.
target_include_directories(libA PUBLIC ${CMAKE_SOURCE_DIR})
The main/main.cpp
file:
#include <iostream>
#include <libA/foo.h>
int main() {
FooClass fooclass;
fooclass.myFunction();
std::cout << "Hello World!" << std::endl;
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With