在链接可执行文件时仅指定一个静态库的链接标志

时间:2011-04-17 12:06:05

标签: cmake

我有一个可执行文件,它由几个目标文件构建,并与多个静态和共享库链接。我想为其中一个链接库指定-Wl​​,-whole-archive链接器选项。

例如,从此命令:

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

我想得到这个命令:

/usr/bin/c++ _objectFiles_ -o _myExec_  _someCommonOptions_  _allOtherLibs_ \
  -Wl,-whole-archive _one particular lib_ -Wl,-no_whole-archive -Wl,-rpath _path to libs_

我能使用cmake实现这一目标吗?据我所知,当我添加类似

的内容时
set_target_properties(myExec PROPERTIES LINK_FLAGS "-Wl,-whole-archive")

然后为所有链接库设置-whole-archive选项,这绝对不是我想要的。

谢谢。

3 个答案:

答案 0 :(得分:33)

这个帖子Linking static libraries into shared libs?有一个方法。

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

CMake docs州:

  

如果库名称与库名称相匹配   项目中的另一个目标a   将自动添加依赖项   在构建系统中确保   链接的库是最新的   在目标链接之前。物品名称   以' - '开头,但不是'-l'或   '-framework'被视为链接器   标志。

所以-Wl选项不应该被CMake干扰/接触。

答案 1 :(得分:3)

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

只需替换myTargetmyLib

即可

Oryginal帖子:https://stackoverflow.com/a/37564428/1052261

答案 2 :(得分:0)

正如@RichvonLehe 指出的那样,如果您有多个库,建议的解决方案可能不起作用。 CMake 将 -Wl,--whole-archive my_particular_lib -Wl,--no-whole-archive 视为 3 个独立的库,并且不保证排序。在我的特殊情况下,我发现我最终在 -Wl,--whole-archive-Wl,--no-whole-archive 标志之间包含了一堆其他档案,从而导致重复的符号定义。

不幸的是,您可能无法将所有内容都用引号括起来。如果您执行 -Wl,--whole-archive,$<TARGET_FILE:my_particular_lib>,--no-whole-archive 或类似操作,您会发现 CMAKE 不再将 my_particular_lib 视为符号目标,而是将整个字符串视为链接标志。如果 my_particular_lib 碰巧有其他 CMake 副作用,例如 target_include_directories() 或在我的情况下,PUBLIC HEADERS,它们将不再包含在内。

最终我不得不求助于间接层。诀窍是使用 INTERFACE 库作为顶层的东西。使用一个库 (my_lib_part_1) 来悬挂我需要由其他目标传递继承的所有属性,例如 PUBLIC HEADERS,以及另一个库 (my_lib_part_2) 没有任何需要继承的属性,只提供 .a 存档。

即使是这样也是缺乏的。 CMake 很难拥有空的 STATIC 库,并且不允许您将 PUBLIC HEADERS 放在 INTERFACE 库上(还没有?)。

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
  )