C mxe linking fails: ld cannot find symbols

0

trying to cross-compile TranscriberAG with MXE, I'm stuck on a problem I don't understand.

I managed to reproduce the problem on a tiny file:

#include <dlfcn.h>

int test() {
   dlopen("test", RTLD_LAZY);
}

I compile it with:

/path/to/mxe/usr/bin/i686-pc-mingw32.static-g++  -o test_dl.obj -c test_dl.cpp
/path/to/mxe/usr/bin/i686-pc-mingw32.static-ar cr test_dl.a test_dl.obj
/path/to/mxe/usr/bin/i686-pc-mingw32.static-g++  -shared -o test_dl.dll -Wl,--whole-archive test_dl.a -Wl,--no-whole-archive -ldl -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

(of course, these commands are generated by CMake, I cannot just change them simply). It fails with:

test_dl.a(test_dl.obj):test_dl.cpp:(.text+0x16): undefined reference to `_dlopen(char const*, int)'
collect2: error: ld returned 1 exit status

I have installed dlfcn in mxe. If I try a similar command with my native (Debian/Sid) compiler:

g++  -o test_dl.obj -c test_dl.cpp -fPIC
ar cr test_dl.a test_dl.obj
g++  -shared -o test_dl.dll -Wl,--whole-archive test_dl.a -Wl,--no-whole-archive -ldl

it works well...

Here is the output of objdump:

$ /home/eroux/softs/mxe/usr/i686-pc-mingw32/bin/objdump -t /home/eroux/softs/mxe/usr/i686-pc-mingw32.static/lib/libdl.a 
In archive /home/eroux/softs/mxe/usr/i686-pc-mingw32.static/lib/libdl.a:
dlfcn.o:     file format pe-i386

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 dlfcn.c
File 
[  2](sec  1)(fl 0x00)(ty  20)(scl   3) (nx 1) 0x00000000 _save_err_str
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 0) 0x00000040 _error_buffer
[  5](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 0) 0x00000000 _current_error
[  6](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000190 _dlopen
[  7](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 0) 0x00010040 _first_object
[  8](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000300 _dlclose
[  9](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x000003a0 _dlsym
[ 10](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000460 _dlerror
[ 11](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
AUX scnlen 0x470 nreloc 42 nlnno 0
[ 13](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 15](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
AUX scnlen 0x1004c nreloc 0 nlnno 0
[ 17](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata
AUX scnlen 0xb nreloc 0 nlnno 0
[ 19](sec  6)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata$zzz
AUX scnlen 0x11 nreloc 0 nlnno 0
[ 21](sec  7)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .eh_frame
AUX scnlen 0x17c nreloc 5 nlnno 0
[ 23](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _GetLastError@0
[ 24](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _FormatMessageA@28
[ 25](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _SetErrorMode@4
[ 26](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _LoadLibraryExA@12
[ 27](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _malloc
[ 28](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _GetModuleHandleA@4
[ 29](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _sprintf
[ 30](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _FreeLibrary@4
[ 31](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _free
[ 32](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _GetProcAddress@8
[ 33](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 _CloseHandle@4

I must be missing something obvious... What is it?

Edit: if I add -v to the third g++ command, I get:

Using built-in specs.
COLLECT_GCC=/home/eroux/softs/mxe/usr/bin/i686-pc-mingw32.static-g++
COLLECT_LTO_WRAPPER=/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/lto-wrapper
Target: i686-pc-mingw32.static
Configured with: /home/eroux/softs/mxe/tmp-gcc-i686-pc-mingw32.static/gcc-4.9.1/configure --target=i686-pc-mingw32.static --build=x86_64-unknown-linux-gnu --prefix=/home/eroux/softs/mxe/usr --libdir=/home/eroux/softs/mxe/usr/lib --enable-languages=c,c++,objc,fortran --enable-version-specific-runtime-libs --with-gcc --with-gnu-ld --with-gnu-as --disable-nls --disable-shared --disable-multilib --without-x [...]
Thread model: win32
gcc version 4.9.1 (GCC) 
COMPILER_PATH=/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/:/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/:/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/:/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/:/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/:/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/../../../../i686-pc-mingw32.static/bin/
LIBRARY_PATH=/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/:/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/../../../../i686-pc-mingw32.static/lib/
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'test_dl.dll' '-mtune=generic' '-march=pentiumpro'
/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/collect2 -plugin /home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/liblto_plugin.so -plugin-opt=/home/eroux/softs/mxe/usr/libexec/gcc/i686-pc-mingw32.static/4.9.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cc3LyEtG.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt --shared -Bdynamic -e _DllMainCRTStartup@12 --enable-auto-image-base -o test_dl.dll /home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/../../../../i686-pc-mingw32.static/lib/dllcrt2.o /home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/crtbegin.o -L/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1 -L/home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/../../../../i686-pc-mingw32.static/lib --whole-archive test_dl.a --no-whole-archive -ldl -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lstdc++ -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt /home/eroux/softs/mxe/usr/lib/gcc/i686-pc-mingw32.static/4.9.1/crtend.o
test_dl.a(test_dl.obj):test_dl.cpp:(.text+0x16): undefined reference to `dlopen(char const*, int)'
collect2: error: ld returned 1 exit status

Which seems to indicate that the good libdl is taken, right?

Edit: Adding LD_LIBRARY_PATH='' before the commands doesn't change anything...

c++
mingw
cross-compiling
ld
mxe
asked on Stack Overflow Aug 15, 2014 by Elie Roux • edited Aug 16, 2014 by Elie Roux

1 Answer

1

It's looks like the dlfcn.h header doesn't have function prototypes wrapped in a extern "C" block so it doesn't get compiled correctly with C++.

Make sure the dlfcn-win32 library that you're using is up to date (the extern "C" wrapper was added to dlfcn.h in January).

answered on Stack Overflow Aug 16, 2014 by Michael Burr

User contributions licensed under CC BY-SA 3.0