diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2018-10-04 20:52:08 -0400 |
---|---|---|
committer | John Ericson <git@JohnEricson.me> | 2019-06-09 13:13:25 -0400 |
commit | 07777e15d47dbddaf849d24b3a30c85745c533ca (patch) | |
tree | f472472ed511498c329b4e13e19b1585e1afb621 /mesonbuild | |
parent | 32e827dcdc451e1c5dde952cf08e4b654eac7057 (diff) | |
download | meson-07777e15d47dbddaf849d24b3a30c85745c533ca.zip meson-07777e15d47dbddaf849d24b3a30c85745c533ca.tar.gz meson-07777e15d47dbddaf849d24b3a30c85745c533ca.tar.bz2 |
Purge `is_cross` and friends without changing user interfaces
In most cases instead pass `for_machine`, the name of the relevant
machines (what compilers target, what targets run on, etc). This allows
us to use the cross code path in the native case, deduplicating the
code.
As one can see, environment got bigger as more information is kept
structured there, while ninjabackend got a smaller. Overall a few amount
of lines were added, but the hope is what's added is a lot simpler than
what's removed.
Diffstat (limited to 'mesonbuild')
36 files changed, 701 insertions, 841 deletions
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 5ac6133..617b140 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -18,6 +18,7 @@ from . import AstInterpreter from .. import compilers, environment, mesonlib, optinterpreter from .. import coredata as cdata +from ..mesonlib import MachineChoice from ..interpreterbase import InvalidArguments from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode @@ -127,11 +128,11 @@ class IntrospectionInterpreter(AstInterpreter): def func_add_languages(self, node, args, kwargs): args = self.flatten_args(args) - need_cross_compiler = self.environment.is_cross_build() - for lang in sorted(args, key=compilers.sort_clink): - lang = lang.lower() - if lang not in self.coredata.compilers: - self.environment.detect_compilers(lang, need_cross_compiler) + for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: + for lang in sorted(args, key=compilers.sort_clink): + lang = lang.lower() + if lang not in self.coredata.compilers[for_machine]: + self.environment.detect_compiler_for(lang, for_machine) def func_dependency(self, node, args, kwargs): args = self.flatten_args(args) @@ -195,10 +196,10 @@ class IntrospectionInterpreter(AstInterpreter): kwargs_reduced = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs and k in ['install', 'build_by_default', 'build_always']} kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()} kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)} - is_cross = False + for_machine = MachineChoice.HOST objects = [] empty_sources = [] # Passing the unresolved sources list causes errors - target = targetclass(name, self.subdir, self.subproject, is_cross, empty_sources, objects, self.environment, kwargs_reduced) + target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, objects, self.environment, kwargs_reduced) new_target = { 'name': target.get_basename(), diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 6e75974..5e71933 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -195,14 +195,9 @@ class Backend: self.environment.coredata.base_options) def get_compiler_options_for_target(self, target): - if self.environment.is_cross_build() and not target.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - return OptionOverrideProxy( target.option_overrides, - self.environment.coredata.compiler_options[for_machine]) + self.environment.coredata.compiler_options[target.for_machine]) def get_option_for_target(self, option_name, target): if option_name in target.option_overrides: @@ -357,17 +352,15 @@ class Backend: with open(exe_data, 'wb') as f: if isinstance(exe, dependencies.ExternalProgram): exe_cmd = exe.get_command() - exe_is_native = True + exe_for_machine = exe.for_machine elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): exe_cmd = [self.get_target_filename_abs(exe)] - exe_is_native = not exe.is_cross + exe_for_machine = exe.for_machine else: exe_cmd = [exe] - exe_is_native = True - is_cross_built = (not exe_is_native) and \ - self.environment.is_cross_build() and \ - self.environment.need_exe_wrapper() - if is_cross_built: + exe_for_machine = MachineChoice.BUILD + is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) + if is_cross_built and self.environment.need_exe_wrapper(): exe_wrapper = self.environment.get_exe_wrapper() if not exe_wrapper.found(): msg = 'The exe_wrapper {!r} defined in the cross file is ' \ @@ -397,10 +390,7 @@ class Backend: 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, [] + return self.build.static_linker[target.for_machine], [] l, stdlib_args = target.get_clink_dynamic_linker_and_stdlibs() return l, stdlib_args @@ -476,7 +466,8 @@ class Backend: else: source = os.path.relpath(os.path.join(build_dir, rel_src), os.path.join(self.environment.get_source_dir(), target.get_subdir())) - return source.replace('/', '_').replace('\\', '_') + '.' + self.environment.get_object_suffix() + machine = self.environment.machines[target.for_machine] + return source.replace('/', '_').replace('\\', '_') + '.' + machine.get_object_suffix() def determine_ext_objs(self, extobj, proj_dir_to_build_root): result = [] @@ -608,18 +599,14 @@ class Backend: commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target)) commands += compiler.get_debug_args(self.get_option_for_target('debug', target)) # Add compile args added using add_project_arguments() - commands += self.build.get_project_args(compiler, target.subproject, target.is_cross) + commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) # Add compile args added using add_global_arguments() # These override per-project arguments - commands += self.build.get_global_args(compiler, target.is_cross) - if self.environment.is_cross_build() and not target.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST + commands += self.build.get_global_args(compiler, target.for_machine) # Compile args added from the env: CFLAGS/CXXFLAGS, etc, or the cross # file. We want these to override all the defaults, but not the # per-target compile args. - commands += self.environment.coredata.get_external_args(for_machine, compiler.get_language()) + commands += self.environment.coredata.get_external_args(target.for_machine, compiler.get_language()) # Always set -fPIC for shared libraries if isinstance(target, build.SharedLibrary): commands += compiler.get_pic_args() @@ -679,11 +666,11 @@ class Backend: def get_mingw_extra_paths(self, target): paths = OrderedSet() # The cross bindir - root = self.environment.properties.host.get_root() + root = self.environment.properties[target.for_machine].get_root() if root: paths.add(os.path.join(root, 'bin')) # The toolchain bindir - sys_root = self.environment.properties.host.get_sys_root() + sys_root = self.environment.properties[target.for_machine].get_sys_root() if sys_root: paths.add(os.path.join(sys_root, 'bin')) # Get program and library dirs from all target compilers @@ -693,7 +680,7 @@ class Backend: paths.update(cc.get_library_dirs(self.environment)) return list(paths) - def determine_windows_extra_paths(self, target, extra_bdeps, is_cross=False): + def determine_windows_extra_paths(self, target: typing.Union[build.BuildTarget, str], extra_bdeps): '''On Windows there is no such thing as an rpath. We must determine all locations of DLLs that this exe links to and return them so they can be used in unit @@ -713,7 +700,8 @@ class Backend: continue dirseg = os.path.join(self.environment.get_build_dir(), self.get_target_dir(ld)) result.add(dirseg) - if is_cross: + if (isinstance(target, build.BuildTarget) and + not self.environment.machines.matches_build_machine(target.for_machine)): result.update(self.get_mingw_extra_paths(target)) return list(result) @@ -731,24 +719,23 @@ class Backend: cmd = exe.get_command() else: cmd = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))] - is_cross = self.environment.is_cross_build() and \ - self.environment.need_exe_wrapper() - if isinstance(exe, build.BuildTarget): - is_cross = is_cross and exe.is_cross - if isinstance(exe, dependencies.ExternalProgram): + if isinstance(exe, (build.BuildTarget, dependencies.ExternalProgram)): + test_for_machine = exe.for_machine + else: # E.g. an external verifier or simulator program run on a generated executable. # Can always be run without a wrapper. - is_cross = False - if is_cross: + test_for_machine = MachineChoice.BUILD + is_cross = not self.environment.machines.matches_build_machine(test_for_machine) + if is_cross and self.environment.need_exe_wrapper(): exe_wrapper = self.environment.get_exe_wrapper() else: exe_wrapper = None - if mesonlib.for_windows(self.environment) or \ - mesonlib.for_cygwin(self.environment): + machine = self.environment.machines[exe.for_machine] + if machine.is_windows() or machine.is_cygwin(): extra_bdeps = [] if isinstance(exe, build.CustomTarget): extra_bdeps = exe.get_transitive_build_target_deps() - extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps, is_cross) + extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) else: extra_paths = [] cmd_args = [] @@ -811,15 +798,22 @@ class Backend: return deps def exe_object_to_cmd_array(self, exe): - if self.environment.is_cross_build() and \ - isinstance(exe, build.BuildTarget) and exe.is_cross: - if self.environment.exe_wrapper is None and self.environment.need_exe_wrapper(): - s = textwrap.dedent(''' - Can not use target {} as a generator because it is cross-built - and no exe wrapper is defined or needs_exe_wrapper is true. - You might want to set it to native instead.'''.format(exe.name)) - raise MesonException(s) if isinstance(exe, build.BuildTarget): + if exe.for_machine is not MachineChoice.BUILD: + if (self.environment.is_cross_build() and + self.environment.exe_wrapper is None and + self.environment.need_exe_wrapper()): + s = textwrap.dedent(''' + Cannot use target {} as a generator because it is built for the + host machine and no exe wrapper is defined or needs_exe_wrapper is + true. You might want to set `native: true` instead to build it for + the build machine.'''.format(exe.name)) + raise MesonException(s) + else: + mlog.warning(''' + Target {} is used as a generator, but is built for the host + machine. This means most cross builds will fail. You might want to + set `native: true` instead to build it for the build machine.'''.format(exe.name)) exe_arr = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe))] else: exe_arr = exe.get_command() diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index c919d8f..9f9574d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -29,9 +29,11 @@ from .. import build from .. import mlog from .. import dependencies from .. import compilers -from ..compilers import CompilerArgs, CCompiler, VisualStudioLikeCompiler, FortranCompiler +from ..compilers import Compiler, CompilerArgs, CCompiler, VisualStudioLikeCompiler, FortranCompiler from ..linkers import ArLinker -from ..mesonlib import File, MachineChoice, MesonException, OrderedSet, LibType +from ..mesonlib import ( + File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine +) from ..mesonlib import get_compiler_for_source, has_path_sep from .backends import CleanTrees from ..build import InvalidArguments @@ -202,6 +204,7 @@ class NinjaBackend(backends.Backend): self.fortran_deps = {} self.all_outputs = {} self.introspection_data = {} + self.created_llvm_ir_rule = PerMachine(False, False) def create_target_alias(self, to_target): # We need to use aliases for targets that might be used as directory @@ -219,7 +222,8 @@ class NinjaBackend(backends.Backend): def detect_vs_dep_prefix(self, tempfilename): '''VS writes its dependency in a locale dependent format. Detect the search prefix to use.''' - for compiler in self.environment.coredata.compilers.values(): + # TODO don't hard-code host + for compiler in self.environment.coredata.compilers.host.values(): # Have to detect the dependency format # IFort on windows is MSVC like, but doesn't have /showincludes @@ -314,10 +318,12 @@ int dummy; # http://clang.llvm.org/docs/JSONCompilationDatabase.html def generate_compdb(self): - pch_compilers = ['%s_PCH' % i for i in self.environment.coredata.compilers] - native_compilers = ['%s_COMPILER' % i for i in self.environment.coredata.compilers] - cross_compilers = ['%s_CROSS_COMPILER' % i for i in self.environment.coredata.cross_compilers] - ninja_compdb = [self.ninja_command, '-t', 'compdb'] + pch_compilers + native_compilers + cross_compilers + rules = [] + for for_machine in MachineChoice: + for lang in self.environment.coredata.compilers[for_machine]: + rules += [self.get_compiler_rule_name(lang, for_machine)] + rules += [self.get_pch_rule_name(lang, for_machine)] + ninja_compdb = [self.ninja_command, '-t', 'compdb'] + rules builddir = self.environment.get_build_dir() try: jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) @@ -663,13 +669,10 @@ int dummy; # the project, we need to set PATH so the DLLs are found. We use # a serialized executable wrapper for that and check if the # CustomTarget command needs extra paths first. - is_cross = self.environment.is_cross_build() and \ - self.environment.need_exe_wrapper() - if mesonlib.for_windows(self.environment) or \ - mesonlib.for_cygwin(self.environment): + machine = self.environment.machines[target.for_machine] + if machine.is_windows() or machine.is_cygwin(): extra_bdeps = target.get_transitive_build_target_deps() - extra_paths = self.determine_windows_extra_paths(target.command[0], - extra_bdeps, is_cross) + extra_paths = self.determine_windows_extra_paths(target.command[0], extra_bdeps) if extra_paths: serialize = True if serialize: @@ -846,9 +849,7 @@ int dummy; self.add_rule_comment(NinjaComment('Rules for compiling.')) self.generate_compile_rules() self.add_rule_comment(NinjaComment('Rules for linking.')) - if self.environment.is_cross_build(): - self.generate_static_link_rules(True) - self.generate_static_link_rules(False) + self.generate_static_link_rules() self.generate_dynamic_link_rules() self.add_rule_comment(NinjaComment('Other rules')) # Ninja errors out if you have deps = gcc but no depfile, so we must @@ -1014,10 +1015,10 @@ int dummy; for dep in target.get_external_deps(): commands.extend_direct(dep.get_link_args()) - commands += self.build.get_project_args(compiler, target.subproject, target.is_cross) - commands += self.build.get_global_args(compiler, target.is_cross) + commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) + commands += self.build.get_global_args(compiler, target.for_machine) - elem = NinjaBuildElement(self.all_outputs, outputs, 'cs_COMPILER', rel_srcs + generated_rel_srcs) + elem = NinjaBuildElement(self.all_outputs, outputs, self.get_compiler_rule_name('cs', target.for_machine), rel_srcs + generated_rel_srcs) elem.add_dep(deps) elem.add_item('ARGS', commands) self.add_build(elem) @@ -1028,8 +1029,8 @@ int dummy; def determine_single_java_compile_args(self, target, compiler): args = [] args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) - args += self.build.get_global_args(compiler, target.is_cross) - args += self.build.get_project_args(compiler, target.subproject, target.is_cross) + args += self.build.get_global_args(compiler, target.for_machine) + args += self.build.get_project_args(compiler, target.subproject, target.for_machine) args += target.get_java_args() args += compiler.get_output_args(self.get_target_private_dir(target)) args += target.get_classpath_args() @@ -1051,7 +1052,7 @@ int dummy; rel_src = src.rel_to_builddir(self.build_to_src) plain_class_path = src.fname[:-4] + 'class' rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path) - element = NinjaBuildElement(self.all_outputs, rel_obj, compiler.get_language() + '_COMPILER', rel_src) + element = NinjaBuildElement(self.all_outputs, rel_obj, self.compiler_to_rule_name(compiler), rel_src) element.add_dep(deps) element.add_item('ARGS', args) self.add_build(element) @@ -1248,7 +1249,7 @@ int dummy; extra_dep_files += dependency_vapis args += extra_args element = NinjaBuildElement(self.all_outputs, valac_outputs, - valac.get_language() + '_COMPILER', + self.compiler_to_rule_name(valac), all_files + dependency_vapis) element.add_item('ARGS', args) element.add_dep(extra_dep_files) @@ -1285,8 +1286,8 @@ int dummy; args += ['--crate-name', target.name] args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target)) args += rustc.get_debug_args(self.get_option_for_target('debug', target)) - args += self.build.get_global_args(rustc, target.is_cross) - args += self.build.get_project_args(rustc, target.subproject, target.is_cross) + args += self.build.get_global_args(rustc, target.for_machine) + args += self.build.get_project_args(rustc, target.subproject, target.for_machine) depfile = os.path.join(target.subdir, target.name + '.d') args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link'] args += target.get_extra_args('rust') @@ -1334,10 +1335,7 @@ int dummy; # installations for rpath_arg in rpath_args: args += ['-C', 'link-arg=' + rpath_arg + ':' + os.path.join(rustc.get_sysroot(), 'lib')] - crstr = '' - if target.is_cross: - crstr = '_CROSS' - compiler_name = 'rust%s_COMPILER' % crstr + compiler_name = self.get_compiler_rule_name('rust', target.for_machine) element = NinjaBuildElement(self.all_outputs, target_name, compiler_name, main_rust_file) if len(orderdeps) > 0: element.add_orderdep(orderdeps) @@ -1349,6 +1347,26 @@ int dummy; self.generate_shsym(target) self.create_target_source_introspection(target, rustc, args, [main_rust_file], []) + @staticmethod + def get_rule_suffix(for_machine: MachineChoice) -> str: + return PerMachine('_FOR_BUILD', '')[for_machine] + + @classmethod + def get_compiler_rule_name(cls, lang: str, for_machine: MachineChoice) -> str: + return '%s_COMPILER%s' % (lang, cls.get_rule_suffix(for_machine)) + + @classmethod + def get_pch_rule_name(cls, lang: str, for_machine: MachineChoice) -> str: + return '%s_PCH%s' % (lang, cls.get_rule_suffix(for_machine)) + + @classmethod + def compiler_to_rule_name(cls, compiler: Compiler) -> str: + return cls.get_compiler_rule_name(compiler.get_language(), compiler.for_machine) + + @classmethod + def compiler_to_pch_rule_name(cls, compiler: Compiler) -> str: + return cls.get_pch_rule_name(compiler.get_language(), compiler.for_machine) + def swift_module_file_name(self, target): return os.path.join(self.get_target_private_dir(target), self.target_swift_modulename(target) + '.swiftmodule') @@ -1417,8 +1435,8 @@ int dummy; compile_args += swiftc.get_optimization_args(self.get_option_for_target('optimization', target)) compile_args += swiftc.get_debug_args(self.get_option_for_target('debug', target)) compile_args += swiftc.get_module_args(module_name) - compile_args += self.build.get_project_args(swiftc, target.subproject, target.is_cross) - compile_args += self.build.get_global_args(swiftc, target.is_cross) + compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine) + compile_args += self.build.get_global_args(swiftc, target.for_machine) for i in reversed(target.get_include_dirs()): basedir = i.get_curdir() for d in i.get_incdirs(): @@ -1430,8 +1448,8 @@ int dummy; sargs = swiftc.get_include_args(srctreedir) compile_args += sargs link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))) - link_args += self.build.get_project_link_args(swiftc, target.subproject, target.is_cross) - link_args += self.build.get_global_link_args(swiftc, target.is_cross) + link_args += self.build.get_project_link_args(swiftc, target.subproject, target.for_machine) + link_args += self.build.get_global_link_args(swiftc, target.for_machine) rundir = self.get_target_private_dir(target) out_module_name = self.swift_module_file_name(target) in_module_files = self.determine_swift_dep_modules(target) @@ -1458,17 +1476,17 @@ int dummy; objects.append(oname) rel_objects.append(os.path.join(self.get_target_private_dir(target), oname)) + rulename = self.get_compiler_rule_name('swift', target.for_machine) + # Swiftc does not seem to be able to emit objects and module files in one go. - elem = NinjaBuildElement(self.all_outputs, rel_objects, - 'swift_COMPILER', - abssrc) + elem = NinjaBuildElement(self.all_outputs, rel_objects, rulename, abssrc) elem.add_dep(in_module_files + rel_generated) elem.add_dep(abs_headers) elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes) elem.add_item('RUNDIR', rundir) self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, out_module_name, - 'swift_COMPILER', + self.get_compiler_rule_name('swift', target.for_machine), abssrc) elem.add_dep(in_module_files + rel_generated) elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args()) @@ -1476,10 +1494,10 @@ int dummy; self.add_build(elem) if isinstance(target, build.StaticLibrary): elem = self.generate_link(target, self.get_target_filename(target), - rel_objects, self.build.static_linker) + rel_objects, self.build.static_linker[target.for_machine]) self.add_build(elem) elif isinstance(target, build.Executable): - elem = NinjaBuildElement(self.all_outputs, self.get_target_filename(target), 'swift_COMPILER', []) + elem = NinjaBuildElement(self.all_outputs, self.get_target_filename(target), rulename, []) elem.add_dep(rel_objects) elem.add_dep(link_deps) elem.add_item('ARGS', link_args + swiftc.get_std_exe_link_args() + objects + abs_link_deps) @@ -1490,61 +1508,49 @@ int dummy; # Introspection information self.create_target_source_introspection(target, swiftc, compile_args + header_imports + module_includes, relsrc, rel_generated) - def generate_static_link_rules(self, is_cross): + def generate_static_link_rules(self): num_pools = self.environment.coredata.backend_options['backend_max_links'].value - if 'java' in self.environment.coredata.compilers: - if not is_cross: - self.generate_java_link() - if is_cross: - if self.environment.is_cross_build(): - static_linker = self.build.static_cross_linker + if 'java' in self.environment.coredata.compilers.host: + self.generate_java_link() + for for_machine in MachineChoice: + static_linker = self.build.static_linker[for_machine] + if static_linker is None: + return + rule = 'STATIC_LINKER%s' % self.get_rule_suffix(for_machine) + cmdlist = [] + args = ['$in'] + # FIXME: Must normalize file names with pathlib.Path before writing + # them out to fix this properly on Windows. See: + # https://github.com/mesonbuild/meson/issues/1517 + # https://github.com/mesonbuild/meson/issues/1526 + if isinstance(static_linker, ArLinker) and not mesonlib.is_windows(): + # `ar` has no options to overwrite archives. It always appends, + # which is never what we want. Delete an existing library first if + # it exists. https://github.com/mesonbuild/meson/issues/1355 + cmdlist = execute_wrapper + [c.format('$out') for c in rmfile_prefix] + cmdlist += static_linker.get_exelist() + cmdlist += ['$LINK_ARGS'] + cmdlist += static_linker.get_output_args('$out') + description = 'Linking static target $out.' + if num_pools > 0: + pool = 'pool = link_pool' else: - static_linker = self.build.static_linker - crstr = '_CROSS' - else: - static_linker = self.build.static_linker - crstr = '' - if static_linker is None: - return - rule = 'STATIC%s_LINKER' % crstr - cmdlist = [] - args = ['$in'] - # FIXME: Must normalize file names with pathlib.Path before writing - # them out to fix this properly on Windows. See: - # https://github.com/mesonbuild/meson/issues/1517 - # https://github.com/mesonbuild/meson/issues/1526 - if isinstance(static_linker, ArLinker) and not mesonlib.is_windows(): - # `ar` has no options to overwrite archives. It always appends, - # which is never what we want. Delete an existing library first if - # it exists. https://github.com/mesonbuild/meson/issues/1355 - cmdlist = execute_wrapper + [c.format('$out') for c in rmfile_prefix] - cmdlist += static_linker.get_exelist() - cmdlist += ['$LINK_ARGS'] - cmdlist += static_linker.get_output_args('$out') - description = 'Linking static target $out.' - if num_pools > 0: - pool = 'pool = link_pool' - else: - pool = None - self.add_rule(NinjaRule(rule, cmdlist, args, description, - rspable=static_linker.can_linker_accept_rsp(), - extra=pool)) + pool = None + self.add_rule(NinjaRule(rule, cmdlist, args, description, + rspable=static_linker.can_linker_accept_rsp(), + extra=pool)) def generate_dynamic_link_rules(self): num_pools = self.environment.coredata.backend_options['backend_max_links'].value - ctypes = [(self.environment.coredata.compilers, False), - (self.environment.coredata.cross_compilers, True)] - for (complist, is_cross) in ctypes: + for for_machine in MachineChoice: + complist = self.environment.coredata.compilers[for_machine] for langname, compiler in complist.items(): if langname == 'java' \ or langname == 'vala' \ or langname == 'rust' \ or langname == 'cs': continue - crstr = '' - if is_cross: - crstr = '_CROSS' - rule = '%s%s_LINKER' % (langname, crstr) + rule = '%s_LINKER%s' % (langname, self.get_rule_suffix(for_machine)) command = compiler.get_linker_exelist() args = ['$ARGS'] + compiler.get_linker_output_args('$out') + ['$in', '$LINK_ARGS'] description = 'Linking target $out.' @@ -1568,14 +1574,14 @@ int dummy; self.add_rule(NinjaRule(symrule, symcmd, [], syndesc, extra=synstat)) def generate_java_compile_rule(self, compiler): - rule = '%s_COMPILER' % compiler.get_language() + rule = self.compiler_to_rule_name(compiler) invoc = [ninja_quote(i) for i in compiler.get_exelist()] command = invoc + ['$ARGS', '$in'] description = 'Compiling Java object $in.' self.add_rule(NinjaRule(rule, command, [], description)) def generate_cs_compile_rule(self, compiler): - rule = '%s_COMPILER' % compiler.get_language() + rule = self.compiler_to_rule_name(compiler) invoc = [ninja_quote(i) for i in compiler.get_exelist()] command = invoc args = ['$ARGS', '$in'] @@ -1584,17 +1590,14 @@ int dummy; rspable=mesonlib.is_windows())) def generate_vala_compile_rules(self, compiler): - rule = '%s_COMPILER' % compiler.get_language() + rule = self.compiler_to_rule_name(compiler) invoc = [ninja_quote(i) for i in compiler.get_exelist()] command = invoc + ['$ARGS', '$in'] description = 'Compiling Vala source $in.' self.add_rule(NinjaRule(rule, command, [], description, extra='restat = 1')) - def generate_rust_compile_rules(self, compiler, is_cross): - crstr = '' - if is_cross: - crstr = '_CROSS' - rule = '%s%s_COMPILER' % (compiler.get_language(), crstr) + def generate_rust_compile_rules(self, compiler): + rule = self.compiler_to_rule_name(compiler) invoc = [ninja_quote(i) for i in compiler.get_exelist()] command = invoc + ['$ARGS', '$in'] description = 'Compiling Rust source $in.' @@ -1604,7 +1607,7 @@ int dummy; depfile=depfile)) def generate_swift_compile_rules(self, compiler): - rule = '%s_COMPILER' % compiler.get_language() + rule = self.compiler_to_rule_name(compiler) full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ '--internal', 'dirchanger', @@ -1626,44 +1629,41 @@ https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.add_rule(NinjaRule(rule, cmd, [], 'Dep hack', extra='restat = 1')) - def generate_llvm_ir_compile_rule(self, compiler, is_cross): - if getattr(self, 'created_llvm_ir_rule', False): + def generate_llvm_ir_compile_rule(self, compiler): + if self.created_llvm_ir_rule[compiler.for_machine]: return - rule = 'llvm_ir{}_COMPILER'.format('_CROSS' if is_cross else '') + rule = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) command = [ninja_quote(i) for i in compiler.get_exelist()] args = ['$ARGS'] + compiler.get_output_args('$out') + compiler.get_compile_only_args() + ['$in'] description = 'Compiling LLVM IR object $in.' self.add_rule(NinjaRule(rule, command, args, description, rspable=compiler.can_linker_accept_rsp())) - self.created_llvm_ir_rule = True + self.created_llvm_ir_rule[compiler.for_machine] = True - def generate_compile_rule_for(self, langname, compiler, is_cross): + def generate_compile_rule_for(self, langname, compiler): if langname == 'java': - if not is_cross: + if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_java_compile_rule(compiler) return if langname == 'cs': - if not is_cross: + if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_cs_compile_rule(compiler) return if langname == 'vala': - if not is_cross: + if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_vala_compile_rules(compiler) return if langname == 'rust': - self.generate_rust_compile_rules(compiler, is_cross) + self.generate_rust_compile_rules(compiler) return if langname == 'swift': - if not is_cross: + if self.environment.machines.matches_build_machine(compiler.for_machine): self.generate_swift_compile_rules(compiler) return - if is_cross: - crstr = '_CROSS' - else: - crstr = '' + crstr = self.get_rule_suffix(compiler.for_machine) if langname == 'fortran': self.generate_fortran_dep_hack(crstr) - rule = '%s%s_COMPILER' % (langname, crstr) + rule = self.get_compiler_rule_name(langname, compiler.for_machine) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] for d in depargs: @@ -1684,14 +1684,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) rspable=compiler.can_linker_accept_rsp(), deps=deps, depfile=depfile)) - def generate_pch_rule_for(self, langname, compiler, is_cross): + def generate_pch_rule_for(self, langname, compiler): if langname != 'c' and langname != 'cpp': return - if is_cross: - crstr = '_CROSS' - else: - crstr = '' - rule = '%s%s_PCH' % (langname, crstr) + rule = self.compiler_to_pch_rule_name(compiler) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] @@ -1715,18 +1711,13 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) depfile=depfile)) def generate_compile_rules(self): - for langname, compiler in self.environment.coredata.compilers.items(): - if compiler.get_id() == 'clang': - self.generate_llvm_ir_compile_rule(compiler, False) - self.generate_compile_rule_for(langname, compiler, False) - self.generate_pch_rule_for(langname, compiler, False) - if self.environment.is_cross_build(): - cclist = self.environment.coredata.cross_compilers - for langname, compiler in cclist.items(): + for for_machine in MachineChoice: + clist = self.environment.coredata.compilers[for_machine] + for langname, compiler in clist.items(): if compiler.get_id() == 'clang': - self.generate_llvm_ir_compile_rule(compiler, True) - self.generate_compile_rule_for(langname, compiler, True) - self.generate_pch_rule_for(langname, compiler, True) + self.generate_llvm_ir_compile_rule(compiler) + self.generate_compile_rule_for(langname, compiler) + self.generate_pch_rule_for(langname, compiler) def generate_generator_list_rules(self, target): # CustomTargets have already written their rules and @@ -1820,7 +1811,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) Find all module and submodule made available in a Fortran code file. """ compiler = None - for lang, c in self.environment.coredata.compilers.items(): + # TODO other compilers + for lang, c in self.environment.coredata.compilers.host.items(): if lang == 'fortran': compiler = c break @@ -1881,7 +1873,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) return mod_files def get_cross_stdlib_args(self, target, compiler): - if not target.is_cross: + if self.environment.machines.matches_build_machine(target.for_machine): return [] if not self.environment.properties.host.has_stdlib(compiler.language): return [] @@ -1964,7 +1956,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) src_filename = src obj_basename = src_filename.replace('/', '_').replace('\\', '_') rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) - rel_obj += '.' + self.environment.get_object_suffix() + rel_obj += '.' + self.environment.machines[target.for_machine].get_object_suffix() commands += self.get_compile_debugfile_args(compiler, target, rel_obj) if isinstance(src, File) and src.is_built: rel_src = src.fname @@ -1973,7 +1965,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) else: raise InvalidArguments('Invalid source type: {!r}'.format(src)) # Write the Ninja build command - compiler_name = 'llvm_ir{}_COMPILER'.format('_CROSS' if target.is_cross else '') + compiler_name = self.get_compiler_rule_name('llvm_ir', compiler.for_machine) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) # Convert from GCC-style link argument naming to the naming used by the # current compiler. @@ -2161,10 +2153,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) arr.append(i) pch_dep = arr - crstr = '' - if target.is_cross: - crstr = '_CROSS' - compiler_name = '%s%s_COMPILER' % (compiler.get_language(), crstr) + compiler_name = self.compiler_to_rule_name(compiler) extra_deps = [] if compiler.get_language() == 'fortran': # Can't read source file to scan for deps if it's generated later @@ -2181,6 +2170,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) compiler.module_name_to_filename(modname)) if srcfile == src: + crstr = self.get_rule_suffix(target.for_machine) depelem = NinjaBuildElement(self.all_outputs, modfile, 'FORTRAN_DEP_HACK' + crstr, rel_obj) self.add_build(depelem) commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) @@ -2268,10 +2258,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) def generate_pch(self, target, header_deps=None): header_deps = header_deps if header_deps is not None else [] - cstr = '' pch_objects = [] - if target.is_cross: - cstr = '_CROSS' for lang in ['c', 'cpp']: pch = target.get_pch(lang) if not pch: @@ -2293,7 +2280,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) (commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0]) extradep = None pch_objects += objs - rulename = compiler.get_language() + cstr + '_PCH' + rulename = self.compiler_to_pch_rule_name(compiler) elem = NinjaBuildElement(self.all_outputs, dst, rulename, src) if extradep is not None: elem.add_dep(extradep) @@ -2310,11 +2297,12 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) symname = os.path.join(targetdir, target_name + '.symbols') elem = NinjaBuildElement(self.all_outputs, symname, 'SHSYM', target_file) if self.environment.is_cross_build(): - elem.add_item('CROSS', '--cross-host=' + self.environment.machines.host.system) + elem.add_item('CROSS', '--cross-host=' + self.environment.machines[target.for_machine].system) self.add_build(elem) def get_cross_stdlib_link_args(self, target, linker): - if isinstance(target, build.StaticLibrary) or not target.is_cross: + if isinstance(target, build.StaticLibrary) or \ + self.environment.machines.matches_build_machine(target.for_machine): return [] if not self.environment.properties.host.has_stdlib(linker.language): return [] @@ -2455,10 +2443,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) linker_base = linker.get_language() # Fixme. if isinstance(target, build.SharedLibrary): self.generate_shsym(target) - crstr = '' - if target.is_cross: - crstr = '_CROSS' - linker_rule = linker_base + crstr + '_LINKER' + crstr = self.get_rule_suffix(target.for_machine) + linker_rule = linker_base + '_LINKER' + crstr # Create an empty commands list, and start adding link arguments from # various sources in the order in which they must override each other # starting from hard-coded defaults followed by build options and so on. @@ -2492,20 +2478,15 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) if not isinstance(target, build.StaticLibrary): commands += self.get_link_whole_args(linker, target) - if self.environment.is_cross_build() and not target.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - if not isinstance(target, build.StaticLibrary): # Add link args added using add_project_link_arguments() - commands += self.build.get_project_link_args(linker, target.subproject, target.is_cross) + commands += self.build.get_project_link_args(linker, target.subproject, target.for_machine) # Add link args added using add_global_link_arguments() # These override per-project link arguments - commands += self.build.get_global_link_args(linker, target.is_cross) + commands += self.build.get_global_link_args(linker, target.for_machine) # Link args added from the env: LDFLAGS. We want these to override # all the defaults but not the per-target link args. - commands += self.environment.coredata.get_external_link_args(for_machine, linker.get_language()) + commands += self.environment.coredata.get_external_link_args(target.for_machine, linker.get_language()) # Now we will add libraries and library paths from various sources @@ -2544,7 +2525,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. - commands += linker.get_option_link_args(self.environment.coredata.compiler_options[for_machine]) + commands += linker.get_option_link_args(self.environment.coredata.compiler_options[target.for_machine]) dep_targets = [] dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal)) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index ef08fdb..86a7f83 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -27,7 +27,7 @@ from .. import mlog from .. import compilers from ..compilers import CompilerArgs from ..mesonlib import ( - MesonException, MachineChoice, File, python_command, replace_if_different + MesonException, File, python_command, replace_if_different ) from ..environment import Environment, build_filename @@ -720,7 +720,7 @@ class Vs2010Backend(backends.Backend): # No source files, only objects, but we still need a compiler, so # return a found compiler if len(target.objects) > 0: - for lang, c in self.environment.coredata.compilers.items(): + for lang, c in self.environment.coredata.compilers[target.for_machine].items(): if lang in ('c', 'cpp'): return c raise MesonException('Could not find a C or C++ compiler. MSVC can only build C/C++ projects.') @@ -883,27 +883,23 @@ class Vs2010Backend(backends.Backend): file_inc_dirs = dict((lang, []) for lang in target.compilers) # The order in which these compile args are added must match # generate_single_compile() and generate_basic_compiler_args() - if self.environment.is_cross_build() and not target.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST for l, comp in target.compilers.items(): if l in file_args: file_args[l] += compilers.get_base_compile_args(self.get_base_options_for_target(target), comp) - file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options[for_machine]) + file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options[target.for_machine]) # Add compile args added using add_project_arguments() - for l, args in self.build.projects_args.get(target.subproject, {}).items(): + for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items(): if l in file_args: file_args[l] += args # Add compile args added using add_global_arguments() # These override per-project arguments - for l, args in self.build.global_args.items(): + for l, args in self.build.global_args[target.for_machine].items(): if l in file_args: file_args[l] += args # Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these # to override all the defaults, but not the per-target compile args. - for key, opt in self.environment.coredata.compiler_options[for_machine].items(): + for key, opt in self.environment.coredata.compiler_options[target.for_machine].items(): l, suffix = key.split('_', 1) if suffix == 'args' and l in file_args: file_args[l] += opt.value @@ -1083,14 +1079,14 @@ class Vs2010Backend(backends.Backend): options = self.environment.coredata.base_options extra_link_args += compiler.get_std_shared_module_link_args(options) # Add link args added using add_project_link_arguments() - extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.is_cross) + extra_link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine) # Add link args added using add_global_link_arguments() # These override per-project link arguments - extra_link_args += self.build.get_global_link_args(compiler, target.is_cross) + extra_link_args += self.build.get_global_link_args(compiler, target.for_machine) # Link args added from the env: LDFLAGS, or the cross file. We want # these to override all the defaults but not the per-target link # args. - extra_link_args += self.environment.coredata.get_external_link_args(for_machine, compiler.get_language()) + extra_link_args += self.environment.coredata.get_external_link_args(target.for_machine, compiler.get_language()) # Only non-static built targets need link args and link dependencies extra_link_args += target.link_args # External deps must be last because target link libraries may depend on them. @@ -1113,7 +1109,7 @@ class Vs2010Backend(backends.Backend): # to be after all internal and external libraries so that unresolved # symbols from those can be found here. This is needed when the # *_winlibs that we want to link to are static mingw64 libraries. - extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options[for_machine]) + extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options[compiler.for_machine]) (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) # Add more libraries to be linked if needed diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index be22c78..7c66250 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -742,10 +742,10 @@ class XCodeBackend(backends.Backend): if lang not in langnamemap: continue # Add compile args added using add_project_arguments() - pargs = self.build.projects_args.get(target.subproject, {}).get(lang, []) + pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, []) # Add compile args added using add_global_arguments() # These override per-project arguments - gargs = self.build.global_args.get(lang, []) + gargs = self.build.global_args[target.for_machine].get(lang, []) targs = target.get_extra_args(lang) args = pargs + gargs + targs if args: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 3394459..763e5c9 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -25,10 +25,9 @@ from . import environment from . import dependencies from . import mlog from .mesonlib import ( - File, MesonException, listify, extract_as_list, OrderedSet, - typeslistify, stringlistify, classify_unity_sources, - get_filenames_templates_dict, substitute_values, - for_windows, for_darwin, for_cygwin, for_android, has_path_sep + File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, + extract_as_list, typeslistify, stringlistify, classify_unity_sources, + get_filenames_templates_dict, substitute_values, has_path_sep, ) from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes, get_macos_dylib_install_name from .interpreterbase import FeatureNew @@ -114,21 +113,16 @@ class Build: self.environment = environment self.projects = {} self.targets = OrderedDict() - self.global_args = {} - self.projects_args = {} - self.global_link_args = {} - self.projects_link_args = {} - self.cross_global_args = {} - self.cross_projects_args = {} - self.cross_global_link_args = {} - self.cross_projects_link_args = {} + self.global_args = PerMachine({}, {}) + self.projects_args = PerMachine({}, {}) + self.global_link_args = PerMachine({}, {}) + self.projects_link_args = PerMachine({}, {}) self.tests = [] self.benchmarks = [] self.headers = [] self.man = [] self.data = [] - self.static_linker = None - self.static_cross_linker = None + self.static_linker = PerMachine(None, None) self.subprojects = {} self.subproject_dir = '' self.install_scripts = [] @@ -137,7 +131,7 @@ class Build: self.install_dirs = [] self.dep_manifest_name = None self.dep_manifest = {} - self.cross_stdlibs = {} + self.stdlibs = PerMachine({}, {}) self.test_setups = {} # type: typing.Dict[str, TestSetup] self.test_setup_default_name = None self.find_overrides = {} @@ -157,12 +151,8 @@ class Build: self.__dict__[k] = v def ensure_static_linker(self, compiler): - if self.static_linker is None and compiler.needs_static_linker(): - self.static_linker = self.environment.detect_static_linker(compiler) - - def ensure_static_cross_linker(self, compiler): - if self.static_cross_linker is None and compiler.needs_static_linker(): - self.static_cross_linker = self.environment.detect_static_linker(compiler) + if self.static_linker[compiler.for_machine] is None and compiler.needs_static_linker(): + self.static_linker[compiler.for_machine] = self.environment.detect_static_linker(compiler) def get_project(self): return self.projects[''] @@ -191,23 +181,23 @@ class Build: def get_install_subdirs(self): return self.install_dirs - def get_global_args(self, compiler, for_cross): - d = self.cross_global_args if for_cross else self.global_args + def get_global_args(self, compiler, for_machine): + d = self.global_args[for_machine] return d.get(compiler.get_language(), []) - def get_project_args(self, compiler, project, for_cross): - d = self.cross_projects_args if for_cross else self.projects_args + def get_project_args(self, compiler, project, for_machine): + d = self.projects_args[for_machine] args = d.get(project) if not args: return [] return args.get(compiler.get_language(), []) - def get_global_link_args(self, compiler, for_cross): - d = self.cross_global_link_args if for_cross else self.global_link_args + def get_global_link_args(self, compiler, for_machine): + d = self.global_link_args[for_machine] return d.get(compiler.get_language(), []) - def get_project_link_args(self, compiler, project, for_cross): - d = self.cross_projects_link_args if for_cross else self.projects_link_args + def get_project_link_args(self, compiler, project, for_machine): + d = self.projects_link_args[for_machine] link_args = d.get(project) if not link_args: @@ -336,7 +326,7 @@ class EnvironmentVariables: return env class Target: - def __init__(self, name, subdir, subproject, build_by_default): + def __init__(self, name, subdir, subproject, build_by_default, for_machine: MachineChoice): if has_path_sep(name): # Fix failing test 53 when this becomes an error. mlog.warning('''Target "%s" has a path separator in its name. @@ -346,6 +336,7 @@ a hard error in the future.''' % name) self.subdir = subdir self.subproject = subproject self.build_by_default = build_by_default + self.for_machine = for_machine self.install = False self.build_always_stale = False self.option_overrides = {} @@ -438,9 +429,8 @@ a hard error in the future.''' % name) class BuildTarget(Target): known_kwargs = known_build_target_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): - super().__init__(name, subdir, subproject, True) - self.is_cross = is_cross + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): + super().__init__(name, subdir, subproject, True, for_machine) unity_opt = environment.coredata.get_builtin_option('unity') self.is_unity = unity_opt == 'on' or (unity_opt == 'subprojects' and subproject != '') self.environment = environment @@ -483,7 +473,7 @@ class BuildTarget(Target): raise InvalidArguments('Build target %s has no sources.' % name) self.process_compilers_late() self.validate_sources() - self.validate_cross_install(environment) + self.validate_install(environment) self.check_module_linking() def __lt__(self, other): @@ -493,9 +483,12 @@ class BuildTarget(Target): repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.filename) - def validate_cross_install(self, environment): - if environment.is_cross_build() and not self.is_cross and self.need_install: - raise InvalidArguments('Tried to install a natively built target in a cross build.') + def validate_install(self, environment): + if self.for_machine is MachineChoice.BUILD and self.need_install: + if environment.is_cross_build(): + raise InvalidArguments('Tried to install a target for the build machine in a cross build.') + else: + mlog.warning('Installing target build for the build machine. This will fail in a cross build.') def check_unknown_kwargs(self, kwargs): # Override this method in derived classes that have more @@ -562,10 +555,7 @@ class BuildTarget(Target): which compiler to use if one hasn't been selected already. """ # Populate list of compilers - if self.is_cross: - compilers = self.environment.coredata.cross_compilers - else: - compilers = self.environment.coredata.compilers + compilers = self.environment.coredata.compilers[self.for_machine] # did user override clink_langs for this target? link_langs = [self.link_language] if self.link_language else clink_langs @@ -602,10 +592,7 @@ class BuildTarget(Target): if not self.sources and not self.generated and not self.objects: return # Populate list of compilers - if self.is_cross: - compilers = self.environment.coredata.cross_compilers - else: - compilers = self.environment.coredata.compilers + compilers = self.environment.coredata.compilers[self.for_machine] # Pre-existing sources sources = list(self.sources) # All generated sources @@ -928,13 +915,14 @@ This will become a hard error in a future Meson release.''') # You can't disable PIC on OS X. The compiler ignores -fno-PIC. # PIC is always on for Windows (all code is position-independent # since library loading is done differently) - if for_darwin(self.environment) or for_windows(self.environment): + m = self.environment.machines[self.for_machine] + if m.is_darwin() or m.is_windows(): self.pic = True else: self.pic = self._extract_pic_pie(kwargs, 'pic') if isinstance(self, Executable): # Executables must be PIE on Android - if for_android(self.is_cross, self.environment): + if self.environment.machines[self.for_machine].is_android(): self.pie = True else: self.pie = self._extract_pic_pie(kwargs, 'pie') @@ -1073,8 +1061,12 @@ You probably should put it in link_with instead.''') msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if not isinstance(t, (CustomTarget, CustomTargetIndex)) and self.is_cross != t.is_cross: - raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name)) + if self.for_machine is not t.for_machine: + msg = 'Tried to mix libraries for machines {1} and {2} in target {!r}'.format(self.name, self.for_machine, t.for_machine) + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') self.link_targets.append(t) def link_whole(self, target): @@ -1090,8 +1082,12 @@ You probably should put it in link_with instead.''') msg = "Can't link non-PIC static library {!r} into shared library {!r}. ".format(t.name, self.name) msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if not isinstance(t, (CustomTarget, CustomTargetIndex)) and self.is_cross != t.is_cross: - raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name)) + if self.for_machine is not t.for_machine: + msg = 'Tried to mix libraries for machines {1} and {2} in target {!r}'.format(self.name, self.for_machine, t.for_machine) + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') self.link_whole_targets.append(t) def add_pch(self, language, pchlist): @@ -1192,10 +1188,7 @@ You probably should put it in link_with instead.''') ''' # Populate list of all compilers, not just those being used to compile # sources in this target - if self.is_cross: - all_compilers = self.environment.coredata.cross_compilers - else: - all_compilers = self.environment.coredata.compilers + all_compilers = self.environment.coredata.compilers[self.for_machine] # Languages used by dependencies dep_langs = self.get_langs_used_by_deps() # Pick a compiler based on the language priority-order @@ -1253,7 +1246,7 @@ You probably should put it in link_with instead.''') ''' for link_target in self.link_targets: if isinstance(link_target, SharedModule): - if for_darwin(self.environment): + if self.environment.machines[self.for_machine].is_darwin(): raise MesonException('''target links against shared modules. This is not permitted on OSX''') else: @@ -1425,19 +1418,19 @@ class GeneratedList: class Executable(BuildTarget): known_kwargs = known_exe_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'executable' if 'pie' not in kwargs and 'b_pie' in environment.coredata.base_options: kwargs['pie'] = environment.coredata.base_options['b_pie'].value - super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) # Unless overridden, executables have no suffix or prefix. Except on # Windows and with C#/Mono executables where the suffix is 'exe' if not hasattr(self, 'prefix'): self.prefix = '' if not hasattr(self, 'suffix'): + machine = environment.machines[for_machine] # Executable for Windows or C#/Mono - if (for_windows(environment) or - for_cygwin(environment) or 'cs' in self.compilers): + if machine.is_windows() or machine.is_cygwin() or 'cs' in self.compilers: self.suffix = 'exe' elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('arm') or 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('arm')): @@ -1446,7 +1439,7 @@ class Executable(BuildTarget): 'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('ccrx')): self.suffix = 'abs' else: - self.suffix = '' + self.suffix = environment.machines[for_machine].get_exe_suffix() self.filename = self.name if self.suffix: self.filename += '.' + self.suffix @@ -1475,7 +1468,8 @@ class Executable(BuildTarget): implib_basename = self.name + '.exe' if not isinstance(kwargs.get('implib', False), bool): implib_basename = kwargs['implib'] - if for_windows(environment) or for_cygwin(environment): + m = environment.machines[for_machine] + if m.is_windows() or m.is_cygwin(): self.vs_import_filename = '{0}.lib'.format(implib_basename) self.gcc_import_filename = 'lib{0}.a'.format(implib_basename) if self.get_using_msvc(): @@ -1515,11 +1509,11 @@ class Executable(BuildTarget): class StaticLibrary(BuildTarget): known_kwargs = known_stlib_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'static library' if 'pic' not in kwargs and 'b_staticpic' in environment.coredata.base_options: kwargs['pic'] = environment.coredata.base_options['b_staticpic'].value - super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.') if 'rust' in self.compilers: @@ -1575,7 +1569,7 @@ class StaticLibrary(BuildTarget): class SharedLibrary(BuildTarget): known_kwargs = known_shlib_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'shared library' self.soversion = None self.ltversion = None @@ -1588,7 +1582,7 @@ class SharedLibrary(BuildTarget): self.vs_import_filename = None # The import library that GCC would generate (and prefer) self.gcc_import_filename = None - super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) if 'rust' in self.compilers: # If no crate type is specified, or it's the generic lib type, use dylib if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': @@ -1602,7 +1596,7 @@ class SharedLibrary(BuildTarget): if not hasattr(self, 'suffix'): self.suffix = None self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}' - self.determine_filenames(is_cross, environment) + self.determine_filenames(environment) def get_link_deps_mapping(self, prefix, environment): result = {} @@ -1619,7 +1613,7 @@ class SharedLibrary(BuildTarget): def get_default_install_dir(self, environment): return environment.get_shared_lib_dir() - def determine_filenames(self, is_cross, env): + def determine_filenames(self, env): """ See https://github.com/mesonbuild/meson/pull/417 for details. @@ -1652,7 +1646,7 @@ class SharedLibrary(BuildTarget): # C, C++, Swift, Vala # Only Windows uses a separate import library for linking # For all other targets/platforms import_filename stays None - elif for_windows(env): + elif env.machines[self.for_machine].is_windows(): suffix = 'dll' self.vs_import_filename = '{0}{1}.lib'.format(self.prefix if self.prefix is not None else '', self.name) self.gcc_import_filename = '{0}{1}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) @@ -1677,7 +1671,7 @@ class SharedLibrary(BuildTarget): self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' - elif for_cygwin(env): + elif env.machines[self.for_machine].is_cygwin(): suffix = 'dll' self.gcc_import_filename = '{0}{1}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) # Shared library is of the form cygfoo.dll @@ -1689,7 +1683,7 @@ class SharedLibrary(BuildTarget): self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' - elif for_darwin(env): + elif env.machines[self.for_machine].is_darwin(): prefix = 'lib' suffix = 'dylib' # On macOS, the filename can only contain the major version @@ -1699,7 +1693,7 @@ class SharedLibrary(BuildTarget): else: # libfoo.dylib self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' - elif for_android(env): + elif env.machines[self.for_machine].is_android(): prefix = 'lib' suffix = 'so' # Android doesn't support shared_library versioning @@ -1764,7 +1758,7 @@ class SharedLibrary(BuildTarget): def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) - if not for_android(self.environment): + if not self.environment.machines[self.for_machine].is_android(): supports_versioning = True else: supports_versioning = False @@ -1884,12 +1878,12 @@ class SharedLibrary(BuildTarget): class SharedModule(SharedLibrary): known_kwargs = known_shmod_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): if 'version' in kwargs: raise MesonException('Shared modules must not specify the version kwarg.') if 'soversion' in kwargs: raise MesonException('Shared modules must not specify the soversion kwarg.') - super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) self.typename = 'shared module' def get_default_install_dir(self, environment): @@ -1917,7 +1911,8 @@ class CustomTarget(Target): def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False): self.typename = 'custom' - super().__init__(name, subdir, subproject, False) + # TODO expose keyword arg to make MachineChoice.HOST configurable + super().__init__(name, subdir, subproject, False, MachineChoice.HOST) self.dependencies = [] self.extra_depends = [] self.depend_files = [] # Files that this target depends on but are not on the command line. @@ -2171,7 +2166,8 @@ class CustomTarget(Target): class RunTarget(Target): def __init__(self, name, command, args, dependencies, subdir, subproject): self.typename = 'run' - super().__init__(name, subdir, subproject, False) + # These don't produce output artifacts + super().__init__(name, subdir, subproject, False, MachineChoice.BUILD) self.command = command self.args = args self.dependencies = dependencies @@ -2212,9 +2208,9 @@ class RunTarget(Target): class Jar(BuildTarget): known_kwargs = known_jar_kwargs - def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): + def __init__(self, name, subdir, subproject, for_machine: MachineChoice, sources, objects, environment, kwargs): self.typename = 'jar' - super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) + super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs) for s in self.sources: if not s.endswith('.java'): raise InvalidArguments('Jar source %s is not a java file.' % s) @@ -2234,7 +2230,7 @@ class Jar(BuildTarget): def get_java_args(self): return self.java_args - def validate_cross_install(self, environment): + def validate_install(self, environment): # All jar targets are installable. pass @@ -2260,6 +2256,7 @@ class CustomTargetIndex: self.typename = 'custom' self.target = target self.output = output + self.for_machine = target.for_machine def __repr__(self): return '<CustomTargetIndex: {!r}[{}]>'.format( diff --git a/mesonbuild/cmake/client.py b/mesonbuild/cmake/client.py index f4b549b..93985e9 100644 --- a/mesonbuild/cmake/client.py +++ b/mesonbuild/cmake/client.py @@ -18,6 +18,7 @@ from .common import CMakeException from ..environment import Environment from ..dependencies.base import CMakeDependency, ExternalProgram +from ..mesonlib import MachineChoice from .. import mlog from contextlib import contextmanager from subprocess import Popen, PIPE, TimeoutExpired @@ -473,8 +474,8 @@ class CMakeClient: def startup(self) -> None: if self.proc is not None: raise CMakeException('The CMake server was already started') - - cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env) + for_machine = MachineChoice.HOST # TODO make parameter + cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env, for_machine) if cmake_exe is None or cmake_exe is False: raise CMakeException('Unable to find CMake') assert(isinstance(cmake_exe, ExternalProgram)) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index ec17906..435f8d2 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -20,6 +20,7 @@ from .client import CMakeClient, RequestCMakeInputs, RequestConfigure, RequestCo from .. import mlog from ..build import Build from ..environment import Environment +from ..mesonlib import MachineChoice from ..mparser import Token, BaseNode, CodeBlockNode, FunctionNode, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, StringNode, IdNode, MethodNode from ..backend.backends import Backend from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes @@ -300,8 +301,9 @@ class CMakeInterpreter: self.generated_targets = {} def configure(self, extra_cmake_options: List[str]) -> None: + for_machine = MachineChoice.HOST # TODO make parameter # Find CMake - cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env) + cmake_exe, cmake_vers, _ = CMakeDependency.find_cmake_binary(self.env, for_machine) if cmake_exe is None or cmake_exe is False: raise CMakeException('Unable to find CMake') assert(isinstance(cmake_exe, ExternalProgram)) @@ -312,7 +314,7 @@ class CMakeInterpreter: cmake_args = cmake_exe.get_command() # Map meson compiler to CMake variables - for lang, comp in self.env.coredata.compilers.items(): + for lang, comp in self.env.coredata.compilers[for_machine].items(): if lang not in language_map: continue cmake_lang = language_map[lang] diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 3e536ea..3b58a07 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -16,7 +16,7 @@ import os.path import typing from .. import coredata -from ..mesonlib import MesonException, version_compare, mlog +from ..mesonlib import MachineChoice, MesonException, mlog, version_compare from .c_function_attributes import C_FUNC_ATTRIBUTES from .clike import CLikeCompiler @@ -47,11 +47,11 @@ class CCompiler(CLikeCompiler, Compiler): except KeyError: raise MesonException('Unknown function attribute "{}"'.format(name)) - def __init__(self, exelist, version, is_cross: bool, + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrapper: typing.Optional[str] = None, **kwargs): # If a child ObjC or CPP class has already set it, don't set it ourselves self.language = 'c' - Compiler.__init__(self, exelist, version, **kwargs) + Compiler.__init__(self, exelist, version, for_machine, **kwargs) CLikeCompiler.__init__(self, is_cross, exe_wrapper) def get_no_stdinc_args(self): @@ -76,8 +76,8 @@ class CCompiler(CLikeCompiler, Compiler): class ClangCCompiler(ClangCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -119,8 +119,8 @@ class ClangCCompiler(ClangCompiler, CCompiler): class ArmclangCCompiler(ArmclangCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ArmclangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -148,8 +148,8 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler): class GnuCCompiler(GnuCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -191,14 +191,14 @@ class GnuCCompiler(GnuCompiler, CCompiler): class PGICCompiler(PGICompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) PGICompiler.__init__(self, compiler_type) class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None, **kwargs): - GnuCCompiler.__init__(self, exelist, version, compiler_type, is_cross, exe_wrapper, defines, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + GnuCCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, defines, **kwargs) ElbrusCompiler.__init__(self, compiler_type, defines) # It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports. @@ -223,8 +223,8 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) IntelGnuLikeCompiler.__init__(self, compiler_type) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark'] @@ -267,14 +267,14 @@ class VisualStudioLikeCCompilerMixin: class VisualStudioCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap, target: str): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target: str): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) self.id = 'msvc' class ClangClCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap, target): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) self.id = 'clang-cl' @@ -285,8 +285,8 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM __have_warned = False - def __init__(self, exelist, version, is_cross, exe_wrap, target): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) IntelVisualStudioLikeCompiler.__init__(self, target) def get_options(self): @@ -310,8 +310,8 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM class ArmCCompiler(ArmCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ArmCompiler.__init__(self, compiler_type) def get_options(self): @@ -329,8 +329,8 @@ class ArmCCompiler(ArmCompiler, CCompiler): return args class CcrxCCompiler(CcrxCompiler, CCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) CcrxCompiler.__init__(self, compiler_type) # Override CCompiler.get_always_args diff --git a/mesonbuild/compilers/clike.py b/mesonbuild/compilers/clike.py index 968685b..8941931 100644 --- a/mesonbuild/compilers/clike.py +++ b/mesonbuild/compilers/clike.py @@ -30,7 +30,7 @@ import typing from pathlib import Path from .. import mesonlib -from ..mesonlib import MachineChoice, LibType +from ..mesonlib import LibType from .. import mlog from . import compilers @@ -277,7 +277,7 @@ class CLikeCompiler: m = env.machines[self.for_machine] if m.is_windows() or m.is_cygwin(): return ['-Wl,--export-all-symbols'] - elif mesonlib.for_darwin(env): + elif env.machines[self.for_machine].is_darwin(): return [] else: return ['-Wl,-export-dynamic'] @@ -384,13 +384,9 @@ class CLikeCompiler: # Select a CRT if needed since we're linking if mode == 'link': args += self.get_linker_debug_crt_args() - if env.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST if mode in {'compile', 'preprocess'}: # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env - sys_args = env.coredata.get_external_args(for_machine, self.language) + sys_args = env.coredata.get_external_args(self.for_machine, self.language) # Apparently it is a thing to inject linker flags both # via CFLAGS _and_ LDFLAGS, even though the former are # also used during linking. These flags can break @@ -399,7 +395,7 @@ class CLikeCompiler: args += cleaned_sys_args elif mode == 'link': # Add LDFLAGS from the env - args += env.coredata.get_external_link_args(for_machine, self.language) + args += env.coredata.get_external_link_args(self.for_machine, self.language) return args def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'): @@ -885,7 +881,7 @@ class CLikeCompiler: for p in prefixes: for s in suffixes: patterns.append(p + '{}.' + s) - if shared and mesonlib.for_openbsd(env): + if shared and env.machines[self.for_machine].is_openbsd(): # Shared libraries on OpenBSD can be named libfoo.so.X.Y: # https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs # @@ -912,9 +908,9 @@ class CLikeCompiler: else: prefixes = ['lib', ''] # Library suffixes and prefixes - if mesonlib.for_darwin(env): + if env.machines[self.for_machine].is_darwin(): shlibext = ['dylib', 'so'] - elif mesonlib.for_windows(env): + elif env.machines[self.for_machine].is_windows(): # FIXME: .lib files can be import or static so we should read the # file, figure out which one it is, and reject the wrong kind. if isinstance(self, compilers.VisualStudioLikeCompiler): @@ -923,7 +919,7 @@ class CLikeCompiler: shlibext = ['dll.a', 'lib', 'dll'] # Yep, static libraries can also be foo.lib stlibext += ['lib'] - elif mesonlib.for_cygwin(env): + elif env.machines[self.for_machine].is_cygwin(): shlibext = ['dll', 'dll.a'] prefixes = ['cyg'] + prefixes else: @@ -1074,11 +1070,7 @@ class CLikeCompiler: commands = self.get_exelist() + ['-v', '-E', '-'] commands += self.get_always_args() # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env - if env.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - commands += env.coredata.get_external_args(for_machine, self.language) + commands += env.coredata.get_external_args(self.for_machine, self.language) mlog.debug('Finding framework path by running: ', ' '.join(commands), '\n') os_env = os.environ.copy() os_env['LC_ALL'] = 'C' @@ -1127,12 +1119,14 @@ class CLikeCompiler: return self.find_framework_impl(name, env, extra_dirs, allow_system) def thread_flags(self, env): - if mesonlib.for_haiku(env) or mesonlib.for_darwin(env): + host_m = env.machines[self.for_machine] + if host_m.is_haiku() or host_m.is_darwin(): return [] return ['-pthread'] def thread_link_flags(self, env): - if mesonlib.for_haiku(env) or mesonlib.for_darwin(env): + host_m = env.machines[self.for_machine] + if host_m.is_haiku() or host_m.is_darwin(): return [] return ['-pthread'] @@ -1190,8 +1184,8 @@ class CLikeCompiler: def has_func_attribute(self, name, env): # Just assume that if we're not on windows that dllimport and dllexport # don't work - if not (mesonlib.for_windows(env) or - mesonlib.for_cygwin(env)): + m = env.machines[self.for_machine] + if not (m.is_windows() or m.is_cygwin()): if name in ['dllimport', 'dllexport']: return False, False diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 3ad80fe..0a228b4 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -21,7 +21,7 @@ from .. import coredata from .. import mlog from .. import mesonlib from ..mesonlib import ( - EnvironmentException, MesonException, OrderedSet, + EnvironmentException, MachineChoice, MesonException, OrderedSet, version_compare, Popen_safe ) from ..envconfig import ( @@ -871,7 +871,7 @@ class Compiler: # manually searched. internal_libs = () - def __init__(self, exelist, version, **kwargs): + def __init__(self, exelist, version, for_machine: MachineChoice, **kwargs): if isinstance(exelist, str): self.exelist = [exelist] elif isinstance(exelist, list): @@ -889,6 +889,7 @@ class Compiler: self.full_version = kwargs['full_version'] else: self.full_version = None + self.for_machine = for_machine self.base_options = [] def __repr__(self): @@ -2183,7 +2184,7 @@ class ClangCompiler(GnuLikeCompiler): class ArmclangCompiler: def __init__(self, compiler_type): - if not self.is_cross: + if self.is_cross: raise EnvironmentException('armclang supports only cross-compilation.') # Check whether 'armlink.exe' is available in path self.linker_exe = 'armlink.exe' diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 253525a..e43d839 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -19,7 +19,7 @@ import typing from .. import coredata from .. import mlog -from ..mesonlib import MesonException, version_compare +from ..mesonlib import MesonException, MachineChoice, version_compare from .compilers import ( gnu_winlibs, @@ -55,11 +55,11 @@ class CPPCompiler(CLikeCompiler, Compiler): except KeyError: raise MesonException('Unknown function attribute "{}"'.format(name)) - def __init__(self, exelist, version, is_cross: bool, + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str] = None, **kwargs): # If a child ObjCPP class has already set it, don't set it ourselves self.language = 'cpp' - Compiler.__init__(self, exelist, version, **kwargs) + Compiler.__init__(self, exelist, version, for_machine, **kwargs) CLikeCompiler.__init__(self, is_cross, exe_wrap) def get_display_language(self): @@ -147,8 +147,8 @@ class CPPCompiler(CLikeCompiler, Compiler): class ClangCPPCompiler(ClangCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -185,8 +185,8 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler): class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) ArmclangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -221,8 +221,8 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): class GnuCPPCompiler(GnuCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap, defines, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrap, defines, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -272,14 +272,14 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): class PGICPPCompiler(PGICompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) PGICompiler.__init__(self, compiler_type) class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None, **kwargs): - GnuCPPCompiler.__init__(self, exelist, version, compiler_type, is_cross, exe_wrapper, defines, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + GnuCPPCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, defines, **kwargs) ElbrusCompiler.__init__(self, compiler_type, defines) # It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98. @@ -308,8 +308,8 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrap, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) IntelGnuLikeCompiler.__init__(self, compiler_type) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', @@ -441,8 +441,8 @@ class CPP11AsCPP14Mixin: class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap, target): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like self.id = 'msvc' @@ -474,8 +474,8 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi return args class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) self.id = 'clang-cl' @@ -486,8 +486,8 @@ class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, Vi class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): - def __init__(self, exelist, version, is_cross, exe_wrap, target): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrap, target): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap) IntelVisualStudioLikeCompiler.__init__(self, target) def get_options(self): @@ -497,8 +497,8 @@ class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLike class ArmCPPCompiler(ArmCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrap=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) ArmCompiler.__init__(self, compiler_type) def get_options(self): @@ -525,8 +525,8 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler): class CcrxCPPCompiler(CcrxCompiler, CPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap=None, **kwargs): - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrap=None, **kwargs): + CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrap, **kwargs) CcrxCompiler.__init__(self, compiler_type) # Override CCompiler.get_always_args diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index c6355f2..8069ab1 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -17,7 +17,7 @@ import os.path, subprocess from ..mesonlib import EnvironmentException from ..mesonlib import is_windows -from .compilers import Compiler, mono_buildtype_args +from .compilers import Compiler, MachineChoice, mono_buildtype_args cs_optimization_args = {'0': [], 'g': [], @@ -28,9 +28,9 @@ cs_optimization_args = {'0': [], } class CsCompiler(Compiler): - def __init__(self, exelist, version, comp_id, runner=None): + def __init__(self, exelist, version, for_machine: MachineChoice, comp_id, runner=None): self.language = 'cs' - super().__init__(exelist, version) + super().__init__(exelist, version, for_machine) self.id = comp_id self.is_cross = False self.runner = runner @@ -143,14 +143,14 @@ class CsCompiler(Compiler): return cs_optimization_args[optimization_level] class MonoCompiler(CsCompiler): - def __init__(self, exelist, version): - super().__init__(exelist, version, 'mono', + def __init__(self, exelist, version, for_machine: MachineChoice): + super().__init__(exelist, version, for_machine, 'mono', 'mono') class VisualStudioCsCompiler(CsCompiler): - def __init__(self, exelist, version): - super().__init__(exelist, version, 'csc') + def __init__(self, exelist, version, for_machine: MachineChoice): + super().__init__(exelist, version, for_machine, 'csc') def get_buildtype_args(self, buildtype): res = mono_buildtype_args[buildtype] diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 51a1300..3c38c09 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -15,15 +15,15 @@ import re, os.path from .. import mlog -from ..mesonlib import EnvironmentException, Popen_safe +from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, cuda_debug_args, CompilerType, get_gcc_soname_args) class CudaCompiler(Compiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None): if not hasattr(self, 'language'): self.language = 'cuda' - super().__init__(exelist, version) + super().__init__(exelist, version, for_machine) self.is_cross = is_cross self.exe_wrapper = exe_wrapper self.id = 'nvcc' diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 46cc054..b7bc49a 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -73,11 +73,10 @@ class DCompiler(Compiler): 'mtd': ['-mscrtlib=libcmtd'], } - def __init__(self, exelist, version, is_cross, arch, **kwargs): + def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): self.language = 'd' - super().__init__(exelist, version, **kwargs) + super().__init__(exelist, version, for_machine, **kwargs) self.id = 'unknown' - self.is_cross = is_cross self.arch = arch def sanity_check(self, work_dir, environment): @@ -308,17 +307,12 @@ class DCompiler(Compiler): # Add link flags needed to find dependencies args += d.get_link_args() - if env.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - if mode == 'compile': # Add DFLAGS from the env - args += env.coredata.get_external_args(for_machine, self.language) + args += env.coredata.get_external_args(self.for_machine, self.language) elif mode == 'link': # Add LDFLAGS from the env - args += env.coredata.get_external_link_args(for_machine, self.language) + args += env.coredata.get_external_link_args(self.for_machine, self.language) # extra_args must override all other arguments, so we add them last args += extra_args return args @@ -494,8 +488,8 @@ class DCompiler(Compiler): return ['-pthread'] class GnuDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, arch, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, arch, **kwargs) + def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): + DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'gcc' default_warn_args = ['-Wall', '-Wdeprecated'] self.warn_args = {'0': [], @@ -557,8 +551,8 @@ class GnuDCompiler(DCompiler): return gnu_optimization_args[optimization_level] class LLVMDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, arch, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, arch, **kwargs) + def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): + DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'llvm' self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt'] @@ -595,8 +589,8 @@ class LLVMDCompiler(DCompiler): class DmdDCompiler(DCompiler): - def __init__(self, exelist, version, is_cross, arch, **kwargs): - DCompiler.__init__(self, exelist, version, is_cross, arch, **kwargs) + def __init__(self, exelist, version, for_machine: MachineChoice, arch, **kwargs): + DCompiler.__init__(self, exelist, version, for_machine, arch, **kwargs) self.id = 'dmd' self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt'] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 5de1de4..fe23b6b 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -40,9 +40,9 @@ from mesonbuild.mesonlib import ( class FortranCompiler(CLikeCompiler, Compiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs): self.language = 'fortran' - Compiler.__init__(self, exelist, version, **kwargs) + Compiler.__init__(self, exelist, version, for_machine, **kwargs) CLikeCompiler.__init__(self, is_cross, exe_wrapper) self.id = 'unknown' @@ -62,12 +62,8 @@ class FortranCompiler(CLikeCompiler, Compiler): source_name.write_text('print *, "Fortran compilation is working."; end') - if environment.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - extra_flags = environment.coredata.get_external_args(for_machine, self.language) - extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) + extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) extra_flags += self.get_always_args() # %% build the test executable pc = subprocess.Popen(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)]) @@ -167,8 +163,8 @@ class FortranCompiler(CLikeCompiler, Compiler): class GnuFortranCompiler(GnuCompiler, FortranCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None, **kwargs): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall'] self.warn_args = {'0': [], @@ -189,13 +185,13 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler): return ['-lgfortran', '-lm'] class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None, **kwargs): - GnuFortranCompiler.__init__(self, exelist, version, compiler_type, is_cross, exe_wrapper, defines, **kwargs) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs): + GnuFortranCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, defines, **kwargs) ElbrusCompiler.__init__(self, compiler_type, defines) class G95FortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) self.id = 'g95' default_warn_args = ['-Wall'] self.warn_args = {'0': [], @@ -212,8 +208,8 @@ class G95FortranCompiler(FortranCompiler): class SunFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) self.id = 'sun' def get_dependency_gen_args(self, outtarget, outfile): @@ -236,9 +232,9 @@ class SunFortranCompiler(FortranCompiler): class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp') - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler IntelGnuLikeCompiler.__init__(self, CompilerType.ICC_STANDARD) @@ -293,8 +289,8 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): class PathScaleFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) self.id = 'pathscale' default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -307,8 +303,8 @@ class PathScaleFortranCompiler(FortranCompiler): class PGIFortranCompiler(PGICompiler, FortranCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) PGICompiler.__init__(self, compiler_type) def language_stdlib_only_link_flags(self) -> List[str]: @@ -316,8 +312,8 @@ class PGIFortranCompiler(PGICompiler, FortranCompiler): '-lpgf90rtl', '-lpgftnrtl', '-lrt'] class FlangFortranCompiler(ClangCompiler, FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) ClangCompiler.__init__(self, CompilerType.CLANG_STANDARD) self.id = 'flang' default_warn_args = ['-Minform=inform'] @@ -327,8 +323,8 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler): '3': default_warn_args} class Open64FortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) self.id = 'open64' default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -341,8 +337,8 @@ class Open64FortranCompiler(FortranCompiler): class NAGFortranCompiler(FortranCompiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): - FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags): + FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags) self.id = 'nagfor' def get_warn_args(self, level): diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index 5d7f865..ea1fa0f 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -14,14 +14,14 @@ import os.path, shutil, subprocess -from ..mesonlib import EnvironmentException +from ..mesonlib import EnvironmentException, MachineChoice from .compilers import Compiler, java_buildtype_args class JavaCompiler(Compiler): - def __init__(self, exelist, version): + def __init__(self, exelist, version, for_machine: MachineChoice): self.language = 'java' - super().__init__(exelist, version) + super().__init__(exelist, version, for_machine) self.id = 'unknown' self.is_cross = False self.javarunner = 'java' diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index 55311ed..f9ca793 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -21,9 +21,9 @@ from .clike import CLikeCompiler from .compilers import Compiler, ClangCompiler, GnuCompiler class ObjCCompiler(CLikeCompiler, Compiler): - def __init__(self, exelist, version, is_cross: bool, exe_wrap: typing.Optional[str]): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]): self.language = 'objc' - Compiler.__init__(self, exelist, version) + Compiler.__init__(self, exelist, version, for_machine) CLikeCompiler.__init__(self, is_cross, exe_wrap) def get_display_language(self): @@ -33,15 +33,11 @@ class ObjCCompiler(CLikeCompiler, Compiler): # TODO try to use sanity_check_impl instead of duplicated code source_name = os.path.join(work_dir, 'sanitycheckobjc.m') binary_name = os.path.join(work_dir, 'sanitycheckobjc') - if environment.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - extra_flags = environment.coredata.get_external_args(for_machine, self.language) + extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) if self.is_cross: extra_flags += self.get_compile_only_args() else: - extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) with open(source_name, 'w') as ofile: ofile.write('#import<stdio.h>\n' 'int main(int argc, char **argv) { return 0; }\n') @@ -59,8 +55,8 @@ class ObjCCompiler(CLikeCompiler, Compiler): class GnuObjCCompiler(GnuCompiler, ObjCCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None): - ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None): + ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -70,8 +66,8 @@ class GnuObjCCompiler(GnuCompiler, ObjCCompiler): class ClangObjCCompiler(ClangCompiler, ObjCCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None): - ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None): + ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 6743f89..2e81b4c 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -21,9 +21,9 @@ from .clike import CLikeCompiler from .compilers import Compiler, ClangCompiler, GnuCompiler class ObjCPPCompiler(CLikeCompiler, Compiler): - def __init__(self, exelist, version, is_cross: bool, exe_wrap: typing.Optional[str]): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]): self.language = 'objcpp' - Compiler.__init__(self, exelist, version) + Compiler.__init__(self, exelist, version, for_machine) CLikeCompiler.__init__(self, is_cross, exe_wrap) def get_display_language(self): @@ -33,15 +33,11 @@ class ObjCPPCompiler(CLikeCompiler, Compiler): # TODO try to use sanity_check_impl instead of duplicated code source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm') binary_name = os.path.join(work_dir, 'sanitycheckobjcpp') - if environment.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - extra_flags = environment.coredata.get_external_args(for_machine, self.language) + extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) if self.is_cross: extra_flags += self.get_compile_only_args() else: - extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) with open(source_name, 'w') as ofile: ofile.write('#import<stdio.h>\n' 'class MyClass;' @@ -60,8 +56,8 @@ class ObjCPPCompiler(CLikeCompiler, Compiler): class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, defines=None): - ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None): + ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) GnuCompiler.__init__(self, compiler_type, defines) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], @@ -71,8 +67,8 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler): - def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None): - ObjCPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None): + ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper) ClangCompiler.__init__(self, compiler_type) default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'] self.warn_args = {'0': [], diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 410125a..17b7e3b 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -14,7 +14,7 @@ import subprocess, os.path -from ..mesonlib import EnvironmentException, Popen_safe +from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe from .compilers import Compiler, rust_buildtype_args, clike_debug_args @@ -27,12 +27,12 @@ rust_optimization_args = {'0': [], } class RustCompiler(Compiler): - def __init__(self, exelist, version, is_cross, exe_wrapper=None): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None): self.language = 'rust' - super().__init__(exelist, version) - self.is_cross = is_cross + super().__init__(exelist, version, for_machine) self.exe_wrapper = exe_wrapper self.id = 'rustc' + self.is_cross = is_cross def needs_static_linker(self): return False diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index 17705ac..0038264 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -27,12 +27,12 @@ swift_optimization_args = {'0': [], } class SwiftCompiler(Compiler): - def __init__(self, exelist, version): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross): self.language = 'swift' - super().__init__(exelist, version) + super().__init__(exelist, version, for_machine) self.version = version self.id = 'llvm' - self.is_cross = False + self.is_cross = is_cross def get_linker_exelist(self): return self.exelist[:] @@ -102,15 +102,11 @@ class SwiftCompiler(Compiler): src = 'swifttest.swift' source_name = os.path.join(work_dir, src) output_name = os.path.join(work_dir, 'swifttest') - if environment.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - extra_flags = environment.coredata.get_external_args(for_machine, self.language) + extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) if self.is_cross: extra_flags += self.get_compile_only_args() else: - extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) with open(source_name, 'w') as ofile: ofile.write('''print("Swift compilation is working.") ''') diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index c0b2a68..0a612ae 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -20,12 +20,12 @@ from ..mesonlib import EnvironmentException, MachineChoice, version_compare from .compilers import Compiler class ValaCompiler(Compiler): - def __init__(self, exelist, version): + def __init__(self, exelist, version, for_machine: MachineChoice, is_cross): self.language = 'vala' - super().__init__(exelist, version) + super().__init__(exelist, version, for_machine) self.version = version + self.is_cross = is_cross self.id = 'valac' - self.is_cross = False self.base_options = ['b_colorout'] def name_string(self): @@ -87,15 +87,11 @@ class ValaCompiler(Compiler): def sanity_check(self, work_dir, environment): code = 'class MesonSanityCheck : Object { }' - if environment.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - extra_flags = environment.coredata.get_external_args(for_machine, self.language) + extra_flags = environment.coredata.get_external_args(self.for_machine, self.language) if self.is_cross: extra_flags += self.get_compile_only_args() else: - extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language) with self.cached_compile(code, environment.coredata, extra_args=extra_flags, mode='compile') as p: if p.returncode != 0: msg = 'Vala compiler {!r} can not compile programs' \ @@ -114,11 +110,7 @@ class ValaCompiler(Compiler): # no extra dirs are specified. if not extra_dirs: code = 'class MesonFindLibrary : Object { }' - if env.is_cross_build() and not self.is_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - args = env.coredata.get_external_args(for_machine, self.language) + args = env.coredata.get_external_args(self.for_machine, self.language) vapi_args = ['--pkg', libname] args += vapi_args with self.cached_compile(code, env.coredata, extra_args=args, mode='compile') as p: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 173bdc7..9984d1c 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -365,13 +365,11 @@ class CoreData: self.compiler_options = PerMachine({}, {}) self.base_options = {} # : Dict[str, UserOption] self.cross_files = self.__load_config_files(options.cross_file, 'cross') - self.compilers = OrderedDict() - self.cross_compilers = OrderedDict() + self.compilers = PerMachine(OrderedDict(), OrderedDict()) build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache] - self.compiler_check_cache = OrderedDict() # Only to print a warning if it changes between Meson invocations. self.config_files = self.__load_config_files(options.native_file, 'native') @@ -681,35 +679,20 @@ class CoreData: self.set_options(options, subproject) - def process_new_compilers(self, lang: str, comp, cross_comp, env): + def process_new_compiler(self, lang: str, comp, env): from . import compilers - self.compilers[lang] = comp - if cross_comp is not None: - self.cross_compilers[lang] = cross_comp - - # Native compiler always exist so always add its options. - new_options_for_build = comp.get_and_default_options(env.properties.build) - if cross_comp is not None: - new_options_for_host = cross_comp.get_and_default_options(env.properties.host) - else: - new_options_for_host = comp.get_and_default_options(env.properties.host) - - opts_machines_list = [ - (new_options_for_build, MachineChoice.BUILD), - (new_options_for_host, MachineChoice.HOST), - ] + self.compilers[comp.for_machine][lang] = comp optprefix = lang + '_' - for new_options, for_machine in opts_machines_list: - for k, o in new_options.items(): - if not k.startswith(optprefix): - raise MesonException('Internal error, %s has incorrect prefix.' % k) - # prefixed compiler options affect just this machine - opt_prefix = for_machine.get_prefix() - if opt_prefix + k in env.cmd_line_options: - o.set_value(env.cmd_line_options[opt_prefix + k]) - self.compiler_options[for_machine].setdefault(k, o) + for k, o in comp.get_and_default_options(env.properties[comp.for_machine]).items(): + if not k.startswith(optprefix): + raise MesonException('Internal error, %s has incorrect prefix.' % k) + # prefixed compiler options affect just this machine + opt_prefix = comp.for_machine.get_prefix() + if opt_prefix + k in env.cmd_line_options: + o.set_value(env.cmd_line_options[opt_prefix + k]) + self.compiler_options[comp.for_machine].setdefault(k, o) enabled_opts = [] for optname in comp.base_options: diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 9a14232..4c0d410 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -239,10 +239,13 @@ class InternalDependency(Dependency): final_link_args, final_libraries, final_whole_libraries, final_sources, final_deps) +class HasNativeKwarg: + def __init__(self, kwargs): + self.for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST -class ExternalDependency(Dependency): +class ExternalDependency(Dependency, HasNativeKwarg): def __init__(self, type_name, environment, language, kwargs): - super().__init__(type_name, kwargs) + Dependency.__init__(self, type_name, kwargs) self.env = environment self.name = type_name # default self.is_found = False @@ -255,18 +258,12 @@ class ExternalDependency(Dependency): self.static = kwargs.get('static', False) if not isinstance(self.static, bool): raise DependencyException('Static keyword must be boolean') - # Is this dependency for cross-compilation? - if 'native' in kwargs and self.env.is_cross_build(): - self.want_cross = not kwargs['native'] - else: - self.want_cross = self.env.is_cross_build() + # Is this dependency to be run on the build platform? + HasNativeKwarg.__init__(self, kwargs) self.clib_compiler = None # Set the compiler that will be used by this dependency # This is only used for configuration checks - if self.want_cross: - compilers = self.env.coredata.cross_compilers - else: - compilers = self.env.coredata.compilers + compilers = self.env.coredata.compilers[self.for_machine] # Set the compiler for this dependency if a language is specified, # else try to pick something that looks usable. if self.language: @@ -561,18 +558,13 @@ class PkgConfigDependency(ExternalDependency): # stored in the pickled coredata and recovered. self.pkgbin = None - if not self.want_cross and environment.is_cross_build(): - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - # Create an iterator of options def search(): # Lookup in cross or machine file. - potential_pkgpath = environment.binaries[for_machine].lookup_entry('pkgconfig') + potential_pkgpath = environment.binaries[self.for_machine].lookup_entry('pkgconfig') if potential_pkgpath is not None: mlog.debug('Pkg-config binary for {} specified from cross file, native file, ' - 'or env var as {}'.format(for_machine, potential_pkgpath)) + 'or env var as {}'.format(self.for_machine, potential_pkgpath)) yield ExternalProgram.from_entry('pkgconfig', potential_pkgpath) # We never fallback if the user-specified option is no good, so # stop returning options. @@ -580,42 +572,42 @@ class PkgConfigDependency(ExternalDependency): mlog.debug('Pkg-config binary missing from cross or native file, or env var undefined.') # Fallback on hard-coded defaults. # TODO prefix this for the cross case instead of ignoring thing. - if environment.machines.matches_build_machine(for_machine): + if environment.machines.matches_build_machine(self.for_machine): for potential_pkgpath in environment.default_pkgconfig: mlog.debug('Trying a default pkg-config fallback at', potential_pkgpath) yield ExternalProgram(potential_pkgpath, silent=True) # Only search for pkg-config for each machine the first time and store # the result in the class definition - if PkgConfigDependency.class_pkgbin[for_machine] is False: - mlog.debug('Pkg-config binary for %s is cached as not found.' % for_machine) - elif PkgConfigDependency.class_pkgbin[for_machine] is not None: - mlog.debug('Pkg-config binary for %s is cached.' % for_machine) + if PkgConfigDependency.class_pkgbin[self.for_machine] is False: + mlog.debug('Pkg-config binary for %s is cached as not found.' % self.for_machine) + elif PkgConfigDependency.class_pkgbin[self.for_machine] is not None: + mlog.debug('Pkg-config binary for %s is cached.' % self.for_machine) else: - assert PkgConfigDependency.class_pkgbin[for_machine] is None - mlog.debug('Pkg-config binary for %s is not cached.' % for_machine) + assert PkgConfigDependency.class_pkgbin[self.for_machine] is None + mlog.debug('Pkg-config binary for %s is not cached.' % self.for_machine) for potential_pkgbin in search(): mlog.debug('Trying pkg-config binary {} for machine {} at {}' - .format(potential_pkgbin.name, for_machine, potential_pkgbin.command)) + .format(potential_pkgbin.name, self.for_machine, potential_pkgbin.command)) version_if_ok = self.check_pkgconfig(potential_pkgbin) if not version_if_ok: continue if not self.silent: mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()), '(%s)' % version_if_ok) - PkgConfigDependency.class_pkgbin[for_machine] = potential_pkgbin + PkgConfigDependency.class_pkgbin[self.for_machine] = potential_pkgbin break else: if not self.silent: mlog.log('Found Pkg-config:', mlog.red('NO')) # Set to False instead of None to signify that we've already # searched for it and not found it - PkgConfigDependency.class_pkgbin[for_machine] = False + PkgConfigDependency.class_pkgbin[self.for_machine] = False - self.pkgbin = PkgConfigDependency.class_pkgbin[for_machine] + self.pkgbin = PkgConfigDependency.class_pkgbin[self.for_machine] if self.pkgbin is False: self.pkgbin = None - msg = 'Pkg-config binary for machine %s not found. Giving up.' % for_machine + msg = 'Pkg-config binary for machine %s not found. Giving up.' % self.for_machine if self.required: raise DependencyException(msg) else: @@ -665,12 +657,7 @@ class PkgConfigDependency(ExternalDependency): else: env = env.copy() - if not self.want_cross and self.env.is_cross_build(): - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - - extra_paths = self.env.coredata.builtins_per_machine[for_machine]['pkg_config_path'].value + extra_paths = self.env.coredata.builtins_per_machine[self.for_machine]['pkg_config_path'].value new_pkg_config_path = ':'.join([p for p in extra_paths]) mlog.debug('PKG_CONFIG_PATH: ' + new_pkg_config_path) env['PKG_CONFIG_PATH'] = new_pkg_config_path @@ -1059,7 +1046,7 @@ class CMakeDependency(ExternalDependency): # List of successfully found modules self.found_modules = [] - self.cmakebin, self.cmakevers, for_machine = self.find_cmake_binary(environment, self.want_cross, self.silent) + self.cmakebin, self.cmakevers, for_machine = self.find_cmake_binary(environment, self.for_machine, self.silent) if self.cmakebin is False: self.cmakebin = None msg = 'No CMake binary for machine %s not found. Giving up.' % for_machine @@ -1068,9 +1055,9 @@ class CMakeDependency(ExternalDependency): mlog.debug(msg) return - if CMakeDependency.class_cmakeinfo[for_machine] is None: - CMakeDependency.class_cmakeinfo[for_machine] = self._get_cmake_info() - self.cmakeinfo = CMakeDependency.class_cmakeinfo[for_machine] + if CMakeDependency.class_cmakeinfo[self.for_machine] is None: + CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info() + self.cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine] if self.cmakeinfo is None: raise self._gen_exception('Unable to obtain CMake system information') @@ -1082,24 +1069,16 @@ class CMakeDependency(ExternalDependency): if cm_path: cm_args.append('-DCMAKE_MODULE_PATH=' + ';'.join(cm_path)) - pref_path = self.env.coredata.builtins_per_machine[for_machine]['cmake_prefix_path'].value + pref_path = self.env.coredata.builtins_per_machine[self.for_machine]['cmake_prefix_path'].value if pref_path: cm_args.append('-DCMAKE_PREFIX_PATH={}'.format(';'.join(pref_path))) - if not self._preliminary_find_check(name, cm_path, pref_path, environment.machines[for_machine]): + if not self._preliminary_find_check(name, cm_path, pref_path, environment.machines[self.for_machine]): return self._detect_dep(name, modules, cm_args) - @staticmethod - def find_cmake_binary(environment: Environment, want_cross: bool = False, silent: bool = False) -> Tuple[str, str, MachineChoice]: - # When finding dependencies for cross-compiling, we don't care about - # the 'native' CMake binary - # TODO: Test if this works as expected - if environment.is_cross_build() and not want_cross: - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST - + @classmethod + def find_cmake_binary(cls, environment: Environment, for_machine: MachineChoice, silent: bool = False) -> Tuple[str, str, MachineChoice]: # Create an iterator of options def search(): # Lookup in cross or machine file. @@ -1130,7 +1109,7 @@ class CMakeDependency(ExternalDependency): for potential_cmakebin in search(): mlog.debug('Trying CMake binary {} for machine {} at {}' .format(potential_cmakebin.name, for_machine, potential_cmakebin.command)) - version_if_ok = CMakeDependency.check_cmake(potential_cmakebin) + version_if_ok = cls.check_cmake(potential_cmakebin) if not version_if_ok: continue if not silent: @@ -2098,6 +2077,8 @@ class DubDependency(ExternalDependency): class ExternalProgram: windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd') + # An 'ExternalProgram' always runs on the build machine + for_machine = MachineChoice.BUILD def __init__(self, name: str, command: typing.Optional[typing.List[str]] = None, silent: bool = False, search_dir: typing.Optional[str] = None): @@ -2479,7 +2460,7 @@ def get_dep_identifier(name, kwargs) -> Tuple: identifier = (name, ) for key, value in kwargs.items(): # 'version' is irrelevant for caching; the caller must check version matches - # 'native' is handled above with `want_cross` + # 'native' is handled above with `for_machine` # 'required' is irrelevant for caching; the caller handles it separately # 'fallback' subprojects cannot be cached -- they must be initialized # 'default_options' is only used in fallback case @@ -2520,12 +2501,9 @@ def find_external_dependency(name, env, kwargs): # display the dependency name with correct casing display_name = display_name_map.get(lname, lname) - # if this isn't a cross-build, it's uninteresting if native: is used or not - if not env.is_cross_build(): - type_text = 'Dependency' - else: - type_text = 'Native' if kwargs.get('native', False) else 'Cross' - type_text += ' dependency' + for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST + + type_text = PerMachine('Build-time', 'Run-time')[for_machine] + ' dependency' # build a list of dependency methods to try candidates = _build_external_dependency_list(name, env, kwargs) @@ -2648,12 +2626,12 @@ def _build_external_dependency_list(name, env: Environment, kwargs: Dict[str, An return candidates -def strip_system_libdirs(environment, link_args): +def strip_system_libdirs(environment, for_machine: MachineChoice, link_args): """Remove -L<system path> arguments. leaving these in will break builds where a user has a version of a library in the system path, and a different version not in the system path if they want to link against the non-system path version. """ - exclude = {'-L{}'.format(p) for p in environment.get_compiler_system_dirs()} + exclude = {'-L{}'.format(p) for p in environment.get_compiler_system_dirs(for_machine)} return [l for l in link_args if l not in exclude] diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index a955b6a..5c9e0b5 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -123,13 +123,13 @@ class BoostDependency(ExternalDependency): self.libdir = os.environ['BOOST_LIBRARYDIR'] if self.boost_root is None: - if mesonlib.for_windows(self.env): + if self.env.machines[self.for_machine].is_windows(): self.boost_roots = self.detect_win_roots() else: self.boost_roots = self.detect_nix_roots() if self.incdir is None: - if mesonlib.for_windows(self.env): + if self.env.machines[self.for_machine].is_windows(): self.incdir = self.detect_win_incdir() else: self.incdir = self.detect_nix_incdir() @@ -268,7 +268,7 @@ class BoostDependency(ExternalDependency): pass # 2. Fall back to the old method else: - if mesonlib.for_windows(self.env): + if self.env.machines[self.for_machine].is_windows(): self.detect_lib_modules_win() else: self.detect_lib_modules_nix() @@ -289,8 +289,8 @@ class BoostDependency(ExternalDependency): def compiler_tag(self): tag = None - compiler = self.env.detect_cpp_compiler(self.want_cross) - if mesonlib.for_windows(self.env): + compiler = self.env.detect_cpp_compiler(self.for_machine) + if self.env.machines[self.for_machine].is_windows(): if compiler.get_id() in ['msvc', 'clang-cl']: comp_ts_version = compiler.get_toolset_version() compiler_ts = comp_ts_version.split('.') @@ -304,10 +304,10 @@ class BoostDependency(ExternalDependency): if not self.is_multithreading: return '' - if mesonlib.for_darwin(self.env): + if self.env.machines[self.for_machine].is_darwin(): # - Mac: requires -mt for multithreading, so should not fall back to non-mt libraries. return '-mt' - elif mesonlib.for_windows(self.env): + elif self.env.machines[self.for_machine].is_windows(): # - Windows: requires -mt for multithreading, so should not fall back to non-mt libraries. return '-mt' else: @@ -323,12 +323,12 @@ class BoostDependency(ExternalDependency): def arch_tag(self): # currently only applies to windows msvc installed binaries - if self.env.detect_cpp_compiler(self.want_cross).get_id() not in ['msvc', 'clang-cl']: + if self.env.detect_cpp_compiler(self.for_machine).get_id() not in ['msvc', 'clang-cl']: return '' # pre-compiled binaries only added arch tag for versions > 1.64 if float(self.version) < 1.65: return '' - arch = detect_cpu_family(self.env.coredata.compilers) + arch = detect_cpu_family(self.env.coredata.compilers.host) if arch == 'x86': return '-x32' elif arch == 'x86_64': @@ -340,16 +340,16 @@ class BoostDependency(ExternalDependency): # FIXME - how to handle different distributions, e.g. for Mac? Currently we handle homebrew and macports, but not fink. def abi_tags(self): - if mesonlib.for_windows(self.env): + if self.env.machines[self.for_machine].is_windows(): return [self.versioned_abi_tag(), self.threading_tag()] else: return [self.threading_tag()] def sourceforge_dir(self): - if self.env.detect_cpp_compiler(self.want_cross).get_id() != 'msvc': + if self.env.detect_cpp_compiler(self.for_machine).get_id() != 'msvc': return None - comp_ts_version = self.env.detect_cpp_compiler(self.want_cross).get_toolset_version() - arch = detect_cpu_family(self.env.coredata.compilers) + comp_ts_version = self.env.detect_cpp_compiler(self.for_machine).get_toolset_version() + arch = detect_cpu_family(self.env.coredata.compilers.host) if arch == 'x86': return 'lib32-msvc-{}'.format(comp_ts_version) elif arch == 'x86_64': @@ -437,7 +437,7 @@ class BoostDependency(ExternalDependency): def detect_lib_modules_nix(self): if self.static: libsuffix = 'a' - elif mesonlib.for_darwin(self.env): + elif self.env.machines[self.for_machine].is_darwin(): libsuffix = 'dylib' else: libsuffix = 'so' diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 19991c3..5fd547b 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -24,20 +24,21 @@ from .. import mesonlib, mlog from ..mesonlib import version_compare, stringlistify, extract_as_list, MachineChoice from .base import ( DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency, - strip_system_libdirs, ConfigToolDependency, CMakeDependency + strip_system_libdirs, ConfigToolDependency, CMakeDependency, HasNativeKwarg ) from .misc import ThreadDependency from typing import List, Tuple -def get_shared_library_suffix(environment, native): +def get_shared_library_suffix(environment, for_machine: MachineChoice): """This is only gauranteed to work for languages that compile to machine code, not for languages like C# that use a bytecode and always end in .dll """ - if mesonlib.for_windows(native, environment): + m = environment.machines[for_machine] + if m.is_windows(): return '.dll' - elif mesonlib.for_darwin(native, environment): + elif m.is_darwin(): return '.dylib' return '.so' @@ -203,6 +204,10 @@ class LLVMDependencyConfigTool(ConfigToolDependency): __cpp_blacklist = {'-DNDEBUG'} def __init__(self, environment, kwargs): + # Already called by `super().__init__`, but need `self.for_machine` + # before `super().__init__` is called. + HasNativeKwarg.__init__(self, kwargs) + # Ordered list of llvm-config binaries to try. Start with base, then try # newest back to oldest (3.5 is arbitrary), and finally the devel version. # Please note that llvm-config-6.0 is a development snapshot and it should @@ -227,8 +232,7 @@ class LLVMDependencyConfigTool(ConfigToolDependency): # of bits in the isa that llvm targets, for example, on x86_64 # and aarch64 the name will be llvm-config-64, on x86 and arm # it will be llvm-config-32. - m = MachineChoice.BUILD if environment.is_cross_build() and kwargs.get('native', True) else MachineChoice.HOST - if environment.machines[m].is_64_bit: + if environment.machines[self.for_machine].is_64_bit: self.tools.append('llvm-config-64') else: self.tools.append('llvm-config-32') @@ -256,7 +260,7 @@ class LLVMDependencyConfigTool(ConfigToolDependency): self._set_new_link_args(environment) else: self._set_old_link_args() - self.link_args = strip_system_libdirs(environment, self.link_args) + self.link_args = strip_system_libdirs(environment, self.for_machine, self.link_args) self.link_args = self.__fix_bogus_link_args(self.link_args) self._add_sub_dependency(ThreadDependency, environment, kwargs) @@ -271,7 +275,7 @@ class LLVMDependencyConfigTool(ConfigToolDependency): "-L IBPATH:...", if we're using an msvc like compilers convert that to "/LIBPATH", otherwise to "-L ..." """ - cpp = self.env.coredata.compilers['cpp'] + cpp = self.env.coredata.compilers[self.for_machine]['cpp'] new_args = [] for arg in args: @@ -316,7 +320,7 @@ class LLVMDependencyConfigTool(ConfigToolDependency): try: self.__check_libfiles(True) except DependencyException: - lib_ext = get_shared_library_suffix(environment, self.native) + lib_ext = get_shared_library_suffix(environment, self.for_machine) libdir = self.get_config_value(['--libdir'], 'link_args')[0] # Sort for reproducability matches = sorted(glob.iglob(os.path.join(libdir, 'libLLVM*{}'.format(lib_ext)))) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 72ba7b3..a537716 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -213,7 +213,7 @@ class MPIDependency(ExternalDependency): if not self.is_found and mesonlib.is_windows(): # only Intel Fortran compiler is compatible with Microsoft MPI at this time. - if language == 'fortran' and environment.detect_fortran_compiler(False).name_string() != 'intel': + if language == 'fortran' and environment.detect_fortran_compiler(self.for_machine).name_string() != 'intel': return result = self._try_msmpi() if result is not None: @@ -228,7 +228,7 @@ class MPIDependency(ExternalDependency): result = [] multi_args = ('-I', ) if self.language == 'fortran': - fc = self.env.coredata.compilers['fortran'] + fc = self.env.coredata.compilers[self.for_machine]['fortran'] multi_args += fc.get_module_incdir_args() include_next = False @@ -325,7 +325,7 @@ class MPIDependency(ExternalDependency): if 'MSMPI_INC' not in os.environ: return incdir = os.environ['MSMPI_INC'] - arch = detect_cpu_family(self.env.coredata.compilers) + arch = detect_cpu_family(self.env.coredata.compilers.host) if arch == 'x86': if 'MSMPI_LIB32' not in os.environ: return @@ -396,7 +396,7 @@ class Python3Dependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('python3', environment, None, kwargs) - if self.want_cross: + if not environment.machines.matches_build_machine(self.for_machine): return self.name = 'python3' @@ -480,7 +480,7 @@ class Python3Dependency(ExternalDependency): if pyarch is None: self.is_found = False return - arch = detect_cpu_family(env.coredata.compilers) + arch = detect_cpu_family(env.coredata.compilers.host) if arch == 'x86': arch = '32' elif arch == 'x86_64': @@ -560,7 +560,7 @@ class PcapDependency(ExternalDependency): def get_pcap_lib_version(ctdep): # Since we seem to need to run a program to discover the pcap version, # we can't do that when cross-compiling - if ctdep.want_cross: + if not ctdep.env.machines.matches_build_machine(ctdep.for_machine): return None v = ctdep.clib_compiler.get_return_value('pcap_lib_version', 'string', diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index b1fa632..f96668b 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -23,8 +23,7 @@ from collections import OrderedDict from .. import mlog from .. import mesonlib from ..mesonlib import ( - MesonException, Popen_safe, extract_as_list, for_windows, - version_compare_many + MesonException, Popen_safe, extract_as_list, version_compare_many ) from ..environment import detect_cpu @@ -38,13 +37,13 @@ class GLDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('gl', environment, None, kwargs) - if mesonlib.for_darwin(self.want_cross, self.env): + if self.env.machines[self.for_machine].is_darwin(): self.is_found = True # FIXME: Use AppleFrameworks dependency self.link_args = ['-framework', 'OpenGL'] # FIXME: Detect version using self.clib_compiler return - if mesonlib.for_windows(self.want_cross, self.env): + if self.env.machines[self.for_machine].is_windows(): self.is_found = True # FIXME: Use self.clib_compiler.find_library() self.link_args = ['-lopengl32'] @@ -310,7 +309,7 @@ class QtBaseDependency(ExternalDependency): language=self.language) modules['Core'] = core - if for_windows(self.env.is_cross_build(), self.env) and self.qtmain: + if self.env.machines[self.for_machine].is_windows() and self.qtmain: # Check if we link with debug binaries debug_lib_name = self.qtpkgname + 'Core' + self._get_modules_lib_suffix(True) is_debug = False @@ -414,7 +413,7 @@ class QtBaseDependency(ExternalDependency): break self.link_args.append(libfile) - if for_windows(self.env.is_cross_build(), self.env) and self.qtmain: + if self.env.machines[self.for_machine].is_windows() and self.qtmain: if not self._link_with_qtmain(is_debug, libdir): self.is_found = False @@ -422,7 +421,7 @@ class QtBaseDependency(ExternalDependency): def _get_modules_lib_suffix(self, is_debug): suffix = '' - if for_windows(self.env.is_cross_build(), self.env): + if self.env.machines[self.for_machine].is_windows(): if is_debug: suffix += 'd' if self.qtver == '4': diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index f8603f6..ce78162 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -510,22 +510,6 @@ class Environment: self.default_cmake = ['cmake'] self.default_pkgconfig = ['pkg-config'] - # Various prefixes and suffixes for import libraries, shared libraries, - # static libraries, and executables. - # Versioning is added to these names in the backends as-needed. - if mesonlib.for_windows(self): - self.exe_suffix = 'exe' - self.object_suffix = 'obj' - self.win_libdir_layout = True - elif mesonlib.for_cygwin(self): - self.exe_suffix = 'exe' - self.object_suffix = 'o' - self.win_libdir_layout = True - else: - self.exe_suffix = '' - self.object_suffix = 'o' - self.win_libdir_layout = False - def create_new_coredata(self, options): # WARNING: Don't use any values from coredata in __init__. It gets # re-initialized with project options by the interpreter during @@ -631,17 +615,11 @@ class Environment: return CompilerType.GCC_CYGWIN return CompilerType.GCC_STANDARD - def _get_compilers(self, lang, want_cross): + def _get_compilers(self, lang, for_machine): ''' The list of compilers is detected in the exact same way for C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. ''' - - # This morally assumes `want_cross = !native`. It may not yet be - # consistently set that way in the non cross build case, but it doesn't - # really matter since both options are the same in that case. - for_machine = MachineChoice.HOST if want_cross else MachineChoice.BUILD - value = self.binaries[for_machine].lookup_entry(lang) if value is not None: compilers, ccache = BinaryTable.parse_entry(value) @@ -654,13 +632,11 @@ class Environment: ccache = BinaryTable.detect_ccache() if self.machines.matches_build_machine(for_machine): - is_cross = False exe_wrap = None else: - is_cross = True exe_wrap = self.get_exe_wrapper() - return compilers, ccache, is_cross, exe_wrap + return compilers, ccache, exe_wrap def _handle_exceptions(self, exceptions, binaries, bintype='compiler'): errmsg = 'Unknown {}(s): {}'.format(bintype, binaries) @@ -670,9 +646,10 @@ class Environment: errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e) raise EnvironmentException(errmsg) - def _detect_c_or_cpp_compiler(self, lang, want_cross): + def _detect_c_or_cpp_compiler(self, lang, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers(lang, want_cross) + compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): @@ -737,7 +714,7 @@ class Environment: else: version = self.get_gnu_version_from_defines(defines) cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version) if 'armclang' in out: # The compiler version is not present in the first line of output, @@ -755,7 +732,7 @@ class Environment: full_version = arm_ver_str compiler_type = CompilerType.ARM_WIN cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'CL.EXE COMPATIBILITY' in out: # if this is clang-cl masquerading as cl, detect it as cl, not # clang @@ -771,21 +748,22 @@ class Environment: else: target = 'unknown target' cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) if 'clang' in out: - if 'Apple' in out or mesonlib.for_darwin(self): + if 'Apple' in out or self.machines[for_machine].is_darwin(): compiler_type = CompilerType.CLANG_OSX - elif 'windows' in out or mesonlib.for_windows(self): + elif 'windows' in out or self.machines[for_machine].is_windows(): compiler_type = CompilerType.CLANG_MINGW else: compiler_type = CompilerType.CLANG_STANDARD cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Intel(R) C++ Intel(R)' in err: version = search_version(err) target = 'x86' if 'IA-32' in err else 'x86_64' cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Microsoft' in out or 'Microsoft' in err: # Latest versions of Visual Studio print version # number to stderr but earlier ones print version @@ -804,8 +782,7 @@ class Environment: else: target = 'x86' cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler - return cls(compiler, version, is_cross, exe_wrap, target) - + return cls(compiler, version, for_machine, is_cross, exe_wrap, target) if 'PGI Compilers' in out: if self.machines[for_machine].is_darwin(): compiler_type = CompilerType.PGI_OSX @@ -814,37 +791,37 @@ class Environment: else: compiler_type = CompilerType.PGI_STANDARD cls = PGICCompiler if lang == 'c' else PGICPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, compiler_type, exe_wrap) if '(ICC)' in out: - if self.machine[for_macine].is_darwin(): + if self.machines[for_machine].is_darwin(): compiler_type = CompilerType.ICC_OSX - elif mesonlib.for_windows(want_cross, self): + elif self.machines[for_machine].is_windows(): # TODO: fix ICC on Windows compiler_type = CompilerType.ICC_WIN else: compiler_type = CompilerType.ICC_STANDARD cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'ARM' in out: compiler_type = CompilerType.ARM_WIN cls = ArmCCompiler if lang == 'c' else ArmCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'RX Family' in out: compiler_type = CompilerType.CCRX_WIN cls = CcrxCCompiler if lang == 'c' else CcrxCPPCompiler - return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) - def detect_c_compiler(self, want_cross): - return self._detect_c_or_cpp_compiler('c', want_cross) + def detect_c_compiler(self, for_machine): + return self._detect_c_or_cpp_compiler('c', for_machine) - def detect_cpp_compiler(self, want_cross): - return self._detect_c_or_cpp_compiler('cpp', want_cross) + def detect_cpp_compiler(self, for_machine): + return self._detect_c_or_cpp_compiler('cpp', for_machine) - def detect_cuda_compiler(self, want_cross): + def detect_cuda_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('cuda', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('cuda', for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -873,12 +850,13 @@ class Environment: # the full version: version = out.strip().split('V')[-1] cls = CudaCompiler - return cls(ccache + compiler, version, is_cross, exe_wrap) + return cls(ccache + compiler, version, for_machine, exe_wrap) raise EnvironmentException('Could not find suitable CUDA compiler: "' + ' '.join(compilers) + '"') - def detect_fortran_compiler(self, want_cross): + def detect_fortran_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('fortran', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('fortran', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -910,14 +888,14 @@ class Environment: else: version = self.get_gnu_version_from_defines(defines) cls = GnuFortranCompiler - return cls(compiler, version, compiler_type, is_cross, exe_wrap, defines, full_version=full_version) + return cls(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version) if 'G95' in out: - return G95FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return G95FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Sun Fortran' in err: version = search_version(err) - return SunFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return SunFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Intel(R) Visual Fortran' in err: version = search_version(err) @@ -925,36 +903,37 @@ class Environment: return IntelClFortranCompiler(compiler, version, is_cross, target, exe_wrap) if 'ifort (IFORT)' in out: - return IntelFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return IntelFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'PathScale EKOPath(tm)' in err: - return PathScaleFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return PathScaleFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'PGI Compilers' in out: - if self.machine[for_macine].is_darwin(): + if self.machine[for_machine].is_darwin(): compiler_type = CompilerType.PGI_OSX elif self.machines[for_machine].is_windows(): compiler_type = CompilerType.PGI_WIN else: compiler_type = CompilerType.PGI_STANDARD - return PGIFortranCompiler(compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + return PGIFortranCompiler(compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version) if 'flang' in out or 'clang' in out: - return FlangFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return FlangFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'Open64 Compiler Suite' in err: - return Open64FortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return Open64FortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) if 'NAG Fortran' in err: - return NAGFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + return NAGFortranCompiler(compiler, version, for_machine, is_cross, exe_wrap, full_version=full_version) self._handle_exceptions(popen_exceptions, compilers) def get_scratch_dir(self): return self.scratch_dir - def detect_objc_compiler(self, want_cross): + def detect_objc_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('objc', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('objc', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -972,18 +951,19 @@ class Environment: continue compiler_type = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuObjCCompiler(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines) + return GnuObjCCompiler(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines) if out.startswith('Apple LLVM'): - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, for_machine, is_cross, exe_wrap) if 'windows' in out: - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, for_machine, is_cross, exe_wrap) if out.startswith(('clang', 'OpenBSD clang')): - return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, is_cross, exe_wrap) + return ClangObjCCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_objcpp_compiler(self, want_cross): + def detect_objcpp_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('objcpp', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('objcpp', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -1001,16 +981,16 @@ class Environment: continue compiler_type = self.get_gnu_compiler_type(defines) version = self.get_gnu_version_from_defines(defines) - return GnuObjCPPCompiler(ccache + compiler, version, compiler_type, is_cross, exe_wrap, defines) + return GnuObjCPPCompiler(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines) if out.startswith('Apple LLVM'): - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_OSX, for_machine, is_cross, exe_wrap) if 'windows' in out: - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_MINGW, for_machine, is_cross, exe_wrap) if out.startswith(('clang', 'OpenBSD clang')): - return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, is_cross, exe_wrap) + return ClangObjCPPCompiler(ccache + compiler, version, CompilerType.CLANG_STANDARD, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_java_compiler(self): + def detect_java_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('java') if exelist is None: # TODO support fallback @@ -1026,11 +1006,11 @@ class Environment: parts = (err if 'javac' in err else out).split() if len(parts) > 1: version = parts[1] - return JavaCompiler(exelist, version) + return JavaCompiler(exelist, version, for_machine) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_cs_compiler(self): - compilers, ccache, is_cross, exe_wrap = self._get_compilers('cs', False) + def detect_cs_compiler(self, for_machine): + compilers, ccache, exe_wrap = self._get_compilers('cs', for_machine) popen_exceptions = {} for comp in compilers: if not isinstance(comp, list): @@ -1043,14 +1023,15 @@ class Environment: version = search_version(out) if 'Mono' in out: - return MonoCompiler(comp, version) + return MonoCompiler(comp, version, for_machine) elif "Visual C#" in out: - return VisualStudioCsCompiler(comp, version) + return VisualStudioCsCompiler(comp, version, for_machine) self._handle_exceptions(popen_exceptions, compilers) - def detect_vala_compiler(self): + def detect_vala_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('vala') + is_cross = not self.machines.matches_build_machine(for_machine) if exelist is None: # TODO support fallback exelist = [self.default_vala[0]] @@ -1061,12 +1042,13 @@ class Environment: raise EnvironmentException('Could not execute Vala compiler "%s"' % ' '.join(exelist)) version = search_version(out) if 'Vala' in out: - return ValaCompiler(exelist, version) + return ValaCompiler(exelist, version, for_machine, is_cross) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_rust_compiler(self, want_cross): + def detect_rust_compiler(self, for_machine): popen_exceptions = {} - compilers, ccache, is_cross, exe_wrap = self._get_compilers('rust', want_cross) + compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine) + is_cross = not self.machines.matches_build_machine(for_machine) for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -1080,13 +1062,12 @@ class Environment: version = search_version(out) if 'rustc' in out: - return RustCompiler(compiler, version, is_cross, exe_wrap) + return RustCompiler(compiler, version, for_machine, is_cross, exe_wrap) self._handle_exceptions(popen_exceptions, compilers) - def detect_d_compiler(self, want_cross): - is_cross = want_cross and self.is_cross_build() - exelist = self.binaries.host.lookup_entry('d') + def detect_d_compiler(self, for_machine: MachineChoice): + exelist = self.binaries[for_machine].lookup_entry('d') # Search for a D compiler. # We prefer LDC over GDC unless overridden with the DC # environment variable because LDC has a much more @@ -1115,22 +1096,23 @@ class Environment: c_compiler = {} is_msvc = mesonlib.is_windows() and 'VCINSTALLDIR' in os.environ if is_msvc: - c_compiler = {'c': self.detect_c_compiler(want_cross)} # MSVC compiler is required for correct platform detection. + c_compiler = {'c': self.detect_c_compiler(for_machine)} # MSVC compiler is required for correct platform detection. arch = detect_cpu_family(c_compiler) if is_msvc and arch == 'x86': arch = 'x86_mscoff' if 'LLVM D compiler' in out: - return compilers.LLVMDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.LLVMDCompiler(exelist, version, for_machine, arch, full_version=full_version) elif 'gdc' in out: - return compilers.GnuDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.GnuDCompiler(exelist, version, for_machine, arch, full_version=full_version) elif 'The D Language Foundation' in out or 'Digital Mars' in out: - return compilers.DmdDCompiler(exelist, version, is_cross, arch, full_version=full_version) + return compilers.DmdDCompiler(exelist, version, for_machine, arch, full_version=full_version) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_swift_compiler(self): + def detect_swift_compiler(self, for_machine): exelist = self.binaries.host.lookup_entry('swift') + is_cross = not self.machines.matches_build_machine(for_machine) if exelist is None: # TODO support fallback exelist = [self.default_swift[0]] @@ -1141,53 +1123,47 @@ class Environment: raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist)) version = search_version(err) if 'Swift' in err: - return compilers.SwiftCompiler(exelist, version) + return compilers.SwiftCompiler(exelist, version, for_machine, is_cross) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def compiler_from_language(self, lang: str, want_cross: bool): + def compiler_from_language(self, lang: str, for_machine: MachineChoice): if lang == 'c': - comp = self.detect_c_compiler(want_cross) + comp = self.detect_c_compiler(for_machine) elif lang == 'cpp': - comp = self.detect_cpp_compiler(want_cross) + comp = self.detect_cpp_compiler(for_machine) elif lang == 'objc': - comp = self.detect_objc_compiler(want_cross) + comp = self.detect_objc_compiler(for_machine) elif lang == 'cuda': - comp = self.detect_cuda_compiler(want_cross) + comp = self.detect_cuda_compiler(for_machine) elif lang == 'objcpp': - comp = self.detect_objcpp_compiler(want_cross) + comp = self.detect_objcpp_compiler(for_machine) elif lang == 'java': - comp = self.detect_java_compiler() # Java is platform independent. + comp = self.detect_java_compiler(for_machine) elif lang == 'cs': - comp = self.detect_cs_compiler() # C# is platform independent. + comp = self.detect_cs_compiler(for_machine) elif lang == 'vala': - comp = self.detect_vala_compiler() # Vala compiles to platform-independent C + comp = self.detect_vala_compiler(for_machine) elif lang == 'd': - comp = self.detect_d_compiler(want_cross) + comp = self.detect_d_compiler(for_machine) elif lang == 'rust': - comp = self.detect_rust_compiler(want_cross) + comp = self.detect_rust_compiler(for_machine) elif lang == 'fortran': - comp = self.detect_fortran_compiler(want_cross) + comp = self.detect_fortran_compiler(for_machine) elif lang == 'swift': - if want_cross: - raise EnvironmentException('Cross compilation with Swift is not working yet.') - comp = self.detect_swift_compiler() + comp = self.detect_swift_compiler(for_machine) else: comp = None return comp - def detect_compilers(self, lang: str, need_cross_compiler: bool): - comp = self.compiler_from_language(lang, False) - if need_cross_compiler: - cross_comp = self.compiler_from_language(lang, True) - else: - cross_comp = None + def detect_compiler_for(self, lang: str, for_machine: MachineChoice): + comp = self.compiler_from_language(lang, for_machine) if comp is not None: - self.coredata.process_new_compilers(lang, comp, cross_comp, self) - return comp, cross_comp + assert comp.for_machine == for_machine + self.coredata.process_new_compiler(lang, comp, self) + return comp def detect_static_linker(self, compiler): - for_machine = MachineChoice.HOST if compiler.is_cross else MachineChoice.BUILD - linker = self.binaries[for_machine].lookup_entry('ar') + linker = self.binaries[compiler.for_machine].lookup_entry('ar') if linker is not None: linkers = [linker] else: @@ -1255,9 +1231,6 @@ class Environment: def get_build_dir(self): return self.build_dir - def get_exe_suffix(self): - return self.exe_suffix - def get_import_lib_dir(self) -> str: "Install dir for the import library (library used for linking)" return self.get_libdir() @@ -1268,7 +1241,9 @@ class Environment: def get_shared_lib_dir(self) -> str: "Install dir for the shared library" - if self.win_libdir_layout: + m = self.machines.host + # Windows has no RPATH or similar, so DLLs must be next to EXEs. + if m.is_windows() or m.is_cygwin(): return self.get_bindir() return self.get_libdir() @@ -1276,9 +1251,6 @@ class Environment: "Install dir for the static library" return self.get_libdir() - def get_object_suffix(self): - return self.object_suffix - def get_prefix(self) -> str: return self.coredata.get_builtin_option('prefix') @@ -1300,8 +1272,8 @@ class Environment: def get_datadir(self) -> str: return self.coredata.get_builtin_option('datadir') - def get_compiler_system_dirs(self): - for comp in self.coredata.compilers.values(): + def get_compiler_system_dirs(self, for_machine: MachineChoice): + for comp in self.coredata.compilers[for_machine].values(): if isinstance(comp, compilers.ClangCompiler): index = 1 break diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 7c17e1c..5dddb22 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -21,7 +21,7 @@ from . import optinterpreter from . import compilers from .wrap import wrap, WrapMode from . import mesonlib -from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep +from .mesonlib import FileMode, MachineChoice, PerMachine, Popen_safe, listify, extract_as_list, has_path_sep from .dependencies import ExternalProgram from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException from .interpreterbase import InterpreterBase @@ -738,7 +738,7 @@ class BuildTargetHolder(TargetHolder): return r.format(self.__class__.__name__, h.get_id(), h.filename) def is_cross(self): - return self.held_object.is_cross() + return not self.held_object.environment.machines.matches_build_machine(self.held_object.for_machine) @noPosargs @permittedKwargs({}) @@ -1696,8 +1696,10 @@ class ModuleHolder(InterpreterObject, ObjectHolder): data=self.interpreter.build.data, headers=self.interpreter.build.get_headers(), man=self.interpreter.build.get_man(), - global_args=self.interpreter.build.global_args, - project_args=self.interpreter.build.projects_args.get(self.interpreter.subproject, {}), + #global_args_for_build = self.interpreter.build.global_args.build, + global_args = self.interpreter.build.global_args.host, + #project_args_for_build = self.interpreter.build.projects_args.build.get(self.interpreter.subproject, {}), + project_args = self.interpreter.build.projects_args.host.get(self.interpreter.subproject, {}), build_machine=self.interpreter.builtin['build_machine'].held_object, host_machine=self.interpreter.builtin['host_machine'].held_object, target_machine=self.interpreter.builtin['target_machine'].held_object, @@ -1847,10 +1849,7 @@ class MesonMain(InterpreterObject): native = True if not isinstance(native, bool): raise InterpreterException('Type of "native" must be a boolean.') - if native: - clist = self.interpreter.coredata.compilers - else: - clist = self.interpreter.coredata.cross_compilers + clist = self.interpreter.coredata.compilers[MachineChoice.BUILD if native else MachineChoice.HOST] if cname in clist: return CompilerHolder(clist[cname], self.build.environment, self.interpreter.subproject) raise InterpreterException('Tried to access compiler for unspecified language "%s".' % cname) @@ -2085,7 +2084,7 @@ class Interpreter(InterpreterBase): # have the compilers needed to gain more knowledge, so wipe out old # inferrence and start over. machines = self.build.environment.machines.miss_defaulting() - machines.build = environment.detect_machine_info(self.coredata.compilers) + machines.build = environment.detect_machine_info(self.coredata.compilers.build) self.build.environment.machines = machines.default_missing() assert self.build.environment.machines.build.cpu is not None assert self.build.environment.machines.host.cpu is not None @@ -2237,10 +2236,10 @@ class Interpreter(InterpreterBase): def get_variables(self): return self.variables - def check_cross_stdlibs(self): - if self.build.environment.is_cross_build(): - props = self.build.environment.properties.host - for l in self.coredata.cross_compilers.keys(): + def check_stdlibs(self): + for for_machine in MachineChoice: + props = self.build.environment.properties[for_machine] + for l in self.coredata.compilers[for_machine].keys(): try: di = mesonlib.stringlistify(props.get_stdlib(l)) if len(di) != 2: @@ -2248,7 +2247,7 @@ class Interpreter(InterpreterBase): % l) projname, depname = di subproj = self.do_subproject(projname, 'meson', {}) - self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {}) + self.build.stdlibs.host[l] = subproj.get_variable_method([depname], {}) except KeyError: pass except InvalidArguments: @@ -2729,7 +2728,7 @@ external dependencies (including libraries) must go to "dependencies".''') mlog.log('Project version:', mlog.bold(self.project_version)) self.add_languages(proj_langs, True) if not self.is_subproject(): - self.check_cross_stdlibs() + self.check_stdlibs() @permittedKwargs(permitted_kwargs['add_languages']) @stringArgs @@ -2786,37 +2785,38 @@ external dependencies (including libraries) must go to "dependencies".''') raise Exception() def add_languages(self, args, required): + success = self.add_languages_for(args, required, MachineChoice.BUILD) + success &= self.add_languages_for(args, required, MachineChoice.HOST) + return success + + def add_languages_for(self, args, required, for_machine: MachineChoice): success = True - need_cross_compiler = self.environment.is_cross_build() for lang in sorted(args, key=compilers.sort_clink): lang = lang.lower() - if lang in self.coredata.compilers: - comp = self.coredata.compilers[lang] - cross_comp = self.coredata.cross_compilers.get(lang, None) + clist = self.coredata.compilers[for_machine] + machine_name = for_machine.get_lower_case_name() + if lang in clist: + comp = clist[lang] else: try: - (comp, cross_comp) = self.environment.detect_compilers(lang, need_cross_compiler) + comp = self.environment.detect_compiler_for(lang, for_machine) if comp is None: raise InvalidArguments('Tried to use unknown language "%s".' % lang) comp.sanity_check(self.environment.get_scratch_dir(), self.environment) - if cross_comp: - cross_comp.sanity_check(self.environment.get_scratch_dir(), self.environment) except Exception: if not required: - mlog.log('Compiler for language', mlog.bold(lang), 'not found.') + mlog.log('Compiler for language', + mlog.bold(lang), 'for the', machine_name, + 'machine not found.') success = False continue else: raise - mlog.log('Native', comp.get_display_language(), 'compiler:', + mlog.log(comp.get_display_language(), 'compiler for the', machine_name, 'machine:', mlog.bold(' '.join(comp.get_exelist())), comp.get_version_string()) self.build.ensure_static_linker(comp) - if need_cross_compiler: - mlog.log('Cross', cross_comp.get_display_language(), 'compiler:', - mlog.bold(' '.join(cross_comp.get_exelist())), cross_comp.get_version_string()) - self.build.ensure_static_cross_linker(cross_comp) - langs = self.coredata.compilers.keys() + langs = self.coredata.compilers[for_machine].keys() if 'vala' in langs: if 'c' not in langs: raise InterpreterException('Compiling Vala requires C. Add C to your project languages and rerun Meson.') @@ -2935,14 +2935,9 @@ external dependencies (including libraries) must go to "dependencies".''') ) def _find_cached_dep(self, name, kwargs): - # Check if we want this as a cross-dep or a native-dep - # FIXME: Not all dependencies support such a distinction right now, - # and we repeat this check inside dependencies that do. We need to - # consolidate this somehow. - if self.environment.is_cross_build() and kwargs.get('native', False): - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST + # Check if we want this as a build-time / build machine or runt-time / + # host machine dep. + for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST identifier = dependencies.get_dep_identifier(name, kwargs) cached_dep = self.coredata.deps[for_machine].get(identifier) @@ -3097,10 +3092,7 @@ external dependencies (including libraries) must go to "dependencies".''') # cannot cache them. They must always be evaluated else # we won't actually read all the build files. if dep.found(): - if self.environment.is_cross_build() and kwargs.get('native', False): - for_machine = MachineChoice.BUILD - else: - for_machine = MachineChoice.HOST + for_machine = MachineChoice.BUILD if kwargs.get('native', False) else MachineChoice.HOST self.coredata.deps[for_machine].put(identifier, dep) return DependencyHolder(dep, self.subproject) @@ -3849,45 +3841,47 @@ different subdirectory. env = self.unpack_env_kwarg(kwargs) self.build.test_setups[setup_name] = build.TestSetup(exe_wrapper, gdb, timeout_multiplier, env) - def get_argdict_on_crossness(self, native_dict, cross_dict, kwargs): + # TODO make cross agnostic, just taking into account for_machine + # TODO PerMachine[T], Iterator[T] + def get_argdict_on_crossness(self, dicts_per_machine: PerMachine, kwargs) -> typing.Iterator: for_native = kwargs.get('native', not self.environment.is_cross_build()) if not isinstance(for_native, bool): raise InterpreterException('Keyword native must be a boolean.') - if for_native: - return native_dict + if self.environment.is_cross_build(): + if for_native: + return iter([dicts_per_machine[MachineChoice.BUILD]]) + else: + return iter([dicts_per_machine[MachineChoice.HOST]]) else: - return cross_dict + if for_native: + return iter([dicts_per_machine[MachineChoice.BUILD], + dicts_per_machine[MachineChoice.HOST]]) + else: + return iter([]) @permittedKwargs(permitted_kwargs['add_global_arguments']) @stringArgs def func_add_global_arguments(self, node, args, kwargs): - argdict = self.get_argdict_on_crossness(self.build.global_args, - self.build.cross_global_args, - kwargs) - self.add_global_arguments(node, argdict, args, kwargs) + for argdict in self.get_argdict_on_crossness(self.build.global_args, kwargs): + self.add_global_arguments(node, argdict, args, kwargs) @permittedKwargs(permitted_kwargs['add_global_link_arguments']) @stringArgs def func_add_global_link_arguments(self, node, args, kwargs): - argdict = self.get_argdict_on_crossness(self.build.global_link_args, - self.build.cross_global_link_args, - kwargs) - self.add_global_arguments(node, argdict, args, kwargs) + for argdict in self.get_argdict_on_crossness(self.build.global_link_args, kwargs): + self.add_global_arguments(node, argdict, args, kwargs) @permittedKwargs(permitted_kwargs['add_project_arguments']) @stringArgs def func_add_project_arguments(self, node, args, kwargs): - argdict = self.get_argdict_on_crossness(self.build.projects_args, - self.build.cross_projects_args, - kwargs) - self.add_project_arguments(node, argdict, args, kwargs) + for argdict in self.get_argdict_on_crossness(self.build.projects_args, kwargs): + self.add_project_arguments(node, argdict, args, kwargs) @permittedKwargs(permitted_kwargs['add_project_link_arguments']) @stringArgs def func_add_project_link_arguments(self, node, args, kwargs): - argdict = self.get_argdict_on_crossness(self.build.projects_link_args, - self.build.cross_projects_link_args, kwargs) - self.add_project_arguments(node, argdict, args, kwargs) + for argdict in self.get_argdict_on_crossness(self.build.projects_link_args, kwargs): + self.add_project_arguments(node, argdict, args, kwargs) def add_global_arguments(self, node, argsdict, args, kwargs): if self.is_subproject(): @@ -3940,7 +3934,8 @@ different subdirectory. self.print_extra_warnings() def print_extra_warnings(self): - for c in self.coredata.compilers.values(): + # TODO cross compilation + for c in self.coredata.compilers.host.values(): if c.get_id() == 'clang': self.check_clang_asan_lundef() break @@ -4091,13 +4086,10 @@ Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_s if not args: raise InterpreterException('Target does not have a name.') name, *sources = args - if self.environment.is_cross_build(): - if kwargs.get('native', False): - is_cross = False - else: - is_cross = True + if kwargs.get('native', False): + for_machine = MachineChoice.BUILD else: - is_cross = False + for_machine = MachineChoice.HOST if 'sources' in kwargs: sources += listify(kwargs['sources']) sources = self.source_strings_to_files(sources) @@ -4128,9 +4120,9 @@ Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_s kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs} kwargs['include_directories'] = self.extract_incdirs(kwargs) - target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) + target = targetclass(name, self.subdir, self.subproject, for_machine, sources, objs, self.environment, kwargs) - if is_cross: + if not self.environment.machines.matches_build_machine(for_machine): self.add_cross_stdlib_info(target) l = targetholder(target, self) self.add_target(name, l.held_object) @@ -4157,18 +4149,21 @@ This will become a hard error in the future.''', location=self.current_node) def get_used_languages(self, target): result = {} for i in target.sources: - for lang, c in self.coredata.compilers.items(): + # TODO other platforms + for lang, c in self.coredata.compilers.host.items(): if c.can_compile(i): result[lang] = True break return result def add_cross_stdlib_info(self, target): + if target.for_machine != MachineChoice.HOST: + return for l in self.get_used_languages(target): props = self.environment.properties.host if props.has_stdlib(l) \ and self.subproject != props.get_stdlib(l)[0]: - target.add_deps(self.build.cross_stdlibs[l]) + target.add_deps(self.build.stdlibs.host[l]) def check_sources_exist(self, subdir, sources): for s in sources: diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index 8ce5aef..a36d748 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -110,7 +110,7 @@ class CmakeModule(ExtensionModule): self.snippets.add('subproject') def detect_voidp_size(self, env): - compilers = env.coredata.compilers + compilers = env.coredata.compilers.host compiler = compilers.get('c', None) if not compiler: compiler = compilers.get('cpp', None) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index a223b78..fd9e063 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1048,7 +1048,7 @@ This will become a hard error in the future.''') if state.environment.is_cross_build(): compiler = state.environment.coredata.cross_compilers.get('c') else: - compiler = state.environment.coredata.compilers.get('c') + compiler = state.environment.coredata.compilers.host.get('c') compiler_flags = self._get_langs_compilers_flags(state, [('c', compiler)]) cflags.extend(compiler_flags[0]) diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index d4d0625..0284f3d 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -397,7 +397,7 @@ class PkgConfigModule(ExtensionModule): dversions = kwargs.get('d_module_versions', None) if dversions: - compiler = state.environment.coredata.compilers.get('d') + compiler = state.environment.coredata.compilers.host.get('d') if compiler: deps.add_cflags(compiler.get_feature_args({'versions': dversions}, None)) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 04941ea..2f4e5d6 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -211,7 +211,7 @@ class PythonDependency(ExternalDependency): if pyarch is None: self.is_found = False return - arch = detect_cpu_family(env.coredata.compilers) + arch = detect_cpu_family(env.coredata.compilers.host) if arch == 'x86': arch = '32' elif arch == 'x86_64': diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 3b4eb15..efc3218 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -18,7 +18,7 @@ import re from .. import mlog from .. import mesonlib, build -from ..mesonlib import MesonException, extract_as_list +from ..mesonlib import MachineChoice, MesonException, extract_as_list from . import get_include_args from . import ModuleReturnValue from . import ExtensionModule @@ -41,16 +41,17 @@ class WindowsModule(ExtensionModule): def _find_resource_compiler(self, state): # FIXME: Does not handle `native: true` executables, see # See https://github.com/mesonbuild/meson/issues/1531 - # But given a machine, we can un-hardcode `binaries.host` below. + # Take a parameter instead of the hardcoded definition below + for_machine = MachineChoice.HOST if hasattr(self, '_rescomp'): return self._rescomp # Will try cross / native file and then env var - rescomp = ExternalProgram.from_bin_list(state.environment.binaries.host, 'windres') + rescomp = ExternalProgram.from_bin_list(state.environment.binaries[for_machine], 'windres') if not rescomp or not rescomp.found(): - comp = self.detect_compiler(state.environment.coredata.compilers) + comp = self.detect_compiler(state.environment.coredata.compilers[for_machine]) if comp.id in {'msvc', 'clang-cl', 'intel-cl'}: rescomp = ExternalProgram('rc', silent=True) else: diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py index 864df04..d3cc1da 100644 --- a/mesonbuild/munstable_coredata.py +++ b/mesonbuild/munstable_coredata.py @@ -14,6 +14,7 @@ from . import coredata as cdata +from .mesonlib import MachineChoice import os.path import pprint @@ -91,18 +92,11 @@ def run(options): if v: print('Native File: ' + ' '.join(v)) elif k == 'compilers': - print('Cached native compilers:') - dump_compilers(v) - elif k == 'cross_compilers': - print('Cached cross compilers:') - dump_compilers(v) + for for_machine in MachineChoice: + print('Cached {} machine compilers:'.format( + for_machine.get_lower_case_name())) + dump_compilers(v[for_machine]) elif k == 'deps': - native = list(sorted(v.build.items())) - if v.host is not v.build: - cross = list(sorted(v.host.items())) - else: - cross = [] - def print_dep(dep_key, dep): print(' ' + dep_key[0] + ": ") print(' compile args: ' + repr(dep.get_compile_args())) @@ -111,16 +105,13 @@ def run(options): print(' sources: ' + repr(dep.get_sources())) print(' version: ' + repr(dep.get_version())) - if native: - print('Cached native dependencies:') - for dep_key, deps in native: - for dep in deps: - print_dep(dep_key, dep) - if cross: - print('Cached dependencies:') - for dep_key, deps in cross: - for dep in deps: - print_dep(dep_key, dep) + for for_machine in iter(MachineChoice): + items_list = list(sorted(v[for_machine].items())) + if items_list: + print('Cached dependencies for {} machine' % for_machine.get_lower_case_name()) + for dep_key, deps in items_list: + for dep in deps: + print_dep(dep_key, dep) else: print(k + ':') print(textwrap.indent(pprint.pformat(v), ' ')) |