From 18cfa545f03ddb6cb8378fdadec4f284aa7ea221 Mon Sep 17 00:00:00 2001 From: Nomura Date: Tue, 28 Mar 2023 11:25:19 +0200 Subject: [PATCH] Initial support for Metrowerks C/C++ compiler --- cross/metrowerks-arm.txt | 28 +++ cross/metrowerks-eppc.txt | 28 +++ cross/metrowerks.lcf | 18 ++ docs/markdown/Reference-tables.md | 4 + .../snippets/add_metrowerks_compiler.md | 5 + mesonbuild/backend/ninjabackend.py | 18 +- mesonbuild/build.py | 3 + mesonbuild/compilers/c.py | 59 +++++ mesonbuild/compilers/cpp.py | 59 +++++ mesonbuild/compilers/detect.py | 41 +++- mesonbuild/compilers/mixins/metrowerks.py | 232 ++++++++++++++++++ mesonbuild/linkers/__init__.py | 12 + mesonbuild/linkers/linkers.py | 65 +++++ run_project_tests.py | 4 +- 14 files changed, 571 insertions(+), 5 deletions(-) create mode 100644 cross/metrowerks-arm.txt create mode 100644 cross/metrowerks-eppc.txt create mode 100644 cross/metrowerks.lcf create mode 100644 docs/markdown/snippets/add_metrowerks_compiler.md create mode 100644 mesonbuild/compilers/mixins/metrowerks.py diff --git a/cross/metrowerks-arm.txt b/cross/metrowerks-arm.txt new file mode 100644 index 000000000..a13175b17 --- /dev/null +++ b/cross/metrowerks-arm.txt @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks Embedded ARM +# toolchain is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the .lcf file on your machine + +[binaries] +c = 'mwccarm' +c_ld = 'mwldarm' +cpp = 'mwccarm' +cpp_ld = 'mwldarm' +ar = 'mwldarm' +as = 'mwasmarm' + +[built-in options] +c_args = ['-lang', 'c99', '-D_NITRO', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-D_NITRO', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'arm' +endian = 'little' \ No newline at end of file diff --git a/cross/metrowerks-eppc.txt b/cross/metrowerks-eppc.txt new file mode 100644 index 000000000..e5e0e42fe --- /dev/null +++ b/cross/metrowerks-eppc.txt @@ -0,0 +1,28 @@ +# This file assumes that the path to your Metrowerks toolchain +# of choice is added to the environment(PATH) variable, so that +# Meson can find the binaries while building. + +# You should also do one of the following to ensure Meson can +# locate the .lcf linker script: +# - Add the cross directory to PATH as well +# - Edit c_link_args and cpp_link_args with the full +# path to the lcf file on your machine + +[binaries] +c = 'mwcceppc' +c_ld = 'mwldeppc' +cpp = 'mwcceppc' +cpp_ld = 'mwldeppc' +ar = 'mwldeppc' +as = 'mwasmeppc' + +[built-in options] +c_args = ['-lang', 'c99', '-nosyspath'] +c_link_args = 'metrowerks.lcf' +cpp_args = ['-lang', 'c++', '-nosyspath'] +cpp_link_args = 'metrowerks.lcf' + +[host_machine] +system = 'bare metal' +cpu_family = 'ppc' +endian = 'little' \ No newline at end of file diff --git a/cross/metrowerks.lcf b/cross/metrowerks.lcf new file mode 100644 index 000000000..96d13afda --- /dev/null +++ b/cross/metrowerks.lcf @@ -0,0 +1,18 @@ +# General-purpose linker script for Metrowerks toolchains. +# This script will link a blank application. Its only purpose +# is to allow the toolchains to run Meson tests. To link an +# actual application, you need to write your own fine-tuned lcf. + +MEMORY { + TEST (RWX) : ORIGIN=0, LENGTH=0 +} + +SECTIONS { + .TEST:{ + * (.text) + * (.data) + * (.rodata) + * (.bss) + __startup=.; + } > TEST +} \ No newline at end of file diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index a32182697..fb7deda8a 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -25,6 +25,8 @@ These are return values of the `get_id` (Compiler family) and | lcc | Elbrus C/C++/Fortran Compiler | | | llvm | LLVM-based compiler (Swift, D) | | | mono | Xamarin C# compiler | | +| mwccarm | Metrowerks C/C++ compiler for Embedded ARM | | +| mwcceppc | Metrowerks C/C++ compiler for Embedded PowerPC | | | msvc | Microsoft Visual Studio | msvc | | nagfor | The NAG Fortran compiler | | | nvidia_hpc| NVidia HPC SDK compilers | | @@ -69,6 +71,8 @@ These are return values of the `get_linker_id` method in a compiler object. | pgi | Portland/Nvidia PGI | | nvlink | Nvidia Linker used with cuda | | ccomp | CompCert used as the linker driver | +| mwldarm | The Metrowerks Linker with the ARM interface, used with mwccarm only | +| mwldeppc | The Metrowerks Linker with the PowerPC interface, used with mwcceppc only | For languages that don't have separate dynamic linkers such as C# and Java, the `get_linker_id` will return the compiler name. diff --git a/docs/markdown/snippets/add_metrowerks_compiler.md b/docs/markdown/snippets/add_metrowerks_compiler.md new file mode 100644 index 000000000..cebf74f97 --- /dev/null +++ b/docs/markdown/snippets/add_metrowerks_compiler.md @@ -0,0 +1,5 @@ +## Added Metrowerks C/C++ toolchains + +Added support for the Metrowerks Embedded ARM and Metrowerks Embedded PowerPC toolchains (https://www.nxp.com/docs/en/reference-manual/CWMCUKINCMPREF.pdf). + +The implementation is somewhat experimental. It has been tested on a few projects and works fairly well, but may have issues. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index edf9c1f56..45b4a11a9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2446,7 +2446,12 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) output = [] else: output = NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) - command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] + + if 'mwcc' in compiler.id: + output[0].s = '-precompile' + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + ['$in'] # '-c' must be removed + else: + command = compiler.get_exelist() + ['$ARGS'] + depargs + output + compiler.get_compile_only_args() + ['$in'] description = 'Precompiling header $in' if compiler.get_argument_syntax() == 'msvc': deps = 'msvc' @@ -3024,6 +3029,13 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. + def generate_mwcc_pch_command(self, target, compiler, pch): + commands = self._generate_single_compile(target, compiler) + dst = os.path.join(self.get_target_private_dir(target), + os.path.basename(pch) + '.' + compiler.get_pch_suffix()) + dep = os.path.splitext(dst)[0] + '.' + compiler.get_depfile_suffix() + return commands, dep, dst, [] # mwcc compilers do not create an object file during pch generation. + def generate_pch(self, target, header_deps=None): header_deps = header_deps if header_deps is not None else [] pch_objects = [] @@ -3042,6 +3054,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elif compiler.id == 'intel': # Intel generates on target generation continue + elif 'mwcc' in compiler.id: + src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) + (commands, dep, dst, objs) = self.generate_mwcc_pch_command(target, compiler, pch[0]) + extradep = None else: src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[0]) (commands, dep, dst, objs) = self.generate_gcc_pch_command(target, compiler, pch[0]) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 0c4326a87..fefc28c36 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1875,6 +1875,9 @@ class Executable(BuildTarget): elif ('c' in self.compilers and self.compilers['c'].get_id() in {'ti', 'c2000'} or 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'ti', 'c2000'}): self.suffix = 'out' + elif ('c' in self.compilers and self.compilers['c'].get_id() in {'mwccarm', 'mwcceppc'} or + 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'mwccarm', 'mwcceppc'}): + self.suffix = 'nef' else: self.suffix = machine.get_exe_suffix() self.filename = self.name diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 4d9283a25..cba10a63f 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -34,6 +34,8 @@ from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args from .compilers import ( gnu_winlibs, msvc_winlibs, @@ -738,3 +740,60 @@ class TICCompiler(TICompiler, CCompiler): class C2000CCompiler(TICCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' + +class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CCompiler.get_options(self) + c_stds = ['c99'] + opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang ' + std.value) + return args diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 3da5b7f17..dbdcb2fa2 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -39,6 +39,8 @@ from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler from .mixins.emscripten import EmscriptenMixin +from .mixins.metrowerks import MetrowerksCompiler +from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args if T.TYPE_CHECKING: from .compilers import CompileCheckMode @@ -893,3 +895,60 @@ class TICPPCompiler(TICompiler, CPPCompiler): class C2000CPPCompiler(TICPPCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' + +class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): + id = 'mwccarm' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwccarm_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang') + args.append(std.value) + return args + +class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler): + id = 'mwcceppc' + + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, + is_cross: bool, info: 'MachineInfo', + exe_wrapper: T.Optional['ExternalProgram'] = None, + linker: T.Optional['DynamicLinker'] = None, + full_version: T.Optional[str] = None): + CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, + info, exe_wrapper, linker=linker, full_version=full_version) + MetrowerksCompiler.__init__(self) + + def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: + return mwcceppc_instruction_set_args.get(instruction_set, None) + + def get_options(self) -> 'MutableKeyedOptionDictType': + opts = CPPCompiler.get_options(self) + key = OptionKey('std', machine=self.for_machine, lang=self.language) + opts[key].choices = ['none'] + return opts + + def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + args = [] + std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] + if std.value != 'none': + args.append('-lang ' + std.value) + return args diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index a3233f476..a700cfd60 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -36,7 +36,7 @@ if T.TYPE_CHECKING: from .cpp import CPPCompiler from .fortran import FortranCompiler from .rust import RustCompiler - from ..linkers import StaticLinker + from ..linkers import StaticLinker, DynamicLinker from ..environment import Environment from ..programs import ExternalProgram @@ -237,6 +237,11 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker return linkers.TILinker(linker) if out.startswith('The CompCert'): return linkers.CompCertLinker(linker) + if out.strip().startswith('Metrowerks') or out.strip().startswith('Freescale'): + if 'ARM' in out: + return linkers.MetrowerksStaticLinkerARM(linker) + else: + return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker) if p.returncode == 0: return linkers.ArLinker(compiler.for_machine, linker) if p.returncode == 1 and err.startswith('usage'): # OSX @@ -269,6 +274,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] cls: T.Union[T.Type[CCompiler], T.Type[CPPCompiler]] + lnk: T.Union[T.Type[StaticLinker], T.Type[DynamicLinker]] for compiler in compilers: if isinstance(compiler, str): @@ -529,7 +535,6 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=l) if 'TMS320C2000 C/C++' in out or 'MSP430 C/C++' in out or 'TI ARM C/C++ Compiler' in out: - lnk: T.Union[T.Type[linkers.C2000DynamicLinker], T.Type[linkers.TIDynamicLinker]] if 'TMS320C2000 C/C++' in out: cls = c.C2000CCompiler if lang == 'c' else cpp.C2000CPPCompiler lnk = linkers.C2000DynamicLinker @@ -542,7 +547,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin return cls( ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) - if 'ARM' in out: + if 'ARM' in out and not ('Metrowerks' in out or 'Freescale' in out): cls = c.ArmCCompiler if lang == 'c' else cpp.ArmCPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.ArmDynamicLinker(for_machine, version=version) @@ -573,6 +578,36 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) + if 'Metrowerks C/C++' in out or 'Freescale C/C++' in out: + if 'ARM' in out: + cls = c.MetrowerksCCompilerARM if lang == 'c' else cpp.MetrowerksCPPCompilerARM + lnk = linkers.MetrowerksLinkerARM + else: + cls = c.MetrowerksCCompilerEmbeddedPowerPC if lang == 'c' else cpp.MetrowerksCPPCompilerEmbeddedPowerPC + lnk = linkers.MetrowerksLinkerEmbeddedPowerPC + + mwcc_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', out) + assert mwcc_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + compiler_version = '.'.join(x for x in mwcc_ver_match.groups() if x is not None) + + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + ld = env.lookup_binary_entry(for_machine, cls.language + '_ld') + + if ld is not None: + _, o_ld, _ = Popen_safe(ld + ['--version']) + + mwld_ver_match = re.search(r'Version (\d+)\.(\d+)\.?(\d+)? build (\d+)', o_ld) + assert mwld_ver_match is not None, 'for mypy' # because mypy *should* be complaning that this could be None + linker_version = '.'.join(x for x in mwld_ver_match.groups() if x is not None) + + linker = lnk(ld, for_machine, version=linker_version) + else: + raise EnvironmentException(f'Failed to detect linker for {cls.id!r} compiler. Please update your cross file(s).') + + return cls( + ccache, compiler, compiler_version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + _handle_exceptions(popen_exceptions, compilers) raise EnvironmentException(f'Unknown compiler {compilers}') diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py new file mode 100644 index 000000000..89c612835 --- /dev/null +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -0,0 +1,232 @@ +# Copyright 2012-2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +"""Representations specific to the Metrowerks/Freescale Embedded C/C++ compiler family.""" + +import os +import typing as T + +from ...mesonlib import EnvironmentException, OptionKey + +if T.TYPE_CHECKING: + from ...envconfig import MachineInfo + from ...compilers.compilers import Compiler, CompileCheckMode +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + +mwcc_buildtype_args = { + 'plain': [], + 'debug': ['-g'], + 'debugoptimized': ['-g', '-O4'], + 'release': ['-O4,p'], + 'minsize': ['-Os'], + 'custom': [], +} # type: T.Dict[str, T.List[str]] + +mwccarm_instruction_set_args = { + 'generic': ['-proc', 'generic'], + 'v4': ['-proc', 'v4'], + 'v4t': ['-proc', 'v4t'], + 'v5t': ['-proc', 'v5t'], + 'v5te': ['-proc', 'v5te'], + 'v6': ['-proc', 'v6'], + 'arm7tdmi': ['-proc', 'arm7tdmi'], + 'arm710t': ['-proc', 'arm710t'], + 'arm720t': ['-proc', 'arm720t'], + 'arm740t': ['-proc', 'arm740t'], + 'arm7ej': ['-proc', 'arm7ej'], + 'arm9tdmi': ['-proc', 'arm9tdmi'], + 'arm920t': ['-proc', 'arm920t'], + 'arm922t': ['-proc', 'arm922t'], + 'arm940t': ['-proc', 'arm940t'], + 'arm9ej': ['-proc', 'arm9ej'], + 'arm926ej': ['-proc', 'arm926ej'], + 'arm946e': ['-proc', 'arm946e'], + 'arm966e': ['-proc', 'arm966e'], + 'arm1020e': ['-proc', 'arm1020e'], + 'arm1022e': ['-proc', 'arm1022e'], + 'arm1026ej': ['-proc', 'arm1026ej'], + 'dbmx1': ['-proc', 'dbmx1'], + 'dbmxl': ['-proc', 'dbmxl'], + 'XScale': ['-proc', 'XScale'], + 'pxa255': ['-proc', 'pxa255'], + 'pxa261': ['-proc', 'pxa261'], + 'pxa262': ['-proc', 'pxa262'], + 'pxa263': ['-proc', 'pxa263'] +} # type: T.Dict[str, T.List[str]] + +mwcceppc_instruction_set_args = { + 'generic': ['-proc', 'generic'], + '401': ['-proc', '401'], + '403': ['-proc', '403'], + '505': ['-proc', '505'], + '509': ['-proc', '509'], + '555': ['-proc', '555'], + '601': ['-proc', '601'], + '602': ['-proc', '602'], + '603': ['-proc', '603'], + '603e': ['-proc', '603e'], + '604': ['-proc', '604'], + '604e': ['-proc', '604e'], + '740': ['-proc', '740'], + '750': ['-proc', '750'], + '801': ['-proc', '801'], + '821': ['-proc', '821'], + '823': ['-proc', '823'], + '850': ['-proc', '850'], + '860': ['-proc', '860'], + '7400': ['-proc', '7400'], + '7450': ['-proc', '7450'], + '8240': ['-proc', '8240'], + '8260': ['-proc', '8260'], + 'e500': ['-proc', 'e500'], + 'gekko': ['-proc', 'gekko'], +} # type: T.Dict[str, T.List[str]] + +mwcc_optimization_args = { + 'plain': [], + '0': ['-O0'], + 'g': ['-Op'], + '1': ['-O1'], + '2': ['-O2'], + '3': ['-O3'], + 's': ['-Os'] +} # type: T.Dict[str, T.List[str]] + +mwcc_debug_args = { + False: [], + True: ['-g'] +} # type: T.Dict[bool, T.List[str]] + + +class MetrowerksCompiler(Compiler): + id = 'mwcc' + + # These compilers can actually invoke the linker, but they choke on + # linker-specific flags. So it's best to invoke the linker directly + INVOKES_LINKER = False + + def __init__(self) -> None: + if not self.is_cross: + raise EnvironmentException(f'{id} supports only cross-compilation.') + + self.base_options = { + OptionKey(o) for o in ['b_pch', 'b_ndebug']} + + default_warn_args = [] # type: T.List[str] + self.warn_args = {'0': ['-w', 'off'], + '1': default_warn_args, + '2': default_warn_args + ['-w', 'most'], + '3': default_warn_args + ['-w', 'all'], + 'everything': default_warn_args + ['-w', 'full']} # type: T.Dict[str, T.List[str]] + + def depfile_for_object(self, objfile: str) -> T.Optional[str]: + # Earlier versions of these compilers do not support specifying + # a custom name for a depfile, and can only generate '.d' + return os.path.splitext(objfile)[0] + '.' + self.get_depfile_suffix() + + def get_always_args(self) -> T.List[str]: + return ['-gccinc'] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return mwcc_buildtype_args[buildtype] + + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + return [] + + def get_compile_only_args(self) -> T.List[str]: + return ['-c'] + + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return mwcc_debug_args[is_debug] + + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + # Check comment in depfile_for_object() + return ['-gccdep', '-MD'] + + def get_depfile_suffix(self) -> str: + return 'd' + + def get_include_args(self, path: str, is_system: bool) -> T.List[str]: + if not path: + path = '.' + return ['-I' + path] + + def get_no_optimization_args(self) -> T.List[str]: + return ['-opt', 'off'] + + def get_no_stdinc_args(self) -> T.List[str]: + return ['-nostdinc'] + + def get_no_stdlib_link_args(self) -> T.List[str]: + return ['-nostdlib'] + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return mwcc_optimization_args[optimization_level] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_pic_args(self) -> T.List[str]: + return ['-pic'] + + def get_preprocess_only_args(self) -> T.List[str]: + return ['-E'] + + def get_preprocess_to_file_args(self) -> T.List[str]: + return ['-P'] + + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: + return ['-prefix', self.get_pch_name(header)] + + def get_pch_name(self, name: str) -> str: + return os.path.basename(name) + '.' + self.get_pch_suffix() + + def get_pch_suffix(self) -> str: + return 'mch' + + def get_warn_args(self, level: str) -> T.List[str]: + return self.warn_args[level] + + def get_werror_args(self) -> T.List[str]: + return ['-w', 'error'] + + @classmethod + def _unix_args_to_native(cls, args: T.List[str], info: MachineInfo) -> T.List[str]: + result = [] + for i in args: + if i.startswith('-D'): + i = '-D' + i[2:] + if i.startswith('-I'): + i = '-I' + i[2:] + if i.startswith('-Wl,-rpath='): + continue + elif i == '--print-search-dirs': + continue + elif i.startswith('-L'): + continue + result.append(i) + return result + + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: + for idx, i in enumerate(parameter_list): + if i[:2] == '-I': + parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:])) + + return parameter_list diff --git a/mesonbuild/linkers/__init__.py b/mesonbuild/linkers/__init__.py index 298e90163..ff50d6926 100644 --- a/mesonbuild/linkers/__init__.py +++ b/mesonbuild/linkers/__init__.py @@ -36,6 +36,9 @@ from .linkers import ( AIXArLinker, PGIStaticLinker, NvidiaHPC_StaticLinker, + MetrowerksStaticLinker, + MetrowerksStaticLinkerARM, + MetrowerksStaticLinkerEmbeddedPowerPC, DynamicLinker, PosixDynamicLinkerMixin, @@ -58,6 +61,9 @@ from .linkers import ( PGIDynamicLinker, NvidiaHPC_DynamicLinker, NAGDynamicLinker, + MetrowerksLinker, + MetrowerksLinkerARM, + MetrowerksLinkerEmbeddedPowerPC, VisualStudioLikeLinkerMixin, MSVCDynamicLinker, @@ -98,6 +104,9 @@ __all__ = [ 'AppleArLinker', 'PGIStaticLinker', 'NvidiaHPC_StaticLinker', + 'MetrowerksStaticLinker', + 'MetrowerksStaticLinkerARM', + 'MetrowerksStaticLinkerEmbeddedPowerPC', 'DynamicLinker', 'PosixDynamicLinkerMixin', @@ -120,6 +129,9 @@ __all__ = [ 'PGIDynamicLinker', 'NvidiaHPC_DynamicLinker', 'NAGDynamicLinker', + 'MetrowerksLinker', + 'MetrowerksLinkerARM', + 'MetrowerksLinkerEmbeddedPowerPC', 'VisualStudioLikeLinkerMixin', 'MSVCDynamicLinker', diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 4c00032d4..2db82e3f5 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -327,6 +327,28 @@ class AIXArLinker(ArLikeLinker): std_args = ['-csr', '-Xany'] +class MetrowerksStaticLinker(StaticLinker): + + def can_linker_accept_rsp(self) -> bool: + return True + + def get_linker_always_args(self) -> T.List[str]: + return ['-library'] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksStaticLinkerARM(MetrowerksStaticLinker): + id = 'mwldarm' + + +class MetrowerksStaticLinkerEmbeddedPowerPC(MetrowerksStaticLinker): + id = 'mwldeppc' + def prepare_rpaths(raw_rpaths: T.Tuple[str, ...], build_dir: str, from_dir: str) -> T.List[str]: # The rpaths we write must be relative if they point to the build dir, # because otherwise they have different length depending on the build @@ -1554,3 +1576,46 @@ class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker): def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: return [] + + +class MetrowerksLinker(DynamicLinker): + + def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, + *, version: str = 'unknown version'): + super().__init__(exelist, for_machine, '', [], + version=version) + + def fatal_warnings(self) -> T.List[str]: + return ['-w', 'error'] + + def get_allow_undefined_args(self) -> T.List[str]: + return [] + + def get_accepts_rsp(self) -> bool: + return True + + def get_lib_prefix(self) -> str: + return "" + + def get_linker_always_args(self) -> T.List[str]: + return [] + + def get_output_args(self, target: str) -> T.List[str]: + return ['-o', target] + + def get_search_args(self, dirname: str) -> T.List[str]: + return self._apply_prefix('-L' + dirname) + + def invoked_by_compiler(self) -> bool: + return False + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC + + +class MetrowerksLinkerARM(MetrowerksLinker): + id = 'mwldarm' + + +class MetrowerksLinkerEmbeddedPowerPC(MetrowerksLinker): + id = 'mwldeppc' diff --git a/run_project_tests.py b/run_project_tests.py index 448d559d2..bf8860862 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -212,7 +212,9 @@ class InstalledFile: suffix = '{}.{}'.format(suffix, '.'.join(self.version)) return p.with_suffix(suffix) elif self.typ == 'exe': - if env.machines.host.is_windows() or env.machines.host.is_cygwin(): + if 'mwcc' in canonical_compiler: + return p.with_suffix('.nef') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): return p.with_suffix('.exe') elif self.typ == 'pdb': if self.version: