lib: Add attrsets.mainProgram#138418
Conversation
Small correction: conventionally we put binaries in the default output, specifically so this doesn't break. I'm not aware of many cases of binaries being renamed while still being compatible either, fwiw. |
1db581e to
3f9c97d
Compare
Thanks for the correction, I amended the PR description. |
nix-repl> lib.mainProgram bash error: attribute 'mainProgram' missing, at /home/src/nixpkgs/lib/attrsets.nix:500:43 I think for this to be useful, it would have to work the same way |
OK; I was thinking of PRing definitions of Is there a way to check whether the file exists and is executable, so I can provide a nicer error message in that case? |
4ad911d to
92277e3
Compare
That's how I'd have preferred it would work, tbh, but that ship seems to have sailed — it wouldn't make sense to have this function work differently from how Nix does it.
Not in lib, because the package hasn't necessarily been build at eval time. |
Same, I just didn't remember in the moment that
That's what I guessed, but I'm not super-familiar w/ some language details so I figured I'd rather ask. Thanks for confirming 💜 |
|
should this be renamed to |
|
As Alyssa said, that seemed unambiguous and clear, while still being concise. |
|
I feel like |
I don't understand what you mean here, this seems like a nonsequitur to me. |
|
I think |
'k, thanks for clarifying :) |
|
I'd prefer and runCommand "greeting-text" { } ''
${hello.mainProgram} >$out
''No function required. Also |
|
EDIT: I wasn't paying attention. It's in |
That's an interesting approach, but #119942 has received no attention from reviewers since May, and currently has merge conflicts, so it seems inappropriate to block other changes on it. |
This helper function provides the path to a package's main program, as a string. It handles correctly multi-output packages, and relies on the package's `meta.mainProgram` attribute.
Makes things more readable & uniform (see inconsistent use of `.outPath`) and
robust against `chromium` becoming a multi-output package.
No functional change in the current state of nixpkgs:
nix-repl> :l <nixpkgs>
Added 14970 variables.
nix-repl> "${pkgs.chromium}/bin/chromium"
"/nix/store/4lrnzi90yv1fhlip0l26xb6p2n7402aj-chromium-93.0.4577.82/bin/chromium"
nix-repl> "${pkgs.chromium.outPath}/bin/chromium"
"/nix/store/4lrnzi90yv1fhlip0l26xb6p2n7402aj-chromium-93.0.4577.82/bin/chromium"
nix-repl> lib.mainProgram pkgs.chromium
"/nix/store/4lrnzi90yv1fhlip0l26xb6p2n7402aj-chromium-93.0.4577.82/bin/chromium"
This behaviour is the same as `nix run`; thanks to @alyssais for the suggestion.
a87238b to
49eb934
Compare
|
Rebased to deal with merge conflict |
|
@zimbatm I believe Alyssa would like your opinion prior to merging this. |
I really like this, but we don't even need it to be this verbose. Support for this can be embedded into the Since then there would be both |
|
Oh, I didn't realize |
|
Something like this seems to work well: diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
index 56cfa0c503f..01a474ba26c 100644
--- a/pkgs/stdenv/generic/make-derivation.nix
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -370,9 +370,8 @@ else let
else true);
};
-in
-lib.extendDerivation
+self = lib.extendDerivation
validity.handled
({
overrideAttrs = f: stdenv.mkDerivation (attrs // (f attrs));
@@ -402,10 +401,13 @@ lib.extendDerivation
args = [ "-c" "export > $out" ];
});
+ mainProgram = "${lib.getBin self.outPath}/bin/${meta.mainProgram or derivationArg.pname or (builtins.parseDrvName derivationArg.name).name}";
+
inherit meta passthru;
} //
# Pass through extra attributes that are not inputs, but
# should be made available to Nix expressions using the
# derivation (e.g., in assertions).
passthru)
- (derivation derivationArg)
+ (derivation derivationArg);
+ in self |
zimbatm
left a comment
There was a problem hiding this comment.
Looks good to me. nixpkgs can benefit a lot from having a utility like that.
| getMan = getOutput "man"; | ||
|
|
||
| /* Get the path to a package's main executable */ | ||
| mainProgram = pkg: |
There was a problem hiding this comment.
What do you think mainBin to make it a bit shorter? I know it's bike-shedding territory, feel free to ignore.
There was a problem hiding this comment.
Please let's keep bin as the directory. The executable files can be exe if we want to keep it short.
Then why not review it?
Why would that be? I think we should ask ourselves the question whether we want Nixpkgs to have a good design or just pile convenience upon convenience until we have a big pile of unnecessary code. |
roberth
left a comment
There was a problem hiding this comment.
This should be solved with an attribute, not a function.
|
Actually you don't have to wait for #119942 because you can implement the logic for this directly in DetailsI don't think it's the best way to do it, but here you go.diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
index 8fa30637049..1a8ff222673 100644
--- a/pkgs/stdenv/generic/make-derivation.nix
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -411,4 +411,4 @@ lib.extendDerivation
# should be made available to Nix expressions using the
# derivation (e.g., in assertions).
passthru)
- (derivation derivationArg)
+ (let d = derivation derivationArg; in d // { exe = lib.getBin d + "/bin/${meta.mainProgram}"; } )
|
I've been using the same approach via a helper function which takes a derivation and adds |
This is: #158461 |
|
Let's get this unstuck.
Middle ground seems to be an #!${exe bash}
echo hello worldWhile it doesn't help with my Windows 95 LARP, it is similarly short and therefore usable as a shorthand notation rather than just a utility function for generic code. |
|
Being worried about the performance of adding an attribute to each derivation makes me wonder about the optimization potential by removing existing attributes: Many of those probably aren't really needed. Note that these are added by the |
Those guts should never have been exposed. Maybe create an issue if you want to discuss this more? It's a bit off topic here. |
|
merged #167247 |
|
Thank you @nbraud for starting the conversation and doing the work, even if another implementation got merged in the end. |
Motivation for this change
Writing
"${pkgs.something}/bin/something"is a common idiom, both innixpkgsitself and Nix users' configuration.That idiom is brittle, as it will break if the binary is renamed
or the package is made multi-output.Using instead
lib.mainProgram pkgs.somethingavoids both of those issues, and avoids implementing ad-hoc solutionseverywhere, while often being shorter.
As an example,
node-packagesis simplified and made more uniform; prior to the change,PUPEETER_EXECUTABLE_PATHwas defined in several different — but equivalent — ways using
.outPathor not; usinglib.mainProgramisequivalent to both of those and less brittle.
Things done
For non-Linux: Issandbox = trueset innix.conf? (See Nix manual)Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"Tested execution of all binary files (usually in./result/bin/)(Package updates) Added a release notes entry if the change is major or breaking(Module updates) Added a release notes entry if the change is significant(Module addition) Added a release notes entry if adding a new NixOS module