CMake:如何产生二进制“尽可能静态”
我想控制在CMake中find/链接到我的二进制文件的types。 最终的目标是“尽可能静态地生成二进制文件”,即静态链接到每个具有静态版本的库。 这一点非常重要,因为在testing过程中可以在不同的系统上移植二进制代码。
ATM似乎很难实现FindXXX.cmake包,或者更确切地说find_library命令总是在静态和dynamic都可用的时候selectdynamic库。
关于如何实现这个function的技巧 – 最好以一种优雅的方式 – 非常受欢迎!
我做了一些调查,虽然找不到令人满意的解决办法,但我确实find了一个解决办法。
静态构build的问题归结为三件事情:
-
build立和链接项目的内部库。
很简单,只需要将
BUILD_SHARED_LIBS
开关OFF
。 -
寻找外部库的静态版本。
唯一的办法似乎是设置
CMAKE_FIND_LIBRARY_SUFFIXES
包含所需的文件后缀(es)(这是一个优先级列表)。这个解决scheme相当“脏”,非常反对CMake的跨平台愿望。 恕我直言,这应该由CMake幕后处理,但据我了解,由于Windows上的“.lib”混淆,似乎CMake开发人员更喜欢当前的实现。
-
静态链接到系统库。
CMake提供了一个基于文档“ LINK_SEARCH_END_STATIC
的选项:“结束链接,以便使用静态系统库”。 有人会想,这就是问题解决了。 但是,目前的实施似乎没有完成任务。 如果选项打开,CMake会生成一个带有参数列表的隐式链接器调用,该链接器调用以传递给链接器的选项(包括-Wl,-Bstatic
。 但是,这还不够。 只是指示链接器静态链接导致错误,在我的情况下: /usr/bin/ld: cannot find -lgcc_s
。 缺less的是告诉gcc,我们需要静态链接通过CMake链接器调用不生成的静态参数。 我认为这是一个错误,但是我还没有得到开发者的确认。
最后,我认为所有这一切都可以并且应该由CMake在幕后完成,毕竟它不是那么复杂,除非在Windows上不可能 – 如果这种计算复杂的话…
一个很好的FindXXX.cmake文件将包含这个东西。 如果您查看FindBoost.cmake,则可以设置Boost_USE_STATIC_LIBSvariables来控制它是否find静态库或共享库。 不幸的是,大部分软件包都没有实现这个function。
如果一个模块使用find_library命令(大部分是),那么你可以通过CMAKE_FIND_LIBRARY_SUFFIXESvariables来改变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文件,我将它们全部放在源代码pipe理的自己的文件夹中。 我这样做是因为我发现为某些库提供正确的.cmake文件是不一致的,保留我自己的副本允许我进行修改,并确保签出代码的每个人都具有相同的构build系统文件。