静态链接第三方库与我的C++包装代码

静态链接第三方库与我的C++包装代码,c++,cuda,linker,static-libraries,C++,Cuda,Linker,Static Libraries,我正在做一个小项目,以便更好地理解编译器和链接器链 假设我有libfoo.a和libbar.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_SR

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


假设我有libfoo.a和libbar.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.a和libbar.a中的函数有未定义的引用。据我所知,链接器只在libmy.a中创建一个声明,而不包括外部库中的定义。我通过使用nm libmy.a命令打开libmy.a检查了这一点,其中声明了外部库的已用函数,但未定义

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

需要注意的是,这些库包中有一个是CUDA吗

我肯定有解决办法,但我没能找到。任何帮助都将不胜感激


目标是,构建可执行文件只需要libmy.a

这已经是静态库的一个非常规目标

静态库通常只包含从该库的源代码生成的目标代码。该库的用户还必须链接到库所需的库,因为在构建库时,定义尚未复制到库中

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

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

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

目标是,构建可执行文件只需要libmy.a,这与静态库打包并提供给最终用户的传统方式背道而驰。静态lib可以使用ar与它们的依赖项捆绑在一起,但我认为您的问题来自希望这样做并排除未使用的目标代码。该优化由编译器在构建可执行或共享库时完成。最终用户也应该能够使用这些依赖项中的代码,因此他们最终将链接到这些依赖项,而您的库将引入重复的定义。@Romen:那么解决方案将是一个共享对象,它可以作为包含所有定义的独立库来工作?是的,这是一种方法。构建一个共享对象允许您使用GCC链接器选项(如果需要,可以使用完整存档)将整个静态lib绑定到其中。如果您这样做,您的最终用户需要知道您的库包含cuda,这样他们就不会再链接它,您是否应该包含cuda取决于他们的许可证。@Romen非常感谢,它工作得非常好。正如您所指出的,我的误解是,静态库已经包含了外部库的代码。但它们只保留引用,因此这些库必须一起部署,以便用户进行编译。我是如此专注于构建一个静态库,以至于我没有想到尝试一个动态库。如果你愿意,你可以发表你的评论作为回答,这样我就可以接受了。