Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce "wrapCommand" builder #43074

Closed
wants to merge 12 commits into from

Conversation

matthewbauer
Copy link
Member

Motivation for this change

"wrapCommand" is an abstraction of somethings fairly common in Nixpkgs where single binary is produced from a single source file. This happens frequently when using something like .jar or .phar files as well as in some of the Ruby things.

This should lead to less code & maintenance.

wrapCommand needs to use makeWrapper to work, so I had to move it from all-packages.nix into a new setup-hooks/default.nix file that will be used pulled in from stage.nix.

This makes it possible to use some of the setup hooks in trivial
builders.
This is a useful way to wrap a command without having to use a full
mkDerivation. There are a couple of options that can be passed to
control it.
Usually we want to compile .java files directly but ocassionaly this
is not possible. The most common reason is the code is closed source.
Any way, the .jar format is about as cross-platform as you can get so
it makes sense to support it. Adding the wrapCommand simplifies these
derivations greatly.
Ruby related packages that can now use wrapCommand.
@GrahamcOfBorg
Copy link

Success on x86_64-darwin (full log)

Attempted: apktool, emv, grepm, nix-generate-from-cpan, nixpkgs-lint

Partial log (click to expand)

copying path '/nix/store/jsrbbj64xx11h12g0mwj3mrinjhvgci1-mutt-1.10.0' from 'https://cache.nixos.org'...
building '/nix/store/sbfcrv2nc4sl51zk5w4jlpr4ygghlzpx-emv-1.95.drv'...
building '/nix/store/myglrnxxlj8wdmcg2g1khghfmxy542iz-grepm-0.6.drv'...
building '/nix/store/gf605cy6zdhnhpk7xvd372wcx0cvabfb-nix-generate-from-cpan-3.drv'...
building '/nix/store/54fi222lq07gm15v5vfmv56hdjn3damw-nixpkgs-lint-1.drv'...
/nix/store/qy0ibvzi3kcmhfq1vffp0lvhfflabbzq-apktool-2.3.3
/nix/store/ki0p5h9zzi72h3sc3i2rh5fl8wa308jy-emv-1.95
/nix/store/g1qv8q7ic1dzv9gj595380llz9bj70kz-grepm-0.6
/nix/store/mpsfw94pm1p31w975ai652caakd2q8cr-nix-generate-from-cpan-3
/nix/store/pfkh7nnxwd3k3wqwd00bk56s2dbz6h3r-nixpkgs-lint-1

@GrahamcOfBorg
Copy link

Failure on x86_64-linux (full log)

Attempted: apktool, emv, grepm, nix-generate-from-cpan, nixpkgs-lint

Partial log (click to expand)

cannot build derivation '/nix/store/85hw40bccmapnz4zxac76rwb5h7llzaj-gtk+-2.24.32.drv': 5 dependencies couldn't be built
cannot build derivation '/nix/store/s48mnd96gzblqvv5i0h78rgw79gj9h6g-gnome-vfs-2.24.4.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/hv4nz6d66406zi0dpybkl10k4pivxm7a-pinentry-1.1.0.drv': 2 dependencies couldn't be built
cannot build derivation '/nix/store/dgm4a3yf14wnwm2z0bf9cfigybmj6b9c-gnupg-2.2.8.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/f9f8shnzwlkm5mk8b0ihl5hi7acd8k58-openjdk-8u172b11.drv': 3 dependencies couldn't be built
cannot build derivation '/nix/store/9pvacih768gq2sfrkw6055khk44vg2f5-apktool-2.3.3.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/98scrsv6v8wbclkr7rbcqgrg5ka3p3c9-gpgme-1.11.1.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/9w94d35mmxrp3fabmj08ca6jr22aangq-mutt-1.10.0.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/si3f7k388jlp12y7zws4psxmdq7v9kxr-grepm-0.6.drv': 1 dependencies couldn't be built
error: build of '/nix/store/9pvacih768gq2sfrkw6055khk44vg2f5-apktool-2.3.3.drv', '/nix/store/si3f7k388jlp12y7zws4psxmdq7v9kxr-grepm-0.6.drv' failed

@GrahamcOfBorg
Copy link

Success on aarch64-linux (full log)

Attempted: emv, grepm, nix-generate-from-cpan, nixpkgs-lint

The following builds were skipped because they don't evaluate on aarch64-linux: apktool

Partial log (click to expand)

