Skip to content

Commit

Permalink
Added ARMCLANG compiler support for C/C++ (mesonbuild#3717)
Browse files Browse the repository at this point in the history
  • Loading branch information
sompen authored and jpakkane committed Jun 20, 2018
1 parent f3c01a3 commit 7140afc
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 2 deletions.
20 changes: 20 additions & 0 deletions cross/armclang.txt
Original file line number Diff line number Diff line change
@@ -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'
1 change: 1 addition & 0 deletions docs/markdown/Reference-tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
25 changes: 25 additions & 0 deletions docs/markdown/snippets/armclang-cross.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 4 additions & 2 deletions mesonbuild/compilers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,19 @@
IntelCompiler,
)
from .c import (
ArmCCompiler,
CCompiler,
ArmCCompiler,
ArmclangCCompiler,
ClangCCompiler,
GnuCCompiler,
ElbrusCCompiler,
IntelCCompiler,
VisualStudioCCompiler,
)
from .cpp import (
ArmCPPCompiler,
CPPCompiler,
ArmCPPCompiler,
ArmclangCPPCompiler,
ClangCPPCompiler,
GnuCPPCompiler,
ElbrusCPPCompiler,
Expand Down
29 changes: 29 additions & 0 deletions mesonbuild/compilers/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
vs32_instruction_set_args,
vs64_instruction_set_args,
ArmCompiler,
ArmclangCompiler,
ClangCompiler,
Compiler,
CompilerArgs,
Expand Down Expand Up @@ -979,6 +980,34 @@ def get_linker_always_args(self):
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)
Expand Down
80 changes: 80 additions & 0 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ def is_library(fname):
'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'],
Expand Down Expand Up @@ -1414,6 +1420,80 @@ def openmp_flags(self):
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):
Expand Down
29 changes: 29 additions & 0 deletions mesonbuild/compilers/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ElbrusCompiler,
IntelCompiler,
ArmCompiler,
ArmclangCompiler,
)

class CPPCompiler(CCompiler):
Expand Down Expand Up @@ -98,6 +99,34 @@ def language_stdlib_only_link_flags(self):
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)
Expand Down
18 changes: 18 additions & 0 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
from .compilers import (
ArmCCompiler,
ArmCPPCompiler,
ArmclangCCompiler,
ArmclangCPPCompiler,
ClangCCompiler,
ClangCPPCompiler,
ClangObjCCompiler,
Expand Down Expand Up @@ -553,6 +555,22 @@ def sanitize(p):
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
Expand Down

0 comments on commit 7140afc

Please sign in to comment.