1{ pkgs, options, config, version, revision, extraSources ? [] }:
2
3with pkgs;
4
5let
6 lib = pkgs.lib;
7
8 # Remove invisible and internal options.
9 optionsList = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
10
11 # Replace functions by the string <function>
12 substFunction = x:
13 if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
14 else if builtins.isList x then map substFunction x
15 else if builtins.isFunction x then "<function>"
16 else x;
17
18 # Clean up declaration sites to not refer to the NixOS source tree.
19 optionsList' = lib.flip map optionsList (opt: opt // {
20 declarations = map stripAnyPrefixes opt.declarations;
21 }
22 // lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
23 // lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
24 // lib.optionalAttrs (opt ? type) { type = substFunction opt.type; });
25
26 # We need to strip references to /nix/store/* from options,
27 # including any `extraSources` if some modules came from elsewhere,
28 # or else the build will fail.
29 #
30 # E.g. if some `options` came from modules in ${pkgs.customModules}/nix,
31 # you'd need to include `extraSources = [ pkgs.customModules ]`
32 prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
33 stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
34
35 # Convert the list of options into an XML file.
36 optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList');
37
38 optionsDocBook = runCommand "options-db.xml" {} ''
39 optionsXML=${optionsXML}
40 if grep /nixpkgs/nixos/modules $optionsXML; then
41 echo "The manual appears to depend on the location of Nixpkgs, which is bad"
42 echo "since this prevents sharing via the NixOS channel. This is typically"
43 echo "caused by an option default that refers to a relative path (see above"
44 echo "for hints about the offending path)."
45 exit 1
46 fi
47 ${libxslt.bin}/bin/xsltproc \
48 --stringparam revision '${revision}' \
49 -o $out ${./options-to-docbook.xsl} $optionsXML
50 '';
51
52 sources = lib.sourceFilesBySuffices ./. [".xml"];
53
54 modulesDoc = builtins.toFile "modules.xml" ''
55 <section xmlns:xi="http://www.w3.org/2001/XInclude" id="modules">
56 ${(lib.concatMapStrings (path: ''
57 <xi:include href="${path}" />
58 '') (lib.catAttrs "value" config.meta.doc))}
59 </section>
60 '';
61
62 copySources =
63 ''
64 cp -prd $sources/* . # */
65 chmod -R u+w .
66 ln -s ${modulesDoc} configuration/modules.xml
67 ln -s ${optionsDocBook} options-db.xml
68 printf "%s" "${version}" > version
69 '';
70
71 toc = builtins.toFile "toc.xml"
72 ''
73 <toc role="chunk-toc">
74 <d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-nixos-manual"><?dbhtml filename="index.html"?>
75 <d:tocentry linkend="ch-options"><?dbhtml filename="options.html"?></d:tocentry>
76 <d:tocentry linkend="ch-release-notes"><?dbhtml filename="release-notes.html"?></d:tocentry>
77 </d:tocentry>
78 </toc>
79 '';
80
81 manualXsltprocOptions = toString [
82 "--param section.autolabel 1"
83 "--param section.label.includes.component.label 1"
84 "--stringparam html.stylesheet style.css"
85 "--param xref.with.number.and.title 1"
86 "--param toc.section.depth 3"
87 "--stringparam admon.style ''"
88 "--stringparam callout.graphics.extension .gif"
89 "--stringparam current.docid manual"
90 "--param chunk.section.depth 0"
91 "--param chunk.first.sections 1"
92 "--param use.id.as.filename 1"
93 "--stringparam generate.toc 'book toc appendix toc'"
94 "--stringparam chunk.toc ${toc}"
95 ];
96
97 manual-combined = runCommand "nixos-manual-combined"
98 { inherit sources;
99 buildInputs = [ libxml2 libxslt ];
100 meta.description = "The NixOS manual as plain docbook XML";
101 }
102 ''
103 ${copySources}
104
105 xmllint --xinclude --output ./manual-combined.xml ./manual.xml
106 xmllint --xinclude --noxincludenode \
107 --output ./man-pages-combined.xml ./man-pages.xml
108
109 xmllint --debug --noout --nonet \
110 --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
111 manual-combined.xml
112 xmllint --debug --noout --nonet \
113 --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
114 man-pages-combined.xml
115
116
117 mkdir $out
118 cp manual-combined.xml $out/
119 cp man-pages-combined.xml $out/
120 '';
121
122 olinkDB = runCommand "manual-olinkdb"
123 { inherit sources;
124 buildInputs = [ libxml2 libxslt ];
125 }
126 ''
127 xsltproc \
128 ${manualXsltprocOptions} \
129 --stringparam collect.xref.targets only \
130 --stringparam targets.filename "$out/manual.db" \
131 --nonet \
132 ${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl \
133 ${manual-combined}/manual-combined.xml
134
135 cat > "$out/olinkdb.xml" <<EOF
136 <?xml version="1.0" encoding="utf-8"?>
137 <!DOCTYPE targetset SYSTEM
138 "file://${docbook5_xsl}/xml/xsl/docbook/common/targetdatabase.dtd" [
139 <!ENTITY manualtargets SYSTEM "file://$out/manual.db">
140 ]>
141 <targetset>
142 <targetsetinfo>
143 Allows for cross-referencing olinks between the manpages
144 and manual.
145 </targetsetinfo>
146
147 <document targetdoc="manual">&manualtargets;</document>
148 </targetset>
149 EOF
150 '';
151
152in rec {
153
154 # The NixOS options in JSON format.
155 optionsJSON = runCommand "options-json"
156 { meta.description = "List of NixOS options in JSON format";
157 }
158 ''
159 # Export list of options in different format.
160 dst=$out/share/doc/nixos
161 mkdir -p $dst
162
163 cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
164 (builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList'))))
165 } $dst/options.json
166
167 mkdir -p $out/nix-support
168 echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
169 ''; # */
170
171 # Generate the NixOS manual.
172 manual = runCommand "nixos-manual"
173 { inherit sources;
174 buildInputs = [ libxml2 libxslt ];
175 meta.description = "The NixOS manual in HTML format";
176 allowedReferences = ["out"];
177 }
178 ''
179 # Generate the HTML manual.
180 dst=$out/share/doc/nixos
181 mkdir -p $dst
182 xsltproc \
183 ${manualXsltprocOptions} \
184 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
185 --nonet --output $dst/ \
186 ${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl \
187 ${manual-combined}/manual-combined.xml
188
189 mkdir -p $dst/images/callouts
190 cp ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/
191
192 cp ${./style.css} $dst/style.css
193
194 mkdir -p $out/nix-support
195 echo "nix-build out $out" >> $out/nix-support/hydra-build-products
196 echo "doc manual $dst" >> $out/nix-support/hydra-build-products
197 ''; # */
198
199
200 manualEpub = runCommand "nixos-manual-epub"
201 { inherit sources;
202 buildInputs = [ libxml2 libxslt zip ];
203 }
204 ''
205 # Generate the epub manual.
206 dst=$out/share/doc/nixos
207
208 xsltproc \
209 ${manualXsltprocOptions} \
210 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
211 --nonet --xinclude --output $dst/epub/ \
212 ${docbook5_xsl}/xml/xsl/docbook/epub/docbook.xsl \
213 ${manual-combined}/manual-combined.xml
214
215 mkdir -p $dst/epub/OEBPS/images/callouts
216 cp -r ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/epub/OEBPS/images/callouts # */
217 echo "application/epub+zip" > mimetype
218 manual="$dst/nixos-manual.epub"
219 zip -0Xq "$manual" mimetype
220 cd $dst/epub && zip -Xr9D "$manual" *
221
222 rm -rf $dst/epub
223
224 mkdir -p $out/nix-support
225 echo "doc-epub manual $manual" >> $out/nix-support/hydra-build-products
226 '';
227
228
229 # Generate the NixOS manpages.
230 manpages = runCommand "nixos-manpages"
231 { inherit sources;
232 buildInputs = [ libxml2 libxslt ];
233 allowedReferences = ["out"];
234 }
235 ''
236 # Generate manpages.
237 mkdir -p $out/share/man
238 xsltproc --nonet \
239 --param man.output.in.separate.dir 1 \
240 --param man.output.base.dir "'$out/share/man/'" \
241 --param man.endnotes.are.numbered 0 \
242 --param man.break.after.slash 1 \
243 --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
244 ${docbook5_xsl}/xml/xsl/docbook/manpages/docbook.xsl \
245 ${manual-combined}/man-pages-combined.xml
246 '';
247
248}