-
Notifications
You must be signed in to change notification settings - Fork 2
/
SConstruct
118 lines (96 loc) · 4.01 KB
/
SConstruct
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import os
import shlex
import subprocess
import sys
import warnings
# check SCons version
EnsureSConsVersion(3, 0)
# we need at least Python 3.5, for example for subprocess.run
if sys.version_info < (3, 5):
raise RuntimeError("These SCons scripts require Python 3.5 or newer. "
"Try running `python3 /usr/bin/scons` or similar.")
# class with helper methods
class Helper(object):
isPDFSizeOptInstalled = None
@staticmethod
def checkPDFSizeOptInstalled(env):
if Helper.checkProgramInstalled(env, "pdfsizeopt"):
Helper.isPDFSizeOptInstalled = True
else:
warnings.warn("pdfsizeopt required for compressing output PDFs. "
"Output PDFs won't be compressed.")
Helper.isPDFSizeOptInstalled = False
# check if a dependency is installed, fail if not (if desired)
@staticmethod
def checkProgramInstalled(env, program, fail=False):
if (not env.GetOption("help")) and (not env.GetOption("clean")):
conf = Configure(env, log_file=None)
result = (conf.CheckProg(program) is not None)
if (not result) and fail:
message = "Program \"{}\" required, but not found in PATH.".format(
program)
if env["REQUIRE_PROGRAMS"]: raise RuntimeError(message)
else: warnings.warn(message)
conf.Finish()
return result
else:
return True
# compress PDF via pdfsizeopt
def compressPDFs(target, source, env):
pdf = target[0].abspath
if Helper.isPDFSizeOptInstalled:
pdfOptimized = "{}.opt".format(pdf)
Helper.runCommand(["pdfsizeopt", "--do-unify-fonts=no",
"--use-pngout=no", "--v=30", pdf, pdfOptimized])
os.remove(pdf)
os.rename(pdfOptimized, pdf)
else:
print("Skipping compression of \"{}\".".format(pdf))
# print and run command line, check=True by default
@staticmethod
def runCommand(args, check=True, **kwargs):
print(" ".join([shlex.quote(arg) for arg in args]))
kwargs["check"] = check
return subprocess.run(args, **kwargs)
# build flags
variables = Variables(None, ARGUMENTS)
variables.Add(BoolVariable("REQUIRE_PROGRAMS",
"Fail if a required program is not installed.", True))
# set up environment, export environment variables of the shell
# (for example needed for custom TeX installations which need PATH)
env = Environment(variables=variables, ENV=os.environ)
# display help about build flags when called with -h
Help(variables.GenerateHelpText(env))
# check if pdfsizeopt is installed
Helper.checkPDFSizeOptInstalled(env)
# use timestamp to decide if a file should be rebuilt
# (otherwise SCons won't rebuild even if it is necessary)
env.Decider("timestamp-newer")
# iterate over all dependent directories
# note: "tex" has to be before "out"
dirTargets = {}
dirs = ["bib", "gfx", "lua", "misc", "tex", "out"]
createDirs = (not env.GetOption("help")) and (not env.GetOption("clean"))
for dir_ in dirs:
# tell SConscript which its build directory is
env["BUILD_DIR"] = env.Dir(os.path.join("build", dir_))
# create build directory
if (dir_ not in ["lua", "misc"]) and createDirs:
env.Execute(Mkdir(env["BUILD_DIR"]))
# execute SConscript
dirTargets[dir_] = env.SConscript(os.path.join(dir_, "SConscript"),
exports=["env", "Helper"])
# clean up dir_
env.Clean(dirTargets[dir_], env["BUILD_DIR"])
# set BUILD_PDF variable (build/tex/thesis.pdf)
if dir_ == "tex": env["BUILD_PDF"] = dirTargets[dir_][0]
# the PDF depends on everything that is not in tex (these dependencies are
# handled by tex/SConscript) and out
env.Depends(env["BUILD_PDF"], [dirTargets[dir_] for dir_ in dirs
if dir_ not in ["tex", "out"]])
# dirty fix for Debian bug #893740
# (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=893740),
# they seem to have reintroduced the Python-2-only syntax "dict.has_key"
# (instead of "in") in SCons/Script/Main.py, line 1111,
# occurs when cleaning, i.e., `scons -c`
os.environ.has_key = (lambda x: x in os.environ)