Can link against static libraries.

pull/15/head
Jussi Pakkanen 12 years ago
parent 6137bfe326
commit 216a8ca1ea
  1. 46
      interpreter.py
  2. 58
      shellgenerator.py
  3. 5
      test cases/5 linkstatic/builder.txt
  4. 3
      test cases/5 linkstatic/libfile.c
  5. 5
      test cases/5 linkstatic/main.c

@ -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

@ -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 = """

@ -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)

@ -0,0 +1,3 @@
int func() {
return 0;
}

@ -0,0 +1,5 @@
int func();
int main(int argc, char **arg) {
return func();
}
Loading…
Cancel
Save