I want to compile the dialog program as 32-bit and statically linked executable in a 64-bit Ubuntu (16.04). This makes it easily distributable in a makeself archive without worrying about dependencies and such. I already built it 3 years ago that way and also took notes how to do it:
# get source and build-deps, then run:
./configure CFLAGS="-m32" LDFLAGS="-m32 -static"
make
Now I modified the source (added additional option) but the rebuild fails with complaints about undefined reference to Gpm_***
functions. This is unrelated to my modifications. Linking stage:
gcc -o dialog dialog.o -L. -ldialog -Wl,-rpath,/lib64 -L/lib64 -m32 -static -lncurses -ltermcap -lm
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `_nc_mouse_event':
(.text+0x632): undefined reference to `Gpm_GetEvent'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `enable_gpm_mouse':
(.text+0xcd2): undefined reference to `Gpm_Close'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `enable_gpm_mouse':
(.text+0xd22): undefined reference to `Gpm_Open'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `enable_gpm_mouse':
(.text+0xd3a): undefined reference to `Gpm_Close'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `_nc_mouse_init':
(.text+0xe8c): undefined reference to `gpm_fd'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/libncurses.a(lib_mouse.o): In function `mouse_activate':
(.text+0x1061): undefined reference to `gpm_fd'
collect2: error: ld returned 1 exit status
makefile:211: recipe for target 'dialog' failed
make: *** [dialog] Error 1
The linker picks up the libncurses.a
which seems to be ok to me as it is a static library archive. I don't understand why the Gpm_*** functions are not found. The libgpm.a
provides these and is in the same directory. Even configuring with adding /usr/lib/i386-linux-gnu/libgpm.a
to the LDFLAGS has no effect.
How can I make it link successfully?
Update:
See results with verbose linking (-Wl,--verbose
) here: https://pastebin.com/AP48KMGt
It works for me after installing gcc-multilib
(of course) and the i386 development packages for libncurses5
, libtinfo
and libgpm
:
sudo apt install gcc-multilib libncurses5-dev:i386 libtinfo-dev:i386 libgpm-dev:i386
and linking explicitly with them:
gcc -o dialog dialog.o -L. -ldialog -g -O2 -m32 -static -lncurses -ltinfo -lgpm -lm
I got./configure
to generate a working Makefile based on your example, with
$ ./configure CFLAGS="-m32" LDFLAGS="-m32 -static" LIBS="-lgpm"
$ make
...
gcc -o dialog dialog.o -L. -ldialog -m32 -Wl,-rpath,/lib64 -L/lib64 -m32 -static -lncurses -ltermcap -lm -lgpm
The result seems to be a valid i386 executable:
$ file dialog
dialog: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=4cbdb45a86cb5e6859db8c7cbeeaaa49baf45718, not stripped
Note: I tried passing --host=i686-linux-gnu
, --host=i686-pc-linux-gnu
, --host=i386-linux-gnu
or --host=i386-pc-linux-gnu
to ./configure
, but it didn't make any difference.