Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/markdown/Reference-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ These are return values of the `get_id` (Compiler family) and
| mwasmarm | Metrowerks Assembler for Embedded ARM | |
| mwasmeppc | Metrowerks Assembler for Embedded PowerPC | |
| tasking | TASKING VX-toolset | |
| diab | Wind River Diab | |

## Linker ids

Expand Down Expand Up @@ -83,6 +84,7 @@ These are return values of the `get_linker_id` method in a compiler object.
| mwldarm | The Metrowerks Linker with the ARM interface, used with mwccarm only |
| mwldeppc | The Metrowerks Linker with the PowerPC interface, used with mwcceppc only |
| tasking | TASKING VX-toolset |
| diab | Wind River Diab |

For languages that don't have separate dynamic linkers such as C# and Java, the
`get_linker_id` will return the compiler name.
Expand Down
5 changes: 5 additions & 0 deletions docs/markdown/Release-notes.md
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# Release notes

## Added Wind River Diab compiler suite for bare-metal PowerPC

Tested with C++, C and assembler using [Diab](https://www.windriver.com/products/diab-compiler) 5.2.1.0 from 2004.
Comment on lines +3 to +5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release notes are compiled at release time by a script from individual snippets in docs/markdown/snippets/*.md, so this should be moved there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've mentioned C here, but there's no C compiler implementation, just a C++. That means if a user requests project('name', 'c') then this compiler won't be selected.


255 changes: 254 additions & 1 deletion mesonbuild/compilers/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import functools
import os.path
import typing as T
import enum

from .. import options
from .. import mlog
Expand Down Expand Up @@ -39,7 +40,7 @@
from ..envconfig import MachineInfo
from ..environment import Environment
from ..linkers.linkers import DynamicLinker
from ..mesonlib import MachineChoice
from ..mesonlib import MachineChoice, File, FileOrString
from ..build import BuildTarget
CompilerMixinBase = CLikeCompiler
else:
Expand Down Expand Up @@ -1128,3 +1129,255 @@ def get_option_std_args(self, target: BuildTarget, env: Environment, subproject:
if std != 'none':
args.append('-lang ' + std)
return args

class DiabCppCompiler(CPPCompiler):
"""The Wind River Diab compiler suite for bare-metal PowerPC

The suite entry program _dplus_ handles c++, c and assembler sources, and linking.

This object should have a DiabLinker instance in its `linker` member.

Archiving can be done with DiabArchiver.
"""
id = "diab"

# Target processor
processor = [
"PPC", # Generic PowerPC
"MGT5200",
"PPC401",
"PPC403",
"PPC405",
"PPC440",
"PPC440GX",
"PPC505",
"PPC509",
"PPC553",
"PPC555",
"PPC561",
"PPC565",
"PPC601",
"PPC602",
"PPC603",
"PPC603e",
"PPC604",
"PPC740",
"PPC745",
"PPC750",
"PPC755",
"PPC801",
"PPC821",
"PPC823",
"PPC850",
"PPC852",
"PPC855",
"PPC857",
"PPC859",
"PPC860",
"PPC862",
"PPC866",
"PPC970",
"PPCE500",
"PPC5500",
"PPC5534",
"PPC5534V",
"PPC5534N",
"PPC5553",
"PPC5554",
"PPC7400",
"PPC7410",
"PPC7440",
"PPC7441",
"PPC7445",
"PPC7447",
"PPC7450",
"PPC7451",
"PPC7455",
"PPC7457",
"PPC8240",
"PPC8241",
"PPC8245",
"PPC8250",
"PPC8255",
"PPC8260",
"PPC8264",
"PPC8265",
"PPC8266",
"PPC8270",
"PPC8275",
"PPC8280",
"PPC8540",
"PPC8541",
"PPC8543",
"PPC8545",
"PPC8547",
"PPC8548",
"PPC8560",
"POWER",
]

# Object format
object_format = {
'EABI': 'E', # ELF using EABI conventions
'Motorola': 'C', # Motorola compressible ELF
'no-small-section': 'F', # global and static scalar variables may be placed in a local data area
'little-endian': 'L', # little-endian
'COFF': 'D' # COFF using AIX conventions
}

# Floating point support
floating_point = {
'Hard': 'H', # Hardware floating point
'HardSingle': 'F', # Single precision uses hardware, double precision uses software emulation
'HardSingleOnly': 'G', # Single precision uses hardware, double precision is mapped to single precision
'Vector': 'V', # Vector floating point for AltiVec with the PPC7400 or PPC970 processor only
'Soft': 'S', # Software floating point emulation provided with the compiler
'None': 'N' # No floating point support
}

# Basic operating system functions
os_impl = {
'stdinout': 'simple', # Simple character input/output for stdin and stdout only
'ramdisk': 'cross' # Ram-disk file input/output
}

optimization_args: T.Dict[str, T.List[str]] = {
"plain": [],
"0": [],
"g": ["-O", "-Xno-optimized-debug"],
"1": ["-O"],
"2": ["-O", "-Xinline=40"],
"3": ["XO"],
"s": ["-Xsize-opt"],
}

class Prefix(enum.Enum):
CPP = "cpp"
CXX = "c++"
C = "c"
AS = "as"
LD = "ld"

def _apply_prefix(self, prefix: Prefix, arg: T.Union[str, T.List[str]]) -> T.List[str]:
"""Prefix commands to redirect to compiler suite sub programs"""
args = [arg] if isinstance(arg, str) else arg
return [f"-W:{prefix.value}:,{arg}" for arg in args]

@functools.lru_cache(maxsize=None)
def can_compile(self, src: FileOrString) -> bool:
if super().can_compile(src):
return True
if isinstance(src, File):
src = src.fname
suffix = os.path.splitext(src)[1]
return suffix in {".s", ".c"}

def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
return super().get_include_args(path, is_system) + self._apply_prefix(self.Prefix.AS, f"-I{path}")

def get_warn_args(self, level: str) -> T.List[str]:
"""No such levels"""
return []

def get_werror_args(self) -> T.List[str]:
return ["-Xstop-on-warning"]

def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return self.optimization_args[optimization_level]

def get_debug_args(self, is_debug: bool) -> T.List[str]:
return ['-g'] if is_debug else []

def _create_string_option(self, key: str, description: str) -> T.Tuple[options.OptionKey, options.UserStringArrayOption]:
return self.form_compileropt_key(key), options.UserStringArrayOption(key, description, [])

def _create_boolean_option(self, key: str, description: str, default: bool) -> T.Tuple[options.OptionKey, options.UserBooleanOption]:
return self.form_compileropt_key(key), options.UserBooleanOption(key, description, default)

def _create_combo_option(self, key: str, description: str, choices: T.Iterable[str]) -> T.Tuple[options.OptionKey, options.UserComboOption]:
choices = list(choices)
return self.form_compileropt_key(key), options.UserComboOption(key, description, choices[0], choices=choices)

def get_options(self) -> 'MutableKeyedOptionDictType':
opts = super().get_options()
key = self.form_compileropt_key("std")
std_opt = opts[key]
assert isinstance(std_opt, options.UserStdOption), "for mypy"
std_opt.set_versions(["c++98"])
opts.update([
self._create_string_option('args', "compile args"),
self._create_string_option('link_args', "link args"),
self._create_boolean_option('eh', 'C++ exception handling', True),
self._create_boolean_option('rtti', 'RTTI enabled', True),
self._create_boolean_option('lic_wait', 'Enable waiting for available license', False),
self._create_boolean_option('subprog_cmd', 'Print subprogram cmd lines with args as they are executed', False),
self._create_boolean_option('map', 'Save linker memory map', False),
self._create_combo_option('tgt_proc', "Target processor", self.processor),
self._create_combo_option('tgt_fmt', "Target object format", self.object_format),
self._create_combo_option('tgt_fp', "Target floating point processing", self.floating_point),
self._create_combo_option('os_impl', "Basic operating system functions", self.os_impl),
])
return opts

def _get_option_common_args(self, target: 'BuildTarget', env: 'Environment', subproject: T.Optional[str] = None) -> T.List[str]:
args: T.List[str] = []

if self.get_compileropt_value('lic_wait', env, target, subproject):
args.append('-Xlicense-wait')
if self.get_compileropt_value('subprog_cmd', env, target, subproject):
args.append('-#')

tgt_fmt = self.get_compileropt_value("tgt_fmt", env, target, subproject)
assert isinstance(tgt_fmt, str)
tgt_fp = self.get_compileropt_value("tgt_fp", env, target, subproject)
assert isinstance(tgt_fp, str)

args.append(
"-t{0}{1}{2}:simple".format(
self.get_compileropt_value("tgt_proc", env, target, subproject),
self.object_format[tgt_fmt],
self.floating_point[tgt_fp],
)
)

return args

def get_option_compile_args(self, target: 'BuildTarget', env: 'Environment', subproject: T.Optional[str] = None) -> T.List[str]:
args = self._get_option_common_args(target, env, subproject)

if not self.get_compileropt_value('eh', env, target, subproject):
args += self._apply_prefix(self.Prefix.CXX, '-Xexceptions-off')
if not self.get_compileropt_value('rtti', env, target, subproject):
args += self._apply_prefix(self.Prefix.CXX, '-Xrtti-off')

return args

def get_option_std_args(self, target: BuildTarget, env: Environment, subproject: T.Optional[str] = None) -> T.List[str]:
std = self.get_compileropt_value('std', env, target, subproject)
assert isinstance(std, str)
if std == 'c++98':
return self._apply_prefix(self.Prefix.CXX, '-Xstrict-ansi')
else:
return []

def get_option_link_args(self, target: 'BuildTarget', env: 'Environment', subproject: T.Optional[str] = None) -> T.List[str]:
args = self._get_option_common_args(target, env, subproject)

if self.get_compileropt_value('map', env, target, subproject):
args += self.linker._apply_prefix(['-m2', '-Xunused-sections-list', '-Xcheck-overlapping', f'-@O={target.filename}.map'])

return args

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' or i[:2] == '-L':
parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))

return parameter_list

def get_always_args(self) -> T.List[str]:
"""Disable super's large-file-support"""
return []

def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
return super(CPPCompiler, self).get_compiler_check_args(mode)
14 changes: 14 additions & 0 deletions mesonbuild/compilers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import tempfile
import os
import typing as T
import itertools

if T.TYPE_CHECKING:
from .compilers import Compiler
Expand Down Expand Up @@ -200,6 +201,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker
arg = '/?'
elif linker_name in {'ar2000', 'ar2000.exe', 'ar430', 'ar430.exe', 'armar', 'armar.exe', 'ar6x', 'ar6x.exe'}:
arg = '?'
elif linker_name in {'dar'}:
arg = '-V'
else:
arg = '--version'
try:
Expand Down Expand Up @@ -244,6 +247,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker
return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker)
if 'TASKING VX-toolset' in err:
return linkers.TaskingStaticLinker(linker)
if 'Wind River Systems, Inc.' in out:
return linkers.DiabArchiver(linker)
if p.returncode == 0:
return linkers.ArLinker(compiler.for_machine, linker)
if p.returncode == 1 and err.startswith('usage'): # OSX
Expand All @@ -252,6 +257,7 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker
return linkers.AIXArLinker(linker)
if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris
return linkers.ArLinker(compiler.for_machine, linker)

_handle_exceptions(popen_exceptions, trials, 'linker')
raise EnvironmentException('Unreachable code (exception to make mypy happy)')

Expand Down Expand Up @@ -321,6 +327,9 @@ def sanitize(p: T.Optional[str]) -> T.Optional[str]:
elif compiler_name in {'icl', 'icl.exe'}:
# if you pass anything to icl you get stuck in a pager
arg = ''
elif compiler_name in {f'd{name}{suffix}' for name, suffix in itertools.product(['cc', 'plus'], ['', '.exe'])}:
# Wind River Diab
arg = '-V'
else:
arg = '--version'

Expand Down Expand Up @@ -629,6 +638,11 @@ def sanitize(p: T.Optional[str]) -> T.Optional[str]:
ccache, compiler, tasking_version, for_machine, is_cross, info,
full_version=full_version, linker=linker)

if 'Wind River Systems, Inc.' in out:
if lang == "cpp":
linker = linkers.DiabLinker(compiler, for_machine, '-W:ld:,', [], system='none', version=version)
return cpp.DiabCppCompiler(ccache, compiler, version, for_machine, is_cross, info, linker)

_handle_exceptions(popen_exceptions, compilers)
raise EnvironmentException(f'Unknown compiler {compilers}')

Expand Down
34 changes: 34 additions & 0 deletions mesonbuild/linkers/linkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import typing as T
import re
import itertools

from .base import ArLikeLinker, RSPFileSyntax
from .. import mesonlib
Expand Down Expand Up @@ -1788,3 +1789,36 @@ def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
for a in args:
l.extend(self._apply_prefix('-Wl--whole-archive=' + a))
return l

class DiabLinker(DynamicLinker):
"""Linker for DiabCppCompiler

When used by DiabCppCompiler, prefix should be `-W:ld:,`, and empty if instantiated
independently controlling the Diab ld program _dld_ directly.
"""
id = 'diab'

def get_output_args(self, outputname: str) -> T.List[str]:
return ["-o", outputname]

def get_search_args(self, dirname: str) -> T.List[str]:
return ["-L", dirname]

def get_allow_undefined_args(self) -> T.List[str]:
return []

def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
return list(itertools.chain(*([self._apply_prefix("-A")[0], arg] for arg in args)))

class DiabArchiver(StaticLinker):
"""Archiver for DiabCppCompiler"""
id = 'diab'

def can_linker_accept_rsp(self) -> bool:
return False

def get_output_args(self, target: str) -> T.List[str]:
return [target]

def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]:
return ["-rc"]
Loading