core/pkgs/by-name/te/texlive/build-texlive-package.nix

277 lines
8.2 KiB
Nix
Raw Normal View History

2024-06-30 08:16:52 +00:00
{
lib,
fetchurl,
runCommand,
writeShellScript,
2024-05-02 00:46:19 +00:00
# script interpreters
2024-06-30 08:16:52 +00:00
bash,
jdk,
perl,
python3,
ruby,
snobol4,
tk,
2024-05-02 00:46:19 +00:00
# TeX Live prerequisites
2024-06-30 08:16:52 +00:00
texliveBinaries,
2024-05-02 00:46:19 +00:00
}:
2024-06-30 08:16:52 +00:00
/*
Convert an attribute set extracted from tlpdb.nix (with the deps attribute
2024-05-02 00:46:19 +00:00
already processed) to a fake multi-output derivation with possible outputs
[ "tex" "texdoc" "texsource" "tlpkg" "out" "man" "info" ]
The multi-output is emulated as follows:
- the main derivation is a multi-output derivation that builds links to the
containers (tex, texdoc, ...)
- the output attributes are replaced with the actual containers with the
outputSpecified attribute set to true
In this way, when texlive.withPackages picks an output such as drv.tex, it
receives the actual container, avoiding superfluous dependencies on the other
containers (for instance doc containers).
*/
# TODO stabilise a generic interface decoupled from the finer details of the
# translation from texlive.tlpdb to tlpdb.nix
2024-06-30 08:16:52 +00:00
{
pname,
revision,
version ? toString revision,
extraRevision ? "",
extraVersion ? "",
sha512,
mirrors,
fixedHashes ? { },
postUnpack ? "",
postFixup ? "",
stripPrefix ? 1,
license ? [ ],
hasHyphens ? false,
hasInfo ? false,
hasManpages ? false,
hasRunfiles ? false,
hasTlpkg ? false,
extraNativeBuildInputs ? [ ],
...
2024-05-02 00:46:19 +00:00
}@args:
let
# common metadata
name = "${pname}-${version}${extraVersion}";
meta = {
license = map (x: lib.licenses.${x}) license;
# TeX Live packages should not be installed directly into the user profile
outputsToInstall = [ ];
longDescription = ''
This package cannot be installed directly. Please use `texlive.withPackages`.
'';
# discourage nix-env from matching this package
priority = 10;
2024-06-30 08:16:52 +00:00
} // lib.optionalAttrs (args ? shortdesc) { description = args.shortdesc; };
2024-05-02 00:46:19 +00:00
hasBinfiles = args ? binfiles && args.binfiles != [ ];
hasDocfiles = sha512 ? doc;
hasSource = sha512 ? source;
# containers that will be built by Hydra
2024-06-30 08:16:52 +00:00
outputs =
lib.optional hasBinfiles "out"
++ lib.optional hasRunfiles "tex"
++ lib.optional hasDocfiles "texdoc"
++
# omit building sources, since as far as we know, installing them is not common
# the sources will still be available under drv.texsource
# lib.optional hasSource "texsource" ++
lib.optional hasTlpkg "tlpkg"
++ lib.optional hasManpages "man"
++ lib.optional hasInfo "info";
2024-05-02 00:46:19 +00:00
outputDrvs = lib.getAttrs outputs containers;
2024-06-30 08:16:52 +00:00
passthru =
{
# metadata
inherit pname;
revision = toString revision + extraRevision;
version = version + extraVersion;
# containers behave like specified outputs
outputSpecified = true;
}
// lib.optionalAttrs (args ? deps) { tlDeps = args.deps; }
// lib.optionalAttrs (args ? fontMaps) { inherit (args) fontMaps; }
// lib.optionalAttrs (args ? formats) { inherit (args) formats; }
// lib.optionalAttrs (args ? hyphenPatterns) { inherit (args) hyphenPatterns; }
// lib.optionalAttrs (args ? postactionScript) { inherit (args) postactionScript; }
// lib.optionalAttrs hasSource { inherit (containers) texsource; }
// lib.optionalAttrs (!hasRunfiles) { tex = fakeTeX; };
2024-05-02 00:46:19 +00:00
# build run, doc, source, tlpkg containers
2024-06-30 08:16:52 +00:00
mkContainer =
tlType: tlOutputName: sha512:
2024-05-02 00:46:19 +00:00
let
fixedHash = fixedHashes.${tlType} or null; # be graceful about missing hashes
# the basename used by upstream (without ".tar.xz" suffix)
# tlpkg is not a true container but a subfolder of the run container
urlName = pname + (lib.optionalString (tlType != "run" && tlType != "tlpkg") ".${tlType}");
urls = map (up: "${up}/archive/${urlName}.r${toString revision}.tar.xz") mirrors;
2024-06-30 08:16:52 +00:00
container =
runCommand "${name}-${tlOutputName}"
(
{
src = fetchurl { inherit urls sha512; };
inherit passthru;
# save outputName, since fixed output derivations cannot change nor override outputName
inherit meta stripPrefix tlOutputName;
}
// lib.optionalAttrs (fixedHash != null) {
outputHash = fixedHash;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
}
)
(
''
mkdir "$out"
if [[ "$tlOutputName" == "tlpkg" ]]; then
tar -xf "$src" \
--strip-components=1 \
-C "$out" --anchored --exclude=tlpkg/tlpobj --keep-old-files \
tlpkg
else
tar -xf "$src" \
--strip-components="$stripPrefix" \
-C "$out" --anchored --exclude=tlpkg --keep-old-files
fi
''
+ postUnpack
);
2024-05-02 00:46:19 +00:00
in
# remove drv.out to avoid confusing texlive.withPackages
2024-06-30 08:16:52 +00:00
removeAttrs container [ "out" ] // outputDrvs;
2024-05-02 00:46:19 +00:00
# find interpreters for the script extensions found in tlpdb
extToInput = {
jar = jdk;
lua = texliveBinaries.luatex;
py = python3;
rb = ruby;
sno = snobol4;
tcl = tk;
texlua = texliveBinaries.luatex;
tlu = texliveBinaries.luatex;
};
# fake derivation for resolving dependencies in the absence of a "tex" containers
2024-06-30 08:16:52 +00:00
fakeTeX =
passthru
// {
inherit meta;
tlOutputName = "tex";
}
2024-05-02 00:46:19 +00:00
// outputDrvs;
containers = rec {
tex = mkContainer "run" "tex" sha512.run;
texdoc = mkContainer "doc" "texdoc" sha512.doc;
texsource = mkContainer "source" "texsource" sha512.source;
tlpkg = mkContainer "tlpkg" "tlpkg" sha512.run;
# bin container
2024-06-30 08:16:52 +00:00
out =
runCommand "${name}"
{
inherit meta;
passthru = passthru // {
tlOutputName = "out";
};
# shebang interpreters
buildInputs =
let
outName = builtins.replaceStrings [ "-" ] [ "_" ] pname;
in
[
texliveBinaries.core.${outName} or null
texliveBinaries.${pname} or null
texliveBinaries.core-big.${outName} or null
]
++ (args.extraBuildInputs or [ ])
++ [
bash
perl
]
++ (lib.attrVals (args.scriptExts or [ ]) extToInput);
nativeBuildInputs = extraNativeBuildInputs;
# absolute scripts folder
scriptsFolder = lib.optionals (hasRunfiles && tex ? outPath) (
map (f: tex.outPath + "/scripts/" + f) (lib.toList args.scriptsFolder or pname)
);
# binaries info
inherit (args) binfiles;
binlinks = builtins.attrNames (args.binlinks or { });
bintargets = builtins.attrValues (args.binlinks or { });
# build scripts
patchScripts = ./patch-scripts.sed;
makeBinContainers = ./make-bin-containers.sh;
}
''
. "$makeBinContainers"
${args.postFixup or ""}
''
// outputDrvs;
2024-05-02 00:46:19 +00:00
# build man, info containers
2024-06-30 08:16:52 +00:00
man =
removeAttrs (runCommand "${name}-man"
2024-05-02 00:46:19 +00:00
{
inherit meta texdoc;
2024-06-30 08:16:52 +00:00
passthru = passthru // {
tlOutputName = "man";
};
2024-05-02 00:46:19 +00:00
}
''
mkdir -p "$out"/share
ln -s {"$texdoc"/doc,"$out"/share}/man
2024-06-30 08:16:52 +00:00
''
) [ "out" ]
// outputDrvs;
2024-05-02 00:46:19 +00:00
2024-06-30 08:16:52 +00:00
info =
removeAttrs (runCommand "${name}-info"
2024-05-02 00:46:19 +00:00
{
inherit meta texdoc;
2024-06-30 08:16:52 +00:00
passthru = passthru // {
tlOutputName = "info";
};
2024-05-02 00:46:19 +00:00
}
''
mkdir -p "$out"/share
ln -s {"$texdoc"/doc,"$out"/share}/info
2024-06-30 08:16:52 +00:00
''
) [ "out" ]
// outputDrvs;
2024-05-02 00:46:19 +00:00
};
in
2024-06-30 08:16:52 +00:00
if outputs == [ ] then
removeAttrs fakeTeX [ "outputSpecified" ]
else
runCommand name
{
__structuredAttrs = true;
inherit meta outputDrvs outputs;
passthru = removeAttrs passthru [ "outputSpecified" ];
# force output name in case "out" is missing
nativeBuildInputs = lib.optional (!hasBinfiles) (
writeShellScript "force-output.sh" ''
export out="''${${builtins.head outputs}-}"
''
);
}
''
for outputName in ''${!outputs[@]} ; do
ln -s "''${outputDrvs[$outputName]}" "''${outputs[$outputName]}"
done
''
// outputDrvs