I am trying to combine several static libraries with CMake and I found an answer that suggests doing the following:
SET_TARGET_PROPERTIES(merged PROPERTIES STATIC_LIBRARY_FLAGS "full\path\to\lib1.lib full\path\to\lib2.lib")
The libraries I want to combine are the output of other targets and when I want to refer to the output of a target I usually use generator expression such as $< TARGET_FILE:MyLib>. However in this context it does not work because the generator expression does not get expanded before being passed to the linker and it complains that $< TARGET_FILE:MyLib> cannot be found.
This does not work:
set_target_properties(merged PROPERTIES STATIC_LIBRARY_FLAGS $<TARGET_FILE:MyLib>)
I guess I am meant to set the property to the path of the library:
set_target_properties(merged PROPERTIES STATIC_LIBRARY_FLAGS ${CURRENT_BIN_DIR}/MyLib.lib})
Generating this path manually can be tedious (I have many targets) and I was wondering if, given a target, there was a better way to get that path automatically.
For example (I am making up the syntax here):
set_target_properties(merged PROPERTIES STATIC_LIBRARY_FLAGS EXPAND_PATH($<TARGET_FILE:MyLib>))
You are right that generator expressions would have been the right choice - especially in multi-configuration environments - but if a certain command or property does not support them, you can't trick them into working.
But there are alternatives:
Setting ARCHIVE_OUTPUT_DIRECTORY
Property
You could slightly change your "I guess I am meant to" strategy and place your library outputs you want to merge into a path of your own choosing. The following example is for a multi-configuration environment like Visual Studio:
add_library(lib1 STATIC bar.cc)
set_target_properties(lib1 PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Libs")
file(WRITE dummy.cc "")
add_library(merged STATIC dummy.cc)
add_dependencies(merged lib1)
set_target_properties(
merged PROPERTIES
STATIC_LIBRARY_FLAGS_DEBUG "${CMAKE_BINARY_DIR}/Libs/Debug/lib1.lib"
STATIC_LIBRARY_FLAGS_RELEASE "${CMAKE_BINARY_DIR}/Libs/Release/lib1.lib"
)
Using OBJECT
Libraries
Or you can work with OBJECT libraries as intermediate grouping targets to prevent having to trick CMake into building your merged
library:
add_library(lib1 OBJECT bar.cc)
add_library(lib2 OBJECT foo.cc)
add_library(merged $<TARGET_OBJECTS:lib1> $<TARGET_OBJECTS:lib2>)
I personally prefer the later.