开发者

specifying link flags for only one static lib while linking executable

I have an executable built from several object files and linked with several static and shared libraries. I want to specify -Wl,-whole-archive linker option to one of linked libraries.

For example, from this command:

/usr/bin/c++ _objectFiles_ -o _myExec_  _someCommonOptions_  _myLibraries_ -Wl,-rpath _path to libs_

I want to get this command:

/usr/bin/c++ _objectFiles_ -o _myExec_  _someCommonOptions_  _allOtherLibs_ \
  -Wl,-whole-archive _one parti开发者_Go百科cular lib_ -Wl,-no_whole-archive -Wl,-rpath _path to libs_

Is it any way I can achieve this using cmake? As I understand when I add something like

set_target_properties(myExec PROPERTIES LINK_FLAGS "-Wl,-whole-archive")

then -whole-archive options is set for all linked libraries and this is definitely not what I want.

Thank you.


This thread Linking static libraries into shared libs? has a method for that.

SET (MYLIB -Wl,--whole-archive my_particular_lib -Wl,--no-whole-archive)
....
TARGET_LINK_LIBRARIES(yourtarget ${normalstuff} ${MYLIB} ${othernormalstuff})

The CMake docs state:

If a library name matches that of another target in the project a dependency will automatically be added in the build system to make sure the library being linked is up-to-date before the target links. Item names starting with '-', but not '-l' or '-framework', are treated as linker flags.

So the -Wl options should not interfere/be touched by CMake.


TARGET_LINK_LIBRARIES(myTarget -Wl,--whole-archive myLib -Wl,--no-whole-archive)

Simply replace myTarget and myLib

Oryginal post: https://stackoverflow.com/a/37564428/1052261


As @RichvonLehe points out, the proposed solution may not work if you have multiple libraries. CMake treats -Wl,--whole-archive my_particular_lib -Wl,--no-whole-archive as 3 separate libraries, and makes no guarantees about ordering. In my particular case, I found that I ended up having a bunch of other archives being included between the -Wl,--whole-archive and -Wl,--no-whole-archive flags, resulting in duplicate symbol definitions.

Unfortunately, you also may not be able to wrap everything in quotes. If you do -Wl,--whole-archive,$<TARGET_FILE:my_particular_lib>,--no-whole-archive or similar you'll find that CMAKE stops treating my_particular_lib as a symbolic target and instead just treats the whole string as a link flag. If my_particular_lib happens to have other CMake side-effects, such as target_include_directories() or in my case, PUBLIC HEADERS, they will cease to be included.

Ultimately I had to resort to a layer of indirection. The trick is to use an INTERFACE library as the top level thing. Use one library (my_lib_part_1) to dangle all of the properties that I needed to be transitively inherited by other targets, such as PUBLIC HEADERS, and another library (my_lib_part_2) that emphatically does not have any properties that needed to be inherited and only vends the .a archive.

Even this is lacking. CMake makes it difficult to have empty STATIC libraries and does not allow you to put PUBLIC HEADERS on INTERFACE libraries (yet?).

add_library(my_lib INTERFACE)

add_library(my_lib_part_1 STATIC
  foo.cpp
  )

add_library(my_lib_part_2 STATIC
  bar.cpp
  )

target_link_libraries(my_lib
  INTERFACE
    my_lib_part_1
    # It is very important this is in quotes so CMake treats it as a single flag
    "-Wl,--whole-archive $<TARGET_FILE:my_lib_part_2> -Wl,--no-whole-archive"
   )

set_target_properties(my_lib_part_1 PROPERTIES
  PUBLIC_HEADER "my_public_header.hpp"
  )


set_target_properties(my_lib_part_2 PROPERTIES
  POSITION_INDEPENDENT_CODE ON
  )
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