bbb129bd6182844e3ce8cb95ec584457eb272307
[senf.git] / senfscons / pdflatex.py
1 import SCons.Defaults
2
3 import md5, os.path
4 import SCons.Action, SCons.Builder, SCons.Util, SCons.Errors, SCons.Environment
5
6 PDFLaTeXAction = SCons.Action.CommandAction("$PDFLATEXCOM")
7
8 # copied from Action.py ... changed to tage explicit path-names as
9 # target/source instead of node objects
10 def my_executeCommand(cmd_list, target, source, env):
11     import SCons.Util 
12     escape = env.get('ESCAPE', lambda x: x)
13     if env.has_key('SHELL'): shell = env['SHELL']
14     else: raise SCons.Errors.UserError('Missing SHELL construction variable.')
15     if env.has_key('PIPE_BUILD'):
16         pipe_build = 1
17         if env.has_key('PSPAWN'): pspawn = env['PSPAWN']
18         else: raise SCons.Errors.UserError('Missing PSPAWN construction variable.')
19         if env.has_key('PSTDOUT'): pstdout = env['PSTDOUT']
20         else: raise SCons.Errors.UserError('Missing PSTDOUT construction variable.')
21         if env.has_key('PSTDERR'): pstderr = env['PSTDERR']
22         else: raise SCons.Errors.UserError('Missing PSTDOUT construction variable.')
23     else:
24         pipe_build = 0
25         if env.has_key('SPAWN'): spawn = env['SPAWN']
26         else: raise SCons.Errors.UserError('Missing SPAWN construction variable.')
27     # Here, replaced the source and target argumnets with a dict argument
28     cmd_list = env.subst_list(cmd_list, 0, dict = { 'TARGET': target, 'TARGETS': [ target ],
29                                                     'SOURCE': source, 'SOURCES': [ source ] })
30     for cmd_line in cmd_list:
31         if len(cmd_line):
32             try: ENV = env['ENV']
33             except KeyError:
34                 global default_ENV
35                 if not default_ENV:
36                     import SCons.Environment
37                     default_ENV = SCons.Environment.Environment()['ENV']
38                 ENV = default_ENV
39             for key, value in ENV.items():
40                 if SCons.Util.is_List(value):
41                     value = SCons.Util.flatten(value)
42                     ENV[key] = string.join(map(str, value), os.pathsep)
43                 elif not SCons.Util.is_String(value):
44                     ENV[key] = str(value)
45             cmd_line = SCons.Util.escape_list(cmd_line, escape)
46             if pipe_build: ret = pspawn( shell, escape, cmd_line[0], cmd_line,
47                                          ENV, pstdout, pstderr )
48             else: ret = spawn(shell, escape, cmd_line[0], cmd_line, ENV)
49             if ret: return ret
50     return 0
51
52 def TeXchecksum(files):
53     m = md5.new()
54     for f in files:
55         try:
56             m.update(file(f,"rb").read())
57         except IOError: pass
58     return m.digest()
59
60 def TeXPdfAction(target, source, env):
61     src = os.path.abspath(str(source[0]))
62     path, pdf = os.path.split(str(target[0]))
63     base, ext = os.path.splitext(pdf)
64     cwd = os.getcwd()
65     if path: os.chdir(path)
66     checkfiles = [ base + ext for ext in env["TEXCHECKEXT"] ]
67     checksum = TeXchecksum(checkfiles)
68     rv = 0
69     for i in range(env["TEXMAXRECURSE"]+1):
70         if i==env["TEXMAXRECURSE"]:
71             print "\nWARNING: TeX recursion depth exceeded. They generated file may not be final.\n"
72             break
73         rv = my_executeCommand("$PDFLATEXCOM", pdf, src, env)
74         if rv: break
75         new_checksum = TeXchecksum(checkfiles)
76         if new_checksum == checksum: break
77         checksum = new_checksum
78     os.chdir(cwd)
79     return rv
80
81 class TeXPdfBuilder(SCons.Builder.BuilderBase) :
82     def __call__(self, env, target = None, source = SCons.Builder._null, **kw):
83         tlist = SCons.Builder.BuilderBase.__call__(self, env, target, source, **kw)
84         exts = env["TEXCHECKEXT"] + env["TEXCLEANEXT"]
85         for t in tlist:
86             base, ext = os.path.splitext(str(t))
87             for ext in exts:
88                 env.Clean(t,base+ext)
89         return tlist
90
91
92 def generate(env):
93     env['TEXCHECKEXT'] = [ '.aux', '.toc' ]
94     env['TEXCLEANEXT'] = [ '.log', '.dvi' ]
95     env['TEXMAXRECURSE'] = 5
96     env['BUILDERS']['PDF'] = TeXPdfBuilder(action = TeXPdfAction, suffix='.pdf')
97
98 def exists(env):
99     return 1