Tengo problemas para generar una configuración de compilación que permita compilar bibliotecas compartidas tanto en Linux como en Windows usando gcc y MinGW, respectivamente. En Linux, una biblioteca compartida no tiene que resolver todas las dependencias en tiempo de compilación; mientras que, esto parece ser el caso en Windows. Aquí está la configuración del problema:
$ 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
Ahora, en Linux, esto compila y funciona bien:
$ 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!
En Windows, necesitamos cambiarlo a dll, que es menor y está bien:
$ 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
Sin embargo, cuando intentamos compilar, obtenemos el siguiente error:
$ 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
Ahora, podemos corregir el error simplemente incluyendo los objetos de foo.o en 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!
Sin embargo, no me gusta este enfoque ya que libbar.dll ahora contiene símbolos tanto para foo como para bar. En Linux, solo contiene símbolos para barra. Esta separación es importante para situaciones en las que una biblioteca depende de alguna biblioteca numérica estándar como BLAS. Me gustaría poder implementar la biblioteca compartida y hacer que dependa de la versión optimizada de la biblioteca numérica en la máquina del usuario y no en la mía.
En cualquier caso, ¿cuál es el procedimiento adecuado para crear una biblioteca compartida en la que no todos los símbolos estén presentes en el momento de la compilación?
En caso de que importe, compilé estos ejemplos con gcc 4.6.3 en Linux y mingw-get-inst-20120426.exe con gcc 4.7.2 en Windows.
Te falta lo requerido
__declspec(dllimport)
y__declspec(dllexport)
en ambosfoo.h
ybar.h
. Algo como:#if defined __ELF__ #define API __attribute((visibility("default"))) #elif defined EXPORT #define API __declspec(dllexport) #else #define API __declspec(dllimport) #endif
Luego#define EXPORT
enfoo.c
ybar.c
.– bit2shift
13 de septiembre de 2017 a las 2:58
Algo como esta pero sin
extern "C"
que es una construcción de C++.– bit2shift
13 de septiembre de 2017 a las 3:01