texlive.withPackages: generate formats in separate derivations (#291396)

Generate TeX formats into separate derivations so that they can be
shared across different environments, considerably reducing build times.

authored by Vincenzo Mantova and committed by GitHub 017e73bd cfda13b1

+47 -19
+11 -7
pkgs/tools/typesetting/tex/texlive/build-tex-env.nix
··· 35 35 , __combine ? false 36 36 # adjust behavior further if called from the texlive.combine wrapper 37 37 , __fromCombineWrapper ? false 38 + # build only the formats of a package (for internal use!) 39 + , __formatsOf ? null 38 40 }@args: 39 41 40 42 let ··· 116 118 hyphenPatterns = lib.filter (p: p ? hyphenPatterns && (p.tlOutputName or p.outputName == "tex")) nonbin; 117 119 sortedHyphenPatterns = builtins.sort (a: b: a.pname < b.pname) hyphenPatterns; 118 120 formatPkgs = lib.filter (p: p ? formats && (p.outputSpecified or false -> p.tlOutputName or p.outputName == "tex") && builtins.any (f: f.enabled or true) p.formats) all; 119 - sortedFormatPkgs = builtins.sort (a: b: a.pname < b.pname) formatPkgs; 121 + sortedFormatPkgs = if __formatsOf != null then [ __formatsOf ] else builtins.sort (a: b: a.pname < b.pname) formatPkgs; 122 + formats = map (p: self { requiredTeXPackages = ps: [ ps.scheme-infraonly p ] ++ hyphenPatterns; __formatsOf = p; }) sortedFormatPkgs; 120 123 }; 121 124 122 125 # list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts` ··· 125 128 needsGhostscript = lib.any (p: lib.elem p.pname [ "context" "dvipdfmx" "latex-papersize" "lyluatex" ]) pkgList.bin; 126 129 127 130 name = if __combine then "texlive-${__extraName}-${bin.texliveYear}${__extraVersion}" # texlive.combine: old name name 128 - else "texlive-${bin.texliveYear}-env"; 131 + else "texlive-${bin.texliveYear}-" + (if __formatsOf != null then "${__formatsOf.pname}-fmt" else "env"); 129 132 130 133 texmfdist = buildEnv' { 131 134 name = "${name}-texmfdist"; ··· 260 263 inherit name; 261 264 262 265 # use attrNames, attrValues to ensure the two lists are sorted in the same way 263 - outputs = [ "out" ] ++ lib.optionals (! __combine) (builtins.attrNames nonEnvOutputs); 264 - otherOutputs = lib.optionals (! __combine) (builtins.attrValues nonEnvOutputs); 266 + outputs = [ "out" ] ++ lib.optionals (! __combine && __formatsOf == null) (builtins.attrNames nonEnvOutputs); 267 + otherOutputs = lib.optionals (! __combine && __formatsOf == null) (builtins.attrValues nonEnvOutputs); 265 268 266 269 # remove fake derivations (without 'outPath') to avoid undesired build dependencies 267 - paths = builtins.catAttrs "outPath" pkgList.bin 270 + paths = builtins.catAttrs "outPath" pkgList.bin ++ lib.optionals (! __combine && __formatsOf == null) pkgList.formats 268 271 ++ lib.optional __combine doc; 269 272 pathsToLink = [ 270 273 "/" ··· 286 289 287 290 buildInputs = [ coreutils gawk gnugrep gnused ] ++ lib.optional needsGhostscript ghostscript; 288 291 289 - inherit meta passthru; 292 + inherit meta passthru __combine; 293 + __formatsOf = __formatsOf.pname or null; 290 294 291 295 inherit texmfdist texmfroot; 292 296 ··· 306 310 ''; 307 311 }; 308 312 # outputsToInstall must be set *after* overrideAttrs (used in buildEnv') or it fails the checkMeta tests 309 - in if __combine then out else lib.addMetaAttrs { inherit (pkgList) outputsToInstall; } out) 313 + in if __combine || __formatsOf != null then out else lib.addMetaAttrs { inherit (pkgList) outputsToInstall; } out)
+36 -12
pkgs/tools/typesetting/tex/texlive/build-tex-env.sh
··· 143 143 # in principle, we could use writeText and share them across different 144 144 # environments, but the eval & build overhead is not worth the savings 145 145 tlutils_create_fmtutil 146 - tlutils_create_updmap 146 + # can be skipped if generating formats only 147 + if [[ -z $__formatsOf ]] ; then 148 + tlutils_create_updmap 149 + fi 147 150 tlutils_create_language_dat 148 151 tlutils_create_language_def 149 152 tlutils_create_language_lua ··· 152 155 tlutils_info "running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG" 153 156 mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG" 154 157 155 - # update font maps 156 - tlutils_info "generating font maps" 157 - updmap-sys --quiet --force --nohash 2>&1 158 - # configure the paper size 159 - # tlmgr --no-execute-actions paper letter 160 - # install-tl: "rerun mktexlsr for updmap-sys and tlmgr paper updates" 161 - tlutils_info "re-running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG" 162 - mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG" 158 + # can be skipped if generating formats only 159 + if [[ -z $__formatsOf ]] ; then 160 + # update font maps 161 + tlutils_info "generating font maps" 162 + updmap-sys --quiet --force --nohash 2>&1 163 + # configure the paper size 164 + # tlmgr --no-execute-actions paper letter 165 + # install-tl: "rerun mktexlsr for updmap-sys and tlmgr paper updates" 166 + tlutils_info "re-running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG" 167 + mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG" 163 168 164 - tlutils_update_context_cache 169 + tlutils_update_context_cache 170 + fi 165 171 166 172 # generate formats 167 173 # install-tl would run fmtutil-sys $common_fmtutil_args --no-strict --all 168 174 # instead, we want fmtutil to exit with error on failure 169 - if [[ -n $fmtutilCnf ]] ; then 175 + if [[ -n $fmtutilCnf && -n $__combine$__formatsOf ]] ; then 170 176 tlutils_info "pre-generating all format files, be patient..." 171 177 # many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1 172 178 # libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE ··· 177 183 substitute "$texmfdist"/scripts/texlive/fmtutil.pl fmtutil \ 178 184 --replace-fail "my \$cmdline = \"\$eng -ini " "my \$cmdline = \"faketime -f '\@$(date +'%F %T' --date=@"$SOURCE_DATE_EPOCH") x0.001' \$eng -ini " 179 185 FORCE_SOURCE_DATE=1 perl fmtutil --quiet --strict --sys --all 2>&1 | grep '^fmtutil' # too verbose 186 + 187 + # if generating formats only, delete everything else and exit 188 + if [[ -n $__formatsOf ]] ; then 189 + # see fmtutil.pl::compute_format_destination for file extensions 190 + find "$out" \( -type f -or -type l \) \ 191 + -not -path "$TEXMFSYSVAR/*.mem" \ 192 + -not -path "$TEXMFSYSVAR/*.base" \ 193 + -not -path "$TEXMFSYSVAR/*.fmt" \ 194 + -delete 195 + find "$out" -type d -empty -delete 196 + exit 197 + fi 198 + elif [[ -z $__combine ]] ; then 199 + # double check that all formats are present 200 + if fmtutil --quiet --strict --sys --missing --dry-run 2>&1 | grep running ; then 201 + tlutils_info 'formats not found, aborting' 202 + exit 1 203 + fi 180 204 fi 181 205 182 206 installtl_do_path_adjustments ··· 190 214 ### TeXLive::TLUtils 191 215 192 216 tlutils_info () { 193 - printf '%s\n' "texlive: $*" 217 + printf "texlive${__formatsOf:+($__formatsOf-fmt)}: %s\n" "$*" 194 218 } 195 219 196 220 tlutils_create_fmtutil () {