1{ pkgs, options, config, version, revision, extraSources ? [] }:
2
3with pkgs;
4
5let
6 lib = pkgs.lib;
7
8 # We need to strip references to /nix/store/* from options,
9 # including any `extraSources` if some modules came from elsewhere,
10 # or else the build will fail.
11 #
12 # E.g. if some `options` came from modules in ${pkgs.customModules}/nix,
13 # you'd need to include `extraSources = [ pkgs.customModules ]`
14 prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
15 stripAnyPrefixes = lib.flip (lib.foldr lib.removePrefix) prefixesToStrip;
16
17 optionsDoc = buildPackages.nixosOptionsDoc {
18 inherit options revision;
19 transformOptions = opt: opt // {
20 # Clean up declaration sites to not refer to the NixOS source tree.
21 declarations = map stripAnyPrefixes opt.declarations;
22 };
23 };
24
25 sources = lib.sourceFilesBySuffices ./. [".xml"];
26
27 modulesDoc = builtins.toFile "modules.xml" ''
28 <section xmlns:xi="http://www.w3.org/2001/XInclude" id="modules">
29 ${(lib.concatMapStrings (path: ''
30 <xi:include href="${path}" />
31 '') (lib.catAttrs "value" config.meta.doc))}
32 </section>
33 '';
34
35 generatedSources = runCommand "generated-docbook" {} ''
36 mkdir $out
37 ln -s ${modulesDoc} $out/modules.xml
38 ln -s ${optionsDoc.optionsDocBook} $out/options-db.xml
39 printf "%s" "${version}" > $out/version
40 '';
41
42 copySources =
43 ''
44 cp -prd $sources/* . # */
45 ln -s ${generatedSources} ./generated
46 chmod -R u+w .
47 '';
48
49 toc = builtins.toFile "toc.xml"
50 ''
51 <toc role="chunk-toc">
52 <d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-nixos-manual"><?dbhtml filename="index.html"?>
53 <d:tocentry linkend="ch-options"><?dbhtml filename="options.html"?></d:tocentry>
54 <d:tocentry linkend="ch-release-notes"><?dbhtml filename="release-notes.html"?></d:tocentry>
55 </d:tocentry>
56 </toc>
57 '';
58
59 manualXsltprocOptions = toString [
60 "--param section.autolabel 1"
61 "--param section.label.includes.component.label 1"
62 "--stringparam html.stylesheet 'style.css overrides.css highlightjs/mono-blue.css'"
63 "--stringparam html.script './highlightjs/highlight.pack.js ./highlightjs/loader.js'"
64 "--param xref.with.number.and.title 1"
65 "--param toc.section.depth 0"
66 "--param generate.consistent.ids 1"
67 "--stringparam admon.style ''"
68 "--stringparam callout.graphics.extension .svg"
69 "--stringparam current.docid manual"
70 "--param chunk.section.depth 0"
71 "--param chunk.first.sections 1"
72 "--param use.id.as.filename 1"
73 "--stringparam chunk.toc ${toc}"
74 ];
75
76 manual-combined = runCommand "nixos-manual-combined"
77 { inherit sources;
78 nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
79 meta.description = "The NixOS manual as plain docbook XML";
80 }
81 ''
82 ${copySources}
83
84 xmllint --xinclude --output ./manual-combined.xml ./manual.xml
85 xmllint --xinclude --noxincludenode \
86 --output ./man-pages-combined.xml ./man-pages.xml
87
88 # outputs the context of an xmllint error output
89 # LEN lines around the failing line are printed
90 function context {
91 # length of context
92 local LEN=6
93 # lines to print before error line
94 local BEFORE=4
95
96 # xmllint output lines are:
97 # file.xml:1234: there was an error on line 1234
98 while IFS=':' read -r file line rest; do
99 echo
100 if [[ -n "$rest" ]]; then
101 echo "$file:$line:$rest"
102 local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1))
103 # number lines & filter context
104 nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p"
105 else
106 if [[ -n "$line" ]]; then
107 echo "$file:$line"
108 else
109 echo "$file"
110 fi
111 fi
112 done
113 }
114
115 function lintrng {
116 xmllint --debug --noout --nonet \
117 --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
118 "$1" \
119 2>&1 | context 1>&2
120 # ^ redirect assumes xmllint doesn’t print to stdout
121 }
122
123 lintrng manual-combined.xml
124 lintrng man-pages-combined.xml
125
126 mkdir $out
127 cp manual-combined.xml $out/
128 cp man-pages-combined.xml $out/
129 '';
130
131 olinkDB = runCommand "manual-olinkdb"
132 { inherit sources;
133 nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
134 }
135 ''
136 xsltproc \
137 ${manualXsltprocOptions} \
138 --stringparam collect.xref.targets only \
139 --stringparam targets.filename "$out/manual.db" \
140 --nonet \
141 ${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \
142 ${manual-combined}/manual-combined.xml
143
144 cat > "$out/olinkdb.xml" <<EOF
145 <?xml version="1.0" encoding="utf-8"?>
146 <!DOCTYPE targetset SYSTEM
147 "file://${docbook_xsl_ns}/xml/xsl/docbook/common/targetdatabase.dtd" [
148 <!ENTITY manualtargets SYSTEM "file://$out/manual.db">
149 ]>
150 <targetset>
151 <targetsetinfo>
152 Allows for cross-referencing olinks between the manpages
153 and manual.
154 </targetsetinfo>
155
156 <document targetdoc="manual">&manualtargets;</document>
157 </targetset>
158 EOF
159 '';
160
161in rec {
162 inherit generatedSources;
163
164 inherit (optionsDoc) optionsJSON optionsXML optionsDocBook;
165
166 # Generate the NixOS manual.
167 manualHTML = runCommand "nixos-manual-html"
168 { inherit sources;
169 nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
170 meta.description = "The NixOS manual in HTML format";
171 allowedReferences = ["out"];
172 }
173 ''
174 # Generate the HTML manual.
175 dst=$out/share/doc/nixos
176 mkdir -p $dst
177 xsltproc \
178 ${manualXsltprocOptions} \
179 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
180 --stringparam id.warnings "1" \
181 --nonet --output $dst/ \
182 ${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \
183 ${manual-combined}/manual-combined.xml \
184 |& tee xsltproc.out
185 grep "^ID recommended on" xsltproc.out &>/dev/null && echo "error: some IDs are missing" && false
186 rm xsltproc.out
187
188 mkdir -p $dst/images/callouts
189 cp ${docbook_xsl_ns}/xml/xsl/docbook/images/callouts/*.svg $dst/images/callouts/
190
191 cp ${../../../doc/style.css} $dst/style.css
192 cp ${../../../doc/overrides.css} $dst/overrides.css
193 cp -r ${pkgs.documentation-highlighter} $dst/highlightjs
194
195 mkdir -p $out/nix-support
196 echo "nix-build out $out" >> $out/nix-support/hydra-build-products
197 echo "doc manual $dst" >> $out/nix-support/hydra-build-products
198 ''; # */
199
200 # Alias for backward compatibility. TODO(@oxij): remove eventually.
201 manual = manualHTML;
202
203 # Index page of the NixOS manual.
204 manualHTMLIndex = "${manualHTML}/share/doc/nixos/index.html";
205
206 manualEpub = runCommand "nixos-manual-epub"
207 { inherit sources;
208 buildInputs = [ libxml2.bin libxslt.bin zip ];
209 }
210 ''
211 # Generate the epub manual.
212 dst=$out/share/doc/nixos
213
214 xsltproc \
215 ${manualXsltprocOptions} \
216 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
217 --nonet --xinclude --output $dst/epub/ \
218 ${docbook_xsl_ns}/xml/xsl/docbook/epub/docbook.xsl \
219 ${manual-combined}/manual-combined.xml
220
221 mkdir -p $dst/epub/OEBPS/images/callouts
222 cp -r ${docbook_xsl_ns}/xml/xsl/docbook/images/callouts/*.svg $dst/epub/OEBPS/images/callouts # */
223 echo "application/epub+zip" > mimetype
224 manual="$dst/nixos-manual.epub"
225 zip -0Xq "$manual" mimetype
226 cd $dst/epub && zip -Xr9D "$manual" *
227
228 rm -rf $dst/epub
229
230 mkdir -p $out/nix-support
231 echo "doc-epub manual $manual" >> $out/nix-support/hydra-build-products
232 '';
233
234
235 # Generate the NixOS manpages.
236 manpages = runCommand "nixos-manpages"
237 { inherit sources;
238 nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
239 allowedReferences = ["out"];
240 }
241 ''
242 # Generate manpages.
243 mkdir -p $out/share/man
244 xsltproc --nonet \
245 --maxdepth 6000 \
246 --param man.output.in.separate.dir 1 \
247 --param man.output.base.dir "'$out/share/man/'" \
248 --param man.endnotes.are.numbered 0 \
249 --param man.break.after.slash 1 \
250 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
251 ${docbook_xsl_ns}/xml/xsl/docbook/manpages/docbook.xsl \
252 ${manual-combined}/man-pages-combined.xml
253 '';
254
255}