From 0c8cc4c19c7cc1cc91bf357fd74adf18d54921b6 Mon Sep 17 00:00:00 2001 From: Benjamin Sparks Date: Sat, 31 May 2025 20:30:19 +0200 Subject: [PATCH 1/5] stdenv: pass `meta.mainProgram` to build environment as `NIX_MAIN_PROGRAM` --- pkgs/stdenv/generic/make-derivation.nix | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index bc58907fbe5b7..e585ed84d6c3b 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -716,7 +716,9 @@ let ); let - envIsExportable = isAttrs env && !isDerivation env; + mainProgram = meta.mainProgram or null; + env' = env // lib.optionalAttrs (mainProgram != null) { NIX_MAIN_PROGRAM = mainProgram; }; + envIsExportable = isAttrs env' && !isDerivation env'; derivationArg = makeDerivationArgument ( removeAttrs attrs ( @@ -746,11 +748,11 @@ let checkedEnv = let - overlappingNames = attrNames (builtins.intersectAttrs env derivationArg); + overlappingNames = attrNames (builtins.intersectAttrs env' derivationArg); prettyPrint = lib.generators.toPretty { }; makeError = name: - " - ${name}: in `env`: ${prettyPrint env.${name}}; in derivation arguments: ${ + " - ${name}: in `env`: ${prettyPrint env'.${name}}; in derivation arguments: ${ prettyPrint derivationArg.${name} }"; errors = lib.concatMapStringsSep "\n" makeError overlappingNames; @@ -764,7 +766,7 @@ let assert assertMsg (isString v || isBool v || isInt v || isDerivation v) "The `env` attribute set can only contain derivation, string, boolean or integer attributes. The `${n}` attribute is of type ${builtins.typeOf v}."; v - ) env; + ) env'; # Fixed-output derivations may not reference other paths, which means that # for a fixed-output derivation, the corresponding inputDerivation should From 98380fcfe11be39ca8c92b0b913309d2ecf4a764 Mon Sep 17 00:00:00 2001 From: Benjamin Sparks Date: Sat, 31 May 2025 22:17:32 +0200 Subject: [PATCH 2/5] doc/rl-25.11: Changing `meta.mainProgram` influences package rebuilds --- doc/release-notes/rl-2511.section.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release-notes/rl-2511.section.md b/doc/release-notes/rl-2511.section.md index 77dbb7815b9f6..ba758d5b39156 100644 --- a/doc/release-notes/rl-2511.section.md +++ b/doc/release-notes/rl-2511.section.md @@ -32,6 +32,11 @@ - `gramps` has been updated to 6.0.0 Upstream recommends [backing up your Family Trees](https://gramps-project.org/wiki/index.php/Gramps_6.0_Wiki_Manual_-_Manage_Family_Trees#Backing_up_a_Family_Tree) before upgrading. +- `meta.mainProgram`: Changing this `meta` entry can lead to a package rebuild due to being used to determine the `NIX_MAIN_PROGRAM` environment variable. + +- `versionCheckHook`: Packages that previously relied solely on `pname` to locate the program used to version check, but have a differing `meta.mainProgram` entry, might now fail. + + ## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib} From 1b92d2f2827098a825c5e1aab0b769505eb3c15a Mon Sep 17 00:00:00 2001 From: Benjamin Sparks Date: Sat, 31 May 2025 20:33:14 +0200 Subject: [PATCH 3/5] versionCheckHook: consider `NIX_MAIN_PROGRAM` as a fallback for `versionCheckProgram` Should `versionCheckProgram` not be specified, the hook now first defaults to `$outputBin/bin/$NIX_MAIN_PROGRAM` before considering `$outputBin/bin/$pname`. Falling back to $pname will also emit a warning now, similar to that of `lib.getExe`. --- pkgs/by-name/ve/versionCheckHook/hook.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pkgs/by-name/ve/versionCheckHook/hook.sh b/pkgs/by-name/ve/versionCheckHook/hook.sh index ac4605640b70e..26ebf294c37fe 100644 --- a/pkgs/by-name/ve/versionCheckHook/hook.sh +++ b/pkgs/by-name/ve/versionCheckHook/hook.sh @@ -38,18 +38,19 @@ versionCheckHook(){ : "${versionCheckKeepEnvironment:=}" local cmdProgram cmdArg echoPrefix - if [[ -z "${versionCheckProgram-}" ]]; then - if [[ -z "${pname-}" ]]; then - echo "both \$pname and \$versionCheckProgram are empty, so" \ - "we don't know which program to run the versionCheckPhase" \ - "upon" >&2 - exit 2 - else - cmdProgram="${!outputBin}/bin/$pname" - fi - else + if [[ ! -z "${versionCheckProgram-}" ]]; then cmdProgram="$versionCheckProgram" + elif [[ ! -z "${NIX_MAIN_PROGRAM-}" ]]; then + cmdProgram="${!outputBin}/bin/${NIX_MAIN_PROGRAM}" + elif [[ ! -z "${pname-}" ]]; then + cmdProgram="${!outputBin}/bin/${pname}" + else + echo "versionCheckHook: \$NIX_MAIN_PROGRAM, \$versionCheckProgram and \$pname are all empty, so" \ + "we don't know how to run the versionCheckPhase." \ + "To fix this, set one of \`meta.mainProgram\` or \`versionCheckProgram\`." >&2 + exit 2 fi + if [[ ! -x "$cmdProgram" ]]; then echo "versionCheckHook: $cmdProgram was not found, or is not an executable" >&2 exit 2 From 651abd93078062cc19f0fa0e44b225d98f60839e Mon Sep 17 00:00:00 2001 From: Benjamin Sparks Date: Sat, 31 May 2025 21:32:33 +0200 Subject: [PATCH 4/5] doc: `versionCheckProgram` first defaults to `$outputBin/bin/$NIX_MAIN_PROGRAM` --- doc/hooks/versionCheckHook.section.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/hooks/versionCheckHook.section.md b/doc/hooks/versionCheckHook.section.md index 9bc2aea293e68..c97911fb349f0 100644 --- a/doc/hooks/versionCheckHook.section.md +++ b/doc/hooks/versionCheckHook.section.md @@ -31,7 +31,7 @@ It does so in a clean environment (using `env --ignore-environment`), and it che The variables that this phase control are: - `dontVersionCheck`: Disable adding this hook to the [`preInstallCheckHooks`](#ssec-installCheck-phase). Useful if you do want to load the bash functions of the hook, but run them differently. -- `versionCheckProgram`: The full path to the program that should print the `${version}` string. Defaults roughly to `${placeholder "out"}/bin/${pname}`. Using `$out` in the value of this variable won't work, as environment variables from this variable are not expanded by the hook. Hence using `placeholder` is unavoidable. +- `versionCheckProgram`: The full path to the program that should print the `${version}` string. Defaults to using the first non-empty value `$binary` out of `${NIX_MAIN_PROGRAM}` and `${pname}`, in that order, to build roughly `${placeholder "out"}/bin/$binary`. `${NIX_MAIN_PROGRAM}`'s value comes from `meta.mainProgram`, and does not normally need to be set explicitly. When setting `versionCheckProgram`, using `$out` directly won't work, as environment variables from this variable are not expanded by the hook. Hence using `placeholder "out"` is unavoidable. - `versionCheckProgramArg`: The argument that needs to be passed to `versionCheckProgram`. If undefined the hook tries first `--help` and then `--version`. Examples: `version`, `-V`, `-v`. - `versionCheckKeepEnvironment`: A list of environment variables to keep and pass to the command. Only those variables should be added to this list that are actually required for the version command to work. If it is not feasible to explicitly list all these environment variables you can set this parameter to the special value `"*"` to disable the `--ignore-environment` flag and thus keep all environment variables. - `preVersionCheck`: A hook to run before the check is done. From 32a6fb65a103f1021cb6c1d361273367034e4e37 Mon Sep 17 00:00:00 2001 From: Benjamin Sparks Date: Sat, 14 Jun 2025 13:03:13 +0200 Subject: [PATCH 5/5] versionCheckHook: emit warning when falling back to pname --- pkgs/by-name/ve/versionCheckHook/hook.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/by-name/ve/versionCheckHook/hook.sh b/pkgs/by-name/ve/versionCheckHook/hook.sh index 26ebf294c37fe..4a977fe7a888c 100644 --- a/pkgs/by-name/ve/versionCheckHook/hook.sh +++ b/pkgs/by-name/ve/versionCheckHook/hook.sh @@ -43,6 +43,11 @@ versionCheckHook(){ elif [[ ! -z "${NIX_MAIN_PROGRAM-}" ]]; then cmdProgram="${!outputBin}/bin/${NIX_MAIN_PROGRAM}" elif [[ ! -z "${pname-}" ]]; then + echo "versionCheckHook: Package \`${pname}\` does not have the \`meta.mainProgram\` attribute." \ + "We'll assume that the main program has the same name for now, but this behavior is deprecated," \ + "because it leads to surprising errors when the assumption does not hold." \ + "If the package has a main program, please set \`meta.mainProgram\` in its definition to make this warning go away." \ + "Should the binary that outputs the intended version differ from \`meta.mainProgram\`, consider setting \`versionCheckProgram\` instead." >&2 cmdProgram="${!outputBin}/bin/${pname}" else echo "versionCheckHook: \$NIX_MAIN_PROGRAM, \$versionCheckProgram and \$pname are all empty, so" \