I'm cross / native compiling (Host: x86_64, Target: x86_64) a Linux root file system from scratch using a pre-compiled x86_64 toolchain from toolchains.bootlin.com with the below software.
binutils
- 2.31.1gcc
- 8.2.0glibc
- 2.28linux-headers
- 4.14.80
However I've come to a road block where not everything seems right...
Inside the rootfs (Compilation completes without any hiccups) using chroot
I compile this small program using gcc
:
#include <stdio.h>
#include <limits.h>
int main()
{
printf("PATH_MAX=%u\n", PATH_MAX);
return 0;
}
Which doesn't complete and outputs a error:
(chroot)$ gcc test.c -o test
test.c: In function 'main':
test.c:6:27: error: 'PATH_MAX' undeclared (first use in this function)
6 | printf("PATH_MAX=%u\n", PATH_MAX);
| ^~~~~~~~
test.c:6:27: note: each undeclared identifier is reported only once for each function it appears in
However limits.h
does exist in the chroot.
/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/include-fixed/limits.h
/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/install-tools/include/limits.h
/usr/include/limits.h
/usr/include/c++/8.2.0/tr1/limits.h
/usr/include/linux/limits.h
Additonally, below is the paths for gcc inside the chroot (This is not the toolchain):
gcc version 8.2.0 (BDK-ng)
COLLECT_GCC_OPTIONS='-v''-E''-mtune=generic''-march=x86-64'
/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/cc1 -E -quiet -v - -mtune=generic -march=x86-64
ignoring nonexistent directory "/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/../../../../x86_64-buildroot-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/include-fixed
/usr/include
End of search list.
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
COMPILER_PATH=/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-buildroot-linux-gnu/8.2.0/../../../:/lib/:/usr/lib/
I made a small software project on Github to automate the building and testing of this so I could easily share what I'm doing. It can be found here.
I suspect it's either the glibc
or gcc
steps of the build process but haven't found anything conclusive when messing around with the configuration. Below is the steps for compiling glibc and gcc.
Note: I've compiled the root filesystem in a Ubuntu VM (non-root user) and a Ubuntu based Docker container (root user), both have the same result.
Predefined variables:
SYSROOT_DIR=/opt/x86-64-core-i7--glibc--bleeding-edge-2018.11-1/x86_64-buildroot-linux-gnu/sysroot
ROOTFS_DIR=/opt/rootfs
STAGE_DIR=/opt/stage
XHOST="x86_64-cross-linux-gnu"
XTARGET="x86_64-buildroot-linux-gnu"
glibc:
cd $STAGE_DIR/glibc-2.28
mkdir build && cd build
echo "libc_cv_forced_unwind=yes"> config.cache
echo "libc_cv_c_cleanup=yes">> config.cache
echo "libc_cv_ssp=no">> config.cache
echo "libc_cv_ssp_strong=no">> config.cache
BUILD_CC="$HOSTCC" \
CC="$XTARGET-gcc" \
AR="$XTARGET-ar" \
RANLIB="$XTARGET-ranlib" \
../configure \
--prefix=/usr \
--libdir=/usr/lib \
--libexecdir=/usr/lib \
--build=$XHOST \
--host=$XTARGET \
--target=$XTARGET \
--with-pkgversion="openBDK-ng glibc" \
--without-gd \
--without-selinux \
--enable-add-ons \
--enable-bind-now \
--enable-kernel=3.2 \
--enable-lock-elision \
--enable-stack-protector=strong \
--enable-stackguard-randomization \
--disable-profile \
--disable-werror \
--enable-shared \
--cache-file=config.cache
make -j1
make install_root=$ROOTFS_DIR install
mkdir -p "$ROOTFS_DIR"/usr/bin
ln -sf ../lib/libc.so "$ROOTFS_DIR"/usr/bin/ldd
gcc:
(Note libgmp, libmpfr, and libmpc are compiled and install on both the toolchain sysroot and root filesystem directories)
cd $STAGE_DIR/gcc-8.2.0
sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in
mv ../isl-0.19 isl
mkdir build && cd build
GCC_XTARGET="x86_64-buildroot-linux-gnu"
SED=sed \
../configure \
--prefix=/usr \
--build=$XHOST \
--host=$GCC_XTARGET \
--target=$GCC_XTARGET \
--with-arch=x86-64 --with-tune=generic \
--with-linker-hash-style=gnu \
--libdir=/usr/lib \
--libexecdir=/usr/lib \
--with-pkgversion="BDK-ng" \
--with-isl \
--with-system-zlib \
--enable-__cxa_atexit \
--enable-checking=release \
--enable-clocale=generic \
--enable-default-pie \
--enable-default-ssp \
--enable-install-libiberty \
--enable-languages=c,c++,lto \
--enable-libstdcxx-time \
--enable-linker-build-id \
--enable-lto \
--enable-shared \
--enable-threads=posix \
--enable-tls \
--disable-bootstrap \
--disable-gnu-indirect-function \
--disable-libmudflap \
--disable-libsanitizer \
--disable-libssp \
--disable-libstdcxx-pch \
--disable-multilib \
--disable-nls \
--disable-symvers \
--disable-werror
make AS_FOR_TARGET="$GCC_XTARGET-as" LD_FOR_TARGET="$GCC_XTARGET-ld"
make -j1 DESTDIR="$ROOTFS_DIR" install
ln -sf ../bin/cpp "$ROOTFS_DIR"/usr/lib
install -dm755 "$ROOTFS_DIR"/usr/lib/bfd-plugins
ln -sf /usr/lib/gcc/$GCC_XTARGET/8.2.0/liblto_plugin.so "$ROOTFS_DIR"/usr/lib/bfd-plugins/
mkdir -p "$ROOTFS_DIR"/usr/share/gdb/auto-load/usr/lib
cd "$ROOTFS_DIR"/usr/bin
mv g++ g++-gcc-8.2.0
mv gcc gcc-8.2.0
ln -sf g++-gcc-8.2.0 g++
ln -sf gcc-8.2.0 gcc
ln -sf g++ c++
ln -sf gcc cc
ln -sf gcc-8.2.0 $GCC_XTARGET-gcc
ln -sf gcc-8.2.0 $GCC_XTARGET-gcc-8.2.0
ln -sf gcc-ar $GCC_XTARGET-gcc-ar
ln -sf gcc-nm $GCC_XTARGET-gcc-nm
ln -sf gcc-ranlib $GCC_XTARGET-gcc-ranlib
ln -sf g++-gcc-8.2.0 $GCC_XTARGET-c++
ln -sf g++-gcc-8.2.0 $GCC_XTARGET-g++
So with that being said, what part of my configuration is wrong? I'm certain that the toolchain is not at fault since I've tested that and a similar toolchain built by crosstool-ng
(Bootlins toolchains are built using the buildroot
build system) which have the same result as state above.