Skip to content

Commit

Permalink
Add TASKING compiler support
Browse files Browse the repository at this point in the history
  • Loading branch information
gerioldman committed Feb 2, 2024
1 parent 41b1ed8 commit fea42a5
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 8 deletions.
2 changes: 1 addition & 1 deletion docs/markdown/Builtin-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ available on all platforms or with all compilers:
| b_staticpic | true | true, false | Build static libraries as position independent |
| b_pie | false | true, false | Build position-independent executables (since 0.49.0) |
| b_vscrt | from_buildtype | none, md, mdd, mt, mtd, from_buildtype, static_from_buildtype | VS runtime library to use (since 0.48.0) (static_from_buildtype since 0.56.0) |
| b_tasking_mil_link | false | true, false | Use MIL linking for the TASKING VX-tools compiler family (since 1.?.?) |
| b_tasking_mil_link | false | true, false | Use MIL linking for the TASKING VX-tools compiler family (since 1.4.0) |

The value of `b_sanitize` can be one of: `none`, `address`, `thread`,
`undefined`, `memory`, `leak`, `address,undefined`, but note that some
Expand Down
2 changes: 1 addition & 1 deletion docs/markdown/Reference-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ These are return values of the `get_id` (Compiler family) and
| cctc | TASKING VX-toolset for TriCore compiler | |
| ccarm | TASKING VX-toolset for ARM compiler | |
| cc51 | TASKING VX-toolset for 8051 compiler | |
| ccmsc | TASKING VX-toolset for MCS compiler | |
| ccmcs | TASKING VX-toolset for MCS compiler | |
| ccpcp | TASKING VX-toolset for PCP compiler | |

## Linker ids
Expand Down
99 changes: 93 additions & 6 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def _quoter(x, qf = quote_func):

def write(self, outfile: T.TextIO) -> None:
rspfile_args = self.args
if self.rspfile_quote_style is RSPFileSyntax.MSVC:
if self.rspfile_quote_style in {RSPFileSyntax.MSVC, RSPFileSyntax.TASKING}:
rspfile_quote_func = cmd_quote
rspfile_args = [NinjaCommandArg('$in_newline', arg.quoting) if arg.s == '$in' else arg for arg in rspfile_args]
else:
Expand All @@ -241,7 +241,10 @@ def rule_iter():
for rsp in rule_iter():
outfile.write(f'rule {self.name}{rsp}\n')
if rsp == '_RSP':
outfile.write(' command = {} @$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command])))
if self.rspfile_quote_style is RSPFileSyntax.TASKING:
outfile.write(' command = {} --option-file=$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command])))
else:
outfile.write(' command = {} @$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command])))
outfile.write(' rspfile = $out.rsp\n')
outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in rspfile_args])))
else:
Expand Down Expand Up @@ -390,7 +393,7 @@ def write(self, outfile):
outfile.write(line)

if use_rspfile:
if self.rule.rspfile_quote_style is RSPFileSyntax.MSVC:
if self.rule.rspfile_quote_style in {RSPFileSyntax.MSVC, RSPFileSyntax.TASKING}:
qf = cmd_quote
else:
qf = gcc_rsp_quote
Expand Down Expand Up @@ -688,6 +691,12 @@ def generate_compdb(self):
for ext in ['', '_RSP']]
rules += [f"{rule}{ext}" for rule in [self.compiler_to_pch_rule_name(compiler)]
for ext in ['', '_RSP']]
# Add custom MIL link rules to get the files compiled by the TASKING compiler family to MIL files included in the database
key = OptionKey('b_tasking_mil_link')
if key in compiler.base_options:
rule = self.get_compiler_rule_name('tasking_mil_compile', compiler.for_machine)
rules.append(rule)
rules.append(f'{rule}_RSP')
compdb_options = ['-x'] if mesonlib.version_compare(self.ninja_version, '>=1.9') else []
ninja_compdb = self.ninja_command + ['-t', 'compdb'] + compdb_options + rules
builddir = self.environment.get_build_dir()
Expand Down Expand Up @@ -1036,8 +1045,19 @@ def generate_target(self, target):
# Skip the link stage for this special type of target
return
linker, stdlib_args = self.determine_linker_and_stdlib_args(target)
if isinstance(target, build.StaticLibrary) and target.prelink:
# For prelinking and TASKING mil linking there needs to be an additional link target and the object list is modified
if not isinstance(target, build.StaticLibrary):
final_obj_list = obj_list
elif target.prelink:
final_obj_list = self.generate_prelink(target, obj_list)
elif 'c' in target.compilers:
key = OptionKey('b_tasking_mil_link')
if key not in target.get_options() or key not in target.compilers['c'].base_options:
final_obj_list = obj_list
elif target.get_option(key):
final_obj_list = self.generate_mil_link(target, obj_list)
else:
final_obj_list = obj_list
else:
final_obj_list = obj_list
elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args)
Expand Down Expand Up @@ -2429,6 +2449,33 @@ def generate_llvm_ir_compile_rule(self, compiler):
self.add_rule(NinjaRule(rule, command, args, description, **options))
self.created_llvm_ir_rule[compiler.for_machine] = True

