Search code examples
linuxgccundefined-reference

How to satisfy dependencies for static compilation of 'dialog' tool for 32-bit


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


Solution

  • 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.