Incorporate changes from pre-release reviews.
[scons.git] / doc / SConscript
1 #
2 # SConscript file for building SCons documentation.
3 #
4
5 #
6 # __COPYRIGHT__
7 #
8 # Permission is hereby granted, free of charge, to any person obtaining
9 # a copy of this software and associated documentation files (the
10 # "Software"), to deal in the Software without restriction, including
11 # without limitation the rights to use, copy, modify, merge, publish,
12 # distribute, sublicense, and/or sell copies of the Software, and to
13 # permit persons to whom the Software is furnished to do so, subject to
14 # the following conditions:
15 #
16 # The above copyright notice and this permission notice shall be included
17 # in all copies or substantial portions of the Software.
18 #
19 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
20 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
21 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #
27
28 import os.path
29 import re
30 import string
31
32 Import('env', 'whereis')
33
34 build = os.path.join('#build', 'doc')
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 jade = whereis('jade')
52 jadetex = whereis('jadetex')
53 pdfjadetex = whereis('pdfjadetex')
54 jw = whereis('jw')
55 tidy = whereis('tidy')
56
57 tar_deps = []
58 tar_list = []
59
60 entity_re = re.compile(r'<!entity\s+(?:%\s+)?(?:\S+)\s+SYSTEM\s+"([^"]*)">', re.I)
61 format_re = re.compile(r'<(?:graphic|imagedata)\s+fileref="([^"]*)"(?:\s+format="([^"]*)")?')
62
63 #
64 # Find internal dependencies in .sgml files:
65 #
66 #   <!entity bground SYSTEM "bground.sgml">
67 #   <graphic fileref="file.jpg">
68 #   <imagedata fileref="file.jpg">
69 #
70 # This only finds one per line, and assumes that anything
71 # defined as a SYSTEM entity is, in fact, a file included
72 # somewhere in the document.
73 #
74 def scansgml(node, env, target):
75     includes = []
76
77     contents = node.get_contents()
78
79     includes.extend(entity_re.findall(contents))
80
81     matches = format_re.findall(contents)
82     for m in matches:
83         file, format = m
84         if format and file[-len(format):] != format:
85             file = file + '.' + format
86         if not os.path.isabs(file):
87             a = []
88             f = file
89             while f:
90                 f, tail = os.path.split(f)
91                 if tail == 'doc':
92                     break
93                 a = [tail] + a
94             file = apply(os.path.join, a, {})
95         includes.append(file)
96
97     return includes
98
99 s = Scanner(name = 'sgml', function = scansgml, skeys = ['.sgml', '.mod'])
100 orig_env = env
101 env = orig_env.Copy(SCANNERS = [s])
102
103 if jw:
104     #
105     # Always create a version.sgml file containing the version information
106     # for this run.  Ignore it for dependency purposes so we don't
107     # rebuild all the docs every time just because the date changes.
108     #
109     date, ver, rev = env.Dictionary('DATE', 'VERSION', 'REVISION')
110     version_sgml = File(os.path.join(build, "version.sgml"))
111     #version_sgml = File("version.sgml")
112     verfile = str(version_sgml)
113     try:
114         os.unlink(verfile)
115     except OSError:
116         pass    # okay if the file didn't exist
117     dir, f = os.path.split(verfile)
118     try:
119         os.makedirs(dir)
120     except OSError:
121         pass    # okay if the directory already exists
122     open(verfile, "w").write("""<!--
123 THIS IS AN AUTOMATICALLY-GENERATED FILE.  DO NOT EDIT.
124 -->
125 <!ENTITY builddate "%s">
126 <!ENTITY buildversion "%s">
127 <!ENTITY buildrevision "%s">
128 """ % (date, ver, rev))
129
130     #
131     # Each document will live in its own subdirectory.  List them here
132     # as hash keys, with a hash of the info to control its build.
133     #
134     docs = {
135         'design' : {
136                 'htmlindex' : 'book1.html',
137                 'ps'        : 1,
138                 'pdf'       : 1,
139                 'text'      : 0,
140         },
141         'python10' : {
142                 'htmlindex' : 't1.html',
143                 'html'      : 1,
144                 'ps'        : 1,
145                 'pdf'       : 0,
146                 'text'      : 0,
147                 'graphics'  : [
148                                 'arch.fig',
149                                 'builder.fig',
150                                 'job-task.fig',
151                                 'node.fig',
152                                 'scanner.fig',
153                                 'sig.fig'
154                               ],
155         },
156         'reference' : {
157                 'htmlindex' : 'book1.html',
158                 'html'      : 1,
159                 'ps'        : 1,
160                 'pdf'       : 1,
161                 'text'      : 0,
162         },
163         'user' : {
164                 'htmlindex' : 'book1.html',
165                 'html'      : 1,
166                 'ps'        : 1,
167                 'pdf'       : 1,
168                 'text'      : 0,
169                 'graphics'  : [
170                                 'SCons-win32-install-1.jpg',
171                                 'SCons-win32-install-2.jpg',
172                                 'SCons-win32-install-3.jpg',
173                                 'SCons-win32-install-4.jpg',
174                               ],
175         },
176     }
177
178     #
179     # We have to tell SCons to scan the top-level SGML files which
180     # get included by the document SGML files in the subdirectories.
181     #
182     manifest = File('MANIFEST').rstr()
183     src_files = map(lambda x: x[:-1], open(manifest).readlines())
184     for s in src_files:
185         base, ext = os.path.splitext(s)
186         if ext in ['.fig', '.jpg']:
187             orig_env.Install(build, s)
188         else:
189             orig_env.SCons_revision(os.path.join(build, s), s)
190         Local(os.path.join(build, s))
191
192     #
193     # For each document, build the document itself in HTML, Postscript,
194     # and PDF formats.
195     #
196     for doc in docs.keys():
197         manifest = File(os.path.join(doc, 'MANIFEST')).rstr()
198         src_files = map(lambda x: x[:-1],
199                         open(manifest).readlines())
200         for s in src_files:
201             base, ext = os.path.splitext(s)
202             if ext in ['.fig', '.jpg']:
203                 orig_env.Install(os.path.join(build, doc), os.path.join(doc, s))
204             else:
205                 orig_env.SCons_revision(os.path.join(build, doc, s),
206                                         os.path.join(doc, s))
207             Local(os.path.join(build, doc, s))
208
209         main = os.path.join(build, doc, 'main.sgml')
210         out = 'main.out'
211
212         # Hard-coding the scons-src path is a bit of a hack.  This can
213         # be reworked when a better solution presents itself.
214         scons_src_main = os.path.join('#build', 'scons-src', 'doc', main)
215         env.Ignore(scons_src_main, version_sgml)
216
217         htmldir = os.path.join(build, 'HTML', 'scons-%s' % doc)
218         htmlindex = os.path.join(htmldir, docs[doc]['htmlindex'])
219         html = os.path.join(build, 'HTML', 'scons-%s.html' % doc)
220         ps = os.path.join(build, 'PS', 'scons-%s.ps' % doc)
221         pdf = os.path.join(build, 'PDF', 'scons-%s.pdf' % doc)
222         text = os.path.join(build, 'TEXT', 'scons-%s.txt' % doc)
223
224         if docs[doc].get('html') and jade:
225             cmds = [
226                 "rm -f ${TARGET.dir}/*.html",
227                 "jw -b html -o ${TARGET.dir} $SOURCES",
228                 "mv -v ${TARGET.dir}/index.html $TARGET || true",
229             ]
230             if tidy:
231                 cmds.append("tidy -m -q $TARGET || true")
232             env.Command(htmlindex, main, cmds)
233             Local(htmlindex)
234
235             cmds = [
236                 "rm -f ${TARGET.dir}/main.html",
237                 "jw -u -b html -o ${TARGET.dir} $SOURCES",
238                 "mv -v ${TARGET.dir}/main.html $TARGET || true",
239             ]
240             if tidy:
241                 cmds.append("tidy -m -q $TARGET || true")
242             env.Command(html, main, cmds)
243             Local(html)
244
245             env.Ignore([html, htmlindex], version_sgml)
246
247             tar_deps.extend([html, htmlindex])
248             tar_list.extend([html, htmldir])
249
250             for g in docs[doc].get('graphics', []):
251                 if g[-4:] == '.fig' and fig2dev:
252                     fig = os.path.join(build, doc, g)
253                     jpg = os.path.join(htmldir, g[:-4] + '.jpg')
254                     env.Command(jpg, fig,
255                                 "%s -L jpeg -q 100 $SOURCES $TARGET" % fig2dev)
256                     env.Depends(html, jpg)
257                     Local(jpg)
258                 else:
259                     src = os.path.join(build, doc, g)
260                     Local(env.Install(htmldir, src))
261
262         if docs[doc].get('ps') and jadetex:
263             env.Command(ps, main, [
264                 "rm -f ${TARGET.dir}/%s" % out,
265                 "jw -b ps -o ${TARGET.dir} $SOURCES",
266                 "mv ${TARGET.dir}/main.ps $TARGET",
267                 "rm -f ${TARGET.dir}/%s" % out,
268             ])
269             Local(ps)
270
271             env.Ignore(ps, version_sgml)
272
273             tar_deps.append(ps)
274             tar_list.append(ps)
275
276             for g in docs[doc].get('graphics', []):
277                 if g[-4:] == '.fig' and fig2dev:
278                     fig = os.path.join(build, doc, g)
279                     eps = os.path.join(build, 'PS', g[:-4] + '.eps')
280                     env.Command(eps, fig, "%s -L eps $SOURCES $TARGET" % fig2dev)
281                     env.Depends(ps, eps)
282                     Local(eps)
283                 else:
284                     src = os.path.join(build, doc, g)
285                     Local(env.Install(htmldir, src))
286
287         if docs[doc].get('pdf') and pdfjadetex:
288             env.Command(pdf, main, [
289                 "rm -f ${TARGET.dir}/%s" % out,
290                 "jw -b pdf -o ${TARGET.dir} $SOURCES",
291                 "mv ${TARGET.dir}/main.pdf $TARGET",
292                 "rm -f ${TARGET.dir}/out",
293             ])
294             Local(pdf)
295
296             env.Ignore(pdf, version_sgml)
297
298             tar_deps.append(pdf)
299             tar_list.append(pdf)
300
301         if docs[doc].get('text') and jade and lynx:
302             env.Command(text, html, "lynx -dump ${SOURCE.abspath} > $TARGET")
303             Local(text)
304
305             env.Ignore(text, version_sgml)
306
307             tar_deps.append(text)
308             tar_list.append(text)
309
310 #
311 # Man page(s), in good ol' troff format.
312 #
313 man_page_list = ['scons', 'sconsign']
314
315 for man in man_page_list:
316     man_1 = os.path.join('man', '%s.1' % man)
317
318     if groff:
319         ps = os.path.join(build, 'PS', '%s-man.ps' % man)
320         text = os.path.join(build, 'TEXT', '%s-man.txt' % man)
321
322         env.Command(ps, man_1, "groff -man -Tps $SOURCES > $TARGET")
323         Local(ps)
324
325         env.Command(text, man_1, "groff -man -Tascii $SOURCES > $TARGET")
326         Local(text)
327
328         tar_deps.extend([ps, text])
329         tar_list.extend([ps, text])
330
331     if man2html:
332         html = os.path.join(build, 'HTML' , '%s-man.html' % man)
333
334         cmds = [ "man2html $SOURCES > $TARGET" ]
335         if tidy:
336             cmds.append("tidy -m -q $TARGET || true")
337         env.Command(html, man_1, cmds)
338         Local(html)
339
340         tar_deps.append(html)
341         tar_list.append(html)
342
343 #
344 # Now actually create the tar file of the documentation,
345 # for easy distribution to the web site.
346 #
347 if tar_deps:
348     tar_list = string.join(map(lambda x: x[11:], tar_list))
349     env.Command(doc_tar_gz, tar_deps,
350                 "tar cf${TAR_HFLAG} - -C build/doc %s | gzip > $TARGET" % tar_list)
351     Local(doc_tar_gz)