def generate_tasking_mil_compile_rules(self, compiler: Compiler) -> None:
rule = self.get_compiler_rule_name('tasking_mil_compile', compiler.for_machine)
depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none)
command = compiler.get_exelist()
args = ['$ARGS'] + depargs + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + ['-cm', '$in']
description = 'Compiling to C object $in'
if compiler.get_argument_syntax() == 'msvc':
deps = 'msvc'
depfile = None
else:
deps = 'gcc'
depfile = '$DEPFILE'

options = self._rsp_options(compiler)

self.add_rule(NinjaRule(rule, command, args, description, **options, deps=deps, depfile=depfile))

def generate_tasking_mil_link_rules(self, compiler: Compiler) -> None:
rule = self.get_compiler_rule_name('tasking_mil_link', compiler.for_machine)
command = compiler.get_exelist()
args = ['$ARGS', '--mil-link'] + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + ['-c', '$in']
description = 'MIL linking object $out'

options = self._rsp_options(compiler)

self.add_rule(NinjaRule(rule, command, args, description, **options))

def generate_compile_rule_for(self, langname, compiler):
if langname == 'java':
self.generate_java_compile_rule(compiler)
Expand Down Expand Up @@ -2519,6 +2566,9 @@ def generate_compile_rules(self):
for langname, compiler in clist.items():
if compiler.get_id() == 'clang':
self.generate_llvm_ir_compile_rule(compiler)
if OptionKey('b_tasking_mil_link') in compiler.base_options:
self.generate_tasking_mil_compile_rules(compiler)
self.generate_tasking_mil_link_rules(compiler)
self.generate_compile_rule_for(langname, compiler)
self.generate_pch_rule_for(langname, compiler)
for mode in compiler.get_modes():
Expand Down Expand Up @@ -2953,6 +3003,11 @@ def generate_single_compile(self, target: build.BuildTarget, src,
else:
raise InvalidArguments(f'Invalid source type: {src!r}')
obj_basename = self.object_filename_from_source(target, src)
# If mil linking is enabled for the target, then compilation output has to be MIL files instead of object files
if compiler.get_language() == 'c':
key = OptionKey('b_tasking_mil_link')
if key in compiler.base_options and target.get_option(key) and src.rsplit('.', 1)[1] in compilers.lang_suffixes['c']:
obj_basename = f'{os.path.splitext(obj_basename)[0]}.mil'
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename)
dep_file = compiler.depfile_for_object(rel_obj)

Expand All @@ -2973,8 +3028,14 @@ def generate_single_compile(self, target: build.BuildTarget, src,
i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0]))
arr.append(i)
pch_dep = arr

compiler_name = self.compiler_to_rule_name(compiler)
# If TASKING compiler family is used and MIL linking is enabled for the target,
# then compilation rule name is a special one to output MIL files
# instead of object files for .c files
key = OptionKey('b_tasking_mil_link')
if key in compiler.base_options and target.get_option(key) and src.rsplit('.', 1)[1] in compilers.lang_suffixes['c']:
compiler_name = self.get_compiler_rule_name('tasking_mil_compile', compiler.for_machine)
else:
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
Expand Down Expand Up @@ -3355,6 +3416,29 @@ def generate_prelink(self, target, obj_list):
self.add_build(elem)
return [prelink_name]

def generate_mil_link(self, target: build.StaticLibrary, obj_list: T.List[str]) -> T.List[str]:
assert isinstance(target, build.StaticLibrary)

mil_linked_name = os.path.join(self.get_target_private_dir(target), target.name + '-mil_link.o')
mil_link_list = []
obj_file_list = []
for obj in obj_list:
if obj.endswith('.mil'):
mil_link_list.append(obj)
else:
obj_file_list.append(obj)
obj_file_list.append(mil_linked_name)
compiler = get_compiler_for_source(target.compilers.values(), mil_link_list[0][:-3] + '.c')
commands = self._generate_single_compile_base_args(target, compiler)
commands += self._generate_single_compile_target_args(target, compiler)
commands = commands.compiler.compiler_args(commands)

elem = NinjaBuildElement(self.all_outputs, [mil_linked_name], self.get_compiler_rule_name('tasking_mil_link', compiler.for_machine), mil_link_list)
elem.add_item('ARGS', commands)
self.add_build(elem)

return obj_file_list

