51

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

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

关于如何实现此功能的提示 - 最好以优雅的方式 - 将非常受欢迎!

4

2 回答 2

29

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

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

  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参数进行静态链接,该参数不是由 CMake 生成到链接器调用的。我认为这是一个错误,但我还没有设法得到开发人员的确认。

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

于 2010-11-09T12:29:28.583 回答
16

一个制作精良的 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 文件并回馈社区。

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

于 2010-11-08T17:52:33.223 回答