😀

Nix で Setup スクリプトのある Custom Package を作る

2024/08/03に公開

はじめに

巷に溢れる Nix の記事には、カスタムパッケージを作るやり方はたくさんあるが、それに shellHook などをかぶせたやり方の解説はほとんど存在しない。
pythonPackage.venvShellHook を参考にミニマムな setupHook を含んだ package の作り方を紹介する。

サンプルコード

flake.nix

{
  description = "Flake shell";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs =
    { nixpkgs, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (
      system:
      let
        pkgs = nixpkgs.legacyPackages."${system}";
      in
      rec {

        defaultPackage = pkgs.stdenvNoCC.mkDerivation {
          name = "mypkg";
          src = ./.;
          dontUnpack = true;
          dontConfigure = true;
          dontBuild = true;
          installPhase = ''
            mkdir -p $out/bin
            echo "echo 'Hello, world!'" > $out/bin/hello
            chmod +x $out/bin/hello
          '';
        };

        mypkgShellHook =
          pkgs.makeSetupHook
            {
              name = "mypkg";
              propagatedBuildInputs = [
                pkgs.bash
                defaultPackage
              ];
              substitutions = {
                valueFromNix = "'value from nix!'";
                shell = "${pkgs.bash}/bin/bash";
              };
            }
            (
              pkgs.writeScript "setup.sh" ''
                #!@shell@

                export GREETING="Hello, World!"
                export VALUE_FROM_NIX=@valueFromNix@
              ''
            );
      }
    );
}

これだけである、 makeSetupHook を利用して自分の ShellHook を定義してあげれば良い。

呼び出し方

flake.nix

{
  description = "Flake shell";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.mypkg.url = "path:./mypkg";

  outputs =
    {
      nixpkgs,
      flake-utils,
      mypkg,
      ...
    }:
    flake-utils.lib.eachDefaultSystem (
      system: {
        devShells.default = pkgs.mkShell { packages = [ mypkg.mypkgShellHook.${system} ]; };
      }
    );
}

呼び出す時は mypkgShellHook を packages に指定してあげれば良い、
あとは nix develop でお好みの環境に入ることができる。

おまけ

mkDerivation に setupHook というものがあり、そこで完結させることも可能である。

{
  description = "Flake shell";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs =
    { nixpkgs, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (
      system:
      let
        pkgs = nixpkgs.legacyPackages."${system}";
      in
      {
        defaultPackage = pkgs.stdenvNoCC.mkDerivation {
          name = "mypkg";
          src = ./.;
          dontUnpack = true;
          dontConfigure = true;
          dontBuild = true;
          installPhase = ''
            mkdir -p $out/bin
            echo "echo 'Hello, world!'" > $out/bin/hello
            chmod +x $out/bin/hello
          '';
          setupHook = (
            pkgs.writeScript "setup.sh" ''
              #!/bin/bash

              export GREETING="Hello, World!"
            ''
          );
        };
      }
    );
}
GitHubで編集を提案

Discussion