Cannot find -lgcc when building 32bit program with -m32 on an 64bit machine ( gcc, docker )

Viewed 443

I would like to build a simple hello world C program for linux in 32 bit. I tried to do it with docker ( because the OS on my machine is not Linux )

This is the Dockerfile:

FROM gcc:4.9
RUN dpkg --add-architecture i386
RUN apt-get update && apt-get install -y libc6-dbg libc6-dbg:i386 gcc-multilib libc-dev:i386 gcc-4.9-base:i386

I build it like this:

docker build -t my-gcc .

Then I try to use it like this:

docker run --rm -v ${pwd}:/usr/src/myapp -w /usr/src/myapp my-gcc gcc -m32 -o hello hello.c

I get this error:

/usr/bin/ld: skipping incompatible /usr/local/lib/gcc/x86_64-linux-gnu/4.9.4/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status

What do I wrong? How is it possible to fix it? I've found similar questions, but they suggest gcc-multilib, which I already installed.


The host machine is Windows 10 x64, with WSL2. But as far as I know, this should not matter. I would like to build x86 32bit linux binaries with gcc.

2 Answers

The following Dockerfile fixes the issue:

FROM gcc:4.9

RUN apt-get update \
 && apt-get install --assume-yes --no-install-recommends --quiet \
        libc6-dev-i386 \
        gcc-multilib \
 && apt-get clean all

ENTRYPOINT ["/usr/bin/gcc-4.9", "-m32"]

Test:

$ docker run --rm -v .:/usr/local/src/:rw my-gcc /usr/local/src/hello.c -o /usr/local/src/hello
$ file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=32f247e8f3406cde7902af8baf469907b42ed969, not stripped

The docker image provides two gcc compilers:

$ docker run --rm -it --entrypoint=bash my-gcc
root@efe1bcf6c715:/# which gcc
/usr/local/bin/gcc
root@efe1bcf6c715:/# which gcc-4.9
/usr/bin/gcc-4.9

If the gcc compiler is used we get several linker errors:

$ podman run --rm -v .:/usr/local/src/:rw --entrypoint="gcc" my-gcc:latest -m32 /usr/local/src/hello.c -o /usr/local/src/hello 
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/local/lib/gcc/x86_64-linux-gnu/4.9.4/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status

Forcing the gcc-4.9 one, fixes the problem.

I got 32bit compilation to work with gcc 10 (on debian) using this dockerfile:

FROM debian:bullseye

RUN apt-get update \
 && apt-get install --assume-yes --no-install-recommends --quiet \
         build-essential \
         gcc-multilib \
         g++-multilib \
         autoconf \
         automake \
         libtool

I also needed various autotools as you can see.

If you need to use configure to setup a tool (cpputest in my case) in 32bit mode then you can use args like this:

RUN ./configure \
      CFLAGS=-m32 \
      CXXFLAGS=-m32 \
      LDFLAGS=-m32 \
      --build=x86_64-pc-linux-gnu \
      --host=i686-pc-linux-gnu

And then when you compile inside the container as in your question, with gcc and the correct -m32 flag, it all works nicely without errors:

gcc -m32 -O2 main.c -o main.o
Related