emacs: replace ad hoc implementation with lib.extendMkDerivation (#379540)

This commit is contained in:
Lin Jian
2025-02-06 20:07:06 +08:00
committed by GitHub
5 changed files with 268 additions and 273 deletions

View File

@@ -16,40 +16,41 @@ let
texinfo
;
};
libBuildHelper = import ./lib-build-helper.nix;
in
libBuildHelper.extendMkDerivation' genericBuild (
finalAttrs:
lib.extendMkDerivation {
constructDrv = genericBuild;
extendDrvArgs =
finalAttrs:
{
pname,
dontUnpack ? true,
meta ? { },
...
}@args:
{
pname,
dontUnpack ? true,
meta ? { },
...
}@args:
{
{
elpa2nix = args.elpa2nix or ./elpa2nix.el;
elpa2nix = args.elpa2nix or ./elpa2nix.el;
inherit dontUnpack;
inherit dontUnpack;
installPhase =
args.installPhase or ''
runHook preInstall
installPhase =
args.installPhase or ''
runHook preInstall
emacs --batch -Q -l "$elpa2nix" \
-f elpa2nix-install-package \
"$src" "$out/share/emacs/site-lisp/elpa"
emacs --batch -Q -l "$elpa2nix" \
-f elpa2nix-install-package \
"$src" "$out/share/emacs/site-lisp/elpa"
runHook postInstall
'';
runHook postInstall
'';
meta = {
homepage = args.src.meta.homepage or "https://elpa.gnu.org/packages/${pname}.html";
} // meta;
}
meta = {
homepage = args.src.meta.homepage or "https://elpa.gnu.org/packages/${pname}.html";
} // meta;
};
)
}

View File

@@ -11,100 +11,100 @@
let
inherit (lib) optionalAttrs;
libBuildHelper = import ./lib-build-helper.nix;
in
libBuildHelper.extendMkDerivation' stdenv.mkDerivation (
finalAttrs:
lib.extendMkDerivation {
constructDrv = stdenv.mkDerivation;
extendDrvArgs =
finalAttrs:
{
buildInputs ? [ ],
nativeBuildInputs ? [ ],
packageRequires ? [ ],
propagatedBuildInputs ? [ ],
propagatedUserEnvPkgs ? [ ],
postInstall ? "",
meta ? { },
turnCompilationWarningToError ? false,
ignoreCompilationError ? false,
...
}@args:
{
buildInputs ? [ ],
nativeBuildInputs ? [ ],
packageRequires ? [ ],
propagatedBuildInputs ? [ ],
propagatedUserEnvPkgs ? [ ],
postInstall ? "",
meta ? { },
turnCompilationWarningToError ? false,
ignoreCompilationError ? false,
...
}@args:
{
name = args.name or "emacs-${finalAttrs.pname}-${finalAttrs.version}";
{
name = args.name or "emacs-${finalAttrs.pname}-${finalAttrs.version}";
unpackCmd =
args.unpackCmd or ''
case "$curSrc" in
*.el)
# keep original source filename without the hash
local filename=$(basename "$curSrc")
filename="''${filename:33}"
cp $curSrc $filename
chmod +w $filename
sourceRoot="."
;;
*)
_defaultUnpack "$curSrc"
;;
esac
'';
unpackCmd =
args.unpackCmd or ''
case "$curSrc" in
*.el)
# keep original source filename without the hash
local filename=$(basename "$curSrc")
filename="''${filename:33}"
cp $curSrc $filename
chmod +w $filename
sourceRoot="."
;;
*)
_defaultUnpack "$curSrc"
;;
esac
'';
inherit packageRequires;
buildInputs = [ emacs ] ++ buildInputs;
nativeBuildInputs = [
emacs
texinfo
] ++ nativeBuildInputs;
propagatedBuildInputs = finalAttrs.packageRequires ++ propagatedBuildInputs;
propagatedUserEnvPkgs = finalAttrs.packageRequires ++ propagatedUserEnvPkgs;
inherit packageRequires;
buildInputs = [ emacs ] ++ buildInputs;
nativeBuildInputs = [
emacs
texinfo
] ++ nativeBuildInputs;
propagatedBuildInputs = finalAttrs.packageRequires ++ propagatedBuildInputs;
propagatedUserEnvPkgs = finalAttrs.packageRequires ++ propagatedUserEnvPkgs;
strictDeps = args.strictDeps or true;
strictDeps = args.strictDeps or true;
inherit turnCompilationWarningToError ignoreCompilationError;
inherit turnCompilationWarningToError ignoreCompilationError;
meta =
{
broken = false;
platforms = emacs.meta.platforms;
}
// optionalAttrs ((args.src.meta.homepage or "") != "") {
homepage = args.src.meta.homepage;
}
// meta;
}
meta =
{
broken = false;
platforms = emacs.meta.platforms;
}
// optionalAttrs ((args.src.meta.homepage or "") != "") {
homepage = args.src.meta.homepage;
}
// meta;
}
// optionalAttrs (emacs.withNativeCompilation or false) {
// optionalAttrs (emacs.withNativeCompilation or false) {
addEmacsNativeLoadPath = args.addEmacsNativeLoadPath or true;
addEmacsNativeLoadPath = args.addEmacsNativeLoadPath or true;
postInstall =
''
# Besides adding the output directory to the native load path, make sure
# the current package's elisp files are in the load path, otherwise
# (require 'file-b) from file-a.el in the same package will fail.
mkdir -p $out/share/emacs/native-lisp
addEmacsVars "$out"
postInstall =
''
# Besides adding the output directory to the native load path, make sure
# the current package's elisp files are in the load path, otherwise
# (require 'file-b) from file-a.el in the same package will fail.
mkdir -p $out/share/emacs/native-lisp
addEmacsVars "$out"
# package-activate-all is used to activate packages. In other builder
# helpers, package-initialize is used for this purpose because
# package-activate-all is not available before Emacs 27.
find $out/share/emacs -type f -name '*.el' -not -name ".dir-locals.el" -print0 \
| xargs --verbose -0 -I {} -n 1 -P $NIX_BUILD_CORES sh -c \
"emacs \
--batch \
-f package-activate-all \
--eval '(setq native-comp-eln-load-path (cdr native-comp-eln-load-path))' \
--eval '(let ((default-directory \"$out/share/emacs/site-lisp\")) (normal-top-level-add-subdirs-to-load-path))' \
--eval '(setq large-file-warning-threshold nil)' \
--eval '(setq byte-compile-error-on-warn ${
if finalAttrs.turnCompilationWarningToError then "t" else "nil"
})' \
-f batch-native-compile {} \
|| exit ${if finalAttrs.ignoreCompilationError then "0" else "\\$?"}"
''
+ postInstall;
}
# package-activate-all is used to activate packages. In other builder
# helpers, package-initialize is used for this purpose because
# package-activate-all is not available before Emacs 27.
find $out/share/emacs -type f -name '*.el' -not -name ".dir-locals.el" -print0 \
| xargs --verbose -0 -I {} -n 1 -P $NIX_BUILD_CORES sh -c \
"emacs \
--batch \
-f package-activate-all \
--eval '(setq native-comp-eln-load-path (cdr native-comp-eln-load-path))' \
--eval '(let ((default-directory \"$out/share/emacs/site-lisp\")) (normal-top-level-add-subdirs-to-load-path))' \
--eval '(setq large-file-warning-threshold nil)' \
--eval '(setq byte-compile-error-on-warn ${
if finalAttrs.turnCompilationWarningToError then "t" else "nil"
})' \
-f batch-native-compile {} \
|| exit ${if finalAttrs.ignoreCompilationError then "0" else "\\$?"}"
''
+ postInstall;
};
)
}

