1 # builder for Emacs packages built for packages.el
2 # using MELPA package-build.el
4 { lib, stdenv, fetchFromGitHub, emacs, texinfo, writeText }:
7 genericBuild = import ./generic.nix { inherit lib stdenv emacs texinfo writeText; };
8 libBuildHelper = import ./lib-build-helper.nix;
10 packageBuild = stdenv.mkDerivation {
11 name = "package-build";
12 src = fetchFromGitHub {
14 repo = "package-build";
15 rev = "d5661f1f1996a893fbcbacb4d290c57acab4fb0e";
16 hash = "sha256-zVhFR2kLLkCKC+esPBbIk3qOa033YND1HF9GiNI4JM8=";
19 patches = [ ./package-build-dont-use-mtime.patch ];
32 libBuildHelper.extendMkDerivation' genericBuild (finalAttrs:
35 pname: Nix package name without special symbols and without version or
40 ename: Original Emacs package name, possibly containing special symbols.
45 version: Either a stable version such as "1.2" or an unstable version.
46 An unstable version can use either Nix format (preferred) such as
47 "1.2-unstable-2024-06-01" or MELPA format such as "20240601.1230".
51 commit: Optional package history commit.
52 Default: src.rev or "unknown"
53 This will be written into the generated package but it is not needed during
56 , commit ? (finalAttrs.src.rev or "unknown")
58 files: Optional recipe property specifying the files used to build the package.
59 If null, do not set it in recipe, keeping the default upstream behaviour.
64 recipe: Optional MELPA recipe.
65 Default: a minimally functional recipe
66 This can be a path of a recipe file, a string of the recipe content or an empty string.
67 The default value is used if it is an empty string.
78 elpa2nix = args.elpa2nix or ./elpa2nix.el;
79 melpa2nix = args.melpa2nix or ./melpa2nix.el;
81 inherit commit ename files recipe;
83 packageBuild = args.packageBuild or packageBuild;
85 melpaVersion = args.melpaVersion or (
87 parsed = lib.flip builtins.match version
88 # match <version>-unstable-YYYY-MM-DD format
89 "^.*-unstable-([[:digit:]]{4})-([[:digit:]]{2})-([[:digit:]]{2})$";
90 unstableVersionInNixFormat = parsed != null; # heuristics
91 date = builtins.concatStringsSep "" parsed;
92 time = "0"; # unstable version in nix format lacks this info
94 if unstableVersionInNixFormat
95 then date + "." + time
96 else finalAttrs.version);
99 mkdir -p "$NIX_BUILD_TOP/recipes"
100 recipeFile="$NIX_BUILD_TOP/recipes/$ename"
101 if [ -r "$recipe" ]; then
102 ln -s "$recipe" "$recipeFile"
103 nixInfoLog "link recipe"
104 elif [ -n "$recipe" ]; then
105 printf "%s" "$recipe" > "$recipeFile"
106 nixInfoLog "write recipe"
108 cat > "$recipeFile" <<'EOF'
109 (${finalAttrs.ename} :fetcher git :url "" ${lib.optionalString (finalAttrs.files != null) ":files ${finalAttrs.files}"})
111 nixInfoLog "use default recipe"
113 nixInfoLog "recipe content:" "$(< $recipeFile)"
116 ln -s "$packageBuild" "$NIX_BUILD_TOP/package-build"
118 mkdir -p "$NIX_BUILD_TOP/packages"
122 mkdir -p "$NIX_BUILD_TOP/working"
123 ln -s "$NIX_BUILD_TOP/$sourceRoot" "$NIX_BUILD_TOP/working/$ename"
126 buildPhase = args.buildPhase or ''
129 # This is modified from stdenv buildPhase. foundMakefile is used in stdenv checkPhase.
130 if [[ ! ( -z "''${makeFlags-}" && -z "''${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ) ]]; then
134 pushd "$NIX_BUILD_TOP"
137 -L "$NIX_BUILD_TOP/package-build" \
139 -f melpa2nix-build-package \
140 $ename $melpaVersion $commit
147 installPhase = args.installPhase or ''
150 archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.el"
151 if [ ! -f "$archive" ]; then
152 archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.tar"
157 -f elpa2nix-install-package \
158 "$archive" "$out/share/emacs/site-lisp/elpa"
164 homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";