diff options
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r-- | mesonbuild/compilers/__init__.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 5 | ||||
-rw-r--r-- | mesonbuild/compilers/c_function_attributes.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 394 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 11 | ||||
-rw-r--r-- | mesonbuild/compilers/cuda.py | 10 | ||||
-rw-r--r-- | mesonbuild/compilers/d.py | 28 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 14 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/arm.py | 28 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clang.py | 17 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clike.py | 185 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/gnu.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/islinker.py | 7 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/visualstudio.py | 5 | ||||
-rw-r--r-- | mesonbuild/compilers/objc.py | 2 | ||||
-rw-r--r-- | mesonbuild/compilers/objcpp.py | 2 |
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, |