静的ライブラリのリンク時にundefined referenceエラーが出る(gcc)

概要

gccでリンク時にundefined referenceエラーが出る場合がある。 通常はオブジェクトやライブラリの指定忘れが原因であるが、 静的ライブラリをリンクする順番に間違いがあって出る場合もある (自分でMakefileを書く場合にこのミスをすることが多い)

リンクの順番には依存性があり、あるオブジェクトが静的 ライブラリ内の関数を呼び出すときには呼び出される側の ライブラリは「後で」リンクする必要がある。

例えば foo.o が静的ライブラリ libfoo.a 内の関数を使用している、つまり

foo.o → libfoo.a
という依存関係があるとき、
g++ -o foo libfoo.a foo.o
とするとundefined referenceエラーが出る。従って
g++ -o foo foo.o libfoo.a
と先にfoo.oを書かなくてはいけない。

ソース

libtest.h

class LibTest
{
  public:
    void func();
};

libtest.cpp

#include "libtest.h"
#include <iostream>

void LibTest::func()
{
    std::cout << "ok\n";
}

main.cpp

#include "libtest.h"

int main()
{
    LibTest libtest;
    libtest.func();
    return 0;
}

コンパイル

次のようなMakefileを書く。ここでOBJSの順番に気を付けること (わざとリンクエラーが出るようにしてある)

Makefile

OBJS = libtest.a main.o

linktest : $(OBJS)
	g++ -o linktest $(OBJS)

libtest.a : libtest.o
	ar r $@ $<
	ranlib $@

.cpp.o : 
	g++ -c $< -g -O2 

all : linktest

clean:
	rm -rf *.o *.a linktest

結果

$ make
g++ -c libtest.cpp -g -O2
ar r libtest.a libtest.o
ar: libtest.a を作成します
ranlib libtest.a
g++ -c main.cpp -g -O2
g++ -o linktest libtest.a main.o
main.o(.text+0x11): In function `main':
/home/tokai/src/linktest/main.cpp:6: undefined reference to `LibTest::func()'
collect2: ld はステータス 1 で終了しました
このようにリンクエラーが出る。ここでOBJSの順番を
OBJS = main.o libtest.a
と変更すると正常にリンクされる。
$ make
g++ -c main.cpp -g -O2
g++ -c libtest.cpp -g -O2
ar r libtest.a libtest.o
ar: libtest.a を作成します
ranlib libtest.a
g++ -o linktest main.o libtest.a
$ ./linktest
ok