CMake:如何从子项目的所有静态库创建单个共享库? [英] CMake: how create a single shared library from all static libraries of subprojects?

查看:344
本文介绍了CMake:如何从子项目的所有静态库创建单个共享库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下布局:

top_project
    + subproject1
    + subproject2

每个 subproject1 subproject2 创建一个静态库。我想在 top_project 级别的单个共享库中链接这些静态库。

Each of subproject1 and subproject2 creates a static library. I would like to link these static libraries in a single shared library at the top_project level.

我收集的信息到目前为止:

The information I gathered so far is:


  • 使用 -fPic ),以便创建与位置无关的代码,这将允许将静态库链接到单个共享库或解压缩所有静态库(例如使用 ar ),并将它们重新链接到共享库(我认为这是一个不起眼和不可移植的解决方案)

  • 所有源文件必须明确给予 add_library 命令:由于某些我不能理解的原因,只需写 add_library($ {PROJECT_NAME} SHARED subproject1 subproject2)不能按预期工作(它本质上创建一个空的库&没有正确注册依赖关系)

  • 在CMake中有一个OBJECT库功能,但我不认为它的目的是真正做我想要的。

  • Either compile using -fPic (necessary on everything but Windows) in order to create position-independent code which will allow linking the static libraries into a single shared library or decompress all static libraries (e.g. using ar) and re-link them into a shared library (which I think is an inelegant & non-portable solution)
  • All source files must be given explicitly to the add_library command: for some reason which I cannot comprehend, simply writing add_library(${PROJECT_NAME} SHARED subproject1 subproject2) does not work as expected (it essentially creates an empty library & does not register the dependencies properly)
  • There is an OBJECT library feature in CMake but I don't think it's purpose is really to do what I want.

任何想法?

推荐答案

这是比它应该是更痛苦。直到最近,Kitware的人不明白为什么任何人都想要从静态库创建一个DLL。他们的论点是,应该总是在主文件(例如 top_project 在我的情况下)目录中的源文件,因为它实际上是一个自己的项目。我看到的东西不同&我需要将 top_project 分成更小的子项目,这些子项目不应该独立存在(也就是说,没有必要为他们创建一个完整的项目并使用<$ c $添加它们) c> ExternalProject_Add )。此外,当我出售我的共享库(例如使用Java本地接口),我不想运送几十个共享库,因为这将暴露我的项目的内部布局。无论如何,我想 - 从静态库创建一个共享库的情况下,我将继续技术细节。

OK, I figured it out: this is much more painful than it should be. Until very recently, people at Kitware didn't understand why anyone would ever want to create a DLL from static libs. Their argument is that there should always be source files in the main (e.g. top_project in my case) directory because it is effectively a project of its own. I see things differently & I need to break top_project into smaller subprojects which should not exist independently (i.e. there is no point in creating a full-blown project for them & add them using ExternalProject_Add). Besides, when I ship my shared library (for use, e.g. with a Java Native Interface), I don't want to ship dozens of shared libraries because that would amount to exposing the internal layout of my project. Anyway, having - I think - made a case for creating a shared library from static libraries, I'll proceed to the technical details.

在CMakeLists.txt subproject1 subproject2 ,您应该使用OBJECT库功能(在CMake 2.8.8中介绍)创建目标: p>

In the CMakeLists.txt of subproject1 and subproject2, you should create your target using the OBJECT library feature (introduced in CMake 2.8.8):

add_library(${PROJECT_NAME} OBJECT ${SRC})

其中 SRC 指定源文件列表(请注意,这些文件应在CMakeLists.txt文件中明确设置为允许在检测到CMakeLists.txt的修改时重新启动CMake,例如添加或删除文件时)

where SRC designates the list of source files (note that these should be set explicitly in the CMakeLists.txt file as it allows make to re-launch CMake when a modification of CMakeLists.txt is detected, e.g. when adding or removing a file)

top_project ,使用以下命令添加子项目:

In the top_project, add the subprojects using:

add_subdirectory(subproject1)
add_subdirectory(subproject2)

要查看静态库中的符号,请使用:

In order to see the symbols from the static library, use:

set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")

您可以使用以下方式创建共享库:

You can then create the shared library using:

add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:subproject1>
                                   $<TARGET_OBJECTS:subproject2>)



我发现任何正常库(即非对象)需要在单独的 add_library 命令中添加,否则将被忽略。

I've found that any "normal" library (i.e. not object) needs to be added in a separate add_library command, otherwise it is simply ignored.

对于可执行文件,您可以使用:

For executables, you can use:

add_executable(name_of_executable $<TARGET_OBJECTS:subproject1>
                  $<TARGET_OBJECTS:subproject2>)
set(LINK_FLAGS ${LINK_FLAGS} "-Wl,-whole-archive")
target_link_libraries(name_of_executable ${PROJECT_NAME}

我重复一下,这只适用于CMake的版本2.8.8,以及CMake非常好地管理依赖,而且是跨平台的,因为它没有那么痛苦比普通的Makefile和肯定不那么灵活。

I repeat that this only works as of version 2.8.8 of CMake. Just as well CMake manages the dependencies extremely well & is cross-platform because it's not much less painful than plain old Makefiles & certainly less flexible.

这篇关于CMake:如何从子项目的所有静态库创建单个共享库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