texlive: merge withDocs, tlDeps updates and remove texlive.combine from the documentation (#523350)

This commit is contained in:
Dmitry Kalinkin
2026-05-24 16:27:43 +00:00
committed by GitHub
15 changed files with 573 additions and 607 deletions
+17 -65
View File
@@ -2,9 +2,7 @@
There is a TeX Live packaging that lives entirely under attribute `texlive`.
## User's guide (experimental new interface) {#sec-language-texlive-user-guide-experimental}
Release 23.11 ships with a new interface that will eventually replace `texlive.combine`.
## User's guide {#sec-language-texlive-user-guide}
- For basic usage, use some of the prebuilt environments available at the top level, such as `texliveBasic`, `texliveSmall`. For the full list of prebuilt environments, inspect `texlive.schemes`.
@@ -24,7 +22,7 @@ Release 23.11 ships with a new interface that will eventually replace `texlive.c
- `texlive.withPackages` uses the same logic as `buildEnv`. Only parts of a package are installed in an environment: its 'runtime' files (`tex` output), binaries (`out` output), and support files (`tlpkg` output). Moreover, man and info pages are assembled into separate `man` and `info` outputs. To add only the TeX files of a package, or its documentation (`texdoc` output), just specify the outputs:
```nix
texlive.withPackages (
texliveBasic.withPackages (
ps: with ps; [
texdoc # recommended package to navigate the documentation
perlPackages.LaTeXML.tex # tex files of LaTeXML, omit binaries
@@ -34,64 +32,19 @@ Release 23.11 ships with a new interface that will eventually replace `texlive.c
)
```
- To add the documentation for all packages in the environment, use
```nix
texliveSmall.overrideAttrs { withDocs = true; }
```
This can be applied before or after calling `withPackages`. The parameter `withSources` adds all source containers.
- All packages distributed by TeX Live, which contains most of CTAN, are available and can be found under `texlive.pkgs`:
```ShellSession
$ nix repl
nix-repl> :l <nixpkgs>
nix-repl> texlive.pkgs.[TAB]
```
Note that the packages in `texlive.pkgs` are only provided for search purposes and must not be used directly.
- **Experimental and subject to change without notice:** to add the documentation for all packages in the environment, use
```nix
texliveSmall.__overrideTeXConfig { withDocs = true; }
```
This can be applied before or after calling `withPackages`.
The function currently supports the parameters `withDocs`, `withSources`, and `requireTeXPackages`.
## User's guide {#sec-language-texlive-user-guide}
- For basic usage just pull `texlive.combined.scheme-basic` for an environment with basic LaTeX support.
- It typically won't work to use separately installed packages together. Instead, you can build a custom set of packages like this. Most CTAN packages should be available:
```nix
texlive.combine {
inherit (texlive)
scheme-small
collection-langkorean
algorithms
cm-super
;
}
```
- There are all the schemes, collections and a few thousand packages, as defined upstream (perhaps with tiny differences).
- By default you only get executables and files needed during runtime, and a little documentation for the core packages. To change that, you need to add `pkgFilter` function to `combine`.
```nix
texlive.combine {
# inherit (texlive) whatever-you-want;
pkgFilter =
pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.hasManpages || pkg.pname == "cm-super";
# elem tlType [ "run" "bin" "doc" "source" ]
# there are also other attributes: version, name
}
```
- You can list packages e.g. by `nix repl`.
```ShellSession
$ nix repl
nix-repl> :l <nixpkgs>
nix-repl> texlive.collection-[TAB]
```
- 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.
- 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
These are derivations with outputs `out`, `tex`, `texdoc`, `texsource`, `tlpkg`, `man`, `info`. They cannot be installed outside of `texlive.withPackages` but are available for other uses. To repackage a font, for instance, use
```nix
stdenvNoCC.mkDerivation (finalAttrs: {
@@ -112,9 +65,9 @@ Release 23.11 ships with a new interface that will eventually replace `texlive.c
## Custom packages {#sec-language-texlive-custom-packages}
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 `"tex"` output, according to the [TeX Directory Structure](https://tug.ctan.org/tds/tds.html). Dependencies on other TeX packages can be listed in the attribute `tlDeps`.
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 `"tex"` output, according to the [TeX Directory Structure](https://tug.ctan.org/tds/tds.html). Dependencies on other TeX packages can be listed in the attribute `passthru.tlDeps`, which is a function taking a package set and returning a list of packages.
The functions `texlive.combine` and `texlive.withPackages` recognise the following outputs:
The function `texlive.withPackages` recognise the following outputs:
- `"out"`: contents are linked in the TeX Live environment, and binaries in the `$out/bin` folder are wrapped;
- `"tex"`: linked in `$TEXMFDIST`; files should follow the TDS (for instance `$tex/tex/latex/foiltex/foiltex.cls`);
@@ -122,8 +75,6 @@ The functions `texlive.combine` and `texlive.withPackages` recognise the followi
- `"tlpkg"`: linked in `$TEXMFROOT/tlpkg`;
- `"man"`, `"info"`, ...: the other outputs are combined into separate outputs.
When using `pkgFilter`, `texlive.combine` will assign `tlType` respectively `"bin"`, `"run"`, `"doc"`, `"source"`, `"tlpkg"` to the above outputs.
Here is a (very verbose) example. See also the packages `auctex`, `eukleides`, `mftrace` for more examples.
```nix
@@ -138,7 +89,7 @@ let
"tex"
"texdoc"
];
passthru.tlDeps = with texlive; [ latex ];
passthru.tlDeps = ps: [ ps.latex ];
srcs = [
(fetchurl {
@@ -169,13 +120,14 @@ let
latexmk
]
))
# multiple-outputs.sh fails if $out is not defined
(writeShellScript "force-tex-output.sh" ''
out="''${tex-}"
'')
writableTmpDirAsHomeHook # Need a writable $HOME for latexmk
];
# multiple-outputs.sh fails if $out is not defined
preHook = ''
out="''${tex-}"
'';
dontConfigure = true;
buildPhase = ''
+2 -4
View File
@@ -4452,11 +4452,9 @@
"sec-language-texlive": [
"index.html#sec-language-texlive"
],
"sec-language-texlive-user-guide-experimental": [
"index.html#sec-language-texlive-user-guide-experimental"
],
"sec-language-texlive-user-guide": [
"index.html#sec-language-texlive-user-guide"
"index.html#sec-language-texlive-user-guide",
"index.html#sec-language-texlive-user-guide-experimental"
],
"sec-language-texlive-custom-packages": [
"index.html#sec-language-texlive-custom-packages"
+13 -17
View File
@@ -16,7 +16,6 @@
perl,
readline,
tcl,
texlive,
texliveSmall,
tk,
xz,
@@ -198,23 +197,20 @@ stdenv.mkDerivation (finalAttrs: {
passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
# make tex output available to texlive.combine
passthru.pkgs = [ finalAttrs.finalPackage.tex ];
passthru.tlType = "run";
# dependencies (based on \RequirePackage in jss.cls, Rd.sty, Sweave.sty)
passthru.tlDeps = with texlive; [
amsfonts
amsmath
fancyvrb
graphics
hyperref
iftex
jknapltx
latex
lm
tools
upquote
url
passthru.tlDeps = ps: [
ps.amsfonts
ps.amsmath
ps.fancyvrb
ps.graphics
ps.hyperref
ps.iftex
ps.jknapltx
ps.latex
ps.lm
ps.tools
ps.upquote
ps.url
];
meta = {
+36 -43
View File
@@ -7,50 +7,43 @@
ghostscript,
}:
let
auctex = stdenv.mkDerivation rec {
# Make this a valid tex(live-new) package;
# the pkgs attribute is provided with a hack below.
pname = "auctex";
version = "13.2";
tlType = "run";
stdenv.mkDerivation rec {
pname = "auctex";
version = "13.2";
outputs = [
"out"
"tex"
];
outputs = [
"out"
"tex"
];
src = fetchurl {
url = "mirror://gnu/auctex/auctex-${version}.tar.gz";
hash = "sha256-Hn5AKrz4RmlOuncZklvwlcI+8zpeZgIgHHS2ymCUQDU=";
};
buildInputs = [
emacs
ghostscript
(texliveBasic.withPackages (ps: [
ps.etoolbox
ps.hypdoc
]))
];
preConfigure = ''
mkdir -p "$tex"
export HOME=$(mktemp -d)
'';
configureFlags = [
"--with-lispdir=\${out}/share/emacs/site-lisp"
"--with-texmf-dir=\${tex}"
];
meta = {
homepage = "https://www.gnu.org/software/auctex";
description = "Extensible package for writing and formatting TeX files in GNU Emacs and XEmacs";
license = lib.licenses.gpl3Plus;
platforms = lib.platforms.unix;
};
src = fetchurl {
url = "mirror://gnu/auctex/auctex-${version}.tar.gz";
hash = "sha256-Hn5AKrz4RmlOuncZklvwlcI+8zpeZgIgHHS2ymCUQDU=";
};
in
auctex // { pkgs = [ auctex.tex ]; }
buildInputs = [
emacs
ghostscript
(texliveBasic.withPackages (ps: [
ps.etoolbox
ps.hypdoc
]))
];
preConfigure = ''
mkdir -p "$tex"
export HOME=$(mktemp -d)
'';
configureFlags = [
"--with-lispdir=\${out}/share/emacs/site-lisp"
"--with-texmf-dir=\${tex}"
];
meta = {
homepage = "https://www.gnu.org/software/auctex";
description = "Extensible package for writing and formatting TeX files in GNU Emacs and XEmacs";
license = lib.licenses.gpl3Plus;
platforms = lib.platforms.unix;
};
}
@@ -145,11 +145,6 @@ stdenv.mkDerivation (finalAttrs: {
perlWithPackages
];
passthru = {
tlType = "run";
pkgs = [ finalAttrs.finalPackage ];
};
meta = {
description = "Create and manage multiple choice questionnaires with automated marking";
mainProgram = "auto-multiple-choice";
+7 -12
View File
@@ -9,7 +9,6 @@
getopt,
readline,
texinfo,
texlive,
versionCheckHook,
}:
@@ -91,17 +90,13 @@ stdenv.mkDerivation (finalAttrs: {
"tex"
];
passthru = {
tlType = "run";
# packages needed by euktoeps, euktopdf and eukleides.sty
tlDeps = with texlive; [
collection-pstricks
epstopdf
iftex
moreverb
];
pkgs = [ finalAttrs.finalPackage.tex ];
};
# packages needed by euktoeps, euktopdf and eukleides.sty
passthru.tlDeps = ps: [
ps.collection-pstricks
ps.epstopdf
ps.iftex
ps.moreverb
];
doInstallCheck = true;
nativeInstallCheckInputs = [ versionCheckHook ];
+3 -4
View File
@@ -2,7 +2,6 @@
lib,
stdenvNoCC,
fetchzip,
texlive,
callPackage,
}:
@@ -47,9 +46,9 @@ stdenvNoCC.mkDerivation rec {
'';
passthru = {
tlDeps = with texlive; [
xkeyval
fontspec
tlDeps = ps: [
ps.xkeyval
ps.fontspec
];
tests = callPackage ./tests.nix { };
+5 -7
View File
@@ -7,7 +7,6 @@
python3,
fontforge,
potrace,
texlive,
fetchpatch2,
}:
@@ -59,12 +58,11 @@ stdenv.mkDerivation (finalAttrs: {
wrapProgram $out/bin/mftrace --prefix PATH : ${lib.makeBinPath finalAttrs.buildInputs}
'';
# experimental texlive.combine support
# (note that only the bin/ folder will be combined into texlive)
passthru.tlDeps = with texlive; [
kpathsea
t1utils
metafont
# for use with texlive.withPackages
passthru.tlDeps = ps: [
ps.kpathsea
ps.t1utils
ps.metafont
];
meta = {
-5
View File
@@ -88,11 +88,6 @@ stdenv.mkDerivation (finalAttrs: {
"tex"
];
passthru = {
tlType = "run";
pkgs = [ finalAttrs.finalPackage.tex ];
};
meta = {
description = "Simple, extensible literate-programming tool";
homepage = "https://www.cs.tufts.edu/~nr/noweb";
+2 -6
View File
@@ -239,11 +239,7 @@ rec {
runCommand "texlive-test-texdoc"
{
nativeBuildInputs = [
(texlive.withPackages (ps: [
ps.luatex
ps.texdoc
ps.texdoc.texdoc
]))
((texlive.withPackages (ps: [ ps.texdoc ])).overrideAttrs { withDocs = true; })
];
}
''
@@ -951,7 +947,7 @@ rec {
scheme:
builtins.foldl' (
acc: pkg: concatLicenses acc (lib.toList (pkg.meta.license or [ ]))
) [ ] scheme.passthru.requiredTeXPackages;
) [ ] scheme.passthru.includedTeXPackages;
correctLicensesAttrNames = scheme: lib.sort lt (map licenseToAttrName (correctLicenses scheme));
hasLicenseMismatch =
@@ -1,7 +1,6 @@
{
# texlive package set
tl,
bin,
tlpdbVersion,
@@ -11,10 +10,7 @@
makeFontsConf,
makeWrapper,
runCommand,
writeShellScript,
writeText,
toTLPkgSets,
bash,
perl,
# common runtime dependencies
@@ -26,12 +22,9 @@
}:
lib.fix (
self:
buildTeXEnv:
{
withDocs ? false,
withSources ? false,
requiredTeXPackages ? ps: [ ps.scheme-infraonly ],
### texlive.combine backward compatibility
__extraName ? "combined",
__extraVersion ? "",
@@ -41,448 +34,494 @@ lib.fix (
__fromCombineWrapper ? false,
# build only the formats of a package (for internal use!)
__formatsOf ? null,
}@args:
}:
buildEnv (
finalAttrs:
let
### texlive.combine backward compatibility
# if necessary, convert old style { pkgs = [ ... ]; } packages to attribute sets
isOldPkgList = p: !p.outputSpecified or false && p ? pkgs && builtins.all (p: p ? tlType) p.pkgs;
ensurePkgSets =
ps:
if !__fromCombineWrapper && builtins.any isOldPkgList ps then
let
oldPkgLists = builtins.partition isOldPkgList ps;
in
oldPkgLists.wrong ++ lib.concatMap toTLPkgSets oldPkgLists.right
else
ps;
pkgList = rec {
# resolve dependencies of the packages that affect the runtime
all =
let
packages = ensurePkgSets (requiredTeXPackages tl);
runtime = builtins.partition (
p:
p.outputSpecified or false
-> builtins.elem (p.tlOutputName or p.outputName) [
"out"
"tex"
"tlpkg"
]
) packages;
keySet = p: {
key =
p.pname or p.name
+ lib.optionalString (p.outputSpecified or false) ("-" + p.tlOutputName or p.outputName or "");
inherit p;
tlDeps = if p ? tlDeps then ensurePkgSets p.tlDeps else (p.requiredTeXPackages or (_: [ ]) tl);
};
in
# texlive.combine: the wrapper already resolves all dependencies
if __fromCombineWrapper then
requiredTeXPackages null
let
# if necessary, convert old style { pkgs = [ ... ]; } packages to attribute sets
isOldPkgList = p: !p.outputSpecified or false && p ? pkgs && builtins.all (p: p ? tlType) p.pkgs;
ensurePkgSets =
ps:
if !finalAttrs.passthru.__fromCombineWrapper && builtins.any isOldPkgList ps then
let
oldPkgLists = builtins.partition isOldPkgList ps;
in
oldPkgLists.wrong ++ lib.concatMap toTLPkgSets oldPkgLists.right
else
builtins.catAttrs "p" (
builtins.genericClosure {
startSet = map keySet runtime.right;
operator = p: map keySet p.tlDeps;
}
)
++ runtime.wrong;
ps;
# group the specified outputs
specified = builtins.partition (p: p.outputSpecified or false) all;
specifiedOutputs = lib.groupBy (p: p.tlOutputName or p.outputName) specified.right;
otherOutputNames = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
lib.concatLists (builtins.catAttrs "outputs" specified.wrong)
);
operator = _: [ ];
}
);
otherOutputs = lib.genAttrs otherOutputNames (n: builtins.catAttrs n specified.wrong);
outputsToInstall = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
[ "out" ]
++ lib.optional (otherOutputs ? man) "man"
++ lib.concatLists (builtins.catAttrs "outputsToInstall" (builtins.catAttrs "meta" specified.wrong))
);
operator = _: [ ];
}
);
pkgList = rec {
# resolve dependencies of the packages that affect the runtime
all =
let
packages = ensurePkgSets (finalAttrs.passthru.requiredTeXPackages tl);
runtime = builtins.partition (
p:
p.outputSpecified or false
-> builtins.elem (p.tlOutputName or p.outputName) [
"out"
"tex"
"tlpkg"
]
) packages;
keySet = p: {
key =
p.pname or p.name
+ lib.optionalString (p.outputSpecified or false) ("-" + p.tlOutputName or p.outputName or "");
inherit p;
tlDeps =
if p ? tlDeps then
(if builtins.isFunction p.tlDeps then p.tlDeps tl else ensurePkgSets p.tlDeps)
else
[ ];
};
in
# texlive.combine: the wrapper already resolves all dependencies
if finalAttrs.passthru.__fromCombineWrapper then
finalAttrs.passthru.requiredTeXPackages null
else
builtins.catAttrs "p" (
builtins.genericClosure {
startSet = map keySet runtime.right;
operator = p: map keySet p.tlDeps;
}
)
++ runtime.wrong;
# split binary and tlpkg from tex, texdoc, texsource
bin =
if __fromCombineWrapper then
builtins.filter (p: p.tlType == "bin") all # texlive.combine: legacy filter
else
otherOutputs.out or [ ] ++ specifiedOutputs.out or [ ];
tlpkg =
if __fromCombineWrapper then
builtins.filter (p: p.tlType == "tlpkg") all # texlive.combine: legacy filter
else
otherOutputs.tlpkg or [ ] ++ specifiedOutputs.tlpkg or [ ];
nonbin =
if __fromCombineWrapper then
builtins.filter (p: p.tlType != "bin" && p.tlType != "tlpkg") all # texlive.combine: legacy filter
else
(
if __combine then # texlive.combine: emulate old input ordering to avoid rebuilds
lib.concatMap (
p:
lib.optional (p ? tex) p.tex
++ lib.optional ((withDocs || p ? man) && p ? texdoc) p.texdoc
++ lib.optional (withSources && p ? texsource) p.texsource
) specified.wrong
else
otherOutputs.tex or [ ]
++ lib.optionals withDocs (otherOutputs.texdoc or [ ])
++ lib.optionals withSources (otherOutputs.texsource or [ ])
)
++ specifiedOutputs.tex or [ ]
++ specifiedOutputs.texdoc or [ ]
++ specifiedOutputs.texsource or [ ];
# outputs that do not become part of the environment
nonEnvOutputs = lib.subtractLists [ "out" "tex" "texdoc" "texsource" "tlpkg" ] otherOutputNames;
# packages that contribute to config files and formats
fontMaps = lib.filter (p: p ? fontMaps && (p.tlOutputName or p.outputName == "tex")) nonbin;
sortedFontMaps = builtins.sort (a: b: a.pname < b.pname) fontMaps;
hyphenPatterns = lib.filter (
p: p ? hyphenPatterns && (p.tlOutputName or p.outputName == "tex")
) nonbin;
sortedHyphenPatterns = builtins.sort (a: b: a.pname < b.pname) hyphenPatterns;
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;
sortedFormatPkgs =
if __formatsOf != null then [ __formatsOf ] else builtins.sort (a: b: a.pname < b.pname) formatPkgs;
formats = map (
p:
self {
requiredTeXPackages =
ps:
[
ps.scheme-infraonly
p
]
++ hyphenPatterns;
__formatsOf = p;
}
) sortedFormatPkgs;
};
# list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts`
# and `grep -IR rungs "$TEXMFDIST"`
# and ignoring luatex, perl, and shell scripts (those must be patched using postFixup)
needsGhostscript = lib.any (
p:
lib.elem p.pname [
"context"
"dvipdfmx"
"latex-papersize"
"lyluatex"
]
) pkgList.bin;
pname =
if __combine then
"texlive-${__extraName}" # texlive.combine: old name
else
"texlive";
version =
if __combine then
"${toString tlpdbVersion.year}${__extraVersion}" # texlive.combine: old version
else
"${toString tlpdbVersion.year}-r${toString tlpdbVersion.revision}-"
+ (lib.optionalString tlpdbVersion.frozen "final-")
+ (if __formatsOf != null then "${__formatsOf.pname}-fmt" else "env");
name = "${pname}-${version}";
texmfdist = buildEnv {
name = "${name}-texmfdist";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.nonbin;
# mktexlsr
nativeBuildInputs = [
tl.texlive-scripts # for mktexlsr.pl with --sort support
perl
];
postBuild = # generate ls-R database
''
perl ${tl.texlive-scripts.tex}/scripts/texlive/mktexlsr.pl --sort "$out"
'';
};
tlpkg = buildEnv {
name = "${name}-tlpkg";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.tlpkg;
};
# the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist
# and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both)
texmfroot =
runCommand "${name}-texmfroot"
{
inherit texmfdist tlpkg;
}
''
mkdir -p "$out"
ln -s "$texmfdist" "$out"/texmf-dist
ln -s "$tlpkg" "$out"/tlpkg
'';
# texlive.combine: expose info and man pages in usual /share/{info,man} location
doc = buildEnv {
name = "${name}-doc";
paths = [ (texmfdist.outPath + "/doc") ];
extraPrefix = "/share";
pathsToLink = [
"/info"
"/man"
];
};
meta = {
description =
"TeX Live environment"
+ lib.optionalString withDocs " with documentation"
+ lib.optionalString (withDocs && withSources) " and"
+ lib.optionalString withSources " with sources";
platforms = lib.platforms.all;
longDescription =
"Contains the following packages and their transitive dependencies:\n - "
+ lib.concatMapStringsSep "\n - " (
p:
p.pname + (lib.optionalString (p.outputSpecified or false) " (${p.tlOutputName or p.outputName})")
) (requiredTeXPackages tl);
};
# other outputs
nonEnvOutputs = lib.genAttrs pkgList.nonEnvOutputs (
outName:
buildEnv {
inherit name;
paths = builtins.catAttrs "outPath" (
pkgList.otherOutputs.${outName} or [ ] ++ pkgList.specifiedOutputs.${outName} or [ ]
# group the specified outputs
specified = builtins.partition (p: p.outputSpecified or false) all;
specifiedOutputs = lib.groupBy (p: p.tlOutputName or p.outputName) specified.right;
otherOutputNames = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
lib.concatLists (builtins.catAttrs "outputs" specified.wrong)
);
operator = _: [ ];
}
);
derivationArgs = {
outputs = [ outName ];
nativeBuildInputs = [
# force the output to be ${outName} or nix-env will not work
(writeShellScript "force-output.sh" ''
export out="''${${outName}-}"
'')
];
inherit meta passthru;
};
}
);
passthru = {
# This is set primarily to help find-tarballs.nix to do its job
requiredTeXPackages = builtins.filter lib.isDerivation (
pkgList.bin
++ pkgList.nonbin
++ lib.optionals (!__fromCombineWrapper) (
lib.concatMap (
n: (pkgList.otherOutputs.${n} or [ ] ++ pkgList.specifiedOutputs.${n} or [ ])
) pkgList.nonEnvOutputs
)
);
# useful for inclusion in the `fonts.packages` nixos option or for use in devshells
fonts = "${texmfroot}/texmf-dist/fonts";
# support variants attrs, (prev: attrs)
__overrideTeXConfig =
newArgs:
let
appliedArgs = if builtins.isFunction newArgs then newArgs args else newArgs;
in
self (args // { __fromCombineWrapper = false; } // appliedArgs);
withPackages =
reqs:
self (
args
// {
requiredTeXPackages = ps: reqs ps ++ requiredTeXPackages ps;
__fromCombineWrapper = false;
otherOutputs = lib.genAttrs otherOutputNames (n: builtins.catAttrs n specified.wrong);
outputsToInstall = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
[ "out" ]
++ lib.optional (otherOutputs ? man) "man"
++ lib.concatLists (builtins.catAttrs "outputsToInstall" (builtins.catAttrs "meta" specified.wrong))
);
operator = _: [ ];
}
);
};
# TeXLive::TLOBJ::fmtutil_cnf_lines
fmtutilLine =
{
name,
engine,
enabled ? true,
patterns ? [ "-" ],
options ? "",
...
}:
lib.optionalString (!enabled) "#! "
+ "${name} ${engine} ${lib.concatStringsSep "," patterns} ${options}";
fmtutilLines =
{ pname, formats, ... }:
[
"#"
"# from ${pname}:"
]
++ map fmtutilLine formats;
# split binary and tlpkg from tex, texdoc, texsource
bin =
if finalAttrs.passthru.__fromCombineWrapper then
builtins.filter (p: p.tlType == "bin") all # texlive.combine: legacy filter
else
otherOutputs.out or [ ] ++ specifiedOutputs.out or [ ];
tlpkg =
if finalAttrs.passthru.__fromCombineWrapper then
builtins.filter (p: p.tlType == "tlpkg") all # texlive.combine: legacy filter
else
otherOutputs.tlpkg or [ ] ++ specifiedOutputs.tlpkg or [ ];
# TeXLive::TLOBJ::language_dat_lines
langDatLine =
{
name,
file,
synonyms ? [ ],
...
}:
[ "${name} ${file}" ] ++ map (s: "=" + s) synonyms;
langDatLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDatLine hyphenPatterns;
nonbin =
if finalAttrs.passthru.__fromCombineWrapper then
builtins.filter (p: p.tlType != "bin" && p.tlType != "tlpkg") all # texlive.combine: legacy filter
else
(
if finalAttrs.__combine then # texlive.combine: emulate old input ordering to avoid rebuilds
lib.concatMap (
p:
lib.optional (p ? tex) p.tex
++ lib.optional ((finalAttrs.withDocs || p ? man) && p ? texdoc) p.texdoc
++ lib.optional (finalAttrs.withSources && p ? texsource) p.texsource
) specified.wrong
else
otherOutputs.tex or [ ]
++ lib.optionals finalAttrs.withDocs (otherOutputs.texdoc or [ ])
++ lib.optionals finalAttrs.withSources (otherOutputs.texsource or [ ])
)
++ specifiedOutputs.tex or [ ]
++ specifiedOutputs.texdoc or [ ]
++ specifiedOutputs.texsource or [ ];
# TeXLive::TLOBJ::language_def_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langDefLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}:
map (
n:
"\\addlanguage{${n}}{${file}}{}{${if lefthyphenmin == "" then "2" else lefthyphenmin}}{${
if righthyphenmin == "" then "3" else righthyphenmin
}}"
) ([ name ] ++ synonyms);
langDefLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDefLine hyphenPatterns;
# outputs that do not become part of the environment
nonEnvOutputs = lib.subtractLists [ "out" "tex" "texdoc" "texsource" "tlpkg" ] otherOutputNames;
# TeXLive::TLOBJ::language_lua_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langLuaLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}@args:
''
''\t['${name}'] = {
''\t''\tloader = '${file}',
''\t''\tlefthyphenmin = ${if lefthyphenmin == "" then "2" else lefthyphenmin},
''\t''\trighthyphenmin = ${if righthyphenmin == "" then "3" else righthyphenmin},
''\t''\tsynonyms = { ${lib.concatStringsSep ", " (map (s: "'${s}'") synonyms)} },
''
+ lib.optionalString (args ? file_patterns) "\t\tpatterns = '${args.file_patterns}',\n"
+ lib.optionalString (args ? file_exceptions) "\t\thyphenation = '${args.file_exceptions}',\n"
+ lib.optionalString (args ? luaspecial) "\t\tspecial = '${args.luaspecial}',\n"
+ "\t},";
langLuaLines =
{ pname, hyphenPatterns, ... }: [ "-- from ${pname}:" ] ++ map langLuaLine hyphenPatterns;
# packages that contribute to config files and formats
fontMaps = lib.filter (p: p ? fontMaps && (p.tlOutputName or p.outputName == "tex")) nonbin;
sortedFontMaps = builtins.sort (a: b: a.pname < b.pname) fontMaps;
hyphenPatterns = lib.filter (
p: p ? hyphenPatterns && (p.tlOutputName or p.outputName == "tex")
) nonbin;
sortedHyphenPatterns = builtins.sort (a: b: a.pname < b.pname) hyphenPatterns;
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;
sortedFormatPkgs =
if __formatsOf != null then [ __formatsOf ] else builtins.sort (a: b: a.pname < b.pname) formatPkgs;
formats = map (
p:
buildTeXEnv {
requiredTeXPackages =
ps:
[
ps.scheme-infraonly
p
]
++ hyphenPatterns;
__formatsOf = p;
}
) sortedFormatPkgs;
};
assembleConfigLines = f: packages: builtins.concatStringsSep "\n" (builtins.concatMap f packages);
# list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts`
# and `grep -IR rungs "$TEXMFDIST"`
# and ignoring luatex, perl, and shell scripts (those must be patched using postFixup)
needsGhostscript = lib.any (
p:
lib.elem p.pname [
"context"
"dvipdfmx"
"latex-papersize"
"lyluatex"
]
) pkgList.bin;
updmapLines = { pname, fontMaps, ... }: [ "# from ${pname}:" ] ++ fontMaps;
pname =
if finalAttrs.__combine then
"texlive-${finalAttrs.passthru.__extraName}" # texlive.combine: old name
else
"texlive";
version =
if finalAttrs.__combine then
"${toString tlpdbVersion.year}${finalAttrs.passthru.__extraVersion}" # texlive.combine: old version
else
"${toString tlpdbVersion.year}-r${toString tlpdbVersion.revision}-"
+ (lib.optionalString tlpdbVersion.frozen "final-")
+ (if __formatsOf != null then "${__formatsOf.pname}-fmt" else "env");
in
buildEnv {
name = "${pname}-${version}";
inherit name;
texmfdist = buildEnv {
name = "${name}-texmfdist";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths =
builtins.catAttrs "outPath" pkgList.bin
++ lib.optionals (!__combine && __formatsOf == null) pkgList.formats
++ lib.optional __combine doc;
pathsToLink = [
"/"
"/share/texmf-var/scripts"
"/share/texmf-var/tex/generic/config"
"/share/texmf-var/web2c"
"/share/texmf-config"
"/bin" # ensure these are writeable directories
];
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.nonbin;
postBuild = ''
. "${./build-tex-env.sh}"
'';
# mktexlsr
nativeBuildInputs = [
tl.texlive-scripts # for mktexlsr.pl with --sort support
perl
];
derivationArgs = {
# use attrNames, attrValues to ensure the two lists are sorted in the same way
outputs = [
"out"
]
++ lib.optionals (!__combine && __formatsOf == null) (builtins.attrNames nonEnvOutputs);
otherOutputs = lib.optionals (!__combine && __formatsOf == null) (
builtins.attrValues nonEnvOutputs
postBuild = # generate ls-R database
''
perl ${tl.texlive-scripts.tex}/scripts/texlive/mktexlsr.pl --sort "$out"
'';
};
tlpkg = buildEnv {
name = "${name}-tlpkg";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.tlpkg;
};
# the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist
# and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both)
texmfroot =
runCommand "${name}-texmfroot"
{
inherit texmfdist tlpkg;
}
''
mkdir -p "$out"
ln -s "$texmfdist" "$out"/texmf-dist
ln -s "$tlpkg" "$out"/tlpkg
'';
# texlive.combine: expose info and man pages in usual /share/{info,man} location
doc = buildEnv {
name = "${name}-doc";
paths = [ (texmfdist.outPath + "/doc") ];
extraPrefix = "/share";
pathsToLink = [
"/info"
"/man"
];
};
meta = {
description =
"TeX Live environment"
+ lib.optionalString finalAttrs.withDocs " with documentation"
+ lib.optionalString (finalAttrs.withDocs && finalAttrs.withSources) " and"
+ lib.optionalString finalAttrs.withSources " with sources";
platforms = lib.platforms.all;
longDescription =
"Contains the following packages and their transitive dependencies:\n - "
+ lib.concatMapStringsSep "\n - " (
p:
p.pname + (lib.optionalString (p.outputSpecified or false) " (${p.tlOutputName or p.outputName})")
) (finalAttrs.passthru.requiredTeXPackages tl);
};
# other outputs
nonEnvOutputs = lib.genAttrs pkgList.nonEnvOutputs (
outName:
buildEnv {
inherit name;
paths = builtins.catAttrs "outPath" (
pkgList.otherOutputs.${outName} or [ ] ++ pkgList.specifiedOutputs.${outName} or [ ]
);
derivationArgs = {
outputs = [ outName ];
# force the output to be ${outName} or nix-env will not work
preHook = ''
export out="''${${outName}}"
'';
inherit meta passthru;
};
}
);
nativeBuildInputs = [
makeWrapper
libfaketime
tl."texlive.infra" # mktexlsr
tl.texlive-scripts # fmtutil, updmap
tl.texlive-scripts-extra # texlinks
perl
passthru = {
inherit
requiredTeXPackages
__fromCombineWrapper
__extraName
__extraVersion
;
# This is set primarily to help find-tarballs.nix to do its job
includedTeXPackages = builtins.filter lib.isDerivation (
pkgList.bin
++ pkgList.nonbin
++ lib.optionals (!finalAttrs.passthru.__fromCombineWrapper) (
lib.concatMap (
n: (pkgList.otherOutputs.${n} or [ ] ++ pkgList.specifiedOutputs.${n} or [ ])
) pkgList.nonEnvOutputs
)
);
# useful for inclusion in the `fonts.packages` nixos option or for use in devshells
fonts = "${texmfroot}/texmf-dist/fonts";
__overrideTeXConfig = lib.warn "__overrideTeXConfig is deprecated, please switch to overrideAttrs" (
newArgs:
let
# arguments of buildTeXEnv before deprecation of __overrideTeXConfig
prevArgs = {
inherit (finalAttrs)
__combine
;
inherit (finalAttrs.passthru)
requiredTeXPackages
__extraName
__extraVersion
__fromCombineWrapper
;
}
// lib.optionalAttrs (finalAttrs ? withDocs) { inherit (finalAttrs) withDocs; }
// lib.optionalAttrs (finalAttrs ? withSources) { inherit (finalAttrs) withSources; };
appliedArgs = prevArgs // (if builtins.isFunction newArgs then newArgs prevArgs else newArgs);
in
finalAttrs.finalPackage.overrideAttrs (
prevAttrs:
{
passthru = prevAttrs.passthru // {
inherit (appliedArgs)
requiredTeXPackages
__extraName
__extraVersion
;
__fromCombineWrapper = false;
};
inherit (appliedArgs) __combine;
}
// lib.optionalAttrs (appliedArgs ? withDocs) { inherit (appliedArgs) withDocs; }
// lib.optionalAttrs (appliedArgs ? withSources) { inherit (appliedArgs) withSources; }
)
);
withPackages =
reqs:
finalAttrs.finalPackage.overrideAttrs (prevAttrs: {
passthru = prevAttrs.passthru // {
requiredTeXPackages = ps: reqs ps ++ prevAttrs.passthru.requiredTeXPackages ps;
__fromCombineWrapper = false;
};
});
};
# TeXLive::TLOBJ::fmtutil_cnf_lines
fmtutilLine =
{
name,
engine,
enabled ? true,
patterns ? [ "-" ],
options ? "",
...
}:
lib.optionalString (!enabled) "#! "
+ "${name} ${engine} ${lib.concatStringsSep "," patterns} ${options}";
fmtutilLines =
{ pname, formats, ... }:
[
"#"
"# from ${pname}:"
]
++ map fmtutilLine formats;
# TeXLive::TLOBJ::language_dat_lines
langDatLine =
{
name,
file,
synonyms ? [ ],
...
}:
[ "${name} ${file}" ] ++ map (s: "=" + s) synonyms;
langDatLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDatLine hyphenPatterns;
# TeXLive::TLOBJ::language_def_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langDefLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}:
map (
n:
"\\addlanguage{${n}}{${file}}{}{${if lefthyphenmin == "" then "2" else lefthyphenmin}}{${
if righthyphenmin == "" then "3" else righthyphenmin
}}"
) ([ name ] ++ synonyms);
langDefLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDefLine hyphenPatterns;
# TeXLive::TLOBJ::language_lua_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langLuaLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}@args:
''
''\t['${name}'] = {
''\t''\tloader = '${file}',
''\t''\tlefthyphenmin = ${if lefthyphenmin == "" then "2" else lefthyphenmin},
''\t''\trighthyphenmin = ${if righthyphenmin == "" then "3" else righthyphenmin},
''\t''\tsynonyms = { ${lib.concatStringsSep ", " (map (s: "'${s}'") synonyms)} },
''
+ lib.optionalString (args ? file_patterns) "\t\tpatterns = '${args.file_patterns}',\n"
+ lib.optionalString (args ? file_exceptions) "\t\thyphenation = '${args.file_exceptions}',\n"
+ lib.optionalString (args ? luaspecial) "\t\tspecial = '${args.luaspecial}',\n"
+ "\t},";
langLuaLines =
{ pname, hyphenPatterns, ... }: [ "-- from ${pname}:" ] ++ map langLuaLine hyphenPatterns;
assembleConfigLines = f: packages: builtins.concatStringsSep "\n" (builtins.concatMap f packages);
updmapLines = { pname, fontMaps, ... }: [ "# from ${pname}:" ] ++ fontMaps;
in
{
inherit name;
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths =
builtins.catAttrs "outPath" pkgList.bin
++ lib.optionals (!finalAttrs.__combine && __formatsOf == null) pkgList.formats
++ lib.optional finalAttrs.__combine doc;
pathsToLink = [
"/"
"/share/texmf-var/scripts"
"/share/texmf-var/tex/generic/config"
"/share/texmf-var/web2c"
"/share/texmf-config"
"/bin" # ensure these are writeable directories
];
buildInputs = [
coreutils
gawk
gnugrep
gnused
]
++ lib.optional needsGhostscript ghostscript;
postBuild = ''
. "${./build-tex-env.sh}"
'';
inherit passthru __combine;
__formatsOf = __formatsOf.pname or null;
derivationArgs = {
# use attrNames, attrValues to ensure the two lists are sorted in the same way
outputs = [
"out"
]
++ lib.optionals (!finalAttrs.__combine && __formatsOf == null) (builtins.attrNames nonEnvOutputs);
otherOutputs = lib.optionals (!finalAttrs.__combine && __formatsOf == null) (
builtins.attrValues nonEnvOutputs
);
inherit texmfdist texmfroot;
strictDeps = true;
fontconfigFile = makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; };
nativeBuildInputs = [
makeWrapper
libfaketime
tl."texlive.infra" # mktexlsr
tl.texlive-scripts # fmtutil, updmap
tl.texlive-scripts-extra # texlinks
perl
];
fmtutilCnf = assembleConfigLines fmtutilLines pkgList.sortedFormatPkgs;
updmapCfg = assembleConfigLines updmapLines pkgList.sortedFontMaps;
buildInputs = [
coreutils
gawk
gnugrep
gnused
]
++ lib.optional needsGhostscript ghostscript;
languageDat = assembleConfigLines langDatLines pkgList.sortedHyphenPatterns;
languageDef = assembleConfigLines langDefLines pkgList.sortedHyphenPatterns;
languageLua = assembleConfigLines langLuaLines pkgList.sortedHyphenPatterns;
inherit passthru __combine;
__formatsOf = __formatsOf.pname or null;
postactionScripts = builtins.catAttrs "postactionScript" pkgList.tlpkg;
inherit texmfdist texmfroot;
allowSubstitutes = true;
preferLocalBuild = false;
fontconfigFile = makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; };
meta =
meta
// lib.optionalAttrs (!__combine && __formatsOf == null) {
inherit (pkgList) outputsToInstall;
};
};
}
fmtutilCnf = assembleConfigLines fmtutilLines pkgList.sortedFormatPkgs;
updmapCfg = assembleConfigLines updmapLines pkgList.sortedFontMaps;
languageDat = assembleConfigLines langDatLines pkgList.sortedHyphenPatterns;
languageDef = assembleConfigLines langDefLines pkgList.sortedHyphenPatterns;
languageLua = assembleConfigLines langLuaLines pkgList.sortedHyphenPatterns;
postactionScripts = builtins.catAttrs "postactionScript" pkgList.tlpkg;
# whethe to include doc, source containers
withDocs = false;
withSources = false;
allowSubstitutes = true;
preferLocalBuild = false;
meta =
meta
// lib.optionalAttrs (!finalAttrs.__combine && __formatsOf == null) {
inherit (pkgList) outputsToInstall;
};
};
}
)
)
@@ -2,7 +2,7 @@
{
lib,
toTLPkgList,
toTLPkgSets,
tl,
buildTeXEnv,
}:
args@{
@@ -46,7 +46,11 @@ let
in
builtins.genericClosure {
startSet = pkgListToSets pkgList;
operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or [ ]);
operator =
{ pkg, ... }:
pkgListToSets (
if pkg ? tlDeps then if builtins.isFunction pkg.tlDeps then pkg.tlDeps tl else pkg.tlDeps else [ ]
);
}
);
combined = combinePkgs (lib.attrValues pkgSet);
+20 -11
View File
@@ -233,7 +233,7 @@ let
# function for creating a working environment
buildTeXEnv = import ./build-tex-env.nix {
inherit bin tl;
inherit tl;
inherit tlpdbVersion;
ghostscript = ghostscript_headless;
inherit
@@ -243,10 +243,7 @@ let
makeFontsConf
makeWrapper
runCommand
writeShellScript
writeText
toTLPkgSets
bash
perl
coreutils
gawk
@@ -260,19 +257,31 @@ let
# respecting specified outputs
toTLPkgList =
drv:
let
drvWithoutDeps = removeAttrs drv [ "tlDeps" ];
drvWithDeps =
if (drv ? tlDeps) then
drv // { tlDeps = if builtins.isFunction drv.tlDeps then drv.tlDeps tl else drv.tlDeps; }
else
drv;
in
if drv.outputSpecified or false then
let
tlType = drv.tlType or tlOutToType.${drv.tlOutputName or drv.outputName} or null;
in
lib.optional (tlType != null) (drv // { inherit tlType; })
lib.optional (tlType != null) (drvWithDeps // { inherit tlType; })
else
[ (drv.tex // { tlType = "run"; }) ]
lib.optional (drv ? tex) (drvWithDeps.tex // { tlType = "run"; })
++ lib.optional (drv ? texdoc) (
drv.texdoc // { tlType = "doc"; } // lib.optionalAttrs (drv ? man) { hasManpages = true; }
drvWithoutDeps.texdoc
// {
tlType = "doc";
}
// lib.optionalAttrs (drv ? man) { hasManpages = true; }
)
++ lib.optional (drv ? texsource) (drv.texsource // { tlType = "source"; })
++ lib.optional (drv ? tlpkg) (drv.tlpkg // { tlType = "tlpkg"; })
++ lib.optional (drv ? out) (drv.out // { tlType = "bin"; });
++ lib.optional (drv ? texsource) (drvWithoutDeps.texsource // { tlType = "source"; })
++ lib.optional (drv ? tlpkg) (drvWithDeps.tlpkg // { tlType = "tlpkg"; })
++ lib.optional (drv ? out) (drvWithDeps.out // { tlType = "bin"; });
tlOutToType = {
out = "bin";
tex = "run";
@@ -315,8 +324,8 @@ let
inherit
buildTeXEnv
lib
tl
toTLPkgList
toTLPkgSets
;
};
+1
View File
@@ -1737,6 +1737,7 @@ with pkgs;
texliveSmall
texliveTeTeX
;
texliveFullWithDocs = texliveFull.overrideAttrs { withDocs = true; };
texlivePackages = recurseIntoAttrs (lib.mapAttrs (_: v: v.build) texlive.pkgs);
futhark = haskell.lib.compose.justStaticExecutables haskellPackages.futhark;
-4
View File
@@ -18573,10 +18573,6 @@ with self;
}
done
'';
passthru = {
tlType = "run";
pkgs = [ LaTeXML.tex ];
};
meta = {
description = "Transforms TeX and LaTeX into XML/HTML/MathML";
homepage = "https://dlmf.nist.gov/LaTeXML/";