core/pkgs/by-name/te/texlive/build-tex-env.sh

329 lines
12 KiB
Bash
Raw Permalink Normal View History

2024-05-02 00:46:19 +00:00
# shellcheck shell=bash
# Replicate the post install phase of the upstream TeX Live installer.
#
# This script is based on the install-tl script and the TeXLive::TLUtils perl
# module, down to using the same (prefixed) function names and log messages.
#
# When updating to the next TeX Live release, review install-tl for changes and
# update this script accordingly.
### install-tl
# adjust texmf.cnf and texmfcnf.lua
installtl_do_texmf_cnf () {
# unlike install-tl, we make a copy of the entire texmf.cnf
# and point the binaries at $TEXMFCNF/texmf.cnf via wrappers
mkdir -p "$TEXMFCNF"
if [[ -e $texmfdist/web2c/texmfcnf.lua ]]; then
tlutils_info "writing texmfcnf.lua to $TEXMFCNF/texmfcnf.lua"
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
tlutils_info "writing texmf.cnf to $TEXMFCNF/texmf.cnf"
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" \
"$texmfdist/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf"
}
# run postaction scripts from texlive.tlpdb
# note that the other postactions (fileassoc, ...) are Windows only
installtl_do_tlpdb_postactions () {
local postaction postInterp
if [[ -n $postactionScripts ]] ; then
tlutils_info "running package-specific postactions"
for postaction in $postactionScripts ; do
# see TeXLive::TLUtils::_installtl_do_postaction_script
case "$postaction" in
*.pl)
postInterp=perl ;;
*.texlua)
postInterp=texlua ;;
*)
postInterp= ;;
esac
tlutils_info "${postInterp:+$postInterp }$postaction install $texmfroot"
FORCE_SOURCE_DATE=1 $postInterp "$texmfroot/$postaction" install "$texmfroot" >>"$TEXMFSYSVAR/postaction-${postaction##*/}.log"
done
tlutils_info "finished with package-specific postactions"
fi
}
installtl_do_path_adjustments () {
# here install-tl would add a system symlink to the man pages
# instead we run other nixpkgs related adjustments
# generate wrappers
tlutils_info "wrapping binaries"
local bash cmd extraPaths link path target wrapCount
bash="$(command -v bash)"
enable -f "${bash%/bin/bash}"/lib/bash/realpath realpath
# common runtime dependencies
for cmd in cat awk sed grep gs ; do
# do not fail if gs is absent
path="$(PATH="$HOST_PATH" command -v "$cmd" || :)"
if [[ -n $path ]] ; then
extraPaths="${extraPaths:+$extraPaths:}${path%/"$cmd"}"
fi
done
declare -i wrapCount=0
for link in "$out"/bin/* ; do
target="$(realpath "$link")"
# skip non-executable files (such as context.lua)
if [[ ! -x $target ]] ; then
continue
fi
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 : "$extraPaths:$out/bin" \
--set-default TEXMFCNF "$TEXMFCNF" \
--set-default FONTCONFIG_FILE "$fontconfigFile"
wrapCount=$((wrapCount + 1))
done
tlutils_info "wrapped $wrapCount binaries and scripts"
# generate format symlinks (using fmtutil.cnf)
tlutils_info "generating format symlinks"
texlinks --quiet "$out/bin"
# remove *-sys scripts since /nix/store is readonly
rm "$out"/bin/*-sys
# link TEXMFDIST in $out/share for backward compatibility
ln -s "$texmfdist" "$out"/share/texmf
# generate other outputs
local otherOutput otherOutputName
local otherOutputs="$otherOutputs"
for otherOutputName in $outputs ; do
if [[ $otherOutputName == out ]] ; then
continue
fi
otherOutput="${otherOutputs%% *}"
otherOutputs="${otherOutputs#* }"
ln -s "$otherOutput" "${!otherOutputName}"
done
}
# run all post install parts
installtl_do_postinst_stuff () {
installtl_do_texmf_cnf
# create various config files
# in principle, we could use writeText and share them across different
# environments, but the eval & build overhead is not worth the savings
tlutils_create_fmtutil
tlutils_create_updmap
tlutils_create_language_dat
tlutils_create_language_def
tlutils_create_language_lua
# make new files available
tlutils_info "running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG"
mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG"
# update font maps
tlutils_info "generating font maps"
updmap-sys --quiet --force --nohash 2>&1
# configure the paper size
# tlmgr --no-execute-actions paper letter
# install-tl: "rerun mktexlsr for updmap-sys and tlmgr paper updates"
tlutils_info "re-running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG"
mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG"
tlutils_update_context_cache
# generate formats
# install-tl would run fmtutil-sys $common_fmtutil_args --no-strict --all
# instead, we want fmtutil to exit with error on failure
if [[ -n $fmtutilCnf ]] ; then
tlutils_info "pre-generating all format files, be patient..."
# 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-fail "my \$cmdline = \"\$eng -ini " "my \$cmdline = \"faketime -f '\@$(date +'%F %T' --date=@"$SOURCE_DATE_EPOCH") x0.001' \$eng -ini "
FORCE_SOURCE_DATE=1 perl fmtutil --quiet --strict --sys --all 2>&1 | grep '^fmtutil' # too verbose
fi
installtl_do_path_adjustments
installtl_do_tlpdb_postactions
# remove log files to improve reproducibility
find "$TEXMFSYSVAR" -name '*.log' -delete
}
### TeXLive::TLUtils
tlutils_info () {
printf '%s\n' "texlive: $*"
}
tlutils_create_fmtutil () {
# fmtutil.cnf created by install-tl already exists readonly in $texmfdist
# so here we need to *disable* the entries that are not in $fmtutilCnf
# and write the output in the writeable $TEXMFSYSVAR
local engine fmt line outFile sedExpr
outFile="$TEXMFSYSVAR"/web2c/fmtutil.cnf
tlutils_info "writing fmtutil.cnf to $outFile"
while IFS= read -r line ; do
# a line is 'fmt engine ...' or '#! fmt engine ...'
# (see fmtutil.pl::read_fmtutil_file)
line="${line#\#! }"
read -r fmt engine _ <<<"$line"
# if a line for the ($fmt,$engine) pair exists, remove it to avoid
# pointless warnings from fmtutil
sedExpr="$sedExpr /^(#! )?$fmt $engine /d;"
done <<<"$fmtutilCnf"
# disable all the remaining formats
sedExpr="$sedExpr /^[^#]/{ s/^/#! /p };"
{
echo "# Generated by nixpkgs"
sed -E -n -e "$sedExpr" "$texmfdist"/web2c/fmtutil.cnf
[[ -z $fmtutilCnf ]] || printf '%s' "$fmtutilCnf"
} >"$outFile"
}
tlutils_create_updmap () {
# updmap.cfg created by install-tl already exists readonly in $texmfdist
# so here we need to *disable* the entries that are not in $updmapCfg
# and write the output in the writeable $TEXMFSYSVAR
local line map outFile sedExpr
outFile="$TEXMFSYSVAR"/web2c/updmap.cfg
tlutils_info "writing updmap.cfg to $outFile"
while IFS= read -r line ; do
# a line is 'type map' or '#! type map'
# (see fmtutil.pl::read_updmap_file)
read -r _ map <<<"$line"
# if a line for $map exists, remove it to avoid
# pointless warnings from updmap
sedExpr="$sedExpr /^(#! )?[^ ]*Map $map$/d;"
done <<<"$updmapCfg"
# disable all the remaining font maps
sedExpr="$sedExpr /^[^ ]*Map/{ s/^/#! /p };"
{
echo "# Generated by nixpkgs"
sed -E -n -e "$sedExpr" "$texmfdist"/web2c/updmap.cfg
[[ -z $updmapCfg ]] || printf '%s' "$updmapCfg"
} >"$outFile"
}
tlutils__create_config_files () {
# simplified arguments
local header="$1"
local dest="$2"
local prefix="$3"
local lines="$4"
local suffix="$5"
if [[ -z "$header" || -e "$header" ]] ; then
tlutils_info "writing ${dest##*/} to $dest"
{
[[ -z $prefix ]] || printf '%s\n' "$prefix"
[[ ! -e $header ]] || cat "$header"
[[ -z $lines ]] || printf '%s\n' "$lines"
[[ -z $suffix ]] || printf '%s\n' "$suffix"
} >"$dest"
fi
}
tlutils_create_language_dat () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us \
"$TEXMFSYSVAR"/tex/generic/config/language.dat \
'% Generated by nixpkgs' \
"$languageDat" \
''
}
tlutils_create_language_def () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us.def \
"$TEXMFSYSVAR"/tex/generic/config/language.def \
'' \
"$languageDef" \
'%%% No changes may be made beyond this point.
\uselanguage {USenglish} %%% This MUST be the last line of the file.'
}
tlutils_create_language_lua () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us.lua \
"$TEXMFSYSVAR"/tex/generic/config/language.dat.lua \
'-- Generated by nixpkgs' \
"$languageLua" \
'}'
}
tlutils_update_context_cache () {
if [[ -x $out/bin/mtxrun ]] ; then
tlutils_info "setting up ConTeXt cache"
# temporarily patch mtxrun.lua to generate uuid's deterministically from SOURCE_DATE_EPOCH
mv "$out"/bin/mtxrun.lua{,.orig}
substitute "$out"/bin/mtxrun.lua.orig "$out"/bin/mtxrun.lua \
--replace-fail 'randomseed(math.initialseed)' "randomseed($SOURCE_DATE_EPOCH)"
# this is very verbose, save the output for debugging purposes
{
mtxrun --generate
context --luatex --generate
[[ ! -x $out/bin/luajittex ]] || context --luajittex --generate
} >"$TEXMFSYSVAR"/context-cache.log
mv "$out"/bin/mtxrun.lua{.orig,}
fi
}
# init variables (export only the ones that are used in the wrappers)
export PATH="$out/bin:$PATH"
TEXMFSYSCONFIG="$out/share/texmf-config"
TEXMFSYSVAR="$out/share/texmf-var"
export TEXMFCNF="$TEXMFSYSVAR/web2c"
installtl_do_postinst_stuff