Issue
I've got a project that used to be a giant set of source files that all got compiled and then linked as one executable. As a first step in making the project more modular, I am breaking up the build into several smaller chunks and making them static libraries. There's a hierarchy, so Exe1
will link against static libs Lib2A
and Lib2B
. Lib2A
will depend on static Lib3A
, lib3B
, lib3C
, etc. The numbers here show their layer in the hierarchy.
The problem is that I need to use --whole-archive
when linking or else some symbols from the underlying libraries are not found.
When I add the below for the linking of Exe1
:
target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)
I end up with an actual link stage command like:
g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a
Inevitably, symbols from some of the layer 3 static libraries get lost and I get missing symbol errors.
I expected that because Lib2A
has Lib3*
libraries as dependencies, that they would also be "inside" the --whole-archive
part of the linker command, but they show up outside.
I've tried many different combinations (e.g. putting the --whole-archive
stuff at lower layers), but haven't come across an approach that works using CMake. What am I doing wrong?
Thanks
Solution
For 3.12 and newer versions of CMake, I would use object libraries.
The workaround I found for versions earlier than that was to create an intermediate static library that used some property magic to place all linkage dependencies inside the --whole-archive section. For me, the top-level static library was called 'source'. It contained actually nothing itself, but had linkage dependencies on a bunch of other static libraries. I created 'source-combined' as follows:
add_library(source-combined STATIC "")
set_target_properties(source-combined PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(source-combined PUBLIC
-Wl,--whole-archive
$<TARGET_PROPERTY:source,INTERFACE_LINK_LIBRARIES>
-Wl,--no-whole-archive
)
Now when I create an executable or a shared library by linking against this souce-combined library, I get the --whole-archive and --no-whole-archive as bookends around the entire set of static libraries that were the link dependencies of 'source'. It took forever to stumble across this technique, so I'm sharing it.
Answered By - Rich von Lehe Answer Checked By - Mildred Charles (WPSolving Admin)