CMake将共享库链接到静态库

CMake将共享库链接到静态库

问题描述:

我将一个AutoTools项目移植到CMake。CMake将共享库链接到静态库

自动工具的作用:

  • 建立一些静态库
  • 建立一些共享库和静态的链接到共享
  • 建立一个可执行文件,它链接到共享库

什么我设法做CMake:

  • 建立一些静态库 - add_library(staticfoo <src>)
  • 建一些共享库 - add_library(sharedfoo SHARED <src>)并将其链接 - target_link_libraries(sharedfoo staticfoo)
  • 建立一个可执行文件,它链接到共享库 - target_link_libraries(exe sharedfoo),但拖累再次静态库了。

因此,除了共享之外,可执行文件的结果链接命令还具有静态库。这与AutoTools项目生成的命令不符。

我试过target_link_libraries(sharedfoo PRIVATE staticfoo),但是没有从静态库中获取符号到共享库的接口中。

如何获得没有“传递”行为的符号?

(以平台无关的方式)

据我所知,CMake的不允许混用静态和共享库。

如果您staticfoo库仅用作其他库/可执行文件的一部分,你可以将它定义为

add_library(staticfoo OBJECT <src>) 

,然后使用作为某种形式的来源时构建其他库:

add_library(sharedfoo SHARED <src> $<TARGET_OBJECTS:staticfoo>) 

欲了解更多信息,请参阅documentation on add_library

+0

CMake不关心你试图链接静态/动态/混合的类型的库......这将成为特定平台链接器的问题。 – zaufi

+0

在窗口上,链接器通过链接已保存的对象/静态库来丢弃导出符号,但解压缩的对象可以工作。这是为什么将对象库添加到cmake中的主要原因之一。 – Youka

+0

事实上,这是转换自动工具项目中找到的模式的好方法。对于替代品和他们的问题,看到这个详细的问题:http://stackoverflow.com/questions/5136184/linking-windows-dll-files-from-static-libraries-using-cmake-without-hand-craftin –

要解决这种情况下,你需要做的几件事情:

  • 首先,确保你已经编译静态库W/-fPIC,所以他们会包含一个重定位代码(这将是一个部分以后,你需要在编译所有库时控制符号的可见性,所以作为共享库的一部分,符号来自静态的将会是可见的
  • 最后,是的,你需要链接您的共享库时指定PRIVATE <static libs>,因此执行程序的链接器命令行表不会有任何静态库
+0

因此,如何'控制符号可见度'? – Velkan

+0

最明显的方法是使用'-fvisibility' [编译器选项](https://gcc.gnu.org/wiki/Visibility)。 CMake> = 3.x具有['CMAKE_ _VISIBILITY_PRESET'](http://www.cmake.org/cmake/help/v3.0/variable/CMAKE_LANG_VISIBILITY_PRESET.html)变量(和相应的[目标属性](http: //www.cmake.org/cmake/help/v3.0/prop_tgt/LANG_VISIBILITY_PRESET.html))。但不幸的是,它不影响静态库。这是一个缺陷,将在即将发布的[CMake 3.3](http://www.kitware.com/blog/home/post/934)中得到修复。 – zaufi

我创建了一个小例子,这不正确的方式,在这里:https://github.com/CarloWood/cmaketest

它显示了两个“静态”库,一个有两个明显的符号,都与默认情况下,隐藏的符号被添加到共享库,然后用于链接可执行文件。

使用的方法是@Tsyvarev,与@Zaufi提到的VISIBILITY目标属性相结合。

唯一的非平台特定的事情(我认为)是使用__EXPORT宏。如果有人知道如何解决,那也是很好的。

查看我的回答here。基本上将/WHOLEARCHIVE,-all_load--whole-archive添加到链接器标志。