diff --git a/backends.py b/backends.py index 01e782cd6..989b65883 100644 --- a/backends.py +++ b/backends.py @@ -171,6 +171,12 @@ class Backend(): for src in target.get_sources(): if not self.environment.is_header(src): obj_list.append(self.generate_single_compile(target, outfile, src, False, header_deps)) + for obj in target.get_objects(): + if isinstance(obj, str): + o = os.path.join(self.build_to_src, target.get_subdir(), obj) + else: + raise MesonException('Unknown data type in object list.') + obj_list.append(o) elem = self.generate_link(target, outfile, outname, obj_list) self.generate_shlib_aliases(target, self.get_target_dir(target), outfile, elem) self.processed_targets[name] = True diff --git a/build.py b/build.py index e95020d86..7b5e513b5 100644 --- a/build.py +++ b/build.py @@ -91,11 +91,12 @@ class IncludeDirs(): return self.incdirs class BuildTarget(): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): self.name = name self.subdir = subdir self.is_cross = is_cross self.sources = [] + self.objects = [] self.external_deps = [] self.include_dirs = [] self.link_targets = [] @@ -105,10 +106,19 @@ class BuildTarget(): self.extra_args = {} self.generated = [] self.process_sourcelist(sources) + self.process_objectlist(objects) self.process_kwargs(kwargs) if len(self.sources) == 0 and len(self.generated) == 0: raise InvalidArguments('Build target %s has no sources.' % name) + def process_objectlist(self, objects): + assert(isinstance(objects, list)) + for s in objects: + if isinstance(s, str): + self.objects.append(s) + else: + raise InvalidArguments('Bad object in target %s.' % self.name) + def process_sourcelist(self, sources): if not isinstance(sources, list): sources = [sources] @@ -215,6 +225,9 @@ class BuildTarget(): def get_sources(self): return self.sources + def get_objects(self): + return self.objects + def get_generated_sources(self): return self.generated @@ -386,8 +399,8 @@ class GeneratedList(): return self.generator class Executable(BuildTarget): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): - super().__init__(name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): + super().__init__(name, subdir, is_cross, sources, objects, environment, kwargs) suffix = environment.get_exe_suffix() if suffix != '': self.filename = self.name + '.' + suffix @@ -396,14 +409,14 @@ class Executable(BuildTarget): class StaticLibrary(BuildTarget): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): - super().__init__(name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): + super().__init__(name, subdir, is_cross, sources, objects, environment, kwargs) prefix = environment.get_static_lib_prefix() suffix = environment.get_static_lib_suffix() self.filename = prefix + self.name + '.' + suffix class SharedLibrary(BuildTarget): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): self.version = None self.soversion = None super().__init__(name, subdir, is_cross, sources, environment, kwargs); diff --git a/interpreter.py b/interpreter.py index 4ab5c5f86..a754cdb6d 100644 --- a/interpreter.py +++ b/interpreter.py @@ -312,23 +312,23 @@ class Man(InterpreterObject): return self.sources class BuildTargetHolder(InterpreterObject): - def __init__(self, targetttype, name, subdir, is_cross, sources, environment, kwargs): - self.target = targetttype(name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, targetttype, name, subdir, is_cross, sources, objects, environment, kwargs): + self.target = targetttype(name, subdir, is_cross, sources, objects, environment, kwargs) def is_cross(self): return self.target.is_cross() class ExecutableHolder(BuildTargetHolder): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): - super().__init__(build.Executable, name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): + super().__init__(build.Executable, name, subdir, is_cross, sources, objects, environment, kwargs) class StaticLibraryHolder(BuildTargetHolder): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): - super().__init__(build.StaticLibrary, name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): + super().__init__(build.StaticLibrary, name, subdir, is_cross, sources, objects, environment, kwargs) class SharedLibraryHolder(BuildTargetHolder): - def __init__(self, name, subdir, is_cross, sources, environment, kwargs): - super().__init__(build.SharedLibrary, name, subdir, is_cross, sources, environment, kwargs) + def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs): + super().__init__(build.SharedLibrary, name, subdir, is_cross, sources, objects, environment, kwargs) class Test(InterpreterObject): def __init__(self, name, exe, is_parallel, cmd_args, env): @@ -985,10 +985,13 @@ class Interpreter(): except KeyError: kw_src = [] sources += kw_src + objs = self.flatten(kwargs.get('objects', [])) + if not isinstance(objs, list): + objs = [objs] if name in self.build.targets: raise InvalidCode('Tried to create target "%s", but a target of that name already exists.' % name) self.check_sources_exist(os.path.join(self.environment.source_dir, self.subdir), sources) - l = targetclass(name, self.subdir, is_cross, sources, self.environment, kwargs) + l = targetclass(name, self.subdir, is_cross, sources, objs, self.environment, kwargs) self.build.targets[name] = l.target if self.environment.is_cross_build() and l.is_cross: txt = ' cross build ' diff --git a/test cases/prebuilt object/1 basic/linux-amd64.o b/test cases/prebuilt object/1 basic/linux-amd64.o new file mode 100644 index 000000000..5c2488542 Binary files /dev/null and b/test cases/prebuilt object/1 basic/linux-amd64.o differ diff --git a/test cases/prebuilt object/1 basic/main.c b/test cases/prebuilt object/1 basic/main.c new file mode 100644 index 000000000..480bda5f4 --- /dev/null +++ b/test cases/prebuilt object/1 basic/main.c @@ -0,0 +1,5 @@ +int func(); + +int main(int argc, char **argv) { + return func() == 42 ? 0 : 99; +} diff --git a/test cases/prebuilt object/1 basic/meson.build b/test cases/prebuilt object/1 basic/meson.build new file mode 100644 index 000000000..5e4fb7e49 --- /dev/null +++ b/test cases/prebuilt object/1 basic/meson.build @@ -0,0 +1,19 @@ +# This test is on its own because it is special. +# To run the test you need the prebuilt object +# file for the given platform. +# +# Combined with cross compilation this would make +# the state space explode so let's just keep this +# in its own subdir so it's not run during cross +# compilation tests. + +project('prebuilt object', 'c') + +object = 'linux-amd64.o' + +# Remember: do not put source.c in this +# declaration. Only the prebuilt object. +e = executable('prog', 'main.c', +objects : object) + +test('objtest', e) diff --git a/test cases/prebuilt object/1 basic/source.c b/test cases/prebuilt object/1 basic/source.c new file mode 100644 index 000000000..f39b4f366 --- /dev/null +++ b/test cases/prebuilt object/1 basic/source.c @@ -0,0 +1,8 @@ +/* + * Compile this manually on new platforms and add the + * object file to revision control and Meson configuration. + */ + +int func() { + return 42; +}