diff --git a/manual tests/9 nostdlib/meson.build b/manual tests/9 nostdlib/meson.build index ad5b7b9ba..3ef743ebf 100644 --- a/manual tests/9 nostdlib/meson.build +++ b/manual tests/9 nostdlib/meson.build @@ -2,13 +2,9 @@ project('own libc', 'c') # A simple project that uses its own libc. -libc_proj = subproject('mylibc') -libc_dep = libc_proj.get_variable('mylibc_dep') - -exe = executable('selfcontained', 'prog.c', - c_args : '-nostdlib', - link_args : '-nostdlib', - dependencies : libc_dep, -) +# Note that we don't need to specify anything, the flags to use +# stdlib come from the cross file. + +exe = executable('selfcontained', 'prog.c') test('standalone test', exe) diff --git a/manual tests/9 nostdlib/subprojects/mylibc/meson.build b/manual tests/9 nostdlib/subprojects/mylibc/meson.build index 9d1fed8cf..aa0184e11 100644 --- a/manual tests/9 nostdlib/subprojects/mylibc/meson.build +++ b/manual tests/9 nostdlib/subprojects/mylibc/meson.build @@ -2,10 +2,9 @@ project('own libc', 'c') # A very simple libc implementation -# Start with manual flags to compile, then add platform support. +# Do not specify -nostdlib & co. They come from cross specifications. -libc = static_library('c', 'libc.c', 'stubstart.s', -) +libc = static_library('c', 'libc.c', 'stubstart.s') mylibc_dep = declare_dependency(link_with : libc, include_directories : include_directories('.') diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index ceb466b62..29966b964 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -244,6 +244,7 @@ class Backend(): def generate_basic_compiler_args(self, target, compiler): commands = [] + commands += self.get_cross_stdlib_args(target, compiler) commands += compiler.get_always_args() commands += compiler.get_warn_args(self.environment.coredata.get_builtin_option('warning_level')) commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 201b2d14e..ec07395ff 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1427,6 +1427,13 @@ rule FORTRAN_DEP_HACK mod_files.append(os.path.join(dirname, mod_name)) return mod_files + def get_cross_stdlib_args(self, target, compiler): + if not target.is_cross: + return [] + if self.environment.cross_info.has_stdlib(compiler.language): + return [] + return compiler.get_no_stdinc_args() + def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): if(isinstance(src, str) and src.endswith('.h')): raise RuntimeError('Fug') @@ -1632,6 +1639,13 @@ rule FORTRAN_DEP_HACK elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info.config['host_machine']['system']) elem.write(outfile) + def get_cross_stdlib_link_args(self, target, linker): + if isinstance(target, build.StaticLibrary) or not target.is_cross: + return [] + if not self.environment.cross_info.has_stdlib(linker.language): + return [] + return linker.get_no_stdlib_link_args() + def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): if isinstance(target, build.StaticLibrary): linker_base = 'STATIC' @@ -1645,6 +1659,7 @@ rule FORTRAN_DEP_HACK linker_rule = linker_base + crstr + '_LINKER' abspath = os.path.join(self.environment.get_build_dir(), target.subdir) commands = [] + commands += self.get_cross_stdlib_link_args(target, linker) commands += linker.get_linker_always_args() if not isinstance(target, build.StaticLibrary): commands += compilers.get_base_link_args(self.environment.coredata.base_options, diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 63cdcf37d..60b5ec0a1 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -102,6 +102,7 @@ class Build: self.install_dirs = [] self.dep_manifest_name = None self.dep_manifest = {} + self.cross_stdlibs = {} def has_language(self, language): for i in self.compilers: diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8dee468a7..c4e8f0d41 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -311,6 +311,12 @@ class CCompiler(Compiler): def get_always_args(self): return [] + def get_no_stdinc_args(self): + return ['-nostdinc'] + + def get_no_stdlib_link_args(self): + return ['-nostdlib'] + def get_warn_args(self, level): return self.warn_args[level] diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index c4591b4e5..19594c86f 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -716,6 +716,12 @@ class CrossBuildInfo(): def has_target(self): return 'target_machine' in self.config + def has_stdlib(self, language): + return language + '_stdlib' in self.config['properties'] + + def get_stdlib(self, language): + return self.config['properties'][language + '_stdlib'] + # Wehn compiling a cross compiler we use the native compiler for everything. # But not when cross compiling a cross compiler. def need_cross_compiler(self): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index d6a3a3e32..b83f4a34e 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1080,6 +1080,22 @@ class Interpreter(): if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': raise InvalidCode('First statement must be a call to project') + 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 + try: + di = mesonlib.stringlistify(cross_info.get_stdlib(l)) + if len(di) != 2: + raise InterpreterException('Stdlib definition for %s should have exactly two elements.' \ + % l) + projname, depname = di + subproj = self.do_subproject(projname, {}) + self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {}) + except KeyError as e: + pass + def run(self): self.evaluate_codeblock(self.ast) mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets)))) @@ -1422,6 +1438,8 @@ class Interpreter(): if 'vala' in langs: if not 'c' in langs: raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.') + if not self.is_subproject(): + self.check_cross_stdlibs() @stringArgs def func_add_languages(self, node, args, kwargs): @@ -1991,11 +2009,28 @@ class Interpreter(): mlog.debug('Unknown target type:', str(targetholder)) raise RuntimeError('Unreachable code') target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) + if is_cross: + self.add_cross_stdlib_info(target) l = targetholder(target, self) self.add_target(name, l.held_object) self.global_args_frozen = True return l + def get_used_languages(self, target): + result = {} + for i in target.sources: + for c in self.build.compilers: + if c.can_compile(i): + result[c.language] = True + break + return result + + def add_cross_stdlib_info(self, target): + for l in self.get_used_languages(target): + if self.environment.cross_info.has_stdlib(l) and \ + self.subproject != self.environment.cross_info.get_stdlib(l)[0]: + target.add_external_deps(self.build.cross_stdlibs[l]) + def check_sources_exist(self, subdir, sources): for s in sources: if not isinstance(s, str):