如何在单个 (.a) 存档中只获取所需的目标文件
How to take only required object files inside a single (.a) archive
只是一个简单的问题,但我在任何地方都找不到答案。将所有目标文件放入存档时,如何指示clang++只取所需的目标文件进行链接,以避免由于存档中不需要的符号而导致未定义的符号错误?
您将无法找到您正在寻找的答案,因为您
想让 linker 做的是它默认做的事情。这是一个演示。
(它在 C 而不是 C++ 中只是为了让我们免于 C++ 名称修改的混淆)。
三个源文件:
alice.c
#include <stdio.h>
void alice(void)
{
puts("alice");
}
bob.c
#include <stdio.h>
void bob(void)
{
puts("bob");
}
mary.c
#include <stdio.h>
void mary(void)
{
puts("mary");
}
编译它们并将目标文件放入存档中:
$ clang -Wall -c alice.c
$ clang -Wall -c bob.c
$ clang -Wall -c mary.c
$ ar rc libabm.a alice.o bob.o mary.o
这里是存档的成员列表:
$ ar -t libabm.a
alice.o
bob.o
mary.o
这里是这些成员的符号table:
$ nm libabm.a
alice.o:
0000000000000000 T alice
U puts
bob.o:
0000000000000000 T bob
U puts
mary.o:
0000000000000000 T mary
U puts
其中 T
表示定义的函数,U
表示未定义的函数。 puts
是
在标准 C 库中定义,默认情况下将 linked。
下面是一个从外部调用alice
的程序,因此依赖于
alice.o
:
说alice.c
extern void alice(void);
int main(void)
{
alice();
return 0;
}
还有另一个程序在外部调用 alice
和 bob
,因此
依赖于 alice.o
和 bob.o
.
sayalice_n_bob.c
extern void alice(void);
extern void bob(void);
int main(void)
{
alice();
bob();
return 0;
}
同时编译这两个源代码:
$ clang -Wall -c sayalice.c
$ clang -Wall -c sayalice_n_bob.c
linker 选项 -trace
指示 linker 报告 linked 的目标文件和 DSO。我们将使用
现在 link 使用 sayalice.o
和 libabm.a
:
编程 sayalice
$ clang -o sayalice sayalice.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice.o
(./libabm.a)alice.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
我们看到所有样板 C 库和运行时都是 linked。和的
我们 创建的目标文件,只有两个是 linked:
sayalice.o
(./libabm.a)alice.o
我们程序不的libabm.a
的两个成员依赖于:
(./libabm.a)bob.o
(./libabm.a)mary.o
不是 linked.
运行程序:
$ ./sayalice
alice
它说 "alice"。
然后为了比较,我们将 link 编程 sayalice_n_bob
,再次与 -trace
:
$ clang -o sayalice_n_bob sayalice_n_bob.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
这一次,我们的三个目标文件被 link编辑:
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
并且 libabm.a
中唯一一个程序不 依赖的成员:
(./libabm.a)mary.o
未 link 编辑。
这个程序运行如下:
$ ./sayalice_n_bob
alice
bob
这里是程序的全局符号table:
$ nm -g sayalice_n_bob
0000000000400520 T alice
0000000000400540 T bob
0000000000601030 B __bss_start
0000000000601020 D __data_start
0000000000601020 W data_start
0000000000601028 D __dso_handle
0000000000601030 D _edata
0000000000601038 B _end
00000000004005d4 T _fini
w __gmon_start__
00000000004003d0 T _init
00000000004005e0 R _IO_stdin_used
00000000004005d0 T __libc_csu_fini
0000000000400560 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
00000000004004f0 T main
U puts@@GLIBC_2.2.5
0000000000400410 T _start
0000000000601030 D __TMC_END__
有 alice
和 bob
,但没有 mary
。
因此,如您所见,linker 的默认行为就是您要问的行为
要得到。 停止 linker 仅提取存档成员
在 linkage 中引用而不是 link all 存档成员,你必须
通过将存档放在 --whole-archive
的范围内,明确告诉它这样做
linkage 命令行中的选项:
$ clang -o sayalice_n_bob sayalice_n_bob.o -L. -Wl,--whole-archive -labm -Wl,--no-whole-archive -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
(./libabm.a)mary.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
您会看到所有存档成员都是 linked:
(./libabm.a)alice.o
(./libabm.a)bob.o
(./libabm.a)mary.o
程序现在定义了所有 alice
、bob
和 mary
:
$ nm -g sayalice_n_bob
0000000000400520 T alice
0000000000400540 T bob
0000000000601030 B __bss_start
0000000000601020 D __data_start
0000000000601020 W data_start
0000000000601028 D __dso_handle
0000000000601030 D _edata
0000000000601038 B _end
00000000004005f4 T _fini
w __gmon_start__
00000000004003d0 T _init
0000000000400600 R _IO_stdin_used
00000000004005f0 T __libc_csu_fini
0000000000400580 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
00000000004004f0 T main
0000000000400560 T mary
U puts@@GLIBC_2.2.5
0000000000400410 T _start
0000000000601030 D __TMC_END__
尽管它从不调用 mary
。
退一步
你问这个问题是因为你相信如果你可以 link 从档案
仅那些定义已在 linkage 中引用的符号的目标文件
那么 linkage 不会因未定义的符号引用而失败
从不使用。但那不是真的,这里有一个证明它不是。
另一个源文件:
alice2.c
#include <stdio.h>
extern void david(void);
void alice(void)
{
puts("alice");
}
void dave(void)
{
david();
}
编译:
$ clang -Wall -c alice2.c
将alice.o
替换为libabm.a
中的alice2.o
:
$ ar d libabm.a alice.o
$ ar r libabm.a alice2.o
然后像以前一样尝试link编程sayalice
:
$ clang -o sayalice sayalice.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice.o
(./libabm.a)alice2.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
./libabm.a(alice2.o): In function `dave':
alice2.c:(.text+0x25): undefined reference to `david'
/usr/bin/ld: link errors found, deleting executable `sayalice'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这一次,唯一获得 linked 的存档成员是:
(./libabm.a)alice2.o
因为在sayalice.o
中只调用了alice
。然而 linkage 失败了
对函数 david
、 的未定义引用,程序从不调用 。
david
仅在函数 dave
的定义中被调用,而 dave
从未被调用。
虽然 dave
从未被调用,但它的定义是 linked 因为它位于一个
目标文件 alice2.o
,即 linked 以提供函数定义 alice
-
被调用。并且根据 linkage 中 dave
的定义,对 david
的调用
成为未解析的引用,默认情况下 linkage 必须找到一个
定义,否则失败。所以它失败了。
然后你会看到 linkage 的失败是由于对 a 的未定义引用
程序从不使用的符号与 linker 的事实一致
不 link 未引用存档中的目标文件。
如何在不使用的符号的未定义引用中幸存下来
如果您遇到这种link年龄故障,您可以通过将
linker 容忍未定义的引用。您可以直接将其指向 ignore
所有未定义的引用,例如:
$ clang -o sayalice sayalice.o -L. -labm -Wl,--unresolved-symbols=ignore-all
$ ./sayalice
alice
或者更谨慎地,您可以将其指向只是发出警告,而不是失败,因为
未定义的引用,例如:
$ clang -o sayalice sayalice.o -L. -labm -Wl,--warn-unresolved-symbols
./libabm.a(alice2.o): In function `dave':
alice2.c:(.text+0x25): warning: undefined reference to `david'
$ ./sayalice
alice
这样,您可以在诊断中检查唯一未定义的符号是
你期待的那些。
只是一个简单的问题,但我在任何地方都找不到答案。将所有目标文件放入存档时,如何指示clang++只取所需的目标文件进行链接,以避免由于存档中不需要的符号而导致未定义的符号错误?
您将无法找到您正在寻找的答案,因为您 想让 linker 做的是它默认做的事情。这是一个演示。 (它在 C 而不是 C++ 中只是为了让我们免于 C++ 名称修改的混淆)。
三个源文件:
alice.c
#include <stdio.h>
void alice(void)
{
puts("alice");
}
bob.c
#include <stdio.h>
void bob(void)
{
puts("bob");
}
mary.c
#include <stdio.h>
void mary(void)
{
puts("mary");
}
编译它们并将目标文件放入存档中:
$ clang -Wall -c alice.c
$ clang -Wall -c bob.c
$ clang -Wall -c mary.c
$ ar rc libabm.a alice.o bob.o mary.o
这里是存档的成员列表:
$ ar -t libabm.a
alice.o
bob.o
mary.o
这里是这些成员的符号table:
$ nm libabm.a
alice.o:
0000000000000000 T alice
U puts
bob.o:
0000000000000000 T bob
U puts
mary.o:
0000000000000000 T mary
U puts
其中 T
表示定义的函数,U
表示未定义的函数。 puts
是
在标准 C 库中定义,默认情况下将 linked。
下面是一个从外部调用alice
的程序,因此依赖于
alice.o
:
说alice.c
extern void alice(void);
int main(void)
{
alice();
return 0;
}
还有另一个程序在外部调用 alice
和 bob
,因此
依赖于 alice.o
和 bob.o
.
sayalice_n_bob.c
extern void alice(void);
extern void bob(void);
int main(void)
{
alice();
bob();
return 0;
}
同时编译这两个源代码:
$ clang -Wall -c sayalice.c
$ clang -Wall -c sayalice_n_bob.c
linker 选项 -trace
指示 linker 报告 linked 的目标文件和 DSO。我们将使用
现在 link 使用 sayalice.o
和 libabm.a
:
sayalice
$ clang -o sayalice sayalice.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice.o
(./libabm.a)alice.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
我们看到所有样板 C 库和运行时都是 linked。和的 我们 创建的目标文件,只有两个是 linked:
sayalice.o
(./libabm.a)alice.o
我们程序不的libabm.a
的两个成员依赖于:
(./libabm.a)bob.o
(./libabm.a)mary.o
不是 linked.
运行程序:
$ ./sayalice
alice
它说 "alice"。
然后为了比较,我们将 link 编程 sayalice_n_bob
,再次与 -trace
:
$ clang -o sayalice_n_bob sayalice_n_bob.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
这一次,我们的三个目标文件被 link编辑:
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
并且 libabm.a
中唯一一个程序不 依赖的成员:
(./libabm.a)mary.o
未 link 编辑。
这个程序运行如下:
$ ./sayalice_n_bob
alice
bob
这里是程序的全局符号table:
$ nm -g sayalice_n_bob
0000000000400520 T alice
0000000000400540 T bob
0000000000601030 B __bss_start
0000000000601020 D __data_start
0000000000601020 W data_start
0000000000601028 D __dso_handle
0000000000601030 D _edata
0000000000601038 B _end
00000000004005d4 T _fini
w __gmon_start__
00000000004003d0 T _init
00000000004005e0 R _IO_stdin_used
00000000004005d0 T __libc_csu_fini
0000000000400560 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
00000000004004f0 T main
U puts@@GLIBC_2.2.5
0000000000400410 T _start
0000000000601030 D __TMC_END__
有 alice
和 bob
,但没有 mary
。
因此,如您所见,linker 的默认行为就是您要问的行为
要得到。 停止 linker 仅提取存档成员
在 linkage 中引用而不是 link all 存档成员,你必须
通过将存档放在 --whole-archive
的范围内,明确告诉它这样做
linkage 命令行中的选项:
$ clang -o sayalice_n_bob sayalice_n_bob.o -L. -Wl,--whole-archive -labm -Wl,--no-whole-archive -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice_n_bob.o
(./libabm.a)alice.o
(./libabm.a)bob.o
(./libabm.a)mary.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
您会看到所有存档成员都是 linked:
(./libabm.a)alice.o
(./libabm.a)bob.o
(./libabm.a)mary.o
程序现在定义了所有 alice
、bob
和 mary
:
$ nm -g sayalice_n_bob
0000000000400520 T alice
0000000000400540 T bob
0000000000601030 B __bss_start
0000000000601020 D __data_start
0000000000601020 W data_start
0000000000601028 D __dso_handle
0000000000601030 D _edata
0000000000601038 B _end
00000000004005f4 T _fini
w __gmon_start__
00000000004003d0 T _init
0000000000400600 R _IO_stdin_used
00000000004005f0 T __libc_csu_fini
0000000000400580 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
00000000004004f0 T main
0000000000400560 T mary
U puts@@GLIBC_2.2.5
0000000000400410 T _start
0000000000601030 D __TMC_END__
尽管它从不调用 mary
。
退一步
你问这个问题是因为你相信如果你可以 link 从档案 仅那些定义已在 linkage 中引用的符号的目标文件 那么 linkage 不会因未定义的符号引用而失败 从不使用。但那不是真的,这里有一个证明它不是。
另一个源文件:
alice2.c
#include <stdio.h>
extern void david(void);
void alice(void)
{
puts("alice");
}
void dave(void)
{
david();
}
编译:
$ clang -Wall -c alice2.c
将alice.o
替换为libabm.a
中的alice2.o
:
$ ar d libabm.a alice.o
$ ar r libabm.a alice2.o
然后像以前一样尝试link编程sayalice
:
$ clang -o sayalice sayalice.o -L. -labm -Wl,-trace
/usr/bin/ld: mode elf_x86_64
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crt1.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtbegin.o
sayalice.o
(./libabm.a)alice2.o
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/lib/x86_64-linux-gnu/libc.so.6
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libgcc_s.so.1 (/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/libgcc_s.so.1)
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/crtend.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../x86_64-linux-gnu/crtn.o
./libabm.a(alice2.o): In function `dave':
alice2.c:(.text+0x25): undefined reference to `david'
/usr/bin/ld: link errors found, deleting executable `sayalice'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这一次,唯一获得 linked 的存档成员是:
(./libabm.a)alice2.o
因为在sayalice.o
中只调用了alice
。然而 linkage 失败了
对函数 david
、 的未定义引用,程序从不调用 。
david
仅在函数 dave
的定义中被调用,而 dave
从未被调用。
虽然 dave
从未被调用,但它的定义是 linked 因为它位于一个
目标文件 alice2.o
,即 linked 以提供函数定义 alice
-
被调用。并且根据 linkage 中 dave
的定义,对 david
的调用
成为未解析的引用,默认情况下 linkage 必须找到一个
定义,否则失败。所以它失败了。
然后你会看到 linkage 的失败是由于对 a 的未定义引用 程序从不使用的符号与 linker 的事实一致 不 link 未引用存档中的目标文件。
如何在不使用的符号的未定义引用中幸存下来
如果您遇到这种link年龄故障,您可以通过将 linker 容忍未定义的引用。您可以直接将其指向 ignore 所有未定义的引用,例如:
$ clang -o sayalice sayalice.o -L. -labm -Wl,--unresolved-symbols=ignore-all
$ ./sayalice
alice
或者更谨慎地,您可以将其指向只是发出警告,而不是失败,因为 未定义的引用,例如:
$ clang -o sayalice sayalice.o -L. -labm -Wl,--warn-unresolved-symbols
./libabm.a(alice2.o): In function `dave':
alice2.c:(.text+0x25): warning: undefined reference to `david'
$ ./sayalice
alice
这样,您可以在诊断中检查唯一未定义的符号是 你期待的那些。