diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2016-12-13 12:22:11 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-13 12:22:11 +0200 |
commit | de83e94b5a9ce0f540814cee40ef3746b6ebb824 (patch) | |
tree | be5504f488f980b6e394b4a2801864485c4dd792 | |
parent | 07679f0330ccc4ee3839e702d79ecdd349437593 (diff) | |
parent | 2c83bd16fc03afd2d8605734dce1ffc1946bf3d2 (diff) | |
download | meson-de83e94b5a9ce0f540814cee40ef3746b6ebb824.zip meson-de83e94b5a9ce0f540814cee40ef3746b6ebb824.tar.gz meson-de83e94b5a9ce0f540814cee40ef3746b6ebb824.tar.bz2 |
Merge pull request #1171 from centricular/fix-extracted-generated-prebuilt-object-targets-linking
Several fixes to how we handle objects in build targets
25 files changed, 292 insertions, 108 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 49b6008..48dfb11 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -178,6 +178,8 @@ class Backend(): o = os.path.join(proj_dir_to_build_root, self.build_to_src, target.get_subdir(), obj) obj_list.append(o) + elif isinstance(obj, mesonlib.File): + obj_list.append(obj.rel_to_builddir(self.build_to_src)) elif isinstance(obj, build.ExtractedObjects): obj_list += self.determine_ext_objs(obj, proj_dir_to_build_root) else: @@ -233,39 +235,21 @@ class Backend(): self.write_benchmark_file(datafile) return (test_data, benchmark_data) - def determine_linker(self, target, src): + def determine_linker(self, target): + ''' + If we're building a static library, there is only one static linker. + Otherwise, we query the target for the dynamic linker. + ''' if isinstance(target, build.StaticLibrary): if target.is_cross: return self.build.static_cross_linker else: return self.build.static_linker - if target.is_cross: - compilers = self.build.cross_compilers - else: - compilers = self.build.compilers - if len(compilers) == 1: - return compilers[0] - # Currently a bit naive. C++ must - # be linked with a C++ compiler, but - # otherwise we don't care. This will - # become trickier if and when Fortran - # and the like become supported. - cpp = None - for c in compilers: - if c.get_language() == 'cpp': - cpp = c - break - if cpp is not None: - for s in src: - if c.can_compile(s): - return cpp - for c in compilers: - if c.get_language() == 'vala': - continue - for s in src: - if c.can_compile(s): - return c - raise AssertionError("BUG: Couldn't determine linker for sources {!r}".format(src)) + l = target.get_clike_dynamic_linker() + if not l: + m = "Couldn't determine linker for target {!r}" + raise MesonException(m.format(target.name)) + return l def object_filename_from_source(self, target, source): if isinstance(source, mesonlib.File): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d8dc333..3562cf8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -299,6 +299,9 @@ int dummy; self.generate_swift_target(target, outfile) return + # Now we handle the following languages: + # ObjC++, ObjC, C++, C, D, Fortran, Vala + # Pre-existing target C/C++ sources to be built; dict of full path to # source relative to build root and the original File object. target_sources = OrderedDict() @@ -332,7 +335,6 @@ int dummy; unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. header_deps += self.get_generated_headers(target) - src_list = [] if is_unity: # Warn about incompatible sources if a unity build is enabled @@ -346,16 +348,12 @@ int dummy; ''.format(langs_are, langs, target.name) mlog.log(mlog.red('FIXME'), msg) - # Get a list of all generated *sources* (sources files, headers, - # objects, etc). Needed to determine the linker. - generated_output_sources = [] # Get a list of all generated headers that will be needed while building # this target's sources (generated sources and pre-existing sources). # This will be set as dependencies of all the target's sources. At the # same time, also deal with generated sources that need to be compiled. generated_source_files = [] for rel_src, gensrc in generated_sources.items(): - generated_output_sources.append(rel_src) raw_src = RawFilename(rel_src) if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src): if is_unity and self.get_target_source_can_unity(target, rel_src): @@ -377,12 +375,12 @@ int dummy; # this target. We create the Ninja build file elements for this here # because we need `header_deps` to be fully generated in the above loop. for src in generated_source_files: - src_list.append(src) if self.environment.is_llvm_ir(src): - obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) - continue - obj_list.append(self.generate_single_compile(target, outfile, src, True, - header_deps=header_deps)) + o = self.generate_llvm_ir_compile(target, outfile, src) + else: + o = self.generate_single_compile(target, outfile, src, True, + header_deps=header_deps) + obj_list.append(o) # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if @@ -390,7 +388,6 @@ int dummy; vala_generated_source_files = [] for src in vala_generated_sources: raw_src = RawFilename(src) - src_list.append(src) if is_unity: unity_src.append(os.path.join(self.environment.get_build_dir(), src)) header_deps.append(raw_src) @@ -415,7 +412,6 @@ int dummy; # Generate compile targets for all the pre-existing sources for this target for f, src in target_sources.items(): if not self.environment.is_header(src): - src_list.append(src) if self.environment.is_llvm_ir(src): obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) elif is_unity and self.get_target_source_can_unity(target, src): @@ -428,7 +424,7 @@ int dummy; if is_unity: for src in self.generate_unity_files(target, unity_src): obj_list.append(self.generate_single_compile(target, outfile, RawFilename(src), True, unity_deps + header_deps)) - linker = self.determine_linker(target, src_list + generated_output_sources) + linker = self.determine_linker(target) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects) self.generate_shlib_aliases(target, self.get_target_dir(target)) elem.write(outfile) @@ -970,7 +966,8 @@ int dummy; (vala_src, vapi_src, other_src) = self.split_vala_sources(target) extra_dep_files = [] if len(vala_src) == 0: - raise InvalidArguments('Vala library has no Vala source files.') + msg = 'Vala library {!r} has no Vala source files.' + raise InvalidArguments(msg.format(target.name)) valac = target.compilers['vala'] c_out_dir = self.get_target_private_dir(target) @@ -1210,7 +1207,7 @@ int dummy; raise MesonException('Swift supports only executable and static library targets.') def generate_static_link_rules(self, is_cross, outfile): - if self.build.has_language('java'): + if 'java' in self.build.compilers: if not is_cross: self.generate_java_link(outfile) if is_cross: @@ -1251,8 +1248,7 @@ int dummy; else: ctypes.append((self.build.cross_compilers, True)) for (complist, is_cross) in ctypes: - for compiler in complist: - langname = compiler.get_language() + for langname, compiler in complist.items(): if langname == 'java' or langname == 'vala' or\ langname == 'rust' or langname == 'cs': continue @@ -1511,8 +1507,7 @@ rule FORTRAN_DEP_HACK def generate_compile_rules(self, outfile): qstr = quote_char + "%s" + quote_char - for compiler in self.build.compilers: - langname = compiler.get_language() + for langname, compiler in self.build.compilers.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, False, outfile) self.generate_compile_rule_for(langname, compiler, qstr, False, outfile) @@ -1524,8 +1519,7 @@ rule FORTRAN_DEP_HACK cclist = self.build.cross_compilers else: cclist = self.build.compilers - for compiler in cclist: - langname = compiler.get_language() + for langname, compiler in cclist.items(): if compiler.get_id() == 'clang': self.generate_llvm_ir_compile_rule(compiler, True, outfile) self.generate_compile_rule_for(langname, compiler, qstr, True, outfile) @@ -1588,8 +1582,8 @@ rule FORTRAN_DEP_HACK def scan_fortran_module_outputs(self, target): compiler = None - for c in self.build.compilers: - if c.get_language() == 'fortran': + for lang, c in self.build.compilers.items(): + if lang == 'fortran': compiler = c break if compiler is None: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 79759ee..106386c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -19,6 +19,7 @@ from . import mlog import copy, os, re from .mesonlib import File, flatten, MesonException, stringlistify, classify_unity_sources from .environment import for_windows, for_darwin +from .compilers import is_object, clike_langs, lang_suffixes known_basic_kwargs = {'install' : True, 'c_pch' : True, @@ -62,17 +63,6 @@ known_lib_kwargs.update({'version' : True, # Only for shared libs 'pic' : True, # Only for static libs }) -def compilers_are_msvc(compilers): - """ - Check if all the listed compilers are MSVC. Used by Executable, - StaticLibrary, and SharedLibrary for deciding when to use MSVC-specific - file naming. - """ - for compiler in compilers.values(): - if compiler.get_id() != 'msvc': - return False - return True - class InvalidArguments(MesonException): pass @@ -88,8 +78,8 @@ class Build: self.environment = environment self.projects = {} self.targets = {} - self.compilers = [] - self.cross_compilers = [] + self.compilers = {} + self.cross_compilers = {} self.global_args = {} self.projects_args = {} self.global_link_args = {} @@ -109,26 +99,19 @@ class Build: self.dep_manifest = {} self.cross_stdlibs = {} - def has_language(self, language): - for i in self.compilers: - if i.get_language() == language: - return True - return False - def add_compiler(self, compiler): if self.static_linker is None and compiler.needs_static_linker(): self.static_linker = self.environment.detect_static_linker(compiler) - if self.has_language(compiler.get_language()): - return - self.compilers.append(compiler) + lang = compiler.get_language() + if lang not in self.compilers: + self.compilers[lang] = compiler def add_cross_compiler(self, compiler): if len(self.cross_compilers) == 0: self.static_cross_linker = self.environment.detect_static_linker(compiler) - for i in self.cross_compilers: - if i.get_language() == compiler.get_language(): - return - self.cross_compilers.append(compiler) + lang = compiler.get_language() + if lang not in self.cross_compilers: + self.cross_compilers[lang] = compiler def get_project(self): return self.projects[''] @@ -204,6 +187,10 @@ class ExtractedObjects(): if is_unity: self.check_unity_compatible() + def __repr__(self): + r = '<{0} {1!r}: {2}>' + return r.format(self.__class__.__name__, self.target.name, self.srclist) + def check_unity_compatible(self): # Figure out if the extracted object list is compatible with a Unity # build. When we're doing a Unified build, we go through the sources, @@ -290,7 +277,14 @@ class BuildTarget(): self.extra_args = {} self.generated = [] self.extra_files = [] + # Sources can be: + # 1. Pre-existing source files in the source tree + # 2. Pre-existing sources generated by configure_file in the build tree + # 3. Sources files generated by another target or a Generator self.process_sourcelist(sources) + # Objects can be: + # 1. Pre-existing objects provided by the user with the `objects:` kwarg + # 2. Compiled objects created by and extracted from another target self.process_objectlist(objects) self.process_kwargs(kwargs, environment) self.check_unknown_kwargs(kwargs) @@ -333,7 +327,7 @@ class BuildTarget(): for s in objects: if hasattr(s, 'held_object'): s = s.held_object - if isinstance(s, (str, ExtractedObjects)): + if isinstance(s, (str, File, ExtractedObjects)): self.objects.append(s) elif isinstance(s, (GeneratedList, CustomTarget)): msg = 'Generated files are not allowed in the \'objects\' kwarg ' + \ @@ -380,19 +374,56 @@ class BuildTarget(): return removed def process_compilers(self): - if len(self.sources) + len(self.generated) == 0: + ''' + Populate self.compilers, which is the list of compilers that this + target will use for compiling all its sources. + We also add compilers that were used by extracted objects to simplify + dynamic linker determination. + ''' + if len(self.sources) + len(self.generated) + len(self.objects) == 0: return - sources = list(self.sources) - for gensrc in self.generated: - sources += gensrc.get_outputs() # Populate list of compilers if self.is_cross: compilers = self.environment.coredata.cross_compilers else: compilers = self.environment.coredata.compilers - for lang, compiler in compilers.items(): - if self.can_compile_sources(compiler, sources): - self.compilers[lang] = compiler + # Pre-existing sources + sources = list(self.sources) + # All generated sources + for gensrc in self.generated: + for s in gensrc.get_outputs(): + # Generated objects can't be compiled, so don't use them for + # compiler detection. If our target only has generated objects, + # we will fall back to using the first c-like compiler we find, + # which is what we need. + if not is_object(s): + sources.append(s) + # Sources that were used to create our extracted objects + for o in self.objects: + if not isinstance(o, ExtractedObjects): + continue + for s in o.srclist: + # Don't add Vala sources since that will pull in the Vala + # compiler even though we will never use it since we are + # dealing with compiled C code. + if not s.endswith(lang_suffixes['vala']): + sources.append(s) + if sources: + # Add compilers based on the above sources + for lang, compiler in compilers.items(): + # We try to be conservative because sometimes people add files + # in the list of sources that we can't determine the type based + # just on the suffix. + if self.can_compile_sources(compiler, sources): + self.compilers[lang] = compiler + else: + # No source files, target consists of only object files of unknown + # origin. Just add the first clike compiler that we have and hope + # that it can link these objects + for lang in clike_langs: + if lang in compilers: + self.compilers[lang] = compilers[lang] + break # If all our sources are Vala, our target also needs the C compiler but # it won't get added above. if 'vala' in self.compilers and 'c' not in self.compilers: @@ -766,6 +797,43 @@ class BuildTarget(): def get_aliaslist(self): return [] + def get_clike_dynamic_linker(self): + ''' + We use the order of languages in `clike_langs` to determine which + linker to use in case the target has sources compiled with multiple + compilers. All languages other than those in this list have their own + linker. + Note that Vala outputs C code, so Vala sources can use any linker + that can link compiled C. We don't actually need to add an exception + for Vala here because of that. + ''' + for l in clike_langs: + if l in self.compilers: + return self.compilers[l] + + def get_using_msvc(self): + ''' + Check if the dynamic linker is MSVC. Used by Executable, StaticLibrary, + and SharedLibrary for deciding when to use MSVC-specific file naming + and debug filenames. + + If at least some code is built with MSVC and the final library is + linked with MSVC, we can be sure that some debug info will be + generated. We only check the dynamic linker here because the static + linker is guaranteed to be of the same type. + + Interesting cases: + 1. The Vala compiler outputs C code to be compiled by whatever + C compiler we're using, so all objects will still be created by the + MSVC compiler. + 2. If the target contains only objects, process_compilers guesses and + picks the first compiler that smells right. + ''' + linker = self.get_clike_dynamic_linker() + if linker and linker.get_id() == 'msvc': + return True + return False + class Generator(): def __init__(self, args, kwargs): @@ -890,7 +958,7 @@ class Executable(BuildTarget): self.filename += '.' + self.suffix # See determine_debug_filenames() in build.SharedLibrary buildtype = environment.coredata.get_builtin_option('buildtype') - if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'): + if self.get_using_msvc() and buildtype.startswith('debug'): self.debug_filename = self.prefix + self.name + '.pdb' def type_suffix(self): @@ -921,7 +989,7 @@ class StaticLibrary(BuildTarget): self.filename = self.prefix + self.name + '.' + self.suffix # See determine_debug_filenames() in build.SharedLibrary buildtype = environment.coredata.get_builtin_option('buildtype') - if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'): + if self.get_using_msvc() and buildtype.startswith('debug'): self.debug_filename = self.prefix + self.name + '.pdb' def type_suffix(self): @@ -997,7 +1065,7 @@ class SharedLibrary(BuildTarget): suffix = 'dll' self.vs_import_filename = '{0}.lib'.format(self.name) self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name) - if compilers_are_msvc(self.compilers): + if self.get_using_msvc(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.lib @@ -1044,7 +1112,7 @@ class SharedLibrary(BuildTarget): determine_filenames() above. """ buildtype = env.coredata.get_builtin_option('buildtype') - if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'): + if self.get_using_msvc() and buildtype.startswith('debug'): # Currently we only implement separate debug symbol files for MSVC # since the toolchain does it for us. Other toolchains embed the # debugging symbols in the file itself by default. diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 88ea3e2..93245f3 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -45,8 +45,15 @@ lang_suffixes = { } cpp_suffixes = lang_suffixes['cpp'] + ('h',) c_suffixes = lang_suffixes['c'] + ('h',) -clike_suffixes = lang_suffixes['c'] + lang_suffixes['cpp'] + ('h',) - +# List of languages that can be linked with C code directly by the linker +# used in build.py:process_compilers() and build.py:get_dynamic_linker() +clike_langs = ('objcpp', 'objc', 'd', 'cpp', 'c', 'fortran',) +clike_suffixes = () +for l in clike_langs: + clike_suffixes += lang_suffixes[l] +clike_suffixes += ('h',) + +# These are used in backend/backends.py:generated_target() def is_header(fname): if hasattr(fname, 'fname'): fname = fname.fname diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index d65ce6f..68be677 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1082,9 +1082,8 @@ class MesonMain(InterpreterObject): clist = self.build.compilers else: clist = self.build.cross_compilers - for c in clist: - if c.get_language() == cname: - return CompilerHolder(c, self.build.environment) + if cname in clist: + return CompilerHolder(clist[cname], self.build.environment) raise InterpreterException('Tried to access compiler for unspecified language "%s".' % cname) def is_unity_method(self, args, kwargs): @@ -1262,8 +1261,7 @@ class Interpreter(InterpreterBase): def check_cross_stdlibs(self): if self.build.environment.is_cross_build(): cross_info = self.build.environment.cross_info - for c in self.build.cross_compilers: - l = c.language + for l, c in self.build.cross_compilers.items(): try: di = mesonlib.stringlistify(cross_info.get_stdlib(l)) if len(di) != 2: @@ -2295,9 +2293,9 @@ requirements use the version keyword argument instead.''') def get_used_languages(self, target): result = {} for i in target.sources: - for c in self.build.compilers: + for lang, c in self.build.compilers.items(): if c.can_compile(i): - result[c.language] = True + result[lang] = True break return result diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 97814f4..af1e8fb 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -526,7 +526,7 @@ class InterpreterBase: def flatten(self, args): if isinstance(args, mparser.StringNode): return args.value - if isinstance(args, (int, str, InterpreterObject)): + if isinstance(args, (int, str, mesonlib.File, InterpreterObject)): return args result = [] for a in args: diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 1912fc1..6d05b4e 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -433,11 +433,11 @@ can not be used with the current version of glib-compiled-resources, due to cflags += state.global_args['c'] if state.project_args.get('c'): cflags += state.project_args['c'] - for compiler in state.compilers: - if compiler.get_language() == 'c': - sanitize = compiler.get_options().get('b_sanitize') - if sanitize: - cflags += compilers.sanitizer_compile_args(sanitize) + if 'c' in state.compilers: + compiler = state.compilers['c'] + sanitize = compiler.get_options().get('b_sanitize') + if sanitize: + cflags += compilers.sanitizer_compile_args(sanitize) if cflags: scan_command += ['--cflags-begin'] scan_command += cflags diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py index 2c9ed57..dca1ad6 100644 --- a/mesonbuild/modules/rpm.py +++ b/mesonbuild/modules/rpm.py @@ -27,7 +27,7 @@ class RPMModule: def generate_spec_template(self, state, args, kwargs): compiler_deps = set() - for compiler in state.compilers: + for compiler in state.compilers.values(): if isinstance(compiler, compilers.GnuCCompiler): compiler_deps.add('gcc') elif isinstance(compiler, compilers.GnuCPPCompiler): diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index cd4e343..ad882cb 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -19,9 +19,9 @@ import os class WindowsModule: def detect_compiler(self, compilers): - for c in compilers: - if c.language == 'c' or c.language == 'cpp': - return c + for l in ('c', 'cpp'): + if l in compilers: + return compilers[l] raise MesonException('Resource compilation requires a C or C++ compiler.') def compile_resources(self, state, args, kwargs): diff --git a/test cases/common/128 extract all shared library/extractor.h b/test cases/common/128 extract all shared library/extractor.h new file mode 100644 index 0000000..d0917a1 --- /dev/null +++ b/test cases/common/128 extract all shared library/extractor.h @@ -0,0 +1,6 @@ +#pragma once + +int func1(); +int func2(); +int func3(); +int func4(); diff --git a/test cases/common/128 extract all shared library/four.c b/test cases/common/128 extract all shared library/four.c new file mode 100644 index 0000000..5ca6696 --- /dev/null +++ b/test cases/common/128 extract all shared library/four.c @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func4() { + return 4; +} diff --git a/test cases/common/128 extract all shared library/func1234.def b/test cases/common/128 extract all shared library/func1234.def new file mode 100644 index 0000000..d62c08d --- /dev/null +++ b/test cases/common/128 extract all shared library/func1234.def @@ -0,0 +1,5 @@ +EXPORTS + func1 + func2 + func3 + func4 diff --git a/test cases/common/128 extract all shared library/meson.build b/test cases/common/128 extract all shared library/meson.build new file mode 100644 index 0000000..7c24fde --- /dev/null +++ b/test cases/common/128 extract all shared library/meson.build @@ -0,0 +1,10 @@ +project('extract all', 'c', 'cpp') + +a = static_library('a', 'one.c', 'two.c') +b = static_library('b', 'three.c', 'four.c') +c = shared_library('c', + objects : [a.extract_all_objects(), b.extract_all_objects()], + vs_module_defs : 'func1234.def') + +e = executable('proggie', 'prog.c', link_with : c) +test('extall', e) diff --git a/test cases/common/128 extract all shared library/one.c b/test cases/common/128 extract all shared library/one.c new file mode 100644 index 0000000..cfb0157 --- /dev/null +++ b/test cases/common/128 extract all shared library/one.c @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func1() { + return 1; +} diff --git a/test cases/common/128 extract all shared library/prog.c b/test cases/common/128 extract all shared library/prog.c new file mode 100644 index 0000000..57a4c64 --- /dev/null +++ b/test cases/common/128 extract all shared library/prog.c @@ -0,0 +1,10 @@ +#include"extractor.h" +#include<stdio.h> + +int main(int argc, char **argv) { + if((1+2+3+4) != (func1() + func2() + func3() + func4())) { + printf("Arithmetic is fail.\n"); + return 1; + } + return 0; +} diff --git a/test cases/common/128 extract all shared library/three.c b/test cases/common/128 extract all shared library/three.c new file mode 100644 index 0000000..c410046 --- /dev/null +++ b/test cases/common/128 extract all shared library/three.c @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func3() { + return 3; +} diff --git a/test cases/common/128 extract all shared library/two.c b/test cases/common/128 extract all shared library/two.c new file mode 100644 index 0000000..3ece512 --- /dev/null +++ b/test cases/common/128 extract all shared library/two.c @@ -0,0 +1,5 @@ +#include"extractor.h" + +int func2() { + return 2; +} diff --git a/test cases/common/129 object only target/installed_files.txt b/test cases/common/129 object only target/installed_files.txt new file mode 100644 index 0000000..c7dab9f --- /dev/null +++ b/test cases/common/129 object only target/installed_files.txt @@ -0,0 +1 @@ +usr/bin/prog?exe diff --git a/test cases/common/129 object only target/meson.build b/test cases/common/129 object only target/meson.build new file mode 100644 index 0000000..58d01d9 --- /dev/null +++ b/test cases/common/129 object only target/meson.build @@ -0,0 +1,45 @@ +project('object generator', 'c') + +# FIXME: Note that this will not add a dependency to the compiler executable. +# Code will not be rebuilt if it changes. +comp = find_program('obj_generator.py') + +if host_machine.system() == 'windows' + ext = '.obj' +else + ext = '.o' +endif + +cc = meson.get_compiler('c').cmd_array().get(-1) + +# Generate an object file with configure_file to mimic prebuilt objects +# provided by the source tree +source1 = configure_file(input : 'source.c', + output : 'source' + ext, + command : [comp, cc, 'source.c', + join_paths(meson.current_build_dir(), 'source' + ext)]) + +obj = static_library('obj', objects : source1) + +# Generate an object file manually. +gen = generator(comp, + output : '@BASENAME@' + ext, + arguments : [cc, '@INPUT@', '@OUTPUT@']) + +generated = gen.process(['source2.c']) + +shr = shared_library('shr', generated, + vs_module_defs : 'source2.def') + +# Generate an object file with indexed OUTPUT replacement. +gen2 = generator(comp, + output : '@BASENAME@' + ext, + arguments : [cc, '@INPUT@', '@OUTPUT0@']) +generated2 = gen2.process(['source3.c']) + +stc = static_library('stc', generated2) + +e = executable('prog', 'prog.c', link_with : [obj, shr, stc], + install : true) + +test('objgen', e) diff --git a/test cases/common/129 object only target/obj_generator.py b/test cases/common/129 object only target/obj_generator.py new file mode 100755 index 0000000..0a4537b --- /dev/null +++ b/test cases/common/129 object only target/obj_generator.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# Mimic a binary that generates an object file (e.g. windres). + +import sys, shutil, subprocess + +if __name__ == '__main__': + if len(sys.argv) != 4: + print(sys.argv[0], 'compiler input_file output_file') + sys.exit(1) + compiler = sys.argv[1] + ifile = sys.argv[2] + ofile = sys.argv[3] + if compiler.endswith('cl'): + cmd = [compiler, '/nologo', '/MDd', '/Fo'+ofile, '/c', ifile] + else: + cmd = [compiler, '-c', ifile, '-o', ofile] + sys.exit(subprocess.call(cmd)) diff --git a/test cases/common/129 object only target/prog.c b/test cases/common/129 object only target/prog.c new file mode 100644 index 0000000..60459d6 --- /dev/null +++ b/test cases/common/129 object only target/prog.c @@ -0,0 +1,7 @@ +int func1_in_obj(); +int func2_in_obj(); +int func3_in_obj(); + +int main(int argc, char **argv) { + return func1_in_obj() + func2_in_obj() + func3_in_obj(); +} diff --git a/test cases/common/129 object only target/source.c b/test cases/common/129 object only target/source.c new file mode 100644 index 0000000..7779b33 --- /dev/null +++ b/test cases/common/129 object only target/source.c @@ -0,0 +1,3 @@ +int func1_in_obj() { + return 0; +} diff --git a/test cases/common/129 object only target/source2.c b/test cases/common/129 object only target/source2.c new file mode 100644 index 0000000..29aad40 --- /dev/null +++ b/test cases/common/129 object only target/source2.c @@ -0,0 +1,3 @@ +int func2_in_obj() { + return 0; +} diff --git a/test cases/common/129 object only target/source2.def b/test cases/common/129 object only target/source2.def new file mode 100644 index 0000000..a993ab8 --- /dev/null +++ b/test cases/common/129 object only target/source2.def @@ -0,0 +1,2 @@ +EXPORTS + func2_in_obj diff --git a/test cases/common/129 object only target/source3.c b/test cases/common/129 object only target/source3.c new file mode 100644 index 0000000..1580f1e --- /dev/null +++ b/test cases/common/129 object only target/source3.c @@ -0,0 +1,3 @@ +int func3_in_obj() { + return 0; +} |