def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.Union['Compiler', 'StaticLinker'], extra_args=None, stdlib_args=None):
extra_args = extra_args if extra_args is not None else []
stdlib_args = stdlib_args if stdlib_args is not None else []
Expand Down Expand Up @@ -3386,6 +3470,9 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.
linker,
isinstance(target, build.SharedModule),
self.environment.get_build_dir())
# Add --mil-link if the option is enabled
if isinstance(target, build.Executable) and 'c' in target.compilers and OptionKey('b_tasking_mil_link') in target.get_options():
commands += target.compilers['c'].get_tasking_mil_link_args(target.get_option(OptionKey('b_tasking_mil_link')))
# Add -nostdlib if needed; can't be overridden
commands += self.get_no_stdlib_link_args(target, linker)
# Add things like /NOLOGO; usually can't be overridden
Expand Down
2 changes: 2 additions & 0 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1980,6 +1980,8 @@ def post_init(self) -> None:
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'
elif ('c' in self.compilers and self.compilers['c'].get_id() in {'cctc', 'ccarm', 'cc51', 'ccmcs', 'ccpcp'}):
self.suffix = 'elf'
else:
self.suffix = machine.get_exe_suffix()
self.filename = self.name
Expand Down
26 changes: 26 additions & 0 deletions mesonbuild/compilers/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .mixins.emscripten import EmscriptenMixin
from .mixins.metrowerks import MetrowerksCompiler
from .mixins.metrowerks import mwccarm_instruction_set_args, mwcceppc_instruction_set_args
from .mixins.tasking import TaskingCompiler
from .compilers import (
gnu_winlibs,
msvc_winlibs,
Expand Down Expand Up @@ -791,3 +792,28 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]
if std.value != 'none':
args.append('-lang ' + std.value)
return args

class _TaskingCCompiler(TaskingCompiler, CCompiler):
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)
TaskingCompiler.__init__(self)

class TaskingTricoreCCompiler(_TaskingCCompiler):
id = 'cctc'

class TaskingArmCCompiler(_TaskingCCompiler):
id = 'ccarm'

class Tasking8051CCompiler(_TaskingCCompiler):
id = 'cc51'

class TaskingMCSCCompiler(_TaskingCCompiler):
id = 'ccmcs'

class TaskingPCPCCompiler(_TaskingCCompiler):
id = 'ccpcp'
8 changes: 8 additions & 0 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class CompileCheckMode(enum.Enum):
OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.',
MSCRT_VALS + ['from_buildtype', 'static_from_buildtype'],
'from_buildtype'),
OptionKey('b_tasking_mil_link'): coredata.UserBooleanOption('Use TASKING compiler families MIL linking feature', False),
}

def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
Expand Down Expand Up @@ -1308,6 +1309,13 @@ def get_preprocessor(self) -> Compiler:
"""
raise EnvironmentException(f'{self.get_id()} does not support preprocessor')

def get_tasking_mil_link_args(self, option_enabled: bool) -> T.List[str]:
"""
Argument for enabling TASKING's MIL link feature,
for most compilers, this will return nothing.
"""
return []

def get_global_options(lang: str,
comp: T.Type[Compiler],
for_machine: MachineChoice,
Expand Down
43 changes: 43 additions & 0 deletions mesonbuild/compilers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,17 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker
return linkers.MetrowerksStaticLinkerARM(linker)
else:
return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker)
if 'TASKING VX-toolset' in err:
if 'TriCore' in err:
return linkers.TaskingTricoreStaticLinker(linker)
if 'ARM' in err:
return linkers.TaskingARMStaticLinker(linker)
if '8051' in err:
return linkers.Tasking8051StaticLinker(linker)
if 'PCP' in err:
return linkers.TaskingPCPStaticLinker(linker)
else:
return linkers.TaskingMCSStaticLinker(linker)
if p.returncode == 0:
return linkers.ArLinker(compiler.for_machine, linker)
if p.returncode == 1 and err.startswith('usage'): # OSX
Expand Down Expand Up @@ -594,6 +605,38 @@ def sanitize(p: str) -> str:
return cls(
ccache, compiler, compiler_version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
if 'TASKING VX-toolset' in err:
if 'TriCore' in err:
cls = c.TaskingTricoreCCompiler
lnk = linkers.TaskingTricoreLinker
elif 'ARM' in err:
cls = c.TaskingArmCCompiler
lnk = linkers.TaskingARMLinker
elif '8051' in err:
cls = c.Tasking8051CCompiler
lnk = linkers.Tasking8051Linker
elif 'PCP' in err:
cls = c.TaskingPCPCCompiler
lnk = linkers.TaskingPCPLinker
elif 'MCS' in err:
cls = c.TaskingMCSCCompiler
lnk = linkers.TaskingMCSLinker
else:
raise EnvironmentException('Failed to detect linker for TASKING VX-toolset compiler. Please update your cross file(s).')

tasking_ver_match = re.search(r'v([0-9]+)\.([0-9]+)r([0-9]+) Build ([0-9]+)', err)
assert tasking_ver_match is not None, 'for mypy'
tasking_version = '.'.join(x for x in tasking_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 None:
raise MesonException(f'{cls.language}_ld was not properly defined in your cross file')

linker = lnk(ld, for_machine, version=tasking_version) # Fix needed here
return cls(
ccache, compiler, tasking_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}')
Expand Down
Loading

0 comments on commit fea42a5

Please sign in to comment.