How to select a specific version of gcc within a flake.nix

I’m attempting to set a specific version of gcc (gcc 10.x) from with in a flake, but not having much luck.

I’ve tried a number of different things, and I can see the package get loaded ‘pkgs.gcc8’ – loads gcc8 package, ‘pkgs.gcc10’ – loads gcc10 package and so on, however, executing ‘gcc --version’ at the command-line always produces (11.3.0):

gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Here’s my current flake.nix

{

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils}:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          config = { allowUnfree = true; };
        };
      in {
        devShell = pkgs.mkShell {
          buildInputs = with pkgs;[
                pkgs.gcc10Stdenv.all
                pkgs.cmake
                pkgs.cmakeWithGui
                pkgs.libv4l
                pkgs.ocl-icd
                pkgs.freeglut
                pkgs.libgeotiff
                pkgs.libusb1
                pkgs.libdc1394
                pkgs.gtk3
                pkgs.cudaPackages_11_2.cudatoolkit          ];
        };
      }
    );
}

Suggestions?

The only package in pkgs.gcc10Stdenv.all contains:

/nix/store/a8qgz7v276wr6fyd8i7b0kd2xkh3gm3c-stdenv-linux
├── nix-support
└── setup

setup is the basic build script that most nixpkgs packages use to build. Even it won’t be available in $PATH in your shell because it’s not in the bin/ subdirectory. I’m not sure if a nested list will actually work with buildInputs, either. I find it surprising this evaluates.

Any particular reason you’re not using pkgs.gcc10? If you literally want every package that is available in the normal nix stdenv, you could do something like this:

# Note, I can't help myself, I cleaned this up a bit
devShell = pkgs.mkShell {
  # Typically you want `packages` for `mkShell`, unless I guess
  # you want to do cross compilation by hand? Does that even
  # work with `mkShell`?
  packages = with pkgs;[
    cmake
    cmakeWithGui
    libv4l
    ocl-icd
    freeglut
    libgeotiff
    libusb1
    libdc1394
    gtk3
    cudaPackages_11_2.cudatoolkit
  ]
  ++ gcc10Stdenv.defaultBuildInputs
  ++ gcc10Stdenv.defaultNativeBuildInputs;
};

But there’s basically only patchelf, gcc10 and a lot of very specific
scripts in there:

defaultNativeBuildInputs="/nix/store/n845kl3915ri14zlkqq7wf3n3xabmgal-patchelf-0.14.5
/nix/store/59jmzisg8fkm9c125fw384dqq1np602l-move-docs.sh
/nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh
/nix/store/m54bmrhj6fqz8nds5zcj97w9s9bckc9v-compress-man-pages.sh
/nix/store/bkxq1nfi6grmww5756ynr1aph7w04lkk-strip.sh
/nix/store/bnj8d7mvbkg3vdb07yz74yhl3g107qq5-patch-shebangs.sh
/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh
/nix/store/8zxndz5ag0p6s526c2xyllhk1nrn4c3i-audit-tmpdir.sh
/nix/store/c8n9kcdddp9np665xz6ri61b383nxvz8-move-systemd-user-units.sh
/nix/store/1i5y55x4b4m9qkx5dqbmr1r6bvrqbanw-multiple-outputs.sh
/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh
/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh
/nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh
/nix/store/wlwcf1nw2b21m4gghj70hbg1v7x53ld8-reproducible-builds.sh
/nix/store/3gjdfspym60d8k3ic9dg5dr9r4w0yihy-gcc-wrapper-10.3.0"

I suppose there’s also a reference to glibc in the variables, so maybe
you want:

devShell = pkgs.mkShell {
  packages = with pkgs;[
    gcc10
    gcc10Stdenv.glibc

    cmake
    cmakeWithGui
    libv4l
    ocl-icd
    freeglut
    libgeotiff
    libusb1
    libdc1394
    gtk3
    cudaPackages_11_2.cudatoolkit
  ];
};

But I think NixOS only packages one glibc for any specific version
anyway?

I did try ‘pkgs.gcc10’ — and I can see that it gets installed — however , when you check the version on the command-line ‘gcc -version’; it always shows ‘11.3’.

I was digging around more after my cry for help :wink: — and I came across this on the NixOS C Wiki (https://nixos.wiki/wiki/C) — but not sure how to apply it within a flake.

Use a different compiler version

Adding a different c compiler to buildInputs in a nix expression will not change the default compiler available in $PATH. Instead, nixpkgs provides a several alternative stdenv which you can search with nix search stdenv so for example:

gcc8Stdenv.mkDerivation {
  name = "env";
}

$ nix-shell --command 'gcc --version'
gcc (GCC) 8.3.0

  • Available gcc based stdenv variants: gcc{49,6-12}Stdenv, gccMultiStdenv (32bit/64bit mixed support)
  • Available clang based stdenv variants: llvmPackages_[5-13].{stdenv,libcxxStdenv}, clangMultiStdenv (32bit/64bit mixed support)

Those stdenv instances can be also constructed using the overrideCC function: Here we are creating a shell environment that will always have the latest available gcc:

(overrideCC stdenv gcc_latest).mkDerivation {
  name = "env";
}

Note that this will only affect compiler and not the used linker. To overwrite the linker and maybe also the used libc Check out the wrapCCWith example in the next section.

It works fine for me:

tlater ~/Scratch $ cat flake.nix
{
  description = "Scratch dir for various testing";

  outputs = {nixpkgs, ...}: let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};
  in {
    devShells.${system}.default = pkgs.mkShell {
      packages = with pkgs; [
        gcc10
      ];
    };
  };
}
tlater ~/Scratch $ nix develop

[tlater@ct-lt-02052:~/Scratch]$ gcc --version
gcc (GCC) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[tlater@ct-lt-02052:~/Scratch]$
exit
tlater ~/Scratch $ gcc --version
gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


What nix version are you using? Any shell extensions? Are you using bash and it’s loading some kind of custom .bashrc? What if you use --ignore-environment?

The prefered and most reliable way to change the C-compiler chain in a mkShell is to override the stdenv.

(mkShell.override { stdenv = gcc10Stdenv; }) {
  …
}
2 Likes

I applied your example as-is and it worked like a champ. Not entirely sure what I was doing differently as “thought” I did something similar, but at least I got it working.

Much appreciate your help!