My project structure looks like this:
Parent/
CMakeLists.txt
file.cpp
third_party/
dependency/
CMakeLists.txt
lib/
dependency.lib
Note that dependency.lib is a precompiled/prebuilt library: I don't even have sources for it.
When I install Parent, I want it to go into a dist folder like this (within the previous tree structure but omitted for clarity):
Parent/
dist/
Parent/
include/
bin/
lib/
cmake/
ParentTargets.cmake
Parent.lib
dependency.lib
The idea here is to just get both the generated as well as the dependency libraries all in one place for easier install.
Relevant parts of Parent's CMakeLists.txt look like this (omitting a lot of stuff like includes, etc.):
cmake_minimum_required(VERSION 3.22)
project(Parent VERSION 0.1.0 LANGUAGES C CXX)
add_library(Parent)
target_sources(Parent PRIVATE file.cpp)
add_subdirectory("${CMAKE_SOURCE_DIR}/third_party/dependency")
target_link_libraries(Parent PRIVATE dependency)
# Manual copy of dependency.lib to install location
install(DIRECTORY "${CMAKE_SOURCE_DIR}/third_party/dependency/lib/"
DESTINATION lib
FILES_MATCHING
PATTERN "dependency.lib"
)
# Install all targets to ParentTargets export set.
# (omitting install dir variables, components, etc. for clarity)
install(
TARGETS
Parent dependency
EXPORT
ParentTargets
LIBRARY
DESTINATION lib
ARCHIVE
DESTINATION lib
)
# Write ParentTargets export set to targets file directly in install folder
install(EXPORT ParentTargets
FILE ParentTargets.cmake
NAMESPACE Parent::
DESTINATION lib/cmake
)
And this is what I have for the dependency's CMakeLists.txt:
add_library(dependency INTERFACE)
target_link_libraries(dependency
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/lib/dependency.lib>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/lib/dependency.lib>
)
This almost sort of works, the issue is that if you look at the generated ParentTargets.cmake, this is what CMake generates for the dependency target:
# Create imported target Parent::dependency
add_library(Parent::dependency INTERFACE IMPORTED)
set_target_properties(Parent::dependency PROPERTIES
INTERFACE_LINK_LIBRARIES "E:/absolute/path/Parent/dist/Parent/lib/dependency.lib"
)
...its a hard-coded absolute path to my installation directory. This is not great, and usually for built libraries CMake would have generated a path like ${_IMPORT_PREFIX}/lib/dependency.lib, which is what I wanted and important to have the install relocatable.
Here are my questions:
- Is this the right way of doing this? I could never find a good reference on how to package dependency static libraries alongside your project, and CMake doesn't seem to do this "on its own" too eagerly (I even had to manually copy the .lib there as you can see);
- How do I get CMake to use
${_IMPORT_PREFIX}there? I can't just use that on my CMakeLists.txt as it would evaluate to the empty string during generation, and I can't escape it like\${_IMPORT_PREFIX}as it still places the escaped version in ParentTargets.cmake...