From 796442ec43df797f46d48b6137600a9feac93205 Mon Sep 17 00:00:00 2001 From: managan Date: Tue, 7 Oct 2008 18:39:19 +0000 Subject: [PATCH] test/TEX/PDF_single_source.py Test of generating several .pdfs from a list of .ps (new single_source setting) test/TEX/LATEX2.py Based on second half of LATEX. generate all .pdf's at once by giving a list of .tex files test of single_source src/engine/SCons/Scanner/LaTeX.py Add test of changing an included file. Add test of included file having no extension src/engine/SCons/Scanner/LaTeX.py Add lists of acceptable graphics extensions, In the furture make this user configurable?? Scan for files in the paths stored in env['TEXINPUTS'] and env['ENV']['TEXINPUTS'] for people who may just input their environment... Add function findENVPatDirs for this purpose src/engine/SCons/Tool/pdf.py add epstopdf action Have to add it after the pdftex action so it is not the default. Make builder single_source since each input produces one output src/engine/SCons/Tool/pdftex.py use tex_eps_emitter call pdf.generate2 to add epstopdf action after the PDFLaTeXAction src/engine/SCons/Tool/dvipdf.py simplify coding that adds the source directory to the search path TEXPICTS src/engine/SCons/Tool/dvips.py Add single_source option since each ps file comes from one dvi file src/engine/SCons/Tool/pdflatex.py add .tex as a valid extension and switch emitters to tex_pdf_emitter src/engine/SCons/Tool/tex.py fix regular expressions ^[^%]* to ^[^%\n]* for multiline environment add REs for \input or \include and \includegraphics get graphics extensions from Scanner.LaTeX so they are defined in one place move modify_env_var to Scanner.LaTeX since it is used there and easier to import it here add FindFile routine to find a file given name, list of suffixes, paths, env returns a node for the file. add tex_eps_emitter and tex_pdf_emitter that call a core routine with a different list of graphics extensions that can be handled by the tool used (latex vs. pdflatex) revamp feature test/suffix list into two lists and build the list used to create sideeffects for each input file... These tests now get applied to each included file so the whole source tree is tested. Get list of paths from env['ENV']['TEXINPUTS'] and env['TEXINPUTS'] if find we need a .pdf file and only have .eps or .ps set up the .pdf as a target with the .eps as source... change emitter to tex_eps_emitter src/engine/SCons/Tool/latex.py add .tex as a valid extension and switch emitters to tex_eps_emitter git-svn-id: http://scons.tigris.org/svn/scons/trunk@3592 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Scanner/LaTeX.py | 83 ++++++++++- src/engine/SCons/Tool/dvipdf.py | 9 +- src/engine/SCons/Tool/dvips.py | 3 +- src/engine/SCons/Tool/latex.py | 6 +- src/engine/SCons/Tool/pdf.py | 17 ++- src/engine/SCons/Tool/pdflatex.py | 6 +- src/engine/SCons/Tool/pdftex.py | 6 +- src/engine/SCons/Tool/tex.py | 222 ++++++++++++++++++++++-------- test/TEX/LATEX.py | 9 +- test/TEX/LATEX2.py | 125 +++++++++++++++++ test/TEX/PDF_single_source.py | 137 ++++++++++++++++++ 11 files changed, 542 insertions(+), 81 deletions(-) create mode 100644 test/TEX/LATEX2.py create mode 100644 test/TEX/PDF_single_source.py diff --git a/src/engine/SCons/Scanner/LaTeX.py b/src/engine/SCons/Scanner/LaTeX.py index 8b1f4af0..df814972 100644 --- a/src/engine/SCons/Scanner/LaTeX.py +++ b/src/engine/SCons/Scanner/LaTeX.py @@ -34,6 +34,67 @@ import string import re import SCons.Scanner +import SCons.Util + +# list of graphics file extensions for TeX and LaTeX +TexGraphics = ['.eps', '.ps'] +LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] + +# Used as a return value of modify_env_var if the variable is not set. +class _Null: + pass +_null = _Null + +# The user specifies the paths in env[variable], similar to other builders. +# They may be relative and must be converted to absolute, as expected +# by LaTeX and Co. The environment may already have some paths in +# env['ENV'][var]. These paths are honored, but the env[var] paths have +# higher precedence. All changes are un-done on exit. +def modify_env_var(env, var, abspath): + try: + save = env['ENV'][var] + except KeyError: + save = _null + env.PrependENVPath(var, abspath) + try: + if SCons.Util.is_List(env[var]): + #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]]) + env.PrependENVPath(var, map(lambda p: os.path.abspath(str(p)), env[var])) + else: + # Split at os.pathsep to convert into absolute path + #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)]) + env.PrependENVPath(var, map(lambda p: os.path.abspath(p), str(env[var]).split(os.pathsep))) + except KeyError: + pass + + # Convert into a string explicitly to append ":" (without which it won't search system + # paths as well). The problem is that env.AppendENVPath(var, ":") + # does not work, refuses to append ":" (os.pathsep). + + if SCons.Util.is_List(env['ENV'][var]): + env['ENV'][var] = os.pathsep.join(env['ENV'][var]) + # Append the trailing os.pathsep character here to catch the case with no env[var] + env['ENV'][var] = env['ENV'][var] + os.pathsep + + return save + +class FindENVPathDirs: + """A class to bind a specific *PATH variable name to a function that + will return all of the *path directories.""" + def __init__(self, variable): + self.variable = variable + def __call__(self, env, dir=None, target=None, source=None, argument=None): + import SCons.PathList + try: + path = env['ENV'][self.variable] + except KeyError: + return () + + dir = dir or env.fs._cwd + path = SCons.PathList.PathList(path).subst_path(env, target, source) + return tuple(dir.Rfindalldirs(path)) + + def LaTeXScanner(): """Return a prototype Scanner instance for scanning LaTeX source files @@ -42,7 +103,7 @@ def LaTeXScanner(): ds = LaTeX(name = "LaTeXScanner", suffixes = '$LATEXSUFFIXES', # in the search order, see below in LaTeX class docstring - graphics_extensions = ['.eps', '.ps'], + graphics_extensions = TexGraphics, recursive = 0) return ds @@ -53,7 +114,7 @@ def PDFLaTeXScanner(): ds = LaTeX(name = "PDFLaTeXScanner", suffixes = '$LATEXSUFFIXES', # in the search order, see below in LaTeX class docstring - graphics_extensions = ['.pdf', '.png', '.jpg', '.gif', '.tif'], + graphics_extensions = LatexGraphics, recursive = 0) return ds @@ -132,14 +193,17 @@ class LaTeX(SCons.Scanner.Base): def __init__(self, dictionary): self.dictionary = {} for k,n in dictionary.items(): - self.dictionary[k] = SCons.Scanner.FindPathDirs(n) + self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n), + FindENVPathDirs(n) ) def __call__(self, env, dir=None, target=None, source=None, argument=None): di = {} - for k,c in self.dictionary.items(): - di[k] = c(env, dir=None, target=None, source=None, - argument=None) + for k,(c,cENV) in self.dictionary.items(): + di[k] = ( c(env, dir=None, target=None, source=None, + argument=None) , + cENV(env, dir=None, target=None, source=None, + argument=None) ) # To prevent "dict is not hashable error" return tuple(di.items()) @@ -197,7 +261,12 @@ class LaTeX(SCons.Scanner.Base): sub_path = () try_names = self._latex_names(include) for n in try_names: - i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path) + # see if we find it using the path in env[var] + i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0]) + if i: + return i, include + # see if we find it using the path in env['ENV'][var] + i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1]) if i: return i, include return i, include diff --git a/src/engine/SCons/Tool/dvipdf.py b/src/engine/SCons/Tool/dvipdf.py index 642b6ac7..00086baa 100644 --- a/src/engine/SCons/Tool/dvipdf.py +++ b/src/engine/SCons/Tool/dvipdf.py @@ -39,7 +39,7 @@ import SCons.Tool.pdf import SCons.Tool.tex import SCons.Util -_null = SCons.Tool.tex._Null +_null = SCons.Scanner.LaTeX._null def DviPdfPsFunction(XXXDviAction, target = None, source= None, env=None): """A builder for DVI files that sets the TEXPICTS environment @@ -50,18 +50,17 @@ def DviPdfPsFunction(XXXDviAction, target = None, source= None, env=None): except AttributeError : abspath = '' - saved_env = {} - saved_env['TEXPICTS'] = SCons.Tool.tex.modify_env_var(env, 'TEXPICTS', abspath) + saved_env = SCons.Scanner.LaTeX.modify_env_var(env, 'TEXPICTS', abspath) result = XXXDviAction(target, source, env) - if saved_env['TEXPICTS'] is _null: + if saved_env is _null: try: del env['ENV']['TEXPICTS'] except KeyError: pass # was never set else: - env['ENV']['TEXPICTS'] = saved_env['TEXPICTS'] + env['ENV']['TEXPICTS'] = saved_env return result diff --git a/src/engine/SCons/Tool/dvips.py b/src/engine/SCons/Tool/dvips.py index 120a12af..20dcc946 100644 --- a/src/engine/SCons/Tool/dvips.py +++ b/src/engine/SCons/Tool/dvips.py @@ -71,7 +71,8 @@ def generate(env): prefix = '$PSPREFIX', suffix = '$PSSUFFIX', src_suffix = '.dvi', - src_builder = 'DVI') + src_builder = 'DVI', + single_source=True) env['BUILDERS']['PostScript'] = PSBuilder diff --git a/src/engine/SCons/Tool/latex.py b/src/engine/SCons/Tool/latex.py index aaac6a7f..3201e013 100644 --- a/src/engine/SCons/Tool/latex.py +++ b/src/engine/SCons/Tool/latex.py @@ -64,8 +64,10 @@ def generate(env): bld = env['BUILDERS']['DVI'] bld.add_action('.ltx', LaTeXAuxAction) bld.add_action('.latex', LaTeXAuxAction) - bld.add_emitter('.ltx', SCons.Tool.tex.tex_emitter) - bld.add_emitter('.latex', SCons.Tool.tex.tex_emitter) + bld.add_action('.tex', LaTeXAuxAction) + bld.add_emitter('.ltx', SCons.Tool.tex.tex_eps_emitter) + bld.add_emitter('.latex', SCons.Tool.tex.tex_eps_emitter) + bld.add_emitter('.tex', SCons.Tool.tex.tex_eps_emitter) env['LATEX'] = 'latex' env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') diff --git a/src/engine/SCons/Tool/pdf.py b/src/engine/SCons/Tool/pdf.py index 37c4c012..856f3a2c 100644 --- a/src/engine/SCons/Tool/pdf.py +++ b/src/engine/SCons/Tool/pdf.py @@ -1,6 +1,7 @@ """SCons.Tool.pdf Common PDF Builder definition for various other Tool modules that use it. +Add an explicit action to run epstopdf to convert .eps files to .pdf """ @@ -34,6 +35,8 @@ import SCons.Tool PDFBuilder = None +EpsPdfAction = SCons.Action.Action('$EPSTOPDFCOM', '$EPSTOPDFCOMSTR') + def generate(env): try: env['BUILDERS']['PDF'] @@ -45,12 +48,24 @@ def generate(env): prefix = '$PDFPREFIX', suffix = '$PDFSUFFIX', emitter = {}, - source_ext_match = None) + source_ext_match = None, + single_source=True) env['BUILDERS']['PDF'] = PDFBuilder env['PDFPREFIX'] = '' env['PDFSUFFIX'] = '.pdf' +# put the epstopdf builder in this routine so we can add it after +# the pdftex builder so that one is the default for no source suffix +def generate2(env): + bld = env['BUILDERS']['PDF'] + bld.add_action('.ps', EpsPdfAction) + bld.add_action('.eps', EpsPdfAction) + + env['EPSTOPDF'] = 'epstopdf' + env['EPSTOPDFFLAGS'] = SCons.Util.CLVar('') + env['EPSTOPDFCOM'] = '$EPSTOPDF $EPSTOPDFFLAGS ${SOURCE} -o ${TARGET}' + def exists(env): # This only puts a skeleton Builder in place, so if someone # references this Tool directly, it's always "available." diff --git a/src/engine/SCons/Tool/pdflatex.py b/src/engine/SCons/Tool/pdflatex.py index 91868ef4..241ed49f 100644 --- a/src/engine/SCons/Tool/pdflatex.py +++ b/src/engine/SCons/Tool/pdflatex.py @@ -63,8 +63,10 @@ def generate(env): bld = env['BUILDERS']['PDF'] bld.add_action('.ltx', PDFLaTeXAuxAction) bld.add_action('.latex', PDFLaTeXAuxAction) - bld.add_emitter('.ltx', SCons.Tool.tex.tex_emitter) - bld.add_emitter('.latex', SCons.Tool.tex.tex_emitter) + bld.add_action('.tex', PDFLaTeXAuxAction) + bld.add_emitter('.ltx', SCons.Tool.tex.tex_pdf_emitter) + bld.add_emitter('.latex', SCons.Tool.tex.tex_pdf_emitter) + bld.add_emitter('.tex', SCons.Tool.tex.tex_pdf_emitter) env['PDFLATEX'] = 'pdflatex' env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') diff --git a/src/engine/SCons/Tool/pdftex.py b/src/engine/SCons/Tool/pdftex.py index 75c6bc9f..a9d3f589 100644 --- a/src/engine/SCons/Tool/pdftex.py +++ b/src/engine/SCons/Tool/pdftex.py @@ -79,7 +79,11 @@ def generate(env): bld = env['BUILDERS']['PDF'] bld.add_action('.tex', PDFTeXLaTeXAction) - bld.add_emitter('.tex', SCons.Tool.tex.tex_emitter) + bld.add_emitter('.tex', SCons.Tool.tex.tex_pdf_emitter) + + # Add the epstopdf builder after the pdftex builder + # so pdftex is the default for no source suffix + pdf.generate2(env) env['PDFTEX'] = 'pdftex' env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 43df235e..ea640dea 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -42,8 +42,9 @@ import SCons.Action import SCons.Node import SCons.Node.FS import SCons.Util +import SCons.Scanner.LaTeX -Verbose = False +Verbose = True must_rerun_latex = True @@ -78,19 +79,29 @@ undefined_references_re = re.compile(undefined_references_str, re.MULTILINE) # used by the emitter auxfile_re = re.compile(r".", re.MULTILINE) -tableofcontents_re = re.compile(r"^[^%]*\\tableofcontents", re.MULTILINE) -makeindex_re = re.compile(r"^[^%]*\\makeindex", re.MULTILINE) -bibliography_re = re.compile(r"^[^%]*\\bibliography", re.MULTILINE) -listoffigures_re = re.compile(r"^[^%]*\\listoffigures", re.MULTILINE) -listoftables_re = re.compile(r"^[^%]*\\listoftables", re.MULTILINE) -hyperref_re = re.compile(r"^[^%]*\\usepackage.*\{hyperref\}", re.MULTILINE) -makenomenclature_re = re.compile(r"^[^%]*\\makenomenclature", re.MULTILINE) -makeglossary_re = re.compile(r"^[^%]*\\makeglossary", re.MULTILINE) -beamer_re = re.compile(r"^[^%]*\\documentclass\{beamer\}", re.MULTILINE) +tableofcontents_re = re.compile(r"^[^%\n]*\\tableofcontents", re.MULTILINE) +makeindex_re = re.compile(r"^[^%\n]*\\makeindex", re.MULTILINE) +bibliography_re = re.compile(r"^[^%\n]*\\bibliography", re.MULTILINE) +listoffigures_re = re.compile(r"^[^%\n]*\\listoffigures", re.MULTILINE) +listoftables_re = re.compile(r"^[^%\n]*\\listoftables", re.MULTILINE) +hyperref_re = re.compile(r"^[^%\n]*\\usepackage.*\{hyperref\}", re.MULTILINE) +makenomenclature_re = re.compile(r"^[^%\n]*\\makenomenclature", re.MULTILINE) +makeglossary_re = re.compile(r"^[^%\n]*\\makeglossary", re.MULTILINE) +beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE) + +# search to find all files included by Latex +include_re = re.compile(r'^[^%\n]*\\(?:include|input){([^}]*)}', re.MULTILINE) + +# search to find all graphics files included by Latex +includegraphics_re = re.compile(r'^[^%\n]*\\(?:includegraphics(?:\[[^\]]+\])?){([^}]*)}', re.MULTILINE) # search to find all files opened by Latex (recorded in .log file) openout_re = re.compile(r"\\openout.*`(.*)'") +# list of graphics file extensions for TeX and LaTeX +TexGraphics = SCons.Scanner.LaTeX.TexGraphics +LatexGraphics = SCons.Scanner.LaTeX.LatexGraphics + # An Action sufficient to build any generic tex file. TeXAction = None @@ -111,39 +122,41 @@ MakeNclAction = None MakeGlossaryAction = None # Used as a return value of modify_env_var if the variable is not set. -class _Null: - pass -_null = _Null - -# The user specifies the paths in env[variable], similar to other builders. -# They may be relative and must be converted to absolute, as expected -# by LaTeX and Co. The environment may already have some paths in -# env['ENV'][var]. These paths are honored, but the env[var] paths have -# higher precedence. All changes are un-done on exit. -def modify_env_var(env, var, abspath): - try: - save = env['ENV'][var] - except KeyError: - save = _null - env.PrependENVPath(var, abspath) - try: - if SCons.Util.is_List(env[var]): - #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]]) - env.PrependENVPath(var, map(lambda p: os.path.abspath(str(p)), env[var])) +_null = SCons.Scanner.LaTeX._null + +modify_env_var = SCons.Scanner.LaTeX.modify_env_var + +def FindFile(name,suffixes,paths,env): + #print "FindFile: name %s, suffixes "% name,suffixes," paths ",paths + if Verbose: + print " searching for '%s' with extensions: " % name,suffixes + + for path in paths: + testName = os.path.join(path,name) + if Verbose: + print " look for '%s'" % testName + if os.path.exists(testName): + if Verbose: + print " found '%s'" % testName + return env.fs.File(testName) else: - # Split at os.pathsep to convert into absolute path - #TODO(1.5) env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)]) - env.PrependENVPath(var, map(lambda p: os.path.abspath(p), str(env[var]).split(os.pathsep))) - except KeyError: - pass - # Convert into a string explicitly to append ":" (without which it won't search system - # paths as well). The problem is that env.AppendENVPath(var, ":") - # does not work, refuses to append ":" (os.pathsep). - if SCons.Util.is_List(env['ENV'][var]): - env['ENV'][var] = os.pathsep.join(env['ENV'][var]) - # Append the trailing os.pathsep character here to catch the case with no env[var] - env['ENV'][var] = env['ENV'][var] + os.pathsep - return save + name_ext = SCons.Util.splitext(testName)[1] + if name_ext: + continue + + # if no suffix try adding those passed in + for suffix in suffixes: + testNameExt = testName + suffix + if Verbose: + print " look for '%s'" % testNameExt + + if os.path.exists(testNameExt): + if Verbose: + print " found '%s'" % testNameExt + return env.fs.File(testNameExt) + if Verbose: + print " did not find '%s'" % name + return None def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None): """A builder for LaTeX files that checks the output in the aux file @@ -171,7 +184,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None for var in SCons.Scanner.LaTeX.LaTeX.env_variables: saved_env[var] = modify_env_var(env, var, abspath) - # Create a base file names with the target directory since the auxiliary files + # Create base file names with the target directory since the auxiliary files # will be made there. That's because the *COM variables have the cd # command in the prolog. We check # for the existence of files before opening them--even ones like the @@ -386,7 +399,25 @@ def TeXLaTeXStrFunction(target = None, source= None, env=None): result = '' return result -def tex_emitter(target, source, env): +def tex_eps_emitter(target, source, env): + """An emitter for TeX and LaTeX sources when + executing tex or latex. It will accept .ps and .eps + graphics files + """ + (target, source) = tex_emitter_core(target, source, env, TexGraphics) + + return (target, source) + +def tex_pdf_emitter(target, source, env): + """An emitter for TeX and LaTeX sources when + executing pdftex or pdflatex. It will accept graphics + files of types .pdf, .jpg, .png, .gif, and .tif + """ + (target, source) = tex_emitter_core(target, source, env, LatexGraphics) + + return (target, source) + +def tex_emitter_core(target, source, env, graphics_extensions): """An emitter for TeX and LaTeX sources. For LaTeX sources we try and find the common created files that are needed on subsequent runs of latex to finish tables of contents, @@ -395,8 +426,9 @@ def tex_emitter(target, source, env): targetbase = SCons.Util.splitext(str(target[0]))[0] basename = SCons.Util.splitext(str(source[0]))[0] basefile = os.path.split(str(basename))[1] - + basedir = os.path.split(str(source[0]))[0] + targetdir = os.path.split(str(target[0]))[0] abspath = os.path.abspath(basedir) target[0].attributes.path = abspath @@ -413,27 +445,99 @@ def tex_emitter(target, source, env): env.Clean(target[0],logfilename) content = source[0].get_contents() + idx_exists = os.path.exists(targetbase + '.idx') nlo_exists = os.path.exists(targetbase + '.nlo') glo_exists = os.path.exists(targetbase + '.glo') - file_tests = [(auxfile_re.search(content),['.aux']), - (makeindex_re.search(content) or idx_exists,['.idx', '.ind', '.ilg']), - (bibliography_re.search(content),['.bbl', '.blg']), - (tableofcontents_re.search(content),['.toc']), - (listoffigures_re.search(content),['.lof']), - (listoftables_re.search(content),['.lot']), - (hyperref_re.search(content),['.out']), - (makenomenclature_re.search(content) or nlo_exists,['.nlo', '.nls', '.nlg']), - (makeglossary_re.search(content) or glo_exists,['.glo', '.gls', '.glg']), - (beamer_re.search(content),['.nav', '.snm', '.out', '.toc']) ] - # Note we add the various makeindex files if the file produced by latex exists (.idx, .glo, .nlo) - # This covers the case where the \makeindex, \makenomenclature, or \makeglossary - # is not in the main file but we want to clean the files and those made by makeindex + # set up list with the regular expressions + # we use to find features used + file_tests_search = [auxfile_re, + makeindex_re, + bibliography_re, + tableofcontents_re, + listoffigures_re, + listoftables_re, + hyperref_re, + makenomenclature_re, + makeglossary_re, + beamer_re ] + # set up list with the file suffixes that need emitting + # when a feature is found + file_tests_suff = [['.aux'], + ['.idx', '.ind', '.ilg'], + ['.bbl', '.blg'], + ['.toc'], + ['.lof'], + ['.lot'], + ['.out'], + ['.nlo', '.nls', '.nlg'], + ['.glo', '.gls', '.glg'], + ['.nav', '.snm', '.out', '.toc'] ] + # build the list of lists + file_tests = [] + for i in range(len(file_tests_search)): + file_tests.append( [file_tests_search[i].search(content), file_tests_suff[i]] ) # TO-DO: need to add a way for the user to extend this list for whatever # auxiliary files they create in other (or their own) packages + inc_files = [str(source[0]), ] + inc_files.extend( include_re.findall(content) ) + if Verbose: + print "files included by '%s': "%source[0],inc_files + # inc_files is list of file names as given. need to find them + # using TEXINPUTS paths. + + # get path list from both env['TEXINPUTS'] and env['ENV']['TEXINPUTS'] + savedpath = modify_env_var(env, 'TEXINPUTS', abspath) + paths = env['ENV']['TEXINPUTS'] + if SCons.Util.is_List(paths): + pass + else: + # Split at os.pathsep to convert into absolute path + paths = paths.split(os.pathsep) + + # now that we have the path list restore the env + if savedpath is _null: + try: + del env['ENV']['TEXINPUTS'] + except KeyError: + pass # was never set + else: + env['ENV']['TEXINPUTS'] = savedpath + if Verbose: + print "search path ",paths + + # search all files read (including the original source file) + # for files that are \input or \include + for src in inc_files: + # we already did this for the base file + if src != inc_files[0]: + content = "" + srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env) + if srcNode: + content = srcNode.get_contents() + for i in range(len(file_tests_search)): + if file_tests[i][0] == None: + file_tests[i][0] = file_tests_search[i].search(content) + + # For each file see if any graphics files are included + # and set up target to create ,pdf graphic + # is this is in pdflatex toolchain + src_inc_files = includegraphics_re.findall(content) + if Verbose: + print "graphics files in '%s': "%basename,src_inc_files + for graphFile in src_inc_files: + graphicNode = FindFile(graphFile,graphics_extensions,paths,env) + # see if we can build this graphics file by epstopdf + graphicSrc = FindFile(graphFile,TexGraphics,paths,env) + if graphicSrc != None: + if Verbose and (graphicNode == None): + print "need to build '%s' by epstopdf %s -o %s" % (graphFile,graphicSrc,graphFile) + graphicNode = env.PDF(os.path.join(targetdir,str(graphicSrc))) + env.Depends(target[0],graphicNode) + for (theSearch,suffix_list) in file_tests: if theSearch: for suffix in suffix_list: @@ -496,7 +600,7 @@ def generate(env): bld = env['BUILDERS']['DVI'] bld.add_action('.tex', TeXLaTeXAction) - bld.add_emitter('.tex', tex_emitter) + bld.add_emitter('.tex', tex_eps_emitter) env['TEX'] = 'tex' env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode') diff --git a/test/TEX/LATEX.py b/test/TEX/LATEX.py index 34c5d138..d80636f4 100644 --- a/test/TEX/LATEX.py +++ b/test/TEX/LATEX.py @@ -162,7 +162,7 @@ It has an Index and includes another file. latex3 = r""" \index{include} -This is the include file. +This is the include file. mod %s \printindex{} """ @@ -175,8 +175,8 @@ This is the include file. test.subdir('subdir') test.write('latexi.tex', latex1 % 'latexi.tex'); - test.write([ 'subdir', 'latexinputfile.tex'], latex2) - test.write([ 'subdir', 'latexincludefile.tex'], latex3) + test.write([ 'subdir', 'latexinputfile'], latex2) + test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '1') test.run(arguments = 'foo.dvi', stderr = None) test.must_not_exist('wrapper.out') @@ -193,6 +193,9 @@ This is the include file. test.must_exist('latexi.dvi') test.must_exist('latexi.ind') + test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '2') + test.not_up_to_date(arguments = 'latexi.dvi', stderr = None) + test.run(arguments = '-c', stderr = None) test.must_not_exist('latexi.ind') test.must_not_exist('latexi.ilg') diff --git a/test/TEX/LATEX2.py b/test/TEX/LATEX2.py new file mode 100644 index 00000000..8ef73213 --- /dev/null +++ b/test/TEX/LATEX2.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Validate that we can produce several .pdf at once from several sources. +""" + +import os +import os.path +import string +import sys +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + + +latex = test.where_is('latex') + +if latex: + + test.write('SConstruct', """ +import os +ENV = { 'PATH' : os.environ['PATH'], + 'TEXINPUTS' : [ os.environ.get('TEXINPUTS', '') ] } +foo = Environment(ENV = ENV) +foo['TEXINPUTS'] = ['subdir',] +foo.PDF(source = ['foo.ltx','bar.latex','makeindex.tex','latexi.tex']) +""" % locals()) + + latex = r""" +\documentclass{letter} +\begin{document} +This is the %s LaTeX file. +\end{document} +""" + + makeindex = r""" +\documentclass{report} +\usepackage{makeidx} +\makeindex +\begin{document} +\index{info} +This is the %s LaTeX file. +\printindex{} +\end{document} +""" + + latex1 = r""" +\documentclass{report} +\usepackage{makeidx} +\input{latexinputfile} +\begin{document} +\index{info} +This is the %s LaTeX file. + +It has an Index and includes another file. +\include{latexincludefile} +\end{document} +""" + + latex2 = r""" +\makeindex +""" + + latex3 = r""" +\index{include} +This is the include file. mod %s +\printindex{} +""" + + test.write('foo.ltx', latex % 'foo.ltx') + + test.write('bar.latex', latex % 'bar.latex') + + test.write('makeindex.tex', makeindex % 'makeindex.tex') + test.write('makeindex.idx', '') + + test.subdir('subdir') + test.write('latexi.tex', latex1 % 'latexi.tex'); + test.write([ 'subdir', 'latexinputfile'], latex2) + test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '1') + + test.run(stderr = None) + test.must_not_exist('wrapper.out') + test.must_exist('foo.pdf') + + test.must_exist('bar.pdf') + + test.must_exist('latexi.pdf') + test.must_exist('latexi.ind') + + test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '2') + test.not_up_to_date(arguments = 'latexi.pdf', stderr = None) + + test.run(arguments = '-c', stderr = None) + test.must_not_exist('latexi.ind') + test.must_not_exist('latexi.ilg') + + +test.pass_test() diff --git a/test/TEX/PDF_single_source.py b/test/TEX/PDF_single_source.py new file mode 100644 index 00000000..5d466055 --- /dev/null +++ b/test/TEX/PDF_single_source.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test creation of a mulitple pdf's from a list of PostScript files. + +Test courtesy Rob Managan. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +epstopdf = test.where_is('epstopdf') +if not epstopdf: + test.skip_test("Could not find 'epstopdf'; skipping test.\n") + + +test.write(['SConstruct'], """\ +import os + +env = Environment(ENV = { 'PATH' : os.environ['PATH'] }) + +env.PDF(['Fig1.ps','Fig3.ps','Fig2.ps']) +""") + + +figure = """\ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: Fig1.fig +%%Creator: fig2dev Version 3.2 Patchlevel 4 +%%CreationDate: Tue Apr 25 09:56:11 2006 +%%For: managan@mangrove.llnl.gov (Rob Managan) +%%BoundingBox: 0 0 98 98 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def + +end +save +newpath 0 98 moveto 0 0 lineto 98 0 lineto 98 98 lineto closepath clip newpath +-24.9 108.2 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/sc {scale} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/tr {translate} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit + 0.06299 0.06299 sc +% +% Fig objects follow +% +7.500 slw +% Ellipse +n 1170 945 766 766 0 360 DrawEllipse gs col0 s gr + +$F2psEnd +rs +""" +test.write('Fig1.ps',figure ) +test.write('Fig2.ps',figure ) +test.write('Fig3.ps',figure ) + + +test.run(arguments = '.', stderr=None) + + +files = [ + 'Fig1.pdf', + 'Fig2.pdf', + 'Fig3.pdf', +] + +for f in files: + test.must_exist(f) + + +test.pass_test() -- 2.26.2