CMake将共享库链接到静态库

时间:2022-09-18 12:22:35

I am porting an AutoTools project to CMake.

我正在向CMake移植一个AutoTools项目。

What AutoTools does:

什么AutoTools:

  • builds some static libraries
  • 建立一些静态库
  • builds some shared libraries and links static ones into shared
  • 构建一些共享库并将静态库链接到共享库中
  • builds an executable, links it to shared libraries
  • 构建可执行文件,将其链接到共享库。

What I've managed to do with CMake:

我用CMake做了什么:

  • build some static libraries - add_library(staticfoo <src>)
  • 构建一些静态库- add_library(staticfoo )
  • build some shared libraries - add_library(sharedfoo SHARED <src>) and link them - target_link_libraries(sharedfoo staticfoo)
  • 构建一些共享库—add_library(sharedfoo共享 )并链接它们—target_link_libraries(sharedfoo staticfoo)
  • build an executable, link it to shared libraries - target_link_libraries(exe sharedfoo), but that dragged the static libraries in again, too.
  • 构建一个可执行文件,将它链接到共享库——target_link_libraries(exe sharedfoo),但这也将静态库拖了进来。

So, the resulting link command for the executable has static libs in addition to shared. Which doesn't correspond to the command generated by AutoTools project.

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

I've tried target_link_libraries(sharedfoo PRIVATE staticfoo), but that doesn't get the symbols from the static lib into the interface of the shared lib.

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

How to get the symbols without that 'transitive' behavior?

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

(in platform-independent way)

(以独立于平台的方式)

4 个解决方案

#1


3  

As I know, CMake doesn't allow to mix STATIC and SHARED libraries.

正如我所知道的,CMake不允许混合静态库和共享库。

If your staticfoo library is used solely as part of other libraries/executables, you can define it as

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

add_library(staticfoo OBJECT <src>)

and use then as some sort of sources when build other library:

然后在建立其他图书馆的时候使用一些资源:

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

For more info see documentation on add_library.

要了解更多信息,请参阅add_library的文档。

#2


2  

To resolve this case you need to do few things:

要解决这个问题,你需要做一些事情:

  • first of all make sure you've compiled static libraries w/ -fPIC, so they'll contain a relocatable code (which would be a part of a shared library later)
  • 首先,确保您已经编译了静态库w/ -fPIC,因此它们将包含可重定位的代码(稍后将成为共享库的一部分)
  • then, you need to control symbols visibility when compiling all libraries, so being a part of shared library, symbols came from the static one would be visible
  • 然后,在编译所有库时需要控制符号的可见性,因此作为共享库的一部分,来自静态库的符号是可见的
  • and finally, yes, you need to specify PRIVATE <static libs> when linking your shared library, so the linker command line for your executable wouldn't have any static libs
  • 最后,是的,在链接共享库时需要指定PRIVATE ,这样可执行文件的链接器命令行就不会有任何静态libs

#3


1  

I created a little example that does this the right way, here: https://github.com/CarloWood/cmaketest

我创建了一个用正确的方式实现这一点的示例:https://github.com/CarloWood/cmaketest

It shows how two "static" libraries, one with two visible symbols, both with by default hidden symbols, are added to a shared library, which is then used to link an executable.

它展示了如何向共享库中添加两个“静态”库,其中一个带有两个可见符号(都带有默认的隐藏符号),然后用于链接可执行文件。

The method used is that of @Tsyvarev, combined with the VISIBILITY target property mentioned by @Zaufi.

使用的方法是@Tsyvarev,结合@Zaufi提到的可见性目标属性。

The only non-platform specific thing (I think) is the __EXPORT macro that is used. It would be nice to fix that too, if anyone knows how.

唯一非平台特定的东西(我认为)是使用的__EXPORT宏。如果有人知道该怎么做的话,最好也能解决这个问题。

#4


0  

See my answer here. Basically add /WHOLEARCHIVE, -all_load, or --whole-archive to the linker flags.

看到我的答案。基本上是向链接器标志添加/WHOLEARCHIVE、-all_load或-全归档。

#1


3  

As I know, CMake doesn't allow to mix STATIC and SHARED libraries.

正如我所知道的,CMake不允许混合静态库和共享库。

If your staticfoo library is used solely as part of other libraries/executables, you can define it as

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

add_library(staticfoo OBJECT <src>)

and use then as some sort of sources when build other library:

然后在建立其他图书馆的时候使用一些资源:

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

For more info see documentation on add_library.

要了解更多信息,请参阅add_library的文档。

#2


2  

To resolve this case you need to do few things:

要解决这个问题,你需要做一些事情:

  • first of all make sure you've compiled static libraries w/ -fPIC, so they'll contain a relocatable code (which would be a part of a shared library later)
  • 首先,确保您已经编译了静态库w/ -fPIC,因此它们将包含可重定位的代码(稍后将成为共享库的一部分)
  • then, you need to control symbols visibility when compiling all libraries, so being a part of shared library, symbols came from the static one would be visible
  • 然后,在编译所有库时需要控制符号的可见性,因此作为共享库的一部分,来自静态库的符号是可见的
  • and finally, yes, you need to specify PRIVATE <static libs> when linking your shared library, so the linker command line for your executable wouldn't have any static libs
  • 最后,是的,在链接共享库时需要指定PRIVATE ,这样可执行文件的链接器命令行就不会有任何静态libs

#3


1  

I created a little example that does this the right way, here: https://github.com/CarloWood/cmaketest

我创建了一个用正确的方式实现这一点的示例:https://github.com/CarloWood/cmaketest

It shows how two "static" libraries, one with two visible symbols, both with by default hidden symbols, are added to a shared library, which is then used to link an executable.

它展示了如何向共享库中添加两个“静态”库,其中一个带有两个可见符号(都带有默认的隐藏符号),然后用于链接可执行文件。

The method used is that of @Tsyvarev, combined with the VISIBILITY target property mentioned by @Zaufi.

使用的方法是@Tsyvarev,结合@Zaufi提到的可见性目标属性。

The only non-platform specific thing (I think) is the __EXPORT macro that is used. It would be nice to fix that too, if anyone knows how.

唯一非平台特定的东西(我认为)是使用的__EXPORT宏。如果有人知道该怎么做的话,最好也能解决这个问题。

#4


0  

See my answer here. Basically add /WHOLEARCHIVE, -all_load, or --whole-archive to the linker flags.

看到我的答案。基本上是向链接器标志添加/WHOLEARCHIVE、-all_load或-全归档。