【问题标题】:Link libc statically静态链接 libc
【发布时间】:2020-05-14 13:54:47
【问题描述】:

我正在尝试使用 CMake 3.15 制作静态可执行文件。我正在 Alpine Linux 上构建(因此使用 musl),目前,我的可执行文件的 ldd 输出是:

# ldd my_executable
    /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fc6f65b3000)
    libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fc6f659f000)

我可以设置target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++),它们是静态链接的:

# ldd my_executable
    /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)
    libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fc6f7977000)

但我无法让 musl 静态链接。我尝试过(使用干净的构建,以确保配置步骤从零开始):

  1. -static 添加到上面的target_link_options
  2. set(CMAKE_EXE_LINKER_FLAGS "-static") 之前调用add_executable(my_executable ...)
  3. -static 添加到target_link_libraries(my_executable lib1 lib2 -static)

当我在 VERBOSE=1 模式下运行 CMake 时,它​​总是以以下方式结束链接命令:

... -Wl,-Bdynamic -ldl -lrt -lm -lpthread

我相信这是我的问题:我想摆脱那个-Bdynamic。我错过了什么?这是 -Bdynamic 来自我的依赖项之一吗?我将它们全部从源代码构建为静态(.a)库,那么它们如何动态链接 libc?或者我需要修补它们以在构建它们时添加-static

【问题讨论】:

  • 对于选项 2,变量应为 CMAKE_EXE_LINKER_FLAGS。另外,要明确选项 3,这意味着您尝试过 target_link_libraries(my_executable -static)?在每次构建尝试之间删除 CMake 缓存可能会有所帮助。
  • 对不起,错字。是的,我试过你说的,让我编辑。我也做了干净的构建,但我可以再试一次。
  • 已编辑,@squareskittles!注意:我在末尾添加了-static(在库之后)。有关系吗?
  • 虽然你可以做到set(CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_C_FLAGS ""),但最好做到like here
  • 不错! LINK_SEARCH_START_STATICLINK_SEARCH_END_STATIC 允许我现在除了 ld-musl 之外的所有东西都是静态链接的。我不知道为什么,但这个仍然是动态的。

标签: cmake libc


【解决方案1】:

正如KamilCuk 的评论所暗示的,答案here 似乎有解决方案。不过,我的做法并不完全相同,因此我也会保留这个答案。

对于我想要静态链接的目标可执行文件:

add_executable(my_executable main.cpp)

我必须设置以下属性/选项:

set_target_properties(my_executable PROPERTIES LINK_SEARCH_START_STATIC ON)
set_target_properties(my_executable PROPERTIES LINK_SEARCH_END_STATIC ON)

target_link_options(my_executable PRIVATE -static-libgcc -static-libstdc++ -static)

一些注意事项:

  • LINK_SEARCH_*_STATIC 有助于从链接命令中删除 -Bdynamic
  • 我从来没有设法从链接命令中删除-ldl,但似乎dl 最终没有获得链接(可能是因为它没有被使用)。
  • ldd 不足以验证 my_executable 是静态链接的。 readelf -l my_executable 表明它没有 INTERP 标头,并且目前没有动态二进制文件这样的东西(使用 musl)。
  • 事实证明,检查二进制文件是否是静态链接的并不是那么简单:-)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2010-11-25
    相关资源
    最近更新 更多