Mam problem z wygenerowaniem konfiguracji kompilacji, która umożliwia budowanie bibliotek współdzielonych w systemach Linux i Windows przy użyciu odpowiednio gcc i MinGW. W systemie Linux wspólna biblioteka nie musi rozwiązywać wszystkich zależności podczas kompilacji; wydaje się, że tak jest w przypadku Windows. Oto konfiguracja Problem:Tworzenie wspólnej biblioteki za pomocą gcc w systemach Linux i MinGW w systemie 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
Teraz w Linuksie, to kompiluje i działa dobrze:
$ 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!
W Windows, musimy zmienić tak, aby dll, które jest niewielkie i dobrze:
$ 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
Jednak, gdy próbujemy budować, pojawia się następujący błąd:
$ 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
Teraz możemy naprawić ten błąd, po prostu w tym obiekty z foo.o do 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!
Ja jednak nie podoba to podejście od libbar.dll teraz zawiera symbole zarówno dla foo jak i baru. W Linuksie zawiera tylko symbole paska. Ten rozdział jest ważny w sytuacjach, w których biblioteka zależy od pewnej standardowej biblioteki numerycznej, takiej jak BLAS. Chciałbym móc wdrożyć współdzieloną bibliotekę i uzależnić ją od zoptymalizowanej wersji biblioteki numerycznej na komputerze użytkownika, a nie mojej własnej.
W każdym razie, jaka jest właściwa procedura tworzenia wspólnej biblioteki, w której nie wszystkie symbole są obecne podczas kompilacji?
Jeśli jest to ważne, skompilowałem te przykłady z gcc 4.6.3 na Linux i mingw-get-inst-20120426.exe z gcc 4.7.2 na Windows.
Brakuje wymaganych '__declspec (dllimport)' i '__declspec (dllexport)' zarówno w 'foo.h', jak i' bar.h'. Coś jak: '#if defined __ELF__ #define API __attribute ((widoczność ("Default"))) #elif określonym EXPORT #define API __declspec (dllexport) #else #define API __declspec (dllimport) #endif ' Następnie' #define EXPORT' w 'foo.c' i' bar.c'. – bit2shift
Coś jak [this] (https://github.com/bit2shift/r3dVoxel/blob/master/inc/r3dVoxel/r3vABI.hpp#L7-L13), ale bez 'extern" C "', który jest konstrukcją C++. – bit2shift