I've seen in multiple places references to using generator expressions when defining include directories, so you can define different places for the includes during compilation and during installation. For example:
# Define headers for this library. PUBLIC headers are used for
# compiling the library, and will be added to consumers' build
# paths.
target_include_directories(lib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE src)
I'm building a library project and since I'm using standard paths (lib/
for the static library and include/
for the public headers), I was hoping to get away by setting CMAKE_INSTALL_PREFIX
and using a simple install()
call, such as:
set(CMAKE_INSTALL_PREFIX "${MY_INSTALL_DIR}")
install(TARGETS myLibrary ARCHIVE PUBLIC_HEADERS)
My expectations were that the DESTINATION
would be the default for both, so I'm just telling CMake to install these kind of files. Of course it doesn't work and I need to explicitly set the destination for both libraries and header files.
So the question remains: what is the use case for the generator expressions at the beginning, if I don't seem to be able to use the INSTALL_INTERFACE
anyway?
This is my sample CMakeLists.txt:
cmake_minimum_required(VERSION 3.12.1)
project(my_library C)
FILE(GLOB SOURCE_FILES src/*.c)
add_library(my_library ${SOURCE_FILES})
target_include_directories(my_library PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/output")
set(INSTALL_DIR "${OUTPUT_DIR}/my_library")
set(INSTALL_LIB_DIR "${INSTALL_DIR}/lib")
set(INSTALL_INC_DIR "${INSTALL_DIR}/include")
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR}")
install(TARGETS my_library ARCHIVE DESTINATION lib)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include" DESTINATION include)
# I was hoping I could do, after setting the headers with the INSTALL_INTERFACE generator expression
#install(TARGETS my_library ARCHIVE PUBLIC_HEADERS)
Generator-like expressions $<BUILD_INTERFACE>
and $<INSTALL_INTERFACE>
are used by CMake for distinguishing things, different for the build tree and for the install tree.
When building the project itself, $<BUILD_INTERFACE>
is used but $<INSTALL_INTERFACE>
is not.
When creating an export file with the install(EXPORT) command, things listed in $<INSTALL_INTERFACE>
will be included into it, but things in $<BUILD_INTERFACE>
won't.
But the creation of an export file with the export command uses $<BUILD_INTERFACE>
, but does not use $<INSTALL_INTERFACE>
.
Other for differentiate build and install trees expressions $<BUILD_INTERFACE>
and $<INSTALL_INTERFACE>
are not used.
E.g. $<INSTALL_INTERFACE>
does NOT affect the install(TARGETS .. PUBLIC_HEADERS)
command.
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