core/pkgs/by-name/te/texlive/default.nix
2024-06-30 09:16:52 +01:00

620 lines
13 KiB
Nix

/*
TeX Live user docs
- source: ../../../../../doc/languages-frameworks/texlive.xml
- current html: https://nixos.org/nixpkgs/manual/#sec-language-texlive
*/
{
lib,
#, stdenv
gcc12Stdenv,
fetchurl,
runCommand,
writeShellScript,
writeText,
buildEnv,
callPackage,
ghostscript_headless,
harfbuzz,
makeWrapper,
installShellFiles,
python3,
ruby,
perl,
tk,
jdk,
bash,
snobol4,
coreutils,
findutils,
gawk,
getopt,
gnugrep,
gnumake,
gnupg,
gnused,
gzip,
html-tidy,
ncurses,
zip,
libfaketime,
asymptote,
biber-ms,
makeFontsConf,
useFixedHashes ? true,
recurseIntoAttrs,
}:
let
stdenv = gcc12Stdenv;
in
let
# various binaries (compiled)
bin = callPackage ./bin.nix {
ghostscript = ghostscript_headless;
harfbuzz = harfbuzz.override {
withIcu = true;
withGraphite2 = true;
};
inherit useFixedHashes;
tlpdb = overriddenTlpdb;
};
tlpdb = import ./tlpdb.nix;
tlpdbVersion = tlpdb."00texlive.config";
# the set of TeX Live packages, collections, and schemes; using upstream naming
overriddenTlpdb =
let
overrides = import ./tlpdb-overrides.nix {
inherit
stdenv
lib
bin
tlpdb
tlpdbxz
tl
installShellFiles
coreutils
findutils
gawk
getopt
ghostscript_headless
gnugrep
gnumake
gnupg
gnused
gzip
html-tidy
ncurses
perl
python3
ruby
zip
;
};
in
overrides tlpdb;
version = {
# day of the snapshot being taken
year = "2024";
month = "03";
day = "16";
# TeX Live version
texliveYear = 2023;
# final (historic) release or snapshot
final = true;
};
# The tarballs on CTAN mirrors for the current release are constantly
# receiving updates, so we can't use those directly. Stable snapshots
# need to be used instead. Ideally, for the release branches of NixOS we
# should be switching to the tlnet-final versions
# (https://tug.org/historic/).
mirrors =
with version;
lib.optionals final [
# tlnet-final snapshot; used when texlive.tlpdb is frozen
# the TeX Live yearly freeze typically happens in mid-March
"http://ftp.math.utah.edu/pub/tex/historic/systems/texlive/${toString texliveYear}/tlnet-final"
"ftp://tug.org/texlive/historic/${toString texliveYear}/tlnet-final"
]
++ [
# CTAN mirrors
"https://mirror.ctan.org/systems/texlive/tlnet"
# daily snapshots hosted by one of the texlive release managers;
# used for packages that in the meanwhile have been updated or removed from CTAN
# and for packages that have not reached yet the historic mirrors
# please note that this server is not meant for large scale deployment
# https://tug.org/pipermail/tex-live/2019-November/044456.html
# https://texlive.info/ MUST appear last (see tlpdbxz)
"https://texlive.info/tlnet-archive/${year}/${month}/${day}/tlnet"
];
tlpdbxz = fetchurl {
urls =
map (up: "${up}/tlpkg/texlive.tlpdb.xz")
# use last mirror for daily snapshots as texlive.tlpdb.xz changes every day
# TODO make this less hacky
(if version.final then mirrors else [ (lib.last mirrors) ]);
hash = "sha256-w+04GBFDk/P/XvW7T9PotGD0nQslMkV9codca2urNK4=";
};
tlpdbNix =
runCommand "tlpdb.nix"
{
inherit tlpdbxz;
tl2nix = ./tl2nix.sed;
}
''
xzcat "$tlpdbxz" | sed -rn -f "$tl2nix" | uniq > "$out"
'';
# map: name -> fixed-output hash
fixedHashes = lib.optionalAttrs useFixedHashes (import ./fixed-hashes.nix);
buildTeXLivePackage = import ./build-texlive-package.nix {
inherit
lib
fetchurl
runCommand
writeShellScript
bash
jdk
perl
python3
ruby
snobol4
tk
;
texliveBinaries = bin;
};
tl = lib.mapAttrs (
pname:
{
revision,
extraRevision ? "",
...
}@args:
buildTeXLivePackage (
args
# NOTE: the fixed naming scheme must match generate-fixed-hashes.nix
// {
inherit mirrors pname;
fixedHashes = fixedHashes."${pname}-${toString revision}${extraRevision}" or { };
}
// lib.optionalAttrs (args ? deps) { deps = map (n: tl.${n}) (args.deps or [ ]); }
)
) overriddenTlpdb;
# function for creating a working environment
buildTeXEnv = import ./build-tex-env.nix {
inherit bin tl;
ghostscript = ghostscript_headless;
inherit
lib
buildEnv
libfaketime
makeFontsConf
makeWrapper
runCommand
writeShellScript
writeText
toTLPkgSets
bash
perl
coreutils
gawk
gnugrep
gnused
;
};
### texlive.combine compatibility layer:
# convert TeX packages to { pkgs = [ ... ]; } lists
# respecting specified outputs
toTLPkgList =
drv:
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; })
else
[ (drv.tex // { tlType = "run"; }) ]
++ lib.optional (drv ? texdoc) (
drv.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"; });
tlOutToType = {
out = "bin";
tex = "run";
texsource = "source";
texdoc = "doc";
tlpkg = "tlpkg";
};
# convert { pkgs = [ ... ]; } lists to TeX packages
# possibly more than one, if pkgs is also used to specify dependencies
tlTypeToOut = {
run = "tex";
doc = "texdoc";
source = "texsource";
bin = "out";
tlpkg = "tlpkg";
};
toSpecifiedNV = p: rec {
name = value.tlOutputName;
value = builtins.removeAttrs p [ "pkgs" ] // {
outputSpecified = true;
tlOutputName = tlTypeToOut.${p.tlType};
};
};
toTLPkgSet =
pname: drvs:
let
set = lib.listToAttrs (builtins.map toSpecifiedNV drvs);
mainDrv = set.out or set.tex or set.tlpkg or set.texdoc or set.texsource;
in
builtins.removeAttrs mainDrv [ "outputSpecified" ];
toTLPkgSets = { pkgs, ... }: lib.mapAttrsToList toTLPkgSet (builtins.groupBy (p: p.pname) pkgs);
# export TeX packages as { pkgs = [ ... ]; } in the top attribute set
allPkgLists = lib.mapAttrs (n: drv: { pkgs = toTLPkgList drv; }) tl;
# function for creating a working environment from a set of TL packages
# now a legacy wrapper around buildTeXEnv
combine = import ./combine-wrapper.nix {
inherit
buildTeXEnv
lib
toTLPkgList
toTLPkgSets
;
};
assertions =
with lib;
assertMsg (
tlpdbVersion.year == version.texliveYear
) "TeX Live year in texlive does not match tlpdb.nix, refusing to evaluate"
&& assertMsg (
tlpdbVersion.frozen == version.final
) "TeX Live final status in texlive does not match tlpdb.nix, refusing to evaluate";
# Pre-defined evironment packages for TeX Live schemes,
# to make nix-env usage more comfortable and build selected on Hydra.
# these license lists should be the sorted union of the licenses of the packages the schemes contain.
# The correctness of this collation is tested by tests.texlive.licenses
licenses = with lib.licenses; {
scheme-basic = [
free
gfl
gpl1Only
gpl2Only
gpl2Plus
knuth
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
];
scheme-bookpub = [
artistic2
asl20
bsd3
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
knuth
lgpl21
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
];
scheme-context = [
bsd2
bsd3
cc-by-sa-40
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
x11
];
scheme-full = [
artistic1-cl8
artistic2
asl20
bsd2
bsd3
bsdOriginal
cc-by-10
cc-by-20
cc-by-30
cc-by-40
cc-by-sa-10
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
fdl13Only
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-gust = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-40
cc-by-sa-40
cc0
fdl13Only
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-infraonly = [
gpl2Plus
lgpl21
];
scheme-medium = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-40
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-minimal = [
free
gpl1Only
gpl2Plus
knuth
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
];
scheme-small = [
asl20
cc-by-40
cc-by-sa-40
cc0
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-tetex = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-30
cc-by-40
cc-by-sa-10
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
};
meta = {
description = "TeX Live environment";
platforms = lib.platforms.all;
maintainers = with lib.maintainers; [ veprbl ];
license = licenses.scheme-infraonly;
};
combined = recurseIntoAttrs (
lib.genAttrs
[
"scheme-basic"
"scheme-bookpub"
"scheme-context"
"scheme-full"
"scheme-gust"
"scheme-infraonly"
"scheme-medium"
"scheme-minimal"
"scheme-small"
"scheme-tetex"
]
(
pname:
(buildTeXEnv {
__extraName = "combined" + lib.removePrefix "scheme" pname;
__extraVersion = with version; if final then "-final" else ".${year}${month}${day}";
requiredTeXPackages = ps: [ ps.${pname} ];
# to maintain full backward compatibility, enable texlive.combine behavior
__combine = true;
}).overrideAttrs
{
meta = meta // {
description = "TeX Live environment for ${pname}";
license = licenses.${pname};
};
}
)
);
schemes = lib.listToAttrs (
map
(s: {
name = "texlive" + s;
value = lib.addMetaAttrs { license = licenses.${"scheme-" + (lib.toLower s)}; } (buildTeXEnv {
requiredTeXPackages = ps: [ ps.${"scheme-" + (lib.toLower s)} ];
});
})
[
"Basic"
"BookPub"
"ConTeXt"
"Full"
"GUST"
"InfraOnly"
"Medium"
"Minimal"
"Small"
"TeTeX"
]
);
in
allPkgLists
// {
pkgs = tl;
tlpdb = {
# nested in an attribute set to prevent them from appearing in search
nix = tlpdbNix;
xz = tlpdbxz;
};
bin =
assert assertions;
bin
// {
# for backward compatibility
latexindent = tl.latexindent;
};
combine =
assert assertions;
combine;
combined =
assert assertions;
combined;
inherit schemes;
# convenience alias
withPackages = (buildTeXEnv { }).withPackages;
}