aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xinterpreter.py46
-rwxr-xr-xshellgenerator.py58
-rw-r--r--test cases/5 linkstatic/builder.txt5
-rw-r--r--test cases/5 linkstatic/libfile.c3
-rw-r--r--test cases/5 linkstatic/main.c5
5 files changed, 89 insertions, 28 deletions
diff --git a/interpreter.py b/interpreter.py
index 8fa3585..82bcf52 100755
--- a/interpreter.py
+++ b/interpreter.py
@@ -38,7 +38,16 @@ class BuildTarget(InterpreterObject):
self.name = name
self.sources = sources
self.external_deps = []
- self.methods = {'add_dep': self.add_dep_method}
+ self.methods = {'add_dep': self.add_dep_method,
+ 'link' : self.link_method}
+ self.link_targets = []
+ self.filename = 'no_name'
+
+ def get_filename(self):
+ return self.filename
+
+ def get_dependencies(self):
+ return self.link_targets
def get_basename(self):
return self.name
@@ -54,22 +63,45 @@ class BuildTarget(InterpreterObject):
def get_external_deps(self):
return self.external_deps
- def add_dep_method(self, method_name, args):
+ def add_dep_method(self, args):
[self.add_external_dep(dep) for dep in args]
+ def link_method(self, args):
+ target = args[0]
+ if not isinstance(target, StaticLibrary) and \
+ not isinstance(target, SharedLibrary):
+ raise InvalidArguments('Link target is not library.')
+ self.link_targets.append(target)
+
def method_call(self, method_name, args):
if method_name in self.methods:
- return self.methods[method_name](self, args)
+ return self.methods[method_name](args)
raise InvalidCode('Unknown method "%s" in BuildTarget.' % method_name)
+
class Executable(BuildTarget):
- pass
+ def __init__(self, name, sources, environment):
+ BuildTarget.__init__(self, name, sources)
+ suffix = environment.get_exe_suffix()
+ if suffix != '':
+ self.filename = self.name + '.' + suffix
+ else:
+ self.filename = self.name
+
class StaticLibrary(BuildTarget):
- pass
+ def __init__(self, name, sources, environment):
+ BuildTarget.__init__(self, name, sources)
+ prefix = environment.get_static_lib_prefix()
+ suffix = environment.get_static_lib_suffix()
+ self.filename = prefix + self.name + '.' + suffix
class SharedLibrary(BuildTarget):
- pass
+ def __init__(self, name, sources, environment):
+ BuildTarget.__init__(self, name, sources)
+ prefix = environment.get_shared_lib_prefix()
+ suffix = environment.get_shared_lib_suffix()
+ self.filename = prefix + self.name + '.' + suffix
class Interpreter():
@@ -182,7 +214,7 @@ class Interpreter():
sources = args[1:]
if name in self.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)
+ l = targetclass(name, sources, self.environment)
self.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 ac8c987..f115fbe 100755
--- a/shellgenerator.py
+++ b/shellgenerator.py
@@ -26,7 +26,8 @@ class ShellGenerator():
self.environment = environment
self.interpreter = interpreter
self.build_filename = 'compile.sh'
-
+ self.processed_targets = {}
+
def generate(self):
self.interpreter.run()
outfilename = os.path.join(self.environment.get_build_dir(), self.build_filename)
@@ -69,6 +70,15 @@ class ShellGenerator():
outfile.write('\necho Compiling \\"%s\\"\n' % src)
outfile.write(' '.join(quoted) + ' || exit\n')
return abs_obj
+
+ def build_target_link_arguments(self, deps):
+ args = []
+ for d in deps:
+ if not isinstance(d, interpreter.StaticLibrary):
+ print(d)
+ raise RuntimeError('Only static libraries supported ATM.')
+ args.append(self.get_target_filename(d))
+ return args
def generate_link(self, target, outfile, outname, obj_list):
if isinstance(target, interpreter.StaticLibrary):
@@ -91,6 +101,7 @@ class ShellGenerator():
commands += linker.get_output_flags()
commands.append(outname)
commands += obj_list
+ commands += self.build_target_link_arguments(target.get_dependencies())
quoted = shell_quote(commands)
outfile.write('\necho Linking \\"%s\\".\n' % target.get_basename())
outfile.write(' '.join(quoted) + ' || exit\n')
@@ -102,27 +113,32 @@ class ShellGenerator():
def generate_commands(self, outfile):
for i in self.interpreter.get_targets().items():
- name = i[0]
target = i[1]
- print('Generating target', name)
- targetdir = self.get_target_dir(target)
- prefix = ''
- suffix = ''
- if isinstance(target, interpreter.Executable):
- suffix = self.environment.get_exe_suffix()
- elif isinstance(target, interpreter.StaticLibrary):
- prefix = self.environment.get_static_lib_prefix()
- suffix = self.environment.get_static_lib_suffix()
- elif isinstance(target, interpreter.SharedLibrary):
- prefix = self.environment.get_shared_lib_prefix()
- suffix = self.environment.get_shared_lib_suffix()
- outname = os.path.join(targetdir, prefix + target.get_basename())
- if suffix != '':
- outname = outname + '.' + suffix
- obj_list = []
- for src in target.get_sources():
- obj_list.append(self.generate_single_compile(target, outfile, src))
- self.generate_link(target, outfile, outname, obj_list)
+ self.generate_target(target, outfile)
+
+ def process_target_dependencies(self, target, outfile):
+ for t in target.get_dependencies():
+ tname = t.get_basename()
+ if not tname in self.processed_targets:
+ self.generate_target(t, outfile)
+
+ def get_target_filename(self, target):
+ targetdir = self.get_target_dir(target)
+ filename = os.path.join(targetdir, target.get_filename())
+ return filename
+
+ def generate_target(self, target, outfile):
+ name = target.get_basename()
+ if name in self.processed_targets:
+ return
+ self.process_target_dependencies(target, outfile)
+ print('Generating target', name)
+ outname = self.get_target_filename(target)
+ obj_list = []
+ for src in target.get_sources():
+ obj_list.append(self.generate_single_compile(target, outfile, src))
+ self.generate_link(target, outfile, outname, obj_list)
+ self.processed_targets[name] = True
if __name__ == '__main__':
code = """
diff --git a/test cases/5 linkstatic/builder.txt b/test cases/5 linkstatic/builder.txt
new file mode 100644
index 0000000..5e98a25
--- /dev/null
+++ b/test cases/5 linkstatic/builder.txt
@@ -0,0 +1,5 @@
+project('static library linking test')
+language('c')
+lib = static_library('mylib', 'libfile.c')
+exe = executable('prog', 'main.c')
+exe.link(lib)
diff --git a/test cases/5 linkstatic/libfile.c b/test cases/5 linkstatic/libfile.c
new file mode 100644
index 0000000..6f1c172
--- /dev/null
+++ b/test cases/5 linkstatic/libfile.c
@@ -0,0 +1,3 @@
+int func() {
+ return 0;
+}
diff --git a/test cases/5 linkstatic/main.c b/test cases/5 linkstatic/main.c
new file mode 100644
index 0000000..8aadb0c
--- /dev/null
+++ b/test cases/5 linkstatic/main.c
@@ -0,0 +1,5 @@
+int func();
+
+int main(int argc, char **arg) {
+ return func();
+}