Globally overriding compile options, can't find overrideAttrs

I’m learning nix, and I don’t understand why my hack to override all of nixpkgs to use a particular flag combo doesn’t work. Is the mechanism for overriding aspects of a package different per package? Googling I found lots of examples of people using overrideAttrs, but usually on only one package. The code:

{
  description = "Example C++ development environment for Zero to Nix";

  # Flake inputs
  inputs = {
    nixpkgs.url = https://flakehub.com/f/NixOS/nixpkgs/0.2405.*.tar.gz;
  };

  # Flake outputs
  outputs = { self, nixpkgs }:
    let
      # Systems supported
      allSystems = [
        "x86_64-linux" # 64-bit Intel/AMD Linux
        "aarch64-linux" # 64-bit ARM Linux
        "x86_64-darwin" # 64-bit Intel macOS
        "aarch64-darwin" # 64-bit ARM macOS
      ];

      # Helper to provide system-specific attributes
      forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
        pkgs = builtins.mapAttrs
          (name: pkg: pkg.overrideAttrs
            (attrs:
              {
                NIX_CFLAGS_COMPILE = (attrs.NIX_CFLAGS_COMPILE or "") + " -ffunction-sections -fdata-sections";
              }))
          (import nixpkgs { inherit system; });
      });
    in
    {
      # Development environment output
      devShells = forAllSystems ({ pkgs }: {
        default = pkgs.mkShell {
          # The Nix packages provided in the environment
          packages = with pkgs; [
            gcc # The GNU Compiler Collection
          ] ++ lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-linux") [
            libhugetlbfs
          ];
        };
      });
    };
}

The error:

$ nix develop
error: attribute 'overrideAttrs' missing
       at /nix/store/10yxp8c9y80lrdlwr9fy3y95bnicrn6n-source/flake.nix:22:46:
           21|       forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
           22|         pkgs = builtins.mapAttrs (name: pkg: pkg.overrideAttrs (attrs: {NIX_CFLAGS_COMPILE = (attrs.NIX_CFLAGS_COMPILE or "") + " -ffunction-sections -fdata-sections";})) (import nixpkgs { inherit system; });
             |                                              ^
           23|       });

If you want to change stdenv you should use adapters, i.e. functions defined in pkgs/stdenv/adapters.nix. In this case, you want withCFlags:

Here, an overlay might not be necessary per se:

      devShells = forAllSystems ({ pkgs }: {
        default = pkgs.mkShell.override {
          stdenv = pkgs.withCFlags [ "-ffunction-sections" "-fdata-sections" ] pkgs.stdenv;
        } {
          # The Nix packages provided in the environment
          packages = lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-linux") [
            libhugetlbfs
          ];
        };
      });

Though if you want to apply it to the entire nixpkgs instance then you may have to modify forAllSystems to use an overlay as the comment mentions. Expect a lot of rebuilding here initially.

And I removed gcc from the shell as I mentioned on your prior question.

1 Like

Just for my own learning though, why doesn’t my approach work? Is overrideAttrs not on every package? I don’t get why examples with it work and mine doesn’t.

And I removed gcc from the shell as I mentioned on your prior question.

Sorry I should also fix the legacy thing to avoid multiple instantiations, this is a separate fork I started just to horse around and figure out how things work. Nobody should take this as best practices :slight_smile:

Because half the attributes of pkgs aren’t packages, and don’t have an attribute called overrideAttrs. Many of the actual packages don’t eval or build either.

1 Like

Hey @waffle8946 finally got around to trying this. AFAICT the stdenv approach has no effect, everything still gets pulled from the binary cache, but since I’ve changed flags surely this should trigger a rebuild? I must still be doing something wrong. neverball installs though and there are no errors when I run nix develop to enter the shell

{
  description = "Example C++ development environment for Zero to Nix";

  # Flake inputs
  inputs = {
    nixpkgs.url = https://flakehub.com/f/NixOS/nixpkgs/0.2405.*.tar.gz;
  };

  # Flake outputs
  outputs = { self, nixpkgs }:
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in
    {
      # Development environment output
      devShells = {
        x86_64-linux.default = pkgs.mkShell.override {
          stdenv = pkgs.withCFlags [
            "-ffunction-sections"
            "-fdata-sections"
            "-frecord-gcc-switches"
          ] pkgs.stdenv;
        } {
          # The Nix packages provided in the environment
          packages = with pkgs; [
            # packages go here, gcc is always included so no need to
            # list
            neverball
          ];
        };
      };
    };
}

For anyone wondering by in the future, this worked, put together with some help from Claude to figure out why it was rebuilding so much just for hello world (it affected the bootstrap packages which this now excludes). IIUC the problem with the above is that overriding stdenv for the shell doesn’t change the stdenv used for any packages built before the shell starts.

{
  description = "Example C++ development environment with custom compiler flags";

  inputs = {
    nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2405.*.tar.gz";
  };

  outputs = { self, nixpkgs }: let
    system = "x86_64-linux";

    # We want to add custom compile flags, but not to the bootstrap
    # packages, because that will trigger unnecessary building of
    # stuff that we never actually link, like bison.
    pkgs = import nixpkgs {
      inherit system;
      overlays = [(final: prev: let
        isBootstrap = name: builtins.match "bootstrap-.*" name != null;
      in {
        stdenv = if isBootstrap prev.stdenv.name
                 then prev.stdenv
                 else prev.withCFlags [ "-frecord-gcc-switches" ] prev.stdenv;
      })];
    };
  in {
    devShells.${system}.default = pkgs.mkShell {
      packages = with pkgs; [
        hello
      ];
    };
  };
}