Is it possible to run a script on the output of a package without having to rebuild it?
The package I would like to modify takes several hours to build, but I just need to add some lines to a bash script it contains in it’s $out
folder.
You could “wrap” it, by copying it’s out to a new out, changing only the scripts you need to change.
Yeah, I thought of something like that aswell. I just thought there would be a convenience function for that which would also leave the attributes and override functions intact.
Sorry to hijack this thread, I am trying to do the same (change the bash script generated by nix to wrap a compiled executable).
@NobbZ By “wrap” you mean wrap the original derivation in a new derivation, not wrap a file in /bin with the makeWrapper
shell command available during builds?
@busti Can you elaborate what you have done?
The basic idea is that you create a new package entirely and then have that copy the outputs of the first package to it’s output directory.
I do what you’re asking for a lot for my projects, and use the copying technique suggested by the other answers.
Here is a fully commented example:
The symlinkJoin
trivial builder constructs a new derivation populated by just directories and symlinks from the paths
argument. Then in postBuild
you can do whatever you want, like wrapProgram
or substituteInPlace
. Since it operates on the output of the original, it doesn’t rebuild the original.
dict = pkgs.symlinkJoin {
name = "dict-wrapped";
paths = [ pkgs.dict ];
nativeBuildInputs = [ pkgs.makeBinaryWrapper ];
postBuild = ''
wrapProgram "$out/bin/dictd" \
--add-flags '--config "${myconfigfile}"'
'';
};
limitation: symlinkJoin
cannot replace files (also cannot delete files)
so, when multiple paths have the same file, then symlinkJoin
will use the first file
symlinkJoin
is defined in nixpkgs/pkgs/build-support/trivial-builders.nix
symlinkJoin
is basically just xorg.lndir
for i in $(cat $pathsPath); do
${lndir}/bin/lndir -silent $i $out
done
reproduce:
cd $(mktemp -d)
nix-shell -p xorg.lndir
mkdir a b z
touch a/f b/f
for path in a b; do lndir $PWD/$path z; done
# f: /tmp/tmp.wbIlOkiaFH/a/f
readlink z/f
# /tmp/tmp.wbIlOkiaFH/a/f