mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-22 11:56:49 +01:00
Removed latex specific things from scons.
This commit is contained in:
parent
2b368a9ecd
commit
53151b3437
@ -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
|
||||
|
||||
|
@ -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:
|
@ -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)
|
||||
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
Loading…
Reference in New Issue
Block a user