aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r--mesonbuild/compilers/__init__.py2
-rw-r--r--mesonbuild/compilers/c.py5
-rw-r--r--mesonbuild/compilers/c_function_attributes.py2
-rw-r--r--mesonbuild/compilers/compilers.py394
-rw-r--r--mesonbuild/compilers/cpp.py11
-rw-r--r--mesonbuild/compilers/cuda.py10
-rw-r--r--mesonbuild/compilers/d.py28
-rw-r--r--mesonbuild/compilers/fortran.py14
-rw-r--r--mesonbuild/compilers/mixins/arm.py28
-rw-r--r--mesonbuild/compilers/mixins/clang.py17
-rw-r--r--mesonbuild/compilers/mixins/clike.py185
-rw-r--r--mesonbuild/compilers/mixins/gnu.py2
-rw-r--r--mesonbuild/compilers/mixins/islinker.py7
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py5
-rw-r--r--mesonbuild/compilers/objc.py2
-rw-r--r--mesonbuild/compilers/objcpp.py2
16 files changed, 264 insertions, 450 deletions
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py
index af7e519..fd47545 100644
--- a/mesonbuild/compilers/__init__.py
+++ b/mesonbuild/compilers/__init__.py
@@ -48,7 +48,6 @@ __all__ = [
'ClangObjCPPCompiler',
'ClangClCCompiler',
'ClangClCPPCompiler',
- 'CompilerArgs',
'CPPCompiler',
'DCompiler',
'DmdDCompiler',
@@ -123,7 +122,6 @@ from .compilers import (
is_known_suffix,
lang_suffixes,
sort_clink,
- CompilerArgs,
)
from .c import (
CCompiler,
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 52a5157..feae8ac 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -86,9 +86,10 @@ class ClangCCompiler(ClangCompiler, CCompiler):
_C18_VERSION = '>=8.0.0'
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ is_cross, info: 'MachineInfo', exe_wrapper=None,
+ defines: T.Optional[T.List[str]] = None, **kwargs):
CCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/c_function_attributes.py b/mesonbuild/compilers/c_function_attributes.py
index e5de485..f31229e 100644
--- a/mesonbuild/compilers/c_function_attributes.py
+++ b/mesonbuild/compilers/c_function_attributes.py
@@ -56,6 +56,8 @@ C_FUNC_ATTRIBUTES = {
'int foo(const char * p, ...) __attribute__((format(printf, 1, 2)));',
'format_arg':
'char * foo(const char * p) __attribute__((format_arg(1)));',
+ 'force_align_arg_pointer':
+ '__attribute__((force_align_arg_pointer)) int foo(void) { return 0; }',
'gnu_inline':
'inline __attribute__((gnu_inline)) int foo(void) { return 0; }',
'hot':
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index ecdb70d..c31439c 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -12,19 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import abc
import contextlib, os.path, re, tempfile
-import collections.abc
import itertools
import typing as T
from functools import lru_cache
-from ..linkers import (
- GnuLikeDynamicLinkerMixin, LinkerEnvVarsMixin, SolarisDynamicLinker,
- StaticLinker,
-)
from .. import coredata
from .. import mlog
from .. import mesonlib
+from ..linkers import LinkerEnvVarsMixin
from ..mesonlib import (
EnvironmentException, Language, MachineChoice, MesonException,
Popen_safe, split_args
@@ -32,6 +29,7 @@ from ..mesonlib import (
from ..envconfig import (
Properties, get_env_var
)
+from ..arglist import CompilerArgs
if T.TYPE_CHECKING:
from ..coredata import OptionDictType
@@ -52,7 +50,7 @@ lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so')
# This means we can't include .h headers here since they could be C, C++, ObjC, etc.
lang_suffixes = {
Language.C: ('c',),
- Language.CPP: ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx'),
+ Language.CPP: ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino'),
Language.CUDA: ('cu',),
# f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
# f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
@@ -113,11 +111,6 @@ cflags_mapping = {
Language.RUST: 'RUSTFLAGS',
}
-unixy_compiler_internal_libs = ('m', 'c', 'pthread', 'dl', 'rt')
-# execinfo is a compiler lib on FreeBSD and NetBSD
-if mesonlib.is_freebsd() or mesonlib.is_netbsd():
- unixy_compiler_internal_libs += ('execinfo',)
-
# All these are only for C-linkable languages; see `clink_langs` above.
def sort_clink(lang):
@@ -153,11 +146,15 @@ def is_llvm_ir(fname):
fname = fname.fname
return fname.split('.')[-1] == 'll'
+@lru_cache(maxsize=None)
+def cached_by_name(fname):
+ suffix = fname.split('.')[-1]
+ return suffix in obj_suffixes
+
def is_object(fname):
if hasattr(fname, 'fname'):
fname = fname.fname
- suffix = fname.split('.')[-1]
- return suffix in obj_suffixes
+ return cached_by_name(fname)
def is_library(fname):
if hasattr(fname, 'fname'):
@@ -201,7 +198,7 @@ rust_buildtype_args = {'plain': [],
d_gdc_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-finline-functions'],
- 'release': ['-frelease', '-finline-functions'],
+ 'release': ['-finline-functions'],
'minsize': [],
'custom': [],
}
@@ -209,7 +206,7 @@ d_gdc_buildtype_args = {'plain': [],
d_ldc_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'],
- 'release': ['-release', '-enable-inlining', '-Hkeep-all-bodies'],
+ 'release': ['-enable-inlining', '-Hkeep-all-bodies'],
'minsize': [],
'custom': [],
}
@@ -217,7 +214,7 @@ d_ldc_buildtype_args = {'plain': [],
d_dmd_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': ['-inline'],
- 'release': ['-release', '-inline'],
+ 'release': ['-inline'],
'minsize': [],
'custom': [],
}
@@ -335,7 +332,7 @@ def get_base_compile_args(options, compiler):
if (options['b_ndebug'].value == 'true' or
(options['b_ndebug'].value == 'if-release' and
options['buildtype'].value in {'release', 'plain'})):
- args += ['-DNDEBUG']
+ args += compiler.get_disable_assert_args()
except KeyError:
pass
# This does not need a try...except
@@ -387,9 +384,10 @@ def get_base_link_args(options, linker, is_shared_module):
# -Wl,-dead_strip_dylibs is incompatible with bitcode
args.extend(linker.get_asneeded_args())
- # Apple's ld (the only one that supports bitcode) does not like any
- # -undefined arguments at all, so don't pass these when using bitcode
+ # Apple's ld (the only one that supports bitcode) does not like -undefined
+ # arguments or -headerpad_max_install_names when bitcode is enabled
if not bitcode:
+ args.extend(linker.headerpad_args())
if (not is_shared_module and
option_enabled(linker.base_options, options, 'b_lundef')):
args.extend(linker.no_undefined_link_args())
@@ -418,334 +416,8 @@ class RunResult:
self.stdout = stdout
self.stderr = stderr
-class CompilerArgs(collections.abc.MutableSequence):
- '''
- List-like class that manages a list of compiler arguments. Should be used
- while constructing compiler arguments from various sources. Can be
- operated with ordinary lists, so this does not need to be used
- everywhere.
-
- All arguments must be inserted and stored in GCC-style (-lfoo, -Idir, etc)
- and can converted to the native type of each compiler by using the
- .to_native() method to which you must pass an instance of the compiler or
- the compiler class.
-
- New arguments added to this class (either with .append(), .extend(), or +=)
- are added in a way that ensures that they override previous arguments.
- For example:
-
- >>> a = ['-Lfoo', '-lbar']
- >>> a += ['-Lpho', '-lbaz']
- >>> print(a)
- ['-Lpho', '-Lfoo', '-lbar', '-lbaz']
-
- Arguments will also be de-duped if they can be de-duped safely.
-
- Note that because of all this, this class is not commutative and does not
- preserve the order of arguments if it is safe to not. For example:
- >>> ['-Ifoo', '-Ibar'] + ['-Ifez', '-Ibaz', '-Werror']
- ['-Ifez', '-Ibaz', '-Ifoo', '-Ibar', '-Werror']
- >>> ['-Ifez', '-Ibaz', '-Werror'] + ['-Ifoo', '-Ibar']
- ['-Ifoo', '-Ibar', '-Ifez', '-Ibaz', '-Werror']
-
- '''
- # NOTE: currently this class is only for C-like compilers, but it can be
- # extended to other languages easily. Just move the following to the
- # compiler class and initialize when self.compiler is set.
-
- # Arg prefixes that override by prepending instead of appending
- prepend_prefixes = ('-I', '-L')
- # Arg prefixes and args that must be de-duped by returning 2
- dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U')
- dedup2_suffixes = ()
- dedup2_args = ()
- # Arg prefixes and args that must be de-duped by returning 1
- #
- # NOTE: not thorough. A list of potential corner cases can be found in
- # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038
- dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic')
- dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
- # Match a .so of the form path/to/libfoo.so.0.1.0
- # Only UNIX shared libraries require this. Others have a fixed extension.
- dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
- dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
- # In generate_link() we add external libs without de-dup, but we must
- # *always* de-dup these because they're special arguments to the linker
- always_dedup_args = tuple('-l' + lib for lib in unixy_compiler_internal_libs)
-
- def __init__(self, compiler: T.Union['Compiler', StaticLinker],
- iterable: T.Optional[T.Iterable[str]] = None):
- self.compiler = compiler
- self.__container = list(iterable) if iterable is not None else [] # type: T.List[str]
- self.__seen_args = set()
- for arg in self.__container:
- self.__seen_args.add(arg)
-
- @T.overload # noqa: F811
- def __getitem__(self, index: int) -> str: # noqa: F811
- pass
-
- @T.overload # noqa: F811
- def __getitem__(self, index: slice) -> T.List[str]: # noqa: F811
- pass
-
- def __getitem__(self, index): # noqa: F811
- return self.__container[index]
-
- @T.overload # noqa: F811
- def __setitem__(self, index: int, value: str) -> None: # noqa: F811
- pass
-
- @T.overload # noqa: F811
- def __setitem__(self, index: slice, value: T.List[str]) -> None: # noqa: F811
- pass
-
- def __setitem__(self, index, value) -> None: # noqa: F811
- self.__container[index] = value
- for v in value:
- self.__seen_args.add(v)
-
- def __delitem__(self, index: T.Union[int, slice]) -> None:
- value = self.__container[index]
- del self.__container[index]
- if value in self.__seen_args and value in self.__container: # this is also honoring that you can have duplicated entries
- self.__seen_args.remove(value)
- def __len__(self) -> int:
- return len(self.__container)
-
- def insert(self, index: int, value: str) -> None:
- self.__container.insert(index, value)
- self.__seen_args.add(value)
-
- def copy(self) -> 'CompilerArgs':
- return CompilerArgs(self.compiler, self.__container.copy())
-
- @classmethod
- @lru_cache(maxsize=None)
- def _can_dedup(cls, arg):
- '''
- Returns whether the argument can be safely de-duped. This is dependent
- on three things:
-
- a) Whether an argument can be 'overridden' by a later argument. For
- example, -DFOO defines FOO and -UFOO undefines FOO. In this case, we
- can safely remove the previous occurrence and add a new one. The same
- is true for include paths and library paths with -I and -L. For
- these we return `2`. See `dedup2_prefixes` and `dedup2_args`.
- b) Arguments that once specified cannot be undone, such as `-c` or
- `-pipe`. New instances of these can be completely skipped. For these
- we return `1`. See `dedup1_prefixes` and `dedup1_args`.
- c) Whether it matters where or how many times on the command-line
- a particular argument is present. This can matter for symbol
- resolution in static or shared libraries, so we cannot de-dup or
- reorder them. For these we return `0`. This is the default.
-
- In addition to these, we handle library arguments specially.
- With GNU ld, we surround library arguments with -Wl,--start/end-group
- to recursively search for symbols in the libraries. This is not needed
- with other linkers.
- '''
- # A standalone argument must never be deduplicated because it is
- # defined by what comes _after_ it. Thus dedupping this:
- # -D FOO -D BAR
- # would yield either
- # -D FOO BAR
- # or
- # FOO -D BAR
- # both of which are invalid.
- if arg in cls.dedup2_prefixes:
- return 0
- if arg.startswith('-L='):
- # DMD and LDC proxy all linker arguments using -L=; in conjunction
- # with ld64 on macOS this can lead to command line arguments such
- # as: `-L=-compatibility_version -L=0 -L=current_version -L=0`.
- # These cannot be combined, ld64 insists they must be passed with
- # spaces and quoting does not work. if we deduplicate these then
- # one of the -L=0 arguments will be removed and the version
- # argument will consume the next argument instead.
- return 0
- if arg in cls.dedup2_args or \
- arg.startswith(cls.dedup2_prefixes) or \
- arg.endswith(cls.dedup2_suffixes):
- return 2
- if arg in cls.dedup1_args or \
- arg.startswith(cls.dedup1_prefixes) or \
- arg.endswith(cls.dedup1_suffixes) or \
- re.search(cls.dedup1_regex, arg):
- return 1
- return 0
-
- @classmethod
- @lru_cache(maxsize=None)
- def _should_prepend(cls, arg):
- if arg.startswith(cls.prepend_prefixes):
- return True
- return False
-
- def need_to_split_linker_args(self):
- return isinstance(self.compiler, Compiler) and self.compiler.get_language() == Language.D
-
- def to_native(self, copy: bool = False) -> T.List[str]:
- # Check if we need to add --start/end-group for circular dependencies
- # between static libraries, and for recursively searching for symbols
- # needed by static libraries that are provided by object files or
- # shared libraries.
- if copy:
- new = self.copy()
- else:
- new = self
- # To proxy these arguments with D you need to split the
- # arguments, thus you get `-L=-soname -L=lib.so` we don't
- # want to put the lib in a link -roup
- split_linker_args = self.need_to_split_linker_args()
- # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which
- # all act like (or are) gnu ld
- # TODO: this could probably be added to the DynamicLinker instead
- if (isinstance(self.compiler, Compiler) and
- self.compiler.linker is not None and
- isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker))):
- group_start = -1
- group_end = -1
- is_soname = False
- for i, each in enumerate(new):
- if is_soname:
- is_soname = False
- continue
- elif split_linker_args and '-soname' in each:
- is_soname = True
- continue
- if not each.startswith(('-Wl,-l', '-l')) and not each.endswith('.a') and \
- not soregex.match(each):
- continue
- group_end = i
- if group_start < 0:
- # First occurrence of a library
- group_start = i
- if group_start >= 0:
- # Last occurrence of a library
- new.insert(group_end + 1, '-Wl,--end-group')
- new.insert(group_start, '-Wl,--start-group')
- # Remove system/default include paths added with -isystem
- if hasattr(self.compiler, 'get_default_include_dirs'):
- default_dirs = self.compiler.get_default_include_dirs()
- bad_idx_list = [] # type: T.List[int]
- for i, each in enumerate(new):
- # Remove the -isystem and the path if the path is a default path
- if (each == '-isystem' and
- i < (len(new) - 1) and
- new[i + 1] in default_dirs):
- bad_idx_list += [i, i + 1]
- elif each.startswith('-isystem=') and each[9:] in default_dirs:
- bad_idx_list += [i]
- elif each.startswith('-isystem') and each[8:] in default_dirs:
- bad_idx_list += [i]
- for i in reversed(bad_idx_list):
- new.pop(i)
- return self.compiler.unix_args_to_native(new.__container)
-
- def append_direct(self, arg: str) -> None:
- '''
- Append the specified argument without any reordering or de-dup except
- for absolute paths to libraries, etc, which can always be de-duped
- safely.
- '''
- if os.path.isabs(arg):
- self.append(arg)
- else:
- self.__container.append(arg)
- self.__seen_args.add(arg)
-
- def extend_direct(self, iterable: T.Iterable[str]) -> None:
- '''
- Extend using the elements in the specified iterable without any
- reordering or de-dup except for absolute paths where the order of
- include search directories is not relevant
- '''
- for elem in iterable:
- self.append_direct(elem)
-
- def extend_preserving_lflags(self, iterable: T.Iterable[str]) -> None:
- normal_flags = []
- lflags = []
- for i in iterable:
- if i not in self.always_dedup_args and (i.startswith('-l') or i.startswith('-L')):
- lflags.append(i)
- else:
- normal_flags.append(i)
- self.extend(normal_flags)
- self.extend_direct(lflags)
-
- def __add__(self, args: T.Iterable[str]) -> 'CompilerArgs':
- new = self.copy()
- new += args
- return new
-
- def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs':
- '''
- Add two CompilerArgs while taking into account overriding of arguments
- and while preserving the order of arguments as much as possible
- '''
- this_round_added = set() # a dict that contains a value, when the value was added this round
- pre = [] # type: T.List[str]
- post = [] # type: T.List[str]
- if not isinstance(args, collections.abc.Iterable):
- raise TypeError('can only concatenate Iterable[str] (not "{}") to CompilerArgs'.format(args))
- for arg in args:
- # If the argument can be de-duped, do it either by removing the
- # previous occurrence of it and adding a new one, or not adding the
- # new occurrence.
- dedup = self._can_dedup(arg)
- if dedup == 1:
- # Argument already exists and adding a new instance is useless
- if arg in self.__seen_args or arg in pre or arg in post:
- continue
- should_prepend = self._should_prepend(arg)
- if dedup == 2:
- # Remove all previous occurrences of the arg and add it anew
- if arg in self.__seen_args and arg not in this_round_added: #if __seen_args contains arg as well as this_round_added, then its not yet part in self.
- self.remove(arg)
- if should_prepend:
- if arg in pre:
- pre.remove(arg)
- else:
- if arg in post:
- post.remove(arg)
- if should_prepend:
- pre.append(arg)
- else:
- post.append(arg)
- self.__seen_args.add(arg)
- this_round_added.add(arg)
- # Insert at the beginning
- self[:0] = pre
- # Append to the end
- self.__container += post
- return self
-
- def __radd__(self, args: T.Iterable[str]):
- new = CompilerArgs(self.compiler, args)
- new += self
- return new
-
- def __eq__(self, other: T.Any) -> T.Union[bool, type(NotImplemented)]:
- # Only allow equality checks against other CompilerArgs and lists instances
- if isinstance(other, CompilerArgs):
- return self.compiler == other.compiler and self.__container == other.__container
- elif isinstance(other, list):
- return self.__container == other
- return NotImplemented
-
- def append(self, arg: str) -> None:
- self.__iadd__([arg])
-
- def extend(self, args: T.Iterable[str]) -> None:
- self.__iadd__(args)
-
- def __repr__(self) -> str:
- return 'CompilerArgs({!r}, {!r})'.format(self.compiler, self.__container)
-
-class Compiler:
+class Compiler(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 = ()
@@ -968,8 +640,12 @@ class Compiler:
args += self.get_preprocess_only_args()
return args
+ def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs:
+ """Return an appropriate CompilerArgs instance for this class."""
+ return CompilerArgs(self, args)
+
@contextlib.contextmanager
- def compile(self, code, extra_args=None, *, mode='link', want_output=False, temp_dir=None):
+ def compile(self, code: str, extra_args: list = None, *, mode: str = 'link', want_output: bool = False, temp_dir: str = None):
if extra_args is None:
extra_args = []
try:
@@ -986,7 +662,7 @@ class Compiler:
srcname = code.fname
# Construct the compiler command-line
- commands = CompilerArgs(self)
+ commands = self.compiler_args()
commands.append(srcname)
# Preprocess mode outputs to stdout, so no output args
if mode != 'preprocess':
@@ -1092,7 +768,7 @@ class Compiler:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
return self.linker.build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
@@ -1102,6 +778,9 @@ class Compiler:
def openmp_flags(self):
raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
+ def openmp_link_flags(self):
+ return self.openmp_flags()
+
def language_stdlib_only_link_flags(self):
return []
@@ -1151,7 +830,7 @@ class Compiler:
def remove_linkerlike_args(self, args):
rm_exact = ('-headerpad_max_install_names',)
rm_prefixes = ('-Wl,', '-L',)
- rm_next = ('-L',)
+ rm_next = ('-L', '-framework',)
ret = []
iargs = iter(args)
for arg in iargs:
@@ -1184,12 +863,12 @@ class Compiler:
def get_asneeded_args(self) -> T.List[str]:
return self.linker.get_asneeded_args()
+ def headerpad_args(self) -> T.List[str]:
+ return self.linker.headerpad_args()
+
def bitcode_args(self) -> T.List[str]:
return self.linker.bitcode_args()
- def get_linker_debug_crt_args(self) -> T.List[str]:
- return self.linker.get_debug_crt_args()
-
def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
return self.linker.get_buildtype_args(buildtype)
@@ -1219,15 +898,18 @@ class Compiler:
def get_coverage_link_args(self) -> T.List[str]:
return self.linker.get_coverage_args()
+ def get_disable_assert_args(self) -> T.List[str]:
+ return []
+
def get_largefile_args(compiler):
'''
Enable transparent large-file-support for 32-bit UNIX systems
'''
- if not (compiler.info.is_windows() or compiler.info.is_darwin()):
+ if not (compiler.get_argument_syntax() == 'msvc' or compiler.info.is_darwin()):
# Enable large-file support unconditionally on all platforms other
- # than macOS and Windows. macOS is now 64-bit-only so it doesn't
- # need anything special, and Windows doesn't have automatic LFS.
+ # than macOS and MSVC. macOS is now 64-bit-only so it doesn't
+ # need anything special, and MSVC doesn't have automatic LFS.
# You must use the 64-bit counterparts explicitly.
# glibc, musl, and uclibc, and all BSD libcs support this. On Android,
# support for transparent LFS is available depending on the version of
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index c4c7da5..71a300a 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -155,10 +155,11 @@ class CPPCompiler(CLikeCompiler, Compiler):
class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
- is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
+ is_cross, info: 'MachineInfo', exe_wrapper=None,
+ defines : T.Optional[T.List[str]] = None, **kwargs):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, defines)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
'1': default_warn_args,
@@ -238,7 +239,9 @@ class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompile
class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
- CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)
+ CPPCompiler.__init__(self, exelist=exelist, version=version,
+ for_machine=for_machine, is_cross=is_cross,
+ info=info, exe_wrapper=exe_wrapper, **kwargs)
ArmclangCompiler.__init__(self)
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
@@ -574,7 +577,7 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
is_cross: bool, info: 'MachineInfo', exe_wrap, target, **kwargs):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs)
MSVCCompiler.__init__(self, target)
- self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like
+ self.base_options = ['b_pch', 'b_vscrt', 'b_ndebug'] # FIXME add lto, pgo and the like
self.id = 'msvc'
def get_options(self):
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 00233b0..b109572 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -268,17 +268,15 @@ class CudaCompiler(Compiler):
def get_depfile_suffix(self):
return 'd'
- def get_linker_debug_crt_args(self) -> T.List[str]:
- return self._cook_link_args(self.host_compiler.get_linker_debug_crt_args())
-
def get_buildtype_linker_args(self, buildtype):
return self._cook_link_args(self.host_compiler.get_buildtype_linker_args(buildtype))
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return self._cook_link_args(self.host_compiler.build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath))
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ (rpath_args, rpath_dirs_to_remove) = self.host_compiler.build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ return (self._cook_link_args(rpath_args), rpath_dirs_to_remove)
def linker_to_compiler_args(self, args):
return args
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index caa8e44..d233713 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -25,7 +25,6 @@ from .compilers import (
d_ldc_buildtype_args,
clike_debug_args,
Compiler,
- CompilerArgs,
)
from .mixins.gnu import GnuCompiler
@@ -220,7 +219,7 @@ class DmdLikeCompilerMixin:
def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.info.is_windows():
- return []
+ return ([], set())
# GNU ld, solaris ld, and lld acting like GNU ld
if self.linker.id.startswith('ld'):
@@ -228,15 +227,16 @@ class DmdLikeCompilerMixin:
# do directly, each argument -rpath and the value to rpath, need to be
# split into two separate arguments both prefaced with the -L=.
args = []
- for r in super().build_rpath_args(
- env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ (rpath_args, rpath_dirs_to_remove) = super().build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ for r in rpath_args:
if ',' in r:
a, b = r.split(',', maxsplit=1)
args.append(a)
args.append(self.LINKER_PREFIX + b)
else:
args.append(r)
- return args
+ return (args, rpath_dirs_to_remove)
return super().build_rpath_args(
env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
@@ -581,7 +581,7 @@ class DCompiler(Compiler):
elif not isinstance(dependencies, list):
dependencies = [dependencies]
# Collect compiler arguments
- args = CompilerArgs(self)
+ args = self.compiler_args()
for d in dependencies:
# Add compile flags needed by dependencies
args += d.get_compile_args()
@@ -645,7 +645,8 @@ class GnuDCompiler(GnuCompiler, DCompiler):
'1': default_warn_args,
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt', 'b_coverage']
+ self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic',
+ 'b_vscrt', 'b_coverage', 'b_pgo', 'b_ndebug']
self._has_color_support = version_compare(self.version, '>=4.9')
# dependencies were implemented before, but broken - support was fixed in GCC 7.1+
@@ -684,6 +685,9 @@ class GnuDCompiler(GnuCompiler, DCompiler):
return args
return args + ['-shared-libphobos']
+ def get_disable_assert_args(self):
+ return ['-frelease']
+
class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
@@ -691,7 +695,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
info: 'MachineInfo', arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'llvm'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
+ self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
def get_colorout_args(self, colortype):
if colortype == 'always':
@@ -733,6 +737,9 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
return args
return args + ['-link-defaultlib-shared']
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['--release']
+
class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
@@ -740,7 +747,7 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
info: 'MachineInfo', arch, **kwargs):
DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'dmd'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
+ self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
def get_colorout_args(self, colortype):
if colortype == 'always':
@@ -803,3 +810,6 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
if self.info.is_windows():
return args
return args + ['-defaultlib=phobos2', '-debuglib=phobos2']
+
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['-release']
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 2b20aa4..31b8558 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -214,6 +214,18 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
def language_stdlib_only_link_flags(self) -> T.List[str]:
return ['-lgfortran', '-lm']
+ def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False):
+ '''
+ Derived from mixins/clike.py:has_header, but without C-style usage of
+ __has_include which breaks with GCC-Fortran 10:
+ https://github.com/mesonbuild/meson/issues/7017
+ '''
+ fargs = {'prefix': prefix, 'header': hname}
+ code = '{prefix}\n#include <{header}>'
+ return self.compiles(code.format(**fargs), env, extra_args=extra_args,
+ dependencies=dependencies, mode='preprocess', disable_cache=disable_cache)
+
+
class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross, info: 'MachineInfo', exe_wrapper=None,
@@ -412,7 +424,7 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
**kwargs):
FortranCompiler.__init__(self, exelist, version, for_machine,
is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
self.id = 'flang'
default_warn_args = ['-Minform=inform']
self.warn_args = {'0': [],
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index aa5d15d..b331d8f 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -27,10 +27,10 @@ if T.TYPE_CHECKING:
arm_buildtype_args = {
'plain': [],
- 'debug': ['-O0', '--debug'],
- 'debugoptimized': ['-O1', '--debug'],
- 'release': ['-O3', '-Otime'],
- 'minsize': ['-O3', '-Ospace'],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': [],
+ 'minsize': [],
'custom': [],
} # type: T.Dict[str, T.List[str]]
@@ -38,27 +38,27 @@ arm_optimization_args = {
'0': ['-O0'],
'g': ['-g'],
'1': ['-O1'],
- '2': ['-O2'],
- '3': ['-O3'],
- 's': [],
+ '2': [], # Compiler defaults to -O2
+ '3': ['-O3', '-Otime'],
+ 's': ['-O3'], # Compiler defaults to -Ospace
} # type: T.Dict[str, T.List[str]]
armclang_buildtype_args = {
'plain': [],
- 'debug': ['-O0', '-g'],
- 'debugoptimized': ['-O1', '-g'],
- 'release': ['-Os'],
- 'minsize': ['-Oz'],
+ 'debug': [],
+ 'debugoptimized': [],
+ 'release': [],
+ 'minsize': [],
'custom': [],
} # type: T.Dict[str, T.List[str]]
armclang_optimization_args = {
- '0': ['-O0'],
+ '0': [], # Compiler defaults to -O0
'g': ['-g'],
'1': ['-O1'],
'2': ['-O2'],
'3': ['-O3'],
- 's': ['-Os']
+ 's': ['-Oz']
} # type: T.Dict[str, T.List[str]]
@@ -181,7 +181,7 @@ class ArmclangCompiler:
# Override CCompiler.get_dependency_gen_args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
- return []
+ return ['-MD', '-MT', outtarget, '-MF', outfile]
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return armclang_optimization_args[optimization_level]
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 1c0ee45..7525c12 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -42,9 +42,10 @@ clang_optimization_args = {
} # type: T.Dict[str, T.List[str]]
class ClangCompiler(GnuLikeCompiler):
- def __init__(self):
+ def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
self.id = 'clang'
+ self.defines = defines or {}
self.base_options.append('b_colorout')
# TODO: this really should be part of the linker base_options, but
# linkers don't have base_options.
@@ -56,6 +57,12 @@ class ClangCompiler(GnuLikeCompiler):
def get_colorout_args(self, colortype: str) -> T.List[str]:
return clang_color_args[colortype][:]
+ def has_builtin_define(self, define: str) -> bool:
+ return define in self.defines
+
+ def get_builtin_define(self, define: str) -> T.Optional[str]:
+ return self.defines.get(define)
+
def get_optimization_args(self, optimization_level: str) -> T.List[str]:
return clang_optimization_args[optimization_level]
@@ -106,6 +113,11 @@ class ClangCompiler(GnuLikeCompiler):
# (and other gcc-like compilers) cannot. This is becuse clang (being
# llvm based) is retargetable, while GCC is not.
#
+
+ # qcld: Qualcomm Snapdragon linker, based on LLVM
+ if linker == 'qcld':
+ return ['-fuse-ld=qcld']
+
if shutil.which(linker):
if not shutil.which(linker):
raise mesonlib.MesonException(
@@ -117,3 +129,6 @@ class ClangCompiler(GnuLikeCompiler):
# Clang only warns about unknown or ignored attributes, so force an
# error.
return ['-Werror=attributes']
+
+ def get_coverage_link_args(self) -> T.List[str]:
+ return ['--coverage']
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 260342e..a42b050 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -29,15 +29,79 @@ import subprocess
import typing as T
from pathlib import Path
+from ... import arglist
from ... import mesonlib
-from ...mesonlib import LibType
from ... import mlog
+from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
+from ...mesonlib import LibType
from .. import compilers
from .visualstudio import VisualStudioLikeCompiler
if T.TYPE_CHECKING:
from ...environment import Environment
+SOREGEX = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
+
+class CLikeCompilerArgs(arglist.CompilerArgs):
+ prepend_prefixes = ('-I', '-L')
+ dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U')
+
+ # NOTE: not thorough. A list of potential corner cases can be found in
+ # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038
+ dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic')
+ dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
+ dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
+
+ def to_native(self, copy: bool = False) -> T.List[str]:
+ # Check if we need to add --start/end-group for circular dependencies
+ # between static libraries, and for recursively searching for symbols
+ # needed by static libraries that are provided by object files or
+ # shared libraries.
+ self.flush_pre_post()
+ if copy:
+ new = self.copy()
+ else:
+ new = self
+ # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which
+ # all act like (or are) gnu ld
+ # TODO: this could probably be added to the DynamicLinker instead
+ if isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker)):
+ group_start = -1
+ group_end = -1
+ for i, each in enumerate(new):
+ if not each.startswith(('-Wl,-l', '-l')) and not each.endswith('.a') and \
+ not SOREGEX.match(each):
+ continue
+ group_end = i
+ if group_start < 0:
+ # First occurrence of a library
+ group_start = i
+ if group_start >= 0:
+ # Last occurrence of a library
+ new.insert(group_end + 1, '-Wl,--end-group')
+ new.insert(group_start, '-Wl,--start-group')
+ # Remove system/default include paths added with -isystem
+ if hasattr(self.compiler, 'get_default_include_dirs'):
+ default_dirs = self.compiler.get_default_include_dirs()
+ bad_idx_list = [] # type: T.List[int]
+ for i, each in enumerate(new):
+ # Remove the -isystem and the path if the path is a default path
+ if (each == '-isystem' and
+ i < (len(new) - 1) and
+ new[i + 1] in default_dirs):
+ bad_idx_list += [i, i + 1]
+ elif each.startswith('-isystem=') and each[9:] in default_dirs:
+ bad_idx_list += [i]
+ elif each.startswith('-isystem') and each[8:] in default_dirs:
+ bad_idx_list += [i]
+ for i in reversed(bad_idx_list):
+ new.pop(i)
+ return self.compiler.unix_args_to_native(new._container)
+
+ def __repr__(self) -> str:
+ self.flush_pre_post()
+ return 'CLikeCompilerArgs({!r}, {!r})'.format(self.compiler, self._container)
+
class CLikeCompiler:
@@ -48,7 +112,7 @@ class CLikeCompiler:
program_dirs_cache = {}
find_library_cache = {}
find_framework_cache = {}
- internal_libs = compilers.unixy_compiler_internal_libs
+ internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS
def __init__(self, is_cross: bool, exe_wrapper: T.Optional[str] = None):
# If a child ObjC or CPP class has already set it, don't set it ourselves
@@ -61,6 +125,9 @@ class CLikeCompiler:
else:
self.exe_wrapper = exe_wrapper.get_command()
+ def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs:
+ return CLikeCompilerArgs(self, args)
+
def needs_static_linker(self):
return True # When compiling static libraries, so yes.
@@ -152,15 +219,24 @@ class CLikeCompiler:
if not files:
retval.append(d)
continue
- file_to_check = os.path.join(d, files[0])
- with open(file_to_check, 'rb') as fd:
- header = fd.read(5)
- # if file is not an ELF file, it's weird, but accept dir
- # if it is elf, and the class matches, accept dir
- if header[1:4] != b'ELF' or int(header[4]) == elf_class:
- retval.append(d)
- # at this point, it's an ELF file which doesn't match the
- # appropriate elf_class, so skip this one
+
+ for f in files:
+ file_to_check = os.path.join(d, f)
+ try:
+ with open(file_to_check, 'rb') as fd:
+ header = fd.read(5)
+ # if file is not an ELF file, it's weird, but accept dir
+ # if it is elf, and the class matches, accept dir
+ if header[1:4] != b'ELF' or int(header[4]) == elf_class:
+ retval.append(d)
+ # at this point, it's an ELF file which doesn't match the
+ # appropriate elf_class, so skip this one
+ # stop scanning after the first sucessful read
+ break
+ except OSError:
+ # Skip the file if we can't read it
+ pass
+
return tuple(retval)
@functools.lru_cache()
@@ -254,14 +330,14 @@ class CLikeCompiler:
code = 'int main(void) { int class=0; return class; }\n'
return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
- def check_header(self, hname, prefix, env, *, extra_args=None, dependencies=None):
+ def check_header(self, hname: str, prefix: str, env, *, extra_args=None, dependencies=None):
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}
#include <{header}>'''
return self.compiles(code.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def has_header(self, hname, prefix, env, *, extra_args=None, dependencies=None, disable_cache=False):
+ def has_header(self, hname: str, prefix: str, env, *, extra_args=None, dependencies=None, disable_cache: bool = False):
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}
#ifdef __has_include
@@ -274,7 +350,7 @@ class CLikeCompiler:
return self.compiles(code.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies, mode='preprocess', disable_cache=disable_cache)
- def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None):
+ def has_header_symbol(self, hname: str, symbol: str, prefix: str, env, *, extra_args=None, dependencies=None):
fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
t = '''{prefix}
#include <{header}>
@@ -288,11 +364,19 @@ class CLikeCompiler:
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def _get_basic_compiler_args(self, env, mode):
+ def _get_basic_compiler_args(self, env, mode: str):
cargs, largs = [], []
- # Select a CRT if needed since we're linking
if mode == 'link':
- cargs += self.get_linker_debug_crt_args()
+ # Sometimes we need to manually select the CRT to use with MSVC.
+ # One example is when trying to do a compiler check that involves
+ # linking with static libraries since MSVC won't select a CRT for
+ # us in that case and will error out asking us to pick one.
+ try:
+ crt_val = env.coredata.base_options['b_vscrt'].value
+ buildtype = env.coredata.base_options['buildtype'].value
+ cargs += self.get_crt_compile_args(crt_val, buildtype)
+ except (KeyError, AttributeError):
+ pass
# Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
sys_args = env.coredata.get_external_args(self.for_machine, self.language)
@@ -329,7 +413,7 @@ class CLikeCompiler:
elif not isinstance(dependencies, list):
dependencies = [dependencies]
# Collect compiler arguments
- cargs = compilers.CompilerArgs(self)
+ cargs = self.compiler_args()
largs = []
for d in dependencies:
# Add compile flags needed by dependencies
@@ -354,11 +438,11 @@ class CLikeCompiler:
def compiles(self, code: str, env, *,
extra_args: T.Sequence[T.Union[T.Sequence[str], str]] = None,
- dependencies=None, mode: str = 'compile', disable_cache=False) -> T.Tuple[bool, bool]:
+ dependencies=None, mode: str = 'compile', disable_cache: bool = False) -> T.Tuple[bool, bool]:
with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p:
return p.returncode == 0, p.cached
- def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir=None) -> T.Tuple[bool, bool]:
+ def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir: str = None) -> T.Tuple[bool, bool]:
args = self._get_compiler_check_args(env, extra_args, dependencies, mode)
if disable_cache or want_output:
return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir)
@@ -369,7 +453,8 @@ class CLikeCompiler:
dependencies=dependencies, mode='link', disable_cache=disable_cache)
def run(self, code: str, env, *, extra_args=None, dependencies=None):
- if self.is_cross and self.exe_wrapper is None:
+ need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
+ if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p:
if p.returncode != 0:
@@ -377,7 +462,7 @@ class CLikeCompiler:
p.input_name,
p.returncode))
return compilers.RunResult(False)
- if self.is_cross:
+ if need_exe_wrapper:
cmdlist = self.exe_wrapper + [p.output_name]
else:
cmdlist = p.output_name
@@ -658,7 +743,7 @@ class CLikeCompiler:
# is not run so we don't care what the return value is.
main = '''\nint main(void) {{
void *a = (void*) &{func};
- long b = (long) a;
+ long long b = (long long) a;
return (int) b;
}}'''
return head, main
@@ -727,24 +812,29 @@ class CLikeCompiler:
# need to look for them differently. On nice compilers like clang, we
# can just directly use the __has_builtin() macro.
fargs['no_includes'] = '#include' not in prefix
- fargs['__builtin_'] = '' if funcname.startswith('__builtin_') else '__builtin_'
+ is_builtin = funcname.startswith('__builtin_')
+ fargs['is_builtin'] = is_builtin
+ fargs['__builtin_'] = '' if is_builtin else '__builtin_'
t = '''{prefix}
int main(void) {{
+
+ /* With some toolchains (MSYS2/mingw for example) the compiler
+ * provides various builtins which are not really implemented and
+ * fall back to the stdlib where they aren't provided and fail at
+ * build/link time. In case the user provides a header, including
+ * the header didn't lead to the function being defined, and the
+ * function we are checking isn't a builtin itself we assume the
+ * builtin is not functional and we just error out. */
+ #if !{no_includes:d} && !defined({func}) && !{is_builtin:d}
+ #error "No definition for {__builtin_}{func} found in the prefix"
+ #endif
+
#ifdef __has_builtin
#if !__has_builtin({__builtin_}{func})
#error "{__builtin_}{func} not found"
#endif
#elif ! defined({func})
- /* Check for {__builtin_}{func} only if no includes were added to the
- * prefix above, which means no definition of {func} can be found.
- * We would always check for this, but we get false positives on
- * MSYS2 if we do. Their toolchain is broken, but we can at least
- * give them a workaround. */
- #if {no_includes:d}
- {__builtin_}{func};
- #else
- #error "No definition for {__builtin_}{func} found in the prefix"
- #endif
+ {__builtin_}{func};
#endif
return 0;
}}'''
@@ -910,21 +1000,21 @@ class CLikeCompiler:
architecture.
'''
# If not building on macOS for Darwin, do a simple file check
- files = [Path(f) for f in files]
+ paths = [Path(f) for f in files]
if not env.machines.host.is_darwin() or not env.machines.build.is_darwin():
- for f in files:
- if f.is_file():
- return f
+ for p in paths:
+ if p.is_file():
+ return p
# Run `lipo` and check if the library supports the arch we want
- for f in files:
- if not f.is_file():
+ for p in paths:
+ if not p.is_file():
continue
- archs = mesonlib.darwin_get_object_archs(f)
+ archs = mesonlib.darwin_get_object_archs(str(p))
if archs and env.machines.host.cpu_family in archs:
- return f
+ return p
else:
mlog.debug('Rejected {}, supports {} but need {}'
- .format(f, archs, env.machines.host.cpu_family))
+ .format(p, archs, env.machines.host.cpu_family))
return None
@functools.lru_cache()
@@ -993,7 +1083,7 @@ class CLikeCompiler:
return value[:]
def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED):
- code = 'int main(void) { return 0; }'
+ code = 'int main(void) { return 0; }\n'
return self.find_library_impl(libname, env, extra_dirs, code, libtype)
def find_framework_paths(self, env):
@@ -1093,7 +1183,7 @@ class CLikeCompiler:
'the compiler you are using. has_link_argument or '
'other similar method can be used instead.'
.format(arg))
- code = 'int i;\n'
+ code = 'extern int i;\nint i;\n'
return self.has_arguments(args, env, code, mode='compile')
def has_multi_link_arguments(self, args, env):
@@ -1102,7 +1192,7 @@ class CLikeCompiler:
# false positive.
args = self.linker.fatal_warnings() + args
args = self.linker_to_compiler_args(args)
- code = 'int main(void) { return 0; }'
+ code = 'int main(void) { return 0; }\n'
return self.has_arguments(args, env, code, mode='link')
@staticmethod
@@ -1131,3 +1221,6 @@ class CLikeCompiler:
return self.compiles(self.attribute_check_func(name), env,
extra_args=self.get_has_func_attribute_extra_args(name))
+
+ def get_disable_assert_args(self) -> T.List[str]:
+ return ['-DNDEBUG']
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 7cfb2c2..f5fd7ef 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -363,7 +363,7 @@ class GnuCompiler(GnuLikeCompiler):
# For some compiler command line arguments, the GNU compilers will
# emit a warning on stderr indicating that an option is valid for a
# another language, but still complete with exit_success
- with self._build_wrapper(code, env, args, None, mode, disable_cache=False, want_output=True) as p:
+ with self._build_wrapper(code, env, args, None, mode) as p:
result = p.returncode == 0
if self.language in {Language.CPP, Language.OBJCPP} and 'is valid for C/ObjC' in p.stde:
result = False
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 681c816..a9967d6 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -107,11 +107,8 @@ class BasicLinkerIsCompilerMixin:
def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
rpath_paths: str, build_rpath: str,
- install_rpath: str) -> T.List[str]:
- return []
-
- def get_linker_debug_crt_args(self) -> T.List[str]:
- return []
+ install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
+ return ([], set())
def get_asneeded_args(self) -> T.List[str]:
return []
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index d0004ce..93101b5 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -114,7 +114,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
# See: https://ninja-build.org/manual.html#_deps
always_args = ['/nologo', '/showIncludes']
warn_args = {
- '0': ['/W1'],
+ '0': [],
'1': ['/W2'],
'2': ['/W3'],
'3': ['/W4'],
@@ -208,6 +208,9 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def openmp_flags(self) -> T.List[str]:
return ['/openmp']
+ def openmp_link_flags(self) -> T.List[str]:
+ return []
+
# FIXME, no idea what these should be.
def thread_flags(self, env: 'Environment') -> T.List[str]:
return []
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index b042bc5..f642a1f 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -86,7 +86,7 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
**kwargs):
ObjCCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
default_warn_args = ['-Wall', '-Winvalid-pch']
self.warn_args = {'0': [],
'1': default_warn_args,
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index 4cfb1ab..871a0a6 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -84,7 +84,7 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
is_cross, info: 'MachineInfo', exe_wrapper=None,
**kwargs):
ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
- ClangCompiler.__init__(self)
+ ClangCompiler.__init__(self, [])
default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
self.warn_args = {'0': [],
'1': default_warn_args,