首页 > 解决方案 > 将第三方库与我的 C++ 包装器代码静态链接在一起

问题描述

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

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

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

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

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

标签: c++cudalinkerstatic-libraries

解决方案


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

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

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

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

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

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


推荐阅读