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) and os.path.isfile(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) and os.path.isfile(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) and os.path.isfile(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) and os.path.isfile(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) and os.path.isfile(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
379 os.path.exists(resultfilename) and
380 os.path.isfile(resultfilename)):
381 if os.path.exists(resultfilename) and os.path.isfile(resultfilename):
382 print "move %s to %s" % (resultfilename, str(target[0]), )
383 shutil.move(resultfilename,str(target[0]))
385 # Original comment (when TEXPICTS was not restored):
386 # The TEXPICTS enviroment variable is needed by a dvi -> pdf step
387 # later on Mac OSX so leave it
389 # It is also used when searching for pictures (implicit dependencies).
390 # Why not set the variable again in the respective builder instead
391 # of leaving local modifications in the environment? What if multiple
392 # latex builds in different directories need different TEXPICTS?
393 for var in SCons.Scanner.LaTeX.LaTeX.env_variables:
394 if var == 'TEXPICTS':
396 if saved_env[var] is _null:
402 env['ENV'][var] = saved_env[var]
406 def LaTeXAuxAction(target = None, source= None, env=None):
407 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env )
410 LaTeX_re = re.compile("\\\\document(style|class)")
412 def is_LaTeX(flist,env,abspath):
413 """Scan a file list to decide if it's TeX- or LaTeX-flavored."""
415 # We need to scan files that are included in case the
416 # \documentclass command is in them.
418 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
419 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
420 paths = env['ENV']['TEXINPUTS']
421 if SCons.Util.is_List(paths):
424 # Split at os.pathsep to convert into absolute path
426 #paths = paths.split(os.pathsep)
427 paths = string.split(paths, os.pathsep)
429 # now that we have the path list restore the env
430 if savedpath is _null:
432 del env['ENV']['TEXINPUTS']
436 env['ENV']['TEXINPUTS'] = savedpath
438 print "is_LaTeX search path ",paths
439 print "files to search :",flist
441 # Now that we have the search path and file list, check each one
444 print " checking for Latex source ",str(f)
446 content = f.get_text_contents()
447 if LaTeX_re.search(content):
449 print "file %s is a LaTeX file" % str(f)
452 print "file %s is not a LaTeX file" % str(f)
454 # now find included files
456 inc_files.extend( include_re.findall(content) )
458 print "files included by '%s': "%str(f),inc_files
459 # inc_files is list of file names as given. need to find them
460 # using TEXINPUTS paths.
462 # search the included files
463 for src in inc_files:
464 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
465 # make this a list since is_LaTeX takes a list.
466 fileList = [srcNode,]
468 print "FindFile found ",srcNode
469 if srcNode is not None:
470 file_test = is_LaTeX(fileList, env, abspath)
472 # return on first file that finds latex is needed.
477 print " done scanning ",str(f)
481 def TeXLaTeXFunction(target = None, source= None, env=None):
482 """A builder for TeX and LaTeX that scans the source file to
483 decide the "flavor" of the source and then executes the appropriate
486 # find these paths for use in is_LaTeX to search for included files
487 basedir = os.path.split(str(source[0]))[0]
488 abspath = os.path.abspath(basedir)
490 if is_LaTeX(source,env,abspath):
491 result = LaTeXAuxAction(target,source,env)
493 print env['LATEX']," returned an error, check the log file"
495 result = TeXAction(target,source,env)
497 print env['TEX']," returned an error, check the log file"
500 def TeXLaTeXStrFunction(target = None, source= None, env=None):
501 """A strfunction for TeX and LaTeX that scans the source file to
502 decide the "flavor" of the source and then returns the appropriate
504 if env.GetOption("no_exec"):
506 # find these paths for use in is_LaTeX to search for included files
507 basedir = os.path.split(str(source[0]))[0]
508 abspath = os.path.abspath(basedir)
510 if is_LaTeX(source,env,abspath):
511 result = env.subst('$LATEXCOM',0,target,source)+" ..."
513 result = env.subst("$TEXCOM",0,target,source)+" ..."
518 def tex_eps_emitter(target, source, env):
519 """An emitter for TeX and LaTeX sources when
520 executing tex or latex. It will accept .ps and .eps
523 (target, source) = tex_emitter_core(target, source, env, TexGraphics)
525 return (target, source)
527 def tex_pdf_emitter(target, source, env):
528 """An emitter for TeX and LaTeX sources when
529 executing pdftex or pdflatex. It will accept graphics
530 files of types .pdf, .jpg, .png, .gif, and .tif
532 (target, source) = tex_emitter_core(target, source, env, LatexGraphics)
534 return (target, source)
536 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files):
537 """ For theFile (a Node) update any file_tests and search for graphics files
538 then find all included files and call ScanFiles recursively for each of them"""
540 content = theFile.get_text_contents()
542 print " scanning ",str(theFile)
544 for i in range(len(file_tests_search)):
545 if file_tests[i][0] is None:
546 file_tests[i][0] = file_tests_search[i].search(content)
548 incResult = includeOnly_re.search(content)
550 aux_files.append(os.path.join(targetdir, incResult.group(1)))
552 print "\include file names : ", aux_files
553 # recursively call this on each of the included files
555 inc_files.extend( include_re.findall(content) )
557 print "files included by '%s': "%str(theFile),inc_files
558 # inc_files is list of file names as given. need to find them
559 # using TEXINPUTS paths.
561 for src in inc_files:
562 srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False)
563 if srcNode is not None:
564 file_tests = ScanFiles(srcNode, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
566 print " done scanning ",str(theFile)
569 def tex_emitter_core(target, source, env, graphics_extensions):
570 """An emitter for TeX and LaTeX sources.
571 For LaTeX sources we try and find the common created files that
572 are needed on subsequent runs of latex to finish tables of contents,
573 bibliographies, indices, lists of figures, and hyperlink references.
575 basename = SCons.Util.splitext(str(source[0]))[0]
576 basefile = os.path.split(str(basename))[1]
577 targetdir = os.path.split(str(target[0]))[0]
578 targetbase = os.path.join(targetdir, basefile)
580 basedir = os.path.split(str(source[0]))[0]
581 abspath = os.path.abspath(basedir)
582 target[0].attributes.path = abspath
585 # file names we will make use of in searching the sources and log file
587 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.glg', '.alg'] + all_suffixes
588 auxfilename = targetbase + '.aux'
589 logfilename = targetbase + '.log'
590 flsfilename = targetbase + '.fls'
592 env.SideEffect(auxfilename,target[0])
593 env.SideEffect(logfilename,target[0])
594 env.SideEffect(flsfilename,target[0])
596 print "side effect :",auxfilename,logfilename,flsfilename
597 env.Clean(target[0],auxfilename)
598 env.Clean(target[0],logfilename)
599 env.Clean(target[0],flsfilename)
601 content = source[0].get_text_contents()
603 # not sure what these were for but they are unused
604 #idx_exists = os.path.exists(targetbase + '.idx') and os.path.isfile(targetbase + '.idx')
605 #nlo_exists = os.path.exists(targetbase + '.nlo') and os.path.isfile(targetbase + '.nlo')
606 #glo_exists = os.path.exists(targetbase + '.glo') and os.path.isfile(targetbase + '.glo')
607 #acr_exists = os.path.exists(targetbase + '.acn') and os.path.isfile(targetbase + '.acn')
609 # set up list with the regular expressions
610 # we use to find features used
611 file_tests_search = [auxfile_re,
623 # set up list with the file suffixes that need emitting
624 # when a feature is found
625 file_tests_suff = [['.aux'],
626 ['.idx', '.ind', '.ilg'],
632 ['.nlo', '.nls', '.nlg'],
633 ['.glo', '.gls', '.glg'],
634 ['.glo', '.gls', '.glg'],
635 ['.acn', '.acr', '.alg'],
636 ['.nav', '.snm', '.out', '.toc'] ]
637 # build the list of lists
639 for i in range(len(file_tests_search)):
640 file_tests.append( [None, file_tests_suff[i]] )
642 # TO-DO: need to add a way for the user to extend this list for whatever
643 # auxiliary files they create in other (or their own) packages
645 # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS']
646 savedpath = modify_env_var(env, 'TEXINPUTS', abspath)
647 paths = env['ENV']['TEXINPUTS']
648 if SCons.Util.is_List(paths):
651 # Split at os.pathsep to convert into absolute path
653 #paths = paths.split(os.pathsep)
654 paths = string.split(paths, os.pathsep)
656 # now that we have the path list restore the env
657 if savedpath is _null:
659 del env['ENV']['TEXINPUTS']
663 env['ENV']['TEXINPUTS'] = savedpath
665 print "search path ",paths
668 file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files)
670 for (theSearch,suffix_list) in file_tests:
672 for suffix in suffix_list:
673 env.SideEffect(targetbase + suffix,target[0])
675 print "side effect :",targetbase + suffix
676 env.Clean(target[0],targetbase + suffix)
678 for aFile in aux_files:
679 aFile_base = SCons.Util.splitext(aFile)[0]
680 env.SideEffect(aFile_base + '.aux',target[0])
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 the next pass
685 # remove files from list that we explicitly dealt with above
686 if os.path.exists(flsfilename) and os.path.isfile(flsfilename):
687 content = open(flsfilename, "rb").read()
688 out_files = openout_re.findall(content)
689 myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf']
690 for filename in out_files[:]:
691 if filename in myfiles:
692 out_files.remove(filename)
693 env.SideEffect(out_files,target[0])
695 print "side effect :",out_files
696 env.Clean(target[0],out_files)
698 return (target, source)
701 TeXLaTeXAction = None
704 """Add Builders and construction variables for TeX to an Environment."""
706 global TeXLaTeXAction
707 if TeXLaTeXAction is None:
708 TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction,
709 strfunction=TeXLaTeXStrFunction)
711 env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes)
718 bld = env['BUILDERS']['DVI']
719 bld.add_action('.tex', TeXLaTeXAction)
720 bld.add_emitter('.tex', tex_eps_emitter)
722 def generate_common(env):
723 """Add internal Builders and construction variables for LaTeX to an Environment."""
725 # A generic tex file Action, sufficient for all tex files.
727 if TeXAction is None:
728 TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR")
730 # An Action to build a latex file. This might be needed more
731 # than once if we are dealing with labels and bibtex.
733 if LaTeXAction is None:
734 LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR")
736 # Define an action to run BibTeX on a file.
738 if BibTeXAction is None:
739 BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR")
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")
746 # Define an action to run MakeIndex on a file for nomenclatures.
748 if MakeNclAction is None:
749 MakeNclAction = SCons.Action.Action("$MAKENCLCOM", "$MAKENCLCOMSTR")
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", "$MAKEGLOSSARYCOMSTR")
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", "$MAKEACRONYMSCOMSTR")
762 env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
763 env['TEXCOM'] = 'cd ${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}'
765 env['PDFTEX'] = 'pdftex'
766 env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
767 env['PDFTEXCOM'] = 'cd ${TARGET.dir} && $PDFTEX $PDFTEXFLAGS ${SOURCE.file}'
769 env['LATEX'] = 'latex'
770 env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
771 env['LATEXCOM'] = 'cd ${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}'
772 env['LATEXRETRIES'] = 3
774 env['PDFLATEX'] = 'pdflatex'
775 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder')
776 env['PDFLATEXCOM'] = 'cd ${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURCE.file}'
778 env['BIBTEX'] = 'bibtex'
779 env['BIBTEXFLAGS'] = SCons.Util.CLVar('')
780 env['BIBTEXCOM'] = 'cd ${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE.filebase}'
782 env['MAKEINDEX'] = 'makeindex'
783 env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('')
784 env['MAKEINDEXCOM'] = 'cd ${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}'
786 env['MAKEGLOSSARY'] = 'makeindex'
787 env['MAKEGLOSSARYSTYLE'] = '${SOURCE.filebase}.ist'
788 env['MAKEGLOSSARYFLAGS'] = SCons.Util.CLVar('-s ${MAKEGLOSSARYSTYLE} -t ${SOURCE.filebase}.glg')
789 env['MAKEGLOSSARYCOM'] = 'cd ${TARGET.dir} && $MAKEGLOSSARY ${SOURCE.filebase}.glo $MAKEGLOSSARYFLAGS -o ${SOURCE.filebase}.gls'
791 env['MAKEACRONYMS'] = 'makeindex'
792 env['MAKEACRONYMSSTYLE'] = '${SOURCE.filebase}.ist'
793 env['MAKEACRONYMSFLAGS'] = SCons.Util.CLVar('-s ${MAKEACRONYMSSTYLE} -t ${SOURCE.filebase}.alg')
794 env['MAKEACRONYMSCOM'] = 'cd ${TARGET.dir} && $MAKEACRONYMS ${SOURCE.filebase}.acn $MAKEACRONYMSFLAGS -o ${SOURCE.filebase}.acr'
796 env['MAKENCL'] = 'makeindex'
797 env['MAKENCLSTYLE'] = 'nomencl.ist'
798 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg'
799 env['MAKENCLCOM'] = 'cd ${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls'
802 return env.Detect('tex')
806 # indent-tabs-mode:nil
808 # vim: set expandtab tabstop=4 shiftwidth=4: