c - 有没有办法让链接器从库中拉出目标文件的一部分进行链接?

标签 c linker translation-unit

我有一个包含数千个 C 文件、许多库和数十个要链接的程序的项目,为了加快编译速度,我将 C 文件组合成包含多个 C 文件的翻译单元。这有时称为单个编译单元、单个翻译单元或统一构建。

我将多个这样的翻译单元编译成不同的库,这些库之前是通过单独编译每个 C 文件创建的。

例如:

旧库.lib:

file1.o
file2.o
file3.o
file4.o
file5.o
file6.o

新库.lib:

translation_unit_1.o
translation_unit_2.o

translation_unit_1.c:

#include "file1.c"
#include "file2.c"
#include "file3.c"

translation_unit_2.c:

#include "file4.c"
#include "file5.c"
#include "file6.c"

所以这些编译成:translation_unit_1.o 和 translation_unit_2.o。而库就是上面显示的新的library.lib。

现在假设我有一个程序,我想链接到 library.lib,它引用 file2.c 中的一个函数。但是它编译的 file1.c 版本不同,会复制库中 file1.c 中的符号,因此它只需要 library.lib 中的 file2.c 进行链接。或者我可能需要从 file1.c 链接代码但无法链接 file2.c,因为它具有我不想依赖的依赖项(如下示例)。

程序:

main.o
file1.o
library.lib

是否有任何您知道的链接器可以让链接器仅将代码从 file2.c 中拉出 translation_unit_1.o 目标代码并使用它来链接 main.o 以制作程序?

另一种方法是将 translation_unit_1.o 拆分为 file1.o、file2.o、file3.o(如果可能),然后将其提供给链接器。

感谢您的帮助。

编辑1

这适用于为使用 ARM ADS 1.2 工具链编译的 ELF 的裸机 ARM 平台和使用 Visual Studio 工具链的 Windows 平台编译的单一代码库。但是,欢迎考虑如何在其他平台和工具链上解决该问题。

这是在 MacOS 上使用 clang 的具体示例。

下面的示例代码在这里:https://github.com/awmorgan/single_translation_unit_lib_link

图书馆:

file1.c 链接需要这个文件

file2.c 此文件不用于链接并且具有 Unresolved 依赖关系,它可能在另一个库或对象中

主.c:

int main( void ) {
    extern int file1_a( void );
    int x = file1_a();
}

文件1.c:

int file1_a(void) {
    return 1;
}

文件2.c:

int file2_a( void ) {
    extern int file3_a( void );
    return file3_a(); // file3_a() is located somewhere else
}

single_translation_unit.c:

#include "file1.c"
#include "file2.c"

这可以生成 program1.out:

++ clang -c file1.c -o file1.o
++ clang -c file2.c -o file2.o
++ libtool -static file1.o file2.o -o library1.lib
++ clang -c main.c -o main1.o
++ clang main1.o library1.lib -o program1.out

这无法生成 program2.out:

++ clang -c single_translation_unit.c -o single_translation_unit.o
++ libtool -static single_translation_unit.o -o library2.lib
++ clang -c main.c -o main2.o
++ clang main2.o library2.lib -o program2.out
Undefined symbols for architecture x86_64:
  "_file3_a", referenced from:
      _file2_a in library2.lib(single_translation_unit.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

更改链接顺序也不起作用:

++ clang library2.lib main2.o -o program2.out
Undefined symbols for architecture x86_64:
  "_file3_a", referenced from:
      _file2_a in library2.lib(single_translation_unit.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

最佳答案

Is there a way with clang, gcc, microsoft or any linker

clanggccmicrosoft 都不是链接器(前两个是编译器,第三个是公司)。

答案还取决于平台(您未指定)。

如果您在 Linux 或其他 ELF 平台上构建,您可以使用 -ffunction-sections -fdata-sections 编译代码,链接器将自动做你想做的。

Is there a way to have a linker pull part of an object file from a library for linking?

一般来说,链接器对部分进行操作,并且不能将部分分开(要么得到全部,要么一无所有)。

没有 -ffunction-sections,单个翻译单元中的所有函数最终都在单个 .text 部分(这是一个近似值——模板实例化和输出inline 函数的离线函数定义通常在它们自己的一个部分中结束)。因此,链接器无法选择 .text 的部分而非全部部分。

关于c - 有没有办法让链接器从库中拉出目标文件的一部分进行链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54607237/

相关文章:

c - 在 C 中链接文件/头文件

c - 从c中的另一个文件链接静态函数

gcc - "Hidden symbol ` atexit ' is referenced by DSO"将 libtool 与 gcov 一起使用时

c++ - 文件中不包含头文件,但仍可以使用未包含的头文件中的类/函数

c - 是否调用 shmget 或 shmat 初始化数据?

c - 错误 : lvalue required as unary ‘&’ operand, 我见过解决方案,但无法将它们与我的查询相关联

c++ - 同名结构,不同定义 : segmentation fault with -O2

c++ 17内联+ thread_local vs thread_local

c - 在此信号处理程序中会发生什么?

c - LED 保持亮起。不会打开和关闭