Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set --whole-archive flag in CMake so that it is used by all the dependent

Tags:

c++

c

cmake

I have a static link library (say libfoo).

 add_library(foo STATIC foo.cpp)

There are many executables that links(uses) this library.

 add_executable(myexe1 myexe1.cpp)
 link_target_libraries(myexe1 foo)
 add_executable(myexe2 myexe2.cpp)
 link_target_libraries(myexe2 foo)
 add_executable(myexe3 myexe3.cpp)
 link_target_libraries(myexe3 foo)
 #... and so on. (These definitions are actually scattered in the project)

Now I would like to use -Wl,--whole-archive flag to the library. It seems one solution is to add the flags in the executable side.

 add_executable(myexe1 myexe1.cpp)
 link_target_libraries(myexe1 -Wl,--whole-archive foo -Wl,--no-whole-archive)

But in this way I have to write this every time I define executable that links to this library.

Is there any way to add this flag to the library definition side so that the flag is always used when linking the executables that depend on the library?

like image 229
Shu Suzuki Avatar asked Jun 26 '17 03:06

Shu Suzuki


People also ask

What is target_ link_ libraries in CMake?

target_link_libraries(<target> [item1 [item2 [...]]] [[debug|optimized|general] <item>] ...) Specify libraries or flags to use when linking a given target. The named <target> must have been created in the current directory by a command such as add_executable() or add_library() .

What does CMake Add_library do?

Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project. The actual file name of the library built is constructed based on conventions of the native platform (such as lib<name>.

What is whole archive?

The /WHOLEARCHIVE option forces the linker to include every object file from either a specified static library, or if no library is specified, from all static libraries specified to the LINK command.


2 Answers

I had the same problem, but could not stop CMAKE from reordering the flags and my library. I ended up doing something like this:

add_library(foo_actual STATIC foo.cpp)
add_library(foo INTERFACE)
set_property(TARGET foo PROPERTY INTERFACE_LINK_LIBRARIES
  -Wl,--whole-archive,$<TARGET_FILE:foo_actual>,--no-whole-archive)

Couple differences with your answer:

  • My version of CMake (3.7) didn't allow the get_property, but $<TARGET_FILE> worked well and ensures the dependency is propagated.
  • I used commas to put the --whole-archive, library, and --no-whole-archive all in one argument, so CMake wouldn't reorder them. I could not get CMake not to wildly reorder them, otherwise.
like image 170
David Ghandehari Avatar answered Oct 21 '22 05:10

David Ghandehari


I solved this with the following solution.

add_library(foo STATIC foo.cpp)
get_property(foo_location TARGET foo PROPERTY LOCATION)     
target_link_libraries(foo -Wl,--whole-archive ${foo_location} -Wl,--no-whole-archive) 
like image 24
Shu Suzuki Avatar answered Oct 21 '22 05:10

Shu Suzuki