Daniel Rodriguez
Daniel Rodriguez

Reputation: 31

MIPS GCC cross-compiler build fails: "cannot find -lc"

I am trying to set up a GCC 4.9.4 cross-compiler for a QCA955X-based router with Linux 2.6.31. This is a MIPS32R2-abi CPU that uses uClibc-0.9.30.1 (as found in /lib.) Due to this, I have decided to compile a GCC 4.x with the matching uClibc and binutils-2.19.1a. My host system is Ubuntu 18.04 with Linux 4.17-rc5 and gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)

~/mips-cross-gcc/staging_dir is my prefix, and ~/mips-cross-gcc/staging_dir/sysroot is the makeshift sysroot for my system.

1) I downloaded binutils-2.19.1a.tar.bz2, gcc-4.9.4.tar.bz2, linux-2.6.31.9.tar.xz, and uClibc-0.9.30.1.tar.bz2 into ~/mips-cross-gcc/sources.

2) I untar'd all the sources.

3) Install linux headers:

make ARCH=mips INSTALL_HDR_PATH=/home/user/mips-cross-gcc/staging_dir/sysroot/usr headers_install

4) Build binutils:

cd binutils-2.19.1
./configure --prefix=/home/user/mips-cross-gcc/staging_dir --target=mips-linux-uclibc --disable-multilib --disable-werror --enable-shared --without-newlib --with-sysroot=/home/user/mips-cross-gcc/staging_dir/sysroot --enable-languages=c,c++ --disable-libgomp

make all-binutils
make all-ld
make all-gas
make install-binutils
make install-ld
make install-gas

5) Build "stage 1" gcc, to bootstrap uClibc:

cd gcc-4.9.4
mkdir -p build/gcc-stage1
../../configure --target=mips-linux-uclibc --prefix=/home/user/mips-cross-gcc/staging_dir --disable-werror --disable-libgomp --without-newlib --disable-multilib --enable-languages=c,c++ --enable-shared --disable-__cxa_atexit --enable-target-optspace --disable-nls --disable-libmudflap  --disable-libssp --with-float=soft --with-sysroot=/home/user/mips-cross-gcc/staging_dir/sysroot --with-gnu-ld --without-headers
make all-gcc
make install-gcc

6) Install uClibc headers:

cd uClibc-0.9.30.1
make PREFIX=/home/user/mips-cross-gcc/staging_dir/sysroot install_headers

7) Build libgcc for target arch: cd gcc-4.9.4 make all-target-libgcc

Libgcc is compiled all the way until the final libgcc_s linking stage:

/home/daniel/mips-cross-gcc/staging_dir/mips-linux-uclibc/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
Makefile:937: recipe for target 'libgcc_s.so' failed

I thought that bootstrapping a GCC would not require a libc, because it has not been compiled yet, right? What could I be doing wrong? I would use this compiled GCC to build uClibc, and then I would compile GCC again with my new uClibc so that I can cross-compile software. The fact that GCC requires libc in the first build seems wrong.

I tried to use the first gcc without compiling libgcc for building uClibc, but nearly instantly I received:

LD ld-uClibc-0.9.30.1.so
mips-linux-uclibc-gcc: error: libgcc.a: No such file or directory
ldso/ldso/Makefile.in:54: recipe for target 'lib/ld-uClibc.so' failed

So, uClibc needs libgcc to link itself, and gcc needs a libc (of any type, including uClibc) to link its own libgcc. This seems like a chicken-and-egg problem. How would one fix this?

Upvotes: 1

Views: 3178

Answers (1)

Daniel Rodriguez
Daniel Rodriguez

Reputation: 31

I fixed it. Apparently, GCC has to be built without shared libraries enabled (--disable-shared) so that it doesn't link the generated libraries like libgcc dynamically (i.e to libc,) but that still didn't work. -lc was still not found.

I did some more googling, and I found this helpful message from eglibc, about making their own toolchain with gcc: eglibc.org

The First GCC

For our work, we need a cross-compiler targeting a PowerPC Linux system. However, that configuration includes the shared library 'libgcc_s.so', which is compiled against the EGLIBC headers (which we haven't installed yet) and linked against 'libc.so' (which we haven't built yet).

Fortunately, there are configuration options for GCC which tell it not to build 'libgcc_s.so'. The '--without-headers' option is supposed to take care of this, but its implementation is incomplete, so you must also configure with the '--with-newlib' option. While '--with-newlib' appears to mean "Use the Newlib C library", its effect is to tell the GCC build machinery, "Don't assume there is a C library available."

Looks like with enough digging, someone's bound to find the exact problem one has.

In short, changing --enable-shared to --disable-shared and adding --with-newlib to GCC's ./configure solved the issue and compiled + linked a libgcc_s.so that I used to compile uClibc, and then recompiled gcc with the newly generated libc, from uClibc. Indeed, it is possible to compile a 2016 GCC 4.x with a 2011 uClibc on a 2018 GCC 7.x.

Upvotes: 2

Related Questions