是否可以使静态 C++ 库自包含?

Posted

技术标签:

【中文标题】是否可以使静态 C++ 库自包含?【英文标题】:Is it possible to make static C++ library self contained? 【发布时间】:2021-01-11 10:49:37 【问题描述】:

如果我的库具有外部依赖项,是否可以将这些库包含到我自己的静态库中,我的库的用户不需要链接到这些依赖项?还是应该让它成为动态库?

图书馆.h

#ifndef AMAZING_CPP_LIBRARY_H
#define AMAZING_CPP_LIBRARY_H

#ifdef __cplusplus
extern "C" 
#endif

typedef struct 
    int m_code;
 Result;

extern void message(const char* msg);

extern Result * get_result();

extern void vector_example(int size);

#ifdef __cplusplus

#endif

#endif //AMAZING_CPP_LIBRARY_H

库.cpp

#include <iostream>
#include <vector>
#include "library.h"

void vector_example(int size)
    std::vector<uint8_t> vec;
    vec.reserve(size);
    for (int i = 0; i < size; ++i) 
        vec.push_back(i);
    
    // do something with vector


void message(const char* msg) 
    std::cout << msg<< "\n";


Result * get_result() 
    Result* result = new Result();
    result->m_code = 200;
    return result;

main.c

#include "library.h"

int main() 
    vector_example(2);
    message("hello from cpp");
    return 0;

我正在运行的命令

1$ clang++ -c library.cpp
2$ ar -rcs libamazing_cpp.a library.o
3$ clang -c main.c 
4$ clang main.o libamazing_cpp.a 

是否可以只链接到我的静态库而无需使用-lstdc++ 或使用clang++ 命令进行编译?

【问题讨论】:

为什么?究竟是什么问题? 静态库 (.a) 只不过是目标文件的集合(“a”代表“归档”)。所以不,不可能。您可以捆绑相关的 libstdc++ 对象,但它们稍后会与共享的 libstdc++ 冲突。 @rustyx:在早期库中拥有库对象模块的副本不会产生冲突。仅当链接器定义了尚未由已采用的目标模块定义的符号时,链接器才从库中获取模块。因此,当它在以后的库中遇到重复模块时,它会简单地忽略它。 github.com/intoli/exodus 您特别提出了避免链接 C++ 标准库的问题,但您似乎忽略了一些重要的细节。例如,大多数 C++ 编译器并不要求你显式链接 C++ 标准库,如果你不使用 C++ 编译器来构建 C++ 程序,那么你就会面临与 C++ 相关的各种不当行为在运行时未正确设置环境。我倾向于认为做你想做的事情的最好结果就是它不会让事情变得更糟。如果你幸运的话。 【参考方案1】:

是否可以使静态 C++ 库自包含?

这是特定于实现的,有时可能是非法的。

请注意,大多数 C++ 标准(例如 n3337)甚至都没有提及库(特别是与您的编译器相关的,例如 GCC 及其标准 C++ 库 libstdc++

但您的 C++ 库可能会使用标准 C++ containers(C++ 标准的一部分)或其他开源 C++ 库,例如 Qt 或 FLTK,其许可证可能要求您的用户能够升级它们。

请务必联系您的律师,因为您的问题可能涉及与软件许可相关的法律问题。

在 Linux 上,效率会很低

如果您以 Linux 为目标,您希望利用 现有 共享库(如 ldd(1) 列出的,或者 - 如果您有一个正在运行的进程 - 由 pmap(1) 列出)。阅读 Drepper 的论文 How to write shared libraries 了解详细信息和解释,并考虑将您的库设为共享库。

clang++ -c library.cpp

提示:至少使用clang++ -c -Wall -Wextra -g library.cpp 然后使用GDB 来调试你的库,同时尝试g++ -Wall -Wextra -g library.cpp 和valgrind。

为了简化您的库在 Linux 系统上的安装(或测试),您可能需要为其提供 package。在Debian 上,它将是一些*.deb 文件。

【讨论】:

如果my_library 仅适用于library_V1 但用户拥有library_V2 会怎样,他是否需要降级/下载该库的另一个版本?另一个案例library_V1 在他的平台上不可用。他需要自己编译吗? 视情况而定。可能是。但是,如果您的*.deb 包被正确编写(不是一件容易的事),那么安装它的dpkg 命令会处理这种依赖关系。考虑使用open source licence 或更好的free software 发布库的C++ 代码(和打包脚本),例如GNU readline。您可能需要获得经理的批准,然后可能需要外部贡献者的帮助。

以上是关于是否可以使静态 C++ 库自包含?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 C++ 类中声明一个虚拟静态常量值?

我们可以在 C++ 中有一个静态类吗?

C++派生类是不是可以从基类继承静态数据成员和静态成员函数?

Java的静态成员和C++的静态成员之间的区别[关闭]

我可以在 Visual Studio 2008 中使用 Visual Studio 6 编译的 C++ 静态库吗?

C++的静态库lib是可以包含函数的注释(说明文档)的