c++ - 将第三方库与我的 C++ 包装器代码静态链接在一起
问题描述
我正在做一个小项目来更好地理解编译器和链接器的链。
假设我有库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 中创建一个声明,而不包括它来自外部库的定义。我通过 libmy.a
使用nm libmy.a
命令打开来检查这一点,其中声明了外部库的使用函数,但未定义。
我遇到了一种用于ar
组合多个库文件的解决方案。但是我想避免这种方法,因为如果它不是单个库,而是一堆,比如 10 个库,不适合在每个库中搜索定义并将其复制到libmy.a
. 将所有库放在一起也不是解决方案,因为文件会变得太大。
重要的是要注意,这些库包之一是 CUDA?
我确信有一个解决方案,但我找不到一个。任何帮助,将不胜感激
解决方案
目标是,只
libmy.a
需要构建可执行文件
这对于静态库来说已经是一个非常规的目标。
静态库通常只包含从该库的源代码构建的目标代码。该库的用户还必须链接到您的库所需的库,因为在构建库时定义尚未复制到您的库中。
诸如此类的工具ar
可用于将多个静态库组合在一起,因为它们只是目标代码的存档。该工具无法预测最终用户将使用哪个目标代码,因此它将捆绑整个库。否则,最终用户可能正在寻找您遗漏的定义,然后无论如何都需要链接到依赖库的第二个副本。
如果您想提供一个包含最终用户需要的所有内容的库,减少到您的包装器实际使用的内容,您可以构建一个共享库。共享库被认为是可执行的,因此编译器知道任何未引用的目标代码都不会被使用,并且不会包含在共享库中。
您可以强制将整个静态库包含在共享库中。
在 GCC 上,您可以使用链接器参数:--whole-archive
以确保包含以下库中的所有目标代码。
在 MSVC 上,您可以使用/WHOLEARCHIVE:<library file name>
参数来执行相同的操作。
推荐阅读
- javascript - 无需身份验证将数据写入 Firebase 实时数据库中的字段
- html - 在图像上添加平滑渐变滤镜
- php - 灯泡服务器中的碳投掷错误
- swift4.1 - URLSession.shared.dataTask 在没有 .resume() 的情况下无法工作
- angular - 在科尔多瓦离子本机应用程序中为openID连接指定重定向uri的位置
- c# - 如何在 FluentValidation 的世界中使用带有 ValidateAsync 的规则集?
- python - 过滤满足一组标准的多对多关系
- asp.net - 可以将纯文本密码发送到服务器端进行身份验证吗?避免这种纯文本传输的常用方法是什么
- symfony - Symfony 4 - Lexik/JwtAuthenticationBundle - 无法更改 token_ttl 默认值
- html - 如何在输入中进行 Html 电子邮件验证?