Skip to content

Commit

Permalink
Merge pull request #12342 from gerioldman/TaskingCCompiler
Browse files Browse the repository at this point in the history
Add support for the TASKING compiler family, and its MIL linking feature
  • Loading branch information
jpakkane authored Jan 9, 2025
2 parents d7c2613 + b95e177 commit 5713f6a
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 25 deletions.
3 changes: 3 additions & 0 deletions docs/markdown/Reference-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ These are return values of the `get_id` (Compiler family) and
| armasm | Microsoft Macro Assembler for ARM and AARCH64 (Since 0.64.0) | |
| mwasmarm | Metrowerks Assembler for Embedded ARM | |
| mwasmeppc | Metrowerks Assembler for Embedded PowerPC | |
| tasking | TASKING VX-toolset | |

## Linker ids

Expand Down Expand Up @@ -80,6 +81,7 @@ These are return values of the `get_linker_id` method in a compiler object.
| 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 |
| tasking | TASKING VX-toolset |

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 Expand Up @@ -139,6 +141,7 @@ set in the cross file.
| wasm64 | 64 bit Webassembly |
| x86 | 32 bit x86 processor |
| x86_64 | 64 bit x86 processor |
| tricore | Tricore 32 bit processor |


Any cpu family not listed in the above list is not guaranteed to
Expand Down
21 changes: 16 additions & 5 deletions mesonbuild/backend/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
from .. import programs
from .. import mesonlib
from .. import mlog
from ..compilers import LANGUAGES_USING_LDFLAGS, detect
from ..compilers import LANGUAGES_USING_LDFLAGS, detect, lang_suffixes
from ..mesonlib import (
File, MachineChoice, MesonException, OrderedSet,
ExecutableSerialisation, classify_unity_sources,
ExecutableSerialisation, EnvironmentException,
classify_unity_sources, get_compiler_for_source
)
from ..options import OptionKey

Expand Down Expand Up @@ -837,7 +838,7 @@ def canonicalize_filename(fname: str) -> str:
fname = fname.replace(ch, '_')
return hashed + fname

def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString', targetdir: T.Optional[str] = None) -> str:
def object_filename_from_source(self, target: build.BuildTarget, compiler: Compiler, source: 'FileOrString', targetdir: T.Optional[str] = None) -> str:
assert isinstance(source, mesonlib.File)
if isinstance(target, build.CompileTarget):
return target.sources_map[source]
Expand Down Expand Up @@ -868,7 +869,16 @@ def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOr
gen_source = os.path.relpath(os.path.join(build_dir, rel_src),
os.path.join(self.environment.get_source_dir(), target.get_subdir()))
machine = self.environment.machines[target.for_machine]
ret = self.canonicalize_filename(gen_source) + '.' + machine.get_object_suffix()
object_suffix = machine.get_object_suffix()
# For the TASKING compiler, in case of LTO or prelinking the object suffix has to be .mil
if compiler.get_id() == 'tasking':
if target.get_option(OptionKey('b_lto')) or (isinstance(target, build.StaticLibrary) and target.prelink):
if not source.rsplit('.', 1)[1] in lang_suffixes['c']:
if isinstance(target, build.StaticLibrary) and not target.prelink:
raise EnvironmentException('Tried using MIL linking for a static library with a assembly file. This can only be done if the static library is prelinked or disable \'b_lto\'.')
else:
object_suffix = 'mil'
ret = self.canonicalize_filename(gen_source) + '.' + object_suffix
if targetdir is not None:
return os.path.join(targetdir, ret)
return ret
Expand Down Expand Up @@ -924,7 +934,8 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_buil
sources.append(_src)

for osrc in sources:
objname = self.object_filename_from_source(extobj.target, osrc, targetdir)
compiler = get_compiler_for_source(extobj.target.compilers.values(), osrc)
objname = self.object_filename_from_source(extobj.target, compiler, osrc, targetdir)
objpath = os.path.join(proj_dir_to_build_root, objname)
result.append(objpath)

