Added ARMCLANG compiler support for C/C++ (#3717)

pull/3771/head
Vasu Penugonda 6 years ago committed by Jussi Pakkanen
parent f3c01a3c4f
commit 7140afc0a8
  1. 20
      cross/armclang.txt
  2. 1
      docs/markdown/Reference-tables.md
  3. 25
      docs/markdown/snippets/armclang-cross.md
  4. 6
      mesonbuild/compilers/__init__.py
  5. 29
      mesonbuild/compilers/c.py
  6. 80
      mesonbuild/compilers/compilers.py
  7. 29
      mesonbuild/compilers/cpp.py
  8. 18
      mesonbuild/environment.py

@ -0,0 +1,20 @@
# This file assumes that path to the arm compiler toolchain is added
# to the environment(PATH) variable, so that Meson can find
# the armclang, armlink and armar while building.
[binaries]
c = 'armclang'
cpp = 'armclang'
ar = 'armar'
strip = 'armar'
[properties]
# The '--target', '-mcpu' options with the appropriate values should be mentioned
# to cross compile c/c++ code with armclang.
c_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus']
cpp_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus']
[host_machine]
system = 'bare metal' # Update with your system name - bare metal/OS.
cpu_family = 'arm'
cpu = 'Cortex-M0+'
endian = 'little'

@ -23,6 +23,7 @@ These are return values of the `get_id` method in a compiler object.
| nagfor | The NAG Fortran compiler |
| lcc | Elbrus C/C++/Fortran Compiler |
| arm | ARM compiler |
| armclang | ARMCLANG compiler |
## Script environment variables

@ -0,0 +1,25 @@
## ARM compiler(version 6) for C and CPP
Cross-compilation is now supported for ARM targets using ARM compiler version 6 - ARMCLANG.
The required ARMCLANG compiler options for building a shareable library are not included in the
current Meson implementation for ARMCLANG support, so it can not build shareable libraries.
This current Meson implementation for ARMCLANG support can not build assembly files with
arm syntax(we need to use armasm instead of ARMCLANG for the .s files with this syntax)
and only supports gnu syntax.
The default extension of the executable output is .axf.
The environment path should be set properly for the ARM compiler executables.
The '--target', '-mcpu' options with the appropriate values should be mentioned
in the cross file as shown in the snippet below.
```
[properties]
c_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus']
cpp_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus']
```
Note:
- The current changes are tested on Windows only.
- PIC support is not enabled by default for ARM,
if users want to use it, they need to add the required arguments
explicitly from cross-file(c_args/c++_args) or some other way.

@ -126,8 +126,9 @@ from .compilers import (
IntelCompiler,
)
from .c import (
ArmCCompiler,
CCompiler,
ArmCCompiler,
ArmclangCCompiler,
ClangCCompiler,
GnuCCompiler,
ElbrusCCompiler,
@ -135,8 +136,9 @@ from .c import (
VisualStudioCCompiler,
)
from .cpp import (
ArmCPPCompiler,
CPPCompiler,
ArmCPPCompiler,
ArmclangCPPCompiler,
ClangCPPCompiler,
GnuCPPCompiler,
ElbrusCPPCompiler,

@ -32,6 +32,7 @@ from .compilers import (
vs32_instruction_set_args,
vs64_instruction_set_args,
ArmCompiler,
ArmclangCompiler,
ClangCompiler,
Compiler,
CompilerArgs,
@ -979,6 +980,34 @@ class ClangCCompiler(ClangCompiler, CCompiler):
return basic
class ArmclangCCompiler(ArmclangCompiler, CCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
ArmclangCompiler.__init__(self)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'1': default_warn_args,
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
opts = CCompiler.get_options(self)
opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use',
['none', 'c90', 'c99', 'c11',
'gnu90', 'gnu99', 'gnu11'],
'none')})
return opts
def get_option_compile_args(self, options):
args = []
std = options['c_std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
def get_option_link_args(self, options):
return []
class GnuCCompiler(GnuCompiler, CCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)

@ -131,6 +131,12 @@ gnulike_buildtype_args = {'plain': [],
'release': ['-O3'],
'minsize': ['-Os', '-g']}
armclang_buildtype_args = {'plain': [],
'debug': ['-O0', '-g'],
'debugoptimized': ['-O1', '-g'],
'release': ['-Os'],
'minsize': ['-Oz']}
arm_buildtype_args = {'plain': [],
'debug': ['-O0', '--debug'],
'debugoptimized': ['-O1', '--debug'],
@ -1414,6 +1420,80 @@ class ClangCompiler:
return []
class ArmclangCompiler:
def __init__(self):
if not self.is_cross:
raise EnvironmentException('armclang supports only cross-compilation.')
# Check whether 'armlink.exe' is available in path
self.linker_exe = 'armlink.exe'
args = '--vsn'
try:
p, stdo, stderr = Popen_safe(self.linker_exe, args)
except OSError as e:
err_msg = 'Unknown linker\nRunning "{0}" gave \n"{1}"'.format(' '.join([self.linker_exe] + [args]), e)
raise EnvironmentException(err_msg)
# Verify the armlink version
ver_str = re.search('.*Component.*', stdo)
if ver_str:
ver_str = ver_str.group(0)
else:
EnvironmentException('armlink version string not found')
# Using the regular expression from environment.search_version,
# which is used for searching compiler version
version_regex = '(?<!(\d|\.))(\d{1,2}(\.\d+)+(-[a-zA-Z0-9]+)?)'
linker_ver = re.search(version_regex, ver_str)
if linker_ver:
linker_ver = linker_ver.group(0)
if not version_compare(self.version, '==' + linker_ver):
raise EnvironmentException('armlink version does not match with compiler version')
self.id = 'armclang'
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
'b_ndebug', 'b_staticpic', 'b_colorout']
# Assembly
self.can_compile_suffixes.update('s')
def can_linker_accept_rsp(self):
return False
def get_pic_args(self):
# PIC support is not enabled by default for ARM,
# if users want to use it, they need to add the required arguments explicitly
return []
def get_colorout_args(self, colortype):
return clang_color_args[colortype][:]
def get_buildtype_args(self, buildtype):
return armclang_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype):
return arm_buildtype_linker_args[buildtype]
# Override CCompiler.get_std_shared_lib_link_args
def get_std_shared_lib_link_args(self):
return []
def get_pch_suffix(self):
return 'gch'
def get_pch_use_args(self, pch_dir, header):
# Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
# This flag is internal to Clang (or at least not documented on the man page)
# so it might change semantics at any time.
return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
# Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget, outfile):
return []
# Override CCompiler.build_rpath_args
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return []
def get_linker_exelist(self):
return [self.linker_exe]
# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
class IntelCompiler:
def __init__(self, icc_type):

@ -27,6 +27,7 @@ from .compilers import (
ElbrusCompiler,
IntelCompiler,
ArmCompiler,
ArmclangCompiler,
)
class CPPCompiler(CCompiler):
@ -98,6 +99,34 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return ['-lstdc++']
class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
ArmclangCompiler.__init__(self)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'1': default_warn_args,
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
def get_options(self):
opts = CPPCompiler.get_options(self)
opts.update({'cpp_std': coredata.UserComboOption('cpp_std', 'C++ language standard to use',
['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17'
'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'],
'none')})
return opts
def get_option_compile_args(self, options):
args = []
std = options['cpp_std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
def get_option_link_args(self, options):
return []
class GnuCPPCompiler(GnuCompiler, CPPCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrap, defines, **kwargs):
CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs)

@ -40,6 +40,8 @@ from .compilers import (
from .compilers import (
ArmCCompiler,
ArmCPPCompiler,
ArmclangCCompiler,
ArmclangCPPCompiler,
ClangCCompiler,
ClangCPPCompiler,
ClangObjCCompiler,
@ -553,6 +555,22 @@ class Environment:
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
return cls(ccache + compiler, version, gtype, 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,
# instead it is present in second line, startswith 'Component:'.
# So, searching for the 'Component' in out although we know it is
# present in second line, as we are not sure about the
# output format in future versions
arm_ver_str = re.search('.*Component.*', out)
if arm_ver_str is None:
popen_exceptions[' '.join(compiler)] = 'version string not found'
continue
arm_ver_str = arm_ver_str.group(0)
# Override previous values
version = search_version(arm_ver_str)
full_version = arm_ver_str
cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler
return cls(ccache + compiler, version, is_cross, exe_wrap, full_version=full_version)
if 'clang' in out:
if 'Apple' in out or mesonlib.for_darwin(want_cross, self):
cltype = CLANG_OSX

Loading…
Cancel
Save