aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.py37
-rwxr-xr-xbuilder.py20
-rwxr-xr-xinterpreter.py37
-rwxr-xr-xshellgenerator.py21
4 files changed, 70 insertions, 45 deletions
diff --git a/build.py b/build.py
new file mode 100644
index 0000000..61a51f4
--- /dev/null
+++ b/build.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python3 -tt
+
+# Copyright 2012 Jussi Pakkanen
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Build:
+ """A class that holds the status of one build including
+ all dependencies and so on.
+ """
+
+ def __init__(self, environment):
+ self.environment = environment
+ self.project = None
+ self.targets = {}
+ self.compilers = []
+ self.tests = []
+ self.static_linker = self.environment.detect_static_linker()
+
+ def get_project(self):
+ return self.project
+
+ def get_targets(self):
+ return self.targets
+
+ def get_tests(self):
+ return self.tests
diff --git a/builder.py b/builder.py
index e11cbd3..f0d161a 100755
--- a/builder.py
+++ b/builder.py
@@ -18,7 +18,7 @@ from optparse import OptionParser
import sys, stat
import os.path
import environment, interpreter
-import shellgenerator
+import shellgenerator, build
parser = OptionParser()
@@ -27,7 +27,7 @@ parser.add_option('--libdir', default='lib', dest='libdir')
parser.add_option('--includedir', default='include', dest='includedir')
parser.add_option('--datadir', default='share', dest='datadir')
-class Builder():
+class BuilderApp():
builder_filename = 'builder.txt'
def __init__(self, dir1, dir2, options):
@@ -35,7 +35,7 @@ class Builder():
self.options = options
def has_builder_file(self, dirname):
- fname = os.path.join(dirname, Builder.builder_filename)
+ fname = os.path.join(dirname, BuilderApp.builder_filename)
try:
ifile = open(fname, 'r')
ifile.close()
@@ -55,20 +55,22 @@ class Builder():
raise RuntimeError('Source and build directories must not be the same. Create a pristine build directory.')
if self.has_builder_file(ndir1):
if self.has_builder_file(ndir2):
- raise RuntimeError('Both directories contain a builder file %s.' % Builder.builder_filename)
+ raise RuntimeError('Both directories contain a builder file %s.' % BuilderApp.builder_filename)
return (ndir1, ndir2)
if self.has_builder_file(ndir2):
return (ndir2, ndir1)
- raise RuntimeError('Neither directory contains a builder file %s.' % Builder.builder_filename)
+ raise RuntimeError('Neither directory contains a builder file %s.' % BuilderApp.builder_filename)
def generate(self):
- code = open(os.path.join(self.source_dir, Builder.builder_filename)).read()
+ code = open(os.path.join(self.source_dir, BuilderApp.builder_filename)).read()
if len(code.strip()) == 0:
raise interpreter.InvalidCode('Builder file is empty.')
assert(isinstance(code, str))
env = environment.Environment(self.source_dir, self.build_dir)
- intr = interpreter.Interpreter(code, env)
- g = shellgenerator.ShellGenerator(intr, env)
+ b = build.Build(env)
+ intr = interpreter.Interpreter(code, b)
+ intr.run()
+ g = shellgenerator.ShellGenerator(b)
g.generate()
if __name__ == '__main__':
@@ -81,7 +83,7 @@ if __name__ == '__main__':
dir2 = args[2]
else:
dir2 = '.'
- builder = Builder(dir1, dir2, options)
+ builder = BuilderApp(dir1, dir2, options)
print ('Source dir: ' + builder.source_dir)
print ('Build dir: ' + builder.build_dir)
builder.generate()
diff --git a/interpreter.py b/interpreter.py
index 9d3aa78..85993fd 100755
--- a/interpreter.py
+++ b/interpreter.py
@@ -116,17 +116,13 @@ class Test(InterpreterObject):
class Interpreter():
- def __init__(self, code, environment):
+ def __init__(self, code, build):
+ self.build = build
self.ast = parser.build_ast(code)
self.sanity_check_ast()
- self.project = None
- self.compilers = []
- self.targets = {}
self.variables = {}
- self.environment = environment
- self.static_linker = self.environment.detect_static_linker()
+ self.environment = build.environment
self.build_func_dict()
- self.tests = []
def build_func_dict(self):
self.funcs = {'project' : self.func_project,
@@ -139,15 +135,6 @@ class Interpreter():
'add_test' : self.func_add_test
}
- def get_project(self):
- return self.project
-
- def get_targets(self):
- return self.targets
-
- def get_tests(self):
- return self.tests
-
def sanity_check_ast(self):
if not isinstance(self.ast, nodes.CodeBlock):
raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.')
@@ -189,10 +176,10 @@ class Interpreter():
def func_project(self, node, args):
self.validate_arguments(args, 1, [str])
- if self.project is not None:
+ if self.build.project is not None:
raise InvalidCode('Second call to project() on line %d.' % node.lineno())
- self.project = args[0]
- print('Project name is "%s".' % self.project)
+ self.build.project = args[0]
+ print('Project name is "%s".' % self.build.project)
def func_message(self, node, args):
self.validate_arguments(args, 1, [str])
@@ -204,17 +191,17 @@ class Interpreter():
for a in args:
if not isinstance(a, str):
raise InvalidArguments('Line %d: Argument %s is not a string.' % (node.lineno(), str(a)))
- if len(self.compilers) > 0:
+ if len(self.build.compilers) > 0:
raise InvalidCode('Function language() can only be called once (line %d).' % node.lineno())
for lang in args:
if lang.lower() == 'c':
comp = self.environment.detect_c_compiler()
comp.sanity_check(self.environment.get_scratch_dir())
- self.compilers.append(comp)
+ self.build.compilers.append(comp)
elif lang.lower() == 'c++':
comp = self.environment.detect_cxx_compiler()
comp.sanity_check(self.environment.get_scratch_dir())
- self.compilers.append(comp)
+ self.build.compilers.append(comp)
else:
raise InvalidCode('Tried to use unknown language "%s".' % lang)
@@ -236,7 +223,7 @@ class Interpreter():
def func_add_test(self, node, args):
self.validate_arguments(args, 2, [str, Executable])
t = Test(args[0], args[1])
- self.tests.append(t)
+ self.build.tests.append(t)
print('Adding test "%s"' % args[0])
def build_target(self, node, args, targetclass):
@@ -245,10 +232,10 @@ class Interpreter():
raise InvalidArguments('Line %d: Argument %s is not a string.' % (node.lineno(), str(a)))
name= args[0]
sources = args[1:]
- if name in self.targets:
+ if name in self.build.targets:
raise InvalidCode('Line %d: tried to create target "%s", but a target of that name already exists.' % (node.lineno(), name))
l = targetclass(name, sources, self.environment)
- self.targets[name] = l
+ self.build.targets[name] = l
print('Creating build target "%s" with %d files.' % (name, len(sources)))
return l
diff --git a/shellgenerator.py b/shellgenerator.py
index 009ac7c..e493354 100755
--- a/shellgenerator.py
+++ b/shellgenerator.py
@@ -22,15 +22,14 @@ def shell_quote(cmdlist):
class ShellGenerator():
- def __init__(self, interpreter, environment):
- self.environment = environment
- self.interpreter = interpreter
+ def __init__(self, build):
+ self.build = build
+ self.environment = build.environment
self.build_filename = 'compile.sh'
self.test_filename = 'run_tests.sh'
self.processed_targets = {}
def generate(self):
- self.interpreter.run()
self.generate_compile_script()
self.generate_test_script()
@@ -39,7 +38,7 @@ class ShellGenerator():
outfile = open(outfilename, 'w')
outfile.write('#!/bin/sh\n\n')
outfile.write('echo This is an autogenerated shell script build file for project \\"%s\\".\n'
- % self.interpreter.get_project())
+ % self.build.get_project())
outfile.write('echo This is experimental and most likely will not work!\n')
cdcmd = ['cd', self.environment.get_build_dir()]
outfile.write(' '.join(shell_quote(cdcmd)) + '\n')
@@ -53,7 +52,7 @@ class ShellGenerator():
outfile = open(outfilename, 'w')
outfile.write('#!/bin/sh\n\n')
outfile.write('echo This is an autogenerated shell script test file for project \\"%s\\".\n'
- % self.interpreter.get_project())
+ % self.build.get_project())
outfile.write('echo Run the compile script before this one or bad things will happen!\n')
cdcmd = ['cd', self.environment.get_build_dir()]
outfile.write(' '.join(shell_quote(cdcmd)) + '\n')
@@ -63,7 +62,7 @@ class ShellGenerator():
stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
def generate_tests(self, outfile):
- for t in self.interpreter.get_tests():
+ for t in self.build.get_tests():
cmds = []
cmds.append(self.get_target_filename(t.get_exe()))
outfile.write('echo Running test \\"%s\\".\n' % t.get_name())
@@ -71,7 +70,7 @@ class ShellGenerator():
def generate_single_compile(self, target, outfile, src):
compiler = None
- for i in self.interpreter.compilers:
+ for i in self.build.compilers:
if i.can_compile(src):
compiler = i
break
@@ -108,9 +107,9 @@ class ShellGenerator():
def generate_link(self, target, outfile, outname, obj_list):
if isinstance(target, interpreter.StaticLibrary):
- linker = self.interpreter.static_linker
+ linker = self.build.static_linker
else:
- linker = self.interpreter.compilers[0] # Fixme.
+ linker = self.build.compilers[0] # Fixme.
commands = []
commands += linker.get_exelist()
if isinstance(target, interpreter.Executable):
@@ -138,7 +137,7 @@ class ShellGenerator():
return dirname
def generate_commands(self, outfile):
- for i in self.interpreter.get_targets().items():
+ for i in self.build.get_targets().items():
target = i[1]
self.generate_target(target, outfile)