Expand Down
76 changes: 67 additions & 9 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def _quoter(x: NinjaCommandArg, qf: T.Callable[[str], str] = quote_func) -> str:
def write(self, outfile: T.TextIO) -> None:
rspfile_args = self.args
rspfile_quote_func: T.Callable[[str], str]
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 @@ -261,7 +261,10 @@ def rule_iter() -> T.Iterable[str]:
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 @@ -412,7 +415,7 @@ def write(self, outfile: T.TextIO) -> None:
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 @@ -732,6 +735,11 @@ def generate_compdb(self) -> None:
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
if compiler.get_id() == 'tasking':
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 @@ -1078,7 +1086,10 @@ def generate_target(self, target) -> None:
# 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:

if not isinstance(target, build.StaticLibrary):
final_obj_list = obj_list
elif target.prelink:
final_obj_list = self.generate_prelink(target, obj_list)
else:
final_obj_list = obj_list
Expand Down Expand Up @@ -2486,6 +2497,33 @@ def generate_llvm_ir_compile_rule(self, compiler) -> None:
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: str, compiler: Compiler) -> None:
if langname == 'java':
self.generate_java_compile_rule(compiler)
Expand Down Expand Up @@ -2576,6 +2614,8 @@ def generate_compile_rules(self) -> None:
for langname, compiler in clist.items():
if compiler.get_id() == 'clang':
self.generate_llvm_ir_compile_rule(compiler)
if compiler.get_id() == 'tasking':
self.generate_tasking_mil_compile_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 @@ -3015,7 +3055,7 @@ def generate_single_compile(self, target: build.BuildTarget, src,
raise AssertionError(f'BUG: broken generated source file handling for {src!r}')
else:
raise InvalidArguments(f'Invalid source type: {src!r}')
obj_basename = self.object_filename_from_source(target, src)
obj_basename = self.object_filename_from_source(target, compiler, src)
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename)
dep_file = compiler.depfile_for_object(rel_obj)

Expand All @@ -3036,8 +3076,17 @@ 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_lto')
if compiler.get_id() == 'tasking':
if ((isinstance(target, build.StaticLibrary) and target.prelink) or 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)
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 @@ -3414,13 +3463,19 @@ def generate_prelink(self, target, obj_list):

prelinker = target.get_prelinker()
cmd = prelinker.exelist[:]
cmd += prelinker.get_prelink_args(prelink_name, obj_list)
obj_list, args = prelinker.get_prelink_args(prelink_name, obj_list)
cmd += args
if prelinker.get_prelink_append_compile_args():
compile_args = self._generate_single_compile_base_args(target, prelinker)
compile_args += self._generate_single_compile_target_args(target, prelinker)
compile_args = compile_args.compiler.compiler_args(compile_args)
cmd += compile_args.to_native()

cmd = self.replace_paths(target, cmd)
elem.add_item('COMMAND', cmd)
elem.add_item('description', f'Prelinking {prelink_name}')
self.add_build(elem)
return [prelink_name]
return obj_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 []
Expand Down Expand Up @@ -3562,6 +3617,9 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.
for t in target.link_depends])
elem = NinjaBuildElement(self.all_outputs, outname, linker_rule, obj_list, implicit_outs=implicit_outs)
elem.add_dep(dep_targets + custom_target_libraries)
if linker.get_id() == 'tasking':
if len([x for x in dep_targets + custom_target_libraries if x.endswith('.ma')]) > 0 and not target.get_option(OptionKey('b_lto')):
raise MesonException(f'Tried to link the target named \'{target.name}\' with a MIL archive without LTO enabled! This causes the compiler to ignore the archive.')

# Compiler args must be included in TI C28x linker commands.
if linker.get_id() in {'c2000', 'c6000', 'ti'}:
Expand Down
4 changes: 2 additions & 2 deletions mesonbuild/backend/vs2010backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1725,7 +1725,7 @@ def path_normalize_add(path, lis):
self.add_preprocessor_defines(lang, inc_cl, file_defines)
self.add_include_dirs(lang, inc_cl, file_inc_dirs)
ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \
self.object_filename_from_source(target, s)
self.object_filename_from_source(target, compiler, s)
for s in gen_src:
if path_normalize_add(s, previous_sources):
inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s)
Expand All @@ -1739,7 +1739,7 @@ def path_normalize_add(path, lis):
self.add_include_dirs(lang, inc_cl, file_inc_dirs)
s = File.from_built_file(target.get_subdir(), s)
ET.SubElement(inc_cl, 'ObjectFileName').text = "$(IntDir)" + \
self.object_filename_from_source(target, s)
self.object_filename_from_source(target, compiler, s)
for lang, headers in pch_sources.items():
impl = headers[1]
if impl and path_normalize_add(impl, previous_sources):
Expand Down
7 changes: 6 additions & 1 deletion mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2019,6 +2019,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() == 'tasking'):
self.suffix = 'elf'
else:
self.suffix = machine.get_exe_suffix()
self.filename = self.name
Expand Down Expand Up @@ -2174,7 +2176,10 @@ def post_init(self) -> None:
elif self.rust_crate_type == 'staticlib':
self.suffix = 'a'
else:
self.suffix = 'a'
if 'c' in self.compilers and self.compilers['c'].get_id() == 'tasking':
self.suffix = 'ma' if self.options.get_value('b_lto') and not self.prelink else 'a'
else:
self.suffix = 'a'
self.filename = self.prefix + self.name + '.' + self.suffix
self.outputs[0] = self.filename

Expand Down
12 changes: 12 additions & 0 deletions mesonbuild/compilers/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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 @@ -830,3 +831,14 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]
if std != 'none':
args.append('-lang ' + std)
return args

class TaskingCCompiler(TaskingCompiler, CCompiler):
id = 'tasking'

def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo',
linker: T.Optional['DynamicLinker'] = None,
full_version: T.Optional[str] = None):
CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross,
info, linker=linker, full_version=full_version)
TaskingCompiler.__init__(self)
8 changes: 6 additions & 2 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ class CompileResult(HoldableObject):
output_name: T.Optional[str] = field(default=None, init=False)
cached: bool = field(default=False, init=False)


class Compiler(HoldableObject, metaclass=abc.ABCMeta):

# Libraries to ignore in find_library() since they are provided by the
# compiler or the C library. Currently only used for MSVC.
ignore_libs: T.List[str] = []
Expand Down Expand Up @@ -1327,9 +1327,13 @@ def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]:
# TODO: using a TypeDict here would improve this
raise EnvironmentException(f'{self.id} does not implement get_feature_args')

def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.Tuple[T.List[str], T.List[str]]:
raise EnvironmentException(f'{self.id} does not know how to do prelinking.')

def get_prelink_append_compile_args(self) -> bool:
"""Controls whether compile args have to be used for prelinking or not"""
return False

def rsp_file_syntax(self) -> 'RSPFileSyntax':
"""The format of the RSP file that this compiler supports.
Expand Down
19 changes: 19 additions & 0 deletions mesonbuild/compilers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker
return linkers.MetrowerksStaticLinkerARM(linker)
else:
return linkers.MetrowerksStaticLinkerEmbeddedPowerPC(linker)
if 'TASKING VX-toolset' in err:
return linkers.TaskingStaticLinker(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 @@ -605,6 +607,23 @@ def sanitize(p: T.Optional[str]) -> T.Optional[str]:
return cls(
ccache, compiler, compiler_version, for_machine, is_cross, info,
full_version=full_version, linker=linker)
if 'TASKING VX-toolset' in err:
cls = c.TaskingCCompiler
lnk = linkers.TaskingLinker

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)
return cls(
ccache, compiler, tasking_version, for_machine, is_cross, info,
full_version=full_version, linker=linker)

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

0 comments on commit 5713f6a

Please sign in to comment.