3 Tool-specific initialization for TeX.
4 Generates .dvi files from .tex files
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()
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:
23 # The above copyright notice and this permission notice shall be included
24 # in all copies or substantial portions of the Software.
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.
35 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
46 import SCons.Scanner.LaTeX
50 must_rerun_latex = True
52 # these are files that just need to be checked for changes and then rerun latex
53 check_suffixes = ['.toc', '.lof', '.lot', '.out', '.nav', '.snm']
55 # these are files that require bibtex or makeindex to be run when they change
56 all_suffixes = check_suffixes + ['.bbl', '.idx', '.nlo', '.glo', '.acn']
59 # regular expressions used to search for Latex features
60 # or outputs that require rerunning latex
62 # search for all .aux files opened by latex (recorded in the .fls file)
63 openout_aux_re = re.compile(r"INPUT *(.*\.aux)")
65 #printindex_re = re.compile(r"^[^%]*\\printindex", re.MULTILINE)
66 #printnomenclature_re = re.compile(r"^[^%]*\\printnomenclature", re.MULTILINE)
67 #printglossary_re = re.compile(r"^[^%]*\\printglossary", re.MULTILINE)
69 # search to find rerun warnings
70 warning_rerun_str = '(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)'
71 warning_rerun_re = re.compile(warning_rerun_str, re.MULTILINE)
73 # search to find citation rerun warnings
74 rerun_citations_str = "^LaTeX Warning:.*\n.*Rerun to get citations correct"
75 rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE)
77 # search to find undefined references or citations warnings
78 undefined_references_str = '(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)'
79 undefined_references_re = re.compile(undefined_references_str, re.MULTILINE)
82 auxfile_re = re.compile(r".", re.MULTILINE)
83 tableofcontents_re = re.compile(r"^[^%\n]*\\tableofcontents", re.MULTILINE)
84 makeindex_re = re.compile(r"^[^%\n]*\\makeindex", re.MULTILINE)
85 bibliography_re = re.compile(r"^[^%\n]*\\bibliography", re.MULTILINE)
86 listoffigures_re = re.compile(r"^[^%\n]*\\listoffigures", re.MULTILINE)
87 listoftables_re = re.compile(r"^[^%\n]*\\listoftables", re.MULTILINE)
88 hyperref_re = re.compile(r"^[^%\n]*\\usepackage.*\{hyperref\}", re.MULTILINE)
89 makenomenclature_re = re.compile(r"^[^%\n]*\\makenomenclature", re.MULTILINE)
90 makeglossary_re = re.compile(r"^[^%\n]*\\makeglossary", re.MULTILINE)
91 makeglossaries_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE)
92 makeacronyms_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE)
93 beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE)
95 # search to find all files included by Latex
96 include_re = re.compile(r'^[^%\n]*\\(?:include|input){([^}]*)}', re.MULTILINE)
97 includeOnly_re = re.compile(r'^[^%\n]*\\(?:include){([^}]*)}', re.MULTILINE)
99 # search to find all graphics files included by Latex
100 includegraphics_re = re.compile(r'^[^%\n]*\\(?:includegraphics(?:\[[^\]]+\])?){([^}]*)}', re.MULTILINE)
102 # search to find all files opened by Latex (recorded in .log file)
103 openout_re = re.compile(r"OUTPUT *(.*)")
105 # list of graphics file extensions for TeX and LaTeX
106 TexGraphics = SCons.Scanner.LaTeX.TexGraphics
107 LatexGraphics = SCons.Scanner.LaTeX.LatexGraphics
109 # An Action sufficient to build any generic tex file.
112 # An action to build a latex file. This action might be needed more
113 # than once if we are dealing with labels and bibtex.
116 # An action to run BibTeX on a file.
119 # An action to run MakeIndex on a file.
120 MakeIndexAction = None
122 # An action to run MakeIndex (for nomencl) on a file.
125 # An action to run MakeIndex (for glossary) on a file.
126 MakeGlossaryAction = None
128 # An action to run MakeIndex (for acronyms) on a file.
129 MakeAcronymsAction = None
131 # Used as a return value of modify_env_var if the variable is not set.
132 _null = SCons.Scanner.LaTeX._null
134 modify_env_var = SCons.Scanner.LaTeX.modify_env_var
136 def check_file_error_message(utility, filename='log'):
137 msg = '%s returned an error, check the %s file\n' % (utility, filename)
138 sys.stdout.write(msg)
140 def FindFile(name,suffixes,paths,env,requireExt=False):
142 name,ext = SCons.Util.splitext(name)
143 # if the user gave an extension use it.
147 print " searching for '%s' with extensions: " % name,suffixes
150 testName = os.path.join(path,name)
152 print " look for '%s'" % testName
153 if os.path.exists(testName) and not os.path.isdir(testName):
155 print " found '%s'" % testName
156 return env.fs.File(testName)
158 name_ext = SCons.Util.splitext(testName)[1]
162 # if no suffix try adding those passed in
163 for suffix in suffixes:
164 testNameExt = testName + suffix
166 print " look for '%s'" % testNameExt
168 if os.path.exists(testNameExt):
170 print " found '%s'" % testNameExt
171 return env.fs.File(testNameExt)
173 print " did not find '%s'" % name
176 def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None):
177 """A builder for LaTeX files that checks the output in the aux file
178 and decides how many times to use LaTeXAction, and BibTeXAction."""
180 global must_rerun_latex
182 # This routine is called with two actions. In this file for DVI builds
183 # with LaTeXAction and from the pdflatex.py with PDFLaTeXAction
184 # set this up now for the case where the user requests a different extension
185 # for the target filename
186 if (XXXLaTeXAction == LaTeXAction):
187 callerSuffix = ".dvi"
189 callerSuffix = env['PDFSUFFIX']
191 basename = SCons.Util.splitext(str(source[0]))[0]
192 basedir = os.path.split(str(source[0]))[0]
193 basefile = os.path.split(str(basename))[1]
194 abspath = os.path.abspath(basedir)
196 targetext = os.path.splitext(str(target[0]))[1]
197 targetdir = os.path.split(str(target[0]))[0]
200 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
201 saved_env[var] = modify_env_var(env, var, abspath)
203 # Create base file names with the target directory since the auxiliary files
204 # will be made there. That's because the *COM variables have the cd
205 # command in the prolog. We check
206 # for the existence of files before opening them--even ones like the
207 # aux file that TeX always creates--to make it possible to write tests
208 # with stubs that don't necessarily generate all of the same files.
210 targetbase = os.path.join(targetdir, basefile)
212 # if there is a \makeindex there will be a .idx and thus
213 # we have to run makeindex at least once to keep the build
214 # happy even if there is no index.
215 # Same for glossaries and nomenclature
216 src_content = source[0].get_text_contents()
217 run_makeindex = makeindex_re.search(src_content) and not os.path.exists(targetbase + '.idx')
218 run_nomenclature = makenomenclature_re.search(src_content) and not os.path.exists(targetbase + '.nlo')
219 run_glossary = makeglossary_re.search(src_content) and not os.path.exists(targetbase + '.glo')
220 run_glossaries = makeglossaries_re.search(src_content) and not os.path.exists(targetbase + '.glo')
221 run_acronyms = makeacronyms_re.search(src_content) and not os.path.exists(targetbase + '.acn')
226 for suffix in all_suffixes:
227 theNode = env.fs.File(targetbase + suffix)
228 suffix_nodes[suffix] = theNode
229 saved_hashes[suffix] = theNode.get_csig()
232 print "hashes: ",saved_hashes
234 must_rerun_latex = True
237 # routine to update MD5 hash and compare
239 # TODO(1.5): nested scopes
240 def check_MD5(filenode, suffix, saved_hashes=saved_hashes, targetbase=targetbase):
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()
247 if saved_hashes[suffix] == new_md5:
249 print "file %s not changed" % (targetbase+suffix)
250 return False # unchanged
251 saved_hashes[suffix] = new_md5
252 must_rerun_latex = True
254 print "file %s changed, rerunning Latex, new hash = " % (targetbase+suffix), new_md5
255 return True # changed
257 # generate the file name that latex will generate
258 resultfilename = targetbase + callerSuffix
262 while (must_rerun_latex and count < int(env.subst('$LATEXRETRIES'))) :
263 result = XXXLaTeXAction(target, source, env)
269 must_rerun_latex = False
270 # Decide if various things need to be run, or run again.
272 # Read the log file to find warnings/errors
273 logfilename = targetbase + '.log'
275 if os.path.exists(logfilename):
276 logContent = open(logfilename, "rb").read()
279 # Read the fls file to find all .aux files
280 flsfilename = targetbase + '.fls'
283 if os.path.exists(flsfilename):
284 flsContent = open(flsfilename, "rb").read()
285 auxfiles = openout_aux_re.findall(flsContent)
287 print "auxfiles ",auxfiles
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
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:
301 print "Need to run bibtex"
302 bibfile = env.fs.File(targetbase)
303 result = BibTeXAction(bibfile, bibfile, env)
305 check_file_error_message(env['BIBTEX'], 'blg')
307 must_rerun_latex = check_MD5(suffix_nodes['.bbl'],'.bbl')
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_makeindex):
312 # We must run makeindex
314 print "Need to run makeindex"
315 idxfile = suffix_nodes['.idx']
316 result = MakeIndexAction(idxfile, idxfile, env)
318 check_file_error_message(env['MAKEINDEX'], 'ilg')
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?)
325 for index in check_suffixes:
326 check_MD5(suffix_nodes[index],index)
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_nomenclature):
330 # We must run makeindex
332 print "Need to run makeindex for nomenclature"
333 nclfile = suffix_nodes['.nlo']
334 result = MakeNclAction(nclfile, nclfile, env)
336 check_file_error_message('%s (nomenclature)' % env['MAKENCL'],
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_glossaries) or (count == 1 and run_glossary):
342 # We must run makeindex
344 print "Need to run makeindex for glossary"
345 glofile = suffix_nodes['.glo']
346 result = MakeGlossaryAction(glofile, glofile, env)
348 check_file_error_message('%s (glossary)' % env['MAKEGLOSSARY'],
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_acronyms):
354 # We must run makeindex
356 print "Need to run makeindex for acronyms"
357 acrfile = suffix_nodes['.acn']
358 result = MakeAcronymsAction(acrfile, acrfile, env)
360 check_file_error_message('%s (acronyms)' % env['MAKEACRONYMS'],
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
368 print "rerun Latex due to latex or package rerun warning"
370 if rerun_citations_re.search(logContent):
371 must_rerun_latex = True
373 print "rerun Latex due to 'Rerun to get citations correct' warning"
375 if undefined_references_re.search(logContent):
376 must_rerun_latex = True
378 print "rerun Latex due to undefined references or citations"
380 if (count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex):
381 print "reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES'))
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]))
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
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':
401 if saved_env[var] is _null:
407 env['ENV'][var] = saved_env[var]
411 def LaTeXAuxAction(target = None, source= None, env=None):
412 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env )
415 LaTeX_re = re.compile("\\\\document(style|class)")
417 def is_LaTeX(flist,env,abspath):
418 """Scan a file list to decide if it's TeX- or LaTeX-flavored."""
420 # We need to scan files that are included in case the
421 # \documentclass command is in them.
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):
429 # Split at os.pathsep to convert into absolute path
431 #paths = paths.split(os.pathsep)
432 paths = paths.split(os.pathsep)
434 # now that we have the path list restore the env
435 if savedpath is _null:
437 del env['ENV']['TEXINPUTS']
441 env['ENV']['TEXINPUTS'] = savedpath
443 print "is_LaTeX search path ",paths
444 print "files to search :",flist
446 # Now that we have the search path and file list, check each one
449 print " checking for Latex source ",str(f)
451 content = f.get_text_contents()
452 if LaTeX_re.search(content):
454 print "file %s is a LaTeX file" % str(f)
457 print "file %s is not a LaTeX file" % str(f)
459 # now find included files
461 inc_files.extend( include_re.findall(content) )
463 print "files included by '%s': "%str(f),inc_files
464 # inc_files is list of file names as given. need to find them
465 # using TEXINPUTS paths.
467 # search the included files
468 for src in inc_files:
469 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
470 # make this a list since is_LaTeX takes a list.
471 fileList = [srcNode,]
473 print "FindFile found ",srcNode
474 if srcNode is not None:
475 file_test = is_LaTeX(fileList, env, abspath)
477 # return on first file that finds latex is needed.
482 print " done scanning ",str(f)
486 def TeXLaTeXFunction(target = None, source= None, env=None):
487 """A builder for TeX and LaTeX that scans the source file to
488 decide the "flavor" of the source and then executes the appropriate
491 # find these paths for use in is_LaTeX to search for included files
492 basedir = os.path.split(str(source[0]))[0]
493 abspath = os.path.abspath(basedir)
495 if is_LaTeX(source,env,abspath):
496 result = LaTeXAuxAction(target,source,env)
498 check_file_error_message(env['LATEX'])
500 result = TeXAction(target,source,env)
502 check_file_error_message(env['TEX'])
505 def TeXLaTeXStrFunction(target = None, source= None, env=None):
506 """A strfunction for TeX and LaTeX that scans the source file to
507 decide the "flavor" of the source and then returns the appropriate
509 if env.GetOption("no_exec"):
511 # find these paths for use in is_LaTeX to search for included files
512 basedir = os.path.split(str(source[0]))[0]
513 abspath = os.path.abspath(basedir)
515 if is_LaTeX(source,env,abspath):
516 result = env.subst('$LATEXCOM',0,target,source)+" ..."
518 result = env.subst("$TEXCOM",0,target,source)+" ..."
523 def tex_eps_emitter(target, source, env):
524 """An emitter for TeX and LaTeX sources when
525 executing tex or latex. It will accept .ps and .eps
528 (target, source) = tex_emitter_core(target, source, env, TexGraphics)
530 return (target, source)
532 def tex_pdf_emitter(target, source, env):
533 """An emitter for TeX and LaTeX sources when
534 executing pdftex or pdflatex. It will accept graphics
535 files of types .pdf, .jpg, .png, .gif, and .tif
537 (target, source) = tex_emitter_core(target, source, env, LatexGraphics)
539 return (target, source)
541 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files):
542 """ For theFile (a Node) update any file_tests and search for graphics files
543 then find all included files and call ScanFiles recursively for each of them"""
545 content = theFile.get_text_contents()
547 print " scanning ",str(theFile)
549 for i in range(len(file_tests_search)):
550 if file_tests[i][0] is None:
551 file_tests[i][0] = file_tests_search[i].search(content)
553 incResult = includeOnly_re.search(content)
555 aux_files.append(os.path.join(targetdir, incResult.group(1)))
557 print "\include file names : ", aux_files
558 # recursively call this on each of the included files
560 inc_files.extend( include_re.findall(content) )
562 print "files included by '%s': "%str(theFile),inc_files
563 # inc_files is list of file names as given. need to find them
564 # using TEXINPUTS paths.
566 for src in inc_files:
567 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
568 if srcNode is not None:
569 file_tests = ScanFiles(srcNode, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
571 print " done scanning ",str(theFile)
574 def tex_emitter_core(target, source, env, graphics_extensions):
575 """An emitter for TeX and LaTeX sources.
576 For LaTeX sources we try and find the common created files that
577 are needed on subsequent runs of latex to finish tables of contents,
578 bibliographies, indices, lists of figures, and hyperlink references.
580 basename = SCons.Util.splitext(str(source[0]))[0]
581 basefile = os.path.split(str(basename))[1]
582 targetdir = os.path.split(str(target[0]))[0]
583 targetbase = os.path.join(targetdir, basefile)
585 basedir = os.path.split(str(source[0]))[0]
586 abspath = os.path.abspath(basedir)
587 target[0].attributes.path = abspath
590 # file names we will make use of in searching the sources and log file
592 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.glg', '.alg'] + all_suffixes
593 auxfilename = targetbase + '.aux'
594 logfilename = targetbase + '.log'
595 flsfilename = targetbase + '.fls'
597 env.SideEffect(auxfilename,target[0])
598 env.SideEffect(logfilename,target[0])
599 env.SideEffect(flsfilename,target[0])
601 print "side effect :",auxfilename,logfilename,flsfilename
602 env.Clean(target[0],auxfilename)
603 env.Clean(target[0],logfilename)
604 env.Clean(target[0],flsfilename)
606 content = source[0].get_text_contents()
608 idx_exists = os.path.exists(targetbase + '.idx')
609 nlo_exists = os.path.exists(targetbase + '.nlo')
610 glo_exists = os.path.exists(targetbase + '.glo')
611 acr_exists = os.path.exists(targetbase + '.acn')
613 # set up list with the regular expressions
614 # we use to find features used
615 file_tests_search = [auxfile_re,
627 # set up list with the file suffixes that need emitting
628 # when a feature is found
629 file_tests_suff = [['.aux'],
630 ['.idx', '.ind', '.ilg'],
636 ['.nlo', '.nls', '.nlg'],
637 ['.glo', '.gls', '.glg'],
638 ['.glo', '.gls', '.glg'],
639 ['.acn', '.acr', '.alg'],
640 ['.nav', '.snm', '.out', '.toc'] ]
641 # build the list of lists
643 for i in range(len(file_tests_search)):
644 file_tests.append( [None, file_tests_suff[i]] )
646 # TO-DO: need to add a way for the user to extend this list for whatever
647 # auxiliary files they create in other (or their own) packages
649 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
650 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
651 paths = env['ENV']['TEXINPUTS']
652 if SCons.Util.is_List(paths):
655 # Split at os.pathsep to convert into absolute path
657 #paths = paths.split(os.pathsep)
658 paths = paths.split(os.pathsep)
660 # now that we have the path list restore the env
661 if savedpath is _null:
663 del env['ENV']['TEXINPUTS']
667 env['ENV']['TEXINPUTS'] = savedpath
669 print "search path ",paths
672 file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
674 for (theSearch,suffix_list) in file_tests:
676 for suffix in suffix_list:
677 env.SideEffect(targetbase + suffix,target[0])
679 print "side effect :",targetbase + suffix
680 env.Clean(target[0],targetbase + suffix)
682 for aFile in aux_files:
683 aFile_base = SCons.Util.splitext(aFile)[0]
684 env.SideEffect(aFile_base + '.aux',target[0])
686 print "side effect :",aFile_base + '.aux'
687 env.Clean(target[0],aFile_base + '.aux')
688 # read fls file to get all other files that latex creates and will read on the next pass
689 # remove files from list that we explicitly dealt with above
690 if os.path.exists(flsfilename):
691 content = open(flsfilename, "rb").read()
692 out_files = openout_re.findall(content)
693 myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf']
694 for filename in out_files[:]:
695 if filename in myfiles:
696 out_files.remove(filename)
697 env.SideEffect(out_files,target[0])
699 print "side effect :",out_files
700 env.Clean(target[0],out_files)
702 return (target, source)
705 TeXLaTeXAction = None
708 """Add Builders and construction variables for TeX to an Environment."""
710 global TeXLaTeXAction
711 if TeXLaTeXAction is None:
712 TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction,
713 strfunction=TeXLaTeXStrFunction)
715 env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes)
722 bld = env['BUILDERS']['DVI']
723 bld.add_action('.tex', TeXLaTeXAction)
724 bld.add_emitter('.tex', tex_eps_emitter)
726 def generate_common(env):
727 """Add internal Builders and construction variables for LaTeX to an Environment."""
729 # A generic tex file Action, sufficient for all tex files.
731 if TeXAction is None:
732 TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR")
734 # An Action to build a latex file. This might be needed more
735 # than once if we are dealing with labels and bibtex.
737 if LaTeXAction is None:
738 LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR")
740 # Define an action to run BibTeX on a file.
742 if BibTeXAction is None:
743 BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR")
745 # Define an action to run MakeIndex on a file.
746 global MakeIndexAction
747 if MakeIndexAction is None:
748 MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXCOMSTR")
750 # Define an action to run MakeIndex on a file for nomenclatures.
752 if MakeNclAction is None:
753 MakeNclAction = SCons.Action.Action("$MAKENCLCOM", "$MAKENCLCOMSTR")
755 # Define an action to run MakeIndex on a file for glossaries.
756 global MakeGlossaryAction
757 if MakeGlossaryAction is None:
758 MakeGlossaryAction = SCons.Action.Action("$MAKEGLOSSARYCOM", "$MAKEGLOSSARYCOMSTR")
760 # Define an action to run MakeIndex on a file for acronyms.
761 global MakeAcronymsAction
762 if MakeAcronymsAction is None:
763 MakeAcronymsAction = SCons.Action.Action("$MAKEACRONYMSCOM", "$MAKEACRONYMSCOMSTR")
766 env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
767 env['TEXCOM'] = 'cd ${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}'
769 env['PDFTEX'] = 'pdftex'
770 env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
771 env['PDFTEXCOM'] = 'cd ${TARGET.dir} && $PDFTEX $PDFTEXFLAGS ${SOURCE.file}'
773 env['LATEX'] = 'latex'
774 env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
775 env['LATEXCOM'] = 'cd ${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}'
776 env['LATEXRETRIES'] = 3
778 env['PDFLATEX'] = 'pdflatex'
779 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
780 env['PDFLATEXCOM'] = 'cd ${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURCE.file}'
782 env['BIBTEX'] = 'bibtex'
783 env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
784 env['BIBTEXCOM'] = 'cd ${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE.filebase}'
786 env['MAKEINDEX'] = 'makeindex'
787 env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('')
788 env['MAKEINDEXCOM'] = 'cd ${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}'
790 env['MAKEGLOSSARY'] = 'makeindex'
791 env['MAKEGLOSSARYSTYLE'] = '${SOURCE.filebase}.ist'
792 env['MAKEGLOSSARYFLAGS'] = SCons.Util.CLVar('-s ${MAKEGLOSSARYSTYLE} -t ${SOURCE.filebase}.glg')
793 env['MAKEGLOSSARYCOM'] = 'cd ${TARGET.dir} && $MAKEGLOSSARY ${SOURCE.filebase}.glo $MAKEGLOSSARYFLAGS -o ${SOURCE.filebase}.gls'
795 env['MAKEACRONYMS'] = 'makeindex'
796 env['MAKEACRONYMSSTYLE'] = '${SOURCE.filebase}.ist'
797 env['MAKEACRONYMSFLAGS'] = SCons.Util.CLVar('-s ${MAKEACRONYMSSTYLE} -t ${SOURCE.filebase}.alg')
798 env['MAKEACRONYMSCOM'] = 'cd ${TARGET.dir} && $MAKEACRONYMS ${SOURCE.filebase}.acn $MAKEACRONYMSFLAGS -o ${SOURCE.filebase}.acr'
800 env['MAKENCL'] = 'makeindex'
801 env['MAKENCLSTYLE'] = 'nomencl.ist'
802 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg'
803 env['MAKENCLCOM'] = 'cd ${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls'
806 return env.Detect('tex')
810 # indent-tabs-mode:nil
812 # vim: set expandtab tabstop=4 shiftwidth=4: