将第三方库与我的 C++ 包装器代码静态链接在一起

Static linking third party libraries together with my C++ wrapper code

我正在做一个小项目以更好地理解编译器和链接器链。

假设我有库 libfoo.alibbar.a。我想创建一个库 libmy.a,作为两个库的包装器或顶级 API。目标是,只需要 libmy.a 来构建一个使用我定义的包装函数的可执行文件。我创建了一个 cmake 项目并设置了库

cmake_minimum_required(VERSION 3.14)
project(Wrapper)

set(CMAKE_CXX_STANDARD 11)


add_library(my STATIC ${SOME_SRC_FILES})

#set up the lib/inc paths and libs to link
target_include_directories(my PUBLIC /path/to/Foo/inc/ /path/to/Bar/inc/)
target_link_directories(my PUBLIC /path/to/Foo/lib/ /path/to/Bar/lib)
target_link_libraries(my PUBLIC foo bar)

运行良好,编译没有问题。但是,如果我尝试从外部项目引用该对象,它会告诉我,我对 libfoo.alibbar.a 中的函数有未定义的引用。据我了解这个问题,链接器只在 libmy.a 中创建一个声明,而不包括它在外部库中的定义。我通过使用 nm libmy.a 命令打开 libmy.a 检查了这一点,其中声明了外部库的使用函数,但未定义。

我遇到了一个使用 ar 组合多个库文件的解决方案。但是我想避免这样的方法,因为如果它不是一个库,而是一堆库,比如说 10 个库,那么不适合在每个库中搜索一个定义并将其复制到 libmy.a 中。将所有库放在一起也不是解决方案,因为文件会变得太大。

重要的是要注意,这些库包之一是 CUDA?

我确定有解决方案,但我找不到。任何帮助将不胜感激

The target is, that only libmy.a should be required to build an executable

这对于静态库来说已经是一个非常规的目标了。

静态库通常只包含从 那个库 的源代码构建的目标代码。该库的用户还必须 link 访问您的库所需的库,因为在构建时尚未将定义复制到您的库中。

ar 等工具可用于将多个静态库组合在一起,因为它们只是目标代码的存档。该工具无法预测最终用户将使用哪个目标代码,因此它将捆绑整个库。否则,最终用户可能正在寻找您遗漏的定义,然后无论如何都需要 link 在依赖库的第二个副本中。

如果你想提供一个包含最终用户所需的一切的库,减少你的包装器实际使用的内容,你可以构建一个共享库。共享库被认为是可执行的,因此编译器知道任何未引用的目标代码都不会被使用,也不会包含在共享库中。

可以强制将整个静态库包含在共享库中。
在 GCC 上,您可以使用 linker 参数:--whole-archive 以确保包含以下库中的所有目标代码。
在 MSVC 上,您可以使用 /WHOLEARCHIVE:<library file name> 参数来执行相同的操作。