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
];
};
});
};
}
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.
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
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.
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
];
};
};
}