【问题标题】:CMake: how to produce binaries "as static as possible"CMake:如何生成“尽可能静态”的二进制文件
【发布时间】:2011-04-15 07:01:39
【问题描述】:

我想控制在 CMake 中找到/链接到我的二进制文件的库的类型。最终目标是生成二进制文件“尽可能静态”,即静态链接每个具有可用静态版本的库。这一点很重要,因为它将在测试期间实现跨不同系统的二进制文件的可移植性。

ATM 这似乎很难实现,因为 FindXXX.cmake 包,或者更准确地说,find_library 命令总是在静态和动态都可用时选择动态库。

非常欢迎提供有关如何实现此功能的提示(最好以优雅的方式)!

【问题讨论】:

  • 不完全是 stackoverflow.com/questions/2113231/… 的欺骗,这是 GCC 特有的。
  • 事实上,它不仅是 gcc 特有的,也是一个不方便的解决方案。请参阅我对另一个问题的评论。
  • @pszilard 你最终找到解决方案了吗?我正在尝试对 g++ 做同样的事情。
  • 什么是“碰撞”一个有趣的问题但没有正确答案的“正确方法”?
  • @augustin Bump 通过设置赏金。

标签: linker shared-libraries cmake static-linking dynamic-library


【解决方案1】:

我做了一些调查,虽然我找不到令人满意的解决方案,但我确实找到了一个半解决方案。

静态构建的问题归结为三件事:

  1. 构建和链接项目的内部库。

    很简单,只需拨动BUILD_SHARED_LIBS 开关OFF

  2. 查找外部库的静态版本。

    似乎唯一的方法是将CMAKE_FIND_LIBRARY_SUFFIXES 设置为包含所需的文件后缀(这是一个优先级列表)。

    这个解决方案是一个相当“肮脏”的解决方案,并且非常违背 CMake 的跨平台愿望。恕我直言,这应该由 CMake 在幕后处理,但据我了解,由于 Windows 上的“.lib”混淆,CMake 开发人员似乎更喜欢当前的实现。

  3. 静态链接到系统库。

CMake 提供了一个选项LINK_SEARCH_END_STATIC,它基于文档:“结束链接行,以便使用静态系统库。” 有人会想,就是这样,问题就解决了。但是,目前的实现似乎无法胜任这项任务。如果打开了该选项,CMake 会生成一个隐式链接器调用,其参数列表以传递给链接器的选项结尾,包括-Wl,-Bstatic。然而,这还不够。仅指示链接器静态链接会导致错误,在我的情况下:/usr/bin/ld: cannot find -lgcc_s。缺少的是告诉 gcc 我们需要通过 -static 参数进行静态链接,该参数 not 由 CMake 生成到链接器调用。我认为这是一个错误,但我还没有设法得到开发人员的确认。

最后,我认为这一切都可以而且应该由 CMake 在幕后完成,毕竟这并不复杂,除了在 Windows 上是不可能的——如果这算复杂的话......

【讨论】:

  • 您不应该将BUILD_SHARED_LIBS 设置为关闭(这样它不会构建共享库)吗?
  • 哈哈,近五年来你是第一个注意到这个错误的人。谢谢。
【解决方案2】:

制作精良的 FindXXX.cmake 文件将为此包含一些内容。如果你查看 FindBoost.cmake,你可以设置 Boost_USE_STATIC_LIBS 变量来控制它是否找到静态或共享库。不幸的是,大多数包都没有实现这一点。

如果一个模块使用 find_library 命令(大多数都使用),那么您可以通过CMAKE_FIND_LIBRARY_SUFFIXES 变量更改 CMake 的行为。这是 FindBoost.cmake 中的相关 CMake 代码以使用它:

IF(WIN32)
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ELSE(WIN32)
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ENDIF(WIN32)

您可以将其放在调用 find_package 之前,或者更好的是,您可以自己修改 .cmake 文件并回馈社区。​​p>

对于我在项目中使用的 .cmake 文件,我将它们全部保存在源代码管理中自己的文件夹中。我这样做是因为我发现某些库的正确 .cmake 文件不一致,保留我自己的副本允许我进行修改并确保签出代码的每个人都拥有相同的构建系统文件。

【讨论】:

  • 感谢您的评论,同时我实际上已经得出结论,上述是唯一可行的解​​决方案来检测外部库的静态版本。但是,这是一种非常肮脏的方式,我宁愿不必指定后缀。不幸的是,根据 CMake 邮件列表上的讨论,似乎由于 Windows 的库命名非常混乱,因此没有计划正确实施它。不过,这应该适用于大多数 *NIX 系统。
  • 请注意,如果您希望检测静态库(因此可能配置失败,则上述命令不应将静态库文件名添加到 CMAKE_FIND_LIBRARY_SUFFIXES,而是将该变量设置为这些文件名。这会阻止 find_*() 函数使用通常的后缀获取共享库
  • 还请注意,如果在隐式链接目录中找到该库,则 FindXXXX.cmake 包的“制作”如何并不重要,例如系统路径。 CMake 故意恢复为 -lXXXX 以允许链接器在这种情况下使用其正常分辨率 - 请参阅 public.kitware.com/pipermail/cmake/2015-January/059702.html
  • 不应该是:IF(MSVC)?
猜你喜欢
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-27
  • 1970-01-01
相关资源
最近更新 更多