
假設有如三個源代碼檔案:
$ 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
x.o: x.cpp
clean:
rm -f a.o b.o x.o x
使用上面的Makefile編譯,将會遇到如下所示的“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: 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。