arglist: Split the C/C++ specifics parts into a subclass for CLike

This means that we don't need work arounds for D-like compilers, as the
special c-like hanlding wont be used for D compilers.
pull/7369/head
Dylan Baker 5 years ago
parent 93c3ec7e2d
commit 4f6bd29ac9
  1. 93
      mesonbuild/arglist.py
  2. 56
      mesonbuild/compilers/mixins/clike.py

@ -31,7 +31,6 @@ UNIXY_COMPILER_INTERNAL_LIBS = ['m', 'c', 'pthread', 'dl', 'rt'] # type: T.List
# execinfo is a compiler lib on FreeBSD and NetBSD
if mesonlib.is_freebsd() or mesonlib.is_netbsd():
UNIXY_COMPILER_INTERNAL_LIBS.append('execinfo')
SOREGEX = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
class Dedup(enum.Enum):
@ -112,11 +111,11 @@ class CompilerArgs(collections.abc.MutableSequence):
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._container = list(iterable) if iterable is not None else [] # type: T.List[str]
self.pre = collections.deque() # type: T.Deque[str]
self.post = collections.deque() # type: T.Deque[str]
# Flush the saved pre and post list into the __container list
# Flush the saved pre and post list into the _container list
#
# This correctly deduplicates the entries after _can_dedup definition
# Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot.
@ -141,19 +140,19 @@ class CompilerArgs(collections.abc.MutableSequence):
post_flush_set.add(a)
#pre and post will overwrite every element that is in the container
#only copy over args that are in __container but not in the post flush or pre flush set
#only copy over args that are in _container but not in the post flush or pre flush set
for a in self.__container:
for a in self._container:
if a not in post_flush_set and a not in pre_flush_set:
pre_flush.append(a)
self.__container = list(pre_flush) + list(post_flush)
self._container = list(pre_flush) + list(post_flush)
self.pre.clear()
self.post.clear()
def __iter__(self) -> T.Iterator[str]:
self.flush_pre_post()
return iter(self.__container)
return iter(self._container)
@T.overload # noqa: F811
def __getitem__(self, index: int) -> str: # noqa: F811
@ -165,7 +164,7 @@ class CompilerArgs(collections.abc.MutableSequence):
def __getitem__(self, index): # noqa: F811
self.flush_pre_post()
return self.__container[index]
return self._container[index]
@T.overload # noqa: F811
def __setitem__(self, index: int, value: str) -> None: # noqa: F811
@ -177,22 +176,22 @@ class CompilerArgs(collections.abc.MutableSequence):
def __setitem__(self, index, value) -> None: # noqa: F811
self.flush_pre_post()
self.__container[index] = value
self._container[index] = value
def __delitem__(self, index: T.Union[int, slice]) -> None:
self.flush_pre_post()
del self.__container[index]
del self._container[index]
def __len__(self) -> int:
return len(self.__container) + len(self.pre) + len(self.post)
return len(self._container) + len(self.pre) + len(self.post)
def insert(self, index: int, value: str) -> None:
self.flush_pre_post()
self.__container.insert(index, value)
self._container.insert(index, value)
def copy(self) -> 'CompilerArgs':
self.flush_pre_post()
return type(self)(self.compiler, self.__container.copy())
return type(self)(self.compiler, self._container.copy())
@classmethod
@lru_cache(maxsize=None)
@ -231,16 +230,7 @@ class CompilerArgs(collections.abc.MutableSequence):
def _should_prepend(cls, arg: str) -> bool:
return arg.startswith(cls.prepend_prefixes)
def need_to_split_linker_args(self) -> bool:
# XXX: gross
from .compilers import Compiler
return isinstance(self.compiler, Compiler) and self.compiler.get_language() == 'd'
def to_native(self, copy: bool = False) -> T.List[str]:
# XXX: gross
from .compilers import Compiler
from .linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
# 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
@ -250,54 +240,7 @@ class CompilerArgs(collections.abc.MutableSequence):
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)
return self.compiler.unix_args_to_native(new._container)
def append_direct(self, arg: str) -> None:
'''
@ -309,7 +252,7 @@ class CompilerArgs(collections.abc.MutableSequence):
if os.path.isabs(arg):
self.append(arg)
else:
self.__container.append(arg)
self._container.append(arg)
def extend_direct(self, iterable: T.Iterable[str]) -> None:
'''
@ -353,7 +296,7 @@ class CompilerArgs(collections.abc.MutableSequence):
dedup = self._can_dedup(arg)
if dedup is Dedup.UNIQUE:
# Argument already exists and adding a new instance is useless
if arg in self.__container or arg in self.pre or arg in self.post:
if arg in self._container or arg in self.pre or arg in self.post:
continue
if self._should_prepend(arg):
tmp_pre.appendleft(arg)
@ -373,9 +316,9 @@ class CompilerArgs(collections.abc.MutableSequence):
self.flush_pre_post()
# Only allow equality checks against other CompilerArgs and lists instances
if isinstance(other, CompilerArgs):
return self.compiler == other.compiler and self.__container == other.__container
return self.compiler == other.compiler and self._container == other._container
elif isinstance(other, list):
return self.__container == other
return self._container == other
return NotImplemented
def append(self, arg: str) -> None:
@ -386,4 +329,4 @@ class CompilerArgs(collections.abc.MutableSequence):
def __repr__(self) -> str:
self.flush_pre_post()
return '{}({!r}, {!r})'.format(self.__name__, self.compiler, self.__container)
return 'CompilerArgs({!r}, {!r})'.format(self.compiler, self._container)

@ -32,7 +32,7 @@ from pathlib import Path
from ... import arglist
from ... import mesonlib
from ... import mlog
from ...arglist import CompilerArgs
from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker
from ...mesonlib import LibType
from .. import compilers
from .visualstudio import VisualStudioLikeCompiler
@ -40,8 +40,9 @@ 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(CompilerArgs):
class CLikeCompilerArgs(arglist.CompilerArgs):
prepend_prefixes = ('-I', '-L')
dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U')
@ -49,9 +50,58 @@ class CLikeCompilerArgs(CompilerArgs):
# 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:

Loading…
Cancel
Save