如何嵌入静态库的副本?
How to embed copies of static library?
这是我的解决方案的结构:
A.lib
定义:
int a(void) { return 1; }
B.lib
定义:
int b(void) { return a(); }
C.lib
定义:
int c(void) { return a() * 2; }
SharedStaticLibsTest.exe
定义:
int main(void) { std::cout << b() + c() << std::endl; return 0;}
我决定检查(通过 DumpBin
)结果应用程序中嵌入的代码。结果是 B
和 C
库使用了 A
库的唯一实例。有没有办法(出于教育目的)在 B
和 C
中使用两个不同的 A
实例?也许这个东西有特定的链接器选项?我明白,这种行为可能会产生意想不到的副作用,这取决于 A
库的逻辑。
P.S。我通过在项目属性中直接包含 .lib 文件来替换对项目的引用。现在 B
、C
个项目有 A
个项目的副本。但最终项目仍然只有 A
库的副本。我不知道链接器是如何解决这个问题的。
首先,如果您最终在构建中有两个 A
实例,则从 A
导出的所有标识符都需要遵循 One-Definition-Rule.
也就是说,即使您在技术上可以拥有两个不同版本的 A
,除非它们在所有意图和目的上都相同,否则您的程序是无效的,无论是编译器还是 linker有义务告诉您(C++ 标准称此 格式错误,不需要诊断 )。在实践中,这意味着您的程序中将有 非常 个奇怪的错误,并且不知道它们来自哪里。
话虽如此,从技术上讲,没有什么能阻止您构建您所要求的情况。通常静态依赖只在 linking 阶段被处理。因此,依赖于另一个静态库 A
的静态库 B
不会导致一个从另一个导出符号 - B
将不包含来自 A
.[= 的任何符号39=]
相反,您的构建系统将跟踪该依赖关系,一旦您到达 linker 阶段(例如,通过构建依赖于 B
的可执行文件),构建系统将采取注意 两个 库都得到 linked。这也意味着,如果您没有构建系统,或者您的构建配置不正确,您将收到 linker 错误,因为缺少 A
库中的符号,即使您 link 明确反对 B
和 C
。
因此,复制符号的规范、可移植方式需要通过 动态库 将它们拉入,因为它们会通过 linker。如果您将 B
和 C
更改为动态库,它们都将 link 反对 A
并包含它们自己使用的来自 A
的函数的单独版本。如果您在构建 B
和 C
之间更改了 A
,它们将包含不同的定义。希望您的构建系统会尝试防止这种情况发生。
请注意,C++ 标准并没有太多关于动态库的内容,因此有关如何在此处解析符号以及重复符号的影响的技术细节,请参阅您的操作系统手册。
使用 MSVC,还可以为静态库执行此操作。在 B
或 C
的项目属性中,前往 Librarian -> General 并设置 Link 库依赖项 选项 Yes
。现在,如果您重新构建并再次查看 B.lib
和 C.lib
的转储,它们应该也包含来自 A
的符号。当然,在构建生成的可执行文件时,linker 将从 B
或 C
中选择版本(或者直接从 A
中选择版本,具体取决于您的方式linking) 对于正在使用的每个 A
符号。请不要在生产中这样做。
这是我的解决方案的结构:
A.lib
定义:
int a(void) { return 1; }
B.lib
定义:
int b(void) { return a(); }
C.lib
定义:
int c(void) { return a() * 2; }
SharedStaticLibsTest.exe
定义:
int main(void) { std::cout << b() + c() << std::endl; return 0;}
我决定检查(通过 DumpBin
)结果应用程序中嵌入的代码。结果是 B
和 C
库使用了 A
库的唯一实例。有没有办法(出于教育目的)在 B
和 C
中使用两个不同的 A
实例?也许这个东西有特定的链接器选项?我明白,这种行为可能会产生意想不到的副作用,这取决于 A
库的逻辑。
P.S。我通过在项目属性中直接包含 .lib 文件来替换对项目的引用。现在 B
、C
个项目有 A
个项目的副本。但最终项目仍然只有 A
库的副本。我不知道链接器是如何解决这个问题的。
首先,如果您最终在构建中有两个 A
实例,则从 A
导出的所有标识符都需要遵循 One-Definition-Rule.
也就是说,即使您在技术上可以拥有两个不同版本的 A
,除非它们在所有意图和目的上都相同,否则您的程序是无效的,无论是编译器还是 linker有义务告诉您(C++ 标准称此 格式错误,不需要诊断 )。在实践中,这意味着您的程序中将有 非常 个奇怪的错误,并且不知道它们来自哪里。
话虽如此,从技术上讲,没有什么能阻止您构建您所要求的情况。通常静态依赖只在 linking 阶段被处理。因此,依赖于另一个静态库 A
的静态库 B
不会导致一个从另一个导出符号 - B
将不包含来自 A
.[= 的任何符号39=]
相反,您的构建系统将跟踪该依赖关系,一旦您到达 linker 阶段(例如,通过构建依赖于 B
的可执行文件),构建系统将采取注意 两个 库都得到 linked。这也意味着,如果您没有构建系统,或者您的构建配置不正确,您将收到 linker 错误,因为缺少 A
库中的符号,即使您 link 明确反对 B
和 C
。
因此,复制符号的规范、可移植方式需要通过 动态库 将它们拉入,因为它们会通过 linker。如果您将 B
和 C
更改为动态库,它们都将 link 反对 A
并包含它们自己使用的来自 A
的函数的单独版本。如果您在构建 B
和 C
之间更改了 A
,它们将包含不同的定义。希望您的构建系统会尝试防止这种情况发生。
请注意,C++ 标准并没有太多关于动态库的内容,因此有关如何在此处解析符号以及重复符号的影响的技术细节,请参阅您的操作系统手册。
使用 MSVC,还可以为静态库执行此操作。在 B
或 C
的项目属性中,前往 Librarian -> General 并设置 Link 库依赖项 选项 Yes
。现在,如果您重新构建并再次查看 B.lib
和 C.lib
的转储,它们应该也包含来自 A
的符号。当然,在构建生成的可执行文件时,linker 将从 B
或 C
中选择版本(或者直接从 A
中选择版本,具体取决于您的方式linking) 对于正在使用的每个 A
符号。请不要在生产中这样做。