diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/build.py | 15 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 18 | ||||
-rw-r--r-- | mesonbuild/compilers/d.py | 9 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/gnu.py | 9 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/visualstudio.py | 12 | ||||
-rw-r--r-- | mesonbuild/dependencies/base.py | 34 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 25 |
7 files changed, 108 insertions, 14 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 4ec742d..267bd16 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1024,17 +1024,17 @@ This will become a hard error in a future Meson release.''') if isinstance(dep, dependencies.InternalDependency): # Those parts that are internal. self.process_sourcelist(dep.sources) - self.add_include_dirs(dep.include_directories) + self.add_include_dirs(dep.include_directories, dep.get_include_type()) for l in dep.libraries: self.link(l) for l in dep.whole_libraries: self.link_whole(l) - if dep.compile_args or dep.link_args: + if dep.get_compile_args() or dep.get_link_args(): # Those parts that are external. extpart = dependencies.InternalDependency('undefined', [], - dep.compile_args, - dep.link_args, + dep.get_compile_args(), + dep.get_link_args(), [], [], [], []) self.external_deps.append(extpart) # Deps of deps. @@ -1150,7 +1150,7 @@ You probably should put it in link_with instead.''') raise MesonException('File %s does not exist.' % f) self.pch[language] = pchlist - def add_include_dirs(self, args): + def add_include_dirs(self, args, set_is_system: typing.Optional[str] = None): ids = [] for a in args: # FIXME same hack, forcibly unpack from holder. @@ -1159,6 +1159,11 @@ You probably should put it in link_with instead.''') if not isinstance(a, IncludeDirs): raise InvalidArguments('Include directory to be added is not an include directory object.') ids.append(a) + if set_is_system is None: + set_is_system = 'preserve' + if set_is_system != 'preserve': + is_system = set_is_system == 'system' + ids = [IncludeDirs(x.get_curdir(), x.get_incdirs(), is_system, x.get_extra_build_dirs()) for x in ids] self.include_dirs += ids def add_compiler_args(self, language, args): diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index b79fa41..ac74fc3 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -420,7 +420,7 @@ class CompilerArgs(list): # 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', '-L', '-D', '-U') + dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U') dedup2_suffixes = () dedup2_args = () # Arg prefixes and args that must be de-duped by returning 1 @@ -548,6 +548,22 @@ class CompilerArgs(list): # 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 = [] + for i, each in enumerate(new): + # Remove the -isystem and the path if the path is a dafault 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) def append_direct(self, arg): diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 5e0c173..346f18e 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -285,7 +285,14 @@ class DmdLikeCompilerMixin: if arg.startswith('-isystem='): dcargs.append('-I=' + arg[9:]) else: - dcargs.append('-I') + dcargs.append('-I' + arg[8:]) + continue + elif arg.startswith('-idirafter'): + # same as -isystem, but appends the path instead + if arg.startswith('-idirafter='): + dcargs.append('-I=' + arg[11:]) + else: + dcargs.append('-I' + arg[10:]) continue elif arg.startswith('-L/') or arg.startswith('-L./'): # we need to handle cases where -L is set by e.g. a pkg-config diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 998b86c..f4ce5b9 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -84,14 +84,13 @@ gnu_color_args = { } # type: typing.Dict[str, typing.List[str]] -# TODO: The result from calling compiler should be cached. So that calling this -# function multiple times don't add latency. -def gnulike_default_include_dirs(compiler: typing.List[str], lang: str) -> typing.List[str]: +@functools.lru_cache(maxsize=None) +def gnulike_default_include_dirs(compiler: typing.Tuple[str], lang: str) -> typing.List[str]: if lang == 'cpp': lang = 'c++' env = os.environ.copy() env["LC_ALL"] = 'C' - cmd = compiler + ['-x{}'.format(lang), '-E', '-v', '-'] + cmd = list(compiler) + ['-x{}'.format(lang), '-E', '-v', '-'] p = subprocess.Popen( cmd, stdin=subprocess.DEVNULL, @@ -171,7 +170,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta): return gnulike_instruction_set_args.get(instruction_set, None) def get_default_include_dirs(self) -> typing.List[str]: - return gnulike_default_include_dirs(self.exelist, self.language) + return gnulike_default_include_dirs(tuple(self.exelist), self.language) @abc.abstractmethod def openmp_flags(self) -> typing.List[str]: diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 48a2229..9fddbb4 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -228,6 +228,18 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): continue else: i = name + '.lib' + elif i.startswith('-isystem'): + # just use /I for -isystem system include path s + if i.startswith('-isystem='): + i = '/I' + i[9:] + else: + i = '/I' + i[8:] + elif i.startswith('-idirafter'): + # same as -isystem, but appends the path instead + if i.startswith('-idirafter='): + i = '/I' + i[11:] + else: + i = '/I' + i[10:] # -pthread in link flags is only used on Linux elif i == '-pthread': continue diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 4e95c94..3c55a56 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -104,6 +104,16 @@ class Dependency: return methods + @classmethod + def _process_include_type_kw(cls, kwargs) -> str: + if 'include_type' not in kwargs: + return 'preserve' + if not isinstance(kwargs['include_type'], str): + raise DependencyException('The include_type kwarg must be a string type') + if kwargs['include_type'] not in ['preserve', 'system', 'non-system']: + raise DependencyException("include_type may only be one of ['preserve', 'system', 'non-system']") + return kwargs['include_type'] + def __init__(self, type_name, kwargs): self.name = "null" self.version = None @@ -117,6 +127,7 @@ class Dependency: self.raw_link_args = None self.sources = [] self.methods = self._process_method_kw(kwargs) + self.include_type = self._process_include_type_kw(kwargs) self.ext_deps = [] # type: List[Dependency] def __repr__(self): @@ -124,6 +135,22 @@ class Dependency: return s.format(self.__class__.__name__, self.name, self.is_found) def get_compile_args(self): + if self.include_type == 'system': + converted = [] + for i in self.compile_args: + if i.startswith('-I') or i.startswith('/I'): + converted += ['-isystem' + i[2:]] + else: + converted += [i] + return converted + if self.include_type == 'non-system': + converted = [] + for i in self.compile_args: + if i.startswith('-isystem'): + converted += ['-I' + i[8:]] + else: + converted += [i] + return converted return self.compile_args def get_link_args(self, raw=False): @@ -152,6 +179,9 @@ class Dependency: else: return 'unknown' + def get_include_type(self) -> str: + return self.include_type + def get_exe_args(self, compiler): return [] @@ -200,6 +230,10 @@ class Dependency: return default_value raise DependencyException('No default provided for dependency {!r}, which is not pkg-config, cmake, or config-tool based.'.format(self)) + def generate_system_dependency(self, include_type: str) -> typing.Type['Dependency']: + new_dep = copy.deepcopy(self) + new_dep.include_type = self._process_include_type_kw({'include_type': include_type}) + return new_dep class InternalDependency(Dependency): def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index ec7a7b2..1d76a1d 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -34,13 +34,12 @@ from .interpreterbase import ObjectHolder from .modules import ModuleReturnValue from .cmake import CMakeInterpreter -from pathlib import Path +from pathlib import Path, PurePath import os, shutil, uuid import re, shlex import subprocess from collections import namedtuple from itertools import chain -from pathlib import PurePath import functools from typing import Sequence, List, Union, Optional, Dict, Any @@ -413,6 +412,8 @@ class DependencyHolder(InterpreterObject, ObjectHolder): 'get_configtool_variable': self.configtool_method, 'get_variable': self.variable_method, 'partial_dependency': self.partial_dependency_method, + 'include_type': self.include_type_method, + 'as_system': self.as_system_method, }) def found(self): @@ -474,6 +475,24 @@ class DependencyHolder(InterpreterObject, ObjectHolder): def variable_method(self, args, kwargs): return self.held_object.get_variable(**kwargs) + @FeatureNew('dep.include_type', '0.52.0') + @noPosargs + @permittedKwargs({}) + def include_type_method(self, args, kwargs): + return self.held_object.get_include_type() + + @FeatureNew('dep.as_system', '0.52.0') + @permittedKwargs({}) + def as_system_method(self, args, kwargs): + args = listify(args) + new_is_system = 'system' + if len(args) > 1: + raise InterpreterException('as_system takes only one optional value') + if len(args) == 1: + new_is_system = args[0] + new_dep = self.held_object.generate_system_dependency(new_is_system) + return DependencyHolder(new_dep, self.subproject) + class ExternalProgramHolder(InterpreterObject, ObjectHolder): def __init__(self, ep): InterpreterObject.__init__(self) @@ -2000,6 +2019,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'}, 'version', 'private_headers', 'cmake_args', + 'include_type', }, 'declare_dependency': {'include_directories', 'link_with', @@ -3050,6 +3070,7 @@ external dependencies (including libraries) must go to "dependencies".''') elif name == 'openmp': FeatureNew('OpenMP Dependency', '0.46.0').use(self.subproject) + @FeatureNewKwargs('dependency', '0.52.0', ['include_type']) @FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args']) @FeatureNewKwargs('dependency', '0.49.0', ['disabler']) @FeatureNewKwargs('dependency', '0.40.0', ['method']) |