2019-06-06に更新

POCO を static に link する

結論

-Wl,--start-group -Wl,-Bstatic -lPocoFoundation -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -Wl,--end-group -Wl,-Bdynamic -lpthread

今世のリンカオプションには --start-group, --end-group なんて便利なものがあるんですね

はじめに

Cerflet ベースの WebApplication を deploy しようとして、POCO に依存してしまうのもアレだなと思い、だったら static に link してしまおうと思ったのが事の発端です

POCO の static library を make

POCO の configure の --static オプションを使って make します

./configure --static
make

はじめは shared library 作る時と同じで make -j4 ってやってたんですけどリンクエラーがでるので、多分、static に link してるから順番とかが影響してるんだろうなと深く考えずに make にしたらでなくなりました
こんな些細なところからすでにlink する時の嫌な事が始まってます ^^;;;

しっかりハマる

マジメな C++ プログラマだった頃の辛い思い出が蘇ってきます...

pthread がない

dynamic に link した時と同じ感覚で素朴に lPocoFoundation をリンクしようとしたのですが

g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/  -L/usr/local/lib -lPocoFoundation -static

Thread.cpp:(.text+0x1ec): undefined reference to `pthread_setspecific'
Thread.cpp:(.text+0x228): undefined reference to `pthread_sigmask'
Thread.cpp:(.text+0x30c): undefined reference to `pthread_mutex_lock'
Thread.cpp:(.text+0x328): undefined reference to `pthread_cond_broadcast'
Thread.cpp:(.text+0x338): undefined reference to `pthread_mutex_unlock'
...

-lpthread つけてやらないといけないんですね

Poco 自身の依存関係

で、-lpthread つけてあげたんですが

g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/  -L/usr/local/lib -lPocoFoundation -static -lpthread

httpcerflet.cpp:(.text+0x54): undefined reference to `Poco::Util::Application::loadConfiguration(int)'
httpcerflet.cpp:(.text+0x64): undefined reference to `Poco::Util::Application::initialize(Poco::Util::Application&)'
/tmp/ccZExLN3.o: In function `HttpCerflet::uninitialize()':
httpcerflet.cpp:(.text+0x8c): undefined reference to `Poco::Util::Application::uninitialize()'
...

あ、static link だから lPocoFoundation が依存する Poco のライブラリも先にリンクしておいてあげないと...

で、undefined だって言われる Poco のライブラリをどんどん前に追加しているのに、まだ undefined が...

g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/  -L/usr/local/lib -lPocoXML -lPocoJSON -lPocoUtil -lPocoNet -lPocoFoundation -static -lpthread

...
JSONConfiguration.cpp:(.text+0x6a0): undefined reference to `Poco::JSON::Query::~Query()'
...
XMLConfiguration.cpp:(.text+0x1cc): undefined reference to `Poco::XML::Document::documentElement() const'

ちゃんと -lPocoXML も -lPocoJSON も link してるのになんで undefined なんて言われるんだろ?
このあたりでもう考えるのが嫌になって POCO static link とかでググるとそのものズバリなのが
定義されていないシンボルへのPoco C++ 静的リンクの問題

そうだ、リンクの順番!使われる前にリンクしておかないといけないんでした

glibc の静的リンク

POCO内部の依存関係に合わせて正しい順番でリンクすると

g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/  -L/usr/local/lib -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -lPocoFoundation -static -lpthread

/usr/local/lib/libPocoFoundation.a(Path.o): In function `Poco::PathImpl::homeImpl[abi:cxx11]()':
Path.cpp:(.text+0x220): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

glibc まで static にリンクしようとしてました ^^;;;

第一次正解

なので、pthread だけは dynamic に link するようにして

g++ -o hellocerflet_s HelloCerflet.cpp ../lib/httpcerflet.cpp -I../lib/  -L/usr/local/lib -Wl,-Bstatic -lPocoUtil -Wl,-Bstatic -lPocoXML -Wl,-Bstatic -lPocoJSON -Wl,-Bstatic -lPocoNet -Wl,-Bstatic -lPocoFoundation -Wl,-Bdynamic -lpthread

やっとできました

ちょっと考察

しかし今どきリンクの順番みたいな機械的に解決できることに人間が頭を使わないといけないのってちょっと残念ですよね、人って機械的な作業が苦手なクリエイティブなクリーチャーなのに

でも、さすがになにか進歩してるんじゃないかとおもって static link order とかでググりまくってると Why does the order in which libraries are linked sometimes cause errors in GCC?
やっぱり人類は賢かった!--start-group, --end-group なんてリンカのオプションをつくってくれた人がいて、この中だと順番気にしなくてもリンカがよしなにやってくれるんですね!

で、本稿の結論にいたります

再度、結論

-Wl,--start-group -Wl,-Bstatic -lPocoFoundation -lPocoUtil -lPocoXML -lPocoJSON -lPocoNet -Wl,--end-group -Wl,-Bdynamic -lpthread

感想

まるで紅茶に浸した一匙のマドレーヌを口に含んだ時みたいに鮮明に記憶が戻ってきました
私は gcc のこういう所があんまり好きじゃなかったんでした

ツイッターでシェア
みんなに共有、忘れないようにメモ

Dr. Takeyuki Ueda

Je suis un Japonipais, experimants ingénieur logiciel de mobile et cloud. Ph.D en ingénierie.

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント