From 53151b34370e905a16c79e82cb652cf233f99f3b Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 20 Mar 2022 01:28:07 +0100 Subject: [PATCH] Removed latex specific things from scons. --- SCSCons/Defaults.py | 1 - SCSCons/Scanner/LaTeX.py | 431 ----------------- SCSCons/Tool/__init__.py | 16 - SCSCons/Tool/dvi.py | 64 --- SCSCons/Tool/dvipdf.py | 122 ----- SCSCons/Tool/dvips.py | 95 ---- SCSCons/Tool/gs.py | 91 ---- SCSCons/Tool/latex.py | 80 ---- SCSCons/Tool/pdf.py | 78 --- SCSCons/Tool/pdflatex.py | 84 ---- SCSCons/Tool/pdftex.py | 109 ----- SCSCons/Tool/tex.py | 993 --------------------------------------- 12 files changed, 2164 deletions(-) delete mode 100644 SCSCons/Scanner/LaTeX.py delete mode 100644 SCSCons/Tool/dvi.py delete mode 100644 SCSCons/Tool/dvipdf.py delete mode 100644 SCSCons/Tool/dvips.py delete mode 100644 SCSCons/Tool/gs.py delete mode 100644 SCSCons/Tool/latex.py delete mode 100644 SCSCons/Tool/pdf.py delete mode 100644 SCSCons/Tool/pdflatex.py delete mode 100644 SCSCons/Tool/pdftex.py delete mode 100644 SCSCons/Tool/tex.py diff --git a/SCSCons/Defaults.py b/SCSCons/Defaults.py index 8a4b9d6e3..a082264fb 100644 --- a/SCSCons/Defaults.py +++ b/SCSCons/Defaults.py @@ -123,7 +123,6 @@ SharedCheck = SCons.Action.Action(SharedFlagChecker, None) # SConscript files until we've given them some fair warning and a # transition period. CScan = SCons.Tool.CScanner -LaTeXScan = SCons.Tool.LaTeXScanner ObjSourceScan = SCons.Tool.SourceFileScanner ProgScan = SCons.Tool.ProgramScanner diff --git a/SCSCons/Scanner/LaTeX.py b/SCSCons/Scanner/LaTeX.py deleted file mode 100644 index 700b7cbe7..000000000 --- a/SCSCons/Scanner/LaTeX.py +++ /dev/null @@ -1,431 +0,0 @@ -# MIT License -# -# Copyright The SCons Foundation -# -# 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. - -"""Dependency scanner for LaTeX code.""" - -import os.path -import re - -import SCons.Node.FS -import SCons.Util -import SCons.Warnings -from . import ScannerBase, FindPathDirs - -# list of graphics file extensions for TeX and LaTeX -TexGraphics = ['.eps', '.ps'] -#LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] -LatexGraphics = [ '.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]): - env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]]) - else: - # Split at os.pathsep to convert into absolute path - env.PrependENVPath(var, [os.path.abspath(p) for p in 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 E{*}PATH variable name to a function that - will return all of the E{*}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 - when built with latex. - """ - ds = LaTeX(name = "LaTeXScanner", - suffixes = '$LATEXSUFFIXES', - # in the search order, see below in LaTeX class docstring - graphics_extensions = TexGraphics, - recursive = 0) - return ds - - -def PDFLaTeXScanner(): - """ - Return a prototype Scanner instance for scanning LaTeX source files - when built with pdflatex. - """ - ds = LaTeX(name = "PDFLaTeXScanner", - suffixes = '$LATEXSUFFIXES', - # in the search order, see below in LaTeX class docstring - graphics_extensions = LatexGraphics, - recursive = 0) - return ds - - -class LaTeX(ScannerBase): - """Class for scanning LaTeX files for included files. - - Unlike most scanners, which use regular expressions that just - return the included file name, this returns a tuple consisting - of the keyword for the inclusion ("include", "includegraphics", - "input", or "bibliography"), and then the file name itself. - Based on a quick look at LaTeX documentation, it seems that we - should append .tex suffix for the "include" keywords, append .tex if - there is no extension for the "input" keyword, and need to add .bib - for the "bibliography" keyword that does not accept extensions by itself. - - Finally, if there is no extension for an "includegraphics" keyword - latex will append .ps or .eps to find the file, while pdftex may use .pdf, - .jpg, .tif, .mps, or .png. - - The actual subset and search order may be altered by - DeclareGraphicsExtensions command. This complication is ignored. - The default order corresponds to experimentation with teTeX:: - - $ latex --version - pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4) - kpathsea version 3.5.4 - - The order is: - ['.eps', '.ps'] for latex - ['.png', '.pdf', '.jpg', '.tif']. - - Another difference is that the search path is determined by the type - of the file being searched: - env['TEXINPUTS'] for "input" and "include" keywords - env['TEXINPUTS'] for "includegraphics" keyword - env['TEXINPUTS'] for "lstinputlisting" keyword - env['BIBINPUTS'] for "bibliography" keyword - env['BSTINPUTS'] for "bibliographystyle" keyword - env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed just allows user to set it if needed. - - FIXME: also look for the class or style in document[class|style]{} - FIXME: also look for the argument of bibliographystyle{} - """ - keyword_paths = {'include': 'TEXINPUTS', - 'input': 'TEXINPUTS', - 'includegraphics': 'TEXINPUTS', - 'bibliography': 'BIBINPUTS', - 'bibliographystyle': 'BSTINPUTS', - 'addbibresource': 'BIBINPUTS', - 'addglobalbib': 'BIBINPUTS', - 'addsectionbib': 'BIBINPUTS', - 'makeindex': 'INDEXSTYLE', - 'usepackage': 'TEXINPUTS', - 'lstinputlisting': 'TEXINPUTS'} - env_variables = SCons.Util.unique(list(keyword_paths.values())) - two_arg_commands = ['import', 'subimport', - 'includefrom', 'subincludefrom', - 'inputfrom', 'subinputfrom'] - - def __init__(self, name, suffixes, graphics_extensions, *args, **kwargs): - regex = r''' - \\( - include - | includegraphics(?:\s*\[[^\]]+\])? - | lstinputlisting(?:\[[^\]]+\])? - | input - | import - | subimport - | includefrom - | subincludefrom - | inputfrom - | subinputfrom - | bibliography - | addbibresource - | addglobalbib - | addsectionbib - | usepackage - ) - \s*{([^}]*)} # first arg - (?: \s*{([^}]*)} )? # maybe another arg - ''' - self.cre = re.compile(regex, re.M | re.X) - self.comment_re = re.compile(r'^((?:(?:\\%)|[^%\n])*)(.*)$', re.M) - - self.graphics_extensions = graphics_extensions - - def _scan(node, env, path=(), self=self): - node = node.rfile() - if not node.exists(): - return [] - return self.scan_recurse(node, path) - - class FindMultiPathDirs: - """The stock FindPathDirs function has the wrong granularity: - it is called once per target, while we need the path that depends - on what kind of included files is being searched. This wrapper - hides multiple instances of FindPathDirs, one per the LaTeX path - variable in the environment. When invoked, the function calculates - and returns all the required paths as a dictionary (converted into - a tuple to become hashable). Then the scan function converts it - back and uses a dictionary of tuples rather than a single tuple - of paths. - """ - def __init__(self, dictionary): - self.dictionary = {} - for k,n in dictionary.items(): - self.dictionary[k] = (FindPathDirs(n), FindENVPathDirs(n)) - - def __call__(self, env, dir=None, target=None, source=None, - argument=None): - di = {} - 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()) - - class LaTeXScanCheck: - """Skip all but LaTeX source files. - - Do not scan *.eps, *.pdf, *.jpg, etc. - """ - - def __init__(self, suffixes): - self.suffixes = suffixes - - def __call__(self, node, env): - current = not node.has_builder() or node.is_up_to_date() - scannable = node.get_suffix() in env.subst_list(self.suffixes)[0] - # Returning false means that the file is not scanned. - return scannable and current - - kwargs['function'] = _scan - kwargs['path_function'] = FindMultiPathDirs(LaTeX.keyword_paths) - kwargs['recursive'] = 0 - kwargs['skeys'] = suffixes - kwargs['scan_check'] = LaTeXScanCheck(suffixes) - kwargs['name'] = name - - super().__init__(*args, **kwargs) - - def _latex_names(self, include_type, filename): - if include_type == 'input': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.tex'] - if include_type in ('include', 'import', 'subimport', - 'includefrom', 'subincludefrom', - 'inputfrom', 'subinputfrom'): - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.tex'] - if include_type == 'bibliography': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.bib'] - if include_type == 'usepackage': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.sty'] - if include_type == 'includegraphics': - base, ext = os.path.splitext( filename ) - if ext == "": - #return [filename+e for e in self.graphics_extensions + TexGraphics] - # use the line above to find dependencies for the PDF builder - # when only an .eps figure is present. Since it will be found - # if the user tells scons how to make the pdf figure, leave - # it out for now. - return [filename+e for e in self.graphics_extensions] - return [filename] - - def sort_key(self, include): - return SCons.Node.FS._my_normcase(str(include)) - - def find_include(self, include, source_dir, path): - inc_type, inc_subdir, inc_filename = include - try: - sub_paths = path[inc_type] - except (IndexError, KeyError): - sub_paths = ((), ()) - try_names = self._latex_names(inc_type, inc_filename) - - # There are three search paths to try: - # 1. current directory "source_dir" - # 2. env[var] - # 3. env['ENV'][var] - search_paths = [(source_dir,)] + list(sub_paths) - - for n in try_names: - for search_path in search_paths: - paths = tuple([d.Dir(inc_subdir) for d in search_path]) - i = SCons.Node.FS.find_file(n, paths) - if i: - return i, include - return None, include - - def canonical_text(self, text): - """Standardize an input TeX-file contents. - - Currently: - * removes comments, unwrapping comment-wrapped lines. - """ - out = [] - line_continues_a_comment = False - for line in text.splitlines(): - line,comment = self.comment_re.findall(line)[0] - if line_continues_a_comment: - out[-1] = out[-1] + line.lstrip() - else: - out.append(line) - line_continues_a_comment = len(comment) > 0 - return '\n'.join(out).rstrip()+'\n' - - def scan(self, node, subdir='.'): - # Modify the default scan function to allow for the regular - # expression to return a comma separated list of file names - # as can be the case with the bibliography keyword. - - # Cache the includes list in node so we only scan it once: - # path_dict = dict(list(path)) - # add option for whitespace (\s) before the '[' - noopt_cre = re.compile(r'\s*\[.*$') - if node.includes is not None: - includes = node.includes - else: - text = self.canonical_text(node.get_text_contents()) - includes = self.cre.findall(text) - # 1. Split comma-separated lines, e.g. - # ('bibliography', 'phys,comp') - # should become two entries - # ('bibliography', 'phys') - # ('bibliography', 'comp') - # 2. Remove the options, e.g., such as - # ('includegraphics[clip,width=0.7\\linewidth]', 'picture.eps') - # should become - # ('includegraphics', 'picture.eps') - split_includes = [] - for include in includes: - inc_type = noopt_cre.sub('', include[0]) - inc_subdir = subdir - if inc_type in self.two_arg_commands: - inc_subdir = os.path.join(subdir, include[1]) - inc_list = include[2].split(',') - else: - inc_list = include[1].split(',') - for inc in inc_list: - split_includes.append((inc_type, inc_subdir, inc)) - - includes = split_includes - node.includes = includes - - return includes - - def scan_recurse(self, node, path=()): - """ do a recursive scan of the top level target file - This lets us search for included files based on the - directory of the main file just as latex does""" - - path_dict = dict(list(path)) - - queue = [] - queue.extend( self.scan(node) ) - seen = {} - - # This is a hand-coded DSU (decorate-sort-undecorate, or - # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the \include, \input, etc. line. - # TODO: what about the comment in the original Classic scanner: - # """which lets - # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally.""" - nodes = [] - source_dir = node.get_dir() - #for include in includes: - while queue: - - include = queue.pop() - inc_type, inc_subdir, inc_filename = include - - try: - if seen[inc_filename]: - continue - except KeyError: - seen[inc_filename] = True - - # - # Handle multiple filenames in include[1] - # - n, i = self.find_include(include, source_dir, path_dict) - if n is None: - # Do not bother with 'usepackage' warnings, as they most - # likely refer to system-level files - if inc_type != 'usepackage': - SCons.Warnings.warn( - SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s " - "(included from: %s) -- file not found" % (i, node), - ) - else: - sortkey = self.sort_key(n) - nodes.append((sortkey, n)) - # recurse down - queue.extend(self.scan(n, inc_subdir)) - - return [pair[1] for pair in sorted(nodes)] - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/__init__.py b/SCSCons/Tool/__init__.py index 725f6eb57..b783912c0 100644 --- a/SCSCons/Tool/__init__.py +++ b/SCSCons/Tool/__init__.py @@ -47,7 +47,6 @@ import SCons.Errors import SCons.Node.FS import SCons.Scanner import SCons.Scanner.C -import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG from SCons.Tool.linkCommon import LibSymlinksActionFunction, LibSymlinksStrFun @@ -55,8 +54,6 @@ from SCons.Tool.linkCommon import LibSymlinksActionFunction, LibSymlinksStrFun DefaultToolpath = [] CScanner = SCons.Scanner.C.CScanner() -LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner() -PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner() ProgramScanner = SCons.Scanner.Prog.ProgramScanner() SourceFileScanner = SCons.Scanner.ScannerBase({}, name='SourceFileScanner') SWIGScanner = SCons.Scanner.SWIG.SWIGScanner() @@ -69,8 +66,6 @@ CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", IDLSuffixes = [".idl", ".IDL"] -LaTeXSuffixes = [".tex", ".ltx", ".latex"] - SWIGSuffixes = ['.i'] for suffix in CSuffixes: @@ -79,14 +74,6 @@ for suffix in CSuffixes: for suffix in SWIGSuffixes: SourceFileScanner.add_scanner(suffix, SWIGScanner) -# FIXME: what should be done here? Two scanners scan the same extensions, -# but look for different files, e.g., "picture.eps" vs. "picture.pdf". -# The builders for DVI and PDF explicitly reference their scanners -# I think that means this is not needed??? -for suffix in LaTeXSuffixes: - SourceFileScanner.add_scanner(suffix, LaTeXScanner) - SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) - # Tool aliases are needed for those tools whose module names also # occur in the python standard library (This causes module shadowing and # can break using python library functions under python3) or if the current tool/file names @@ -789,9 +776,6 @@ def tool_list(platform, env): 'rpcgen', 'swig', # Java 'jar', 'javac', 'javah', 'rmic', - # TeX - 'dvipdf', 'dvips', 'gs', - 'tex', 'latex', 'pdflatex', 'pdftex', # Archivers 'tar', 'zip', # File builders (text) diff --git a/SCSCons/Tool/dvi.py b/SCSCons/Tool/dvi.py deleted file mode 100644 index 4067b2a1e..000000000 --- a/SCSCons/Tool/dvi.py +++ /dev/null @@ -1,64 +0,0 @@ -"""SCons.Tool.dvi - -Common DVI Builder definition for various other Tool modules that use it. - -""" - -# -# __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__" - -import SCons.Builder -import SCons.Tool - -DVIBuilder = None - -def generate(env): - try: - env['BUILDERS']['DVI'] - except KeyError: - global DVIBuilder - - if DVIBuilder is None: - # The suffix is hard-coded to '.dvi', not configurable via a - # construction variable like $DVISUFFIX, because the output - # file name is hard-coded within TeX. - DVIBuilder = SCons.Builder.Builder(action = {}, - source_scanner = SCons.Tool.LaTeXScanner, - suffix = '.dvi', - emitter = {}, - source_ext_match = None) - - env['BUILDERS']['DVI'] = DVIBuilder - -def exists(env): - # This only puts a skeleton Builder in place, so if someone - # references this Tool directly, it's always "available." - return 1 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/dvipdf.py b/SCSCons/Tool/dvipdf.py deleted file mode 100644 index e0622072d..000000000 --- a/SCSCons/Tool/dvipdf.py +++ /dev/null @@ -1,122 +0,0 @@ -"""SCons.Tool.dvipdf - -Tool-specific initialization for dvipdf. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import SCons.Action -import SCons.Defaults -import SCons.Tool.pdf -import SCons.Tool.tex -import SCons.Util - -_null = SCons.Scanner.LaTeX._null - -def DviPdfPsFunction(XXXDviAction, target = None, source= None, env=None): - """A builder for DVI files that sets the TEXPICTS environment - variable before running dvi2ps or dvipdf.""" - - try: - abspath = source[0].attributes.path - except AttributeError : - abspath = '' - - saved_env = SCons.Scanner.LaTeX.modify_env_var(env, 'TEXPICTS', abspath) - - result = XXXDviAction(target, source, env) - - if saved_env is _null: - try: - del env['ENV']['TEXPICTS'] - except KeyError: - pass # was never set - else: - env['ENV']['TEXPICTS'] = saved_env - - return result - -def DviPdfFunction(target = None, source= None, env=None): - result = DviPdfPsFunction(PDFAction,target,source,env) - return result - -def DviPdfStrFunction(target = None, source= None, env=None): - """A strfunction for dvipdf that returns the appropriate - command string for the no_exec options.""" - if env.GetOption("no_exec"): - result = env.subst('$DVIPDFCOM',0,target,source) - else: - result = '' - return result - -PDFAction = None -DVIPDFAction = None - -def PDFEmitter(target, source, env): - """Strips any .aux or .log files from the input source list. - These are created by the TeX Builder that in all likelihood was - used to generate the .dvi file we're using as input, and we only - care about the .dvi file. - """ - def strip_suffixes(n): - return not SCons.Util.splitext(str(n))[1] in ['.aux', '.log'] - source = [src for src in source if strip_suffixes(src)] - return (target, source) - -def generate(env): - """Add Builders and construction variables for dvipdf to an Environment.""" - global PDFAction - if PDFAction is None: - PDFAction = SCons.Action.Action('$DVIPDFCOM', '$DVIPDFCOMSTR') - - global DVIPDFAction - if DVIPDFAction is None: - DVIPDFAction = SCons.Action.Action(DviPdfFunction, strfunction = DviPdfStrFunction) - - from . import pdf - pdf.generate(env) - - bld = env['BUILDERS']['PDF'] - bld.add_action('.dvi', DVIPDFAction) - bld.add_emitter('.dvi', PDFEmitter) - - env['DVIPDF'] = 'dvipdf' - env['DVIPDFFLAGS'] = SCons.Util.CLVar('') - env['DVIPDFCOM'] = 'cd ${TARGET.dir} && $DVIPDF $DVIPDFFLAGS ${SOURCE.file} ${TARGET.file}' - -def exists(env): - SCons.Tool.tex.generate_darwin(env) - return env.Detect('dvipdf') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/dvips.py b/SCSCons/Tool/dvips.py deleted file mode 100644 index 198bda038..000000000 --- a/SCSCons/Tool/dvips.py +++ /dev/null @@ -1,95 +0,0 @@ -"""SCons.Tool.dvips - -Tool-specific initialization for dvips. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import SCons.Action -import SCons.Builder -import SCons.Tool.dvipdf -import SCons.Util - -def DviPsFunction(target = None, source= None, env=None): - result = SCons.Tool.dvipdf.DviPdfPsFunction(PSAction,target,source,env) - return result - -def DviPsStrFunction(target = None, source= None, env=None): - """A strfunction for dvipdf that returns the appropriate - command string for the no_exec options.""" - if env.GetOption("no_exec"): - result = env.subst('$PSCOM',0,target,source) - else: - result = '' - return result - -PSAction = None -DVIPSAction = None -PSBuilder = None - -def generate(env): - """Add Builders and construction variables for dvips to an Environment.""" - global PSAction - if PSAction is None: - PSAction = SCons.Action.Action('$PSCOM', '$PSCOMSTR') - - global DVIPSAction - if DVIPSAction is None: - DVIPSAction = SCons.Action.Action(DviPsFunction, strfunction = DviPsStrFunction) - - global PSBuilder - if PSBuilder is None: - PSBuilder = SCons.Builder.Builder(action = PSAction, - prefix = '$PSPREFIX', - suffix = '$PSSUFFIX', - src_suffix = '.dvi', - src_builder = 'DVI', - single_source=True) - - env['BUILDERS']['PostScript'] = PSBuilder - - env['DVIPS'] = 'dvips' - env['DVIPSFLAGS'] = SCons.Util.CLVar('') - # I'm not quite sure I got the directories and filenames right for variant_dir - # We need to be in the correct directory for the sake of latex \includegraphics eps included files. - env['PSCOM'] = 'cd ${TARGET.dir} && $DVIPS $DVIPSFLAGS -o ${TARGET.file} ${SOURCE.file}' - env['PSPREFIX'] = '' - env['PSSUFFIX'] = '.ps' - -def exists(env): - SCons.Tool.tex.generate_darwin(env) - return env.Detect('dvips') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/gs.py b/SCSCons/Tool/gs.py deleted file mode 100644 index 25359a858..000000000 --- a/SCSCons/Tool/gs.py +++ /dev/null @@ -1,91 +0,0 @@ -"""SCons.Tool.gs - -Tool-specific initialization for Ghostscript. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import SCons.Action -import SCons.Builder -import SCons.Platform -import SCons.Util - -# Ghostscript goes by different names on different platforms... -platform = SCons.Platform.platform_default() - -if platform == 'os2': - gs = 'gsos2' -elif platform == 'win32': - gs = 'gswin32c' -else: - gs = 'gs' - -GhostscriptAction = None - -def generate(env): - """Add Builders and construction variables for Ghostscript to an - Environment.""" - global GhostscriptAction - # The following try-except block enables us to use the Tool - # in standalone mode (without the accompanying pdf.py), - # whenever we need an explicit call of gs via the Gs() - # Builder ... - try: - if GhostscriptAction is None: - GhostscriptAction = SCons.Action.Action('$GSCOM', '$GSCOMSTR') - - from SCons.Tool import pdf - pdf.generate(env) - - bld = env['BUILDERS']['PDF'] - bld.add_action('.ps', GhostscriptAction) - except ImportError as e: - pass - - gsbuilder = SCons.Builder.Builder(action = SCons.Action.Action('$GSCOM', '$GSCOMSTR')) - env['BUILDERS']['Gs'] = gsbuilder - - env['GS'] = gs - env['GSFLAGS'] = SCons.Util.CLVar('-dNOPAUSE -dBATCH -sDEVICE=pdfwrite') - env['GSCOM'] = '$GS $GSFLAGS -sOutputFile=$TARGET $SOURCES' - - -def exists(env): - if 'PS2PDF' in env: - return env.Detect(env['PS2PDF']) - else: - return env.Detect(gs) or SCons.Util.WhereIs(gs) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/latex.py b/SCSCons/Tool/latex.py deleted file mode 100644 index f30356b23..000000000 --- a/SCSCons/Tool/latex.py +++ /dev/null @@ -1,80 +0,0 @@ -"""SCons.Tool.latex - -Tool-specific initialization for LaTeX. -Generates .dvi files from .latex or .ltx files - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import SCons.Action -import SCons.Defaults -import SCons.Scanner.LaTeX -import SCons.Util -import SCons.Tool -import SCons.Tool.tex - -def LaTeXAuxFunction(target = None, source= None, env=None): - result = SCons.Tool.tex.InternalLaTeXAuxAction( SCons.Tool.tex.LaTeXAction, target, source, env ) - if result != 0: - SCons.Tool.tex.check_file_error_message(env['LATEX']) - return result - -LaTeXAuxAction = SCons.Action.Action(LaTeXAuxFunction, - strfunction=SCons.Tool.tex.TeXLaTeXStrFunction) - -def generate(env): - """Add Builders and construction variables for LaTeX to an Environment.""" - - env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - - from . import dvi - dvi.generate(env) - - from . import pdf - pdf.generate(env) - - bld = env['BUILDERS']['DVI'] - bld.add_action('.ltx', LaTeXAuxAction) - bld.add_action('.latex', LaTeXAuxAction) - bld.add_emitter('.ltx', SCons.Tool.tex.tex_eps_emitter) - bld.add_emitter('.latex', SCons.Tool.tex.tex_eps_emitter) - - SCons.Tool.tex.generate_common(env) - -def exists(env): - SCons.Tool.tex.generate_darwin(env) - return env.Detect('latex') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/pdf.py b/SCSCons/Tool/pdf.py deleted file mode 100644 index 050f1a572..000000000 --- a/SCSCons/Tool/pdf.py +++ /dev/null @@ -1,78 +0,0 @@ -"""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 - -""" - -# -# __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__" - -import SCons.Builder -import SCons.Tool - -PDFBuilder = None - -EpsPdfAction = SCons.Action.Action('$EPSTOPDFCOM', '$EPSTOPDFCOMSTR') - -def generate(env): - try: - env['BUILDERS']['PDF'] - except KeyError: - global PDFBuilder - if PDFBuilder is None: - PDFBuilder = SCons.Builder.Builder(action = {}, - source_scanner = SCons.Tool.PDFLaTeXScanner, - prefix = '$PDFPREFIX', - suffix = '$PDFSUFFIX', - emitter = {}, - 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) # this is covered by direct Ghostcript action in gs.py - bld.add_action('.eps', EpsPdfAction) - - env['EPSTOPDF'] = 'epstopdf' - env['EPSTOPDFFLAGS'] = SCons.Util.CLVar('') - env['EPSTOPDFCOM'] = '$EPSTOPDF $EPSTOPDFFLAGS ${SOURCE} --outfile=${TARGET}' - -def exists(env): - # This only puts a skeleton Builder in place, so if someone - # references this Tool directly, it's always "available." - return 1 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/pdflatex.py b/SCSCons/Tool/pdflatex.py deleted file mode 100644 index fbffb2395..000000000 --- a/SCSCons/Tool/pdflatex.py +++ /dev/null @@ -1,84 +0,0 @@ -"""SCons.Tool.pdflatex - -Tool-specific initialization for pdflatex. -Generates .pdf files from .latex or .ltx files - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import SCons.Action -import SCons.Util -import SCons.Tool.pdf -import SCons.Tool.tex - -PDFLaTeXAction = None - -def PDFLaTeXAuxFunction(target = None, source= None, env=None): - result = SCons.Tool.tex.InternalLaTeXAuxAction( PDFLaTeXAction, target, source, env ) - if result != 0: - SCons.Tool.tex.check_file_error_message(env['PDFLATEX']) - return result - -PDFLaTeXAuxAction = None - -def generate(env): - """Add Builders and construction variables for pdflatex to an Environment.""" - global PDFLaTeXAction - if PDFLaTeXAction is None: - PDFLaTeXAction = SCons.Action.Action('$PDFLATEXCOM', '$PDFLATEXCOMSTR') - - global PDFLaTeXAuxAction - if PDFLaTeXAuxAction is None: - PDFLaTeXAuxAction = SCons.Action.Action(PDFLaTeXAuxFunction, - strfunction=SCons.Tool.tex.TeXLaTeXStrFunction) - - env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - - from . import pdf - pdf.generate(env) - - bld = env['BUILDERS']['PDF'] - bld.add_action('.ltx', PDFLaTeXAuxAction) - bld.add_action('.latex', PDFLaTeXAuxAction) - bld.add_emitter('.ltx', SCons.Tool.tex.tex_pdf_emitter) - bld.add_emitter('.latex', SCons.Tool.tex.tex_pdf_emitter) - - SCons.Tool.tex.generate_common(env) - -def exists(env): - SCons.Tool.tex.generate_darwin(env) - return env.Detect('pdflatex') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/pdftex.py b/SCSCons/Tool/pdftex.py deleted file mode 100644 index e9a0bda03..000000000 --- a/SCSCons/Tool/pdftex.py +++ /dev/null @@ -1,109 +0,0 @@ -"""SCons.Tool.pdftex - -Tool-specific initialization for pdftex. -Generates .pdf files from .tex files - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# -# __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__" - -import os -import SCons.Action -import SCons.Util -import SCons.Tool.tex - -PDFTeXAction = None - -# This action might be needed more than once if we are dealing with -# labels and bibtex. -PDFLaTeXAction = None - -def PDFLaTeXAuxAction(target = None, source= None, env=None): - result = SCons.Tool.tex.InternalLaTeXAuxAction( PDFLaTeXAction, target, source, env ) - return result - -def PDFTeXLaTeXFunction(target = None, source= None, env=None): - """A builder for TeX and LaTeX that scans the source file to - decide the "flavor" of the source and then executes the appropriate - program.""" - basedir = os.path.split(str(source[0]))[0] - abspath = os.path.abspath(basedir) - - if SCons.Tool.tex.is_LaTeX(source,env,abspath): - result = PDFLaTeXAuxAction(target,source,env) - if result != 0: - SCons.Tool.tex.check_file_error_message(env['PDFLATEX']) - else: - result = PDFTeXAction(target,source,env) - if result != 0: - SCons.Tool.tex.check_file_error_message(env['PDFTEX']) - return result - -PDFTeXLaTeXAction = None - -def generate(env): - """Add Builders and construction variables for pdftex to an Environment.""" - global PDFTeXAction - if PDFTeXAction is None: - PDFTeXAction = SCons.Action.Action('$PDFTEXCOM', '$PDFTEXCOMSTR') - - global PDFLaTeXAction - if PDFLaTeXAction is None: - PDFLaTeXAction = SCons.Action.Action("$PDFLATEXCOM", "$PDFLATEXCOMSTR") - - global PDFTeXLaTeXAction - if PDFTeXLaTeXAction is None: - PDFTeXLaTeXAction = SCons.Action.Action(PDFTeXLaTeXFunction, - strfunction=SCons.Tool.tex.TeXLaTeXStrFunction) - - env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - - from . import pdf - pdf.generate(env) - - bld = env['BUILDERS']['PDF'] - bld.add_action('.tex', PDFTeXLaTeXAction) - 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) - - SCons.Tool.tex.generate_common(env) - -def exists(env): - SCons.Tool.tex.generate_darwin(env) - return env.Detect('pdftex') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/tex.py b/SCSCons/Tool/tex.py deleted file mode 100644 index d8b694ecd..000000000 --- a/SCSCons/Tool/tex.py +++ /dev/null @@ -1,993 +0,0 @@ -# MIT License -# -# Copyright The SCons Foundation -# -# 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. - -""" Tool-specific initialization for TeX. - -Generates .dvi files from .tex files - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. -""" - -import os.path -import re -import shutil -import sys -import platform -import glob - -import SCons.Action -import SCons.Node -import SCons.Node.FS -import SCons.Util -import SCons.Scanner.LaTeX - -Verbose = False - -must_rerun_latex = True - -# these are files that just need to be checked for changes and then rerun latex -check_suffixes = ['.toc', '.lof', '.lot', '.out', '.nav', '.snm'] - -# these are files that require bibtex or makeindex to be run when they change -all_suffixes = check_suffixes + ['.bbl', '.idx', '.nlo', '.glo', '.acn', '.bcf'] - -# -# regular expressions used to search for Latex features -# or outputs that require rerunning latex -# -# search for all .aux files opened by latex (recorded in the .fls file) -openout_aux_re = re.compile(r"OUTPUT *(.*\.aux)") - -# search for all .bcf files opened by latex (recorded in the .fls file) -# for use by biber -openout_bcf_re = re.compile(r"OUTPUT *(.*\.bcf)") - -#printindex_re = re.compile(r"^[^%]*\\printindex", re.MULTILINE) -#printnomenclature_re = re.compile(r"^[^%]*\\printnomenclature", re.MULTILINE) -#printglossary_re = re.compile(r"^[^%]*\\printglossary", re.MULTILINE) - -# search to find rerun warnings -warning_rerun_str = r'(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)' -warning_rerun_re = re.compile(warning_rerun_str, re.MULTILINE) - -# search to find citation rerun warnings -rerun_citations_str = r"^LaTeX Warning:.*\n.*Rerun to get citations correct" -rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE) - -# search to find undefined references or citations warnings -undefined_references_str = r'(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' -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"^[^%\n]*\\tableofcontents", re.MULTILINE) -makeindex_re = re.compile(r"^[^%\n]*\\makeindex", re.MULTILINE) -bibliography_re = re.compile(r"^[^%\n]*\\bibliography", re.MULTILINE) -bibunit_re = re.compile(r"^[^%\n]*\\begin\{bibunit\}", re.MULTILINE) -multibib_re = re.compile(r"^[^%\n]*\\newcites\{([^\}]*)\}", re.MULTILINE) -addbibresource_re = re.compile(r"^[^%\n]*\\(addbibresource|addglobalbib|addsectionbib)", 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) -makeglossaries_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE) -makeacronyms_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE) -beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE) -regex = r'^[^%\n]*\\newglossary\s*\[([^\]]+)\]?\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}' -newglossary_re = re.compile(regex, re.MULTILINE) -biblatex_re = re.compile(r"^[^%\n]*\\usepackage.*\{biblatex\}", re.MULTILINE) - -newglossary_suffix = [] - -# search to find all files included by Latex -include_re = re.compile(r'^[^%\n]*\\(?:include|input){([^}]*)}', re.MULTILINE) -includeOnly_re = re.compile(r'^[^%\n]*\\(?:include){([^}]*)}', 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"OUTPUT *(.*)") - -# 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 - -# An action to build a latex file. This action might be needed more -# than once if we are dealing with labels and bibtex. -LaTeXAction = None - -# An action to run BibTeX on a file. -BibTeXAction = None - -# An action to run Biber on a file. -BiberAction = None - -# An action to run MakeIndex on a file. -MakeIndexAction = None - -# An action to run MakeIndex (for nomencl) on a file. -MakeNclAction = None - -# An action to run MakeIndex (for glossary) on a file. -MakeGlossaryAction = None - -# An action to run MakeIndex (for acronyms) on a file. -MakeAcronymsAction = None - -# An action to run MakeIndex (for newglossary commands) on a file. -MakeNewGlossaryAction = None - -# Used as a return value of modify_env_var if the variable is not set. -_null = SCons.Scanner.LaTeX._null - -modify_env_var = SCons.Scanner.LaTeX.modify_env_var - -def check_file_error_message(utility, filename='log'): - msg = '%s returned an error, check the %s file\n' % (utility, filename) - sys.stdout.write(msg) - -def FindFile(name,suffixes,paths,env,requireExt=False): - if requireExt: - name,ext = SCons.Util.splitext(name) - # if the user gave an extension use it. - if ext: - name = name + ext - 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.isfile(testName): - if Verbose: - print(" found '%s'" % testName) - return env.fs.File(testName) - else: - 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.isfile(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 - and decides how many times to use LaTeXAction, and BibTeXAction.""" - - global must_rerun_latex - - # This routine is called with two actions. In this file for DVI builds - # with LaTeXAction and from the pdflatex.py with PDFLaTeXAction - # set this up now for the case where the user requests a different extension - # for the target filename - if XXXLaTeXAction == LaTeXAction: - callerSuffix = ".dvi" - else: - callerSuffix = env['PDFSUFFIX'] - - basename = SCons.Util.splitext(str(source[0]))[0] - basedir = os.path.split(str(source[0]))[0] - basefile = os.path.split(str(basename))[1] - abspath = os.path.abspath(basedir) - - targetext = os.path.splitext(str(target[0]))[1] - targetdir = os.path.split(str(target[0]))[0] - - saved_env = {} - for var in SCons.Scanner.LaTeX.LaTeX.env_variables: - saved_env[var] = modify_env_var(env, var, abspath) - - # 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 - # aux file that TeX always creates--to make it possible to write tests - # with stubs that don't necessarily generate all of the same files. - - targetbase = os.path.join(targetdir, basefile) - - # if there is a \makeindex there will be a .idx and thus - # we have to run makeindex at least once to keep the build - # happy even if there is no index. - # Same for glossaries, nomenclature, and acronyms - src_content = source[0].get_text_contents() - run_makeindex = makeindex_re.search(src_content) and not os.path.isfile(targetbase + '.idx') - run_nomenclature = makenomenclature_re.search(src_content) and not os.path.isfile(targetbase + '.nlo') - run_glossary = makeglossary_re.search(src_content) and not os.path.isfile(targetbase + '.glo') - run_glossaries = makeglossaries_re.search(src_content) and not os.path.isfile(targetbase + '.glo') - run_acronyms = makeacronyms_re.search(src_content) and not os.path.isfile(targetbase + '.acn') - - saved_hashes = {} - suffix_nodes = {} - - - for suffix in all_suffixes+sum(newglossary_suffix, []): - theNode = env.fs.File(targetbase + suffix) - suffix_nodes[suffix] = theNode - saved_hashes[suffix] = theNode.get_csig() - - if Verbose: - print("hashes: ",saved_hashes) - - must_rerun_latex = True - - # .aux files already processed by BibTex - already_bibtexed = [] - - # - # routine to update MD5 hash and compare - # - def check_MD5(filenode, suffix): - global must_rerun_latex - # two calls to clear old csig - filenode.clear_memoized_values() - filenode.ninfo = filenode.new_ninfo() - new_md5 = filenode.get_csig() - - if saved_hashes[suffix] == new_md5: - if Verbose: - print("file %s not changed" % (targetbase+suffix)) - return False # unchanged - saved_hashes[suffix] = new_md5 - must_rerun_latex = True - if Verbose: - print("file %s changed, rerunning Latex, new hash = " % (targetbase+suffix), new_md5) - return True # changed - - # generate the file name that latex will generate - resultfilename = targetbase + callerSuffix - - count = 0 - - while must_rerun_latex and count < int(env.subst('$LATEXRETRIES')): - result = XXXLaTeXAction(target, source, env) - if result != 0: - return result - - count = count + 1 - - must_rerun_latex = False - # Decide if various things need to be run, or run again. - - # Read the log file to find warnings/errors - logfilename = targetbase + '.log' - logContent = '' - if os.path.isfile(logfilename): - with open(logfilename, "rb") as f: - logContent = f.read().decode(errors='replace') - - - # Read the fls file to find all .aux files - flsfilename = targetbase + '.fls' - flsContent = '' - auxfiles = [] - if os.path.isfile(flsfilename): - with open(flsfilename, "r") as f: - flsContent = f.read() - auxfiles = openout_aux_re.findall(flsContent) - # remove duplicates - dups = {} - for x in auxfiles: - dups[x] = 1 - auxfiles = list(dups.keys()) - - bcffiles = [] - if os.path.isfile(flsfilename): - with open(flsfilename, "r") as f: - flsContent = f.read() - bcffiles = openout_bcf_re.findall(flsContent) - # remove duplicates - dups = {} - for x in bcffiles: - dups[x] = 1 - bcffiles = list(dups.keys()) - - if Verbose: - print("auxfiles ",auxfiles) - print("bcffiles ",bcffiles) - - # Now decide if bibtex will need to be run. - # The information that bibtex reads from the .aux file is - # pass-independent. If we find (below) that the .bbl file is unchanged, - # then the last latex saw a correct bibliography. - # Therefore only do this once - # Go through all .aux files and remember the files already done. - for auxfilename in auxfiles: - if auxfilename not in already_bibtexed: - already_bibtexed.append(auxfilename) - target_aux = os.path.join(targetdir, auxfilename) - if os.path.isfile(target_aux): - with open(target_aux, "r") as f: - content = f.read() - if content.find("bibdata") != -1: - if Verbose: - print("Need to run bibtex on ",auxfilename) - bibfile = env.fs.File(SCons.Util.splitext(target_aux)[0]) - result = BibTeXAction(bibfile, bibfile, env) - if result != 0: - check_file_error_message(env['BIBTEX'], 'blg') - must_rerun_latex = True - - # Now decide if biber will need to be run. - # When the backend for biblatex is biber (by choice or default) the - # citation information is put in the .bcf file. - # The information that biber reads from the .bcf file is - # pass-independent. If we find (below) that the .bbl file is unchanged, - # then the last latex saw a correct bibliography. - # Therefore only do this once - # Go through all .bcf files and remember the files already done. - for bcffilename in bcffiles: - if bcffilename not in already_bibtexed: - already_bibtexed.append(bcffilename) - target_bcf = os.path.join(targetdir, bcffilename) - if os.path.isfile(target_bcf): - with open(target_bcf, "r") as f: - content = f.read() - if content.find("bibdata") != -1: - if Verbose: - print("Need to run biber on ",bcffilename) - bibfile = env.fs.File(SCons.Util.splitext(target_bcf)[0]) - result = BiberAction(bibfile, bibfile, env) - if result != 0: - check_file_error_message(env['BIBER'], 'blg') - must_rerun_latex = True - - # Now decide if latex will need to be run again due to index. - if check_MD5(suffix_nodes['.idx'],'.idx') or (count == 1 and run_makeindex): - # We must run makeindex - if Verbose: - print("Need to run makeindex") - idxfile = suffix_nodes['.idx'] - result = MakeIndexAction(idxfile, idxfile, env) - if result != 0: - check_file_error_message(env['MAKEINDEX'], 'ilg') - return result - - # 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 - # Harder is case is where an action needs to be called -- that should be rare (I hope?) - - for index in check_suffixes: - check_MD5(suffix_nodes[index],index) - - # Now decide if latex will need to be run again due to nomenclature. - if check_MD5(suffix_nodes['.nlo'],'.nlo') or (count == 1 and run_nomenclature): - # We must run makeindex - if Verbose: - print("Need to run makeindex for nomenclature") - nclfile = suffix_nodes['.nlo'] - result = MakeNclAction(nclfile, nclfile, env) - if result != 0: - check_file_error_message('%s (nomenclature)' % env['MAKENCL'], - 'nlg') - #return result - - # Now decide if latex will need to be run again due to glossary. - if check_MD5(suffix_nodes['.glo'],'.glo') or (count == 1 and run_glossaries) or (count == 1 and run_glossary): - # We must run makeindex - if Verbose: - print("Need to run makeindex for glossary") - glofile = suffix_nodes['.glo'] - result = MakeGlossaryAction(glofile, glofile, env) - if result != 0: - check_file_error_message('%s (glossary)' % env['MAKEGLOSSARY'], - 'glg') - #return result - - # Now decide if latex will need to be run again due to acronyms. - if check_MD5(suffix_nodes['.acn'],'.acn') or (count == 1 and run_acronyms): - # We must run makeindex - if Verbose: - print("Need to run makeindex for acronyms") - acrfile = suffix_nodes['.acn'] - result = MakeAcronymsAction(acrfile, acrfile, env) - if result != 0: - check_file_error_message('%s (acronyms)' % env['MAKEACRONYMS'], - 'alg') - return result - - # Now decide if latex will need to be run again due to newglossary command. - for ng in newglossary_suffix: - if check_MD5(suffix_nodes[ng[2]], ng[2]) or (count == 1): - # We must run makeindex - if Verbose: - print("Need to run makeindex for newglossary") - newglfile = suffix_nodes[ng[2]] - MakeNewGlossaryAction = SCons.Action.Action( - "$MAKENEWGLOSSARYCOM ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" - % (ng[2], ng[0], ng[1]), - "$MAKENEWGLOSSARYCOMSTR", - ) - - result = MakeNewGlossaryAction(newglfile, newglfile, env) - if result != 0: - check_file_error_message( - '%s (newglossary)' % env['MAKENEWGLOSSARY'], ng[0] - ) - return result - - # Now decide if latex needs to be run yet again to resolve warnings. - if warning_rerun_re.search(logContent): - must_rerun_latex = True - if Verbose: - print("rerun Latex due to latex or package rerun warning") - - if rerun_citations_re.search(logContent): - must_rerun_latex = True - if Verbose: - print("rerun Latex due to 'Rerun to get citations correct' warning") - - if undefined_references_re.search(logContent): - must_rerun_latex = True - if Verbose: - print("rerun Latex due to undefined references or citations") - - if count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex: - print("reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES'))) -# end of while loop - - # rename Latex's output to what the target name is - if not (str(target[0]) == resultfilename and os.path.isfile(resultfilename)): - if os.path.isfile(resultfilename): - print("move %s to %s" % (resultfilename, str(target[0]), )) - shutil.move(resultfilename,str(target[0])) - - # Original comment (when TEXPICTS was not restored): - # The TEXPICTS environment variable is needed by a dvi -> pdf step - # later on Mac OSX so leave it - # - # It is also used when searching for pictures (implicit dependencies). - # Why not set the variable again in the respective builder instead - # of leaving local modifications in the environment? What if multiple - # latex builds in different directories need different TEXPICTS? - for var in SCons.Scanner.LaTeX.LaTeX.env_variables: - if var == 'TEXPICTS': - continue - if saved_env[var] is _null: - try: - del env['ENV'][var] - except KeyError: - pass # was never set - else: - env['ENV'][var] = saved_env[var] - - return result - -def LaTeXAuxAction(target = None, source= None, env=None): - result = InternalLaTeXAuxAction( LaTeXAction, target, source, env ) - return result - -LaTeX_re = re.compile("\\\\document(style|class)") - -def is_LaTeX(flist,env,abspath): - """Scan a file list to decide if it's TeX- or LaTeX-flavored.""" - - # We need to scan files that are included in case the - # \documentclass command is in them. - - # 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("is_LaTeX search path ",paths) - print("files to search :",flist) - - # Now that we have the search path and file list, check each one - for f in flist: - if Verbose: - print(" checking for Latex source ",str(f)) - - content = f.get_text_contents() - if LaTeX_re.search(content): - if Verbose: - print("file %s is a LaTeX file" % str(f)) - return 1 - if Verbose: - print("file %s is not a LaTeX file" % str(f)) - - # now find included files - inc_files = [ ] - inc_files.extend( include_re.findall(content) ) - if Verbose: - print("files included by '%s': "%str(f),inc_files) - # inc_files is list of file names as given. need to find them - # using TEXINPUTS paths. - - # search the included files - for src in inc_files: - srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False) - # make this a list since is_LaTeX takes a list. - fileList = [srcNode,] - if Verbose: - print("FindFile found ",srcNode) - if srcNode is not None: - file_test = is_LaTeX(fileList, env, abspath) - - # return on first file that finds latex is needed. - if file_test: - return file_test - - if Verbose: - print(" done scanning ",str(f)) - - return 0 - -def TeXLaTeXFunction(target = None, source= None, env=None): - """A builder for TeX and LaTeX that scans the source file to - decide the "flavor" of the source and then executes the appropriate - program.""" - - # find these paths for use in is_LaTeX to search for included files - basedir = os.path.split(str(source[0]))[0] - abspath = os.path.abspath(basedir) - - if is_LaTeX(source,env,abspath): - result = LaTeXAuxAction(target,source,env) - if result != 0: - check_file_error_message(env['LATEX']) - else: - result = TeXAction(target,source,env) - if result != 0: - check_file_error_message(env['TEX']) - return result - -def TeXLaTeXStrFunction(target = None, source= None, env=None): - """A strfunction for TeX and LaTeX that scans the source file to - decide the "flavor" of the source and then returns the appropriate - command string.""" - if env.GetOption("no_exec"): - - # find these paths for use in is_LaTeX to search for included files - basedir = os.path.split(str(source[0]))[0] - abspath = os.path.abspath(basedir) - - if is_LaTeX(source,env,abspath): - result = env.subst('$LATEXCOM',0,target,source)+" ..." - else: - result = env.subst("$TEXCOM",0,target,source)+" ..." - else: - result = '' - return result - -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 ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files): - """ For theFile (a Node) update any file_tests and search for graphics files - then find all included files and call ScanFiles recursively for each of them""" - - content = theFile.get_text_contents() - if Verbose: - print(" scanning ",str(theFile)) - - for i in range(len(file_tests_search)): - if file_tests[i][0] is None: - if Verbose: - print("scan i ",i," files_tests[i] ",file_tests[i], file_tests[i][1]) - file_tests[i][0] = file_tests_search[i].search(content) - if Verbose and file_tests[i][0]: - print(" found match for ",file_tests[i][1][-1]) - # for newglossary insert the suffixes in file_tests[i] - if file_tests[i][0] and file_tests[i][1][-1] == 'newglossary': - findresult = file_tests_search[i].findall(content) - for l in range(len(findresult)) : - (file_tests[i][1]).insert(0,'.'+findresult[l][3]) - (file_tests[i][1]).insert(0,'.'+findresult[l][2]) - (file_tests[i][1]).insert(0,'.'+findresult[l][0]) - suffix_list = ['.'+findresult[l][0],'.'+findresult[l][2],'.'+findresult[l][3] ] - newglossary_suffix.append(suffix_list) - if Verbose: - print(" new suffixes for newglossary ",newglossary_suffix) - - - incResult = includeOnly_re.search(content) - if incResult: - aux_files.append(os.path.join(targetdir, incResult.group(1))) - if Verbose: - print(r"\include file names : ", aux_files) - # recursively call this on each of the included files - inc_files = [ ] - inc_files.extend( include_re.findall(content) ) - if Verbose: - print("files included by '%s': "%str(theFile),inc_files) - # inc_files is list of file names as given. need to find them - # using TEXINPUTS paths. - - for src in inc_files: - srcNode = FindFile(src,['.tex','.ltx','.latex'],paths,env,requireExt=False) - if srcNode is not None: - file_tests = ScanFiles(srcNode, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files) - if Verbose: - print(" done scanning ",str(theFile)) - return file_tests - -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, - bibliographies, indices, lists of figures, and hyperlink references. - """ - basename = SCons.Util.splitext(str(source[0]))[0] - basefile = os.path.split(str(basename))[1] - targetdir = os.path.split(str(target[0]))[0] - targetbase = os.path.join(targetdir, basefile) - - basedir = os.path.split(str(source[0]))[0] - abspath = os.path.abspath(basedir) - target[0].attributes.path = abspath - - # - # file names we will make use of in searching the sources and log file - # - emit_suffixes = ['.aux', '.log', '.ilg', '.blg', '.nls', '.nlg', '.gls', '.glg', '.alg'] + all_suffixes - auxfilename = targetbase + '.aux' - logfilename = targetbase + '.log' - flsfilename = targetbase + '.fls' - syncfilename = targetbase + '.synctex.gz' - - env.SideEffect(auxfilename,target[0]) - env.SideEffect(logfilename,target[0]) - env.SideEffect(flsfilename,target[0]) - env.SideEffect(syncfilename,target[0]) - if Verbose: - print("side effect :",auxfilename,logfilename,flsfilename,syncfilename) - env.Clean(target[0],auxfilename) - env.Clean(target[0],logfilename) - env.Clean(target[0],flsfilename) - env.Clean(target[0],syncfilename) - - content = source[0].get_text_contents() - - # set up list with the regular expressions - # we use to find features used - file_tests_search = [auxfile_re, - makeindex_re, - bibliography_re, - bibunit_re, - multibib_re, - addbibresource_re, - tableofcontents_re, - listoffigures_re, - listoftables_re, - hyperref_re, - makenomenclature_re, - makeglossary_re, - makeglossaries_re, - makeacronyms_re, - beamer_re, - newglossary_re, - biblatex_re ] - # set up list with the file suffixes that need emitting - # when a feature is found - file_tests_suff = [['.aux','aux_file'], - ['.idx', '.ind', '.ilg','makeindex'], - ['.bbl', '.blg','bibliography'], - ['.bbl', '.blg','bibunit'], - ['.bbl', '.blg','multibib'], - ['.bbl', '.blg','.bcf','addbibresource'], - ['.toc','contents'], - ['.lof','figures'], - ['.lot','tables'], - ['.out','hyperref'], - ['.nlo', '.nls', '.nlg','nomenclature'], - ['.glo', '.gls', '.glg','glossary'], - ['.glo', '.gls', '.glg','glossaries'], - ['.acn', '.acr', '.alg','acronyms'], - ['.nav', '.snm', '.out', '.toc','beamer'], - ['newglossary',], - ['.bcf', '.blg','biblatex'] ] - # for newglossary the suffixes are added as we find the command - # build the list of lists - file_tests = [] - for i in range(len(file_tests_search)): - file_tests.append( [None, 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 - - # 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) - - # scan all sources for side effect files - aux_files = [] - file_tests = ScanFiles(source[0], target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files) - - for (theSearch,suffix_list) in file_tests: - # add side effects if feature is present.If file is to be generated,add all side effects - if Verbose and theSearch: - print("check side effects for ",suffix_list[-1]) - if theSearch is not None or not source[0].exists(): - file_list = [targetbase,] - # for bibunit we need a list of files - if suffix_list[-1] == 'bibunit': - file_basename = os.path.join(targetdir, 'bu*.aux') - file_list = glob.glob(file_basename) - # remove the suffix '.aux' - for fl in file_list.copy(): - file_list.append(SCons.Util.splitext(fl)[0]) - # for multibib we need a list of files - if suffix_list[-1] == 'multibib': - for multibibmatch in multibib_re.finditer(content): - if Verbose: - print("multibib match ",multibibmatch.group(1)) - if multibibmatch is not None: - baselist = multibibmatch.group(1).split(',') - if Verbose: - print("multibib list ", baselist) - for bl in baselist: - file_list.append(os.path.join(targetdir, bl)) - # now define the side effects - for file_name in file_list: - for suffix in suffix_list[:-1]: - env.SideEffect(file_name + suffix,target[0]) - if Verbose: - print("side effect tst :",file_name + suffix, " target is ",str(target[0])) - env.Clean(target[0],file_name + suffix) - - for aFile in aux_files: - aFile_base = SCons.Util.splitext(aFile)[0] - env.SideEffect(aFile_base + '.aux',target[0]) - if Verbose: - print("side effect aux :",aFile_base + '.aux') - env.Clean(target[0],aFile_base + '.aux') - # read fls file to get all other files that latex creates and will read on the next pass - # remove files from list that we explicitly dealt with above - if os.path.isfile(flsfilename): - with open(flsfilename, "r") as f: - content = f.read() - out_files = openout_re.findall(content) - myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf'] - for filename in out_files[:]: - if filename in myfiles: - out_files.remove(filename) - env.SideEffect(out_files,target[0]) - if Verbose: - print("side effect fls :",out_files) - env.Clean(target[0],out_files) - - return (target, source) - - -TeXLaTeXAction = None - -def generate(env): - """Add Builders and construction variables for TeX to an Environment.""" - - global TeXLaTeXAction - if TeXLaTeXAction is None: - TeXLaTeXAction = SCons.Action.Action(TeXLaTeXFunction, - strfunction=TeXLaTeXStrFunction) - - env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - - generate_common(env) - - from . import dvi - dvi.generate(env) - - bld = env['BUILDERS']['DVI'] - bld.add_action('.tex', TeXLaTeXAction) - bld.add_emitter('.tex', tex_eps_emitter) - -def generate_darwin(env): - try: - environ = env['ENV'] - except KeyError: - environ = {} - env['ENV'] = environ - - if platform.system() == 'Darwin': - try: - ospath = env['ENV']['PATHOSX'] - except KeyError: - ospath = None - if ospath: - env.AppendENVPath('PATH', ospath) - -def generate_common(env): - """Add internal Builders and construction variables for LaTeX to an Environment.""" - - # Add OSX system paths so TeX tools can be found - # when a list of tools is given the exists() method is not called - generate_darwin(env) - - # A generic tex file Action, sufficient for all tex files. - global TeXAction - if TeXAction is None: - TeXAction = SCons.Action.Action("$TEXCOM", "$TEXCOMSTR") - - # An Action to build a latex file. This might be needed more - # than once if we are dealing with labels and bibtex. - global LaTeXAction - if LaTeXAction is None: - LaTeXAction = SCons.Action.Action("$LATEXCOM", "$LATEXCOMSTR") - - # Define an action to run BibTeX on a file. - global BibTeXAction - if BibTeXAction is None: - BibTeXAction = SCons.Action.Action("$BIBTEXCOM", "$BIBTEXCOMSTR") - - # Define an action to run Biber on a file. - global BiberAction - if BiberAction is None: - BiberAction = SCons.Action.Action("$BIBERCOM", "$BIBERCOMSTR") - - # Define an action to run MakeIndex on a file. - global MakeIndexAction - if MakeIndexAction is None: - MakeIndexAction = SCons.Action.Action("$MAKEINDEXCOM", "$MAKEINDEXCOMSTR") - - # Define an action to run MakeIndex on a file for nomenclatures. - global MakeNclAction - if MakeNclAction is None: - MakeNclAction = SCons.Action.Action("$MAKENCLCOM", "$MAKENCLCOMSTR") - - # Define an action to run MakeIndex on a file for glossaries. - global MakeGlossaryAction - if MakeGlossaryAction is None: - MakeGlossaryAction = SCons.Action.Action("$MAKEGLOSSARYCOM", "$MAKEGLOSSARYCOMSTR") - - # Define an action to run MakeIndex on a file for acronyms. - global MakeAcronymsAction - if MakeAcronymsAction is None: - MakeAcronymsAction = SCons.Action.Action("$MAKEACRONYMSCOM", "$MAKEACRONYMSCOMSTR") - - try: - environ = env['ENV'] - except KeyError: - environ = {} - env['ENV'] = environ - - # Some Linux platforms have pdflatex set up in a way - # that requires that the HOME environment variable be set. - # Add it here if defined. - v = os.environ.get('HOME') - if v: - environ['HOME'] = v - - CDCOM = 'cd ' - if platform.system() == 'Windows': - # allow cd command to change drives on Windows - CDCOM = 'cd /D ' - - env['TEX'] = 'tex' - env['TEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder') - env['TEXCOM'] = CDCOM + '${TARGET.dir} && $TEX $TEXFLAGS ${SOURCE.file}' - - env['PDFTEX'] = 'pdftex' - env['PDFTEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder') - env['PDFTEXCOM'] = CDCOM + '${TARGET.dir} && $PDFTEX $PDFTEXFLAGS ${SOURCE.file}' - - env['LATEX'] = 'latex' - env['LATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder') - env['LATEXCOM'] = CDCOM + '${TARGET.dir} && $LATEX $LATEXFLAGS ${SOURCE.file}' - env['LATEXRETRIES'] = 4 - - env['PDFLATEX'] = 'pdflatex' - env['PDFLATEXFLAGS'] = SCons.Util.CLVar('-interaction=nonstopmode -recorder') - env['PDFLATEXCOM'] = CDCOM + '${TARGET.dir} && $PDFLATEX $PDFLATEXFLAGS ${SOURCE.file}' - - env['BIBTEX'] = 'bibtex' - env['BIBTEXFLAGS'] = SCons.Util.CLVar('') - env['BIBTEXCOM'] = CDCOM + '${TARGET.dir} && $BIBTEX $BIBTEXFLAGS ${SOURCE.filebase}' - - env['BIBER'] = 'biber' - env['BIBERFLAGS'] = SCons.Util.CLVar('') - env['BIBERCOM'] = CDCOM + '${TARGET.dir} && $BIBER $BIBERFLAGS ${SOURCE.filebase}' - - env['MAKEINDEX'] = 'makeindex' - env['MAKEINDEXFLAGS'] = SCons.Util.CLVar('') - env['MAKEINDEXCOM'] = CDCOM + '${TARGET.dir} && $MAKEINDEX $MAKEINDEXFLAGS ${SOURCE.file}' - - env['MAKEGLOSSARY'] = 'makeindex' - env['MAKEGLOSSARYSTYLE'] = '${SOURCE.filebase}.ist' - env['MAKEGLOSSARYFLAGS'] = SCons.Util.CLVar('-s ${MAKEGLOSSARYSTYLE} -t ${SOURCE.filebase}.glg') - env['MAKEGLOSSARYCOM'] = CDCOM + '${TARGET.dir} && $MAKEGLOSSARY ${SOURCE.filebase}.glo $MAKEGLOSSARYFLAGS -o ${SOURCE.filebase}.gls' - - env['MAKEACRONYMS'] = 'makeindex' - env['MAKEACRONYMSSTYLE'] = '${SOURCE.filebase}.ist' - env['MAKEACRONYMSFLAGS'] = SCons.Util.CLVar('-s ${MAKEACRONYMSSTYLE} -t ${SOURCE.filebase}.alg') - env['MAKEACRONYMSCOM'] = CDCOM + '${TARGET.dir} && $MAKEACRONYMS ${SOURCE.filebase}.acn $MAKEACRONYMSFLAGS -o ${SOURCE.filebase}.acr' - - env['MAKENCL'] = 'makeindex' - env['MAKENCLSTYLE'] = 'nomencl.ist' - env['MAKENCLFLAGS'] = '-s ${MAKENCLSTYLE} -t ${SOURCE.filebase}.nlg' - env['MAKENCLCOM'] = CDCOM + '${TARGET.dir} && $MAKENCL ${SOURCE.filebase}.nlo $MAKENCLFLAGS -o ${SOURCE.filebase}.nls' - - env['MAKENEWGLOSSARY'] = 'makeindex' - env['MAKENEWGLOSSARYCOM'] = CDCOM + '${TARGET.dir} && $MAKENEWGLOSSARY ' - -def exists(env): - generate_darwin(env) - return env.Detect('tex') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: