nixpkgs/pkgs/applications/editors/emacs/build-support/melpa.nix
Maximilian Marx c51ca826ce
melpa2nix: update to work with current MELPA recipes
MELPA has started to use :rename in the :files attribute of
recipes (e.g., for bbdb), which is rejected as an invalid recipe by
earlier versions of package-build.
2024-09-09 11:59:51 +02:00

169 lines
4.5 KiB
Nix

# builder for Emacs packages built for packages.el
# using MELPA package-build.el
{ lib, stdenv, fetchFromGitHub, emacs, texinfo, writeText }:
let
genericBuild = import ./generic.nix { inherit lib stdenv emacs texinfo writeText; };
libBuildHelper = import ./lib-build-helper.nix;
packageBuild = stdenv.mkDerivation {
name = "package-build";
src = fetchFromGitHub {
owner = "melpa";
repo = "package-build";
rev = "d5661f1f1996a893fbcbacb4d290c57acab4fb0e";
hash = "sha256-zVhFR2kLLkCKC+esPBbIk3qOa033YND1HF9GiNI4JM8=";
};
patches = [ ./package-build-dont-use-mtime.patch ];
dontConfigure = true;
dontBuild = true;
installPhase = "
mkdir -p $out
cp -r * $out
";
};
in
libBuildHelper.extendMkDerivation' genericBuild (finalAttrs:
{ /*
pname: Nix package name without special symbols and without version or
"emacs-" prefix.
*/
pname
/*
ename: Original Emacs package name, possibly containing special symbols.
Default: pname
*/
, ename ? pname
/*
version: Either a stable version such as "1.2" or an unstable version.
An unstable version can use either Nix format (preferred) such as
"1.2-unstable-2024-06-01" or MELPA format such as "20240601.1230".
*/
, version
/*
commit: Optional package history commit.
Default: src.rev or "unknown"
This will be written into the generated package but it is not needed during
the build process.
*/
, commit ? (finalAttrs.src.rev or "unknown")
/*
files: Optional recipe property specifying the files used to build the package.
If null, do not set it in recipe, keeping the default upstream behaviour.
Default: null
*/
, files ? null
/*
recipe: Optional MELPA recipe.
Default: a minimally functional recipe
This can be a path of a recipe file, a string of the recipe content or an empty string.
The default value is used if it is an empty string.
*/
, recipe ? ""
, preUnpack ? ""
, postUnpack ? ""
, meta ? {}
, ...
}@args:
{
elpa2nix = args.elpa2nix or ./elpa2nix.el;
melpa2nix = args.melpa2nix or ./melpa2nix.el;
inherit commit ename files recipe;
packageBuild = args.packageBuild or packageBuild;
melpaVersion = args.melpaVersion or (
let
parsed = lib.flip builtins.match version
# match <version>-unstable-YYYY-MM-DD format
"^.*-unstable-([[:digit:]]{4})-([[:digit:]]{2})-([[:digit:]]{2})$";
unstableVersionInNixFormat = parsed != null; # heuristics
date = builtins.concatStringsSep "" parsed;
time = "0"; # unstable version in nix format lacks this info
in
if unstableVersionInNixFormat
then date + "." + time
else finalAttrs.version);
preUnpack = ''
mkdir -p "$NIX_BUILD_TOP/recipes"
recipeFile="$NIX_BUILD_TOP/recipes/$ename"
if [ -r "$recipe" ]; then
ln -s "$recipe" "$recipeFile"
nixInfoLog "link recipe"
elif [ -n "$recipe" ]; then
printf "%s" "$recipe" > "$recipeFile"
nixInfoLog "write recipe"
else
cat > "$recipeFile" <<'EOF'
(${finalAttrs.ename} :fetcher git :url "" ${lib.optionalString (finalAttrs.files != null) ":files ${finalAttrs.files}"})
EOF
nixInfoLog "use default recipe"
fi
nixInfoLog "recipe content:" "$(< $recipeFile)"
unset -v recipeFile
ln -s "$packageBuild" "$NIX_BUILD_TOP/package-build"
mkdir -p "$NIX_BUILD_TOP/packages"
'' + preUnpack;
postUnpack = ''
mkdir -p "$NIX_BUILD_TOP/working"
ln -s "$NIX_BUILD_TOP/$sourceRoot" "$NIX_BUILD_TOP/working/$ename"
'' + postUnpack;
buildPhase = args.buildPhase or ''
runHook preBuild
# This is modified from stdenv buildPhase. foundMakefile is used in stdenv checkPhase.
if [[ ! ( -z "''${makeFlags-}" && -z "''${makefile:-}" && ! ( -e Makefile || -e makefile || -e GNUmakefile ) ) ]]; then
foundMakefile=1
fi
pushd "$NIX_BUILD_TOP"
emacs --batch -Q \
-L "$NIX_BUILD_TOP/package-build" \
-l "$melpa2nix" \
-f melpa2nix-build-package \
$ename $melpaVersion $commit
popd
runHook postBuild
'';
installPhase = args.installPhase or ''
runHook preInstall
archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.el"
if [ ! -f "$archive" ]; then
archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.tar"
fi
emacs --batch -Q \
-l "$elpa2nix" \
-f elpa2nix-install-package \
"$archive" "$out/share/emacs/site-lisp/elpa"
runHook postInstall
'';
meta = {
homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";
} // meta;
}
)