aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2019-07-02 14:03:32 -0700
committerDylan Baker <dylan@pnwbakers.com>2019-07-15 10:59:22 -0700
commitcd5360821a0d107dbc1a097ec93524fd9336b3e9 (patch)
tree04249ea4ee7318e2c8c1ef580a325f47797077c5 /mesonbuild
parentd68969f1691515b45f0f9d438aebb120059872d9 (diff)
downloadmeson-cd5360821a0d107dbc1a097ec93524fd9336b3e9.zip
meson-cd5360821a0d107dbc1a097ec93524fd9336b3e9.tar.gz
meson-cd5360821a0d107dbc1a097ec93524fd9336b3e9.tar.bz2
compilers: split gnu and gnulike compilers out of compilers
I debated a bit whether both classes really belong in the same module, and decided that they do because the share a number of helpers.
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/compilers/__init__.py3
-rw-r--r--mesonbuild/compilers/c.py2
-rw-r--r--mesonbuild/compilers/compilers.py359
-rw-r--r--mesonbuild/compilers/cpp.py2
-rw-r--r--mesonbuild/compilers/cuda.py3
-rw-r--r--mesonbuild/compilers/d.py4
-rw-r--r--mesonbuild/compilers/fortran.py9
-rw-r--r--mesonbuild/compilers/mixins/gnu.py390
-rw-r--r--mesonbuild/compilers/objc.py3
-rw-r--r--mesonbuild/compilers/objcpp.py3
10 files changed, 405 insertions, 373 deletions
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py
index 98241a6..ac3f160 100644
--- a/mesonbuild/compilers/__init__.py
+++ b/mesonbuild/compilers/__init__.py
@@ -107,7 +107,6 @@ from .compilers import (
clink_langs,
c_suffixes,
cpp_suffixes,
- get_macos_dylib_install_name,
get_base_compile_args,
get_base_link_args,
is_header,
@@ -121,7 +120,6 @@ from .compilers import (
sort_clink,
ClangCompiler,
CompilerArgs,
- GnuCompiler,
IntelGnuLikeCompiler,
IntelVisualStudioLikeCompiler,
)
@@ -190,3 +188,4 @@ from .rust import RustCompiler
from .swift import SwiftCompiler
from .vala import ValaCompiler
from .mixins.visualstudio import VisualStudioLikeCompiler
+from .mixins.gnu import GnuCompiler, get_macos_dylib_install_name \ No newline at end of file
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 2effec6..3a7c1f9 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -22,6 +22,7 @@ from .mixins.clike import CLikeCompiler
from .mixins.ccrx import CcrxCompiler
from .mixins.arm import ArmCompiler
from .mixins.visualstudio import VisualStudioLikeCompiler
+from .mixins.gnu import GnuCompiler
from .compilers import (
gnu_winlibs,
msvc_winlibs,
@@ -29,7 +30,6 @@ from .compilers import (
ClangCompiler,
Compiler,
CompilerType,
- GnuCompiler,
ElbrusCompiler,
IntelGnuLikeCompiler,
IntelVisualStudioLikeCompiler,
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 0b06072..ed41c2e 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -13,8 +13,6 @@
# limitations under the License.
import abc, contextlib, enum, os.path, re, tempfile, shlex
-import functools
-import subprocess
from typing import List, Optional, Tuple
from pathlib import Path
@@ -30,6 +28,7 @@ from ..envconfig import (
Properties,
)
from .mixins.visualstudio import VisualStudioLikeCompiler
+from .mixins.gnu import GnuCompiler, GnuLikeCompiler
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
@@ -139,14 +138,6 @@ def is_library(fname):
suffix = fname.split('.')[-1]
return suffix in lib_suffixes
-gnulike_buildtype_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': [],
- 'minsize': [],
- 'custom': [],
- }
-
armclang_buildtype_args = {'plain': [],
'debug': ['-O0', '-g'],
'debugoptimized': ['-O1', '-g'],
@@ -168,21 +159,6 @@ pgi_buildtype_args = {'plain': [],
'minsize': [],
'custom': [],
}
-apple_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': [],
- 'minsize': [],
- 'custom': [],
- }
-
-gnulike_buildtype_linker_args = {'plain': [],
- 'debug': [],
- 'debugoptimized': [],
- 'release': ['-Wl,-O1'],
- 'minsize': [],
- 'custom': [],
- }
pgi_buildtype_linker_args = {'plain': [],
@@ -256,11 +232,6 @@ msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
'uuid.lib', 'comdlg32.lib', 'advapi32.lib']
-gnu_color_args = {'auto': ['-fdiagnostics-color=auto'],
- 'always': ['-fdiagnostics-color=always'],
- 'never': ['-fdiagnostics-color=never'],
- }
-
clang_color_args = {'auto': ['-Xclang', '-fcolor-diagnostics'],
'always': ['-Xclang', '-fcolor-diagnostics'],
'never': ['-Xclang', '-fno-color-diagnostics'],
@@ -282,14 +253,6 @@ clike_optimization_args = {'0': [],
's': ['-Os'],
}
-gnu_optimization_args = {'0': [],
- 'g': ['-Og'],
- '1': ['-O1'],
- '2': ['-O2'],
- '3': ['-O3'],
- 's': ['-Os'],
- }
-
cuda_optimization_args = {'0': [],
'g': ['-O0'],
'1': ['-O1'],
@@ -332,26 +295,6 @@ base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', T
'from_buildtype'),
}
-gnulike_instruction_set_args = {'mmx': ['-mmmx'],
- 'sse': ['-msse'],
- 'sse2': ['-msse2'],
- 'sse3': ['-msse3'],
- 'ssse3': ['-mssse3'],
- 'sse41': ['-msse4.1'],
- 'sse42': ['-msse4.2'],
- 'avx': ['-mavx'],
- 'avx2': ['-mavx2'],
- 'neon': ['-mfpu=neon'],
- }
-
-gnu_symbol_visibility_args = {'': [],
- 'default': ['-fvisibility=default'],
- 'internal': ['-fvisibility=internal'],
- 'hidden': ['-fvisibility=hidden'],
- 'protected': ['-fvisibility=protected'],
- 'inlineshidden': ['-fvisibility=hidden', '-fvisibility-inlines-hidden'],
- }
-
def sanitizer_compile_args(value):
if value == 'none':
return []
@@ -1332,32 +1275,6 @@ class CompilerType(enum.Enum):
def is_windows_compiler(self):
return self.name in ('GCC_MINGW', 'GCC_CYGWIN', 'CLANG_MINGW', 'ICC_WIN', 'ARM_WIN', 'CCRX_WIN', 'PGI_WIN')
-
-def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion):
- install_name = prefix + shlib_name
- if soversion is not None:
- install_name += '.' + soversion
- install_name += '.dylib'
- return '@rpath/' + install_name
-
-def get_gcc_soname_args(compiler_type, prefix, shlib_name, suffix, soversion, darwin_versions, is_shared_module):
- if compiler_type.is_standard_compiler:
- sostr = '' if soversion is None else '.' + soversion
- return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)]
- elif compiler_type.is_windows_compiler:
- # For PE/COFF the soname argument has no effect with GNU LD
- return []
- elif compiler_type.is_osx_compiler:
- if is_shared_module:
- return []
- name = get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion)
- args = ['-install_name', name]
- if darwin_versions:
- args += ['-compatibility_version', darwin_versions[0], '-current_version', darwin_versions[1]]
- return args
- else:
- raise RuntimeError('Not implemented yet.')
-
def get_compiler_is_linuxlike(compiler):
compiler_type = getattr(compiler, 'compiler_type', None)
return compiler_type and compiler_type.is_standard_compiler
@@ -1396,280 +1313,6 @@ def get_largefile_args(compiler):
# those features explicitly.
return []
-# TODO: The result from calling compiler should be cached. So that calling this
-# function multiple times don't add latency.
-def gnulike_default_include_dirs(compiler, lang):
- if lang == 'cpp':
- lang = 'c++'
- env = os.environ.copy()
- env["LC_ALL"] = 'C'
- cmd = compiler + ['-x{}'.format(lang), '-E', '-v', '-']
- p = subprocess.Popen(
- cmd,
- stdin=subprocess.DEVNULL,
- stderr=subprocess.PIPE,
- stdout=subprocess.PIPE,
- env=env
- )
- stderr = p.stderr.read().decode('utf-8', errors='replace')
- parse_state = 0
- paths = []
- for line in stderr.split('\n'):
- if parse_state == 0:
- if line == '#include "..." search starts here:':
- parse_state = 1
- elif parse_state == 1:
- if line == '#include <...> search starts here:':
- parse_state = 2
- else:
- paths.append(line[1:])
- elif parse_state == 2:
- if line == 'End of search list.':
- break
- else:
- paths.append(line[1:])
- if not paths:
- mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd)))
- return paths
-
-
-class GnuLikeCompiler(abc.ABC):
- """
- 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.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_ndebug', 'b_staticpic', 'b_pie']
- if (not self.compiler_type.is_osx_compiler and
- not self.compiler_type.is_windows_compiler and
- not mesonlib.is_openbsd()):
- self.base_options.append('b_lundef')
- if not self.compiler_type.is_windows_compiler:
- self.base_options.append('b_asneeded')
- # All GCC-like backends can do assembly
- self.can_compile_suffixes.add('s')
-
- 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:
- return '-Wl,-dead_strip_dylibs'
- else:
- return '-Wl,--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_pie_args(self):
- return ['-fPIE']
-
- def get_pie_link_args(self):
- return ['-pie']
-
- def get_buildtype_args(self, buildtype):
- return gnulike_buildtype_args[buildtype]
-
- @abc.abstractmethod
- def get_optimization_args(self, optimization_level):
- raise NotImplementedError("get_optimization_args not implemented")
-
- def get_debug_args(self, is_debug):
- return clike_debug_args[is_debug]
-
- 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]
-
- @abc.abstractmethod
- def get_pch_suffix(self):
- raise NotImplementedError("get_pch_suffix not implemented")
-
- 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)
-
- 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 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)
-
- @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]
-
- def gen_vs_module_defs_args(self, defsfile):
- if not isinstance(defsfile, str):
- raise RuntimeError('Module definitions file should be str')
- # On Windows targets, .def files may be specified on the linker command
- # line like an object file.
- if self.compiler_type.is_windows_compiler:
- return [defsfile]
- # For other targets, discard the .def file.
- return []
-
- def get_argument_syntax(self):
- return 'gcc'
-
- def get_profile_generate_args(self):
- return ['-fprofile-generate']
-
- def get_profile_use_args(self):
- return ['-fprofile-use', '-fprofile-correction']
-
- def get_allow_undefined_link_args(self):
- if self.compiler_type.is_osx_compiler:
- # Apple ld
- return ['-Wl,-undefined,dynamic_lookup']
- elif self.compiler_type.is_windows_compiler:
- # For PE/COFF this is impossible
- return []
- elif mesonlib.is_sunos():
- return []
- else:
- # GNU ld and LLVM lld
- return ['-Wl,--allow-shlib-undefined']
-
- def get_gui_app_args(self, value):
- if self.compiler_type.is_windows_compiler:
- return ['-mwindows' if value else '-mconsole']
- return []
-
- def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
- for idx, i in enumerate(parameter_list):
- if i[:2] == '-I' or i[:2] == '-L':
- parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
-
- return parameter_list
-
- @functools.lru_cache()
- def _get_search_dirs(self, env):
- extra_args = ['--print-search-dirs']
- stdo = None
- with self._build_wrapper('', env, extra_args=extra_args,
- dependencies=None, mode='compile',
- want_output=True) as p:
- stdo = p.stdo
- return stdo
-
- def _split_fetch_real_dirs(self, pathstr):
- # We need to use the path separator used by the compiler for printing
- # lists of paths ("gcc --print-search-dirs"). By default
- # we assume it uses the platform native separator.
- pathsep = os.pathsep
-
- # clang uses ':' instead of ';' on Windows https://reviews.llvm.org/D61121
- # so we need to repair things like 'C:\foo:C:\bar'
- if pathsep == ';':
- pathstr = re.sub(r':([^/\\])', r';\1', pathstr)
-
- # pathlib treats empty paths as '.', so filter those out
- paths = [p for p in pathstr.split(pathsep) if p]
-
- result = []
- for p in paths:
- # GCC returns paths like this:
- # /usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/lib
- # It would make sense to normalize them to get rid of the .. parts
- # Sadly when you are on a merged /usr fs it also kills these:
- # /lib/x86_64-linux-gnu
- # since /lib is a symlink to /usr/lib. This would mean
- # paths under /lib would be considered not a "system path",
- # which is wrong and breaks things. Store everything, just to be sure.
- pobj = Path(p)
- unresolved = pobj.as_posix()
- if pobj.exists():
- if unresolved not in result:
- result.append(unresolved)
- try:
- resolved = Path(p).resolve().as_posix()
- if resolved not in result:
- result.append(resolved)
- except FileNotFoundError:
- pass
- return tuple(result)
-
- def get_compiler_dirs(self, env, name):
- '''
- Get dirs from the compiler, either `libraries:` or `programs:`
- '''
- stdo = self._get_search_dirs(env)
- for line in stdo.split('\n'):
- if line.startswith(name + ':'):
- return self._split_fetch_real_dirs(line.split('=', 1)[1])
- return ()
-
-
-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: dict):
- super().__init__(compiler_type)
- self.id = 'gcc'
- self.defines = defines or {}
- self.base_options.append('b_colorout')
-
- def get_colorout_args(self, colortype: str) -> List[str]:
- if mesonlib.version_compare(self.version, '>=4.9.0'):
- return gnu_color_args[colortype][:]
- return []
-
- def get_warn_args(self, level: str) -> list:
- 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: str) -> bool:
- 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: str):
- return gnu_optimization_args[optimization_level]
-
- def get_pch_suffix(self) -> str:
- return 'gch'
-
- def openmp_flags(self) -> List[str]:
- return ['-fopenmp']
-
class PGICompiler:
def __init__(self, compiler_type):
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index cf893b9..67a5748 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -25,7 +25,6 @@ from .compilers import (
gnu_winlibs,
msvc_winlibs,
ClangCompiler,
- GnuCompiler,
ElbrusCompiler,
IntelGnuLikeCompiler,
IntelVisualStudioLikeCompiler,
@@ -38,6 +37,7 @@ from .mixins.clike import CLikeCompiler
from .mixins.ccrx import CcrxCompiler
from .mixins.arm import ArmCompiler
from .mixins.visualstudio import VisualStudioLikeCompiler
+from .mixins.gnu import GnuCompiler
def non_msvc_eh_options(eh, args):
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 3c38c09..152c8ba 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -17,7 +17,8 @@ import re, os.path
from .. import mlog
from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
- cuda_debug_args, CompilerType, get_gcc_soname_args)
+ cuda_debug_args, CompilerType)
+from .mixins.gnu import get_gcc_soname_args
class CudaCompiler(Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None):
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 9d9863b..1a37c63 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -23,13 +23,11 @@ from .compilers import (
d_dmd_buildtype_args,
d_gdc_buildtype_args,
d_ldc_buildtype_args,
- get_gcc_soname_args,
- gnu_color_args,
- gnu_optimization_args,
clike_debug_args,
Compiler,
CompilerArgs,
)
+from .mixins.gnu import get_gcc_soname_args, gnu_color_args, gnu_optimization_args
d_feature_args = {'gcc': {'unittest': '-funittest',
'debug': '-fdebug',
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index e96cb15..12f2dbf 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -17,13 +17,8 @@ from pathlib import Path
from .compilers import (
CompilerType,
- apple_buildtype_linker_args,
- gnulike_buildtype_args,
- gnulike_buildtype_linker_args,
- gnu_optimization_args,
clike_debug_args,
Compiler,
- GnuCompiler,
ClangCompiler,
ElbrusCompiler,
IntelGnuLikeCompiler,
@@ -31,6 +26,10 @@ from .compilers import (
IntelVisualStudioLikeCompiler,
)
from .mixins.clike import CLikeCompiler
+from .mixins.gnu import (
+ GnuCompiler, apple_buildtype_linker_args, gnulike_buildtype_args,
+ gnulike_buildtype_linker_args, gnu_optimization_args,
+)
from .. import mlog
from mesonbuild.mesonlib import (
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
new file mode 100644
index 0000000..6095483
--- /dev/null
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -0,0 +1,390 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Provides mixins for GNU compilers and GNU-like compilers."""
+
+import abc
+import functools
+import os
+import pathlib
+import subprocess
+import typing
+
+from ... import mesonlib
+from ... import mlog
+
+# XXX: prevent circular references.
+# FIXME: this really is a posix interface not a c-like interface
+clike_debug_args = {False: [],
+ True: ['-g']}
+
+gnulike_buildtype_args = {'plain': [],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': [],
+ 'minsize': [],
+ 'custom': [],
+ }
+
+apple_buildtype_linker_args = {'plain': [],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': [],
+ 'minsize': [],
+ 'custom': [],
+ }
+
+gnulike_buildtype_linker_args = {'plain': [],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': ['-Wl,-O1'],
+ 'minsize': [],
+ 'custom': [],
+ }
+
+gnu_optimization_args = {'0': [],
+ 'g': ['-Og'],
+ '1': ['-O1'],
+ '2': ['-O2'],
+ '3': ['-O3'],
+ 's': ['-Os'],
+ }
+
+gnulike_instruction_set_args = {'mmx': ['-mmmx'],
+ 'sse': ['-msse'],
+ 'sse2': ['-msse2'],
+ 'sse3': ['-msse3'],
+ 'ssse3': ['-mssse3'],
+ 'sse41': ['-msse4.1'],
+ 'sse42': ['-msse4.2'],
+ 'avx': ['-mavx'],
+ 'avx2': ['-mavx2'],
+ 'avx2': ['-mavx2'],
+ 'neon': ['-mfpu=neon'],
+ }
+
+gnu_symbol_visibility_args = {'': [],
+ 'default': ['-fvisibility=default'],
+ 'internal': ['-fvisibility=internal'],
+ 'hidden': ['-fvisibility=hidden'],
+ 'protected': ['-fvisibility=protected'],
+ 'inlineshidden': ['-fvisibility=hidden', '-fvisibility-inlines-hidden'],
+ }
+
+gnu_color_args = {'auto': ['-fdiagnostics-color=auto'],
+ 'always': ['-fdiagnostics-color=always'],
+ 'never': ['-fdiagnostics-color=never'],
+ }
+
+
+def get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion):
+ install_name = prefix + shlib_name
+ if soversion is not None:
+ install_name += '.' + soversion
+ install_name += '.dylib'
+ return '@rpath/' + install_name
+
+
+def get_gcc_soname_args(compiler_type, prefix, shlib_name, suffix, soversion, darwin_versions, is_shared_module):
+ if compiler_type.is_standard_compiler:
+ sostr = '' if soversion is None else '.' + soversion
+ return ['-Wl,-soname,%s%s.%s%s' % (prefix, shlib_name, suffix, sostr)]
+ elif compiler_type.is_windows_compiler:
+ # For PE/COFF the soname argument has no effect with GNU LD
+ return []
+ elif compiler_type.is_osx_compiler:
+ if is_shared_module:
+ return []
+ name = get_macos_dylib_install_name(prefix, shlib_name, suffix, soversion)
+ args = ['-install_name', name]
+ if darwin_versions:
+ args += ['-compatibility_version', darwin_versions[0], '-current_version', darwin_versions[1]]
+ return args
+ else:
+ raise RuntimeError('Not implemented yet.')
+
+
+# TODO: The result from calling compiler should be cached. So that calling this
+# function multiple times don't add latency.
+def gnulike_default_include_dirs(compiler, lang):
+ if lang == 'cpp':
+ lang = 'c++'
+ env = os.environ.copy()
+ env["LC_ALL"] = 'C'
+ cmd = compiler + ['-x{}'.format(lang), '-E', '-v', '-']
+ p = subprocess.Popen(
+ cmd,
+ stdin=subprocess.DEVNULL,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ env=env
+ )
+ stderr = p.stderr.read().decode('utf-8', errors='replace')
+ parse_state = 0
+ paths = []
+ for line in stderr.split('\n'):
+ if parse_state == 0:
+ if line == '#include "..." search starts here:':
+ parse_state = 1
+ elif parse_state == 1:
+ if line == '#include <...> search starts here:':
+ parse_state = 2
+ else:
+ paths.append(line[1:])
+ elif parse_state == 2:
+ if line == 'End of search list.':
+ break
+ else:
+ paths.append(line[1:])
+ if not paths:
+ mlog.warning('No include directory found parsing "{cmd}" output'.format(cmd=" ".join(cmd)))
+ return paths
+
+
+class GnuLikeCompiler(metaclass=abc.ABCMeta):
+ """
+ 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.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
+ 'b_ndebug', 'b_staticpic', 'b_pie']
+ if (not self.compiler_type.is_osx_compiler and
+ not self.compiler_type.is_windows_compiler and
+ not mesonlib.is_openbsd()):
+ self.base_options.append('b_lundef')
+ if not self.compiler_type.is_windows_compiler:
+ self.base_options.append('b_asneeded')
+ # All GCC-like backends can do assembly
+ self.can_compile_suffixes.add('s')
+
+ 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:
+ return '-Wl,-dead_strip_dylibs'
+ else:
+ return '-Wl,--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_pie_args(self):
+ return ['-fPIE']
+
+ def get_pie_link_args(self):
+ return ['-pie']
+
+ def get_buildtype_args(self, buildtype):
+ return gnulike_buildtype_args[buildtype]
+
+ @abc.abstractmethod
+ def get_optimization_args(self, optimization_level):
+ raise NotImplementedError("get_optimization_args not implemented")
+
+ def get_debug_args(self, is_debug):
+ return clike_debug_args[is_debug]
+
+ 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]
+
+ @abc.abstractmethod
+ def get_pch_suffix(self):
+ raise NotImplementedError("get_pch_suffix not implemented")
+
+ 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)
+
+ 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 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)
+
+ @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]
+
+ def gen_vs_module_defs_args(self, defsfile):
+ if not isinstance(defsfile, str):
+ raise RuntimeError('Module definitions file should be str')
+ # On Windows targets, .def files may be specified on the linker command
+ # line like an object file.
+ if self.compiler_type.is_windows_compiler:
+ return [defsfile]
+ # For other targets, discard the .def file.
+ return []
+
+ def get_argument_syntax(self):
+ return 'gcc'
+
+ def get_profile_generate_args(self):
+ return ['-fprofile-generate']
+
+ def get_profile_use_args(self):
+ return ['-fprofile-use', '-fprofile-correction']
+
+ def get_allow_undefined_link_args(self):
+ if self.compiler_type.is_osx_compiler:
+ # Apple ld
+ return ['-Wl,-undefined,dynamic_lookup']
+ elif self.compiler_type.is_windows_compiler:
+ # For PE/COFF this is impossible
+ return []
+ elif mesonlib.is_sunos():
+ return []
+ else:
+ # GNU ld and LLVM lld
+ return ['-Wl,--allow-shlib-undefined']
+
+ def get_gui_app_args(self, value):
+ if self.compiler_type.is_windows_compiler:
+ return ['-mwindows' if value else '-mconsole']
+ return []
+
+ def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
+ for idx, i in enumerate(parameter_list):
+ if i[:2] == '-I' or i[:2] == '-L':
+ parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+
+ return parameter_list
+
+ @functools.lru_cache()
+ def _get_search_dirs(self, env):
+ extra_args = ['--print-search-dirs']
+ stdo = None
+ with self._build_wrapper('', env, extra_args=extra_args,
+ dependencies=None, mode='compile',
+ want_output=True) as p:
+ stdo = p.stdo
+ return stdo
+
+ def _split_fetch_real_dirs(self, pathstr):
+ # We need to use the path separator used by the compiler for printing
+ # lists of paths ("gcc --print-search-dirs"). By default
+ # we assume it uses the platform native separator.
+ pathsep = os.pathsep
+
+ # clang uses ':' instead of ';' on Windows https://reviews.llvm.org/D61121
+ # so we need to repair things like 'C:\foo:C:\bar'
+ if pathsep == ';':
+ pathstr = re.sub(r':([^/\\])', r';\1', pathstr)
+
+ # pathlib treats empty paths as '.', so filter those out
+ paths = [p for p in pathstr.split(pathsep) if p]
+
+ result = []
+ for p in paths:
+ # GCC returns paths like this:
+ # /usr/lib/gcc/x86_64-linux-gnu/8/../../../../x86_64-linux-gnu/lib
+ # It would make sense to normalize them to get rid of the .. parts
+ # Sadly when you are on a merged /usr fs it also kills these:
+ # /lib/x86_64-linux-gnu
+ # since /lib is a symlink to /usr/lib. This would mean
+ # paths under /lib would be considered not a "system path",
+ # which is wrong and breaks things. Store everything, just to be sure.
+ pobj = pathlib.Path(p)
+ unresolved = pobj.as_posix()
+ if pobj.exists():
+ if unresolved not in result:
+ result.append(unresolved)
+ try:
+ resolved = pathlib.Path(p).resolve().as_posix()
+ if resolved not in result:
+ result.append(resolved)
+ except FileNotFoundError:
+ pass
+ return tuple(result)
+
+ def get_compiler_dirs(self, env, name):
+ '''
+ Get dirs from the compiler, either `libraries:` or `programs:`
+ '''
+ stdo = self._get_search_dirs(env)
+ for line in stdo.split('\n'):
+ if line.startswith(name + ':'):
+ return self._split_fetch_real_dirs(line.split('=', 1)[1])
+ return ()
+
+
+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: dict):
+ super().__init__(compiler_type)
+ self.id = 'gcc'
+ self.defines = defines or {}
+ self.base_options.append('b_colorout')
+
+ def get_colorout_args(self, colortype: str) -> typing.List[str]:
+ if mesonlib.version_compare(self.version, '>=4.9.0'):
+ return gnu_color_args[colortype][:]
+ return []
+
+ def get_warn_args(self, level: str) -> list:
+ 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: str) -> bool:
+ 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: str):
+ return gnu_optimization_args[optimization_level]
+
+ def get_pch_suffix(self) -> str:
+ return 'gch'
+
+ def openmp_flags(self) -> typing.List[str]:
+ return ['-fopenmp']
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index 44c414a..ec4aa1a 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -17,8 +17,9 @@ import typing
from ..mesonlib import EnvironmentException, MachineChoice
+from .compilers import Compiler, ClangCompiler
from .mixins.clike import CLikeCompiler
-from .compilers import Compiler, ClangCompiler, GnuCompiler
+from .mixins.gnu import GnuCompiler
class ObjCCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]):
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index 3a232b5..38082d2 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -18,7 +18,8 @@ import typing
from ..mesonlib import EnvironmentException, MachineChoice
from .mixins.clike import CLikeCompiler
-from .compilers import Compiler, ClangCompiler, GnuCompiler
+from .compilers import Compiler, ClangCompiler
+from .mixins.gnu import GnuCompiler
class ObjCPPCompiler(CLikeCompiler, Compiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, exe_wrap: typing.Optional[str]):