【问题标题】:force linked static libraries with cmake not working使用 cmake 强制链接静态库不起作用
【发布时间】:2019-12-05 22:24:12
【问题描述】:

我们有一个多项目 cmake 设置,其中包括一些 IMPORTED 静态库。对于我们的其中一个可执行文件,我们需要强制链接其中一些IMPORTED 库中的所有符号,因此我们需要在该库的名称之前将-Wl,-force_load 传递给编译器。请注意,这些导入的库之间存在依赖关系,因此需要在链接命令行中以正确的顺序放置它们。这些依赖关系通过set_target_properties(fake_2 PROPERTIES INTERFACE_LINK_LIBRARIES ...) 在根CMakeLists.txt 中声明。

我们使用的是相当标准的target_link_libraries(lib_a PUBLIC -Wl,-force_load fake_4),但事实证明,cmake 将-Wl,-force_load 视为一个相当随意的链接器标志,如果您将其应用于多个库,例如:

target_link_libraries(lib_a PUBLIC -Wl,-force_load fake_4)
target_link_libraries(lib_a PUBLIC -Wl,-force_load fake_3)

不必将这些链接器标志应用于fake_4fake_3。在某些情况下,它会删除该标志并将其仅应用于其中一个库。尝试解决这个问题

target_link_libraries(lib_a PUBLIC "-Wl,-force_load $<TARGET_PROPERTY:fake_4,IMPORTED_LOCATION>")

导致链接器标志被放置在库之前,但随后 cmake 无法识别导入的库,因此它忽略了它们之间的依赖关系。

可以在此处找到展示这些问题的完整示例项目:https://github.com/REVLUTION/cmake-example

注意:如果您想查看那里的一些 cmets,这是从 cmake discussion forums 移出的。

【问题讨论】:

  • AFAIK -force_load 为链接到应用程序的动态库进行降神会(默认情况下,dll-s 是延迟加载的)。静态库只是成为可执行文件的一部分,因此它们没有单独的“加载”。
  • 通常当您链接静态库时,仅保留在其他代码中使用的符号。 -force_load 告诉编译器包括所有符号,即使它们似乎没有被使用。这对于 TensorFlow 之类的东西是必要的,因为在编译时无法知道将要调用的函数集。

标签: c++ cmake linker


【解决方案1】:

编辑:根据 cmets 看起来这实际上不起作用。


cake discussion forum 发布了解决问题的答案。为了方便查阅,我在这里转贴。

正如阿兰·马丁所说there

我猜那是因为你需要两者:

  • target_link_libraries(utils_video_encode_decode_ffmpeg PUBLIC avfilter) 用于“常规”依赖
  • target_link_libraries(utils_video_encode_decode_ffmpeg PUBLIC "-Wl,-force_load $&lt;TARGET_PROPERTY:avfilter,IMPORTED_LOCATION&gt;") 为 “力负荷”

把它们放在一起:

target_link_libraries(utils_video_encode_decode_ffmpeg
  PUBLIC
    avfilter
      "-Wl,-force_load $<TARGET_PROPERTY:avfilter,IMPORTED_LOCATION>"
)

【讨论】:

  • 我认为这在大多数情况下都会起作用,但不能保证会起作用。假设avfilter 依赖于其他一些库,例如bzip。 cmake 将重新排序普通的avfilter 链接,以确保avfilter 在链接行上位于bzip 之前,以便它需要来自 bzip 的符号得到链接。但是没有使用avfilter,因此链接器删除了它的所有符号,因此也删除了所有bzip 符号。简而言之,“-l/usr/lib/avfilter -lbzip -Wl,-force_load -l/usr/lib/avfilter` 不起作用,也无法保证不会发生这种情况。
  • 原来这个解决方案存在第二个问题:如果您确实使用了库中的一些符号而不是其他符号,那么您在链接时会收到重复符号错误,因为第一个链接保留了您使用的符号并且第二个,force-link 然后重新定义它们。
【解决方案2】:

不久前我填写了一个关于此的错误。已确认但仍未解决:

https://gitlab.kitware.com/cmake/cmake/-/issues/20078#note_665095

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多