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 FindFile(name,suffixes,paths,env,requireExt=False):
138 name,ext = SCons.Util.splitext(name)
139 # if the user gave an extension use it.
143 print " searching for '%s' with extensions: " % name,suffixes
146 testName = os.path.join(path,name)
148 print " look for '%s'" % testName
149 if os.path.exists(testName):
151 print " found '%s'" % testName
152 return env.fs.File(testName)
154 name_ext = SCons.Util.splitext(testName)[1]
158 # if no suffix try adding those passed in
159 for suffix in suffixes:
160 testNameExt = testName + suffix
162 print " look for '%s'" % testNameExt
164 if os.path.exists(testNameExt):
166 print " found '%s'" % testNameExt
167 return env.fs.File(testNameExt)
169 print " did not find '%s'" % name
172 def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None):
173 """A builder for LaTeX files that checks the output in the aux file
174 and decides how many times to use LaTeXAction, and BibTeXAction."""
176 global must_rerun_latex
178 # This routine is called with two actions. In this file for DVI builds
179 # with LaTeXAction and from the pdflatex.py with PDFLaTeXAction
180 # set this up now for the case where the user requests a different extension
181 # for the target filename
182 if (XXXLaTeXAction == LaTeXAction):
183 callerSuffix = ".dvi"
185 callerSuffix = env['PDFSUFFIX']
187 basename = SCons.Util.splitext(str(source[0]))[0]
188 basedir = os.path.split(str(source[0]))[0]
189 basefile = os.path.split(str(basename))[1]
190 abspath = os.path.abspath(basedir)
192 targetext = os.path.splitext(str(target[0]))[1]
193 targetdir = os.path.split(str(target[0]))[0]
196 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
197 saved_env[var] = modify_env_var(env, var, abspath)
199 # Create base file names with the target directory since the auxiliary files
200 # will be made there. That's because the *COM variables have the cd
201 # command in the prolog. We check
202 # for the existence of files before opening them--even ones like the
203 # aux file that TeX always creates--to make it possible to write tests
204 # with stubs that don't necessarily generate all of the same files.
206 targetbase = os.path.join(targetdir, basefile)
208 # if there is a \makeindex there will be a .idx and thus
209 # we have to run makeindex at least once to keep the build
210 # happy even if there is no index.
211 # Same for glossaries and nomenclature
212 src_content = source[0].get_text_contents()
213 run_makeindex = makeindex_re.search(src_content) and not os.path.exists(targetbase + '.idx')
214 run_nomenclature = makenomenclature_re.search(src_content) and not os.path.exists(targetbase + '.nlo')
215 run_glossary = makeglossary_re.search(src_content) and not os.path.exists(targetbase + '.glo')
216 run_glossaries = makeglossaries_re.search(src_content) and not os.path.exists(targetbase + '.glo')
217 run_acronyms = makeacronyms_re.search(src_content) and not os.path.exists(targetbase + '.acn')
222 for suffix in all_suffixes:
223 theNode = env.fs.File(targetbase + suffix)
224 suffix_nodes[suffix] = theNode
225 saved_hashes[suffix] = theNode.get_csig()
228 print "hashes: ",saved_hashes
230 must_rerun_latex = True
233 # routine to update MD5 hash and compare
235 # TODO(1.5): nested scopes
236 def check_MD5(filenode, suffix, saved_hashes=saved_hashes, targetbase=targetbase):
237 global must_rerun_latex
238 # two calls to clear old csig
239 filenode.clear_memoized_values()
240 filenode.ninfo = filenode.new_ninfo()
241 new_md5 = filenode.get_csig()
243 if saved_hashes[suffix] == new_md5:
245 print "file %s not changed" % (targetbase+suffix)
246 return False # unchanged
247 saved_hashes[suffix] = new_md5
248 must_rerun_latex = True
250 print "file %s changed, rerunning Latex, new hash = " % (targetbase+suffix), new_md5
251 return True # changed
253 # generate the file name that latex will generate
254 resultfilename = targetbase + callerSuffix
258 while (must_rerun_latex and count < int(env.subst('$LATEXRETRIES'))) :
259 result = XXXLaTeXAction(target, source, env)
265 must_rerun_latex = False
266 # Decide if various things need to be run, or run again.
268 # Read the log file to find warnings/errors
269 logfilename = targetbase + '.log'
271 if os.path.exists(logfilename):
272 logContent = open(logfilename, "rb").read()
275 # Read the fls file to find all .aux files
276 flsfilename = targetbase + '.fls'
279 if os.path.exists(flsfilename):
280 flsContent = open(flsfilename, "rb").read()
281 auxfiles = openout_aux_re.findall(flsContent)
283 print "auxfiles ",auxfiles
285 # Now decide if bibtex will need to be run.
286 # The information that bibtex reads from the .aux file is
287 # pass-independent. If we find (below) that the .bbl file is unchanged,
288 # then the last latex saw a correct bibliography.
289 # Therefore only do this on the first pass
291 for auxfilename in auxfiles:
292 target_aux = os.path.join(targetdir, auxfilename)
293 if os.path.exists(target_aux):
294 content = open(target_aux, "rb").read()
295 if string.find(content, "bibdata") != -1:
297 print "Need to run bibtex"
298 bibfile = env.fs.File(targetbase)
299 result = BibTeXAction(bibfile, bibfile, env)
301 print env['BIBTEX']," returned an error, check the blg file"
303 must_rerun_latex = check_MD5(suffix_nodes['.bbl'],'.bbl')
306 # Now decide if latex will need to be run again due to index.
307 if check_MD5(suffix_nodes['.idx'],'.idx') or (count == 1 and run_makeindex):
308 # We must run makeindex
310 print "Need to run makeindex"
311 idxfile = suffix_nodes['.idx']
312 result = MakeIndexAction(idxfile, idxfile, env)
314 print env['MAKEINDEX']," returned an error, check the ilg file"
317 # TO-DO: need to add a way for the user to extend this list for whatever
318 # auxiliary files they create in other (or their own) packages
319 # Harder is case is where an action needs to be called -- that should be rare (I hope?)
321 for index in check_suffixes:
322 check_MD5(suffix_nodes[index],index)
324 # Now decide if latex will need to be run again due to nomenclature.
325 if check_MD5(suffix_nodes['.nlo'],'.nlo') or (count == 1 and run_nomenclature):
326 # We must run makeindex
328 print "Need to run makeindex for nomenclature"
329 nclfile = suffix_nodes['.nlo']
330 result = MakeNclAction(nclfile, nclfile, env)
332 print env['MAKENCL']," (nomenclature) returned an error, check the nlg file"
335 # Now decide if latex will need to be run again due to glossary.
336 if check_MD5(suffix_nodes['.glo'],'.glo') or (count == 1 and run_glossaries) or (count == 1 and run_glossary):
337 # We must run makeindex
339 print "Need to run makeindex for glossary"
340 glofile = suffix_nodes['.glo']
341 result = MakeGlossaryAction(glofile, glofile, env)
343 print env['MAKEGLOSSARY']," (glossary) returned an error, check the glg file"
346 # Now decide if latex will need to be run again due to acronyms.
347 if check_MD5(suffix_nodes['.acn'],'.acn') or (count == 1 and run_acronyms):
348 # We must run makeindex
350 print "Need to run makeindex for acronyms"
351 acrfile = suffix_nodes['.acn']
352 result = MakeAcronymsAction(acrfile, acrfile, env)
354 print env['MAKEACRONYMS']," (acronymns) returned an error, check the alg file"
357 # Now decide if latex needs to be run yet again to resolve warnings.
358 if warning_rerun_re.search(logContent):
359 must_rerun_latex = True
361 print "rerun Latex due to latex or package rerun warning"
363 if rerun_citations_re.search(logContent):
364 must_rerun_latex = True
366 print "rerun Latex due to 'Rerun to get citations correct' warning"
368 if undefined_references_re.search(logContent):
369 must_rerun_latex = True
371 print "rerun Latex due to undefined references or citations"
373 if (count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex):
374 print "reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES'))
377 # rename Latex's output to what the target name is
378 if not (str(target[0]) == resultfilename and os.path.exists(resultfilename)):
379 if os.path.exists(resultfilename):
380 print "move %s to %s" % (resultfilename, str(target[0]), )
381 shutil.move(resultfilename,str(target[0]))
383 # Original comment (when TEXPICTS was not restored):
384 # The TEXPICTS enviroment variable is needed by a dvi -> pdf step
385 # later on Mac OSX so leave it
387 # It is also used when searching for pictures (implicit dependencies).
388 # Why not set the variable again in the respective builder instead
389 # of leaving local modifications in the environment? What if multiple
390 # latex builds in different directories need different TEXPICTS?
391 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
392 if var == 'TEXPICTS':
394 if saved_env[var] is _null:
400 env['ENV'][var] = saved_env[var]
404 def LaTeXAuxAction(target = None, source= None, env=None):
405 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env )
408 LaTeX_re = re.compile("\\\\document(style|class)")
410 def is_LaTeX(flist,env,abspath):
411 """Scan a file list to decide if it's TeX- or LaTeX-flavored."""
413 # We need to scan files that are included in case the
414 # \documentclass command is in them.
416 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
417 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
418 paths = env['ENV']['TEXINPUTS']
419 if SCons.Util.is_List(paths):
422 # Split at os.pathsep to convert into absolute path
424 #paths = paths.split(os.pathsep)
425 paths = string.split(paths, os.pathsep)
427 # now that we have the path list restore the env
428 if savedpath is _null:
430 del env['ENV']['TEXINPUTS']
434 env['ENV']['TEXINPUTS'] = savedpath
436 print "is_LaTeX search path ",paths
437 print "files to search :",flist
439 # Now that we have the search path and file list, check each one
442 print " checking for Latex source ",str(f)
444 content = f.get_text_contents()
445 if LaTeX_re.search(content):
447 print "file %s is a LaTeX file" % str(f)
450 print "file %s is not a LaTeX file" % str(f)
452 # now find included files
454 inc_files.extend( include_re.findall(content) )
456 print "files included by '%s': "%str(f),inc_files
457 # inc_files is list of file names as given. need to find them
458 # using TEXINPUTS paths.
460 # search the included files
461 for src in inc_files:
462 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
463 # make this a list since is_LaTeX takes a list.
464 fileList = [srcNode,]
466 print "FindFile found ",srcNode
467 if srcNode is not None:
468 file_test = is_LaTeX(fileList, env, abspath)
470 # return on first file that finds latex is needed.
475 print " done scanning ",str(f)
479 def TeXLaTeXFunction(target = None, source= None, env=None):
480 """A builder for TeX and LaTeX that scans the source file to
481 decide the "flavor" of the source and then executes the appropriate
484 # find these paths for use in is_LaTeX to search for included files
485 basedir = os.path.split(str(source[0]))[0]
486 abspath = os.path.abspath(basedir)
488 if is_LaTeX(source,env,abspath):
489 result = LaTeXAuxAction(target,source,env)
491 print env['LATEX']," returned an error, check the log file"
493 result = TeXAction(target,source,env)
495 print env['TEX']," returned an error, check the log file"
498 def TeXLaTeXStrFunction(target = None, source= None, env=None):
499 """A strfunction for TeX and LaTeX that scans the source file to
500 decide the "flavor" of the source and then returns the appropriate
502 if env.GetOption("no_exec"):
504 # find these paths for use in is_LaTeX to search for included files
505 basedir = os.path.split(str(source[0]))[0]
506 abspath = os.path.abspath(basedir)
508 if is_LaTeX(source,env,abspath):
509 result = env.subst('$LATEXCOM',0,target,source)+" ..."
511 result = env.subst("$TEXCOM",0,target,source)+" ..."
516 def tex_eps_emitter(target, source, env):
517 """An emitter for TeX and LaTeX sources when
518 executing tex or latex. It will accept .ps and .eps
521 (target, source) = tex_emitter_core(target, source, env, TexGraphics)
523 return (target, source)
525 def tex_pdf_emitter(target, source, env):
526 """An emitter for TeX and LaTeX sources when
527 executing pdftex or pdflatex. It will accept graphics
528 files of types .pdf, .jpg, .png, .gif, and .tif
530 (target, source) = tex_emitter_core(target, source, env, LatexGraphics)
532 return (target, source)
534 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files):
535 """ For theFile (a Node) update any file_tests and search for graphics files
536 then find all included files and call ScanFiles recursively for each of them"""
538 content = theFile.get_text_contents()
540 print " scanning ",str(theFile)
542 for i in range(len(file_tests_search)):
543 if file_tests[i][0] is None:
544 file_tests[i][0] = file_tests_search[i].search(content)
546 incResult = includeOnly_re.search(content)
548 aux_files.append(os.path.join(targetdir, incResult.group(1)))
550 print "\include file names : ", aux_files
551 # recursively call this on each of the included files
553 inc_files.extend( include_re.findall(content) )
555 print "files included by '%s': "%str(theFile),inc_files
556 # inc_files is list of file names as given. need to find them
557 # using TEXINPUTS paths.
559 for src in inc_files:
560 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
561 if srcNode is not None:
562 file_tests = ScanFiles(srcNode, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
564 print " done scanning ",str(theFile)
567 def tex_emitter_core(target, source, env, graphics_extensions):
568 """An emitter for TeX and LaTeX sources.
569 For LaTeX sources we try and find the common created files that
570 are needed on subsequent runs of latex to finish tables of contents,
571 bibliographies, indices, lists of figures, and hyperlink references.
573 basename = SCons.Util.splitext(str(source[0]))[0]
574 basefile = os.path.split(str(basename))[1]
575 targetdir = os.path.split(str(target[0]))[0]
576 targetbase = os.path.join(targetdir, basefile)
578 basedir = os.path.split(str(source[0]))[0]
579 abspath = os.path.abspath(basedir)
580 target[0].attributes.path = abspath
583 # file names we will make use of in searching the sources and log file
585 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.glg', '.alg'] + all_suffixes
586 auxfilename = targetbase + '.aux'
587 logfilename = targetbase + '.log'
588 flsfilename = targetbase + '.fls'
590 env.SideEffect(auxfilename,target[0])
591 env.SideEffect(logfilename,target[0])
592 env.SideEffect(flsfilename,target[0])
594 print "side effect :",auxfilename,logfilename,flsfilename
595 env.Clean(target[0],auxfilename)
596 env.Clean(target[0],logfilename)
597 env.Clean(target[0],flsfilename)
599 content = source[0].get_text_contents()
601 idx_exists = os.path.exists(targetbase + '.idx')
602 nlo_exists = os.path.exists(targetbase + '.nlo')
603 glo_exists = os.path.exists(targetbase + '.glo')
604 acr_exists = os.path.exists(targetbase + '.acn')
606 # set up list with the regular expressions
607 # we use to find features used
608 file_tests_search = [auxfile_re,
620 # set up list with the file suffixes that need emitting
621 # when a feature is found
622 file_tests_suff = [['.aux'],
623 ['.idx', '.ind', '.ilg'],
629 ['.nlo', '.nls', '.nlg'],
630 ['.glo', '.gls', '.glg'],
631 ['.glo', '.gls', '.glg'],
632 ['.acn', '.acr', '.alg'],
633 ['.nav', '.snm', '.out', '.toc'] ]
634 # build the list of lists
636 for i in range(len(file_tests_search)):
637 file_tests.append( [None, file_tests_suff[i]] )
639 # TO-DO: need to add a way for the user to extend this list for whatever
640 # auxiliary files they create in other (or their own) packages
642 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
643 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
644 paths = env['ENV']['TEXINPUTS']
645 if SCons.Util.is_List(paths):
648 # Split at os.pathsep to convert into absolute path
650 #paths = paths.split(os.pathsep)
651 paths = string.split(paths, os.pathsep)
653 # now that we have the path list restore the env
654 if savedpath is _null:
656 del env['ENV']['TEXINPUTS']
660 env['ENV']['TEXINPUTS'] = savedpath
662 print "search path ",paths
665 file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
667 for (theSearch,suffix_list) in file_tests:
669 for suffix in suffix_list:
670 env.SideEffect(targetbase + suffix,target[0])
672 print "side effect :",targetbase + suffix
673 env.Clean(target[0],targetbase + suffix)
675 for aFile in aux_files:
676 aFile_base = SCons.Util.splitext(aFile)[0]
677 env.SideEffect(aFile_base + '.aux',target[0])
679 print "side effect :",aFile_base + '.aux'
680 env.Clean(target[0],aFile_base + '.aux')
681 # read fls file to get all other files that latex creates and will read on the next pass
682 # remove files from list that we explicitly dealt with above
683 if os.path.exists(flsfilename):
684 content = open(flsfilename, "rb").read()
685 out_files = openout_re.findall(content)
686 myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf']
687 for filename in out_files[:]:
688 if filename in myfiles:
689 out_files.remove(filename)
690 env.SideEffect(out_files,target[0])
692 print "side effect :",out_files
693 env.Clean(target[0],out_files)
695 return (target, source)
698 TeXLaTeXAction = None
701 """Add Builders and construction variables for TeX to an Environment."""
703 global TeXLaTeXAction
704 if TeXLaTeXAction is None:
705 TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction,
706 strfunction=TeXLaTeXStrFunction)
708 env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes)
715 bld = env['BUILDERS']['DVI']
716 bld.add_action('.tex', TeXLaTeXAction)
717 bld.add_emitter('.tex', tex_eps_emitter)
719 def generate_common(env):
720 """Add internal Builders and construction variables for LaTeX to an Environment."""
722 # A generic tex file Action, sufficient for all tex files.
724 if TeXAction is None:
725 TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR")
727 # An Action to build a latex file. This might be needed more
728 # than once if we are dealing with labels and bibtex.
730 if LaTeXAction is None:
731 LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR")
733 # Define an action to run BibTeX on a file.
735 if BibTeXAction is None:
736 BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR")
738 # Define an action to run MakeIndex on a file.
739 global MakeIndexAction
740 if MakeIndexAction is None:
741 MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXCOMSTR")
743 # Define an action to run MakeIndex on a file for nomenclatures.
745 if MakeNclAction is None:
746 MakeNclAction = SCons.Action.Action("$MAKENCLCOM", "$MAKENCLCOMSTR")
748 # Define an action to run MakeIndex on a file for glossaries.
749 global MakeGlossaryAction
750 if MakeGlossaryAction is None:
751 MakeGlossaryAction = SCons.Action.Action("$MAKEGLOSSARYCOM", "$MAKEGLOSSARYCOMSTR")
753 # Define an action to run MakeIndex on a file for acronyms.
754 global MakeAcronymsAction
755 if MakeAcronymsAction is None:
756 MakeAcronymsAction = SCons.Action.Action("$MAKEACRONYMSCOM", "$MAKEACRONYMSCOMSTR")
759 env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
760 env['TEXCOM'] = 'cd ${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}'
762 env['PDFTEX'] = 'pdftex'
763 env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
764 env['PDFTEXCOM'] = 'cd ${TARGET.dir} && $PDFTEX $PDFTEXFLAGS ${SOURCE.file}'
766 env['LATEX'] = 'latex'
767 env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
768 env['LATEXCOM'] = 'cd ${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}'
769 env['LATEXRETRIES'] = 3
771 env['PDFLATEX'] = 'pdflatex'
772 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
773 env['PDFLATEXCOM'] = 'cd ${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURCE.file}'
775 env['BIBTEX'] = 'bibtex'
776 env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
777 env['BIBTEXCOM'] = 'cd ${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE.filebase}'
779 env['MAKEINDEX'] = 'makeindex'
780 env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('')
781 env['MAKEINDEXCOM'] = 'cd ${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}'
783 env['MAKEGLOSSARY'] = 'makeindex'
784 env['MAKEGLOSSARYSTYLE'] = '${SOURCE.filebase}.ist'
785 env['MAKEGLOSSARYFLAGS'] = SCons.Util.CLVar('-s ${MAKEGLOSSARYSTYLE} -t ${SOURCE.filebase}.glg')
786 env['MAKEGLOSSARYCOM'] = 'cd ${TARGET.dir} && $MAKEGLOSSARY ${SOURCE.filebase}.glo $MAKEGLOSSARYFLAGS -o ${SOURCE.filebase}.gls'
788 env['MAKEACRONYMS'] = 'makeindex'
789 env['MAKEACRONYMSSTYLE'] = '${SOURCE.filebase}.ist'
790 env['MAKEACRONYMSFLAGS'] = SCons.Util.CLVar('-s ${MAKEACRONYMSSTYLE} -t ${SOURCE.filebase}.alg')
791 env['MAKEACRONYMSCOM'] = 'cd ${TARGET.dir} && $MAKEACRONYMS ${SOURCE.filebase}.acn $MAKEACRONYMSFLAGS -o ${SOURCE.filebase}.acr'
793 env['MAKENCL'] = 'makeindex'
794 env['MAKENCLSTYLE'] = 'nomencl.ist'
795 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg'
796 env['MAKENCLCOM'] = 'cd ${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls'
799 return env.Detect('tex')
803 # indent-tabs-mode:nil
805 # vim: set expandtab tabstop=4 shiftwidth=4: