mirror of
https://github.com/NixOS/nix.git
synced 2024-10-29 21:30:51 +00:00
Build the manual with Meson
Co-Authored-By: Qyriad <qyriad@qyriad.me> Co-Authored-By: Robert Hensing <robert@roberthensing.nl> Co-Authored-By: eldritch horrors <pennae@lix.systems> Co-authored-by: Jörg Thalheim <Mic92@users.noreply.github.com> Co-authored-by: Tom Bereknyei <tomberek@gmail.com>
This commit is contained in:
parent
67a66212c3
commit
08b59aad31
1
doc/manual/.version
Symbolic link
1
doc/manual/.version
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../.version
|
@ -7,9 +7,21 @@ additional-js = ["redirects.js"]
|
|||||||
edit-url-template = "https://github.com/NixOS/nix/tree/master/doc/manual/{path}"
|
edit-url-template = "https://github.com/NixOS/nix/tree/master/doc/manual/{path}"
|
||||||
git-repository-url = "https://github.com/NixOS/nix"
|
git-repository-url = "https://github.com/NixOS/nix"
|
||||||
|
|
||||||
|
# Handles replacing @docroot@ with a path to ./src relative to that markdown file,
|
||||||
|
# {{#include handlebars}}, and the @generated@ syntax used within these. it mostly
|
||||||
|
# but not entirely replaces the links preprocessor (which we cannot simply use due
|
||||||
|
# to @generated@ files living in a different directory to make meson happy). we do
|
||||||
|
# not want to disable the links preprocessor entirely though because that requires
|
||||||
|
# disabling *all* built-in preprocessors and selectively reenabling those we want.
|
||||||
|
[preprocessor.substitute]
|
||||||
|
command = "python3 ./substitute.py"
|
||||||
|
before = ["anchors", "links"]
|
||||||
|
|
||||||
[preprocessor.anchors]
|
[preprocessor.anchors]
|
||||||
renderers = ["html"]
|
renderers = ["html"]
|
||||||
command = "jq --from-file doc/manual/anchors.jq"
|
command = "jq --from-file ./anchors.jq"
|
||||||
|
|
||||||
|
[output.markdown]
|
||||||
|
|
||||||
[output.linkcheck]
|
[output.linkcheck]
|
||||||
# no Internet during the build (in the sandbox)
|
# no Internet during the build (in the sandbox)
|
||||||
|
22
doc/manual/generate-deps.py
Executable file
22
doc/manual/generate-deps.py
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# meson expects makefile-style dependency declarations, i.e.
|
||||||
|
#
|
||||||
|
# target: dependency...
|
||||||
|
#
|
||||||
|
# meson seems to pass depfiles straight on to ninja even though
|
||||||
|
# it also parses the file itself (or at least has code to do so
|
||||||
|
# in its tree), so we must live by ninja's rules: only slashes,
|
||||||
|
# spaces and octothorpes can be escaped, anything else is taken
|
||||||
|
# literally. since the rules for these aren't even the same for
|
||||||
|
# all three we will just fail when we encounter any of them (if
|
||||||
|
# asserts are off for some reason the depfile will likely point
|
||||||
|
# to nonexistant paths, making everything phony and thus fine.)
|
||||||
|
for path in glob.glob(sys.argv[1] + '/**', recursive=True):
|
||||||
|
assert '\\' not in path
|
||||||
|
assert ' ' not in path
|
||||||
|
assert '#' not in path
|
||||||
|
print("ignored:", path)
|
@ -223,8 +223,13 @@ $(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/
|
|||||||
sed -i "s,@docroot@,$$docroot,g" "$$file"; \
|
sed -i "s,@docroot@,$$docroot,g" "$$file"; \
|
||||||
done; \
|
done; \
|
||||||
set -euo pipefail; \
|
set -euo pipefail; \
|
||||||
RUST_LOG=warn mdbook build "$$tmp/manual" -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \
|
( \
|
||||||
| { grep -Fv "because fragment resolution isn't implemented" || :; }; \
|
cd "$$tmp/manual"; \
|
||||||
|
RUST_LOG=warn \
|
||||||
|
MDBOOK_SUBSTITUTE_SEARCH=$(d)/src \
|
||||||
|
mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \
|
||||||
|
| { grep -Fv "because fragment resolution isn't implemented" || :; } \
|
||||||
|
); \
|
||||||
rm -rf "$$tmp/manual"
|
rm -rf "$$tmp/manual"
|
||||||
@rm -rf $(DESTDIR)$(docdir)/manual
|
@rm -rf $(DESTDIR)$(docdir)/manual
|
||||||
@mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual
|
@mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual
|
||||||
|
353
doc/manual/meson.build
Normal file
353
doc/manual/meson.build
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
project('nix-manual',
|
||||||
|
version : files('.version'),
|
||||||
|
meson_version : '>= 1.1',
|
||||||
|
license : 'LGPL-2.1-or-later',
|
||||||
|
)
|
||||||
|
|
||||||
|
nix = find_program('nix', native : true)
|
||||||
|
|
||||||
|
mdbook = find_program('mdbook', native : true)
|
||||||
|
bash = find_program('bash', native : true)
|
||||||
|
|
||||||
|
pymod = import('python')
|
||||||
|
python = pymod.find_installation('python3')
|
||||||
|
|
||||||
|
nix_env_for_docs = {
|
||||||
|
'HOME': '/dummy',
|
||||||
|
'NIX_CONF_DIR': '/dummy',
|
||||||
|
'NIX_SSL_CERT_FILE': '/dummy/no-ca-bundle.crt',
|
||||||
|
'NIX_STATE_DIR': '/dummy',
|
||||||
|
'NIX_CONFIG': 'cores = 0',
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_for_docs = [nix, '--experimental-features', 'nix-command']
|
||||||
|
nix_eval_for_docs_common = nix_for_docs + [
|
||||||
|
'eval',
|
||||||
|
'-I', 'nix=' + meson.current_source_dir(),
|
||||||
|
'--store', 'dummy://',
|
||||||
|
'--impure',
|
||||||
|
]
|
||||||
|
nix_eval_for_docs = nix_eval_for_docs_common + '--raw'
|
||||||
|
|
||||||
|
conf_file_json = custom_target(
|
||||||
|
command : nix_for_docs + ['config', 'show', '--json'],
|
||||||
|
capture : true,
|
||||||
|
output : 'conf-file.json',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
language_json = custom_target(
|
||||||
|
command: [nix, '__dump-language'],
|
||||||
|
output : 'language.json',
|
||||||
|
capture : true,
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
nix3_cli_json = custom_target(
|
||||||
|
command : [nix, '__dump-cli'],
|
||||||
|
capture : true,
|
||||||
|
output : 'nix.json',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
generate_manual_deps = files(
|
||||||
|
'generate-deps.py',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generates types
|
||||||
|
subdir('src/store')
|
||||||
|
# Generates builtins.md and builtin-constants.md.
|
||||||
|
subdir('src/language')
|
||||||
|
# Generates new-cli pages, experimental-features-shortlist.md, and conf-file.md.
|
||||||
|
subdir('src/command-ref')
|
||||||
|
# Generates experimental-feature-descriptions.md.
|
||||||
|
subdir('src/development')
|
||||||
|
# Generates rl-next-generated.md.
|
||||||
|
subdir('src/release-notes')
|
||||||
|
subdir('src')
|
||||||
|
|
||||||
|
# Hacky way to figure out if `nix` is an `ExternalProgram` or
|
||||||
|
# `Exectuable`. Only the latter can occur in custom target input lists.
|
||||||
|
if nix.full_path().startswith(meson.build_root())
|
||||||
|
nix_input = nix
|
||||||
|
else
|
||||||
|
nix_input = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
manual = custom_target(
|
||||||
|
'manual',
|
||||||
|
command : [
|
||||||
|
bash,
|
||||||
|
'-euo', 'pipefail',
|
||||||
|
'-c',
|
||||||
|
'''
|
||||||
|
@0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@
|
||||||
|
@0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/src/SUMMARY.md.in > @2@/src/SUMMARY.md
|
||||||
|
rsync -r --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/
|
||||||
|
(cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3
|
||||||
|
rm -rf @2@/manual
|
||||||
|
mv @2@/html @2@/manual
|
||||||
|
find @2@/manual -iname meson.build -delete
|
||||||
|
'''.format(
|
||||||
|
python.full_path(),
|
||||||
|
mdbook.full_path(),
|
||||||
|
meson.current_build_dir(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
generate_manual_deps,
|
||||||
|
'substitute.py',
|
||||||
|
'book.toml',
|
||||||
|
'anchors.jq',
|
||||||
|
'custom.css',
|
||||||
|
nix3_cli_files,
|
||||||
|
experimental_features_shortlist_md,
|
||||||
|
experimental_feature_descriptions_md,
|
||||||
|
types_dir,
|
||||||
|
conf_file_md,
|
||||||
|
builtins_md,
|
||||||
|
rl_next_generated,
|
||||||
|
summary_rl_next,
|
||||||
|
nix_input,
|
||||||
|
],
|
||||||
|
output : [
|
||||||
|
'manual',
|
||||||
|
'markdown',
|
||||||
|
],
|
||||||
|
depfile : 'manual.d',
|
||||||
|
env : {
|
||||||
|
'RUST_LOG': 'info',
|
||||||
|
'MDBOOK_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'src',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
manual_html = manual[0]
|
||||||
|
manual_md = manual[1]
|
||||||
|
|
||||||
|
install_subdir(
|
||||||
|
manual_html.full_path(),
|
||||||
|
install_dir : get_option('datadir') / 'doc/nix',
|
||||||
|
)
|
||||||
|
|
||||||
|
nix_nested_manpages = [
|
||||||
|
[ 'nix-env',
|
||||||
|
[
|
||||||
|
'delete-generations',
|
||||||
|
'install',
|
||||||
|
'list-generations',
|
||||||
|
'query',
|
||||||
|
'rollback',
|
||||||
|
'set-flag',
|
||||||
|
'set',
|
||||||
|
'switch-generation',
|
||||||
|
'switch-profile',
|
||||||
|
'uninstall',
|
||||||
|
'upgrade',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[ 'nix-store',
|
||||||
|
[
|
||||||
|
'add-fixed',
|
||||||
|
'add',
|
||||||
|
'delete',
|
||||||
|
'dump-db',
|
||||||
|
'dump',
|
||||||
|
'export',
|
||||||
|
'gc',
|
||||||
|
'generate-binary-cache-key',
|
||||||
|
'import',
|
||||||
|
'load-db',
|
||||||
|
'optimise',
|
||||||
|
'print-env',
|
||||||
|
'query',
|
||||||
|
'read-log',
|
||||||
|
'realise',
|
||||||
|
'repair-path',
|
||||||
|
'restore',
|
||||||
|
'serve',
|
||||||
|
'verify',
|
||||||
|
'verify-path',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
foreach command : nix_nested_manpages
|
||||||
|
foreach page : command[1]
|
||||||
|
title = command[0] + ' --' + page
|
||||||
|
section = '1'
|
||||||
|
custom_target(
|
||||||
|
command : [
|
||||||
|
bash,
|
||||||
|
files('./render-manpage.sh'),
|
||||||
|
'--out-no-smarty',
|
||||||
|
title,
|
||||||
|
section,
|
||||||
|
'@INPUT0@/command-ref' / command[0] / (page + '.md'),
|
||||||
|
'@OUTPUT0@',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
manual_md,
|
||||||
|
nix_input,
|
||||||
|
],
|
||||||
|
output : command[0] + '-' + page + '.1',
|
||||||
|
install : true,
|
||||||
|
install_dir : get_option('mandir') / 'man1',
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
nix3_manpages = [
|
||||||
|
'nix3-build',
|
||||||
|
'nix3-bundle',
|
||||||
|
'nix3-config',
|
||||||
|
'nix3-config-show',
|
||||||
|
'nix3-copy',
|
||||||
|
'nix3-daemon',
|
||||||
|
'nix3-derivation-add',
|
||||||
|
'nix3-derivation',
|
||||||
|
'nix3-derivation-show',
|
||||||
|
'nix3-develop',
|
||||||
|
#'nix3-doctor',
|
||||||
|
'nix3-edit',
|
||||||
|
'nix3-eval',
|
||||||
|
'nix3-flake-archive',
|
||||||
|
'nix3-flake-check',
|
||||||
|
'nix3-flake-clone',
|
||||||
|
'nix3-flake-info',
|
||||||
|
'nix3-flake-init',
|
||||||
|
'nix3-flake-lock',
|
||||||
|
'nix3-flake',
|
||||||
|
'nix3-flake-metadata',
|
||||||
|
'nix3-flake-new',
|
||||||
|
'nix3-flake-prefetch',
|
||||||
|
'nix3-flake-show',
|
||||||
|
'nix3-flake-update',
|
||||||
|
'nix3-fmt',
|
||||||
|
'nix3-hash-file',
|
||||||
|
'nix3-hash',
|
||||||
|
'nix3-hash-path',
|
||||||
|
'nix3-hash-to-base16',
|
||||||
|
'nix3-hash-to-base32',
|
||||||
|
'nix3-hash-to-base64',
|
||||||
|
'nix3-hash-to-sri',
|
||||||
|
'nix3-help',
|
||||||
|
'nix3-help-stores',
|
||||||
|
'nix3-key-convert-secret-to-public',
|
||||||
|
'nix3-key-generate-secret',
|
||||||
|
'nix3-key',
|
||||||
|
'nix3-log',
|
||||||
|
'nix3-nar-cat',
|
||||||
|
'nix3-nar-dump-path',
|
||||||
|
'nix3-nar-ls',
|
||||||
|
'nix3-nar',
|
||||||
|
'nix3-path-info',
|
||||||
|
'nix3-print-dev-env',
|
||||||
|
'nix3-profile-diff-closures',
|
||||||
|
'nix3-profile-history',
|
||||||
|
'nix3-profile-install',
|
||||||
|
'nix3-profile-list',
|
||||||
|
'nix3-profile',
|
||||||
|
'nix3-profile-remove',
|
||||||
|
'nix3-profile-rollback',
|
||||||
|
'nix3-profile-upgrade',
|
||||||
|
'nix3-profile-wipe-history',
|
||||||
|
'nix3-realisation-info',
|
||||||
|
'nix3-realisation',
|
||||||
|
'nix3-registry-add',
|
||||||
|
'nix3-registry-list',
|
||||||
|
'nix3-registry',
|
||||||
|
'nix3-registry-pin',
|
||||||
|
'nix3-registry-remove',
|
||||||
|
'nix3-repl',
|
||||||
|
'nix3-run',
|
||||||
|
'nix3-search',
|
||||||
|
#'nix3-shell',
|
||||||
|
'nix3-store-add-file',
|
||||||
|
'nix3-store-add-path',
|
||||||
|
'nix3-store-cat',
|
||||||
|
'nix3-store-copy-log',
|
||||||
|
'nix3-store-copy-sigs',
|
||||||
|
'nix3-store-delete',
|
||||||
|
'nix3-store-diff-closures',
|
||||||
|
'nix3-store-dump-path',
|
||||||
|
'nix3-store-gc',
|
||||||
|
'nix3-store-ls',
|
||||||
|
'nix3-store-make-content-addressed',
|
||||||
|
'nix3-store',
|
||||||
|
'nix3-store-optimise',
|
||||||
|
'nix3-store-path-from-hash-part',
|
||||||
|
'nix3-store-ping',
|
||||||
|
'nix3-store-prefetch-file',
|
||||||
|
'nix3-store-repair',
|
||||||
|
'nix3-store-sign',
|
||||||
|
'nix3-store-verify',
|
||||||
|
'nix3-upgrade-nix',
|
||||||
|
'nix3-why-depends',
|
||||||
|
'nix',
|
||||||
|
]
|
||||||
|
|
||||||
|
foreach page : nix3_manpages
|
||||||
|
section = '1'
|
||||||
|
custom_target(
|
||||||
|
command : [
|
||||||
|
bash,
|
||||||
|
'@INPUT0@',
|
||||||
|
page,
|
||||||
|
section,
|
||||||
|
'@INPUT1@/command-ref/new-cli/@0@.md'.format(page),
|
||||||
|
'@OUTPUT@',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
files('./render-manpage.sh'),
|
||||||
|
manual_md,
|
||||||
|
nix_input,
|
||||||
|
],
|
||||||
|
output : page + '.1',
|
||||||
|
install : true,
|
||||||
|
install_dir : get_option('mandir') / 'man1',
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
nix_manpages = [
|
||||||
|
[ 'nix-env', 1 ],
|
||||||
|
[ 'nix-store', 1 ],
|
||||||
|
[ 'nix-build', 1 ],
|
||||||
|
[ 'nix-shell', 1 ],
|
||||||
|
[ 'nix-instantiate', 1 ],
|
||||||
|
[ 'nix-collect-garbage', 1 ],
|
||||||
|
[ 'nix-prefetch-url', 1 ],
|
||||||
|
[ 'nix-channel', 1 ],
|
||||||
|
[ 'nix-hash', 1 ],
|
||||||
|
[ 'nix-copy-closure', 1 ],
|
||||||
|
[ 'nix.conf', 5, conf_file_md.full_path() ],
|
||||||
|
[ 'nix-daemon', 8 ],
|
||||||
|
[ 'nix-profiles', 5, 'files/profiles.md' ],
|
||||||
|
]
|
||||||
|
|
||||||
|
foreach entry : nix_manpages
|
||||||
|
title = entry[0]
|
||||||
|
# nix.conf.5 and nix-profiles.5 are based off of conf-file.md and files/profiles.md,
|
||||||
|
# rather than a stem identical to its mdbook source.
|
||||||
|
# Therefore we use an optional third element of this array to override the name pattern
|
||||||
|
md_file = entry.get(2, title + '.md')
|
||||||
|
section = entry[1].to_string()
|
||||||
|
md_file_resolved = join_paths('@INPUT1@/command-ref/', md_file)
|
||||||
|
custom_target(
|
||||||
|
command : [
|
||||||
|
bash,
|
||||||
|
'@INPUT0@',
|
||||||
|
title,
|
||||||
|
section,
|
||||||
|
md_file_resolved,
|
||||||
|
'@OUTPUT@',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
files('./render-manpage.sh'),
|
||||||
|
manual_md,
|
||||||
|
entry.get(3, []),
|
||||||
|
nix_input,
|
||||||
|
],
|
||||||
|
output : '@0@.@1@'.format(entry[0], entry[1]),
|
||||||
|
install : true,
|
||||||
|
install_dir : get_option('mandir') / 'man@0@'.format(entry[1]),
|
||||||
|
)
|
||||||
|
endforeach
|
71
doc/manual/package.nix
Normal file
71
doc/manual/package.nix
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{ lib
|
||||||
|
, mkMesonDerivation
|
||||||
|
|
||||||
|
, meson
|
||||||
|
, ninja
|
||||||
|
, lowdown
|
||||||
|
, mdbook
|
||||||
|
, mdbook-linkcheck
|
||||||
|
, jq
|
||||||
|
, python3
|
||||||
|
, rsync
|
||||||
|
, nix-cli
|
||||||
|
|
||||||
|
# Configuration Options
|
||||||
|
|
||||||
|
, version
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
in
|
||||||
|
|
||||||
|
mkMesonDerivation (finalAttrs: {
|
||||||
|
pname = "nix-manual";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
workDir = ./.;
|
||||||
|
fileset = fileset.difference
|
||||||
|
(fileset.unions [
|
||||||
|
../../.version
|
||||||
|
# Too many different types of files to filter for now
|
||||||
|
../../doc/manual
|
||||||
|
./.
|
||||||
|
])
|
||||||
|
# Do a blacklist instead
|
||||||
|
../../doc/manual/package.nix;
|
||||||
|
|
||||||
|
# TODO the man pages should probably be separate
|
||||||
|
outputs = [ "out" "man" ];
|
||||||
|
|
||||||
|
# Hack for sake of the dev shell
|
||||||
|
passthru.externalNativeBuildInputs = [
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
(lib.getBin lowdown)
|
||||||
|
mdbook
|
||||||
|
mdbook-linkcheck
|
||||||
|
jq
|
||||||
|
python3
|
||||||
|
rsync
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = finalAttrs.passthru.externalNativeBuildInputs ++ [
|
||||||
|
nix-cli
|
||||||
|
];
|
||||||
|
|
||||||
|
preConfigure =
|
||||||
|
''
|
||||||
|
chmod u+w ./.version
|
||||||
|
echo ${finalAttrs.version} > ./.version
|
||||||
|
'';
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
mkdir -p ''$out/nix-support
|
||||||
|
echo "doc manual ''$out/share/doc/nix/manual" >> ''$out/nix-support/hydra-build-products
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
platforms = lib.platforms.all;
|
||||||
|
};
|
||||||
|
})
|
33
doc/manual/remove_before_wrapper.py
Normal file
33
doc/manual/remove_before_wrapper.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import typing as t
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 4 or '--' not in sys.argv:
|
||||||
|
print("Usage: remove-before-wrapper <output> -- <nix command...>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Extract the parts
|
||||||
|
output: str = sys.argv[1]
|
||||||
|
nix_command_idx: int = sys.argv.index('--') + 1
|
||||||
|
nix_command: t.List[str] = sys.argv[nix_command_idx:]
|
||||||
|
|
||||||
|
output_temp: str = output + '.tmp'
|
||||||
|
|
||||||
|
# Remove the output and temp output in case they exist
|
||||||
|
shutil.rmtree(output, ignore_errors=True)
|
||||||
|
shutil.rmtree(output_temp, ignore_errors=True)
|
||||||
|
|
||||||
|
# Execute nix command with `--write-to` tempary output
|
||||||
|
nix_command_write_to = nix_command + ['--write-to', output_temp]
|
||||||
|
subprocess.run(nix_command_write_to, check=True)
|
||||||
|
|
||||||
|
# Move the temporary output to the intended location
|
||||||
|
os.rename(output_temp, output)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
25
doc/manual/render-manpage.sh
Executable file
25
doc/manual/render-manpage.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
lowdown_args=
|
||||||
|
|
||||||
|
if [ "$1" = --out-no-smarty ]; then
|
||||||
|
lowdown_args=--out-no-smarty
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ "$#" = 4 ] || {
|
||||||
|
echo "wrong number of args passed" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
title="$1"
|
||||||
|
section="$2"
|
||||||
|
infile="$3"
|
||||||
|
outfile="$4"
|
||||||
|
|
||||||
|
(
|
||||||
|
printf "Title: %s\n\n" "$title"
|
||||||
|
cat "$infile"
|
||||||
|
) | lowdown -sT man --nroff-nolinks $lowdown_args -M section="$section" -o "$outfile"
|
63
doc/manual/src/command-ref/meson.build
Normal file
63
doc/manual/src/command-ref/meson.build
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
xp_features_json = custom_target(
|
||||||
|
command : [nix, '__dump-xp-features'],
|
||||||
|
capture : true,
|
||||||
|
output : 'xp-features.json',
|
||||||
|
)
|
||||||
|
|
||||||
|
experimental_features_shortlist_md = custom_target(
|
||||||
|
command : nix_eval_for_docs + [
|
||||||
|
'--expr',
|
||||||
|
'import @INPUT0@ (builtins.fromJSON (builtins.readFile ./@INPUT1@))',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
'../../generate-xp-features-shortlist.nix',
|
||||||
|
xp_features_json,
|
||||||
|
],
|
||||||
|
output : 'experimental-features-shortlist.md',
|
||||||
|
capture : true,
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
nix3_cli_files = custom_target(
|
||||||
|
command : [
|
||||||
|
python.full_path(),
|
||||||
|
'@INPUT0@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
'--'
|
||||||
|
] + nix_eval_for_docs + [
|
||||||
|
'--expr',
|
||||||
|
'import @INPUT1@ true (builtins.readFile ./@INPUT2@)',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
'../../remove_before_wrapper.py',
|
||||||
|
'../../generate-manpage.nix',
|
||||||
|
nix3_cli_json,
|
||||||
|
],
|
||||||
|
output : 'new-cli',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
conf_file_md_body = custom_target(
|
||||||
|
command : [
|
||||||
|
nix_eval_for_docs,
|
||||||
|
'--expr',
|
||||||
|
'import @INPUT0@ { prefix = "conf"; } (builtins.fromJSON (builtins.readFile ./@INPUT1@))',
|
||||||
|
],
|
||||||
|
capture : true,
|
||||||
|
input : [
|
||||||
|
'../../generate-settings.nix',
|
||||||
|
conf_file_json,
|
||||||
|
],
|
||||||
|
output : 'conf-file.body.md',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
||||||
|
|
||||||
|
conf_file_md = custom_target(
|
||||||
|
command : [ 'cat', '@INPUT0@', '@INPUT1@' ],
|
||||||
|
capture : true,
|
||||||
|
input : [
|
||||||
|
'conf-file-prefix.md',
|
||||||
|
conf_file_md_body,
|
||||||
|
],
|
||||||
|
output : 'conf-file.md',
|
||||||
|
)
|
12
doc/manual/src/development/meson.build
Normal file
12
doc/manual/src/development/meson.build
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
experimental_feature_descriptions_md = custom_target(
|
||||||
|
command : nix_eval_for_docs + [
|
||||||
|
'--expr',
|
||||||
|
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
'../../generate-xp-features.nix',
|
||||||
|
xp_features_json,
|
||||||
|
],
|
||||||
|
capture : true,
|
||||||
|
output : 'experimental-feature-descriptions.md',
|
||||||
|
)
|
1
doc/manual/src/language/constructs.md
Normal file
1
doc/manual/src/language/constructs.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Language Constructs
|
20
doc/manual/src/language/meson.build
Normal file
20
doc/manual/src/language/meson.build
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
builtins_md = custom_target(
|
||||||
|
command : [
|
||||||
|
python.full_path(),
|
||||||
|
'@INPUT0@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
'--'
|
||||||
|
] + nix_eval_for_docs + [
|
||||||
|
'--expr',
|
||||||
|
'(builtins.readFile @INPUT3@) + import @INPUT1@ (builtins.fromJSON (builtins.readFile ./@INPUT2@)) + (builtins.readFile @INPUT4@)',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
'../../remove_before_wrapper.py',
|
||||||
|
'../../generate-builtins.nix',
|
||||||
|
language_json,
|
||||||
|
'builtins-prefix.md',
|
||||||
|
'builtins-suffix.md'
|
||||||
|
],
|
||||||
|
output : 'builtins.md',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
1
doc/manual/src/language/values.md
Normal file
1
doc/manual/src/language/values.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Data Types
|
17
doc/manual/src/meson.build
Normal file
17
doc/manual/src/meson.build
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
summary_rl_next = custom_target(
|
||||||
|
command : [
|
||||||
|
bash,
|
||||||
|
'-euo', 'pipefail',
|
||||||
|
'-c',
|
||||||
|
'''
|
||||||
|
if [ -e "@INPUT@" ]; then
|
||||||
|
echo ' - [Upcoming release](release-notes/rl-next.md)'
|
||||||
|
fi
|
||||||
|
''',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
rl_next_generated,
|
||||||
|
],
|
||||||
|
capture: true,
|
||||||
|
output : 'SUMMARY-rl-next.md',
|
||||||
|
)
|
1
doc/manual/src/protocols/json/index.md
Normal file
1
doc/manual/src/protocols/json/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# JSON Formats
|
24
doc/manual/src/release-notes/meson.build
Normal file
24
doc/manual/src/release-notes/meson.build
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
rl_next_generated = custom_target(
|
||||||
|
command : [
|
||||||
|
'bash',
|
||||||
|
'-euo',
|
||||||
|
'pipefail',
|
||||||
|
'-c',
|
||||||
|
'''
|
||||||
|
if type -p build-release-notes > /dev/null; then
|
||||||
|
build-release-notes --change-authors @CURRENT_SOURCE_DIR@/../../change-authors.yml @CURRENT_SOURCE_DIR@/../../rl-next
|
||||||
|
elif type -p changelog-d > /dev/null; then
|
||||||
|
changelog-d @CURRENT_SOURCE_DIR@/../../rl-next
|
||||||
|
fi
|
||||||
|
@0@ @INPUT0@ @CURRENT_SOURCE_DIR@/../../rl-next > @DEPFILE@
|
||||||
|
'''.format(
|
||||||
|
python.full_path(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
generate_manual_deps,
|
||||||
|
],
|
||||||
|
output : 'rl-next.md',
|
||||||
|
capture : true,
|
||||||
|
depfile : 'rl-next.d',
|
||||||
|
)
|
18
doc/manual/src/store/meson.build
Normal file
18
doc/manual/src/store/meson.build
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
types_dir = custom_target(
|
||||||
|
command : [
|
||||||
|
python.full_path(),
|
||||||
|
'@INPUT0@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
'--'
|
||||||
|
] + nix_eval_for_docs + [
|
||||||
|
'--expr',
|
||||||
|
'import @INPUT1@ (builtins.fromJSON (builtins.readFile ./@INPUT2@)).stores',
|
||||||
|
],
|
||||||
|
input : [
|
||||||
|
'../../remove_before_wrapper.py',
|
||||||
|
'../../generate-store-types.nix',
|
||||||
|
nix3_cli_json,
|
||||||
|
],
|
||||||
|
output : 'types',
|
||||||
|
env : nix_env_for_docs,
|
||||||
|
)
|
111
doc/manual/substitute.py
Normal file
111
doc/manual/substitute.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import os, os.path
|
||||||
|
import sys
|
||||||
|
import typing as t
|
||||||
|
|
||||||
|
name = 'substitute.py'
|
||||||
|
|
||||||
|
def log(*args: t.Any, **kwargs: t.Any) -> None:
|
||||||
|
kwargs['file'] = sys.stderr
|
||||||
|
print(f'{name}:', *args, **kwargs)
|
||||||
|
|
||||||
|
def do_include(content: str, relative_md_path: Path, source_root: Path, search_path: Path) -> str:
|
||||||
|
assert not relative_md_path.is_absolute(), f'{relative_md_path=} from mdbook should be relative'
|
||||||
|
|
||||||
|
md_path_abs = source_root / relative_md_path
|
||||||
|
var_abs = md_path_abs.parent
|
||||||
|
assert var_abs.is_dir(), f'supposed directory {var_abs} is not a directory (cwd={os.getcwd()})'
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for l in content.splitlines(keepends=True):
|
||||||
|
if l.strip().startswith("{{#include "):
|
||||||
|
requested = l.strip()[11:][:-2]
|
||||||
|
if requested.startswith("@generated@/"):
|
||||||
|
included = search_path / Path(requested[12:])
|
||||||
|
requested = included.relative_to(search_path)
|
||||||
|
else:
|
||||||
|
included = source_root / relative_md_path.parent / requested
|
||||||
|
requested = included.resolve().relative_to(source_root)
|
||||||
|
assert included.exists(), f"{requested} not found at {included}"
|
||||||
|
lines.append(do_include(included.read_text(), requested, source_root, search_path) + "\n")
|
||||||
|
else:
|
||||||
|
lines.append(l)
|
||||||
|
return "".join(lines)
|
||||||
|
|
||||||
|
def recursive_replace(data: dict[str, t.Any], book_root: Path, search_path: Path) -> dict[str, t.Any]:
|
||||||
|
match data:
|
||||||
|
case {'sections': sections}:
|
||||||
|
return data | dict(
|
||||||
|
sections = [recursive_replace(section, book_root, search_path) for section in sections],
|
||||||
|
)
|
||||||
|
case {'Chapter': chapter}:
|
||||||
|
path_to_chapter = Path(chapter['path'])
|
||||||
|
chapter_content = chapter['content']
|
||||||
|
|
||||||
|
return data | dict(
|
||||||
|
Chapter = chapter | dict(
|
||||||
|
# first process includes. this must happen before docroot processing since
|
||||||
|
# mdbook does not see these included files, only the final agglomeration.
|
||||||
|
content = do_include(
|
||||||
|
chapter_content,
|
||||||
|
path_to_chapter,
|
||||||
|
book_root,
|
||||||
|
search_path
|
||||||
|
).replace(
|
||||||
|
'@docroot@',
|
||||||
|
("../" * len(path_to_chapter.parent.parts) or "./")[:-1]
|
||||||
|
),
|
||||||
|
sub_items = [
|
||||||
|
recursive_replace(sub_item, book_root, search_path)
|
||||||
|
for sub_item in chapter['sub_items']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
case rest:
|
||||||
|
assert False, f'should have been called on a dict, not {type(rest)=}\n\t{rest=}'
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == 'supports':
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# includes pointing into @generated@ will look here
|
||||||
|
search_path = Path(os.environ['MDBOOK_SUBSTITUTE_SEARCH'])
|
||||||
|
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == 'summary':
|
||||||
|
print(do_include(
|
||||||
|
sys.stdin.read(),
|
||||||
|
Path('src/SUMMARY.md'),
|
||||||
|
Path(sys.argv[2]).resolve(),
|
||||||
|
search_path))
|
||||||
|
return
|
||||||
|
|
||||||
|
# mdbook communicates with us over stdin and stdout.
|
||||||
|
# It splorks us a JSON array, the first element describing the context,
|
||||||
|
# the second element describing the book itself,
|
||||||
|
# and then expects us to send it the modified book JSON over stdout.
|
||||||
|
|
||||||
|
context, book = json.load(sys.stdin)
|
||||||
|
|
||||||
|
# book_root is the directory where book contents leave (ie, src/)
|
||||||
|
book_root = Path(context['root']) / context['config']['book']['src']
|
||||||
|
|
||||||
|
# Find @var@ in all parts of our recursive book structure.
|
||||||
|
replaced_content = recursive_replace(book, book_root, search_path)
|
||||||
|
|
||||||
|
replaced_content_str = json.dumps(replaced_content)
|
||||||
|
|
||||||
|
# Give mdbook our changes.
|
||||||
|
print(replaced_content_str)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sys.exit(main())
|
||||||
|
except AssertionError as e:
|
||||||
|
print(f'{name}: INTERNAL ERROR in mdbook preprocessor: {e}', file=sys.stderr)
|
||||||
|
print(f'this is a bug in {name}', file=sys.stderr)
|
||||||
|
raise
|
@ -221,6 +221,7 @@
|
|||||||
inherit (nixpkgsFor.${system}.native)
|
inherit (nixpkgsFor.${system}.native)
|
||||||
changelog-d;
|
changelog-d;
|
||||||
default = self.packages.${system}.nix-ng;
|
default = self.packages.${system}.nix-ng;
|
||||||
|
nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual;
|
||||||
nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs;
|
nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs;
|
||||||
nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs;
|
nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs;
|
||||||
}
|
}
|
||||||
@ -349,6 +350,7 @@
|
|||||||
++ pkgs.nixComponents.nix-store.nativeBuildInputs
|
++ pkgs.nixComponents.nix-store.nativeBuildInputs
|
||||||
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
|
++ pkgs.nixComponents.nix-fetchers.nativeBuildInputs
|
||||||
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
|
++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.nativeBuildInputs
|
||||||
|
++ lib.optionals buildCanExecuteHost pkgs.nixComponents.nix-manual.externalNativeBuildInputs
|
||||||
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
|
++ pkgs.nixComponents.nix-internal-api-docs.nativeBuildInputs
|
||||||
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
|
++ pkgs.nixComponents.nix-external-api-docs.nativeBuildInputs
|
||||||
++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs
|
++ pkgs.nixComponents.nix-functional-tests.externalNativeBuildInputs
|
||||||
|
@ -23,6 +23,9 @@ subproject('nix')
|
|||||||
# Docs
|
# Docs
|
||||||
subproject('internal-api-docs')
|
subproject('internal-api-docs')
|
||||||
subproject('external-api-docs')
|
subproject('external-api-docs')
|
||||||
|
if not meson.is_cross_build()
|
||||||
|
subproject('nix-manual')
|
||||||
|
endif
|
||||||
|
|
||||||
# External C wrapper libraries
|
# External C wrapper libraries
|
||||||
subproject('libutil-c')
|
subproject('libutil-c')
|
||||||
|
@ -60,6 +60,7 @@ in
|
|||||||
|
|
||||||
nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; };
|
nix-functional-tests = callPackage ../src/nix-functional-tests/package.nix { version = fineVersion; };
|
||||||
|
|
||||||
|
nix-manual = callPackage ../doc/manual/package.nix { version = fineVersion; };
|
||||||
nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; };
|
nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { version = fineVersion; };
|
||||||
nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; };
|
nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { version = fineVersion; };
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
nix-functional-tests,
|
nix-functional-tests,
|
||||||
|
|
||||||
|
nix-manual,
|
||||||
nix-internal-api-docs,
|
nix-internal-api-docs,
|
||||||
nix-external-api-docs,
|
nix-external-api-docs,
|
||||||
|
|
||||||
@ -70,6 +71,7 @@
|
|||||||
|
|
||||||
nix-cli
|
nix-cli
|
||||||
|
|
||||||
|
nix-manual
|
||||||
nix-internal-api-docs
|
nix-internal-api-docs
|
||||||
nix-external-api-docs
|
nix-external-api-docs
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ in
|
|||||||
withCoverageChecks = true;
|
withCoverageChecks = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Nix's manual
|
||||||
|
manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual;
|
||||||
|
|
||||||
# API docs for Nix's unstable internal C++ interfaces.
|
# API docs for Nix's unstable internal C++ interfaces.
|
||||||
internal-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-internal-api-docs;
|
internal-api-docs = nixpkgsFor.x86_64-linux.native.nixComponents.nix-internal-api-docs;
|
||||||
|
|
||||||
|
1
src/nix-manual
Symbolic link
1
src/nix-manual
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../doc/manual/
|
Loading…
Reference in New Issue
Block a user