CMake:如何"尽可能静态地"生成二进制文件

psz*_*ard 47 linker cmake shared-libraries static-linking dynamic-library

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

ATM这似乎很难实现,因为FindXXX.cmake软件包,或者更确切地说,只要静态和动态都可用,find_library命令总是会获取动态库.

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

psz*_*ard 28

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

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

  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上是不可能的 - 如果算得那么复杂......

  • 您不应该将BUILD_SHARED_LIBS设置为关闭(这样它*将不会*构建共享库)吗? (2认同)

Jon*_*erg 15

一个精心设计的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)
Run Code Online (Sandbox Code Playgroud)

您可以在调用find_package之前放置它,或者更好的是,您可以自己修改.cmake文件并返回社区.

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