简体   繁体   English

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

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

I am working on a little project to understand the chain of compiler and linker better.我正在做一个小项目,以更好地了解编译器链和 linker。

Suppose that i have the libraries libfoo.a and libbar.a .假设我有库libfoo.alibbar.a I want to create a library libmy.a , that acts like a wrapper or top level API to both libraries.我想创建一个库libmy.a ,它就像两个库的包装器或顶级 API 。 The target is, that only libmy.a should be required to build an executable, that uses my defined wrapper functions.目标是,只需要libmy.a来构建一个使用我定义的包装函数的可执行文件。 I created a cmake project and set up the library我创建了一个 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)

That works fine and there is no problem in compilation.这工作正常,编译没有问题。 However, if I try to reference the object from an external project, it tells me, that I have undefined references to the functions in libfoo.a and libbar.a .但是,如果我尝试从外部项目引用 object,它会告诉我,我对libfoo.alibbar.a中的函数有未定义的引用。 As far as I understand the problem, the linker only creates a declaration in the libmy.a, without including its definition from the external library.据我了解这个问题,linker 只在 libmy.a 中创建一个声明,而不包括它从外部库中的定义。 I checked this by opening libmy.a with the nm libmy.a command, where the used functions of the external libraries are declared, but undefined.我通过使用nm libmy.a命令打开libmy.a来检查这一点,其中声明了外部库的使用函数,但未定义。

I came across one solution that used ar to combine multiple library files.我遇到了一种使用ar组合多个库文件的解决方案。 However I would like to avoid such methods, because if it is not a single library, but a bunch of, say 10 libraries, it is not suitable to search each library for a definition and copy it into libmy.a .但是我想避免这种方法,因为如果它不是一个库,而是一堆,比如 10 个库,不适合在每个库中搜索定义并将其复制到libmy.a中。 Just throwing all libraries together isn't a solution either, because the file will get too big.将所有库放在一起也不是解决方案,因为文件会变得太大。

Is it importand to note, that one of these library packages is CUDA?重要的是要注意,这些库包之一是 CUDA?

I am sure there is a solution, but I was not able to find one.我确信有一个解决方案,但我找不到一个。 Any help would be appreciated任何帮助,将不胜感激

The target is, that only libmy.a should be required to build an executable目标是,构建可执行文件只需要libmy.a

This is already an unconventional goal for static libraries.对于 static 库来说,这已经是一个非常规的目标。

Static libraries normally only contain the object code built from the source code for that library . Static 库通常只包含从该的源代码构建的 object 代码。 Users of that library must also link to the libraries that your library requires, because the definitions have not been copied in to your library when it was built.该库的用户还必须链接到您的库所需的库,因为在构建库时定义尚未复制到您的库中。

Tools like ar can be used to combine multiple static libraries together, since they are just archives of object code.ar这样的工具可用于将多个 static 库组合在一起,因为它们只是 object 代码的存档。 The tool can not predict which object code the end-user will use though, so it will bundle entire libraries.该工具无法预测最终用户将使用哪个 object 代码,因此它将捆绑整个库。 Otherwise, the end user may be looking for a definition that you left out and then need to link in a 2nd copy of the dependency lib anyways.否则,最终用户可能正在寻找您遗漏的定义,然后无论如何都需要链接到依赖库的第二个副本。

If you want to provide a library that has everything the end-user needs, cut down to what your wrapper actually uses, you can build a shared library.如果您想提供一个包含最终用户需要的所有内容的库,减少到您的包装器实际使用的内容,您可以构建一个共享库。 Shared libraries are considered executable, so the compiler knows that any unreferenced object code is not going to be used, and it will not be included in the shared library.共享库被认为是可执行的,因此编译器知道任何未引用的 object 代码都不会被使用,也不会包含在共享库中。

You can force the entire static libraries to be included in shared libraries though.可以强制将整个 static 库包含在共享库中。
On GCC you can use the linker argument: --whole-archive to ensure that all of the object code from the following libraries is included.在 GCC 上,您可以使用 linker 参数:--whole --whole-archive以确保包含以下库中的所有 object 代码。
On MSVC, you can use the /WHOLEARCHIVE:<library file name> argument to do the same.在 MSVC 上,您可以使用/WHOLEARCHIVE:<library file name>参数来执行相同的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM