derelict使用時にハマったのでメモ。
間違いやD言語の作法に則っていないところなどあれば指摘してもらえると嬉しいです。
現象
derelict3を使用したコードをビルドした際、コードにpragma(lib, "dl");
を書いたのにdlopen等が無いと言われた。
dmd -ofmatrix_sample -I/home/maueki/work/Derelict3/import/ -L-L/home/maueki/work/Derelict3/lib/dmd matrix_sample.d
/home/maueki/work/Derelict3/lib/dmd/libDerelictUtil.a(loader_1_5c5.o): 関数 `_D8derelict4util6loader15SharedLibLoader6unloadMFZv' 内:
../import/derelict/util/loader.d:(.text._D8derelict4util6loader15SharedLibLoader6unloadMFZv+0x1f): `dlclose' に対する定義されていない参照です
(中略)
collect2: error: ld returned 1 exit status
--- errorlevel 1
修正
以下がリンクエラーとなった際のコードの一部。
matrix_sample.d
pragma(lib, "dl");
pragma(lib, "DerelictGL3");
pragma(lib, "DerelictGLFW3");
pragma(lib, "DerelictUtil");
pragma(lib, "DerelictIL");
pragma(lib, "dl");
を頭に書いてたのがダメだった。以下が正しいコード。
matrix_sample.d
pragma(lib, "DerelictGL3");
pragma(lib, "DerelictGLFW3");
pragma(lib, "DerelictUtil");
pragma(lib, "DerelictIL");
pragma(lib, "dl");
理由
間違ったコードをコンパイルする際、dmdをverbose(-v)で動かすと以下出力が見られる。
gcc matrix_sample.o -o matrix_sample -m64 -L/home/maueki/work/Derelict3/lib/dmd -L/usr/lib/x86_64-linux-gnu -Xlinker --export-dynamic -ldl -lDerelictGL3 -lDerelictGLFW3 -lDerelictUtil -lDerelictIL -l:libphobos2.a -lpthread -lm -lrt
gccにリンクをお願いしているわけだが、ライブラリはコードに記載した順序で並んでいる。つまり-ldl
が一番最初に書かれている。
この順序が実は重要で-ldl
が最初に来てしまうとその時点では参照されていないdlopen等のシンボルが消されてしまい、後になってDerelictUtil等から使用されているdlopen等のシンボルを探しても見つからずにエラーとなってしまう。
疑問
上記gccのオプションに-Xlinker --export-dynamic
があるけど、これはあくまで、動的シンボルテーブルに全シンボルを追加するだけで、静的解決についてはこのオプションは関係ないのだろうか。