OLD | NEW |
1 """SCons.Tool.tex | 1 """SCons.Tool.tex |
2 | 2 |
3 Tool-specific initialization for TeX. | 3 Tool-specific initialization for TeX. |
4 | 4 |
5 There normally shouldn't be any need to import this module directly. | 5 There normally shouldn't be any need to import this module directly. |
6 It will usually be imported through the generic SCons.Tool.Tool() | 6 It will usually be imported through the generic SCons.Tool.Tool() |
7 selection method. | 7 selection method. |
8 | 8 |
9 """ | 9 """ |
10 | 10 |
11 # | 11 # |
12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat
ion | 12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F
oundation |
13 # | 13 # |
14 # Permission is hereby granted, free of charge, to any person obtaining | 14 # Permission is hereby granted, free of charge, to any person obtaining |
15 # a copy of this software and associated documentation files (the | 15 # a copy of this software and associated documentation files (the |
16 # "Software"), to deal in the Software without restriction, including | 16 # "Software"), to deal in the Software without restriction, including |
17 # without limitation the rights to use, copy, modify, merge, publish, | 17 # without limitation the rights to use, copy, modify, merge, publish, |
18 # distribute, sublicense, and/or sell copies of the Software, and to | 18 # distribute, sublicense, and/or sell copies of the Software, and to |
19 # permit persons to whom the Software is furnished to do so, subject to | 19 # permit persons to whom the Software is furnished to do so, subject to |
20 # the following conditions: | 20 # the following conditions: |
21 # | 21 # |
22 # The above copyright notice and this permission notice shall be included | 22 # The above copyright notice and this permission notice shall be included |
23 # in all copies or substantial portions of the Software. | 23 # in all copies or substantial portions of the Software. |
24 # | 24 # |
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | 25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | 26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
32 # | 32 # |
33 | 33 |
34 __revision__ = "src/engine/SCons/Tool/tex.py 3842 2008/12/20 22:59:52 scons" | 34 __revision__ = "src/engine/SCons/Tool/tex.py 3897 2009/01/13 06:45:54 scons" |
35 | 35 |
36 import os.path | 36 import os.path |
37 import re | 37 import re |
38 import string | 38 import string |
39 import shutil | 39 import shutil |
40 | 40 |
41 import SCons.Action | 41 import SCons.Action |
42 import SCons.Node | 42 import SCons.Node |
43 import SCons.Node.FS | 43 import SCons.Node.FS |
44 import SCons.Util | 44 import SCons.Util |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 # An action to run MakeIndex (for glossary) on a file. | 121 # An action to run MakeIndex (for glossary) on a file. |
122 MakeGlossaryAction = None | 122 MakeGlossaryAction = None |
123 | 123 |
124 # Used as a return value of modify_env_var if the variable is not set. | 124 # Used as a return value of modify_env_var if the variable is not set. |
125 _null = SCons.Scanner.LaTeX._null | 125 _null = SCons.Scanner.LaTeX._null |
126 | 126 |
127 modify_env_var = SCons.Scanner.LaTeX.modify_env_var | 127 modify_env_var = SCons.Scanner.LaTeX.modify_env_var |
128 | 128 |
129 def FindFile(name,suffixes,paths,env,requireExt=False): | 129 def FindFile(name,suffixes,paths,env,requireExt=False): |
130 if requireExt: | 130 if requireExt: |
131 name = SCons.Util.splitext(name)[0] | 131 name,ext = SCons.Util.splitext(name) |
| 132 # if the user gave an extension use it. |
| 133 if ext: |
| 134 name = name + ext |
132 if Verbose: | 135 if Verbose: |
133 print " searching for '%s' with extensions: " % name,suffixes | 136 print " searching for '%s' with extensions: " % name,suffixes |
134 | 137 |
135 for path in paths: | 138 for path in paths: |
136 testName = os.path.join(path,name) | 139 testName = os.path.join(path,name) |
137 if Verbose: | 140 if Verbose: |
138 print " look for '%s'" % testName | 141 print " look for '%s'" % testName |
139 if os.path.exists(testName): | 142 if os.path.exists(testName): |
140 if Verbose: | 143 if Verbose: |
141 print " found '%s'" % testName | 144 print " found '%s'" % testName |
(...skipping 29 matching lines...) Expand all Loading... |
171 # for the target filename | 174 # for the target filename |
172 if (XXXLaTeXAction == LaTeXAction): | 175 if (XXXLaTeXAction == LaTeXAction): |
173 callerSuffix = ".dvi" | 176 callerSuffix = ".dvi" |
174 else: | 177 else: |
175 callerSuffix = env['PDFSUFFIX'] | 178 callerSuffix = env['PDFSUFFIX'] |
176 | 179 |
177 basename = SCons.Util.splitext(str(source[0]))[0] | 180 basename = SCons.Util.splitext(str(source[0]))[0] |
178 basedir = os.path.split(str(source[0]))[0] | 181 basedir = os.path.split(str(source[0]))[0] |
179 basefile = os.path.split(str(basename))[1] | 182 basefile = os.path.split(str(basename))[1] |
180 abspath = os.path.abspath(basedir) | 183 abspath = os.path.abspath(basedir) |
| 184 |
181 targetext = os.path.splitext(str(target[0]))[1] | 185 targetext = os.path.splitext(str(target[0]))[1] |
182 targetdir = os.path.split(str(target[0]))[0] | 186 targetdir = os.path.split(str(target[0]))[0] |
183 | 187 |
184 saved_env = {} | 188 saved_env = {} |
185 for var in SCons.Scanner.LaTeX.LaTeX.env_variables: | 189 for var in SCons.Scanner.LaTeX.LaTeX.env_variables: |
186 saved_env[var] = modify_env_var(env, var, abspath) | 190 saved_env[var] = modify_env_var(env, var, abspath) |
187 | 191 |
188 # Create base file names with the target directory since the auxiliary files | 192 # Create base file names with the target directory since the auxiliary files |
189 # will be made there. That's because the *COM variables have the cd | 193 # will be made there. That's because the *COM variables have the cd |
190 # command in the prolog. We check | 194 # command in the prolog. We check |
191 # for the existence of files before opening them--even ones like the | 195 # for the existence of files before opening them--even ones like the |
192 # aux file that TeX always creates--to make it possible to write tests | 196 # aux file that TeX always creates--to make it possible to write tests |
193 # with stubs that don't necessarily generate all of the same files. | 197 # with stubs that don't necessarily generate all of the same files. |
194 | 198 |
195 targetbase = os.path.join(targetdir, basefile) | 199 targetbase = os.path.join(targetdir, basefile) |
196 | 200 |
197 # if there is a \makeindex there will be a .idx and thus | 201 # if there is a \makeindex there will be a .idx and thus |
198 # we have to run makeindex at least once to keep the build | 202 # we have to run makeindex at least once to keep the build |
199 # happy even if there is no index. | 203 # happy even if there is no index. |
200 # Same for glossaries and nomenclature | 204 # Same for glossaries and nomenclature |
201 src_content = source[0].get_contents() | 205 src_content = source[0].get_text_contents() |
202 run_makeindex = makeindex_re.search(src_content) and not os.path.exists(targ
etbase + '.idx') | 206 run_makeindex = makeindex_re.search(src_content) and not os.path.exists(targ
etbase + '.idx') |
203 run_nomenclature = makenomenclature_re.search(src_content) and not os.path.e
xists(targetbase + '.nlo') | 207 run_nomenclature = makenomenclature_re.search(src_content) and not os.path.e
xists(targetbase + '.nlo') |
204 run_glossary = makeglossary_re.search(src_content) and not os.path.exists(ta
rgetbase + '.glo') | 208 run_glossary = makeglossary_re.search(src_content) and not os.path.exists(ta
rgetbase + '.glo') |
205 | 209 |
206 saved_hashes = {} | 210 saved_hashes = {} |
207 suffix_nodes = {} | 211 suffix_nodes = {} |
208 | 212 |
209 for suffix in all_suffixes: | 213 for suffix in all_suffixes: |
210 theNode = env.fs.File(targetbase + suffix) | 214 theNode = env.fs.File(targetbase + suffix) |
211 suffix_nodes[suffix] = theNode | 215 suffix_nodes[suffix] = theNode |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 | 370 |
367 def LaTeXAuxAction(target = None, source= None, env=None): | 371 def LaTeXAuxAction(target = None, source= None, env=None): |
368 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env ) | 372 result = InternalLaTeXAuxAction( LaTeXAction, target, source, env ) |
369 return result | 373 return result |
370 | 374 |
371 LaTeX_re = re.compile("\\\\document(style|class)") | 375 LaTeX_re = re.compile("\\\\document(style|class)") |
372 | 376 |
373 def is_LaTeX(flist): | 377 def is_LaTeX(flist): |
374 # Scan a file list to decide if it's TeX- or LaTeX-flavored. | 378 # Scan a file list to decide if it's TeX- or LaTeX-flavored. |
375 for f in flist: | 379 for f in flist: |
376 content = f.get_contents() | 380 content = f.get_text_contents() |
377 if LaTeX_re.search(content): | 381 if LaTeX_re.search(content): |
378 return 1 | 382 return 1 |
379 return 0 | 383 return 0 |
380 | 384 |
381 def TeXLaTeXFunction(target = None, source= None, env=None): | 385 def TeXLaTeXFunction(target = None, source= None, env=None): |
382 """A builder for TeX and LaTeX that scans the source file to | 386 """A builder for TeX and LaTeX that scans the source file to |
383 decide the "flavor" of the source and then executes the appropriate | 387 decide the "flavor" of the source and then executes the appropriate |
384 program.""" | 388 program.""" |
385 if is_LaTeX(source): | 389 if is_LaTeX(source): |
386 result = LaTeXAuxAction(target,source,env) | 390 result = LaTeXAuxAction(target,source,env) |
(...skipping 28 matching lines...) Expand all Loading... |
415 executing pdftex or pdflatex. It will accept graphics | 419 executing pdftex or pdflatex. It will accept graphics |
416 files of types .pdf, .jpg, .png, .gif, and .tif | 420 files of types .pdf, .jpg, .png, .gif, and .tif |
417 """ | 421 """ |
418 (target, source) = tex_emitter_core(target, source, env, LatexGraphics) | 422 (target, source) = tex_emitter_core(target, source, env, LatexGraphics) |
419 | 423 |
420 return (target, source) | 424 return (target, source) |
421 | 425 |
422 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi
cs_extensions, targetdir): | 426 def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi
cs_extensions, targetdir): |
423 # for theFile (a Node) update any file_tests and search for graphics files | 427 # for theFile (a Node) update any file_tests and search for graphics files |
424 # then find all included files and call ScanFiles for each of them | 428 # then find all included files and call ScanFiles for each of them |
425 content = theFile.get_contents() | 429 content = theFile.get_text_contents() |
426 if Verbose: | 430 if Verbose: |
427 print " scanning ",str(theFile) | 431 print " scanning ",str(theFile) |
428 | 432 |
429 for i in range(len(file_tests_search)): | 433 for i in range(len(file_tests_search)): |
430 if file_tests[i][0] == None: | 434 if file_tests[i][0] == None: |
431 file_tests[i][0] = file_tests_search[i].search(content) | 435 file_tests[i][0] = file_tests_search[i].search(content) |
432 | 436 |
433 # For each file see if any graphics files are included | |
434 # and set up target to create ,pdf graphic | |
435 # is this is in pdflatex toolchain | |
436 graphic_files = includegraphics_re.findall(content) | |
437 if Verbose: | |
438 print "graphics files in '%s': "%str(theFile),graphic_files | |
439 for graphFile in graphic_files: | |
440 graphicNode = FindFile(graphFile,graphics_extensions,paths,env,requireEx
t=True) | |
441 # if building with pdflatex see if we need to build the .pdf version of
the graphic file | |
442 # I should probably come up with a better way to tell which builder we a
re using. | |
443 if graphics_extensions == LatexGraphics: | |
444 # see if we can build this graphics file by epstopdf | |
445 graphicSrc = FindFile(graphFile,TexGraphics,paths,env,requireExt=Tru
e) | |
446 # it seems that FindFile checks with no extension added | |
447 # so if the extension is included in the name then both searches fin
d it | |
448 # we don't want to try to build a .pdf from a .pdf so make sure src!
=file wanted | |
449 if (graphicSrc != None) and (graphicSrc != graphicNode): | |
450 if Verbose: | |
451 if graphicNode == None: | |
452 print "need to build '%s' by epstopdf %s -o %s" % (graph
File,graphicSrc,graphFile) | |
453 else: | |
454 print "no need to build '%s', but source file %s exists"
% (graphicNode,graphicSrc) | |
455 graphicNode = env.PDF(graphicSrc) | |
456 env.Depends(target[0],graphicNode) | |
457 | |
458 # recursively call this on each of the included files | 437 # recursively call this on each of the included files |
459 inc_files = [ ] | 438 inc_files = [ ] |
460 inc_files.extend( include_re.findall(content) ) | 439 inc_files.extend( include_re.findall(content) ) |
461 if Verbose: | 440 if Verbose: |
462 print "files included by '%s': "%str(theFile),inc_files | 441 print "files included by '%s': "%str(theFile),inc_files |
463 # inc_files is list of file names as given. need to find them | 442 # inc_files is list of file names as given. need to find them |
464 # using TEXINPUTS paths. | 443 # using TEXINPUTS paths. |
465 | 444 |
466 for src in inc_files: | 445 for src in inc_files: |
467 srcNode = srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requ
ireExt=False) | 446 srcNode = srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requ
ireExt=False) |
(...skipping 23 matching lines...) Expand all Loading... |
491 # | 470 # |
492 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.g
lg'] + all_suffixes | 471 emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.g
lg'] + all_suffixes |
493 auxfilename = targetbase + '.aux' | 472 auxfilename = targetbase + '.aux' |
494 logfilename = targetbase + '.log' | 473 logfilename = targetbase + '.log' |
495 | 474 |
496 env.SideEffect(auxfilename,target[0]) | 475 env.SideEffect(auxfilename,target[0]) |
497 env.SideEffect(logfilename,target[0]) | 476 env.SideEffect(logfilename,target[0]) |
498 env.Clean(target[0],auxfilename) | 477 env.Clean(target[0],auxfilename) |
499 env.Clean(target[0],logfilename) | 478 env.Clean(target[0],logfilename) |
500 | 479 |
501 content = source[0].get_contents() | 480 content = source[0].get_text_contents() |
502 | 481 |
503 idx_exists = os.path.exists(targetbase + '.idx') | 482 idx_exists = os.path.exists(targetbase + '.idx') |
504 nlo_exists = os.path.exists(targetbase + '.nlo') | 483 nlo_exists = os.path.exists(targetbase + '.nlo') |
505 glo_exists = os.path.exists(targetbase + '.glo') | 484 glo_exists = os.path.exists(targetbase + '.glo') |
506 | 485 |
507 # set up list with the regular expressions | 486 # set up list with the regular expressions |
508 # we use to find features used | 487 # we use to find features used |
509 file_tests_search = [auxfile_re, | 488 file_tests_search = [auxfile_re, |
510 makeindex_re, | 489 makeindex_re, |
511 bibliography_re, | 490 bibliography_re, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg' | 631 env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg' |
653 env['MAKENCLCOM'] = 'cd ${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $
MAKENCLFLAGS -o ${SOURCE.filebase}.nls' | 632 env['MAKENCLCOM'] = 'cd ${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $
MAKENCLFLAGS -o ${SOURCE.filebase}.nls' |
654 | 633 |
655 # Duplicate from pdflatex.py. If latex.py goes away, then this is still OK. | 634 # Duplicate from pdflatex.py. If latex.py goes away, then this is still OK. |
656 env['PDFLATEX'] = 'pdflatex' | 635 env['PDFLATEX'] = 'pdflatex' |
657 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') | 636 env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') |
658 env['PDFLATEXCOM'] = 'cd ${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURC
E.file}' | 637 env['PDFLATEXCOM'] = 'cd ${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURC
E.file}' |
659 | 638 |
660 def exists(env): | 639 def exists(env): |
661 return env.Detect('tex') | 640 return env.Detect('tex') |
OLD | NEW |