From 333a351b288a708b258b251a7535f4ac2ddf16f8 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:02:33 +0100 Subject: texlive.buildTeXLivePackage: switch to fake multi-output derivations for TeX Live packages --- pkgs/test/texlive/default.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 12c42444f18..249b880b221 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -648,10 +648,13 @@ rec { # this is effectively an eval-time assertion, converted into a derivation for # ease of testing fixedHashes = with lib; let - combine = findFirst (p: (head p.pkgs).pname == "combine") { pkgs = []; } (head texlive.collection-latexextra.pkgs).tlDeps; - all = concatLists (map (p: p.pkgs or []) (attrValues (removeAttrs texlive [ "bin" "combine" "combined" "tlpdb" ]))) ++ combine.pkgs; - fods = filter (p: isDerivation p && p.tlType != "bin") all; - errorText = concatMapStrings (p: optionalString (! p ? outputHash) "${p.pname + optionalString (p.tlType != "run") ("." + p.tlType)} does not have a fixed output hash\n") fods; + fods = lib.concatMap + (p: lib.optional (p ? tex) p.tex + ++ lib.optional (p ? texdoc) p.texdoc + ++ lib.optional (p ? texsource) p.texsource + ++ lib.optional (p ? tlpkg) p.tlpkg) + (attrValues texlive.pkgs); + errorText = concatMapStrings (p: optionalString (! p ? outputHash) "${p.pname}-${p.tlOutputName} does not have a fixed output hash\n") fods; in runCommand "texlive-test-fixed-hashes" { inherit errorText; passAsFile = [ "errorText" ]; -- cgit 1.4.1 From 361364aba0bb0796ff4e17265beab04868a3d745 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:02:33 +0100 Subject: tests.texlive.binaries: use new texlive package source --- pkgs/test/texlive/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 249b880b221..28986b428ef 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -454,8 +454,7 @@ rec { ''; # link all binaries in single derivation - allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive))); - binPackages = lib.filter (p: p.tlType == "bin") allPackages; + binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs); binaries = buildEnv { name = "texlive-binaries"; paths = binPackages; }; in runCommand "texlive-test-binaries" -- cgit 1.4.1 From 988124cf206384e4ef826987d8a1158cc27ec1c2 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sun, 3 Sep 2023 12:02:34 +0100 Subject: tests.texlive.shebangs: use new texlive package source --- pkgs/test/texlive/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 28986b428ef..7be9f817a74 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -564,8 +564,7 @@ rec { # check that all scripts have a Nix shebang shebangs = let - allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive))); - binPackages = lib.filter (p: p.tlType == "bin") allPackages; + binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs); in runCommand "texlive-test-shebangs" { } ('' -- cgit 1.4.1 From 7620b617e59c9d78119fa67081ce72efd9bc1b40 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:42:43 +0100 Subject: texlive: implement __overrideTeXConfig and withPackage Implement new 'buildTeXEnv' to leverage multi-output packages and provide __overrideTeXConfig/withPackages for modifying the configuration or adding packages. The override mechanism is prefixed until stabilized. --- pkgs/test/texlive/default.nix | 2 +- .../typesetting/tex/texlive/build-tex-env.nix | 434 +++++++++++++++++++++ .../typesetting/tex/texlive/combine-wrapper.nix | 42 ++ pkgs/tools/typesetting/tex/texlive/combine.nix | 315 --------------- pkgs/tools/typesetting/tex/texlive/default.nix | 138 ++++--- 5 files changed, 561 insertions(+), 370 deletions(-) create mode 100644 pkgs/tools/typesetting/tex/texlive/build-tex-env.nix create mode 100644 pkgs/tools/typesetting/tex/texlive/combine-wrapper.nix delete mode 100644 pkgs/tools/typesetting/tex/texlive/combine.nix (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 7be9f817a74..70813466882 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -613,7 +613,7 @@ rec { correctLicenses = scheme: builtins.foldl' (acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or []))) [] - scheme.passthru.packages; + scheme.passthru.requiredTeXPackages; correctLicensesAttrNames = scheme: lib.sort lt (map licenseToAttrName (correctLicenses scheme)); diff --git a/pkgs/tools/typesetting/tex/texlive/build-tex-env.nix b/pkgs/tools/typesetting/tex/texlive/build-tex-env.nix new file mode 100644 index 00000000000..99eb67aa6ff --- /dev/null +++ b/pkgs/tools/typesetting/tex/texlive/build-tex-env.nix @@ -0,0 +1,434 @@ +{ + # texlive package set + tl +, bin + +, lib +, buildEnv +, libfaketime +, makeFontsConf +, makeWrapper +, runCommand +, writeShellScript +, writeText +, toTLPkgSets +, bash +, perl + + # common runtime dependencies +, coreutils +, gawk +, gnugrep +, gnused +, ghostscript +}: + +lib.fix (self: { + withDocs ? false +, withSources ? false +, requiredTeXPackages ? ps: [ ps.scheme-infraonly ] + +### texlive.combine backward compatibility +, __extraName ? "combined" +, __extraVersion ? "" +# emulate the old texlive.combine (e.g. add man pages to main output) +, __combine ? false +# adjust behavior further if called from the texlive.combine wrapper +, __fromCombineWrapper ? false +}@args: + +let + ### texlive.combine backward compatibility + # if necessary, convert old style { pkgs = [ ... ]; } packages to attribute sets + ensurePkgSets = ps: if ! __fromCombineWrapper && builtins.any (p: p ? pkgs && builtins.all (p: p ? tlType) p.pkgs) ps + then let oldStyle = builtins.partition (p: p ? pkgs && builtins.all (p: p ? tlType) p.pkgs) ps; + in oldStyle.wrong ++ lib.concatMap toTLPkgSets oldStyle.right + else ps; + + pkgList = rec { + # resolve dependencies of the packages that affect the runtime + all = + let + # order of packages is irrelevant + packages = builtins.sort (a: b: a.pname < b.pname) (ensurePkgSets (requiredTeXPackages tl)); + runtime = builtins.partition + (p: p.outputSpecified or false -> builtins.elem (p.tlOutputName or p.outputName) [ "out" "tex" "tlpkg" ]) + packages; + keySet = p: { + key = ((p.name or "${p.pname}-${p.version}") + "-" + p.tlOutputName or p.outputName or ""); + inherit p; + tlDeps = p.tlDeps or (p.requiredTeXPackages or (_: [ ]) [ ]); + }; + in + # texlive.combine: the wrapper already resolves all dependencies + if __fromCombineWrapper then requiredTeXPackages null else + builtins.catAttrs "p" (builtins.genericClosure { + startSet = map keySet runtime.right; + operator = p: map keySet p.tlDeps; + }) ++ runtime.wrong; + + # group the specified outputs + specified = builtins.partition (p: p.outputSpecified or false) all; + specifiedOutputs = builtins.groupBy (p: p.tlOutputName or p.outputName) specified.right; + otherOutputNames = builtins.catAttrs "key" (builtins.genericClosure { + startSet = map (key: { inherit key; }) (lib.concatLists (builtins.catAttrs "outputs" specified.wrong)); + operator = _: [ ]; + }); + otherOutputs = lib.genAttrs otherOutputNames (n: builtins.catAttrs n specified.wrong); + outputsToInstall = builtins.catAttrs "key" (builtins.genericClosure { + startSet = map (key: { inherit key; }) + ([ "out" ] ++ lib.optional (splitOutputs ? man) "man" + ++ lib.concatLists (builtins.catAttrs "outputsToInstall" (builtins.catAttrs "meta" specified.wrong))); + operator = _: [ ]; + }); + + # split binary and tlpkg from tex, texdoc, texsource + bin = if __fromCombineWrapper + then builtins.filter (p: p.tlType == "bin") all # texlive.combine: legacy filter + else otherOutputs.out or [ ] ++ specifiedOutputs.out or [ ]; + tlpkg = if __fromCombineWrapper + then builtins.filter (p: p.tlType == "tlpkg") all # texlive.combine: legacy filter + else otherOutputs.tlpkg or [ ] ++ specifiedOutputs.tlpkg or [ ]; + + nonbin = if __fromCombineWrapper then builtins.filter (p: p.tlType != "bin" && p.tlType != "tlpkg") all # texlive.combine: legacy filter + else (if __combine then # texlive.combine: emulate old input ordering to avoid rebuilds + lib.concatMap (p: lib.optional (p ? tex) p.tex + ++ lib.optional ((withDocs || p ? man) && p ? texdoc) p.texdoc + ++ lib.optional (withSources && p ? texsource) p.texsource) specified.wrong + else otherOutputs.tex or [ ] + ++ lib.optionals withDocs (otherOutputs.texdoc or [ ]) + ++ lib.optionals withSources (otherOutputs.texsource or [ ])) + ++ specifiedOutputs.tex or [ ] ++ specifiedOutputs.texdoc or [ ] ++ specifiedOutputs.texsource or [ ]; + + # outputs that do not become part of the environment + nonEnvOutputs = lib.subtractLists [ "out" "tex" "texdoc" "texsource" "tlpkg" ] otherOutputNames; + }; + + # list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts` + # and `grep -IR rungs "$TEXMFDIST"` + # and ignoring luatex, perl, and shell scripts (those must be patched using postFixup) + needsGhostscript = lib.any (p: lib.elem p.pname [ "context" "dvipdfmx" "latex-papersize" "lyluatex" ]) pkgList.bin; + + name = if __combine then "texlive-${__extraName}-${bin.texliveYear}${__extraVersion}" # texlive.combine: old name name + else "texlive-${bin.texliveYear}-env"; + + texmfdist = (buildEnv { + name = "${name}-texmfdist"; + + # remove fake derivations (without 'outPath') to avoid undesired build dependencies + paths = builtins.catAttrs "outPath" pkgList.nonbin; + + # mktexlsr + nativeBuildInputs = [ tl."texlive.infra" ]; + + postBuild = # generate ls-R database + '' + mktexlsr "$out" + ''; + }).overrideAttrs (_: { allowSubstitutes = true; }); + + tlpkg = (buildEnv { + name = "${name}-tlpkg"; + + # remove fake derivations (without 'outPath') to avoid undesired build dependencies + paths = builtins.catAttrs "outPath" pkgList.tlpkg; + }).overrideAttrs (_: { allowSubstitutes = true; }); + + # the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist + # and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both) + texmfroot = runCommand "${name}-texmfroot" { + inherit texmfdist tlpkg; + } '' + mkdir -p "$out" + ln -s "$texmfdist" "$out"/texmf-dist + ln -s "$tlpkg" "$out"/tlpkg + ''; + + # texlive.combine: expose info and man pages in usual /share/{info,man} location + doc = buildEnv { + name = "${name}-doc"; + + paths = [ (texmfdist.outPath + "/doc") ]; + extraPrefix = "/share"; + + pathsToLink = [ + "/info" + "/man" + ]; + }; + + meta = { + description = "TeX Live environment" + + lib.optionalString withDocs " with documentation" + + lib.optionalString (withDocs && withSources) " and" + + lib.optionalString withSources " with sources"; + platforms = lib.platforms.all; + longDescription = "Contains the following packages and their transitive dependencies:\n - " + + lib.concatMapStringsSep "\n - " + (p: p.pname + (lib.optionalString (p.outputSpecified or false) " (${p.tlOutputName or p.outputName})")) + (requiredTeXPackages tl); + }; + + # emulate split output derivation + splitOutputs = { + out = out // { outputSpecified = true; }; + texmfdist = texmfdist // { outputSpecified = true; }; + texmfroot = texmfroot // { outputSpecified = true; }; + } // (lib.genAttrs pkgList.nonEnvOutputs (outName: (buildEnv { + inherit name; + paths = builtins.catAttrs "outPath" + (pkgList.otherOutputs.${outName} or [ ] ++ pkgList.specifiedOutputs.${outName} or [ ]); + # force the output to be ${outName} or nix-env will not work + nativeBuildInputs = [ (writeShellScript "force-output.sh" '' + export out="''${${outName}-}" + '') ]; + inherit meta passthru; + }).overrideAttrs { outputs = [ outName ]; } // { outputSpecified = true; })); + + passthru = lib.optionalAttrs (! __combine) (splitOutputs // { + all = builtins.attrValues splitOutputs; + outputs = [ "out" ] ++ pkgList.nonEnvOutputs; + }) // { + # This is set primarily to help find-tarballs.nix to do its job + requiredTeXPackages = builtins.filter lib.isDerivation (pkgList.bin ++ pkgList.nonbin + ++ lib.optionals (! __fromCombineWrapper) + (lib.concatMap (n: (pkgList.otherOutputs.${n} or [ ] ++ pkgList.specifiedOutputs.${n} or [ ]))) pkgList.nonEnvOutputs); + # useful for inclusion in the `fonts.packages` nixos option or for use in devshells + fonts = "${texmfroot}/texmf-dist/fonts"; + # support variants attrs, (prev: attrs) + __overrideTeXConfig = newArgs: + let appliedArgs = if builtins.isFunction newArgs then newArgs args else newArgs; in + self (args // { __fromCombineWrapper = false; } // appliedArgs); + withPackages = reqs: self (args // { requiredTeXPackages = ps: requiredTeXPackages ps ++ reqs ps; __fromCombineWrapper = false; }); + }; + + out = (if (! __combine) + # meta.outputsToInstall = [ "out" "man" ] is invalid within buildEnv: + # checkMeta will notice that there is no actual "man" output, and fail + # so we set outputsToInstall from the outside, where it is safe + then lib.addMetaAttrs { inherit (pkgList) outputsToInstall; } + else x: x) # texlive.combine: man pages used to be part of out +# no indent for git diff purposes +((buildEnv { + + inherit name; + + ignoreCollisions = false; + + # remove fake derivations (without 'outPath') to avoid undesired build dependencies + paths = builtins.catAttrs "outPath" pkgList.bin + ++ lib.optional __combine doc; + pathsToLink = [ + "/" + "/share/texmf-var/scripts" + "/share/texmf-var/tex/generic/config" + "/share/texmf-var/web2c" + "/share/texmf-config" + "/bin" # ensure these are writeable directories + ]; + + nativeBuildInputs = [ + makeWrapper + libfaketime + tl."texlive.infra" # mktexlsr + tl.texlive-scripts # fmtutil, updmap + tl.texlive-scripts-extra # texlinks + perl + ]; + + inherit meta passthru; + + postBuild = + # environment variables (note: only export the ones that are used in the wrappers) + '' + TEXMFROOT="${texmfroot}" + TEXMFDIST="${texmfdist}" + export PATH="$out/bin:$PATH" + TEXMFSYSCONFIG="$out/share/texmf-config" + TEXMFSYSVAR="$out/share/texmf-var" + export TEXMFCNF="$TEXMFSYSVAR/web2c" + '' + + # wrap executables with required env vars as early as possible + # 1. we use the wrapped binaries in the scripts below, to catch bugs + # 2. we do not want to wrap links generated by texlinks + '' + enable -f '${bash}/lib/bash/realpath' realpath + declare -i wrapCount=0 + for link in "$out"/bin/*; do + target="$(realpath "$link")" + if [[ "''${target##*/}" != "''${link##*/}" ]] ; then + # detected alias with different basename, use immediate target of $link to preserve $0 + # relevant for mktexfmt, repstopdf, ... + target="$(readlink "$link")" + fi + + rm "$link" + makeWrapper "$target" "$link" \ + --inherit-argv0 \ + --prefix PATH : "${ + # very common dependencies that are not detected by tests.texlive.binaries + lib.makeBinPath ([ coreutils gawk gnugrep gnused ] ++ lib.optional needsGhostscript ghostscript)}:$out/bin" \ + --set-default TEXMFCNF "$TEXMFCNF" \ + --set-default FONTCONFIG_FILE "${ + # necessary for XeTeX to find the fonts distributed with texlive + makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; } + }" + wrapCount=$((wrapCount + 1)) + done + echo "wrapped $wrapCount binaries and scripts" + '' + + # patch texmf-dist -> $TEXMFDIST + # patch texmf-local -> $out/share/texmf-local + # patch texmf.cnf -> $TEXMFSYSVAR/web2c/texmf.cnf + # TODO: perhaps do lua actions? + # tried inspiration from install-tl, sub do_texmf_cnf + '' + mkdir -p "$TEXMFCNF" + if [ -e "$TEXMFDIST/web2c/texmfcnf.lua" ]; then + sed \ + -e "s,\(TEXMFOS[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFROOT\",g" \ + -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFDIST\",g" \ + -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSVAR\",g" \ + -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSCONFIG\",g" \ + -e "s,\(TEXMFLOCAL[ ]*=[ ]*\)[^\,]*,\1\"$out/share/texmf-local\",g" \ + -e "s,\$SELFAUTOLOC,$out,g" \ + -e "s,selfautodir:/,$out/share/,g" \ + -e "s,selfautodir:,$out/share/,g" \ + -e "s,selfautoparent:/,$out/share/,g" \ + -e "s,selfautoparent:,$out/share/,g" \ + "$TEXMFDIST/web2c/texmfcnf.lua" > "$TEXMFCNF/texmfcnf.lua" + fi + + sed \ + -e "s,\(TEXMFROOT[ ]*=[ ]*\)[^\,]*,\1$TEXMFROOT,g" \ + -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1$TEXMFDIST,g" \ + -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSVAR,g" \ + -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSCONFIG,g" \ + -e "s,\$SELFAUTOLOC,$out,g" \ + -e "s,\$SELFAUTODIR,$out/share,g" \ + -e "s,\$SELFAUTOPARENT,$out/share,g" \ + -e "s,\$SELFAUTOGRANDPARENT,$out/share,g" \ + -e "/^mpost,/d" `# CVE-2016-10243` \ + "$TEXMFDIST/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf" + '' + + # now filter hyphenation patterns and formats + (let + hyphens = lib.filter (p: p.hasHyphens or false && p.tlOutputName or p.outputName == "tex") pkgList.nonbin; + hyphenPNames = map (p: p.pname) hyphens; + formats = lib.filter (p: p ? formats && p.tlOutputName or p.outputName == "tex") pkgList.nonbin; + formatPNames = map (p: p.pname) formats; + # sed expression that prints the lines in /start/,/end/ except for /end/ + section = start: end: "/${start}/,/${end}/{ /${start}/p; /${end}/!p; };\n"; + script = + writeText "hyphens.sed" ( + # document how the file was generated (for language.dat) + "1{ s/^(% Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; p; }\n" + # pick up the header + + "2,/^% from/{ /^% from/!p; };\n" + # pick up all sections matching packages that we combine + + lib.concatMapStrings (pname: section "^% from ${pname}:$" "^% from|^%%% No changes may be made beyond this point.$") hyphenPNames + # pick up the footer (for language.def) + + "/^%%% No changes may be made beyond this point.$/,$p;\n" + ); + scriptLua = + writeText "hyphens.lua.sed" ( + "1{ s/^(-- Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; p; }\n" + + "2,/^-- END of language.us.lua/p;\n" + + lib.concatMapStrings (pname: section "^-- from ${pname}:$" "^}$|^-- from") hyphenPNames + + "$p;\n" + ); + # formats not being installed must be disabled by prepending #! (see man fmtutil) + # sed expression that enables the formats in /start/,/end/ + enableFormats = pname: "/^# from ${pname}:$/,/^# from/{ s/^#! //; };\n"; + fmtutilSed = + writeText "fmtutil.sed" ( + # document how file was generated + "1{ s/^(# Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; }\n" + # disable all formats, even those already disabled + + "s/^([^#]|#! )/#! \\1/;\n" + # enable the formats from the packages being installed + + lib.concatMapStrings enableFormats formatPNames + # clean up formats that have been disabled twice + + "s/^#! #! /#! /;\n" + ); + in '' + mkdir -p "$TEXMFSYSVAR/tex/generic/config" + for fname in tex/generic/config/language.{dat,def}; do + [[ -e "$TEXMFDIST/$fname" ]] && sed -E -n -f '${script}' "$TEXMFDIST/$fname" > "$TEXMFSYSVAR/$fname" + done + [[ -e "$TEXMFDIST"/tex/generic/config/language.dat.lua ]] && sed -E -n -f '${scriptLua}' \ + "$TEXMFDIST"/tex/generic/config/language.dat.lua > "$TEXMFSYSVAR"/tex/generic/config/language.dat.lua + [[ -e "$TEXMFDIST"/web2c/fmtutil.cnf ]] && sed -E -f '${fmtutilSed}' "$TEXMFDIST"/web2c/fmtutil.cnf > "$TEXMFCNF"/fmtutil.cnf + + # create $TEXMFSYSCONFIG database, make new $TEXMFSYSVAR files visible to kpathsea + mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" + '') + + # generate format links (reads fmtutil.cnf to know which ones) *after* the wrappers have been generated + '' + texlinks --quiet "$out/bin" + '' + + # texlive postactions (see TeXLive::TLUtils::_do_postaction_script) + (lib.concatMapStrings (pkg: '' + postaction='${pkg.postactionScript}' + case "$postaction" in + *.pl) postInterp=perl ;; + *.texlua) postInterp=texlua ;; + *) postInterp= ;; + esac + echo "postaction install script for ${pkg.pname}: ''${postInterp:+$postInterp }$postaction install $TEXMFROOT" + $postInterp "$TEXMFROOT/$postaction" install "$TEXMFROOT" + '') (lib.filter (pkg: pkg ? postactionScript) pkgList.tlpkg)) + + # generate formats + '' + # many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1 + # libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE + # we cannot fix further randomness caused by luatex; for further details, see + # https://salsa.debian.org/live-team/live-build/-/blob/master/examples/hooks/reproducible/2006-reproducible-texlive-binaries-fmt-files.hook.chroot#L52 + # note that calling faketime and fmtutil is fragile (faketime uses LD_PRELOAD, fmtutil calls /bin/sh, causing potential glibc issues on non-NixOS) + # so we patch fmtutil to use faketime, rather than calling faketime fmtutil + substitute "$TEXMFDIST"/scripts/texlive/fmtutil.pl fmtutil \ + --replace 'my $cmdline = "$eng -ini ' 'my $cmdline = "faketime -f '"'"'\@1980-01-01 00:00:00 x0.001'"'"' $eng -ini ' + FORCE_SOURCE_DATE=1 TZ= perl fmtutil --sys --all | grep '^fmtutil' # too verbose + + # Disable unavailable map files + echo y | updmap --sys --syncwithtrees --force 2>&1 | grep '^\(updmap\| /\)' + # Regenerate the map files (this is optional) + updmap --sys --force 2>&1 | grep '^\(updmap\| /\)' + + # sort entries to improve reproducibility + [[ -f "$TEXMFSYSCONFIG"/web2c/updmap.cfg ]] && sort -o "$TEXMFSYSCONFIG"/web2c/updmap.cfg "$TEXMFSYSCONFIG"/web2c/updmap.cfg + + mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" # to make sure (of what?) + '' + + # remove *-sys scripts since /nix/store is readonly + '' + rm "$out"/bin/*-sys + '' + + # TODO: a context trigger https://www.preining.info/blog/2015/06/debian-tex-live-2015-the-new-layout/ + # http://wiki.contextgarden.net/ConTeXt_Standalone#Unix-like_platforms_.28Linux.2FMacOS_X.2FFreeBSD.2FSolaris.29 + + # MkIV uses its own lookup mechanism and we need to initialize + # caches for it. + # We use faketime to fix the embedded timestamps and patch the uuids + # with some random but constant values. + '' + if [[ -e "$out/bin/mtxrun" ]]; then + substitute "$TEXMFDIST"/scripts/context/lua/mtxrun.lua mtxrun.lua \ + --replace 'cache_uuid=osuuid()' 'cache_uuid="e2402e51-133d-4c73-a278-006ea4ed734f"' \ + --replace 'uuid=osuuid(),' 'uuid="242be807-d17e-4792-8e39-aa93326fc871",' + FORCE_SOURCE_DATE=1 TZ= faketime -f '@1980-01-01 00:00:00 x0.001' luatex --luaonly mtxrun.lua --generate + fi + '' + + # Get rid of all log files. They are not needed, but take up space + # and render the build unreproducible by their embedded timestamps + # and other non-deterministic diagnostics. + '' + find "$TEXMFSYSVAR"/web2c -name '*.log' -delete + '' + + # link TEXMFDIST in $out/share for backward compatibility + '' + ln -s "$TEXMFDIST" "$out"/share/texmf + '' + ; +}).overrideAttrs (_: { allowSubstitutes = true; })); +in out) diff --git a/pkgs/tools/typesetting/tex/texlive/combine-wrapper.nix b/pkgs/tools/typesetting/tex/texlive/combine-wrapper.nix new file mode 100644 index 00000000000..165e7a22c66 --- /dev/null +++ b/pkgs/tools/typesetting/tex/texlive/combine-wrapper.nix @@ -0,0 +1,42 @@ +# legacy texlive.combine wrapper +{ lib, toTLPkgList, toTLPkgSets, buildTeXEnv }: +args@{ + pkgFilter ? (pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.pname == "core" + || pkg.hasManpages or false) +, extraName ? "combined" +, extraVersion ? "" +, ... +}: +let + pkgSet = removeAttrs args [ "pkgFilter" "extraName" "extraVersion" ]; + + # combine a set of TL packages into a single TL meta-package + combinePkgs = pkgList: lib.catAttrs "pkg" ( + let + # a TeX package used to be an attribute set { pkgs = [ ... ]; ... } where pkgs is a list of derivations + # the derivations make up the TeX package and optionally (for backward compatibility) its dependencies + tlPkgToSets = drv: map ({ tlType, version ? "", outputName ? "", ... }@pkg: { + # outputName required to distinguish among bin.core-big outputs + key = "${pkg.pname or pkg.name}.${tlType}-${version}-${outputName}"; + inherit pkg; + }) (drv.pkgs or (toTLPkgList drv)); + pkgListToSets = lib.concatMap tlPkgToSets; in + builtins.genericClosure { + startSet = pkgListToSets pkgList; + operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or []); + }); + combined = combinePkgs (lib.attrValues pkgSet); + + # convert to specified outputs + tlTypeToOut = { run = "tex"; doc = "texdoc"; source = "texsource"; bin = "out"; tlpkg = "tlpkg"; }; + toSpecified = { tlType, ... }@drv: drv // { outputSpecified = true; tlOutputName = tlTypeToOut.${tlType}; }; + all = lib.filter pkgFilter combined ++ lib.filter (pkg: pkg.tlType == "tlpkg") combined; + converted = builtins.map toSpecified all; +in +buildTeXEnv { + __extraName = extraName; + __extraVersion = extraVersion; + requiredTeXPackages = _: converted; + __combine = true; + __fromCombineWrapper = true; +} diff --git a/pkgs/tools/typesetting/tex/texlive/combine.nix b/pkgs/tools/typesetting/tex/texlive/combine.nix deleted file mode 100644 index 415339bf6da..00000000000 --- a/pkgs/tools/typesetting/tex/texlive/combine.nix +++ /dev/null @@ -1,315 +0,0 @@ -{ lib, buildEnv, runCommand, writeText, makeWrapper, libfaketime, makeFontsConf -, perl, bash, coreutils, gnused, gnugrep, gawk, ghostscript -, bin, tl, toTLPkgList }: -# combine = -args@{ - pkgFilter ? (pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.pname == "core" - || pkg.hasManpages or false) -, extraName ? "combined" -, extraVersion ? "" -, ... -}: -let - # combine a set of TL packages into a single TL meta-package - combinePkgs = pkgList: lib.catAttrs "pkg" ( - let - # a TeX package is an attribute set { pkgs = [ ... ]; ... } where pkgs is a list of derivations - # the derivations make up the TeX package and optionally (for backward compatibility) its dependencies - tlPkgToSets = drv: map ({ tlType, version ? "", outputName ? "", ... }@pkg: { - # outputName required to distinguish among bin.core-big outputs - key = "${pkg.pname or pkg.name}.${tlType}-${version}-${outputName}"; - inherit pkg; - }) (drv.pkgs or (toTLPkgList drv)); - pkgListToSets = lib.concatMap tlPkgToSets; in - builtins.genericClosure { - startSet = pkgListToSets pkgList; - operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or []); - }); - - pkgSet = removeAttrs args [ "pkgFilter" "extraName" "extraVersion" ]; - pkgList = rec { - combined = combinePkgs (lib.attrValues pkgSet); - all = lib.filter pkgFilter combined; - splitBin = builtins.partition (p: p.tlType == "bin") all; - bin = splitBin.right; - nonbin = splitBin.wrong; - tlpkg = lib.filter (pkg: pkg.tlType == "tlpkg") combined; - }; - # list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts` - # and `grep -IR rungs "$TEXMFDIST"` - # and ignoring luatex, perl, and shell scripts (those must be patched using postFixup) - needsGhostscript = lib.any (p: lib.elem p.pname [ "context" "dvipdfmx" "latex-papersize" "lyluatex" ]) pkgList.bin; - - name = "texlive-${extraName}-${bin.texliveYear}${extraVersion}"; - - texmfdist = (buildEnv { - name = "${name}-texmfdist"; - - # remove fake derivations (without 'outPath') to avoid undesired build dependencies - paths = lib.catAttrs "outPath" pkgList.nonbin; - - # mktexlsr - nativeBuildInputs = [ tl."texlive.infra" ]; - - postBuild = # generate ls-R database - '' - mktexlsr "$out" - ''; - }).overrideAttrs (_: { allowSubstitutes = true; }); - - tlpkg = (buildEnv { - name = "${name}-tlpkg"; - - # remove fake derivations (without 'outPath') to avoid undesired build dependencies - paths = lib.catAttrs "outPath" pkgList.tlpkg; - }).overrideAttrs (_: { allowSubstitutes = true; }); - - # the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist - # and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both) - texmfroot = runCommand "${name}-texmfroot" { - inherit texmfdist tlpkg; - } '' - mkdir -p "$out" - ln -s "$texmfdist" "$out"/texmf-dist - ln -s "$tlpkg" "$out"/tlpkg - ''; - - # expose info and man pages in usual /share/{info,man} location - doc = buildEnv { - name = "${name}-doc"; - - paths = [ (texmfdist.outPath + "/doc") ]; - extraPrefix = "/share"; - - pathsToLink = [ - "/info" - "/man" - ]; - }; - -in (buildEnv { - - inherit name; - - ignoreCollisions = false; - - # remove fake derivations (without 'outPath') to avoid undesired build dependencies - paths = lib.catAttrs "outPath" pkgList.bin ++ [ doc ]; - pathsToLink = [ - "/" - "/share/texmf-var/scripts" - "/share/texmf-var/tex/generic/config" - "/share/texmf-var/web2c" - "/share/texmf-config" - "/bin" # ensure these are writeable directories - ]; - - nativeBuildInputs = [ - makeWrapper - libfaketime - tl."texlive.infra" # mktexlsr - tl.texlive-scripts # fmtutil, updmap - tl.texlive-scripts-extra # texlinks - perl - ]; - - passthru = { - # This is set primarily to help find-tarballs.nix to do its job - packages = lib.filter lib.isDerivation pkgList.all; - # useful for inclusion in the `fonts.packages` nixos option or for use in devshells - fonts = "${texmfroot}/texmf-dist/fonts"; - }; - - postBuild = - # environment variables (note: only export the ones that are used in the wrappers) - '' - TEXMFROOT="${texmfroot}" - TEXMFDIST="${texmfdist}" - export PATH="$out/bin:$PATH" - TEXMFSYSCONFIG="$out/share/texmf-config" - TEXMFSYSVAR="$out/share/texmf-var" - export TEXMFCNF="$TEXMFSYSVAR/web2c" - '' + - # wrap executables with required env vars as early as possible - # 1. we want texlive.combine to use the wrapped binaries, to catch bugs - # 2. we do not want to wrap links generated by texlinks - '' - enable -f '${bash}/lib/bash/realpath' realpath - declare -i wrapCount=0 - for link in "$out"/bin/*; do - target="$(realpath "$link")" - if [[ "''${target##*/}" != "''${link##*/}" ]] ; then - # detected alias with different basename, use immediate target of $link to preserve $0 - # relevant for mktexfmt, repstopdf, ... - target="$(readlink "$link")" - fi - - rm "$link" - makeWrapper "$target" "$link" \ - --inherit-argv0 \ - --prefix PATH : "${ - # very common dependencies that are not detected by tests.texlive.binaries - lib.makeBinPath ([ coreutils gawk gnugrep gnused ] ++ lib.optional needsGhostscript ghostscript)}:$out/bin" \ - --set-default TEXMFCNF "$TEXMFCNF" \ - --set-default FONTCONFIG_FILE "${ - # necessary for XeTeX to find the fonts distributed with texlive - makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; } - }" - wrapCount=$((wrapCount + 1)) - done - echo "wrapped $wrapCount binaries and scripts" - '' + - # patch texmf-dist -> $TEXMFDIST - # patch texmf-local -> $out/share/texmf-local - # patch texmf.cnf -> $TEXMFSYSVAR/web2c/texmf.cnf - # TODO: perhaps do lua actions? - # tried inspiration from install-tl, sub do_texmf_cnf - '' - mkdir -p "$TEXMFCNF" - if [ -e "$TEXMFDIST/web2c/texmfcnf.lua" ]; then - sed \ - -e "s,\(TEXMFOS[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFROOT\",g" \ - -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFDIST\",g" \ - -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSVAR\",g" \ - -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSCONFIG\",g" \ - -e "s,\(TEXMFLOCAL[ ]*=[ ]*\)[^\,]*,\1\"$out/share/texmf-local\",g" \ - -e "s,\$SELFAUTOLOC,$out,g" \ - -e "s,selfautodir:/,$out/share/,g" \ - -e "s,selfautodir:,$out/share/,g" \ - -e "s,selfautoparent:/,$out/share/,g" \ - -e "s,selfautoparent:,$out/share/,g" \ - "$TEXMFDIST/web2c/texmfcnf.lua" > "$TEXMFCNF/texmfcnf.lua" - fi - - sed \ - -e "s,\(TEXMFROOT[ ]*=[ ]*\)[^\,]*,\1$TEXMFROOT,g" \ - -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1$TEXMFDIST,g" \ - -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSVAR,g" \ - -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSCONFIG,g" \ - -e "s,\$SELFAUTOLOC,$out,g" \ - -e "s,\$SELFAUTODIR,$out/share,g" \ - -e "s,\$SELFAUTOPARENT,$out/share,g" \ - -e "s,\$SELFAUTOGRANDPARENT,$out/share,g" \ - -e "/^mpost,/d" `# CVE-2016-10243` \ - "$TEXMFDIST/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf" - '' + - # now filter hyphenation patterns and formats - (let - hyphens = lib.filter (p: p.hasHyphens or false && p.tlType == "run") pkgList.splitBin.wrong; - hyphenPNames = map (p: p.pname) hyphens; - formats = lib.filter (p: p ? formats && p.tlType == "run") pkgList.splitBin.wrong; - formatPNames = map (p: p.pname) formats; - # sed expression that prints the lines in /start/,/end/ except for /end/ - section = start: end: "/${start}/,/${end}/{ /${start}/p; /${end}/!p; };\n"; - script = - writeText "hyphens.sed" ( - # document how the file was generated (for language.dat) - "1{ s/^(% Generated by .*)$/\\1, modified by texlive.combine/; p; }\n" - # pick up the header - + "2,/^% from/{ /^% from/!p; };\n" - # pick up all sections matching packages that we combine - + lib.concatMapStrings (pname: section "^% from ${pname}:$" "^% from|^%%% No changes may be made beyond this point.$") hyphenPNames - # pick up the footer (for language.def) - + "/^%%% No changes may be made beyond this point.$/,$p;\n" - ); - scriptLua = - writeText "hyphens.lua.sed" ( - "1{ s/^(-- Generated by .*)$/\\1, modified by texlive.combine/; p; }\n" - + "2,/^-- END of language.us.lua/p;\n" - + lib.concatMapStrings (pname: section "^-- from ${pname}:$" "^}$|^-- from") hyphenPNames - + "$p;\n" - ); - # formats not being installed must be disabled by prepending #! (see man fmtutil) - # sed expression that enables the formats in /start/,/end/ - enableFormats = pname: "/^# from ${pname}:$/,/^# from/{ s/^#! //; };\n"; - fmtutilSed = - writeText "fmtutil.sed" ( - # document how file was generated - "1{ s/^(# Generated by .*)$/\\1, modified by texlive.combine/; }\n" - # disable all formats, even those already disabled - + "s/^([^#]|#! )/#! \\1/;\n" - # enable the formats from the packages being installed - + lib.concatMapStrings enableFormats formatPNames - # clean up formats that have been disabled twice - + "s/^#! #! /#! /;\n" - ); - in '' - mkdir -p "$TEXMFSYSVAR/tex/generic/config" - for fname in tex/generic/config/language.{dat,def}; do - [[ -e "$TEXMFDIST/$fname" ]] && sed -E -n -f '${script}' "$TEXMFDIST/$fname" > "$TEXMFSYSVAR/$fname" - done - [[ -e "$TEXMFDIST"/tex/generic/config/language.dat.lua ]] && sed -E -n -f '${scriptLua}' \ - "$TEXMFDIST"/tex/generic/config/language.dat.lua > "$TEXMFSYSVAR"/tex/generic/config/language.dat.lua - [[ -e "$TEXMFDIST"/web2c/fmtutil.cnf ]] && sed -E -f '${fmtutilSed}' "$TEXMFDIST"/web2c/fmtutil.cnf > "$TEXMFCNF"/fmtutil.cnf - - # create $TEXMFSYSCONFIG database, make new $TEXMFSYSVAR files visible to kpathsea - mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" - '') + - # generate format links (reads fmtutil.cnf to know which ones) *after* the wrappers have been generated - '' - texlinks --quiet "$out/bin" - '' + - # texlive postactions (see TeXLive::TLUtils::_do_postaction_script) - (lib.concatMapStrings (pkg: '' - postaction='${pkg.postactionScript}' - case "$postaction" in - *.pl) postInterp=perl ;; - *.texlua) postInterp=texlua ;; - *) postInterp= ;; - esac - echo "postaction install script for ${pkg.pname}: ''${postInterp:+$postInterp }$postaction install $TEXMFROOT" - $postInterp "$TEXMFROOT/$postaction" install "$TEXMFROOT" - '') (lib.filter (pkg: pkg ? postactionScript) pkgList.tlpkg)) + - # generate formats - '' - # many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1 - # libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE - # we cannot fix further randomness caused by luatex; for further details, see - # https://salsa.debian.org/live-team/live-build/-/blob/master/examples/hooks/reproducible/2006-reproducible-texlive-binaries-fmt-files.hook.chroot#L52 - # note that calling faketime and fmtutil is fragile (faketime uses LD_PRELOAD, fmtutil calls /bin/sh, causing potential glibc issues on non-NixOS) - # so we patch fmtutil to use faketime, rather than calling faketime fmtutil - substitute "$TEXMFDIST"/scripts/texlive/fmtutil.pl fmtutil \ - --replace 'my $cmdline = "$eng -ini ' 'my $cmdline = "faketime -f '"'"'\@1980-01-01 00:00:00 x0.001'"'"' $eng -ini ' - FORCE_SOURCE_DATE=1 TZ= perl fmtutil --sys --all | grep '^fmtutil' # too verbose - - # Disable unavailable map files - echo y | updmap --sys --syncwithtrees --force 2>&1 | grep '^\(updmap\| /\)' - # Regenerate the map files (this is optional) - updmap --sys --force 2>&1 | grep '^\(updmap\| /\)' - - # sort entries to improve reproducibility - [[ -f "$TEXMFSYSCONFIG"/web2c/updmap.cfg ]] && sort -o "$TEXMFSYSCONFIG"/web2c/updmap.cfg "$TEXMFSYSCONFIG"/web2c/updmap.cfg - - mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" # to make sure (of what?) - '' + - # remove *-sys scripts since /nix/store is readonly - '' - rm "$out"/bin/*-sys - '' + - # TODO: a context trigger https://www.preining.info/blog/2015/06/debian-tex-live-2015-the-new-layout/ - # http://wiki.contextgarden.net/ConTeXt_Standalone#Unix-like_platforms_.28Linux.2FMacOS_X.2FFreeBSD.2FSolaris.29 - - # MkIV uses its own lookup mechanism and we need to initialize - # caches for it. - # We use faketime to fix the embedded timestamps and patch the uuids - # with some random but constant values. - '' - if [[ -e "$out/bin/mtxrun" ]]; then - substitute "$TEXMFDIST"/scripts/context/lua/mtxrun.lua mtxrun.lua \ - --replace 'cache_uuid=osuuid()' 'cache_uuid="e2402e51-133d-4c73-a278-006ea4ed734f"' \ - --replace 'uuid=osuuid(),' 'uuid="242be807-d17e-4792-8e39-aa93326fc871",' - FORCE_SOURCE_DATE=1 TZ= faketime -f '@1980-01-01 00:00:00 x0.001' luatex --luaonly mtxrun.lua --generate - fi - '' + - # Get rid of all log files. They are not needed, but take up space - # and render the build unreproducible by their embedded timestamps - # and other non-deterministic diagnostics. - '' - find "$TEXMFSYSVAR"/web2c -name '*.log' -delete - '' + - # link TEXMFDIST in $out/share for backward compatibility - '' - ln -s "$TEXMFDIST" "$out"/share/texmf - '' - ; -}).overrideAttrs (_: { allowSubstitutes = true; }) diff --git a/pkgs/tools/typesetting/tex/texlive/default.nix b/pkgs/tools/typesetting/tex/texlive/default.nix index 8b8dec2d001..82327d29709 100644 --- a/pkgs/tools/typesetting/tex/texlive/default.nix +++ b/pkgs/tools/typesetting/tex/texlive/default.nix @@ -2,7 +2,7 @@ - source: ../../../../../doc/languages-frameworks/texlive.xml - current html: https://nixos.org/nixpkgs/manual/#sec-language-texlive */ -{ stdenv, lib, fetchurl, runCommand, writeText, buildEnv +{ stdenv, lib, fetchurl, runCommand, writeShellScript, writeText, buildEnv , callPackage, ghostscript_headless, harfbuzz , makeWrapper, installShellFiles , python3, ruby, perl, tk, jdk, bash, snobol4 @@ -22,13 +22,6 @@ let tlpdb = overriddenTlpdb; }; - # function for creating a working environment from a set of TL packages - combine = import ./combine.nix { - inherit bin buildEnv lib makeWrapper writeText runCommand toTLPkgList - perl libfaketime makeFontsConf bash tl coreutils gawk gnugrep gnused; - ghostscript = ghostscript_headless; - }; - tlpdb = import ./tlpdb.nix; tlpdbVersion = tlpdb."00texlive.config"; @@ -101,6 +94,14 @@ let // lib.optionalAttrs (args ? deps) { deps = map (n: tl.${n}) (args.deps or [ ]); }) ) overriddenTlpdb; + # function for creating a working environment + buildTeXEnv = import ./build-tex-env.nix { + inherit bin tl; + ghostscript = ghostscript_headless; + inherit lib buildEnv libfaketime makeFontsConf makeWrapper runCommand + writeShellScript writeText toTLPkgSets bash perl coreutils gawk gnugrep gnused; + }; + ### texlive.combine compatibility layer: # convert TeX packages to { pkgs = [ ... ]; } lists # respecting specified outputs @@ -114,13 +115,84 @@ let lib.optional (drv ? out) (drv.out // { tlType = "bin"; }); tlOutToType = { out = "bin"; tex = "run"; texsource = "source"; texdoc = "doc"; tlpkg = "tlpkg"; }; + # convert { pkgs = [ ... ]; } lists to TeX packages + # possibly more than one, if pkgs is also used to specify dependencies + tlTypeToOut = { run = "tex"; doc = "texdoc"; source = "texsource"; bin = "out"; tlpkg = "tlpkg"; }; + toSpecifiedNV = p: rec { + name = value.tlOutputName; + value = builtins.removeAttrs p [ "pkgs" ] + // { outputSpecified = true; tlOutputName = tlTypeToOut.${p.tlType}; }; + }; + toTLPkgSet = pname: drvs: + let set = lib.listToAttrs (builtins.map toSpecifiedNV drvs); + mainDrv = set.out or set.tex or set.tlpkg or set.texdoc or set.texsource; in + builtins.removeAttrs mainDrv [ "outputSpecified" ]; + toTLPkgSets = { pkgs, ... }: lib.mapAttrsToList toTLPkgSet + (builtins.groupBy (p: p.pname) pkgs); + # export TeX packages as { pkgs = [ ... ]; } in the top attribute set allPkgLists = lib.mapAttrs (n: drv: { pkgs = toTLPkgList drv; }) tl; + # function for creating a working environment from a set of TL packages + # now a legacy wrapper around buildTeXEnv + combine = import ./combine-wrapper.nix { inherit buildTeXEnv lib toTLPkgList toTLPkgSets; }; + assertions = with lib; assertMsg (tlpdbVersion.year == version.texliveYear) "TeX Live year in texlive does not match tlpdb.nix, refusing to evaluate" && assertMsg (tlpdbVersion.frozen == version.final) "TeX Live final status in texlive does not match tlpdb.nix, refusing to evaluate"; + # Pre-defined evironment packages for TeX Live schemes, + # to make nix-env usage more comfortable and build selected on Hydra. + + # these license lists should be the sorted union of the licenses of the packages the schemes contain. + # The correctness of this collation is tested by tests.texlive.licenses + licenses = with lib.licenses; { + scheme-basic = [ free gfl gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; + scheme-context = [ bsd2 bsd3 cc-by-sa-40 free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 + lppl1 lppl13c mit ofl publicDomain x11 ]; + scheme-full = [ artistic1-cl8 artistic2 asl20 bsd2 bsd3 bsdOriginal cc-by-10 cc-by-40 cc-by-sa-10 cc-by-sa-20 + cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth + lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; + scheme-gust = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 + gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; + scheme-infraonly = [ gpl2 gpl2Plus lgpl21 ]; + scheme-medium = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only + free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl + publicDomain x11 ]; + scheme-minimal = [ free gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; + scheme-small = [ asl20 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth + lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; + scheme-tetex = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-10 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 + fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a + lppl13c mit ofl publicDomain x11]; + }; + + meta = { + description = "TeX Live environment"; + platforms = lib.platforms.all; + maintainers = with lib.maintainers; [ veprbl ]; + license = licenses.scheme-infraonly; + }; + + combined = recurseIntoAttrs ( + lib.genAttrs [ "scheme-basic" "scheme-context" "scheme-full" "scheme-gust" "scheme-infraonly" + "scheme-medium" "scheme-minimal" "scheme-small" "scheme-tetex" ] + (pname: + (buildTeXEnv { + __extraName = "combined" + lib.removePrefix "scheme" pname; + __extraVersion = with version; if final then "-final" else ".${year}${month}${day}"; + requiredTeXPackages = ps: [ ps.${pname} ]; + # to maintain full backward compatibility, enable texlive.combine behavior + __combine = true; + }).overrideAttrs { + meta = meta // { + description = "TeX Live environment for ${pname}"; + license = licenses.${pname}; + }; + } + ) + ); + in allPkgLists // { pkgs = tl; @@ -138,50 +210,8 @@ in combine = assert assertions; combine; - # Pre-defined combined packages for TeX Live schemes, - # to make nix-env usage more comfortable and build selected on Hydra. - combined = with lib; - let - # these license lists should be the sorted union of the licenses of the packages the schemes contain. - # The correctness of this collation is tested by tests.texlive.licenses - licenses = with lib.licenses; { - scheme-basic = [ free gfl gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; - scheme-context = [ bsd2 bsd3 cc-by-sa-40 free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 - lppl1 lppl13c mit ofl publicDomain x11 ]; - scheme-full = [ artistic1-cl8 artistic2 asl20 bsd2 bsd3 bsdOriginal cc-by-10 cc-by-40 cc-by-sa-10 cc-by-sa-20 - cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth - lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; - scheme-gust = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 - gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; - scheme-infraonly = [ gpl2 gpl2Plus lgpl21 ]; - scheme-medium = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only - free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl - publicDomain x11 ]; - scheme-minimal = [ free gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; - scheme-small = [ asl20 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth - lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; - scheme-tetex = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-10 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 - fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a - lppl13c mit ofl publicDomain x11]; - }; - in recurseIntoAttrs ( - mapAttrs - (pname: attrs: - addMetaAttrs rec { - description = "TeX Live environment for ${pname}"; - platforms = lib.platforms.all; - maintainers = with lib.maintainers; [ veprbl ]; - license = licenses.${pname}; - } - (combine { - ${pname} = attrs; - extraName = "combined" + lib.removePrefix "scheme" pname; - extraVersion = with version; if final then "-final" else ".${year}${month}${day}"; - }) - ) - { inherit (tl) - scheme-basic scheme-context scheme-full scheme-gust scheme-infraonly - scheme-medium scheme-minimal scheme-small scheme-tetex; - } - ); + combined = assert assertions; combined; + + # convenience alias + withPackages = (buildTeXEnv { }).withPackages; } -- cgit 1.4.1 From 80cd75f4cb07ab7b48e750b783be8eee721445f3 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sat, 4 Nov 2023 20:02:25 +0000 Subject: texlive: export schemes at top level --- pkgs/test/texlive/default.nix | 2 +- pkgs/tools/typesetting/tex/texlive/default.nix | 7 +++++++ pkgs/top-level/all-packages.nix | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 70813466882..db94d3070ca 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -623,7 +623,7 @@ rec { (savedLicensesAttrNames scheme) != (correctLicensesAttrNames scheme); incorrectSchemes = lib.filterAttrs (n: hasLicenseMismatch) - texlive.combined; + (texlive.combined // texlive.schemes); prettyPrint = name: scheme: '' license info for ${name} is incorrect! Note that order is enforced. diff --git a/pkgs/tools/typesetting/tex/texlive/default.nix b/pkgs/tools/typesetting/tex/texlive/default.nix index 11eeec0d5dd..bb505f4062b 100644 --- a/pkgs/tools/typesetting/tex/texlive/default.nix +++ b/pkgs/tools/typesetting/tex/texlive/default.nix @@ -194,6 +194,11 @@ let ) ); + schemes = lib.listToAttrs (map (s: { + name = "texlive" + s; + value = lib.addMetaAttrs { license = licenses.${"scheme-" + (lib.toLower s)}; } (buildTeXEnv { requiredTeXPackages = ps: [ ps.${"scheme-" + (lib.toLower s)} ]; }); + }) [ "Basic" "BookPub" "ConTeXt" "Full" "GUST" "InfraOnly" "Medium" "Minimal" "Small" "TeTeX" ]); + in allPkgLists // { pkgs = tl; @@ -213,6 +218,8 @@ in combined = assert assertions; combined; + inherit schemes; + # convenience alias withPackages = (buildTeXEnv { }).withPackages; } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index a6e9ae80df6..960184512ea 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -5446,6 +5446,7 @@ with pkgs; # TeX Live; see https://nixos.org/nixpkgs/manual/#sec-language-texlive texlive = recurseIntoAttrs (callPackage ../tools/typesetting/tex/texlive { }); + inherit (texlive.schemes) texliveBasic texliveBookPub texliveConTeXt texliveFull texliveGUST texliveInfraOnly texliveMedium texliveMinimal texliveSmall texliveTeTeX; fop = callPackage ../tools/typesetting/fop { jdk = openjdk8; -- cgit 1.4.1 From 9a5095a537c98b7c46584800c6f7ee141f9bbf78 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sat, 4 Nov 2023 20:02:26 +0000 Subject: tests.texlive: replace texlive.combine with texlive.withPackages --- pkgs/test/texlive/default.nix | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index db94d3070ca..6169de6d3d6 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, buildEnv, runCommand, fetchurl, file, texlive, writeShellScript, writeText }: +{ lib, stdenv, buildEnv, runCommand, fetchurl, file, texlive, writeShellScript, writeText, texliveInfraOnly, texliveSmall, texliveMedium, texliveFull }: rec { @@ -6,7 +6,7 @@ rec { { name , format , text - , texLive ? texlive.combined.scheme-small + , texLive ? texliveSmall , options ? "-interaction=errorstopmode" , preTest ? "" , postTest ? "" @@ -43,7 +43,7 @@ rec { lualatex = mkTeXTest { name = "opentype-fonts-lualatex"; format = "lualatex"; - texLive = texlive.combine { inherit (texlive) scheme-small libertinus-fonts; }; + texLive = texliveSmall.withPackages (ps: [ ps.libertinus-fonts ]); text = '' \documentclass{article} \usepackage{fontspec} @@ -61,7 +61,7 @@ rec { chktex = runCommand "texlive-test-chktex" { nativeBuildInputs = [ - (texlive.combine { inherit (texlive) scheme-infraonly chktex; }) + (texlive.withPackages (ps: [ ps.chktex ])) ]; input = builtins.toFile "chktex-sample.tex" '' \documentclass{article} @@ -77,7 +77,7 @@ rec { dvipng = lib.recurseIntoAttrs { # https://github.com/NixOS/nixpkgs/issues/75605 basic = runCommand "texlive-test-dvipng-basic" { - nativeBuildInputs = [ file texlive.combined.scheme-medium ]; + nativeBuildInputs = [ file texliveMedium ]; input = fetchurl { name = "test_dvipng.tex"; url = "http://git.savannah.nongnu.org/cgit/dvipng.git/plain/test_dvipng.tex?id=b872753590a18605260078f56cbd6f28d39dc035"; @@ -99,7 +99,7 @@ rec { # test dvipng's limited capability to render postscript specials via GS ghostscript = runCommand "texlive-test-ghostscript" { - nativeBuildInputs = [ file (texlive.combine { inherit (texlive) scheme-small dvipng; }) ]; + nativeBuildInputs = [ file (texliveSmall.withPackages (ps: [ ps.dvipng ])) ]; input = builtins.toFile "postscript-sample.tex" '' \documentclass{minimal} \begin{document} @@ -140,7 +140,7 @@ rec { # https://github.com/NixOS/nixpkgs/issues/75070 dvisvgm = runCommand "texlive-test-dvisvgm" { - nativeBuildInputs = [ file texlive.combined.scheme-medium ]; + nativeBuildInputs = [ file texliveMedium ]; input = builtins.toFile "dvisvgm-sample.tex" '' \documentclass{article} \begin{document} @@ -166,10 +166,7 @@ rec { texdoc = runCommand "texlive-test-texdoc" { nativeBuildInputs = [ - (texlive.combine { - inherit (texlive) scheme-infraonly luatex texdoc; - pkgFilter = pkg: lib.elem pkg.tlType [ "run" "bin" "doc" ]; - }) + (texlive.withPackages (ps: with ps; [ luatex ps.texdoc ps.texdoc.texdoc ])) ]; } '' texdoc --version @@ -214,7 +211,7 @@ rec { }; # check that all languages are available, including synonyms - allLanguages = let hyphenBase = lib.head texlive.hyphen-base.pkgs; texLive = texlive.combined.scheme-full; in + allLanguages = let hyphenBase = lib.head texlive.hyphen-base.pkgs; texLive = texliveFull; in lib.recurseIntoAttrs { # language.def etex = mkTeXTest { @@ -290,8 +287,8 @@ rec { # test that language files are generated as expected hyphen-base = runCommand "texlive-test-hyphen-base" { hyphenBase = lib.head texlive.hyphen-base.pkgs; - schemeFull = texlive.combined.scheme-full; - schemeInfraOnly = texlive.combined.scheme-infraonly; + schemeFull = texliveFull; + schemeInfraOnly = texliveInfraOnly; } '' mkdir -p "$out"/{scheme-infraonly,scheme-full} @@ -323,7 +320,7 @@ rec { # test that fmtutil.cnf is fully regenerated on scheme-full fmtutilCnf = runCommand "texlive-test-fmtutil.cnf" { kpathsea = lib.head texlive.kpathsea.pkgs; - schemeFull = texlive.combined.scheme-full; + schemeFull = texliveFull; } '' mkdir -p "$out" @@ -335,7 +332,7 @@ rec { # verify that the restricted mode gets enabled when # needed (detected by checking if it disallows --gscmd) repstopdf = runCommand "texlive-test-repstopdf" { - nativeBuildInputs = [ (texlive.combine { inherit (texlive) scheme-infraonly epstopdf; }) ]; + nativeBuildInputs = [ (texlive.withPackages (ps: [ ps.epstopdf ])) ]; } '' ! (epstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null (repstopdf --gscmd echo /dev/null 2>&1 || true) | grep forbidden >/dev/null @@ -345,7 +342,7 @@ rec { # verify that the restricted mode gets enabled when # needed (detected by checking if it disallows --gscmd) rpdfcrop = runCommand "texlive-test-rpdfcrop" { - nativeBuildInputs = [ (texlive.combine { inherit (texlive) scheme-infraonly pdfcrop; }) ]; + nativeBuildInputs = [ (texlive.withPackages (ps: [ ps.pdfcrop ])) ]; } '' ! (pdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null (rpdfcrop --gscmd echo $(command -v pdfcrop) 2>&1 || true) | grep 'restricted mode' >/dev/null @@ -460,7 +457,7 @@ rec { runCommand "texlive-test-binaries" { inherit binaries contextTestTex latexTestTex texTestTex; - texliveScheme = texlive.combined.scheme-full; + texliveScheme = texliveFull; } '' loadables="$(command -v bash)" -- cgit 1.4.1 From 13cb90b5be39b6939dbb01cc6666b0f5c9daa577 Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sat, 4 Nov 2023 20:02:26 +0000 Subject: tests.texlive: use texlive.pkgs.PKGNAME attribute set instead of texlive.PKGNAME.pkgs list --- pkgs/test/texlive/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index 6169de6d3d6..e4fdf91e941 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -211,7 +211,7 @@ rec { }; # check that all languages are available, including synonyms - allLanguages = let hyphenBase = lib.head texlive.hyphen-base.pkgs; texLive = texliveFull; in + allLanguages = let hyphenBase = texlive.pkgs.hyphen-base; texLive = texliveFull; in lib.recurseIntoAttrs { # language.def etex = mkTeXTest { @@ -286,7 +286,7 @@ rec { # test that language files are generated as expected hyphen-base = runCommand "texlive-test-hyphen-base" { - hyphenBase = lib.head texlive.hyphen-base.pkgs; + hyphenBase = texlive.pkgs.hyphen-base; schemeFull = texliveFull; schemeInfraOnly = texliveInfraOnly; } '' @@ -319,7 +319,7 @@ rec { # test that fmtutil.cnf is fully regenerated on scheme-full fmtutilCnf = runCommand "texlive-test-fmtutil.cnf" { - kpathsea = lib.head texlive.kpathsea.pkgs; + kpathsea = texlive.pkgs.kpathsea.tex; schemeFull = texliveFull; } '' mkdir -p "$out" -- cgit 1.4.1 From f5edeac421435433eb651ae520ae0b9994c2d07b Mon Sep 17 00:00:00 2001 From: Vincenzo Mantova <1962985+xworld21@users.noreply.github.com> Date: Sun, 5 Nov 2023 12:08:08 +0000 Subject: tests.texlive.fixedHashes: ignore .tex attribute sets that are not derivations --- pkgs/test/texlive/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pkgs/test/texlive') diff --git a/pkgs/test/texlive/default.nix b/pkgs/test/texlive/default.nix index e4fdf91e941..12fdd5c45f8 100644 --- a/pkgs/test/texlive/default.nix +++ b/pkgs/test/texlive/default.nix @@ -644,7 +644,7 @@ rec { # ease of testing fixedHashes = with lib; let fods = lib.concatMap - (p: lib.optional (p ? tex) p.tex + (p: lib.optional (p ? tex && isDerivation p.tex) p.tex ++ lib.optional (p ? texdoc) p.texdoc ++ lib.optional (p ? texsource) p.texsource ++ lib.optional (p ? tlpkg) p.tlpkg) -- cgit 1.4.1