Building gcc with glibc together in 10 easy steps
With https://github.com/spack/spack/pull/40013 it should be possible to build new gcc with old glibc.
Here are my current notes. This assumes you have an empty directory $work
.
-
Create an environment in
$work
with the relevant GCC and glibcspack: specs: - glibc@2.5 - gcc@13 view: view concretizer: unify: true
-
Install all dependencies, but not gcc and glibc -- they're built together by hand
-
Run
spack -e . patch gcc glibc
to download, stage and patch -
Move the sources
$ mv `spack -e . location gcc` gcc-src $ mv `spack -e . location glibc` glibc-src
-
Install the glibc headers:
$ export linux_headers="$(spack -e . location -i linux-headers)/include" $ spack -e . build-env glibc -- bash $ mkdir glibc-hdrs && cd glibc-hdrs $ CXX=/nonsense ../glibc-src/configure \ --prefix=$work/glibc-install \ --with-headers=$linux_headers \ --enable-kernel=6.2.0 $ make install-headers cross-compiling=yes -j $(nproc) $ exit # the build env shell
So here we configure glibc with the "wrong" compiler, but it's all we have. The
cross-compiling=yes
is necessary for older glibc that ships sunrpc; without it it attempts to compile/link smth, which fails. -
Manually create dummy versions of missing headers (not all bootstrap headers are included in install):
$ touch $work/glibc-install/include/gnu/stubs.h $ touch $work/glibc-install/include/bits/stdio_lim.h $ touch $work/glibc-install/include/bits/syscall.h
TODO: are these all?
-
Then configure GCC once and only once
TODO: should set
LD_FOR_TARGET
and friends, otherwise GCC stores the compiler wrapper, and it gets used when building glibc, which is problematic cause we can't have an rpath for ld.so.$ spack -e . build-env gcc -- bash $ mkdir gcc-obj && cd gcc-obj $ LDFLAGS_FOR_TARGET="-L$work/glibc-install/lib -Wl,-rpath,$work/glibc-install/lib,-dynamic-linker,$work/glibc-install/lib/ld-linux-x86-64.so.2" CFLAGS_FOR_TARGET="-isystem $linux_headers" CXXFLAGS_FOR_TARGET="-isystem $linux_headers" ../gcc-src/configure \ --prefix=$work/gcc-install \ --disable-bootstrap \ --enable-languages=c,c++ \ --disable-multilib \ --with-native-system-header-dir=$work/glibc-install/include \ --with-gmp=$work/view
Note: since we have glibc and linux headers in separate packages, we need that extra
-isystem
flag. For some reason, GCC does not save the flagCPPFLAGS_FOR_TARGET
, only[C|CXX]FLAGS_FOR_TARGET
, so we use that. -
First build
libgcc.a
only. Since we haven't configured gcc with --disable-shared, we need to overrideenable_shared=no
, otherwiselibgcc_eh.a
andlibgcc_s.so
build too:$ make all-target-libgcc enable_shared=no -j $(nproc) $ exit # the build env
-
The
glibc
we're using is patched on older version so it doesn't needlibgcc_eh.a
/libgcc_s.so
, so now we should be able to configure it with just-builtxgcc
.Some configure tests need to be disabled because they require executables to be created or run (but
xgcc
cannot yet)A bunch of
CFLAGS
are needed for older versions, but Spack's build env should already do thatOverride
CXX
to garbage since we don't have a g++ compiler, and if glibc detects a system g++, it will start building tests (which fails to link). Also, we should avoid hitting Spack's linker wrapper here, so remove the wrapper dir fromPATH
(!). If not, you'll end up with ld.so built with rpaths, which causes startup errors of the dynamic linker. I also had to modify the wrappers in$work/gcc-obj/gcc/collect-ld
etc that still referenced the spack linker wrapper, and replace it with /usr/bin/ld.$ spack -e . build-env glibc -- bash $ mkdir glibc-obj && cd glibc-obj $ export CC="$work/gcc-obj/gcc/xgcc -B $work/gcc-obj/gcc/" CXX=/no/no/no $ ../glibc-src/configure \ --with-headers=$linux_headers \ --prefix=$work/glibc-install \ --enable-kernel=6.2.0 \ libc_cv_forced_unwind=yes \ libc_cv_c_cleanup=yes \ ac_cv_sizeof_long_double=8 $ make -j $(nproc) $ make install $ exit
-
Return to GCC and install the rest, now with
TFLAGS
so glibc crt*.o files are picked up for building shared libs (the other flags were already set when we configured gcc):
$ spack -e . build-env gcc -- bash
$ cd gcc-obj
$ make TFLAGS="-B$work/glibc-install/lib" -j $(nproc)
$ make install
$ exit
Now you should have GCC in $work/gcc-install
with runtime libs linked against glibc in $work/glibc-install
.
Caveat: Old glibc ldd
gets the lib
dir wrong (on ubuntu at least): it has lib64/ld.so
, but it lives in in lib/
.
To use the compiler, a spec file is useful to deal with all custom locations; I've adapted it from gcc -dumpspecs
; some rules can be extended, but startfile
and endfile
cannot easily. My glibc.spec
looks as follows (with $work and $linux_headers the actual absolute paths) and can be used with gcc -specs=glibc.spec ...
:
*cpp:
+ -isystem $linux_headers
*link_libgcc:
+ -rpath $work/gcc-install/lib64/
*link:
+ -dynamic-linker $work/glibc-install/lib/ld-2.5.so -L $work/glibc-install/lib/ -rpath $work/glibc-install/lib/
*endfile:
%{!mandroid|tno-android-ld:%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!shared:%{!mno-daz-ftz:crtfastmath.o%s}}} %{mpc32:crtprec32.o%s} %{mpc64:crtprec64.o%s} %{mpc80:crtprec80.o%s} %{!static:%{fvtable-verify=none:%s; fvtable-verify=preinit:vtv_end_preinit.o%s; fvtable-verify=std:vtv_end.o%s}} %{static:crtend.o%s; shared|static-pie|pie:crtendS.o%s; :crtend.o%s} $work/glibc-install/lib/crtn.o%s ;:%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!shared:%{!mno-daz-ftz:crtfastmath.o%s}}} %{mpc32:crtprec32.o%s} %{mpc64:crtprec64.o%s} %{mpc80:crtprec80.o%s} %{shared: crtend_so%O%s;: crtend_android%O%s}}
*startfile:
%{!mandroid|tno-android-ld:%{shared:; pg|p|profile:%{static-pie:grcrt1.o%s;:$work/glibc-install/lib/gcrt1.o%s}; static:$work/glibc-install/lib/crt1.o%s; static-pie:rcrt1.o%s; pie:$work/glibc-install/lib/Scrt1.o%s; :$work/glibc-install/lib/crt1.o%s} $work/glibc-install/lib/crti.o%s %{static:crtbeginT.o%s; shared|static-pie|pie:crtbeginS.o%s; :crtbegin.o%s} %{fvtable-verify=none:%s; fvtable-verify=preinit:vtv_start_preinit.o%s; fvtable-verify=std:vtv_start.o%s} ;:%{shared: crtbegin_so%O%s;: %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}}