Reputation: 31
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
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