假设有如三个源代码文件:
$?cat?a.cpp
void?a()
{
}
$?cat?b.cpp
extern?void?a();
void?b()
{
a();?//?调用a.cpp中的a()
}
$?cat?x.cpp
extern?void?b();
int?main()
{
b();?//?调用b.cpp中的b()
return?0;
}
对应的Makefile文件:
all:?x
liba.a:?a.o
libb.a:?b.o
x:?x.o?liba.a?libb.a?#?问题出在这儿
g++?-g?-o?$@?$^
a.o:?a.cpp
g++?-g?-c?$^
b.o:?b.cpp
g++?-g?-c?$^
x.o:?x.cpp
g++?-g?-c?$^
clean:
rm?-f?a.o?b.o?x.o?x
使用上面的Makefile编译,将会遇到如下所示的“?developer/article/1178753/undefined?reference”问题:
g++?-g?-c?x.cpp
g++?-g?-c?a.cpp
g++?-g?-c?b.cpp
g++?-g?-o?x?x.o?liba.a?libb.a?#?改成“g++?-g?-o?x?x.o?libb.a?liba.a”即可解决
libb.a(b.o):?In?function?`b()':
/tmp/b.cpp:2:??developer/article/1178753/undefined?reference?to?`a()'
collect2:?ld?returned?1?exit?status
make:?***?[x]?Error?1
这个问题的原因是b.cpp依赖a.cpp,gcc要求(实际是ld要求)libb.a须放在liba.a前面,即需要改成:g++?-g?-o?x?x.o?libb.a?liba.a,也就是被依赖的库需要放在后头。
这是最常规的解决办法,除此之外,只需要加入--start-group和--end-group两个链接参数,即可保持被依赖的库放在前头,也就是改成如下即可:g++?-g?-o?$@?-Wl,--start-group?$^?-Wl,--end-group。
这里的“-Wl,”表示后面跟着的参数是传递给链接器ld的,gcc不关心具体是啥。“--start-group”表示范围的开始;“--end-group”表示范围的结束,是可选的。位于“--end-group”之后的仍然要求被依赖的库放在后头。注意“--start-group”不能重复,相关链接参数:--whole-archive 和 --no-whole-archive。