What I’m trying to accomplish here is to have a utility script that is part of my nix shell for a project. I think that I should be able to create it using writeScript, but the script actually executes as I enter the shell even though what I want is to write it to disk in the nix store and just have it in my path. Here’s a minimal example (replace pkgs-20.03 with your own naming scheme):
This occurs when I put the script in buildInputs and in nativeBuildInputs. I can see the script gets written to the nix store, though. So, how do I just keep it from executing as I enter the shell?
I would try using writeScriptBin instead which will place the script under $out/bin which will be then added to path. From a quick look it seems that the magic in stdenv will try and source an input if it’s a regular file (I could be mistaken on this though).
I didn’t expect that, actually. I see writeScript used in so many places in nixpkgs, and some of the places that I checked looked to me as though they were supposed to be for scripts to be used at runtime, not build time. Though maybe that’s different in mkDerivation instead of mkShell.
writeScriptBin and friends are all based on the writeTextFile function:
writeScript will create a script file directly in the nix store (destination = "" for writeTextFile).
writeScriptBin will create a directory in the nix store, containing a bin directory, which contains the script itself, which is much more like a conventional “package” than what you get from writeScript. This is achieved by setting destination = "/bin" for writeTextFile.
stdenv handles these differently when used in buildInputs: a plain script will be sourced as a so-called “setup hook”, intended to provide additional functionality within stdenv. I’m not sure this behaviour is still used within nixpkgs, as there’s another mechanism for setup hooks which is a little easier to understand: a package can provide the setupHook attribute which refers to such a script. This is most commonly done by build tools like cmake. Meanwhile, a directory containing a bin subdirectory will be interpreted as a tool used explicitly by the build, and the bin subdirectory will be added to PATH in the build environment (this behaviour may be restricted to nativeBuildInputs only in the future).