View File

@@ -1,5 +0,0 @@
{
extendMkDerivation' =
mkDerivationBase: attrsOverlay: fpargs:
(mkDerivationBase fpargs).overrideAttrs attrsOverlay;
}

View File

@@ -18,7 +18,6 @@ let
texinfo
;
};
libBuildHelper = import ./lib-build-helper.nix;
packageBuild = stdenv.mkDerivation {
name = "package-build";
@@ -42,156 +41,158 @@ let
in
libBuildHelper.extendMkDerivation' genericBuild (
finalAttrs:
lib.extendMkDerivation {
constructDrv = genericBuild;
extendDrvArgs =
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:
{
/*
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;
elpa2nix = args.elpa2nix or ./elpa2nix.el;
melpa2nix = args.melpa2nix or ./melpa2nix.el;
inherit
commit
ename
files
recipe
;
inherit
commit
ename
files
recipe
;
packageBuild = args.packageBuild or packageBuild;
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
);
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
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"
ln -s "$packageBuild" "$NIX_BUILD_TOP/package-build"
mkdir -p "$NIX_BUILD_TOP/packages"
''
+ preUnpack;
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;
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
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
# 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"
pushd "$NIX_BUILD_TOP"
emacs --batch -Q \
-L "$NIX_BUILD_TOP/package-build" \
-l "$melpa2nix" \
-f melpa2nix-build-package \
$ename $melpaVersion $commit
emacs --batch -Q \
-L "$NIX_BUILD_TOP/package-build" \
-l "$melpa2nix" \
-f melpa2nix-build-package \
$ename $melpaVersion $commit
popd
popd
runHook postBuild
'';
runHook postBuild
'';
installPhase =
args.installPhase or ''
runHook preInstall
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
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"
emacs --batch -Q \
-l "$elpa2nix" \
-f elpa2nix-install-package \
"$archive" "$out/share/emacs/site-lisp/elpa"
runHook postInstall
'';
runHook postInstall
'';
meta = {
homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";
} // meta;
}
meta = {
homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";
} // meta;
};
)
}

View File

@@ -2,40 +2,38 @@
{ callPackage, lib, ... }@envargs:
let
libBuildHelper = import ./lib-build-helper.nix;
in
lib.extendMkDerivation {
constructDrv = callPackage ./generic.nix envargs;
extendDrvArgs =
finalAttrs:
libBuildHelper.extendMkDerivation' (callPackage ./generic.nix envargs) (
finalAttrs:
args:
args:
{
buildPhase =
args.buildPhase or ''
runHook preBuild
{
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
# 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
emacs -l package -f package-initialize -L . --batch -f batch-byte-compile *.el
emacs -l package -f package-initialize -L . --batch -f batch-byte-compile *.el
runHook postBuild
'';
runHook postBuild
'';
installPhase =
args.installPhase or ''
runHook preInstall
installPhase =
args.installPhase or ''
runHook preInstall
LISPDIR=$out/share/emacs/site-lisp
install -d $LISPDIR
install *.el *.elc $LISPDIR
LISPDIR=$out/share/emacs/site-lisp
install -d $LISPDIR
install *.el *.elc $LISPDIR
runHook postInstall
'';
};
runHook postInstall
'';
}
)
}