Nix Cookbook: Difference between revisions

imported>Dustinlacewell
m Removed superfluous line in "Creating Periodic Services"
imported>Infinisil
Add tutorial on how to wrap derivations
Line 38: Line 38:
   };
   };
}
}
</syntaxHighlight>
== Wrapping packages ==
If you need to wrap a binary of a package (or a non-binary), there are a few ways of doing it. The simplest of which is just creating a new binary that calls the old one:
<syntaxHighlight lang="nix">
pkgs.writeScriptBin "hello" ''
  #!${pkgs.stdenv.shell}
  # Call hello with a traditional greeting
  exec ${pkgs.hello}/bin/hello -t
''
</syntaxHighlight>
The disadvantage of this way is that it doesn't propagate man pages and other paths from the old derivation. There are multiple ways of solving that:
<syntaxHighlight lang="nix">
let
  wrapped = pkgs.writeScriptBin "hello" ''
    #!${pkgs.stdenv.shell}
    exec ${pkgs.hello}/bin/hello -t
  '';
in
pkgs.symlinkJoin {
  name = "hello";
  paths = [
    wrapped
    pkgs.hello
  ];
}
</syntaxHighlight>
Similarly the following works too:
<syntaxHighlight lang="nix">
pkgs.symlinkJoin {
  name = "hello";
  paths = [ pkgs.hello ];
  buildInputs = [ pkgs.makeWrapper ];
  postBuild = ''
    wrapProgram $out/bin/hello \
      --add-flags "-t"
  '';
}
</syntaxHighlight>
If you prefer not to have every file symlinked and have a cleaner result, the following is also possible:
<syntaxHighlight lang="nix">
pkgs.runCommand "hello" {
  buildInputs = [ pkgs.makeWrapper ];
} ''
  mkdir $out
  # Link every top-level folder from pkgs.hello to our new target
  ln -s ${pkgs.hello}/* $out
  # Except the bin folder
  rm $out/bin
  mkdir $out/bin
  # We create the bin folder ourselves and link every binary in it
  ln -s ${pkgs.hello}/bin/* $out/bin
  # Except the hello binary
  rm $out/bin/hello
  # Because we create this ourself, by creating a wrapper
  makeWrapper ${pkgs.hello}/bin/hello $out/bin/hello \
    --add-flags "-t"
''
</syntaxHighlight>
And lastly, there is the possibility of wrapping things right inside the derivation you want to wrap, this is however discouraged and impractical in most cases, as it requires recompilation of it:
<syntaxHighlight lang="nix">
pkgs.hello.overrideAttrs (oldAttrs: {
  buildInputs = oldAttrs.buildInputs or [] ++ [ pkgs.makeWrapper ];
  postInstall = oldAttrs.postInstall or "" + ''
    wrapProgram $out/bin/hello \
      --add-flags "-t"
  '';
})
</syntaxHighlight>
</syntaxHighlight>