Run HTML files through tidy (if it's available) to clean them up.
[scons.git] / doc / SConscript
1 #
2 # SConscript file for building SCons documentation.
3 #
4 # THIS IS NOT READY YET.  DO NOT TRY TO BUILD SCons WITH ITSELF YET.
5 #
6
7 #
8 # Copyright (c) 2001, 2002 Steven Knight
9 #
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #
29
30 import os.path
31 import re
32 import string
33
34 Import('env', 'whereis')
35
36 #
37 #
38 #
39 doc_tar_gz = os.path.join('#build',
40                           'dist',
41                           'scons-doc-%s.tar.gz' % env.Dictionary('VERSION'))
42
43 #
44 # We'll only try to build text files (for some documents)
45 # if lynx is available to do the dump.
46 #
47 fig2dev = whereis('fig2dev')
48 groff = whereis('groff')
49 lynx = whereis('lynx')
50 man2html = whereis('man2html')
51 jw = whereis('jw')
52 tidy = whereis('tidy')
53
54 tar_deps = []
55 tar_list = ""
56
57 entity_re = re.compile(r'<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">', re.I)
58 format_re = re.compile(r'<(?:graphic|imagedata)\s+fileref="([^"]*)"(?:\s+format="([^"]*)")?')
59
60 #
61 # Find internal dependencies in .sgml files:
62 #
63 #   <!entity bground SYSTEM "bground.sgml">
64 #   <graphic fileref="file.jpg">
65 #   <imagedata fileref="file.jpg">
66 #
67 # This only finds one per line, and assumes that anything
68 # defined as a SYSTEM entity is, in fact, a file included
69 # somewhere in the document.
70 #
71 def scansgml(node, env, argument = None):
72     includes = []
73
74     contents = node.get_contents()
75
76     includes.extend(entity_re.findall(contents))
77
78     matches = format_re.findall(contents)
79     for m in matches:
80         file, format = m
81         if format and file[-len(format):] != format:
82             file = file + format
83         if argument and not os.path.isabs(file):
84             file = os.path.join(argument, file)
85         includes.append(file)
86
87     return includes
88
89 if jw:
90     #
91     # Always create a version.sgml file containing the version information
92     # for this run.  Ignore it for dependency purposes so we don't
93     # rebuild all the docs every time just because the date changes.
94     #
95     date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION')
96     verfile = str(File("version.sgml"))
97     try:
98         os.unlink(verfile)
99     except:
100         pass
101     open(verfile, "w").write("""<!--
102 THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
103 -->
104 <!ENTITY builddate "%s">
105 <!ENTITY buildversion "%s">
106 <!ENTITY buildrevision "%s">
107 """ % (date, ver, rev))
108
109     #
110     # Each document will live in its own subdirectory.  List them here
111     # as hash keys, with a hash of the info to control its build.
112     #
113     docs = {
114         'design' : {
115                 'htmlindex' : 'book1.html',
116                 'ps'        : 1,
117                 'pdf'       : 1,
118                 'text'      : 0,
119                 'scan'      : Scanner(name = 'design',
120                                       function = scansgml,
121                                       argument = 'design'),
122         },
123         'python10' : {
124                 'htmlindex' : 't1.html',
125                 'html'      : 1,
126                 'ps'        : 1,
127                 'pdf'       : 0,
128                 'text'      : 0,
129                 'graphics'  : [ 'arch', 'builder', 'job-task', 'node', 'scanner', 'sig' ],
130                 'scan'      : Scanner(name = 'python10',
131                                       function = scansgml,
132                                       argument = 'python10'),
133         },
134         'user' : {
135                 'htmlindex' : 'book1.html',
136                 'html'      : 1,
137                 'ps'        : 1,
138                 'pdf'       : 1,
139                 'text'      : 0,
140                 'scan'      : Scanner(name = 'user',
141                                       function = scansgml,
142                                       argument = 'user'),
143         },
144     }
145
146     #
147     # We have to tell Cons to QuickScan the top-level SGML files which
148     # get included by the document SGML files in the subdirectories.
149     #
150     included_sgml = [
151         'scons.mod',
152         'copyright.sgml',
153     ]
154
155     s = Scanner(name = 'sgml', function = scansgml)
156
157     for sgml in included_sgml:
158         File(sgml).scanner_set(s)
159
160     #
161     # For each document, build the document itself in HTML, Postscript,
162     # and PDF formats.
163     #
164     for doc in docs.keys():
165         main = os.path.join(doc, 'main.sgml')
166         out = 'main.out'
167
168         htmldir = os.path.join('HTML', 'scons-%s' % doc)
169         htmlindex = os.path.join(htmldir, docs[doc]['htmlindex'])
170         html = os.path.join('HTML', 'scons-%s.html' % doc)
171         ps = os.path.join('PS', 'scons-%s.ps' % doc)
172         pdf = os.path.join('PDF', 'scons-%s.pdf' % doc)
173         text = os.path.join('TEXT', 'scons-%s.txt' % doc)
174
175         s = docs[doc].get('scan')
176         if s:
177             File(main).scanner_set(s)
178
179         if docs[doc].get('html'):
180             cmds = [
181                 "rm -f ${TARGET.dir}/*.html",
182                 "jw -b html -o ${TARGET.dir} $SOURCES",
183                 "mv -v ${TARGET.dir}/index.html $TARGET || true",
184             ]
185             if tidy:
186                 cmds.append("tidy -m -q $TARGET || true")
187             env.Command(htmlindex, main, cmds)
188
189             cmds = [
190                 "rm -f ${TARGET.dir}/main.html",
191                 "jw -u -b html -o ${TARGET.dir} $SOURCES",
192                 "mv -v ${TARGET.dir}/main.html $TARGET || true",
193             ]
194             if tidy:
195                 cmds.append("tidy -m -q $TARGET || true")
196             env.Command(html, main, cmds)
197
198             env.Ignore([html, htmlindex], "version.sgml")
199
200             tar_deps.extend([html, htmlindex])
201             tar_list = string.join([tar_list, html, htmldir], " ")
202
203             if fig2dev:
204                 for g in docs[doc].get('graphics', []):
205                     fig = os.path.join(doc, '%s.fig' % g)
206                     jpg = os.path.join(htmldir, '%s.jpg' % g)
207                     env.Command(jpg, fig,
208                                 "%s -L jpeg -q 100 $SOURCES $TARGET" % fig2dev)
209                     env.Depends(ps, jpg)
210
211         if docs[doc].get('ps'):
212             env.Command(ps, main, [
213                 "rm -f ${TARGET.dir}/%s" % out,
214                 "jw -b ps -o ${TARGET.dir} $SOURCES",
215                 "mv ${TARGET.dir}/main.ps $TARGET",
216                 "rm -f ${TARGET.dir}/%s" % out,
217             ])
218
219             env.Ignore(ps, "version.sgml")
220
221             tar_deps.append(ps)
222             tar_list = tar_list + " " + ps
223
224             if fig2dev:
225                 for g in docs[doc].get('graphics', []):
226                     fig = os.path.join(doc, '%s.fig' % g)
227                     eps = os.path.join('PS', '%s.eps' % g)
228                     env.Command(eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev)
229                     env.Depends(ps, eps)
230
231         if docs[doc].get('pdf'):
232             env.Command(pdf, main, [
233                 "rm -f ${TARGET.dir}/%s" % out,
234                 "jw -b pdf -o ${TARGET.dir} $SOURCES",
235                 "mv ${TARGET.dir}/main.pdf $TARGET",
236                 "rm -f ${TARGET.dir}/out",
237             ])
238
239             env.Ignore(pdf, "version.sgml")
240
241             tar_deps.append(pdf)
242             tar_list = tar_list + " " + pdf
243
244         if docs[doc].get('text') and lynx:
245             env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET")
246
247             env.Ignore(text, "version.sgml")
248
249             tar_deps.append(text)
250             tar_list = tar_list + " " + text
251
252 #
253 # Man page(s), in good ol' troff format.
254 #
255 scons_1 = os.path.join('man', 'scons.1')
256
257 if groff:
258     ps = os.path.join('PS', 'scons-man.ps')
259     text = os.path.join('TEXT', 'scons-man.txt')
260
261     env.Command(ps, scons_1, "groff -man -Tps $SOURCES > $TARGET")
262
263     env.Command(text, scons_1, "groff -man -Tascii $SOURCES > $TARGET")
264
265     tar_deps.extend([ps, text])
266     tar_list = string.join([tar_list, ps, text], " ")
267
268 if man2html:
269     html = os.path.join('HTML' , 'scons-man.html')
270
271     cmds = [ "man2html $SOURCES > $TARGET" ]
272     if tidy:
273         cmds.append("tidy -m -q $TARGET || true")
274     env.Command(html, scons_1, cmds)
275
276     tar_deps.append(html)
277     tar_list = tar_list + " " + html
278
279 #
280 # Now actually create the tar file of the documentation,
281 # for easy distribution to the web site.
282 #
283 env.Command(doc_tar_gz, tar_deps,
284             "tar zch -f $TARGET -C build/doc %s" % tar_list)