Abstract shared GCC/Clang/ICC methods in GnuLikeCompiler

pull/4205/head
David Seifert 6 years ago committed by Jussi Pakkanen
parent b6f03f897b
commit 115962e466
  1. 15
      mesonbuild/compilers/c.py
  2. 243
      mesonbuild/compilers/compilers.py
  3. 4
      mesonbuild/compilers/cpp.py

@ -1152,9 +1152,6 @@ class GnuCCompiler(GnuCompiler, CCompiler):
return options['c_winlibs'].value[:] return options['c_winlibs'].value[:]
return [] return []
def get_std_shared_lib_link_args(self):
return ['-shared']
def get_pch_use_args(self, pch_dir, header): def get_pch_use_args(self, pch_dir, header):
return ['-fpch-preprocess', '-include', os.path.basename(header)] return ['-fpch-preprocess', '-include', os.path.basename(header)]
@ -1211,18 +1208,6 @@ class IntelCCompiler(IntelCompiler, CCompiler):
args.append('-std=' + std.value) args.append('-std=' + std.value)
return args return args
def get_std_shared_lib_link_args(self):
return ['-shared']
def get_std_shared_module_link_args(self, options):
if self.compiler_type.is_osx_compiler:
return ['-bundle', '-Wl,-undefined,dynamic_lookup']
return ['-shared']
def has_arguments(self, args, env, code, mode):
# -diag-error 10148 is required to catch invalid -W options
return super().has_arguments(args + ['-diag-error', '10006', '-diag-error', '10148'], env, code, mode)
class VisualStudioCCompiler(CCompiler): class VisualStudioCCompiler(CCompiler):
std_warn_args = ['/W3'] std_warn_args = ['/W3']

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import contextlib, enum, os.path, re, tempfile, shlex import abc, contextlib, enum, os.path, re, tempfile, shlex
import subprocess import subprocess
from ..linkers import StaticLinker from ..linkers import StaticLinker
@ -1171,13 +1171,6 @@ class CompilerType(enum.Enum):
return self.name in ('GCC_MINGW', 'GCC_CYGWIN', 'CLANG_MINGW', 'ICC_WIN') return self.name in ('GCC_MINGW', 'GCC_CYGWIN', 'CLANG_MINGW', 'ICC_WIN')
# GNU ld cannot be installed on macOS
# https://github.com/Homebrew/homebrew-core/issues/17794#issuecomment-328174395
# Hence, we don't need to differentiate between OS and ld
# for the sake of adding as-needed support
GNU_LD_AS_NEEDED = '-Wl,--as-needed'
APPLE_LD_AS_NEEDED = '-Wl,-dead_strip_dylibs'
def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion): def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion):
install_name = prefix + shlib_name install_name = prefix + shlib_name
if soversion is not None: if soversion is not None:
@ -1277,47 +1270,32 @@ def gnulike_default_include_dirs(compiler, lang):
mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd))) mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd)))
return paths return paths
class GnuCompiler:
# Functionality that is common to all GNU family compilers. class GnuLikeCompiler(abc.ABC):
def __init__(self, compiler_type, defines): """
self.id = 'gcc' GnuLikeCompiler is a common interface to all compilers implementing
the GNU-style commandline interface. This includes GCC, Clang
and ICC. Certain functionality between them is different and requires
that the actual concrete subclass define their own implementation.
"""
def __init__(self, compiler_type):
self.compiler_type = compiler_type self.compiler_type = compiler_type
self.defines = defines or {}
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage', self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
'b_colorout', 'b_ndebug', 'b_staticpic'] 'b_ndebug', 'b_staticpic', 'b_asneeded']
if not self.compiler_type.is_osx_compiler: if not self.compiler_type.is_osx_compiler:
self.base_options.append('b_lundef') self.base_options.append('b_lundef')
self.base_options.append('b_asneeded') # All GCC-like backends can do assembly
# All GCC backends can do assembly
self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('s')
# TODO: centralise this policy more globally, instead
# of fragmenting it into GnuCompiler and ClangCompiler
def get_asneeded_args(self): def get_asneeded_args(self):
# GNU ld cannot be installed on macOS
# https://github.com/Homebrew/homebrew-core/issues/17794#issuecomment-328174395
# Hence, we don't need to differentiate between OS and ld
# for the sake of adding as-needed support
if self.compiler_type.is_osx_compiler: if self.compiler_type.is_osx_compiler:
return APPLE_LD_AS_NEEDED return '-Wl,-dead_strip_dylibs'
else: else:
return GNU_LD_AS_NEEDED return '-Wl,--as-needed'
def get_colorout_args(self, colortype):
if mesonlib.version_compare(self.version, '>=4.9.0'):
return gnu_color_args[colortype][:]
return []
def get_warn_args(self, level):
args = super().get_warn_args(level)
if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
# -Wpedantic was added in 4.8.0
# https://gcc.gnu.org/gcc-4.8/changes.html
args[args.index('-Wpedantic')] = '-pedantic'
return args
def has_builtin_define(self, define):
return define in self.defines
def get_builtin_define(self, define):
if define in self.defines:
return self.defines[define]
def get_pic_args(self): def get_pic_args(self):
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler: if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
@ -1327,8 +1305,9 @@ class GnuCompiler:
def get_buildtype_args(self, buildtype): def get_buildtype_args(self, buildtype):
return gnulike_buildtype_args[buildtype] return gnulike_buildtype_args[buildtype]
@abc.abstractmethod
def get_optimization_args(self, optimization_level): def get_optimization_args(self, optimization_level):
return gnu_optimization_args[optimization_level] raise NotImplementedError("get_optimization_args not implemented")
def get_debug_args(self, is_debug): def get_debug_args(self, is_debug):
return clike_debug_args[is_debug] return clike_debug_args[is_debug]
@ -1338,8 +1317,9 @@ class GnuCompiler:
return apple_buildtype_linker_args[buildtype] return apple_buildtype_linker_args[buildtype]
return gnulike_buildtype_linker_args[buildtype] return gnulike_buildtype_linker_args[buildtype]
@abc.abstractmethod
def get_pch_suffix(self): def get_pch_suffix(self):
return 'gch' raise NotImplementedError("get_pch_suffix not implemented")
def split_shlib_to_parts(self, fname): def split_shlib_to_parts(self, fname):
return os.path.dirname(fname), fname return os.path.dirname(fname), fname
@ -1363,6 +1343,57 @@ class GnuCompiler:
return result return result
return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive'] return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
def get_instruction_set_args(self, instruction_set):
return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
@abc.abstractmethod
def openmp_flags(self):
raise NotImplementedError("openmp_flags not implemented")
def gnu_symbol_visibility_args(self, vistype):
return gnu_symbol_visibility_args[vistype]
class GnuCompiler(GnuLikeCompiler):
"""
GnuCompiler represents an actual GCC in its many incarnations.
Compilers imitating GCC (Clang/Intel) should use the GnuLikeCompiler ABC.
"""
def __init__(self, compiler_type, defines):
super().__init__(compiler_type)
self.id = 'gcc'
self.defines = defines or {}
self.base_options.append('b_colorout')
def get_colorout_args(self, colortype):
if mesonlib.version_compare(self.version, '>=4.9.0'):
return gnu_color_args[colortype][:]
return []
def get_warn_args(self, level):
args = super().get_warn_args(level)
if mesonlib.version_compare(self.version, '<4.8.0') and '-Wpedantic' in args:
# -Wpedantic was added in 4.8.0
# https://gcc.gnu.org/gcc-4.8/changes.html
args[args.index('-Wpedantic')] = '-pedantic'
return args
def has_builtin_define(self, define):
return define in self.defines
def get_builtin_define(self, define):
if define in self.defines:
return self.defines[define]
def get_optimization_args(self, optimization_level):
return gnu_optimization_args[optimization_level]
def get_pch_suffix(self):
return 'gch'
def gen_vs_module_defs_args(self, defsfile): def gen_vs_module_defs_args(self, defsfile):
if not isinstance(defsfile, str): if not isinstance(defsfile, str):
raise RuntimeError('Module definitions file should be str') raise RuntimeError('Module definitions file should be str')
@ -1378,17 +1409,9 @@ class GnuCompiler:
return ['-mwindows'] return ['-mwindows']
return [] return []
def get_instruction_set_args(self, instruction_set):
return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
def openmp_flags(self): def openmp_flags(self):
return ['-fopenmp'] return ['-fopenmp']
def gnu_symbol_visibility_args(self, vistype):
return gnu_symbol_visibility_args[vistype]
class ElbrusCompiler(GnuCompiler): class ElbrusCompiler(GnuCompiler):
# Elbrus compiler is nearly like GCC, but does not support # Elbrus compiler is nearly like GCC, but does not support
@ -1428,50 +1451,23 @@ class ElbrusCompiler(GnuCompiler):
break break
return paths return paths
class ClangCompiler:
class ClangCompiler(GnuLikeCompiler):
def __init__(self, compiler_type): def __init__(self, compiler_type):
super().__init__(compiler_type)
self.id = 'clang' self.id = 'clang'
self.compiler_type = compiler_type self.base_options.append('b_colorout')
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
'b_ndebug', 'b_staticpic', 'b_colorout']
if self.compiler_type.is_osx_compiler: if self.compiler_type.is_osx_compiler:
self.base_options.append('b_bitcode') self.base_options.append('b_bitcode')
else: # All Clang backends can also do LLVM IR
self.base_options.append('b_lundef') self.can_compile_suffixes.add('ll')
self.base_options.append('b_asneeded')
# All Clang backends can do assembly and LLVM IR
self.can_compile_suffixes.update(['ll', 's'])
# TODO: centralise this policy more globally, instead
# of fragmenting it into GnuCompiler and ClangCompiler
def get_asneeded_args(self):
if self.compiler_type.is_osx_compiler:
return APPLE_LD_AS_NEEDED
else:
return GNU_LD_AS_NEEDED
def get_pic_args(self):
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
return [] # On Window and OS X, pic is always on.
return ['-fPIC']
def get_colorout_args(self, colortype): def get_colorout_args(self, colortype):
return clang_color_args[colortype][:] return clang_color_args[colortype][:]
def get_buildtype_args(self, buildtype):
return gnulike_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype):
if self.compiler_type.is_osx_compiler:
return apple_buildtype_linker_args[buildtype]
return gnulike_buildtype_linker_args[buildtype]
def get_optimization_args(self, optimization_level): def get_optimization_args(self, optimization_level):
return clike_optimization_args[optimization_level] return clike_optimization_args[optimization_level]
def get_debug_args(self, is_debug):
return clike_debug_args[is_debug]
def get_pch_suffix(self): def get_pch_suffix(self):
return 'pch' return 'pch'
@ -1481,9 +1477,6 @@ class ClangCompiler:
# so it might change semantics at any time. # so it might change semantics at any time.
return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))] return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]
def get_soname_args(self, *args):
return get_gcc_soname_args(self.compiler_type, *args)
def has_multi_arguments(self, args, env): def has_multi_arguments(self, args, env):
myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'] myargs = ['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument']
if mesonlib.version_compare(self.version, '>=3.6.0'): if mesonlib.version_compare(self.version, '>=3.6.0'):
@ -1503,25 +1496,6 @@ class ClangCompiler:
extra_args.append('-Wl,-no_weak_imports') extra_args.append('-Wl,-no_weak_imports')
return super().has_function(funcname, prefix, env, extra_args, dependencies) return super().has_function(funcname, prefix, env, extra_args, dependencies)
def get_std_shared_module_link_args(self, options):
if self.compiler_type.is_osx_compiler:
return ['-bundle', '-Wl,-undefined,dynamic_lookup']
return ['-shared']
def get_link_whole_for(self, args):
if self.compiler_type.is_osx_compiler:
result = []
for a in args:
result += ['-Wl,-force_load', a]
return result
return ['-Wl,--whole-archive'] + args + ['-Wl,--no-whole-archive']
def get_instruction_set_args(self, instruction_set):
return gnulike_instruction_set_args.get(instruction_set, None)
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
def openmp_flags(self): def openmp_flags(self):
if version_compare(self.version, '>=3.8.0'): if version_compare(self.version, '>=3.8.0'):
return ['-fopenmp'] return ['-fopenmp']
@ -1531,8 +1505,6 @@ class ClangCompiler:
# Shouldn't work, but it'll be checked explicitly in the OpenMP dependency. # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency.
return [] return []
def gnu_symbol_visibility_args(self, vistype):
return gnu_symbol_visibility_args[vistype]
class ArmclangCompiler: class ArmclangCompiler:
def __init__(self): def __init__(self):
@ -1609,37 +1581,15 @@ class ArmclangCompiler:
# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1 # Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
class IntelCompiler: class IntelCompiler(GnuLikeCompiler):
def __init__(self, compiler_type): def __init__(self, compiler_type):
super().__init__(compiler_type)
self.id = 'intel' self.id = 'intel'
self.compiler_type = compiler_type
self.lang_header = 'none' self.lang_header = 'none'
self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
'b_colorout', 'b_ndebug', 'b_staticpic', 'b_asneeded']
if not self.compiler_type.is_osx_compiler:
self.base_options.append('b_lundef')
# Assembly
self.can_compile_suffixes.add('s')
def get_pic_args(self):
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
return [] # On Window and OS X, pic is always on.
return ['-fPIC']
def get_buildtype_args(self, buildtype):
return gnulike_buildtype_args[buildtype]
def get_buildtype_linker_args(self, buildtype):
if self.compiler_type.is_osx_compiler:
return apple_buildtype_linker_args[buildtype]
return gnulike_buildtype_linker_args[buildtype]
def get_optimization_args(self, optimization_level): def get_optimization_args(self, optimization_level):
return gnu_optimization_args[optimization_level] return gnu_optimization_args[optimization_level]
def get_debug_args(self, is_debug):
return clike_debug_args[is_debug]
def get_pch_suffix(self): def get_pch_suffix(self):
return 'pchi' return 'pchi'
@ -1650,40 +1600,15 @@ class IntelCompiler:
def get_pch_name(self, header_name): def get_pch_name(self, header_name):
return os.path.basename(header_name) + '.' + self.get_pch_suffix() return os.path.basename(header_name) + '.' + self.get_pch_suffix()
def split_shlib_to_parts(self, fname):
return os.path.dirname(fname), fname
def get_soname_args(self, *args):
return get_gcc_soname_args(self.compiler_type, *args)
# TODO: centralise this policy more globally, instead
# of fragmenting it into GnuCompiler and ClangCompiler
def get_asneeded_args(self):
if self.compiler_type.is_osx_compiler:
return APPLE_LD_AS_NEEDED
else:
return GNU_LD_AS_NEEDED
def get_std_shared_lib_link_args(self):
# FIXME: Don't know how icc works on OSX
# if self.compiler_type.is_osx_compiler:
# return ['-bundle']
return ['-shared']
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
def openmp_flags(self): def openmp_flags(self):
if version_compare(self.version, '>=15.0.0'): if version_compare(self.version, '>=15.0.0'):
return ['-qopenmp'] return ['-qopenmp']
else: else:
return ['-openmp'] return ['-openmp']
def get_link_whole_for(self, args): def has_arguments(self, args, env, code, mode):
return GnuCompiler.get_link_whole_for(self, args) # -diag-error 10148 is required to catch invalid -W options
return super().has_arguments(args + ['-diag-error', '10006', '-diag-error', '10148'], env, code, mode)
def gnu_symbol_visibility_args(self, vistype):
return gnu_symbol_visibility_args[vistype]
class ArmCompiler: class ArmCompiler:

@ -301,10 +301,6 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler):
def get_option_link_args(self, options): def get_option_link_args(self, options):
return [] return []
def has_arguments(self, args, env, code, mode):
# -diag-error 10148 is required to catch invalid -W options
return super().has_arguments(args + ['-diag-error', '10006', '-diag-error', '10148'], env, code, mode)
class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap, is_64): def __init__(self, exelist, version, is_cross, exe_wrap, is_64):

Loading…
Cancel
Save