Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: scons-2.0.1/engine/SCons/Tool/tex.py

Issue 6711079: Added an unmodified copy of SCons to third_party. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/third_party/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « scons-2.0.1/engine/SCons/Tool/tar.py ('k') | scons-2.0.1/engine/SCons/Tool/textfile.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 """SCons.Tool.tex
2
3 Tool-specific initialization for TeX.
4 Generates .dvi files from .tex files
5
6 There normally shouldn't be any need to import this module directly.
7 It will usually be imported through the generic SCons.Tool.Tool()
8 selection method.
9
10 """
11
12 #
13 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S Cons Foundation
14 #
15 # Permission is hereby granted, free of charge, to any person obtaining
16 # a copy of this software and associated documentation files (the
17 # "Software"), to deal in the Software without restriction, including
18 # without limitation the rights to use, copy, modify, merge, publish,
19 # distribute, sublicense, and/or sell copies of the Software, and to
20 # permit persons to whom the Software is furnished to do so, subject to
21 # the following conditions:
22 #
23 # The above copyright notice and this permission notice shall be included
24 # in all copies or substantial portions of the Software.
25 #
26 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
27 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
28 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #
34
35 __revision__ = "src/engine/SCons/Tool/tex.py 5134 2010/08/16 23:02:40 bdeegan"
36
37 import os.path
38 import re
39 import shutil
40 import sys
41 import platform
42
43 import SCons.Action
44 import SCons.Node
45 import SCons.Node.FS
46 import SCons.Util
47 import SCons.Scanner.LaTeX
48
49 Verbose = False
50
51 must_rerun_latex = True
52
53 # these are files that just need to be checked for changes and then rerun latex
54 check_suffixes = ['.toc', '.lof', '.lot', '.out', '.nav', '.snm']
55
56 # these are files that require bibtex or makeindex to be run when they change
57 all_suffixes = check_suffixes + ['.bbl', '.idx', '.nlo', '.glo', '.acn']
58
59 #
60 # regular expressions used to search for Latex features
61 # or outputs that require rerunning latex
62 #
63 # search for all .aux files opened by latex (recorded in the .fls file)
64 openout_aux_re = re.compile(r"INPUT *(.*\.aux)")
65
66 #printindex_re = re.compile(r"^[^%]*\\printindex", re.MULTILINE)
67 #printnomenclature_re = re.compile(r"^[^%]*\\printnomenclature", re.MULTILINE)
68 #printglossary_re = re.compile(r"^[^%]*\\printglossary", re.MULTILINE)
69
70 # search to find rerun warnings
71 warning_rerun_str = '(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)'
72 warning_rerun_re = re.compile(warning_rerun_str, re.MULTILINE)
73
74 # search to find citation rerun warnings
75 rerun_citations_str = "^LaTeX Warning:.*\n.*Rerun to get citations correct"
76 rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE)
77
78 # search to find undefined references or citations warnings
79 undefined_references_str = '(^LaTeX Warning:.*undefined references)|(^Package \w + Warning:.*undefined citations)'
80 undefined_references_re = re.compile(undefined_references_str, re.MULTILINE)
81
82 # used by the emitter
83 auxfile_re = re.compile(r".", re.MULTILINE)
84 tableofcontents_re = re.compile(r"^[^%\n]*\\tableofcontents", re.MULTILINE)
85 makeindex_re = re.compile(r"^[^%\n]*\\makeindex", re.MULTILINE)
86 bibliography_re = re.compile(r"^[^%\n]*\\bibliography", re.MULTILINE)
87 listoffigures_re = re.compile(r"^[^%\n]*\\listoffigures", re.MULTILINE)
88 listoftables_re = re.compile(r"^[^%\n]*\\listoftables", re.MULTILINE)
89 hyperref_re = re.compile(r"^[^%\n]*\\usepackage.*\{hyperref\}", re.MULTILINE)
90 makenomenclature_re = re.compile(r"^[^%\n]*\\makenomenclature", re.MULTILINE)
91 makeglossary_re = re.compile(r"^[^%\n]*\\makeglossary", re.MULTILINE)
92 makeglossaries_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE)
93 makeacronyms_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE)
94 beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE)
95
96 # search to find all files included by Latex
97 include_re = re.compile(r'^[^%\n]*\\(?:include|input){([^}]*)}', re.MULTILINE)
98 includeOnly_re = re.compile(r'^[^%\n]*\\(?:include){([^}]*)}', re.MULTILINE)
99
100 # search to find all graphics files included by Latex
101 includegraphics_re = re.compile(r'^[^%\n]*\\(?:includegraphics(?:\[[^\]]+\])?){( [^}]*)}', re.MULTILINE)
102
103 # search to find all files opened by Latex (recorded in .log file)
104 openout_re = re.compile(r"OUTPUT *(.*)")
105
106 # list of graphics file extensions for TeX and LaTeX
107 TexGraphics = SCons.Scanner.LaTeX.TexGraphics
108 LatexGraphics = SCons.Scanner.LaTeX.LatexGraphics
109
110 # An Action sufficient to build any generic tex file.
111 TeXAction = None
112
113 # An action to build a latex file. This action might be needed more
114 # than once if we are dealing with labels and bibtex.
115 LaTeXAction = None
116
117 # An action to run BibTeX on a file.
118 BibTeXAction = None
119
120 # An action to run MakeIndex on a file.
121 MakeIndexAction = None
122
123 # An action to run MakeIndex (for nomencl) on a file.
124 MakeNclAction = None
125
126 # An action to run MakeIndex (for glossary) on a file.
127 MakeGlossaryAction = None
128
129 # An action to run MakeIndex (for acronyms) on a file.
130 MakeAcronymsAction = None
131
132 # Used as a return value of modify_env_var if the variable is not set.
133 _null = SCons.Scanner.LaTeX._null
134
135 modify_env_var = SCons.Scanner.LaTeX.modify_env_var
136
137 def check_file_error_message(utility, filename='log'):
138 msg = '%s returned an error, check the %s file\n' % (utility, filename)
139 sys.stdout.write(msg)
140
141 def FindFile(name,suffixes,paths,env,requireExt=False):
142 if requireExt:
143 name,ext = SCons.Util.splitext(name)
144 # if the user gave an extension use it.
145 if ext:
146 name = name + ext
147 if Verbose:
148 print " searching for '%s' with extensions: " % name,suffixes
149
150 for path in paths:
151 testName = os.path.join(path,name)
152 if Verbose:
153 print " look for '%s'" % testName
154 if os.path.exists(testName):
155 if Verbose:
156 print " found '%s'" % testName
157 return env.fs.File(testName)
158 else:
159 name_ext = SCons.Util.splitext(testName)[1]
160 if name_ext:
161 continue
162
163 # if no suffix try adding those passed in
164 for suffix in suffixes:
165 testNameExt = testName + suffix
166 if Verbose:
167 print " look for '%s'" % testNameExt
168
169 if os.path.exists(testNameExt):
170 if Verbose:
171 print " found '%s'" % testNameExt
172 return env.fs.File(testNameExt)
173 if Verbose:
174 print " did not find '%s'" % name
175 return None
176
177 def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None ):
178 """A builder for LaTeX files that checks the output in the aux file
179 and decides how many times to use LaTeXAction, and BibTeXAction."""
180
181 global must_rerun_latex
182
183 # This routine is called with two actions. In this file for DVI builds
184 # with LaTeXAction and from the pdflatex.py with PDFLaTeXAction
185 # set this up now for the case where the user requests a different extension
186 # for the target filename
187 if (XXXLaTeXAction == LaTeXAction):
188 callerSuffix = ".dvi"
189 else:
190 callerSuffix = env['PDFSUFFIX']
191
192 basename = SCons.Util.splitext(str(source[0]))[0]
193 basedir = os.path.split(str(source[0]))[0]
194 basefile = os.path.split(str(basename))[1]
195 abspath = os.path.abspath(basedir)
196
197 targetext = os.path.splitext(str(target[0]))[1]
198 targetdir = os.path.split(str(target[0]))[0]
199
200 saved_env = {}
201 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
202 saved_env[var] = modify_env_var(env, var, abspath)
203
204 # Create base file names with the target directory since the auxiliary files
205 # will be made there. That's because the *COM variables have the cd
206 # command in the prolog. We check
207 # for the existence of files before opening them--even ones like the
208 # aux file that TeX always creates--to make it possible to write tests
209 # with stubs that don't necessarily generate all of the same files.
210
211 targetbase = os.path.join(targetdir, basefile)
212
213 # if there is a \makeindex there will be a .idx and thus
214 # we have to run makeindex at least once to keep the build
215 # happy even if there is no index.
216 # Same for glossaries and nomenclature
217 src_content = source[0].get_text_contents()
218 run_makeindex = makeindex_re.search(src_content) and not os.path.exists(targ etbase + '.idx')
219 run_nomenclature = makenomenclature_re.search(src_content) and not os.path.e xists(targetbase + '.nlo')
220 run_glossary = makeglossary_re.search(src_content) and not os.path.exists(ta rgetbase + '.glo')
221 run_glossaries = makeglossaries_re.search(src_content) and not os.path.exist s(targetbase + '.glo')
222 run_acronyms = makeacronyms_re.search(src_content) and not os.path.exists(ta rgetbase + '.acn')
223
224 saved_hashes = {}
225 suffix_nodes = {}
226
227 for suffix in all_suffixes:
228 theNode = env.fs.File(targetbase + suffix)
229 suffix_nodes[suffix] = theNode
230 saved_hashes[suffix] = theNode.get_csig()
231
232 if Verbose:
233 print "hashes: ",saved_hashes
234
235 must_rerun_latex = True
236
237 #
238 # routine to update MD5 hash and compare
239 #
240 def check_MD5(filenode, suffix):
241 global must_rerun_latex
242 # two calls to clear old csig
243 filenode.clear_memoized_values()
244 filenode.ninfo = filenode.new_ninfo()
245 new_md5 = filenode.get_csig()
246
247 if saved_hashes[suffix] == new_md5:
248 if Verbose:
249 print "file %s not changed" % (targetbase+suffix)
250 return False # unchanged
251 saved_hashes[suffix] = new_md5
252 must_rerun_latex = True
253 if Verbose:
254 print "file %s changed, rerunning Latex, new hash = " % (targetbase+ suffix), new_md5
255 return True # changed
256
257 # generate the file name that latex will generate
258 resultfilename = targetbase + callerSuffix
259
260 count = 0
261
262 while (must_rerun_latex and count < int(env.subst('$LATEXRETRIES'))) :
263 result = XXXLaTeXAction(target, source, env)
264 if result != 0:
265 return result
266
267 count = count + 1
268
269 must_rerun_latex = False
270 # Decide if various things need to be run, or run again.
271
272 # Read the log file to find warnings/errors
273 logfilename = targetbase + '.log'
274 logContent = ''
275 if os.path.exists(logfilename):
276 logContent = open(logfilename, "rb").read()
277
278
279 # Read the fls file to find all .aux files
280 flsfilename = targetbase + '.fls'
281 flsContent = ''
282 auxfiles = []
283 if os.path.exists(flsfilename):
284 flsContent = open(flsfilename, "rb").read()
285 auxfiles = openout_aux_re.findall(flsContent)
286 if Verbose:
287 print "auxfiles ",auxfiles
288
289 # Now decide if bibtex will need to be run.
290 # The information that bibtex reads from the .aux file is
291 # pass-independent. If we find (below) that the .bbl file is unchanged,
292 # then the last latex saw a correct bibliography.
293 # Therefore only do this on the first pass
294 if count == 1:
295 for auxfilename in auxfiles:
296 target_aux = os.path.join(targetdir, auxfilename)
297 if os.path.exists(target_aux):
298 content = open(target_aux, "rb").read()
299 if content.find("bibdata") != -1:
300 if Verbose:
301 print "Need to run bibtex"
302 bibfile = env.fs.File(targetbase)
303 result = BibTeXAction(bibfile, bibfile, env)
304 if result != 0:
305 check_file_error_message(env['BIBTEX'], 'blg')
306 return result
307 must_rerun_latex = check_MD5(suffix_nodes['.bbl'],'.bbl' )
308 break
309
310 # Now decide if latex will need to be run again due to index.
311 if check_MD5(suffix_nodes['.idx'],'.idx') or (count == 1 and run_makeind ex):
312 # We must run makeindex
313 if Verbose:
314 print "Need to run makeindex"
315 idxfile = suffix_nodes['.idx']
316 result = MakeIndexAction(idxfile, idxfile, env)
317 if result != 0:
318 check_file_error_message(env['MAKEINDEX'], 'ilg')
319 return result
320
321 # TO-DO: need to add a way for the user to extend this list for whatever
322 # auxiliary files they create in other (or their own) packages
323 # Harder is case is where an action needs to be called -- that should be rare (I hope?)
324
325 for index in check_suffixes:
326 check_MD5(suffix_nodes[index],index)
327
328 # Now decide if latex will need to be run again due to nomenclature.
329 if check_MD5(suffix_nodes['.nlo'],'.nlo') or (count == 1 and run_nomencl ature):
330 # We must run makeindex
331 if Verbose:
332 print "Need to run makeindex for nomenclature"
333 nclfile = suffix_nodes['.nlo']
334 result = MakeNclAction(nclfile, nclfile, env)
335 if result != 0:
336 check_file_error_message('%s (nomenclature)' % env['MAKENCL'],
337 'nlg')
338 #return result
339
340 # Now decide if latex will need to be run again due to glossary.
341 if check_MD5(suffix_nodes['.glo'],'.glo') or (count == 1 and run_glossar ies) or (count == 1 and run_glossary):
342 # We must run makeindex
343 if Verbose:
344 print "Need to run makeindex for glossary"
345 glofile = suffix_nodes['.glo']
346 result = MakeGlossaryAction(glofile, glofile, env)
347 if result != 0:
348 check_file_error_message('%s (glossary)' % env['MAKEGLOSSARY'],
349 'glg')
350 #return result
351
352 # Now decide if latex will need to be run again due to acronyms.
353 if check_MD5(suffix_nodes['.acn'],'.acn') or (count == 1 and run_acronym s):
354 # We must run makeindex
355 if Verbose:
356 print "Need to run makeindex for acronyms"
357 acrfile = suffix_nodes['.acn']
358 result = MakeAcronymsAction(acrfile, acrfile, env)
359 if result != 0:
360 check_file_error_message('%s (acronyms)' % env['MAKEACRONYMS'],
361 'alg')
362 return result
363
364 # Now decide if latex needs to be run yet again to resolve warnings.
365 if warning_rerun_re.search(logContent):
366 must_rerun_latex = True
367 if Verbose:
368 print "rerun Latex due to latex or package rerun warning"
369
370 if rerun_citations_re.search(logContent):
371 must_rerun_latex = True
372 if Verbose:
373 print "rerun Latex due to 'Rerun to get citations correct' warni ng"
374
375 if undefined_references_re.search(logContent):
376 must_rerun_latex = True
377 if Verbose:
378 print "rerun Latex due to undefined references or citations"
379
380 if (count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex):
381 print "reached max number of retries on Latex ,",int(env.subst('$LAT EXRETRIES'))
382 # end of while loop
383
384 # rename Latex's output to what the target name is
385 if not (str(target[0]) == resultfilename and os.path.exists(resultfilename )):
386 if os.path.exists(resultfilename):
387 print "move %s to %s" % (resultfilename, str(target[0]), )
388 shutil.move(resultfilename,str(target[0]))
389
390 # Original comment (when TEXPICTS was not restored):
391 # The TEXPICTS enviroment variable is needed by a dvi -> pdf step
392 # later on Mac OSX so leave it
393 #
394 # It is also used when searching for pictures (implicit dependencies).
395 # Why not set the variable again in the respective builder instead
396 # of leaving local modifications in the environment? What if multiple
397 # latex builds in different directories need different TEXPICTS?
398 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
399 if var == 'TEXPICTS':
400 continue
401 if saved_env[var] is _null:
402 try:
403 del env['ENV'][var]
404 except KeyError:
405 pass # was never set
406 else:
407 env['ENV'][var] = saved_env[var]
408
409 return result
410
411 def LaTeXAuxAction(target = None, source= None, env=None):
412 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env )
413 return result
414
415 LaTeX_re = re.compile("\\\\document(style|class)")
416
417 def is_LaTeX(flist,env,abspath):
418 """Scan a file list to decide if it's TeX- or LaTeX-flavored."""
419
420 # We need to scan files that are included in case the
421 # \documentclass command is in them.
422
423 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
424 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
425 paths = env['ENV']['TEXINPUTS']
426 if SCons.Util.is_List(paths):
427 pass
428 else:
429 # Split at os.pathsep to convert into absolute path
430 paths = paths.split(os.pathsep)
431
432 # now that we have the path list restore the env
433 if savedpath is _null:
434 try:
435 del env['ENV']['TEXINPUTS']
436 except KeyError:
437 pass # was never set
438 else:
439 env['ENV']['TEXINPUTS'] = savedpath
440 if Verbose:
441 print "is_LaTeX search path ",paths
442 print "files to search :",flist
443
444 # Now that we have the search path and file list, check each one
445 for f in flist:
446 if Verbose:
447 print " checking for Latex source ",str(f)
448
449 content = f.get_text_contents()
450 if LaTeX_re.search(content):
451 if Verbose:
452 print "file %s is a LaTeX file" % str(f)
453 return 1
454 if Verbose:
455 print "file %s is not a LaTeX file" % str(f)
456
457 # now find included files
458 inc_files = [ ]
459 inc_files.extend( include_re.findall(content) )
460 if Verbose:
461 print "files included by '%s': "%str(f),inc_files
462 # inc_files is list of file names as given. need to find them
463 # using TEXINPUTS paths.
464
465 # search the included files
466 for src in inc_files:
467 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt =False)
468 # make this a list since is_LaTeX takes a list.
469 fileList = [srcNode,]
470 if Verbose:
471 print "FindFile found ",srcNode
472 if srcNode is not None:
473 file_test = is_LaTeX(fileList, env, abspath)
474
475 # return on first file that finds latex is needed.
476 if file_test:
477 return file_test
478
479 if Verbose:
480 print " done scanning ",str(f)
481
482 return 0
483
484 def TeXLaTeXFunction(target = None, source= None, env=None):
485 """A builder for TeX and LaTeX that scans the source file to
486 decide the "flavor" of the source and then executes the appropriate
487 program."""
488
489 # find these paths for use in is_LaTeX to search for included files
490 basedir = os.path.split(str(source[0]))[0]
491 abspath = os.path.abspath(basedir)
492
493 if is_LaTeX(source,env,abspath):
494 result = LaTeXAuxAction(target,source,env)
495 if result != 0:
496 check_file_error_message(env['LATEX'])
497 else:
498 result = TeXAction(target,source,env)
499 if result != 0:
500 check_file_error_message(env['TEX'])
501 return result
502
503 def TeXLaTeXStrFunction(target = None, source= None, env=None):
504 """A strfunction for TeX and LaTeX that scans the source file to
505 decide the "flavor" of the source and then returns the appropriate
506 command string."""
507 if env.GetOption("no_exec"):
508
509 # find these paths for use in is_LaTeX to search for included files
510 basedir = os.path.split(str(source[0]))[0]
511 abspath = os.path.abspath(basedir)
512
513 if is_LaTeX(source,env,abspath):
514 result = env.subst('$LATEXCOM',0,target,source)+" ..."
515 else:
516 result = env.subst("$TEXCOM",0,target,source)+" ..."
517 else:
518 result = ''
519 return result
520
521 def tex_eps_emitter(target, source, env):
522 """An emitter for TeX and LaTeX sources when
523 executing tex or latex. It will accept .ps and .eps
524 graphics files
525 """
526 (target, source) = tex_emitter_core(target, source, env, TexGraphics)
527
528 return (target, source)
529
530 def tex_pdf_emitter(target, source, env):
531 """An emitter for TeX and LaTeX sources when
532 executing pdftex or pdflatex. It will accept graphics
533 files of types .pdf, .jpg, .png, .gif, and .tif
534 """
535 (target, source) = tex_emitter_core(target, source, env, LatexGraphics)
536
537 return (target, source)
538
539 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi cs_extensions, targetdir, aux_files):
540 """ For theFile (a Node) update any file_tests and search for graphics files
541 then find all included files and call ScanFiles recursively for each of them """
542
543 content = theFile.get_text_contents()
544 if Verbose:
545 print " scanning ",str(theFile)
546
547 for i in range(len(file_tests_search)):
548 if file_tests[i][0] is None:
549 file_tests[i][0] = file_tests_search[i].search(content)
550
551 incResult = includeOnly_re.search(content)
552 if incResult:
553 aux_files.append(os.path.join(targetdir, incResult.group(1)))
554 if Verbose:
555 print "\include file names : ", aux_files
556 # recursively call this on each of the included files
557 inc_files = [ ]
558 inc_files.extend( include_re.findall(content) )
559 if Verbose:
560 print "files included by '%s': "%str(theFile),inc_files
561 # inc_files is list of file names as given. need to find them
562 # using TEXINPUTS paths.
563
564 for src in inc_files:
565 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=Fal se)
566 if srcNode is not None:
567 file_tests = ScanFiles(srcNode, target, paths, file_tests, file_test s_search, env, graphics_extensions, targetdir, aux_files)
568 if Verbose:
569 print " done scanning ",str(theFile)
570 return file_tests
571
572 def tex_emitter_core(target, source, env, graphics_extensions):
573 """An emitter for TeX and LaTeX sources.
574 For LaTeX sources we try and find the common created files that
575 are needed on subsequent runs of latex to finish tables of contents,
576 bibliographies, indices, lists of figures, and hyperlink references.
577 """
578 basename = SCons.Util.splitext(str(source[0]))[0]
579 basefile = os.path.split(str(basename))[1]
580 targetdir = os.path.split(str(target[0]))[0]
581 targetbase = os.path.join(targetdir, basefile)
582
583 basedir = os.path.split(str(source[0]))[0]
584 abspath = os.path.abspath(basedir)
585 target[0].attributes.path = abspath
586
587 #
588 # file names we will make use of in searching the sources and log file
589 #
590 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.g lg', '.alg'] + all_suffixes
591 auxfilename = targetbase + '.aux'
592 logfilename = targetbase + '.log'
593 flsfilename = targetbase + '.fls'
594
595 env.SideEffect(auxfilename,target[0])
596 env.SideEffect(logfilename,target[0])
597 env.SideEffect(flsfilename,target[0])
598 if Verbose:
599 print "side effect :",auxfilename,logfilename,flsfilename
600 env.Clean(target[0],auxfilename)
601 env.Clean(target[0],logfilename)
602 env.Clean(target[0],flsfilename)
603
604 content = source[0].get_text_contents()
605
606 idx_exists = os.path.exists(targetbase + '.idx')
607 nlo_exists = os.path.exists(targetbase + '.nlo')
608 glo_exists = os.path.exists(targetbase + '.glo')
609 acr_exists = os.path.exists(targetbase + '.acn')
610
611 # set up list with the regular expressions
612 # we use to find features used
613 file_tests_search = [auxfile_re,
614 makeindex_re,
615 bibliography_re,
616 tableofcontents_re,
617 listoffigures_re,
618 listoftables_re,
619 hyperref_re,
620 makenomenclature_re,
621 makeglossary_re,
622 makeglossaries_re,
623 makeacronyms_re,
624 beamer_re ]
625 # set up list with the file suffixes that need emitting
626 # when a feature is found
627 file_tests_suff = [['.aux'],
628 ['.idx', '.ind', '.ilg'],
629 ['.bbl', '.blg'],
630 ['.toc'],
631 ['.lof'],
632 ['.lot'],
633 ['.out'],
634 ['.nlo', '.nls', '.nlg'],
635 ['.glo', '.gls', '.glg'],
636 ['.glo', '.gls', '.glg'],
637 ['.acn', '.acr', '.alg'],
638 ['.nav', '.snm', '.out', '.toc'] ]
639 # build the list of lists
640 file_tests = []
641 for i in range(len(file_tests_search)):
642 file_tests.append( [None, file_tests_suff[i]] )
643
644 # TO-DO: need to add a way for the user to extend this list for whatever
645 # auxiliary files they create in other (or their own) packages
646
647 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
648 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
649 paths = env['ENV']['TEXINPUTS']
650 if SCons.Util.is_List(paths):
651 pass
652 else:
653 # Split at os.pathsep to convert into absolute path
654 paths = paths.split(os.pathsep)
655
656 # now that we have the path list restore the env
657 if savedpath is _null:
658 try:
659 del env['ENV']['TEXINPUTS']
660 except KeyError:
661 pass # was never set
662 else:
663 env['ENV']['TEXINPUTS'] = savedpath
664 if Verbose:
665 print "search path ",paths
666
667 aux_files = []
668 file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_sear ch, env, graphics_extensions, targetdir, aux_files)
669
670 for (theSearch,suffix_list) in file_tests:
671 if theSearch:
672 for suffix in suffix_list:
673 env.SideEffect(targetbase + suffix,target[0])
674 if Verbose:
675 print "side effect :",targetbase + suffix
676 env.Clean(target[0],targetbase + suffix)
677
678 for aFile in aux_files:
679 aFile_base = SCons.Util.splitext(aFile)[0]
680 env.SideEffect(aFile_base + '.aux',target[0])
681 if Verbose:
682 print "side effect :",aFile_base + '.aux'
683 env.Clean(target[0],aFile_base + '.aux')
684 # read fls file to get all other files that latex creates and will read on t he next pass
685 # remove files from list that we explicitly dealt with above
686 if os.path.exists(flsfilename):
687 content = open(flsfilename, "rb").read()
688 out_files = openout_re.findall(content)
689 myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targ etbase+'.pdf']
690 for filename in out_files[:]:
691 if filename in myfiles:
692 out_files.remove(filename)
693 env.SideEffect(out_files,target[0])
694 if Verbose:
695 print "side effect :",out_files
696 env.Clean(target[0],out_files)
697
698 return (target, source)
699
700
701 TeXLaTeXAction = None
702
703 def generate(env):
704 """Add Builders and construction variables for TeX to an Environment."""
705
706 global TeXLaTeXAction
707 if TeXLaTeXAction is None:
708 TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction,
709 strfunction=TeXLaTeXStrFunction)
710
711 env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes)
712
713 generate_common(env)
714
715 import dvi
716 dvi.generate(env)
717
718 bld = env['BUILDERS']['DVI']
719 bld.add_action('.tex', TeXLaTeXAction)
720 bld.add_emitter('.tex', tex_eps_emitter)
721
722 def generate_common(env):
723 """Add internal Builders and construction variables for LaTeX to an Environm ent."""
724
725 # A generic tex file Action, sufficient for all tex files.
726 global TeXAction
727 if TeXAction is None:
728 TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR")
729
730 # An Action to build a latex file. This might be needed more
731 # than once if we are dealing with labels and bibtex.
732 global LaTeXAction
733 if LaTeXAction is None:
734 LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR")
735
736 # Define an action to run BibTeX on a file.
737 global BibTeXAction
738 if BibTeXAction is None:
739 BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR")
740
741 # Define an action to run MakeIndex on a file.
742 global MakeIndexAction
743 if MakeIndexAction is None:
744 MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXCOMSTR ")
745
746 # Define an action to run MakeIndex on a file for nomenclatures.
747 global MakeNclAction
748 if MakeNclAction is None:
749 MakeNclAction = SCons.Action.Action("$MAKENCLCOM", "$MAKENCLCOMSTR")
750
751 # Define an action to run MakeIndex on a file for glossaries.
752 global MakeGlossaryAction
753 if MakeGlossaryAction is None:
754 MakeGlossaryAction = SCons.Action.Action("$MAKEGLOSSARYCOM", "$MAKEGLOSS ARYCOMSTR")
755
756 # Define an action to run MakeIndex on a file for acronyms.
757 global MakeAcronymsAction
758 if MakeAcronymsAction is None:
759 MakeAcronymsAction = SCons.Action.Action("$MAKEACRONYMSCOM", "$MAKEACRON YMSCOMSTR")
760
761 CDCOM = 'cd '
762 if platform.system() == 'Windows':
763 # allow cd command to change drives on Windows
764 CDCOM = 'cd /D '
765
766 env['TEX'] = 'tex'
767 env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
768 env['TEXCOM'] = CDCOM + '${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}'
769
770 env['PDFTEX'] = 'pdftex'
771 env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
772 env['PDFTEXCOM'] = CDCOM + '${TARGET.dir} && $PDFTEX $PDFTEXFLAGS ${SOURCE .file}'
773
774 env['LATEX'] = 'latex'
775 env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
776 env['LATEXCOM'] = CDCOM + '${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE. file}'
777 env['LATEXRETRIES'] = 3
778
779 env['PDFLATEX'] = 'pdflatex'
780 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder' )
781 env['PDFLATEXCOM'] = CDCOM + '${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${ SOURCE.file}'
782
783 env['BIBTEX'] = 'bibtex'
784 env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
785 env['BIBTEXCOM'] = CDCOM + '${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE .filebase}'
786
787 env['MAKEINDEX'] = 'makeindex'
788 env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('')
789 env['MAKEINDEXCOM'] = CDCOM + '${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}'
790
791 env['MAKEGLOSSARY'] = 'makeindex'
792 env['MAKEGLOSSARYSTYLE'] = '${SOURCE.filebase}.ist'
793 env['MAKEGLOSSARYFLAGS'] = SCons.Util.CLVar('-s ${MAKEGLOSSARYSTYLE} -t ${SO URCE.filebase}.glg')
794 env['MAKEGLOSSARYCOM'] = CDCOM + '${TARGET.dir} && $MAKEGLOSSARY ${SOURCE. filebase}.glo $MAKEGLOSSARYFLAGS -o ${SOURCE.filebase}.gls'
795
796 env['MAKEACRONYMS'] = 'makeindex'
797 env['MAKEACRONYMSSTYLE'] = '${SOURCE.filebase}.ist'
798 env['MAKEACRONYMSFLAGS'] = SCons.Util.CLVar('-s ${MAKEACRONYMSSTYLE} -t ${SO URCE.filebase}.alg')
799 env['MAKEACRONYMSCOM'] = CDCOM + '${TARGET.dir} && $MAKEACRONYMS ${SOURCE. filebase}.acn $MAKEACRONYMSFLAGS -o ${SOURCE.filebase}.acr'
800
801 env['MAKENCL'] = 'makeindex'
802 env['MAKENCLSTYLE'] = 'nomencl.ist'
803 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg'
804 env['MAKENCLCOM'] = CDCOM + '${TARGET.dir} && $MAKENCL ${SOURCE.filebase}. nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls'
805
806 def exists(env):
807 return env.Detect('tex')
808
809 # Local Variables:
810 # tab-width:4
811 # indent-tabs-mode:nil
812 # End:
813 # vim: set expandtab tabstop=4 shiftwidth=4:
OLDNEW
« no previous file with comments | « scons-2.0.1/engine/SCons/Tool/tar.py ('k') | scons-2.0.1/engine/SCons/Tool/textfile.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698