patching script interpreter paths in /nix/store/9431s8yli55irp69lx09i9r8mxwvik9w-mutt-1.10.0
/nix/store/9431s8yli55irp69lx09i9r8mxwvik9w-mutt-1.10.0/bin/smime_keys: interpreter directive changed from " /usr/bin/perl -w" to "/nix/store/9g5v9c8dkwm6w9jjc89xabxsmsya9hx2-perl-5.24.3/bin/perl -w"
/nix/store/9431s8yli55irp69lx09i9r8mxwvik9w-mutt-1.10.0/bin/flea: interpreter directive changed from "/bin/sh" to "/nix/store/p0vy17dp9jk2mvqsxsqnb14s3797lay7-bash-4.4-p23/bin/sh"
/nix/store/9431s8yli55irp69lx09i9r8mxwvik9w-mutt-1.10.0/bin/muttbug: interpreter directive changed from "/bin/sh" to "/nix/store/p0vy17dp9jk2mvqsxsqnb14s3797lay7-bash-4.4-p23/bin/sh"
checking for references to /build in /nix/store/9431s8yli55irp69lx09i9r8mxwvik9w-mutt-1.10.0...
building '/nix/store/49gn3kr2fmcw1zgwcl764l50r7gng6l0-grepm-0.6.drv'...
/nix/store/ljh9l72rh4b2s12hqj40f0s0srmddpim-emv-1.95
/nix/store/vindq3m4917yw33chbfmcq90dq16pyvc-grepm-0.6
/nix/store/bnsqvdgx5ic4s5k2b5dfkdd0wy93hcd9-nix-generate-from-cpan-3
/nix/store/1pbqhvgmscsy6rjfjwahcpikqf7dv1p7-nixpkgs-lint-1

Copy link
Contributor

@wmertens wmertens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

I just wonder about the patchShebangs thing, can you comment on that?

I also looked at whether this change may break other nixpkgs configs that are not in the tree, I don't think so, since trivial-builders is augmented and all-pkgs and the build env are the result of merging, so that seems to be ok.

I didn't check all the individual wrapCommands (yet) – so a tentative 👍 from me.

A great idea in any case!

allowSubstitutes = false;
}) ''
local -a args="($makeWrapperArgs)"
makeWrapper ${executable} $out/bin/${name} ''${args[@]}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should put quotes around these arguments, or run some quote-for-shell function. Academic, maybe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, shouldn't ${args[@]} also be in double quotes (I'm assuming that will work like "$@" then)?

Otherwise you can't pass arguments with spaces to makeWrapper. But that would mean you also have to go split all the arguments you have in all the makeWrapperArgs into the individual words.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is definitely good to do before merging - this is more of a proof of concept for now.

''
mkdir -p $out/bin
cp ${./nix-generate-from-cpan.pl} $out/bin/nix-generate-from-cpan
patchShebangs $out/bin/nix-generate-from-cpan
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now patchShebangs is no longer being done? Is that intentional? I'm thinking of the case where people want to run the wrapped program directly for any reason – maybe this should be part of makeCommand?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it may be wanted it some cases. In this case perl is used as the interpreter so the shebang is kind of unused. What's nice about this is it means we can reuse the original path of the file - so fixed output can keep their paths.

For this one anyway it has the correct shebang (#!/usr/bin/env perl will work everywhere!) So it seemed reasonable to avoid the patchShebangs.

The problem with patchShebangs is that it doesn't differentiate between "nativeBuildInputs" & "buildInputs" - so you can wind up with references from nativeBuildInputs in your output paths if you're not careful. It needs to be reworked to be compatible with cross compilation & strictDeps.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#!/usr/bin/env perl will work everywhere!

There is no /usr/bin/env in Nix sandbox. (I have not read the context of this PR so I don't know if this is important or not.)

@FRidh
Copy link
Member

FRidh commented Jul 11, 2018

Instead of being able to wrap a single command, I think it would be nice to have instead a mapping

executables = {
  "/bin/a" = ["--add-flags ${phar}"];
  "bin/* = ["--add-flags ${phar}"];
  };
}

and with the possibility of using glob to apply wrapper arguments to a selection of executables.

adds two new builders:

- buildTree
- wrapExecutable

These each can be used to run wrapCommand.

buildTree can be used to generate an output path from an attribute
list of directories. For instance:

buildTree "test" {
  "/bin" = "${lib.getBin libxml2}/bin";
  "/lib" = "${lib.getLib libxml2}/lib";
  "/share/man" = "${lib.getOutput "man" libxml2}/share/man";
  "/share/doc" = "${lib.getOutput "doc" libxml2}/share/doc";
} {}

Puts the multiple output derivation libxml2 back into one output.

wrapExecutable will use makeWrapper to generate a single output
wrapped version of the old executable. For instance:

wrapExecutable "bash" {
  executable = "";
  makeWrapperArgs = [
    "--prefix" "PATH" ":"
    (lib.makeSearchPathOutput "bin" "bin" [ a b c d e f ])
  [])
}

Will generate wrapped bash with a, b, c, d, e, & f in the PATH.

# Build a tree from an attribute mapping of paths to files.
buildTree = name: tree: args: runCommand name (args // {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is linkFarm but then with a more convenient tree argument?

# Pointless to do this on a remote machine.
preferLocalBuild = true;
allowSubstitutes = false;
}) ''
local -a args="($makeWrapperArgs)"
makeWrapper ${executable} $out/bin/${name} ''${args[@]}
'';
makeWrapper ${executable} $out ''${args[@]}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not keep it in /bin?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants