Crti.o not found when building custom GCC

Hi all,

I have been using Nix/NixOS for a while and would like to gain a deeper understanding of how Nix handles compilers and (eventually) the bootstrap process. I figured building a custom toolchain would be a good place to start. I have been referencing the nixpkgs gcc derivation and the documentation for stdenv. Here is what I have so far:

{
    flex,
    gcc12,
    gmp,
    isl,
    lib,
    libmpc,
    mpfr,
    stdenvNoCC,
    stdenv,
}:

let
    gcc = gcc12;

in stdenvNoCC.mkDerivation {
    pname = "custom-gcc";
    version = "12.3";

    src = builtins.fetchTarball {
        url = "https://ftp.gnu.org/gnu/gcc/gcc-12.3.0/gcc-12.3.0.tar.xz";
        sha256 = "1y705cw28pfx51h7bqqh8zqbiwi1swvmrrmjhxds9s13fc4xq5as";
    };

    nativeBuildInputs = [
        gcc
    ];

    buildInputs = [
        flex
        gmp
        isl
        libmpc
        mpfr
    ];

    preConfigure = ''
        mkdir -p ../build
        cd ../build

        export configureScript=../$sourceRoot/configure
    '';

    enableParallelBuilding = true;
    hardeningDisable = [ "all" ];

    # TODO: dynamic linking
    dontDisableStatic = true;

    configureFlags = [
        # TODO: enable multilib
        "--disable-multilib"

        "--with-gmp-include=${gmp.dev}/include"
        "--with-gmp-lib=${gmp.out}/lib"
        "--with-mpfr-include=${mpfr.dev}/include"
        "--with-mpfr-lib=${mpfr.out}/lib"
        "--with-mpc=${libmpc}"
        "--with-native-system-header-dir=${lib.getDev stdenv.cc.libc}/include"
    ];
}

Unfortunately, it fails in the buildPhase with the following error:

. . .
       > /nix/store/7v7g86ml0ri171gfcrs1d442px5bi1p3-binutils-2.41/bin/ld: cannot find crti.o: No such file or directory
       > collect2: error: ld returned 1 exit status
       > make[3]: *** [Makefile:995: libgcc_s.so] Error 1
       > make[3]: Leaving directory '/build/build/x86_64-pc-linux-gnu/libgcc'
       > make[2]: *** [Makefile:21112: all-stage1-target-libgcc] Error 2
       > make[2]: Leaving directory '/build/build'
       > make[1]: *** [Makefile:26855: stage1-bubble] Error 2
       > make[1]: Leaving directory '/build/build'
       > make: *** [Makefile:1072: all] Error 2
. . .

I tried debugging the derivation with nix develop and NIX_DEBUG=2 and discovered that glibc is in the linker flags (see below) which I believe has the crti.o file.

. . .
extra flags before to /nix/store/7v7g86ml0ri171gfcrs1d442px5bi1p3-binutils-2.41/bin/ld:
  -dynamic-linker
  /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/ld-linux-x86-64.so.2
original flags to /nix/store/7v7g86ml0ri171gfcrs1d442px5bi1p3-binutils-2.41/bin/ld:
. . .
  -L/nix/store/3pmh3p3p02k5959jc7w46vjpmmafd7c6-flex-2.6.4/lib
  -L/nix/store/idz4bvv01z76llr3cn711l0lv5i6h0j5-gmp-with-cxx-6.3.0/lib
  -L/nix/store/qvw3i9qlb0rhbxdm6ibh43y92xpa0z26-isl-0.20/lib
  -L/nix/store/knil2y36slvqvwjs5cm3bi85in561v61-libmpc-1.3.1/lib
  -L/nix/store/v1kj72lpw6a72vvx27z1k6vsrqsfbdla-mpfr-4.2.1/lib
  -L/nix/store/3pmh3p3p02k5959jc7w46vjpmmafd7c6-flex-2.6.4/lib
  -L/nix/store/idz4bvv01z76llr3cn711l0lv5i6h0j5-gmp-with-cxx-6.3.0/lib
  -L/nix/store/qvw3i9qlb0rhbxdm6ibh43y92xpa0z26-isl-0.20/lib
  -L/nix/store/knil2y36slvqvwjs5cm3bi85in561v61-libmpc-1.3.1/lib
  -L/nix/store/v1kj72lpw6a72vvx27z1k6vsrqsfbdla-mpfr-4.2.1/lib
  -L/nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib
  -rpath
  /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib
/nix/store/7v7g86ml0ri171gfcrs1d442px5bi1p3-binutils-2.41/bin/ld: cannot find crti.o: No such file or directory
collect2: error: ld returned 1 exit status
. . .

I feel that I may not be understanding everything that needs to be done to make this work with Nix. All of the resources I have been able to find deal with building GCC in an FHS environment (e.g., this post) which is not what I’m hoping to accomplish.

As a side note, this is my first “complex” Nix derivation. As I mentioned, I’m hoping to learn more about how Nix works, and maybe document some things along the way. Any resources/comments (even those tangentially related to my current issue) are greatly appreciated.

Thanks!

Honestly it might not be. GCC and stdenv are really complicated in nixpkgs. It might be better to start by trying to mess around with how those derivations work in nixpkgs.

I had considered doing this, and it is probably a good idea. The issue is I’m not really sure how to play with these derivations in isolation. From what I can see, they seem to be quite spread out, touching many files. I initially tried to trace the relevant sections by hand, but eventually got lost in the lazy evaluation and intermediate functions. As you have said, the derivations are very complex, so simply reading them doesn’t help me understand what each part does and how it is used (which is why I landed on trying to build it from scratch myself). I would like something I can edit that is on a smaller scale than nixpkgs.

Do you have any recommendations for setting up a “playground” for this? For example, is it possible to trace all the *.nix files that are touched when evaluating the gcc derivation? Debugging Nix derivations has been something I have struggled with since I first got started, so any advice you may have is appreciated.

Write a script that replaces each .nix file with a wrapper .nix file that traces when it is evaluated.