Merge pull request #250805 from xworld21/texlive-buildenv-minimal

texlive: overrideTeXConfig/withPackages

authored by Dmitry Kalinkin and committed by GitHub ec2e217c f77fc56a

+823 -523
+18
doc/languages-frameworks/texlive.section.md
··· 38 38 39 39 - Note that the wrapper assumes that the result has a chance to be useful. For example, the core executables should be present, as well as some core data files. The supported way of ensuring this is by including some scheme, for example `scheme-basic`, into the combination. 40 40 41 + - TeX Live packages are also available under `texlive.pkgs` as derivations with outputs `out`, `tex`, `texdoc`, `texsource`, `tlpkg`, `man`, `info`. They cannot be installed outside of `texlive.combine` but are available for other uses. To repackage a font, for instance, use 42 + 43 + ```nix 44 + stdenvNoCC.mkDerivation rec { 45 + src = texlive.pkgs.iwona; 46 + 47 + inherit (src) pname version; 48 + 49 + installPhase = '' 50 + runHook preInstall 51 + install -Dm644 fonts/opentype/nowacki/iwona/*.otf -t $out/share/fonts/opentype 52 + runHook postInstall 53 + ''; 54 + } 55 + ``` 56 + 57 + See `biber`, `iwona` for complete examples. 58 + 41 59 ## Custom packages {#sec-language-texlive-custom-packages} 42 60 43 61 You may find that you need to use an external TeX package. A derivation for such package has to provide the contents of the "texmf" directory in its output and provide the appropriate `tlType` attribute (one of `"run"`, `"bin"`, `"doc"`, `"source"`). Dependencies on other TeX packages can be listed in the attribute `tlDeps`.
+4 -5
pkgs/data/fonts/iwona/default.nix
··· 1 1 { lib, stdenvNoCC, texlive }: 2 2 3 - stdenvNoCC.mkDerivation { 4 - pname = "iwona"; 5 - version = "0.995b"; 3 + stdenvNoCC.mkDerivation rec { 4 + inherit (src) pname version; 6 5 7 - src = lib.head (builtins.filter (p: p.tlType == "run") texlive.iwona.pkgs); 6 + src = texlive.pkgs.iwona; 8 7 9 8 installPhase = '' 10 9 runHook preInstall ··· 20 19 # "[...] GUST Font License (GFL), which is a free license, legally 21 20 # equivalent to the LaTeX Project Public # License (LPPL), version 1.3c or 22 21 # later." - GUST website 23 - license = licenses.lppl13c; 22 + license = src.meta.license; 24 23 maintainers = with maintainers; [ siddharthist ]; 25 24 platforms = platforms.all; 26 25 };
+10 -8
pkgs/misc/sagetex/default.nix
··· 1 1 { lib 2 2 , stdenv 3 3 , fetchFromGitHub 4 + , writeShellScript 4 5 , texlive 5 6 }: 6 7 7 - stdenv.mkDerivation (finalAttrs: rec { 8 + stdenv.mkDerivation rec { 8 9 pname = "sagetex"; 9 10 version = "3.6.1"; 10 11 ··· 15 16 sha256 = "sha256-OfhbXHbGI+DaDHqZCOGiSHJPHjGuT7ZqSEjKweloW38="; 16 17 }; 17 18 18 - buildInputs = [ 19 + outputs = [ "tex" ]; 20 + 21 + nativeBuildInputs = [ 19 22 texlive.combined.scheme-basic 23 + # multiple-outputs.sh fails if $out is not defined 24 + (writeShellScript "force-tex-output.sh" '' 25 + out="''${tex-}" 26 + '') 20 27 ]; 21 28 22 29 buildPhase = '' ··· 29 36 cp -va *.sty *.cfg *.def "$path/" 30 37 ''; 31 38 32 - passthru = { 33 - tlType = "run"; 34 - pkgs = [ finalAttrs.finalPackage ]; 35 - }; 36 - 37 39 meta = with lib; { 38 40 description = "Embed code, results of computations, and plots from Sage into LaTeX documents"; 39 41 homepage = "https://github.com/sagemath/sagetex"; ··· 41 43 maintainers = with maintainers; [ alexnortung ]; 42 44 platforms = platforms.all; 43 45 }; 44 - }) 46 + }
+10 -9
pkgs/test/texlive/default.nix
··· 454 454 ''; 455 455 456 456 # link all binaries in single derivation 457 - allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive))); 458 - binPackages = lib.filter (p: p.tlType == "bin") allPackages; 457 + binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs); 459 458 binaries = buildEnv { name = "texlive-binaries"; paths = binPackages; }; 460 459 in 461 460 runCommand "texlive-test-binaries" ··· 565 564 566 565 # check that all scripts have a Nix shebang 567 566 shebangs = let 568 - allPackages = with lib; concatLists (catAttrs "pkgs" (filter isAttrs (attrValues texlive))); 569 - binPackages = lib.filter (p: p.tlType == "bin") allPackages; 567 + binPackages = lib.catAttrs "out" (lib.attrValues texlive.pkgs); 570 568 in 571 569 runCommand "texlive-test-shebangs" { } 572 570 ('' ··· 615 613 correctLicenses = scheme: builtins.foldl' 616 614 (acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or []))) 617 615 [] 618 - scheme.passthru.packages; 616 + scheme.passthru.requiredTeXPackages; 619 617 correctLicensesAttrNames = scheme: 620 618 lib.sort lt 621 619 (map licenseToAttrName (correctLicenses scheme)); ··· 648 646 # this is effectively an eval-time assertion, converted into a derivation for 649 647 # ease of testing 650 648 fixedHashes = with lib; let 651 - combine = findFirst (p: (head p.pkgs).pname == "combine") { pkgs = []; } (head texlive.collection-latexextra.pkgs).tlDeps; 652 - all = concatLists (map (p: p.pkgs or []) (attrValues (removeAttrs texlive [ "bin" "combine" "combined" "tlpdb" ]))) ++ combine.pkgs; 653 - fods = filter (p: isDerivation p && p.tlType != "bin") all; 654 - errorText = concatMapStrings (p: optionalString (! p ? outputHash) "${p.pname + optionalString (p.tlType != "run") ("." + p.tlType)} does not have a fixed output hash\n") fods; 649 + fods = lib.concatMap 650 + (p: lib.optional (p ? tex) p.tex 651 + ++ lib.optional (p ? texdoc) p.texdoc 652 + ++ lib.optional (p ? texsource) p.texsource 653 + ++ lib.optional (p ? tlpkg) p.tlpkg) 654 + (attrValues texlive.pkgs); 655 + errorText = concatMapStrings (p: optionalString (! p ? outputHash) "${p.pname}-${p.tlOutputName} does not have a fixed output hash\n") fods; 655 656 in runCommand "texlive-test-fixed-hashes" { 656 657 inherit errorText; 657 658 passAsFile = [ "errorText" ];
+2 -3
pkgs/tools/typesetting/biber-ms/default.nix
··· 1 1 { lib, stdenv, fetchFromGitHub, fetchurl, perlPackages, shortenPerlShebang, texlive }: 2 2 3 3 let 4 - biberSource = lib.head (builtins.filter (p: p.tlType == "source") texlive.biber-ms.pkgs); 4 + biberSource = texlive.pkgs.biber-ms.texsource; 5 5 # missing test file 6 6 multiscriptBltxml = (fetchFromGitHub { 7 7 owner = "plk"; ··· 12 12 in 13 13 14 14 perlPackages.buildPerlModule { 15 - pname = "biber-ms"; 16 - inherit (biberSource) version; 15 + inherit (biberSource) pname version; 17 16 18 17 src = "${biberSource}/source/bibtex/biber-ms/biblatex-biber-ms.tar.gz"; 19 18
+2 -3
pkgs/tools/typesetting/biber/default.nix
··· 1 1 { lib, stdenv, fetchurl, perlPackages, shortenPerlShebang, texlive }: 2 2 3 3 let 4 - biberSource = lib.head (builtins.filter (p: p.tlType == "source") texlive.biber.pkgs); 4 + biberSource = texlive.pkgs.biber.texsource; 5 5 in 6 6 7 7 perlPackages.buildPerlModule { 8 - pname = "biber"; 9 - inherit (biberSource) version; 8 + inherit (biberSource) pname version; 10 9 11 10 src = "${biberSource}/source/bibtex/biber/biblatex-biber.tar.gz"; 12 11
+1 -5
pkgs/tools/typesetting/tex/mftrace/default.nix
··· 43 43 44 44 # experimental texlive.combine support 45 45 # (note that only the bin/ folder will be combined into texlive) 46 - passthru = { 47 - tlType = "bin"; 48 - tlDeps = with texlive; [ kpathsea t1utils metafont ]; 49 - pkgs = [ finalAttrs.finalPackage ]; 50 - }; 46 + passthru.tlDeps = with texlive; [ kpathsea t1utils metafont ]; 51 47 52 48 meta = with lib; { 53 49 description = "Scalable PostScript Fonts for MetaFont";
+2 -2
pkgs/tools/typesetting/tex/texlive/bin.nix
··· 355 355 inherit (src) version; 356 356 format = "other"; 357 357 358 - src = assertFixedHash pname (lib.head (builtins.filter (p: p.tlType == "run") texlive.pygmentex.pkgs)); 358 + src = assertFixedHash pname texlive.pkgs.pygmentex.tex; 359 359 360 360 propagatedBuildInputs = with python3Packages; [ pygments chardet ]; 361 361 ··· 436 436 437 437 xpdfopen = stdenv.mkDerivation { 438 438 pname = "texlive-xpdfopen.bin"; 439 - inherit (lib.head texlive.xpdfopen.pkgs) version; 439 + inherit (texlive.pkgs.xpdfopen) version; 440 440 441 441 inherit (common) src; 442 442
+434
pkgs/tools/typesetting/tex/texlive/build-tex-env.nix
··· 1 + { 2 + # texlive package set 3 + tl 4 + , bin 5 + 6 + , lib 7 + , buildEnv 8 + , libfaketime 9 + , makeFontsConf 10 + , makeWrapper 11 + , runCommand 12 + , writeShellScript 13 + , writeText 14 + , toTLPkgSets 15 + , bash 16 + , perl 17 + 18 + # common runtime dependencies 19 + , coreutils 20 + , gawk 21 + , gnugrep 22 + , gnused 23 + , ghostscript 24 + }: 25 + 26 + lib.fix (self: { 27 + withDocs ? false 28 + , withSources ? false 29 + , requiredTeXPackages ? ps: [ ps.scheme-infraonly ] 30 + 31 + ### texlive.combine backward compatibility 32 + , __extraName ? "combined" 33 + , __extraVersion ? "" 34 + # emulate the old texlive.combine (e.g. add man pages to main output) 35 + , __combine ? false 36 + # adjust behavior further if called from the texlive.combine wrapper 37 + , __fromCombineWrapper ? false 38 + }@args: 39 + 40 + let 41 + ### texlive.combine backward compatibility 42 + # if necessary, convert old style { pkgs = [ ... ]; } packages to attribute sets 43 + ensurePkgSets = ps: if ! __fromCombineWrapper && builtins.any (p: p ? pkgs && builtins.all (p: p ? tlType) p.pkgs) ps 44 + then let oldStyle = builtins.partition (p: p ? pkgs && builtins.all (p: p ? tlType) p.pkgs) ps; 45 + in oldStyle.wrong ++ lib.concatMap toTLPkgSets oldStyle.right 46 + else ps; 47 + 48 + pkgList = rec { 49 + # resolve dependencies of the packages that affect the runtime 50 + all = 51 + let 52 + # order of packages is irrelevant 53 + packages = builtins.sort (a: b: a.pname < b.pname) (ensurePkgSets (requiredTeXPackages tl)); 54 + runtime = builtins.partition 55 + (p: p.outputSpecified or false -> builtins.elem (p.tlOutputName or p.outputName) [ "out" "tex" "tlpkg" ]) 56 + packages; 57 + keySet = p: { 58 + key = ((p.name or "${p.pname}-${p.version}") + "-" + p.tlOutputName or p.outputName or ""); 59 + inherit p; 60 + tlDeps = p.tlDeps or (p.requiredTeXPackages or (_: [ ]) [ ]); 61 + }; 62 + in 63 + # texlive.combine: the wrapper already resolves all dependencies 64 + if __fromCombineWrapper then requiredTeXPackages null else 65 + builtins.catAttrs "p" (builtins.genericClosure { 66 + startSet = map keySet runtime.right; 67 + operator = p: map keySet p.tlDeps; 68 + }) ++ runtime.wrong; 69 + 70 + # group the specified outputs 71 + specified = builtins.partition (p: p.outputSpecified or false) all; 72 + specifiedOutputs = builtins.groupBy (p: p.tlOutputName or p.outputName) specified.right; 73 + otherOutputNames = builtins.catAttrs "key" (builtins.genericClosure { 74 + startSet = map (key: { inherit key; }) (lib.concatLists (builtins.catAttrs "outputs" specified.wrong)); 75 + operator = _: [ ]; 76 + }); 77 + otherOutputs = lib.genAttrs otherOutputNames (n: builtins.catAttrs n specified.wrong); 78 + outputsToInstall = builtins.catAttrs "key" (builtins.genericClosure { 79 + startSet = map (key: { inherit key; }) 80 + ([ "out" ] ++ lib.optional (splitOutputs ? man) "man" 81 + ++ lib.concatLists (builtins.catAttrs "outputsToInstall" (builtins.catAttrs "meta" specified.wrong))); 82 + operator = _: [ ]; 83 + }); 84 + 85 + # split binary and tlpkg from tex, texdoc, texsource 86 + bin = if __fromCombineWrapper 87 + then builtins.filter (p: p.tlType == "bin") all # texlive.combine: legacy filter 88 + else otherOutputs.out or [ ] ++ specifiedOutputs.out or [ ]; 89 + tlpkg = if __fromCombineWrapper 90 + then builtins.filter (p: p.tlType == "tlpkg") all # texlive.combine: legacy filter 91 + else otherOutputs.tlpkg or [ ] ++ specifiedOutputs.tlpkg or [ ]; 92 + 93 + nonbin = if __fromCombineWrapper then builtins.filter (p: p.tlType != "bin" && p.tlType != "tlpkg") all # texlive.combine: legacy filter 94 + else (if __combine then # texlive.combine: emulate old input ordering to avoid rebuilds 95 + lib.concatMap (p: lib.optional (p ? tex) p.tex 96 + ++ lib.optional ((withDocs || p ? man) && p ? texdoc) p.texdoc 97 + ++ lib.optional (withSources && p ? texsource) p.texsource) specified.wrong 98 + else otherOutputs.tex or [ ] 99 + ++ lib.optionals withDocs (otherOutputs.texdoc or [ ]) 100 + ++ lib.optionals withSources (otherOutputs.texsource or [ ])) 101 + ++ specifiedOutputs.tex or [ ] ++ specifiedOutputs.texdoc or [ ] ++ specifiedOutputs.texsource or [ ]; 102 + 103 + # outputs that do not become part of the environment 104 + nonEnvOutputs = lib.subtractLists [ "out" "tex" "texdoc" "texsource" "tlpkg" ] otherOutputNames; 105 + }; 106 + 107 + # list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts` 108 + # and `grep -IR rungs "$TEXMFDIST"` 109 + # and ignoring luatex, perl, and shell scripts (those must be patched using postFixup) 110 + needsGhostscript = lib.any (p: lib.elem p.pname [ "context" "dvipdfmx" "latex-papersize" "lyluatex" ]) pkgList.bin; 111 + 112 + name = if __combine then "texlive-${__extraName}-${bin.texliveYear}${__extraVersion}" # texlive.combine: old name name 113 + else "texlive-${bin.texliveYear}-env"; 114 + 115 + texmfdist = (buildEnv { 116 + name = "${name}-texmfdist"; 117 + 118 + # remove fake derivations (without 'outPath') to avoid undesired build dependencies 119 + paths = builtins.catAttrs "outPath" pkgList.nonbin; 120 + 121 + # mktexlsr 122 + nativeBuildInputs = [ tl."texlive.infra" ]; 123 + 124 + postBuild = # generate ls-R database 125 + '' 126 + mktexlsr "$out" 127 + ''; 128 + }).overrideAttrs (_: { allowSubstitutes = true; }); 129 + 130 + tlpkg = (buildEnv { 131 + name = "${name}-tlpkg"; 132 + 133 + # remove fake derivations (without 'outPath') to avoid undesired build dependencies 134 + paths = builtins.catAttrs "outPath" pkgList.tlpkg; 135 + }).overrideAttrs (_: { allowSubstitutes = true; }); 136 + 137 + # the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist 138 + # and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both) 139 + texmfroot = runCommand "${name}-texmfroot" { 140 + inherit texmfdist tlpkg; 141 + } '' 142 + mkdir -p "$out" 143 + ln -s "$texmfdist" "$out"/texmf-dist 144 + ln -s "$tlpkg" "$out"/tlpkg 145 + ''; 146 + 147 + # texlive.combine: expose info and man pages in usual /share/{info,man} location 148 + doc = buildEnv { 149 + name = "${name}-doc"; 150 + 151 + paths = [ (texmfdist.outPath + "/doc") ]; 152 + extraPrefix = "/share"; 153 + 154 + pathsToLink = [ 155 + "/info" 156 + "/man" 157 + ]; 158 + }; 159 + 160 + meta = { 161 + description = "TeX Live environment" 162 + + lib.optionalString withDocs " with documentation" 163 + + lib.optionalString (withDocs && withSources) " and" 164 + + lib.optionalString withSources " with sources"; 165 + platforms = lib.platforms.all; 166 + longDescription = "Contains the following packages and their transitive dependencies:\n - " 167 + + lib.concatMapStringsSep "\n - " 168 + (p: p.pname + (lib.optionalString (p.outputSpecified or false) " (${p.tlOutputName or p.outputName})")) 169 + (requiredTeXPackages tl); 170 + }; 171 + 172 + # emulate split output derivation 173 + splitOutputs = { 174 + out = out // { outputSpecified = true; }; 175 + texmfdist = texmfdist // { outputSpecified = true; }; 176 + texmfroot = texmfroot // { outputSpecified = true; }; 177 + } // (lib.genAttrs pkgList.nonEnvOutputs (outName: (buildEnv { 178 + inherit name; 179 + paths = builtins.catAttrs "outPath" 180 + (pkgList.otherOutputs.${outName} or [ ] ++ pkgList.specifiedOutputs.${outName} or [ ]); 181 + # force the output to be ${outName} or nix-env will not work 182 + nativeBuildInputs = [ (writeShellScript "force-output.sh" '' 183 + export out="''${${outName}-}" 184 + '') ]; 185 + inherit meta passthru; 186 + }).overrideAttrs { outputs = [ outName ]; } // { outputSpecified = true; })); 187 + 188 + passthru = lib.optionalAttrs (! __combine) (splitOutputs // { 189 + all = builtins.attrValues splitOutputs; 190 + outputs = [ "out" ] ++ pkgList.nonEnvOutputs; 191 + }) // { 192 + # This is set primarily to help find-tarballs.nix to do its job 193 + requiredTeXPackages = builtins.filter lib.isDerivation (pkgList.bin ++ pkgList.nonbin 194 + ++ lib.optionals (! __fromCombineWrapper) 195 + (lib.concatMap (n: (pkgList.otherOutputs.${n} or [ ] ++ pkgList.specifiedOutputs.${n} or [ ]))) pkgList.nonEnvOutputs); 196 + # useful for inclusion in the `fonts.packages` nixos option or for use in devshells 197 + fonts = "${texmfroot}/texmf-dist/fonts"; 198 + # support variants attrs, (prev: attrs) 199 + __overrideTeXConfig = newArgs: 200 + let appliedArgs = if builtins.isFunction newArgs then newArgs args else newArgs; in 201 + self (args // { __fromCombineWrapper = false; } // appliedArgs); 202 + withPackages = reqs: self (args // { requiredTeXPackages = ps: requiredTeXPackages ps ++ reqs ps; __fromCombineWrapper = false; }); 203 + }; 204 + 205 + out = (if (! __combine) 206 + # meta.outputsToInstall = [ "out" "man" ] is invalid within buildEnv: 207 + # checkMeta will notice that there is no actual "man" output, and fail 208 + # so we set outputsToInstall from the outside, where it is safe 209 + then lib.addMetaAttrs { inherit (pkgList) outputsToInstall; } 210 + else x: x) # texlive.combine: man pages used to be part of out 211 + # no indent for git diff purposes 212 + ((buildEnv { 213 + 214 + inherit name; 215 + 216 + ignoreCollisions = false; 217 + 218 + # remove fake derivations (without 'outPath') to avoid undesired build dependencies 219 + paths = builtins.catAttrs "outPath" pkgList.bin 220 + ++ lib.optional __combine doc; 221 + pathsToLink = [ 222 + "/" 223 + "/share/texmf-var/scripts" 224 + "/share/texmf-var/tex/generic/config" 225 + "/share/texmf-var/web2c" 226 + "/share/texmf-config" 227 + "/bin" # ensure these are writeable directories 228 + ]; 229 + 230 + nativeBuildInputs = [ 231 + makeWrapper 232 + libfaketime 233 + tl."texlive.infra" # mktexlsr 234 + tl.texlive-scripts # fmtutil, updmap 235 + tl.texlive-scripts-extra # texlinks 236 + perl 237 + ]; 238 + 239 + inherit meta passthru; 240 + 241 + postBuild = 242 + # environment variables (note: only export the ones that are used in the wrappers) 243 + '' 244 + TEXMFROOT="${texmfroot}" 245 + TEXMFDIST="${texmfdist}" 246 + export PATH="$out/bin:$PATH" 247 + TEXMFSYSCONFIG="$out/share/texmf-config" 248 + TEXMFSYSVAR="$out/share/texmf-var" 249 + export TEXMFCNF="$TEXMFSYSVAR/web2c" 250 + '' + 251 + # wrap executables with required env vars as early as possible 252 + # 1. we use the wrapped binaries in the scripts below, to catch bugs 253 + # 2. we do not want to wrap links generated by texlinks 254 + '' 255 + enable -f '${bash}/lib/bash/realpath' realpath 256 + declare -i wrapCount=0 257 + for link in "$out"/bin/*; do 258 + target="$(realpath "$link")" 259 + if [[ "''${target##*/}" != "''${link##*/}" ]] ; then 260 + # detected alias with different basename, use immediate target of $link to preserve $0 261 + # relevant for mktexfmt, repstopdf, ... 262 + target="$(readlink "$link")" 263 + fi 264 + 265 + rm "$link" 266 + makeWrapper "$target" "$link" \ 267 + --inherit-argv0 \ 268 + --prefix PATH : "${ 269 + # very common dependencies that are not detected by tests.texlive.binaries 270 + lib.makeBinPath ([ coreutils gawk gnugrep gnused ] ++ lib.optional needsGhostscript ghostscript)}:$out/bin" \ 271 + --set-default TEXMFCNF "$TEXMFCNF" \ 272 + --set-default FONTCONFIG_FILE "${ 273 + # necessary for XeTeX to find the fonts distributed with texlive 274 + makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; } 275 + }" 276 + wrapCount=$((wrapCount + 1)) 277 + done 278 + echo "wrapped $wrapCount binaries and scripts" 279 + '' + 280 + # patch texmf-dist -> $TEXMFDIST 281 + # patch texmf-local -> $out/share/texmf-local 282 + # patch texmf.cnf -> $TEXMFSYSVAR/web2c/texmf.cnf 283 + # TODO: perhaps do lua actions? 284 + # tried inspiration from install-tl, sub do_texmf_cnf 285 + '' 286 + mkdir -p "$TEXMFCNF" 287 + if [ -e "$TEXMFDIST/web2c/texmfcnf.lua" ]; then 288 + sed \ 289 + -e "s,\(TEXMFOS[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFROOT\",g" \ 290 + -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFDIST\",g" \ 291 + -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSVAR\",g" \ 292 + -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSCONFIG\",g" \ 293 + -e "s,\(TEXMFLOCAL[ ]*=[ ]*\)[^\,]*,\1\"$out/share/texmf-local\",g" \ 294 + -e "s,\$SELFAUTOLOC,$out,g" \ 295 + -e "s,selfautodir:/,$out/share/,g" \ 296 + -e "s,selfautodir:,$out/share/,g" \ 297 + -e "s,selfautoparent:/,$out/share/,g" \ 298 + -e "s,selfautoparent:,$out/share/,g" \ 299 + "$TEXMFDIST/web2c/texmfcnf.lua" > "$TEXMFCNF/texmfcnf.lua" 300 + fi 301 + 302 + sed \ 303 + -e "s,\(TEXMFROOT[ ]*=[ ]*\)[^\,]*,\1$TEXMFROOT,g" \ 304 + -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1$TEXMFDIST,g" \ 305 + -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSVAR,g" \ 306 + -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSCONFIG,g" \ 307 + -e "s,\$SELFAUTOLOC,$out,g" \ 308 + -e "s,\$SELFAUTODIR,$out/share,g" \ 309 + -e "s,\$SELFAUTOPARENT,$out/share,g" \ 310 + -e "s,\$SELFAUTOGRANDPARENT,$out/share,g" \ 311 + -e "/^mpost,/d" `# CVE-2016-10243` \ 312 + "$TEXMFDIST/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf" 313 + '' + 314 + # now filter hyphenation patterns and formats 315 + (let 316 + hyphens = lib.filter (p: p.hasHyphens or false && p.tlOutputName or p.outputName == "tex") pkgList.nonbin; 317 + hyphenPNames = map (p: p.pname) hyphens; 318 + formats = lib.filter (p: p ? formats && p.tlOutputName or p.outputName == "tex") pkgList.nonbin; 319 + formatPNames = map (p: p.pname) formats; 320 + # sed expression that prints the lines in /start/,/end/ except for /end/ 321 + section = start: end: "/${start}/,/${end}/{ /${start}/p; /${end}/!p; };\n"; 322 + script = 323 + writeText "hyphens.sed" ( 324 + # document how the file was generated (for language.dat) 325 + "1{ s/^(% Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; p; }\n" 326 + # pick up the header 327 + + "2,/^% from/{ /^% from/!p; };\n" 328 + # pick up all sections matching packages that we combine 329 + + lib.concatMapStrings (pname: section "^% from ${pname}:$" "^% from|^%%% No changes may be made beyond this point.$") hyphenPNames 330 + # pick up the footer (for language.def) 331 + + "/^%%% No changes may be made beyond this point.$/,$p;\n" 332 + ); 333 + scriptLua = 334 + writeText "hyphens.lua.sed" ( 335 + "1{ s/^(-- Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; p; }\n" 336 + + "2,/^-- END of language.us.lua/p;\n" 337 + + lib.concatMapStrings (pname: section "^-- from ${pname}:$" "^}$|^-- from") hyphenPNames 338 + + "$p;\n" 339 + ); 340 + # formats not being installed must be disabled by prepending #! (see man fmtutil) 341 + # sed expression that enables the formats in /start/,/end/ 342 + enableFormats = pname: "/^# from ${pname}:$/,/^# from/{ s/^#! //; };\n"; 343 + fmtutilSed = 344 + writeText "fmtutil.sed" ( 345 + # document how file was generated 346 + "1{ s/^(# Generated by .*)$/\\1, modified by ${if __combine then "texlive.combine" else "Nixpkgs"}/; }\n" 347 + # disable all formats, even those already disabled 348 + + "s/^([^#]|#! )/#! \\1/;\n" 349 + # enable the formats from the packages being installed 350 + + lib.concatMapStrings enableFormats formatPNames 351 + # clean up formats that have been disabled twice 352 + + "s/^#! #! /#! /;\n" 353 + ); 354 + in '' 355 + mkdir -p "$TEXMFSYSVAR/tex/generic/config" 356 + for fname in tex/generic/config/language.{dat,def}; do 357 + [[ -e "$TEXMFDIST/$fname" ]] && sed -E -n -f '${script}' "$TEXMFDIST/$fname" > "$TEXMFSYSVAR/$fname" 358 + done 359 + [[ -e "$TEXMFDIST"/tex/generic/config/language.dat.lua ]] && sed -E -n -f '${scriptLua}' \ 360 + "$TEXMFDIST"/tex/generic/config/language.dat.lua > "$TEXMFSYSVAR"/tex/generic/config/language.dat.lua 361 + [[ -e "$TEXMFDIST"/web2c/fmtutil.cnf ]] && sed -E -f '${fmtutilSed}' "$TEXMFDIST"/web2c/fmtutil.cnf > "$TEXMFCNF"/fmtutil.cnf 362 + 363 + # create $TEXMFSYSCONFIG database, make new $TEXMFSYSVAR files visible to kpathsea 364 + mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" 365 + '') + 366 + # generate format links (reads fmtutil.cnf to know which ones) *after* the wrappers have been generated 367 + '' 368 + texlinks --quiet "$out/bin" 369 + '' + 370 + # texlive postactions (see TeXLive::TLUtils::_do_postaction_script) 371 + (lib.concatMapStrings (pkg: '' 372 + postaction='${pkg.postactionScript}' 373 + case "$postaction" in 374 + *.pl) postInterp=perl ;; 375 + *.texlua) postInterp=texlua ;; 376 + *) postInterp= ;; 377 + esac 378 + echo "postaction install script for ${pkg.pname}: ''${postInterp:+$postInterp }$postaction install $TEXMFROOT" 379 + $postInterp "$TEXMFROOT/$postaction" install "$TEXMFROOT" 380 + '') (lib.filter (pkg: pkg ? postactionScript) pkgList.tlpkg)) + 381 + # generate formats 382 + '' 383 + # many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1 384 + # libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE 385 + # we cannot fix further randomness caused by luatex; for further details, see 386 + # https://salsa.debian.org/live-team/live-build/-/blob/master/examples/hooks/reproducible/2006-reproducible-texlive-binaries-fmt-files.hook.chroot#L52 387 + # note that calling faketime and fmtutil is fragile (faketime uses LD_PRELOAD, fmtutil calls /bin/sh, causing potential glibc issues on non-NixOS) 388 + # so we patch fmtutil to use faketime, rather than calling faketime fmtutil 389 + substitute "$TEXMFDIST"/scripts/texlive/fmtutil.pl fmtutil \ 390 + --replace 'my $cmdline = "$eng -ini ' 'my $cmdline = "faketime -f '"'"'\@1980-01-01 00:00:00 x0.001'"'"' $eng -ini ' 391 + FORCE_SOURCE_DATE=1 TZ= perl fmtutil --sys --all | grep '^fmtutil' # too verbose 392 + 393 + # Disable unavailable map files 394 + echo y | updmap --sys --syncwithtrees --force 2>&1 | grep '^\(updmap\| /\)' 395 + # Regenerate the map files (this is optional) 396 + updmap --sys --force 2>&1 | grep '^\(updmap\| /\)' 397 + 398 + # sort entries to improve reproducibility 399 + [[ -f "$TEXMFSYSCONFIG"/web2c/updmap.cfg ]] && sort -o "$TEXMFSYSCONFIG"/web2c/updmap.cfg "$TEXMFSYSCONFIG"/web2c/updmap.cfg 400 + 401 + mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" # to make sure (of what?) 402 + '' + 403 + # remove *-sys scripts since /nix/store is readonly 404 + '' 405 + rm "$out"/bin/*-sys 406 + '' + 407 + # TODO: a context trigger https://www.preining.info/blog/2015/06/debian-tex-live-2015-the-new-layout/ 408 + # http://wiki.contextgarden.net/ConTeXt_Standalone#Unix-like_platforms_.28Linux.2FMacOS_X.2FFreeBSD.2FSolaris.29 409 + 410 + # MkIV uses its own lookup mechanism and we need to initialize 411 + # caches for it. 412 + # We use faketime to fix the embedded timestamps and patch the uuids 413 + # with some random but constant values. 414 + '' 415 + if [[ -e "$out/bin/mtxrun" ]]; then 416 + substitute "$TEXMFDIST"/scripts/context/lua/mtxrun.lua mtxrun.lua \ 417 + --replace 'cache_uuid=osuuid()' 'cache_uuid="e2402e51-133d-4c73-a278-006ea4ed734f"' \ 418 + --replace 'uuid=osuuid(),' 'uuid="242be807-d17e-4792-8e39-aa93326fc871",' 419 + FORCE_SOURCE_DATE=1 TZ= faketime -f '@1980-01-01 00:00:00 x0.001' luatex --luaonly mtxrun.lua --generate 420 + fi 421 + '' + 422 + # Get rid of all log files. They are not needed, but take up space 423 + # and render the build unreproducible by their embedded timestamps 424 + # and other non-deterministic diagnostics. 425 + '' 426 + find "$TEXMFSYSVAR"/web2c -name '*.log' -delete 427 + '' + 428 + # link TEXMFDIST in $out/share for backward compatibility 429 + '' 430 + ln -s "$TEXMFDIST" "$out"/share/texmf 431 + '' 432 + ; 433 + }).overrideAttrs (_: { allowSubstitutes = true; })); 434 + in out)
+160 -97
pkgs/tools/typesetting/tex/texlive/build-texlive-package.nix
··· 15 15 , texliveBinaries 16 16 }: 17 17 18 + /* Convert an attribute set extracted from tlpdb.nix (with the deps attribute 19 + already processed) to a fake multi-output derivation with possible outputs 20 + [ "tex" "texdoc" "texsource" "tlpkg" "out" "man" "info" ] 21 + */ 22 + 23 + # TODO stabilise a generic interface decoupled from the finer details of the 24 + # translation from texlive.tlpdb to tlpdb.nix 18 25 { pname 19 26 , revision 20 27 , version ? toString revision 28 + , extraRevision ? "" 29 + , extraVersion ? "" 21 30 , sha512 22 31 , mirrors 23 - , extraVersion ? "" 24 32 , fixedHashes ? { } 25 33 , postUnpack ? "" 34 + , postFixup ? "" 26 35 , stripPrefix ? 1 27 36 , license ? [ ] 28 37 , hasHyphens ? false 38 + , hasInfo ? false 29 39 , hasManpages ? false 30 40 , hasRunfiles ? false 31 41 , hasTlpkg ? false ··· 34 44 }@args: 35 45 36 46 let 37 - meta = { license = map (x: lib.licenses.${x}) license; }; 47 + # common metadata 48 + name = "${pname}-${version}${extraVersion}"; 49 + meta = { 50 + license = map (x: lib.licenses.${x}) license; 51 + # TeX Live packages should not be installed directly into the user profile 52 + outputsToInstall = [ ]; 53 + }; 54 + 55 + hasBinfiles = args ? binfiles && args.binfiles != [ ]; 56 + hasDocfiles = sha512 ? doc; 57 + hasSource = sha512 ? source; 58 + 59 + # emulate drv.all, drv.outputs lists 60 + all = lib.optional hasBinfiles bin ++ 61 + lib.optional hasRunfiles tex ++ 62 + lib.optional hasDocfiles texdoc ++ 63 + lib.optional hasSource texsource ++ 64 + lib.optional hasTlpkg tlpkg ++ 65 + lib.optional hasManpages man ++ 66 + lib.optional hasInfo info; 67 + outputs = lib.catAttrs "tlOutputName" all; 38 68 39 - commonPassthru = { 40 - inherit pname revision version; 41 - } // lib.optionalAttrs (args ? extraRevision) { 42 - inherit (args) extraRevision; 43 - }; 69 + mainDrv = if hasBinfiles then bin 70 + else if hasRunfiles then tex 71 + else if hasTlpkg then tlpkg 72 + else if hasDocfiles then texdoc 73 + else if hasSource then texsource 74 + else tex; # fall back to attrset tex if there is no derivation 75 + 76 + # emulate multi-output derivation plus additional metadata 77 + # (out is handled in mkContainer) 78 + passthru = { 79 + inherit all outputs pname; 80 + revision = toString revision + extraRevision; 81 + version = version + extraVersion; 82 + outputSpecified = true; 83 + inherit tex; 84 + } // lib.optionalAttrs (args ? deps) { tlDeps = args.deps; } 85 + // lib.optionalAttrs (args ? formats) { inherit (args) formats; } 86 + // lib.optionalAttrs hasHyphens { inherit hasHyphens; } 87 + // lib.optionalAttrs (args ? postactionScript) { inherit (args) postactionScript; } 88 + // lib.optionalAttrs hasDocfiles { texdoc = texdoc; } 89 + // lib.optionalAttrs hasSource { texsource = texsource; } 90 + // lib.optionalAttrs hasTlpkg { tlpkg = tlpkg; } 91 + // lib.optionalAttrs hasManpages { man = man; } 92 + // lib.optionalAttrs hasInfo { info = info; }; 44 93 45 94 # build run, doc, source, tlpkg containers 46 - mkContainer = tlType: passthru: sha512: 95 + mkContainer = tlType: tlOutputName: sha512: 47 96 let 48 - # NOTE: the fixed naming scheme must match generated-fixed-hashes.nix 97 + fixedHash = fixedHashes.${tlType} or null; # be graceful about missing hashes 49 98 # the basename used by upstream (without ".tar.xz" suffix) 99 + # tlpkg is not a true container but a subfolder of the run container 50 100 urlName = pname + (lib.optionalString (tlType != "run" && tlType != "tlpkg") ".${tlType}"); 51 - # name + version for the derivation 52 - tlName = urlName + (lib.optionalString (tlType == "tlpkg") ".tlpkg") + "-${version}${extraVersion}"; 53 - fixedHash = fixedHashes.${tlType} or null; # be graceful about missing hashes 54 - 55 - urls = args.urls or (if args ? url then [ args.url ] else 56 - map (up: "${up}/archive/${urlName}.r${toString revision}.tar.xz") mirrors); 101 + urls = map (up: "${up}/archive/${urlName}.r${toString revision}.tar.xz") mirrors; 102 + # TODO switch to simpler "${name}-${tlOutputName}" (requires new fixed hashes) 103 + container = runCommand "texlive-${pname}${lib.optionalString (tlType != "run") ".${tlType}"}-${version}${extraVersion}" 104 + ({ 105 + src = fetchurl { inherit urls sha512; }; 106 + # save outputName as fixed output derivations cannot change nor override outputName 107 + passthru = passthru // { inherit tlOutputName; }; 108 + # TODO remove tlType from derivation (requires a rebuild) 109 + inherit meta stripPrefix tlType; 110 + } // lib.optionalAttrs (fixedHash != null) { 111 + outputHash = fixedHash; 112 + outputHashAlgo = "sha256"; 113 + outputHashMode = "recursive"; 114 + }) 115 + ('' 116 + mkdir "$out" 117 + if [[ "$tlType" == "tlpkg" ]]; then 118 + tar -xf "$src" \ 119 + --strip-components=1 \ 120 + -C "$out" --anchored --exclude=tlpkg/tlpobj --keep-old-files \ 121 + tlpkg 122 + else 123 + tar -xf "$src" \ 124 + --strip-components="$stripPrefix" \ 125 + -C "$out" --anchored --exclude=tlpkg --keep-old-files 126 + fi 127 + '' + postUnpack); 57 128 in 58 - runCommand "texlive-${tlName}" 59 - ({ 60 - src = fetchurl { inherit urls sha512; }; 61 - inherit meta passthru stripPrefix tlType; 62 - } // lib.optionalAttrs (fixedHash != null) { 63 - outputHash = fixedHash; 64 - outputHashAlgo = "sha256"; 65 - outputHashMode = "recursive"; 66 - }) 67 - ('' 68 - mkdir "$out" 69 - if [[ "$tlType" == "tlpkg" ]]; then 70 - tar -xf "$src" \ 71 - --strip-components=1 \ 72 - -C "$out" --anchored --exclude=tlpkg/tlpobj --keep-old-files \ 73 - tlpkg 74 - else 75 - tar -xf "$src" \ 76 - --strip-components="$stripPrefix" \ 77 - -C "$out" --anchored --exclude=tlpkg --keep-old-files 78 - fi 79 - '' + postUnpack); 129 + # remove the standard drv.out, optionally replace it with the bin container 130 + builtins.removeAttrs container [ "out" ] // lib.optionalAttrs hasBinfiles { out = bin; }; 131 + 132 + tex = 133 + if hasRunfiles then mkContainer "run" "tex" sha512.run 134 + else passthru 135 + // { inherit meta; tlOutputName = "tex"; } 136 + // lib.optionalAttrs hasBinfiles { out = bin; }; 137 + 138 + texdoc = mkContainer "doc" "texdoc" sha512.doc; 139 + 140 + texsource = mkContainer "source" "texsource" sha512.source; 80 141 81 - tex = [ 82 - ( 83 - let passthru = commonPassthru 84 - // lib.optionalAttrs (args ? deps) { tlDeps = args.deps; } 85 - // lib.optionalAttrs (args ? formats) { inherit (args) formats; } 86 - // lib.optionalAttrs hasHyphens { inherit hasHyphens; }; in 87 - if hasRunfiles then mkContainer "run" passthru sha512.run 88 - else (passthru // { tlType = "run"; }) 89 - ) 90 - ]; 142 + tlpkg = mkContainer "tlpkg" "tlpkg" sha512.run; 91 143 92 - doc = let passthru = commonPassthru 93 - // lib.optionalAttrs hasManpages { inherit hasManpages; }; in 94 - lib.optional (sha512 ? doc) (mkContainer "doc" passthru sha512.doc); 144 + # build bin container 145 + extToInput = { 146 + # find interpreters for the script extensions found in tlpdb 147 + jar = jdk; 148 + lua = texliveBinaries.luatex; 149 + py = python3; 150 + rb = ruby; 151 + sno = snobol4; 152 + tcl = tk; 153 + texlua = texliveBinaries.luatex; 154 + tlu = texliveBinaries.luatex; 155 + }; 95 156 96 - source = lib.optional (sha512 ? source) (mkContainer "source" commonPassthru sha512.source); 157 + # TODO switch to simpler "${name}" (requires a rebuild) 158 + bin = runCommand "texlive-${pname}.bin-${version}" 159 + { 160 + inherit meta; 161 + passthru = passthru // { tlOutputName = "out"; }; 162 + # shebang interpreters 163 + buildInputs =let outName = builtins.replaceStrings [ "-" ] [ "_" ] pname; in 164 + [ texliveBinaries.core.${outName} or null 165 + texliveBinaries.${pname} or null 166 + texliveBinaries.core-big.${outName} or null ] 167 + ++ (args.extraBuildInputs or [ ]) ++ [ bash perl ] 168 + ++ (lib.attrVals (args.scriptExts or [ ]) extToInput); 169 + nativeBuildInputs = extraNativeBuildInputs; 170 + # absolute scripts folder 171 + scriptsFolder = lib.optionalString (tex ? outPath) (tex.outPath + "/scripts/" + args.scriptsFolder or pname); 172 + # binaries info 173 + inherit (args) binfiles; 174 + binlinks = builtins.attrNames (args.binlinks or { }); 175 + bintargets = builtins.attrValues (args.binlinks or { }); 176 + # build scripts 177 + patchScripts = ./patch-scripts.sed; 178 + makeBinContainers = ./make-bin-containers.sh; 179 + } 180 + '' 181 + . "$makeBinContainers" 182 + ${args.postFixup or ""} 183 + ''; 97 184 98 - tlpkg = let passthru = commonPassthru 99 - // lib.optionalAttrs (args ? postactionScript) { postactionScript = args.postactionScript; }; in 100 - lib.optional hasTlpkg (mkContainer "tlpkg" passthru sha512.run); 185 + # build man, info containers 186 + # TODO switch to simpler "${name}-man" (requires a rebuild) 187 + man = builtins.removeAttrs (runCommand "texlive-${pname}.man-${version}${extraVersion}" 188 + { 189 + inherit meta texdoc; 190 + passthru = passthru // { tlOutputName = "man"; }; 191 + } 192 + '' 193 + mkdir -p "$out"/share 194 + ln -s {"$texdoc"/doc,"$out"/share}/man 195 + '') [ "out" ] // lib.optionalAttrs hasBinfiles { out = bin; }; 101 196 102 - bin = lib.optional (args ? binfiles && args.binfiles != [ ]) ( 103 - let 104 - # find interpreters for the script extensions found in tlpdb 105 - extToInput = { 106 - jar = jdk; 107 - lua = texliveBinaries.luatex; 108 - py = python3; 109 - rb = ruby; 110 - sno = snobol4; 111 - tcl = tk; 112 - texlua = texliveBinaries.luatex; 113 - tlu = texliveBinaries.luatex; 114 - }; 115 - run = lib.head tex; 116 - in 117 - runCommand "texlive-${pname}.bin-${version}" 118 - { 119 - passthru = commonPassthru // { tlType = "bin"; }; 120 - inherit meta; 121 - # shebang interpreters and compiled binaries 122 - buildInputs = let outName = builtins.replaceStrings [ "-" ] [ "_" ] pname; in 123 - [ texliveBinaries.core.${outName} or null 124 - texliveBinaries.${pname} or null 125 - texliveBinaries.core-big.${outName} or null ] 126 - ++ (args.extraBuildInputs or [ ]) ++ [ bash perl ] 127 - ++ (lib.attrVals (args.scriptExts or [ ]) extToInput); 128 - nativeBuildInputs = extraNativeBuildInputs; 129 - # absolute scripts folder 130 - scriptsFolder = lib.optionalString (run ? outPath) (run.outPath + "/scripts/" + args.scriptsFolder or pname); 131 - # binaries info 132 - inherit (args) binfiles; 133 - binlinks = builtins.attrNames (args.binlinks or { }); 134 - bintargets = builtins.attrValues (args.binlinks or { }); 135 - # build scripts 136 - patchScripts = ./patch-scripts.sed; 137 - makeBinContainers = ./make-bin-containers.sh; 138 - } 139 - '' 140 - . "$makeBinContainers" 141 - ${args.postFixup or ""} 142 - '' 143 - ); 197 + # TODO switch to simpler "${name}-info" (requires a rebuild) 198 + info = builtins.removeAttrs (runCommand "texlive-${pname}.info-${version}${extraVersion}" 199 + { 200 + inherit meta texdoc; 201 + passthru = passthru // { tlOutputName = "info"; }; 202 + } 203 + '' 204 + mkdir -p "$out"/share 205 + ln -s {"$texdoc"/doc,"$out"/share}/info 206 + '') [ "out" ] // lib.optionalAttrs hasBinfiles { out = bin; }; 144 207 in 145 - { pkgs = tex ++ doc ++ source ++ tlpkg ++ bin; } 208 + builtins.removeAttrs mainDrv [ "outputSpecified" ]
+42
pkgs/tools/typesetting/tex/texlive/combine-wrapper.nix
··· 1 + # legacy texlive.combine wrapper 2 + { lib, toTLPkgList, toTLPkgSets, buildTeXEnv }: 3 + args@{ 4 + pkgFilter ? (pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.pname == "core" 5 + || pkg.hasManpages or false) 6 + , extraName ? "combined" 7 + , extraVersion ? "" 8 + , ... 9 + }: 10 + let 11 + pkgSet = removeAttrs args [ "pkgFilter" "extraName" "extraVersion" ]; 12 + 13 + # combine a set of TL packages into a single TL meta-package 14 + combinePkgs = pkgList: lib.catAttrs "pkg" ( 15 + let 16 + # a TeX package used to be an attribute set { pkgs = [ ... ]; ... } where pkgs is a list of derivations 17 + # the derivations make up the TeX package and optionally (for backward compatibility) its dependencies 18 + tlPkgToSets = drv: map ({ tlType, version ? "", outputName ? "", ... }@pkg: { 19 + # outputName required to distinguish among bin.core-big outputs 20 + key = "${pkg.pname or pkg.name}.${tlType}-${version}-${outputName}"; 21 + inherit pkg; 22 + }) (drv.pkgs or (toTLPkgList drv)); 23 + pkgListToSets = lib.concatMap tlPkgToSets; in 24 + builtins.genericClosure { 25 + startSet = pkgListToSets pkgList; 26 + operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or []); 27 + }); 28 + combined = combinePkgs (lib.attrValues pkgSet); 29 + 30 + # convert to specified outputs 31 + tlTypeToOut = { run = "tex"; doc = "texdoc"; source = "texsource"; bin = "out"; tlpkg = "tlpkg"; }; 32 + toSpecified = { tlType, ... }@drv: drv // { outputSpecified = true; tlOutputName = tlTypeToOut.${tlType}; }; 33 + all = lib.filter pkgFilter combined ++ lib.filter (pkg: pkg.tlType == "tlpkg") combined; 34 + converted = builtins.map toSpecified all; 35 + in 36 + buildTeXEnv { 37 + __extraName = extraName; 38 + __extraVersion = extraVersion; 39 + requiredTeXPackages = _: converted; 40 + __combine = true; 41 + __fromCombineWrapper = true; 42 + }
-315
pkgs/tools/typesetting/tex/texlive/combine.nix
··· 1 - { lib, buildEnv, runCommand, writeText, makeWrapper, libfaketime, makeFontsConf 2 - , perl, bash, coreutils, gnused, gnugrep, gawk, ghostscript 3 - , bin, tl }: 4 - # combine = 5 - args@{ 6 - pkgFilter ? (pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.pname == "core" 7 - || pkg.hasManpages or false) 8 - , extraName ? "combined" 9 - , extraVersion ? "" 10 - , ... 11 - }: 12 - let 13 - # combine a set of TL packages into a single TL meta-package 14 - combinePkgs = pkgList: lib.catAttrs "pkg" ( 15 - let 16 - # a TeX package is an attribute set { pkgs = [ ... ]; ... } where pkgs is a list of derivations 17 - # the derivations make up the TeX package and optionally (for backward compatibility) its dependencies 18 - tlPkgToSets = { pkgs, ... }: map ({ tlType, version ? "", outputName ? "", ... }@pkg: { 19 - # outputName required to distinguish among bin.core-big outputs 20 - key = "${pkg.pname or pkg.name}.${tlType}-${version}-${outputName}"; 21 - inherit pkg; 22 - }) pkgs; 23 - pkgListToSets = lib.concatMap tlPkgToSets; in 24 - builtins.genericClosure { 25 - startSet = pkgListToSets pkgList; 26 - operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or []); 27 - }); 28 - 29 - pkgSet = removeAttrs args [ "pkgFilter" "extraName" "extraVersion" ]; 30 - pkgList = rec { 31 - combined = combinePkgs (lib.attrValues pkgSet); 32 - all = lib.filter pkgFilter combined; 33 - splitBin = builtins.partition (p: p.tlType == "bin") all; 34 - bin = splitBin.right; 35 - nonbin = splitBin.wrong; 36 - tlpkg = lib.filter (pkg: pkg.tlType == "tlpkg") combined; 37 - }; 38 - # list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts` 39 - # and `grep -IR rungs "$TEXMFDIST"` 40 - # and ignoring luatex, perl, and shell scripts (those must be patched using postFixup) 41 - needsGhostscript = lib.any (p: lib.elem p.pname [ "context" "dvipdfmx" "latex-papersize" "lyluatex" ]) pkgList.bin; 42 - 43 - name = "texlive-${extraName}-${bin.texliveYear}${extraVersion}"; 44 - 45 - texmfdist = (buildEnv { 46 - name = "${name}-texmfdist"; 47 - 48 - # remove fake derivations (without 'outPath') to avoid undesired build dependencies 49 - paths = lib.catAttrs "outPath" pkgList.nonbin; 50 - 51 - # mktexlsr 52 - nativeBuildInputs = [ (lib.last tl."texlive.infra".pkgs) ]; 53 - 54 - postBuild = # generate ls-R database 55 - '' 56 - mktexlsr "$out" 57 - ''; 58 - }).overrideAttrs (_: { allowSubstitutes = true; }); 59 - 60 - tlpkg = (buildEnv { 61 - name = "${name}-tlpkg"; 62 - 63 - # remove fake derivations (without 'outPath') to avoid undesired build dependencies 64 - paths = lib.catAttrs "outPath" pkgList.tlpkg; 65 - }).overrideAttrs (_: { allowSubstitutes = true; }); 66 - 67 - # the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist 68 - # and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both) 69 - texmfroot = runCommand "${name}-texmfroot" { 70 - inherit texmfdist tlpkg; 71 - } '' 72 - mkdir -p "$out" 73 - ln -s "$texmfdist" "$out"/texmf-dist 74 - ln -s "$tlpkg" "$out"/tlpkg 75 - ''; 76 - 77 - # expose info and man pages in usual /share/{info,man} location 78 - doc = buildEnv { 79 - name = "${name}-doc"; 80 - 81 - paths = [ (texmfdist.outPath + "/doc") ]; 82 - extraPrefix = "/share"; 83 - 84 - pathsToLink = [ 85 - "/info" 86 - "/man" 87 - ]; 88 - }; 89 - 90 - in (buildEnv { 91 - 92 - inherit name; 93 - 94 - ignoreCollisions = false; 95 - 96 - # remove fake derivations (without 'outPath') to avoid undesired build dependencies 97 - paths = lib.catAttrs "outPath" pkgList.bin ++ [ doc ]; 98 - pathsToLink = [ 99 - "/" 100 - "/share/texmf-var/scripts" 101 - "/share/texmf-var/tex/generic/config" 102 - "/share/texmf-var/web2c" 103 - "/share/texmf-config" 104 - "/bin" # ensure these are writeable directories 105 - ]; 106 - 107 - nativeBuildInputs = [ 108 - makeWrapper 109 - libfaketime 110 - (lib.last tl."texlive.infra".pkgs) # mktexlsr 111 - (lib.last tl.texlive-scripts.pkgs) # fmtutil, updmap 112 - (lib.last tl.texlive-scripts-extra.pkgs) # texlinks 113 - perl 114 - ]; 115 - 116 - passthru = { 117 - # This is set primarily to help find-tarballs.nix to do its job 118 - packages = pkgList.all; 119 - # useful for inclusion in the `fonts.packages` nixos option or for use in devshells 120 - fonts = "${texmfroot}/texmf-dist/fonts"; 121 - }; 122 - 123 - postBuild = 124 - # environment variables (note: only export the ones that are used in the wrappers) 125 - '' 126 - TEXMFROOT="${texmfroot}" 127 - TEXMFDIST="${texmfdist}" 128 - export PATH="$out/bin:$PATH" 129 - TEXMFSYSCONFIG="$out/share/texmf-config" 130 - TEXMFSYSVAR="$out/share/texmf-var" 131 - export TEXMFCNF="$TEXMFSYSVAR/web2c" 132 - '' + 133 - # wrap executables with required env vars as early as possible 134 - # 1. we want texlive.combine to use the wrapped binaries, to catch bugs 135 - # 2. we do not want to wrap links generated by texlinks 136 - '' 137 - enable -f '${bash}/lib/bash/realpath' realpath 138 - declare -i wrapCount=0 139 - for link in "$out"/bin/*; do 140 - target="$(realpath "$link")" 141 - if [[ "''${target##*/}" != "''${link##*/}" ]] ; then 142 - # detected alias with different basename, use immediate target of $link to preserve $0 143 - # relevant for mktexfmt, repstopdf, ... 144 - target="$(readlink "$link")" 145 - fi 146 - 147 - rm "$link" 148 - makeWrapper "$target" "$link" \ 149 - --inherit-argv0 \ 150 - --prefix PATH : "${ 151 - # very common dependencies that are not detected by tests.texlive.binaries 152 - lib.makeBinPath ([ coreutils gawk gnugrep gnused ] ++ lib.optional needsGhostscript ghostscript)}:$out/bin" \ 153 - --set-default TEXMFCNF "$TEXMFCNF" \ 154 - --set-default FONTCONFIG_FILE "${ 155 - # necessary for XeTeX to find the fonts distributed with texlive 156 - makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; } 157 - }" 158 - wrapCount=$((wrapCount + 1)) 159 - done 160 - echo "wrapped $wrapCount binaries and scripts" 161 - '' + 162 - # patch texmf-dist -> $TEXMFDIST 163 - # patch texmf-local -> $out/share/texmf-local 164 - # patch texmf.cnf -> $TEXMFSYSVAR/web2c/texmf.cnf 165 - # TODO: perhaps do lua actions? 166 - # tried inspiration from install-tl, sub do_texmf_cnf 167 - '' 168 - mkdir -p "$TEXMFCNF" 169 - if [ -e "$TEXMFDIST/web2c/texmfcnf.lua" ]; then 170 - sed \ 171 - -e "s,\(TEXMFOS[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFROOT\",g" \ 172 - -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFDIST\",g" \ 173 - -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSVAR\",g" \ 174 - -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSCONFIG\",g" \ 175 - -e "s,\(TEXMFLOCAL[ ]*=[ ]*\)[^\,]*,\1\"$out/share/texmf-local\",g" \ 176 - -e "s,\$SELFAUTOLOC,$out,g" \ 177 - -e "s,selfautodir:/,$out/share/,g" \ 178 - -e "s,selfautodir:,$out/share/,g" \ 179 - -e "s,selfautoparent:/,$out/share/,g" \ 180 - -e "s,selfautoparent:,$out/share/,g" \ 181 - "$TEXMFDIST/web2c/texmfcnf.lua" > "$TEXMFCNF/texmfcnf.lua" 182 - fi 183 - 184 - sed \ 185 - -e "s,\(TEXMFROOT[ ]*=[ ]*\)[^\,]*,\1$TEXMFROOT,g" \ 186 - -e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1$TEXMFDIST,g" \ 187 - -e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSVAR,g" \ 188 - -e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSCONFIG,g" \ 189 - -e "s,\$SELFAUTOLOC,$out,g" \ 190 - -e "s,\$SELFAUTODIR,$out/share,g" \ 191 - -e "s,\$SELFAUTOPARENT,$out/share,g" \ 192 - -e "s,\$SELFAUTOGRANDPARENT,$out/share,g" \ 193 - -e "/^mpost,/d" `# CVE-2016-10243` \ 194 - "$TEXMFDIST/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf" 195 - '' + 196 - # now filter hyphenation patterns and formats 197 - (let 198 - hyphens = lib.filter (p: p.hasHyphens or false && p.tlType == "run") pkgList.splitBin.wrong; 199 - hyphenPNames = map (p: p.pname) hyphens; 200 - formats = lib.filter (p: p ? formats && p.tlType == "run") pkgList.splitBin.wrong; 201 - formatPNames = map (p: p.pname) formats; 202 - # sed expression that prints the lines in /start/,/end/ except for /end/ 203 - section = start: end: "/${start}/,/${end}/{ /${start}/p; /${end}/!p; };\n"; 204 - script = 205 - writeText "hyphens.sed" ( 206 - # document how the file was generated (for language.dat) 207 - "1{ s/^(% Generated by .*)$/\\1, modified by texlive.combine/; p; }\n" 208 - # pick up the header 209 - + "2,/^% from/{ /^% from/!p; };\n" 210 - # pick up all sections matching packages that we combine 211 - + lib.concatMapStrings (pname: section "^% from ${pname}:$" "^% from|^%%% No changes may be made beyond this point.$") hyphenPNames 212 - # pick up the footer (for language.def) 213 - + "/^%%% No changes may be made beyond this point.$/,$p;\n" 214 - ); 215 - scriptLua = 216 - writeText "hyphens.lua.sed" ( 217 - "1{ s/^(-- Generated by .*)$/\\1, modified by texlive.combine/; p; }\n" 218 - + "2,/^-- END of language.us.lua/p;\n" 219 - + lib.concatMapStrings (pname: section "^-- from ${pname}:$" "^}$|^-- from") hyphenPNames 220 - + "$p;\n" 221 - ); 222 - # formats not being installed must be disabled by prepending #! (see man fmtutil) 223 - # sed expression that enables the formats in /start/,/end/ 224 - enableFormats = pname: "/^# from ${pname}:$/,/^# from/{ s/^#! //; };\n"; 225 - fmtutilSed = 226 - writeText "fmtutil.sed" ( 227 - # document how file was generated 228 - "1{ s/^(# Generated by .*)$/\\1, modified by texlive.combine/; }\n" 229 - # disable all formats, even those already disabled 230 - + "s/^([^#]|#! )/#! \\1/;\n" 231 - # enable the formats from the packages being installed 232 - + lib.concatMapStrings enableFormats formatPNames 233 - # clean up formats that have been disabled twice 234 - + "s/^#! #! /#! /;\n" 235 - ); 236 - in '' 237 - mkdir -p "$TEXMFSYSVAR/tex/generic/config" 238 - for fname in tex/generic/config/language.{dat,def}; do 239 - [[ -e "$TEXMFDIST/$fname" ]] && sed -E -n -f '${script}' "$TEXMFDIST/$fname" > "$TEXMFSYSVAR/$fname" 240 - done 241 - [[ -e "$TEXMFDIST"/tex/generic/config/language.dat.lua ]] && sed -E -n -f '${scriptLua}' \ 242 - "$TEXMFDIST"/tex/generic/config/language.dat.lua > "$TEXMFSYSVAR"/tex/generic/config/language.dat.lua 243 - [[ -e "$TEXMFDIST"/web2c/fmtutil.cnf ]] && sed -E -f '${fmtutilSed}' "$TEXMFDIST"/web2c/fmtutil.cnf > "$TEXMFCNF"/fmtutil.cnf 244 - 245 - # create $TEXMFSYSCONFIG database, make new $TEXMFSYSVAR files visible to kpathsea 246 - mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" 247 - '') + 248 - # generate format links (reads fmtutil.cnf to know which ones) *after* the wrappers have been generated 249 - '' 250 - texlinks --quiet "$out/bin" 251 - '' + 252 - # texlive postactions (see TeXLive::TLUtils::_do_postaction_script) 253 - (lib.concatMapStrings (pkg: '' 254 - postaction='${pkg.postactionScript}' 255 - case "$postaction" in 256 - *.pl) postInterp=perl ;; 257 - *.texlua) postInterp=texlua ;; 258 - *) postInterp= ;; 259 - esac 260 - echo "postaction install script for ${pkg.pname}: ''${postInterp:+$postInterp }$postaction install $TEXMFROOT" 261 - $postInterp "$TEXMFROOT/$postaction" install "$TEXMFROOT" 262 - '') (lib.filter (pkg: pkg ? postactionScript) pkgList.tlpkg)) + 263 - # generate formats 264 - '' 265 - # many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1 266 - # libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE 267 - # we cannot fix further randomness caused by luatex; for further details, see 268 - # https://salsa.debian.org/live-team/live-build/-/blob/master/examples/hooks/reproducible/2006-reproducible-texlive-binaries-fmt-files.hook.chroot#L52 269 - # note that calling faketime and fmtutil is fragile (faketime uses LD_PRELOAD, fmtutil calls /bin/sh, causing potential glibc issues on non-NixOS) 270 - # so we patch fmtutil to use faketime, rather than calling faketime fmtutil 271 - substitute "$TEXMFDIST"/scripts/texlive/fmtutil.pl fmtutil \ 272 - --replace 'my $cmdline = "$eng -ini ' 'my $cmdline = "faketime -f '"'"'\@1980-01-01 00:00:00 x0.001'"'"' $eng -ini ' 273 - FORCE_SOURCE_DATE=1 TZ= perl fmtutil --sys --all | grep '^fmtutil' # too verbose 274 - 275 - # Disable unavailable map files 276 - echo y | updmap --sys --syncwithtrees --force 2>&1 | grep '^\(updmap\| /\)' 277 - # Regenerate the map files (this is optional) 278 - updmap --sys --force 2>&1 | grep '^\(updmap\| /\)' 279 - 280 - # sort entries to improve reproducibility 281 - [[ -f "$TEXMFSYSCONFIG"/web2c/updmap.cfg ]] && sort -o "$TEXMFSYSCONFIG"/web2c/updmap.cfg "$TEXMFSYSCONFIG"/web2c/updmap.cfg 282 - 283 - mktexlsr "$TEXMFSYSCONFIG" "$TEXMFSYSVAR" # to make sure (of what?) 284 - '' + 285 - # remove *-sys scripts since /nix/store is readonly 286 - '' 287 - rm "$out"/bin/*-sys 288 - '' + 289 - # TODO: a context trigger https://www.preining.info/blog/2015/06/debian-tex-live-2015-the-new-layout/ 290 - # http://wiki.contextgarden.net/ConTeXt_Standalone#Unix-like_platforms_.28Linux.2FMacOS_X.2FFreeBSD.2FSolaris.29 291 - 292 - # MkIV uses its own lookup mechanism and we need to initialize 293 - # caches for it. 294 - # We use faketime to fix the embedded timestamps and patch the uuids 295 - # with some random but constant values. 296 - '' 297 - if [[ -e "$out/bin/mtxrun" ]]; then 298 - substitute "$TEXMFDIST"/scripts/context/lua/mtxrun.lua mtxrun.lua \ 299 - --replace 'cache_uuid=osuuid()' 'cache_uuid="e2402e51-133d-4c73-a278-006ea4ed734f"' \ 300 - --replace 'uuid=osuuid(),' 'uuid="242be807-d17e-4792-8e39-aa93326fc871",' 301 - FORCE_SOURCE_DATE=1 TZ= faketime -f '@1980-01-01 00:00:00 x0.001' luatex --luaonly mtxrun.lua --generate 302 - fi 303 - '' + 304 - # Get rid of all log files. They are not needed, but take up space 305 - # and render the build unreproducible by their embedded timestamps 306 - # and other non-deterministic diagnostics. 307 - '' 308 - find "$TEXMFSYSVAR"/web2c -name '*.log' -delete 309 - '' + 310 - # link TEXMFDIST in $out/share for backward compatibility 311 - '' 312 - ln -s "$TEXMFDIST" "$out"/share/texmf 313 - '' 314 - ; 315 - }).overrideAttrs (_: { allowSubstitutes = true; })
+103 -56
pkgs/tools/typesetting/tex/texlive/default.nix
··· 2 2 - source: ../../../../../doc/languages-frameworks/texlive.xml 3 3 - current html: https://nixos.org/nixpkgs/manual/#sec-language-texlive 4 4 */ 5 - { stdenv, lib, fetchurl, runCommand, writeText, buildEnv 5 + { stdenv, lib, fetchurl, runCommand, writeShellScript, writeText, buildEnv 6 6 , callPackage, ghostscript_headless, harfbuzz 7 7 , makeWrapper, installShellFiles 8 8 , python3, ruby, perl, tk, jdk, bash, snobol4 ··· 20 20 }; 21 21 inherit useFixedHashes; 22 22 tlpdb = overriddenTlpdb; 23 - }; 24 - 25 - # function for creating a working environment from a set of TL packages 26 - combine = import ./combine.nix { 27 - inherit bin buildEnv lib makeWrapper writeText runCommand 28 - perl libfaketime makeFontsConf bash tl coreutils gawk gnugrep gnused; 29 - ghostscript = ghostscript_headless; 30 23 }; 31 24 32 25 tlpdb = import ./tlpdb.nix; ··· 101 94 // lib.optionalAttrs (args ? deps) { deps = map (n: tl.${n}) (args.deps or [ ]); }) 102 95 ) overriddenTlpdb; 103 96 97 + # function for creating a working environment 98 + buildTeXEnv = import ./build-tex-env.nix { 99 + inherit bin tl; 100 + ghostscript = ghostscript_headless; 101 + inherit lib buildEnv libfaketime makeFontsConf makeWrapper runCommand 102 + writeShellScript writeText toTLPkgSets bash perl coreutils gawk gnugrep gnused; 103 + }; 104 + 105 + ### texlive.combine compatibility layer: 106 + # convert TeX packages to { pkgs = [ ... ]; } lists 107 + # respecting specified outputs 108 + toTLPkgList = drv: if drv.outputSpecified or false 109 + then let tlType = drv.tlType or tlOutToType.${drv.tlOutputName or drv.outputName} or null; in 110 + lib.optional (tlType != null) (drv // { inherit tlType; }) 111 + else [ (drv.tex // { tlType = "run"; }) ] ++ 112 + lib.optional (drv ? texdoc) (drv.texdoc // { tlType = "doc"; } // lib.optionalAttrs (drv ? man) { hasManpages = true; }) ++ 113 + lib.optional (drv ? texsource) (drv.texsource // { tlType = "source"; }) ++ 114 + lib.optional (drv ? tlpkg) (drv.tlpkg // { tlType = "tlpkg"; }) ++ 115 + lib.optional (drv ? out) (drv.out // { tlType = "bin"; }); 116 + tlOutToType = { out = "bin"; tex = "run"; texsource = "source"; texdoc = "doc"; tlpkg = "tlpkg"; }; 117 + 118 + # convert { pkgs = [ ... ]; } lists to TeX packages 119 + # possibly more than one, if pkgs is also used to specify dependencies 120 + tlTypeToOut = { run = "tex"; doc = "texdoc"; source = "texsource"; bin = "out"; tlpkg = "tlpkg"; }; 121 + toSpecifiedNV = p: rec { 122 + name = value.tlOutputName; 123 + value = builtins.removeAttrs p [ "pkgs" ] 124 + // { outputSpecified = true; tlOutputName = tlTypeToOut.${p.tlType}; }; 125 + }; 126 + toTLPkgSet = pname: drvs: 127 + let set = lib.listToAttrs (builtins.map toSpecifiedNV drvs); 128 + mainDrv = set.out or set.tex or set.tlpkg or set.texdoc or set.texsource; in 129 + builtins.removeAttrs mainDrv [ "outputSpecified" ]; 130 + toTLPkgSets = { pkgs, ... }: lib.mapAttrsToList toTLPkgSet 131 + (builtins.groupBy (p: p.pname) pkgs); 132 + 133 + # export TeX packages as { pkgs = [ ... ]; } in the top attribute set 134 + allPkgLists = lib.mapAttrs (n: drv: { pkgs = toTLPkgList drv; }) tl; 135 + 136 + # function for creating a working environment from a set of TL packages 137 + # now a legacy wrapper around buildTeXEnv 138 + combine = import ./combine-wrapper.nix { inherit buildTeXEnv lib toTLPkgList toTLPkgSets; }; 139 + 104 140 assertions = with lib; 105 141 assertMsg (tlpdbVersion.year == version.texliveYear) "TeX Live year in texlive does not match tlpdb.nix, refusing to evaluate" && 106 142 assertMsg (tlpdbVersion.frozen == version.final) "TeX Live final status in texlive does not match tlpdb.nix, refusing to evaluate"; 107 143 144 + # Pre-defined evironment packages for TeX Live schemes, 145 + # to make nix-env usage more comfortable and build selected on Hydra. 146 + 147 + # these license lists should be the sorted union of the licenses of the packages the schemes contain. 148 + # The correctness of this collation is tested by tests.texlive.licenses 149 + licenses = with lib.licenses; { 150 + scheme-basic = [ free gfl gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; 151 + scheme-context = [ bsd2 bsd3 cc-by-sa-40 free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 152 + lppl1 lppl13c mit ofl publicDomain x11 ]; 153 + scheme-full = [ artistic1-cl8 artistic2 asl20 bsd2 bsd3 bsdOriginal cc-by-10 cc-by-40 cc-by-sa-10 cc-by-sa-20 154 + cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth 155 + lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 156 + scheme-gust = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 157 + gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 158 + scheme-infraonly = [ gpl2 gpl2Plus lgpl21 ]; 159 + scheme-medium = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only 160 + free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl 161 + publicDomain x11 ]; 162 + scheme-minimal = [ free gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; 163 + scheme-small = [ asl20 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth 164 + lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 165 + 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 166 + fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a 167 + lppl13c mit ofl publicDomain x11]; 168 + }; 169 + 170 + meta = { 171 + description = "TeX Live environment"; 172 + platforms = lib.platforms.all; 173 + maintainers = with lib.maintainers; [ veprbl ]; 174 + license = licenses.scheme-infraonly; 175 + }; 176 + 177 + combined = recurseIntoAttrs ( 178 + lib.genAttrs [ "scheme-basic" "scheme-context" "scheme-full" "scheme-gust" "scheme-infraonly" 179 + "scheme-medium" "scheme-minimal" "scheme-small" "scheme-tetex" ] 180 + (pname: 181 + (buildTeXEnv { 182 + __extraName = "combined" + lib.removePrefix "scheme" pname; 183 + __extraVersion = with version; if final then "-final" else ".${year}${month}${day}"; 184 + requiredTeXPackages = ps: [ ps.${pname} ]; 185 + # to maintain full backward compatibility, enable texlive.combine behavior 186 + __combine = true; 187 + }).overrideAttrs { 188 + meta = meta // { 189 + description = "TeX Live environment for ${pname}"; 190 + license = licenses.${pname}; 191 + }; 192 + } 193 + ) 194 + ); 195 + 108 196 in 109 - tl // { 197 + allPkgLists // { 198 + pkgs = tl; 110 199 111 200 tlpdb = { 112 201 # nested in an attribute set to prevent them from appearing in search ··· 116 205 117 206 bin = assert assertions; bin // { 118 207 # for backward compatibility 119 - latexindent = lib.findFirst (p: p.tlType == "bin") tl.latexindent.pkgs; 208 + latexindent = tl.latexindent; 120 209 }; 121 210 122 211 combine = assert assertions; combine; 123 212 124 - # Pre-defined combined packages for TeX Live schemes, 125 - # to make nix-env usage more comfortable and build selected on Hydra. 126 - combined = with lib; 127 - let 128 - # these license lists should be the sorted union of the licenses of the packages the schemes contain. 129 - # The correctness of this collation is tested by tests.texlive.licenses 130 - licenses = with lib.licenses; { 131 - scheme-basic = [ free gfl gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; 132 - scheme-context = [ bsd2 bsd3 cc-by-sa-40 free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 133 - lppl1 lppl13c mit ofl publicDomain x11 ]; 134 - scheme-full = [ artistic1-cl8 artistic2 asl20 bsd2 bsd3 bsdOriginal cc-by-10 cc-by-40 cc-by-sa-10 cc-by-sa-20 135 - cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth 136 - lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 137 - scheme-gust = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gfsl gpl1Only gpl2 138 - gpl2Plus gpl3 gpl3Plus knuth lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 139 - scheme-infraonly = [ gpl2 gpl2Plus lgpl21 ]; 140 - scheme-medium = [ artistic1-cl8 asl20 bsd2 bsd3 cc-by-40 cc-by-sa-20 cc-by-sa-30 cc-by-sa-40 cc0 fdl13Only 141 - free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a lppl13c mit ofl 142 - publicDomain x11 ]; 143 - scheme-minimal = [ free gpl1Only gpl2 gpl2Plus knuth lgpl21 lppl1 lppl13c mit ofl publicDomain ]; 144 - scheme-small = [ asl20 cc-by-40 cc-by-sa-40 cc0 fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus knuth 145 - lgpl2 lgpl21 lppl1 lppl12 lppl13a lppl13c mit ofl publicDomain x11 ]; 146 - 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 147 - fdl13Only free gfl gpl1Only gpl2 gpl2Plus gpl3 gpl3Plus isc knuth lgpl2 lgpl21 lgpl3 lppl1 lppl12 lppl13a 148 - lppl13c mit ofl publicDomain x11]; 149 - }; 150 - in recurseIntoAttrs ( 151 - mapAttrs 152 - (pname: attrs: 153 - addMetaAttrs rec { 154 - description = "TeX Live environment for ${pname}"; 155 - platforms = lib.platforms.all; 156 - maintainers = with lib.maintainers; [ veprbl ]; 157 - license = licenses.${pname}; 158 - } 159 - (combine { 160 - ${pname} = attrs; 161 - extraName = "combined" + lib.removePrefix "scheme" pname; 162 - extraVersion = with version; if final then "-final" else ".${year}${month}${day}"; 163 - }) 164 - ) 165 - { inherit (tl) 166 - scheme-basic scheme-context scheme-full scheme-gust scheme-infraonly 167 - scheme-medium scheme-minimal scheme-small scheme-tetex; 168 - } 169 - ); 213 + combined = assert assertions; combined; 214 + 215 + # convenience alias 216 + withPackages = (buildTeXEnv { }).withPackages; 170 217 }
+14 -15
pkgs/tools/typesetting/tex/texlive/generate-fixed-hashes.nix
··· 1 1 with import ../../../../.. { }; 2 2 3 3 with lib; let 4 - isFod = p: p.tlType != "bin" && isDerivation p; 4 + getFods = drv: lib.optional (isDerivation drv.tex) (drv.tex // { tlType = "run"; }) 5 + ++ lib.optional (drv ? texdoc) (drv.texdoc // { tlType = "doc"; }) 6 + ++ lib.optional (drv ? texsource) (drv.texsource // { tlType = "source"; }) 7 + ++ lib.optional (drv ? tlpkg) (drv.tlpkg // { tlType = "tlpkg"; }); 5 8 6 - # ugly hack to extract combine from collection-latexextra, since it is masked by texlive.combine 7 - combine = lib.findFirst (p: (lib.head p.pkgs).pname == "combine") { pkgs = [ ]; } (lib.head texlive.collection-latexextra.pkgs).tlDeps; 8 - all = filter (p: p ? pkgs) (attrValues (removeAttrs texlive [ "bin" "combine" "combined" "tlpdb" ])) ++ [ combine ]; 9 - sorted = sort (a: b: (head a.pkgs).pname < (head b.pkgs).pname) all; 10 - fods = filter isFod (concatMap (p: p.pkgs or [ ]) all); 9 + sorted = sort (a: b: a.pname < b.pname) (attrValues texlive.pkgs); 10 + fods = concatMap getFods sorted; 11 11 12 12 computeHash = fod: runCommand "${fod.pname}-${fod.tlType}-fixed-hash" 13 13 { buildInputs = [ nix ]; inherit fod; } ··· 15 15 16 16 hash = fod: fod.outputHash or (builtins.readFile (computeHash fod)); 17 17 18 - hashes = { pkgs }: 19 - concatMapStrings ({ tlType, ... }@p: lib.optionalString (isFod p) (''${tlType}="${hash p}";'')) pkgs; 18 + hashes = fods: 19 + concatMapStrings ({ tlType, ... }@p: ''${tlType}="${hash p}";'') fods; 20 20 21 - hashLine = { pkgs }@pkg: 21 + hashLine = { pname, revision, extraRevision ? "", ... }@drv: 22 22 let 23 - fods = lib.filter isFod pkgs; 24 - first = lib.head fods; 23 + fods = getFods drv; 25 24 # NOTE: the fixed naming scheme must match default.nix 26 - fixedName = with first; "${pname}-${toString revision}${first.extraRevision or ""}"; 25 + fixedName = "${pname}-${toString revision}${extraRevision}"; 27 26 in 28 - lib.optionalString (fods != [ ]) '' 29 - ${strings.escapeNixIdentifier fixedName}={${hashes pkg}}; 27 + optionalString (fods != [ ]) '' 28 + ${strings.escapeNixIdentifier fixedName}={${hashes fods}}; 30 29 ''; 31 30 in 32 31 { ··· 37 36 fixedHashesNix = writeText "fixed-hashes.nix" 38 37 '' 39 38 { 40 - ${lib.concatMapStrings hashLine sorted}} 39 + ${concatMapStrings hashLine sorted}} 41 40 ''; 42 41 }
+1
pkgs/tools/typesetting/tex/texlive/tl2nix.sed
··· 91 91 t next-doc # loop if the previous lines matched 92 92 93 93 / (texmf-dist|RELOC)\/doc\/man\//i\ hasManpages = true; 94 + / (texmf-dist|RELOC)\/doc\/info\//i\ hasInfo = true; 94 95 95 96 D # restart cycle 96 97 }
+5 -5
pkgs/tools/typesetting/tex/texlive/tlpdb-overrides.nix
··· 126 126 127 127 texlive-scripts.binlinks = { 128 128 mktexfmt = "fmtutil"; 129 - texhash = (lib.last tl."texlive.infra".pkgs) + "/bin/mktexlsr"; 129 + texhash = tl."texlive.infra" + "/bin/mktexlsr"; 130 130 }; 131 131 132 132 texlive-scripts-extra.binlinks = { ··· 352 352 mkdir -p support/texdoc 353 353 touch support/texdoc/NEWS 354 354 355 - TEXMFCNF="${lib.head tl.kpathsea.pkgs}/web2c" TEXMF="$out" TEXDOCS=. TEXMFVAR=. \ 355 + TEXMFCNF="${tl.kpathsea.tex}/web2c" TEXMF="$out" TEXDOCS=. TEXMFVAR=. \ 356 356 "${bin.luatex}"/bin/texlua "$out"/scripts/texdoc/texdoc.tlu \ 357 357 -c texlive_tlpdb=texlive.tlpdb -lM texdoc 358 358 ··· 362 362 363 363 # install zsh completion 364 364 postFixup = '' 365 - TEXMFCNF="${lib.head tl.kpathsea.pkgs}"/web2c TEXMF="$scriptsFolder/../.." \ 365 + TEXMFCNF="${tl.kpathsea.tex}"/web2c TEXMF="$scriptsFolder/../.." \ 366 366 texlua "$out"/bin/texdoc --print-completion zsh > "$TMPDIR"/_texdoc 367 367 substituteInPlace "$TMPDIR"/_texdoc \ 368 368 --replace 'compdef __texdoc texdoc' '#compdef texdoc' \ ··· 381 381 license = [ "gpl2Plus" ] ++ lib.toList bin.core.meta.license.shortName ++ orig."texlive.infra".license or [ ]; 382 382 383 383 scriptsFolder = "texlive"; 384 - extraBuildInputs = [ coreutils gnused gnupg (lib.last tl.kpathsea.pkgs) (perl.withPackages (ps: with ps; [ Tk ])) ]; 384 + extraBuildInputs = [ coreutils gnused gnupg tl.kpathsea (perl.withPackages (ps: with ps; [ Tk ])) ]; 385 385 386 386 # make tlmgr believe it can use kpsewhich to evaluate TEXMFROOT 387 387 postFixup = '' 388 388 substituteInPlace "$out"/bin/tlmgr \ 389 389 --replace 'if (-r "$bindir/$kpsewhichname")' 'if (1)' 390 390 sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath [ gnupg ]}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/tlmgr 391 - sed -i '2iPATH="${lib.makeBinPath [ coreutils gnused (lib.last tl.kpathsea.pkgs) ]}''${PATH:+:$PATH}"' "$out"/bin/mktexlsr 391 + sed -i '2iPATH="${lib.makeBinPath [ coreutils gnused tl.kpathsea ]}''${PATH:+:$PATH}"' "$out"/bin/mktexlsr 392 392 ''; 393 393 394 394 # add minimal texlive.tlpdb
+15
pkgs/tools/typesetting/tex/texlive/tlpdb.nix
··· 1707 1707 sha512.run = "4f97d0d87d1f29985c83c99629fc52e8e18f6eabf95d77aa888429187b49ed9525661d9c06b46a9b2295b03df412778ede1490fa9cd8ec680c3209a4ca6d0be0"; 1708 1708 sha512.doc = "940297c3d69de7e01caa09ff44483f7334aba14705bdcdc83661ca9be2210133e094f99a8355b4b88d076355bb4f13f64c21700bff57f452dd5dbc8d2fddb432"; 1709 1709 hasManpages = true; 1710 + hasInfo = true; 1710 1711 hasRunfiles = true; 1711 1712 license = [ "lgpl3" ]; 1712 1713 version = "2.85"; ··· 15500 15501 sha512.run = "d24be610a63a9df22ebe6f53891519ab77900611d1159dec5e97b27160f3552b4cbce42b575a036125d2b15910a72cb5e3793a3409c5d0f4b1df0c2433e828f8"; 15501 15502 sha512.doc = "976ff6c9628fe85adca2287f04d76f2c1605f243e28b4d32cb1ef9a90d30dcae0d202e6d5156914c204fd42b0a66460755a89f7dbdeb9ec1ccf6010cfe8daf78"; 15502 15503 hasManpages = true; 15504 + hasInfo = true; 15503 15505 license = [ "lgpl3" ]; 15504 15506 version = "1.17"; 15505 15507 }; ··· 15521 15523 sha512.run = "a680a4685d3cbb429ad9dada0d48098f7755253ad1d7c808731f0f4fb4c37971cb937a9fa68bcecd892de93cc35a8086b742c86338460585c2912f36d00ade67"; 15522 15524 sha512.doc = "a6acb780a45663fb21976622d7b6c3ea8d4adf1fe405ee97cd7c4cf09fa49b59069ba72b2aa14b53d3ba631b37c5cbd979929adaa274a0bec8b1272d85e1cd43"; 15523 15525 hasManpages = true; 15526 + hasInfo = true; 15524 15527 hasRunfiles = true; 15525 15528 license = [ "free" ]; 15526 15529 }; ··· 16610 16613 sha512.run = "fda8158ae2bdc96187b6e6ace2a94be3e0f68201adbc02553b48a3848481352ac10ddd72babcbc2835e089ce751ade7dfa6cfd1c642c94155c2861db865f5c29"; 16611 16614 sha512.doc = "60902b2422d2f5d7570a19daf7f586df7882505d7c156539699a0aa47a0f3bde5688dcbdc92c8a6a9878f11392bc9b9f147626aad230eecd2740d56f104928ed"; 16612 16615 hasManpages = true; 16616 + hasInfo = true; 16613 16617 sha512.source = "015de2eeeaec99bd15882a190f9ef3f2112520f8c591c7e6d2351c52d8690b024750adea426bcf95f438aaa20c97dd321881ac7212ff181e148337b57f6d386c"; 16614 16618 hasRunfiles = true; 16615 16619 license = [ "gpl2Plus" ]; ··· 16666 16670 revision = 66119; 16667 16671 sha512.run = "f155834a9636991c8ae752f61f70bdf22ab3172270c85aebb05462cf26e44f6e81fb83842c8515bfa54e632a3beab8bb91cccf2b5eef459d77738443c77df56d"; 16668 16672 sha512.doc = "5d06f8a4ef295e0fac8cd1dc73ff98e266dcf4394ed76223c92d20758fa8195ef5bea9bde49b1a247acfdf67aa7717092f978b55fc4fbc8665922487d57985d6"; 16673 + hasInfo = true; 16669 16674 hasRunfiles = true; 16670 16675 scriptExts = [ 16671 16676 "tcl" ··· 18768 18773 stripPrefix = 0; 18769 18774 sha512.run = "424da4dbbc07c41840e6aeb6fabeef5d4778d206b9cb8a90e752ebeb65d962b96ad41a7e20c86a16665e2bf48ad795d85001da66ff41b01ae3c949c6eefa4593"; 18770 18775 sha512.doc = "78199996913192f5f69423b6f412acc52b74f051b01d3e345b97b7f1d9ea4aea762a7b83488068f3091b41da69471d56b3f18ab4d299cc6adfe4e004072db303"; 18776 + hasInfo = true; 18771 18777 hasRunfiles = true; 18772 18778 license = [ "gpl1Only" ]; 18773 18779 }; ··· 24499 24505 sha512.run = "8a9f0dd49470bec5ba0f963a0385bea45141d6b805682bd65e95291b02158b9d2cedd5bd43592de7c447fe87f04efa00e4d1aa191a490147adcb57ec3922b5db"; 24500 24506 sha512.doc = "51500943de0184fd9794dbf6af80aed2fc7bbaf2a7949facb1840ad0e32344d217aa4d58ee76e3934aec891858f789b3847b9027cb2bd75e5962be98ddd9d02f"; 24501 24507 hasManpages = true; 24508 + hasInfo = true; 24502 24509 hasRunfiles = true; 24503 24510 license = [ "lgpl21" ]; 24504 24511 }; ··· 25258 25265 stripPrefix = 0; 25259 25266 sha512.run = "34b91b19e1b71b1df6d0f57dda4d6976a93b16afac259656c9d4e331b0c23a9b0550563c1a10dd7a95640e3740b3b15597c1023f6c2721bf2a64800466b9cd09"; 25260 25267 sha512.doc = "d4584d9259f3c1867e7445d4a219e4decc5ba3b305e20d1e780180a47fbad8df4d55552726d8288e78c8388823a2b652b81080c8139b00f4ea3ca10e5789375b"; 25268 + hasInfo = true; 25261 25269 license = [ "free" ]; 25262 25270 }; 25263 25271 latex2e-help-texinfo-fr = { ··· 25265 25273 stripPrefix = 0; 25266 25274 sha512.run = "96366ea420532f56ae076da48f5402c2ee78ca27fae8180795d6cd18aae118a8c7060208ff43ab64526addcdce9e4d90790583842b20c751f37865cf616e04e4"; 25267 25275 sha512.doc = "52f6aea9ac2393a73d7dc7ce8ad4d6f08e0a224397199d5def97412502026717e8cb966552368899c50718a1049b1ad4610d2d23150a45bee55cc2c776003db7"; 25276 + hasInfo = true; 25268 25277 license = [ "publicDomain" ]; 25269 25278 }; 25270 25279 latex2e-help-texinfo-spanish = { ··· 25272 25281 stripPrefix = 0; 25273 25282 sha512.run = "870c8f3af54ac42df5f4958669cf730cd16084c985f0b377c5aba9d526b8f7be14b367791d2c0a1f1a715739390ab63777ff2a92e7f9aad09897c8bbecff495e"; 25274 25283 sha512.doc = "4c751a7305e089dab61bf991436ab1e612cfca0d17e416e21d659c04ef32eeb2d14dbeb09d63649a2b79f842766a218c43ae2c6fbeeba5549f039f991049a79d"; 25284 + hasInfo = true; 25275 25285 license = [ "free" ]; 25276 25286 }; 25277 25287 latex2man = { ··· 25279 25289 sha512.run = "2617f6e8059f30c0098ea896cff69f585ea2ddbd3bbbd8066e7296dd833d3a246b8fefc0af71a92abf7e2051c754c0e3e6098175a4b181780563416bc9146b95"; 25280 25290 sha512.doc = "390666cc56ad70342c9a24ca593fe65b3760674a882ed8bba383d193f2578285727a085f823afc03fa0dbc9966612caf9a29222fd2a9f39214f01aa268acdc50"; 25281 25291 hasManpages = true; 25292 + hasInfo = true; 25282 25293 hasRunfiles = true; 25283 25294 license = [ "lppl1" ]; 25284 25295 version = "1.29"; ··· 28873 28884 revision = 61217; 28874 28885 sha512.run = "ca93a3ae439f9cd8029720bd1d90fbe75a403e7ab4ebcbe1ba1e5a7a28aa9269197f90a4aee849fea59d734d5dc38f04eedc140ff1be64fd805a10ab5510a2f5"; 28875 28886 sha512.doc = "6c10831fdcc48d25645be675fbf5da29da945bd79032c60e73e04a39d61c287a64e7b884381ac0b08e48f5dc9b6dec27efea874f6e13d6e4a5e3f32c22fa3ce2"; 28887 + hasInfo = true; 28876 28888 hasRunfiles = true; 28877 28889 license = [ "lppl13c" ]; 28878 28890 version = "2.7"; ··· 40536 40548 stripPrefix = 0; 40537 40549 sha512.run = "b03911aa9711eb5eeed77c026c4bbcf952da80322b855ac631e78c07a48ad2ff1a4afdd6e25a00257d1b70e054645f07f65c98fe74f6b1389be46625f5eb8487"; 40538 40550 sha512.doc = "f4078e3b1693fedcbe139b67c50824845644a2b1e57dd27f9e46e44504d8fe8ac0ca706590e9149c06e71794a188b20777bfd6bf1afe85f16c806ba4f9b99cd8"; 40551 + hasInfo = true; 40539 40552 license = [ "free" ]; 40540 40553 version = "1.1"; 40541 40554 }; ··· 41052 41065 stripPrefix = 0; 41053 41066 sha512.run = "f4d160e494b1579743a83b2a0926df9e8dd69fdaa79d3f4f97e0ed5f4ece31ab380ff6994a1c9015e0af9b842bdfb9b066442ca4b3018df6659922af9f746b0b"; 41054 41067 sha512.doc = "e177209a937fa1d9d683eb805e9e8929612b4b1ff750955d38ca681b657662712a59609990f77021063a223ce61a92fdd567eee91376ef4b67fd3a322db09463"; 41068 + hasInfo = true; 41055 41069 hasRunfiles = true; 41056 41070 license = [ "cc-by-40" ]; 41057 41071 version = "v2r3"; ··· 41115 41129 stripPrefix = 0; 41116 41130 sha512.run = "f790f2a94e67573635afb5b4c2d375bede61eb3afe271169078fe905d326119234363ee896ecc93a9892d26e0a394fc350edbda810e218b0b06cc30681fd9cf0"; 41117 41131 sha512.doc = "48ffb3b9053250f4425992c57869c6153601e9dfaa4931ac4ff3c12df44b148dce08496acbae495fd5f9fe37e11044a3fc0669c713515d2cc99506fd6be59859"; 41132 + hasInfo = true; 41118 41133 }; 41119 41134 texlive-es = { 41120 41135 revision = 65640;