gcc と MinGW をそれぞれ使用して Linux と Windows の両方で共有ライブラリをビルドできるようにするビルド セットアップの生成に問題があります。Linux では、共有ライブラリはコンパイル時にすべての依存関係を解決する必要はありません。一方、これは Windows の場合に当てはまります。問題の設定は次のとおりです。
$ cat foo.h
#ifndef FOO_H
#define FOO_H
void printme();
#endif
$ cat foo.c
#include "foo.h"
#include <stdio.h>
void printme() {
printf("Hello World!\n");
}
$ cat bar.h
#ifndef BAR_H
#define BAR_H
void printme2();
#endif
$ cat bar.c
#include "bar.h"
#include "foo.h"
void printme2() {
printme();
printme();
}
$ cat main.c
#include "bar.h"
int main(){
printme2();
}
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.so
gcc -shared bar.o -o libbar.so
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
さて、Linux では、これは問題なくコンパイルされ、実行されます。
$ make
gcc -fPIC -c foo.c
gcc -fPIC -c bar.c
gcc -fPIC -c main.c
gcc -shared foo.o -o libfoo.so
gcc -shared bar.o -o libbar.so
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ ./main
Hello World!
Hello World!
Windows では、マイナーで問題ない dll に変更する必要があります。
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
ただし、ビルドしようとすると、次のエラーが発生します。
$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o -o libbar.dll
bar.o:bar.c:(.text+0x7): undefined reference to `printme'
bar.o:bar.c:(.text+0xc): undefined reference to `printme'
collect2.exe: error: ld returned 1 exit status
make: *** [all] Error 1
これで、foo.o のオブジェクトを libbar.dll に含めるだけでエラーを修正できます。
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o foo.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o foo.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ ./main
Hello World!
Hello World!
ただし、libbar.dll には foo と bar の両方のシンボルが含まれているため、このアプローチは好きではありません。Linux では、バーの記号のみが含まれます。この分離は、ライブラリが BLAS などの標準的な数値ライブラリに依存している場合に重要です。共有ライブラリを展開して、自分のマシンではなく、ユーザーのマシン上の数値ライブラリの最適化されたバージョンに依存できるようにしたいと考えています。
いずれにせよ、コンパイル時にすべてのシンボルが存在しない共有ライブラリを作成する適切な手順は何ですか?
念のため、Linux では gcc 4.6.3 を使用してこれらの例をコンパイルし、Windows では gcc 4.7.2 を使用して mingw-get-inst-20120426.exe をコンパイルしました。