compilers: Use enum for for deupdlication returns in CompilerArgs

pull/7369/head
Dylan Baker 5 years ago
parent d6c6b933c4
commit b887212bee
  1. 63
      mesonbuild/compilers/compilers.py

@ -18,6 +18,7 @@ from collections import deque
import itertools import itertools
import typing as T import typing as T
from functools import lru_cache from functools import lru_cache
import enum
from ..linkers import ( from ..linkers import (
GnuLikeDynamicLinkerMixin, LinkerEnvVarsMixin, SolarisDynamicLinker, GnuLikeDynamicLinkerMixin, LinkerEnvVarsMixin, SolarisDynamicLinker,
@ -409,6 +410,28 @@ class RunResult:
self.stdout = stdout self.stdout = stdout
self.stderr = stderr self.stderr = stderr
class Dedup(enum.Enum):
"""What kind of deduplication can be done to compiler args.
OVERRIDEN - 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.
UNIQUE - Arguments that once specified cannot be undone, such as `-c` or
`-pipe`. New instances of these can be completely skipped.
NO_DEDUP - 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.
"""
NO_DEDUP = 0
UNIQUE = 1
OVERRIDEN = 2
class CompilerArgs(collections.abc.MutableSequence): class CompilerArgs(collections.abc.MutableSequence):
''' '''
List-like class that manages a list of compiler arguments. Should be used List-like class that manages a list of compiler arguments. Should be used
@ -486,13 +509,13 @@ class CompilerArgs(collections.abc.MutableSequence):
dedup = self._can_dedup(a) dedup = self._can_dedup(a)
if a not in pre_flush_set: if a not in pre_flush_set:
pre_flush.append(a) pre_flush.append(a)
if dedup == 2: if dedup is Dedup.OVERRIDEN:
pre_flush_set.add(a) pre_flush_set.add(a)
for a in reversed(self.post): for a in reversed(self.post):
dedup = self._can_dedup(a) dedup = self._can_dedup(a)
if a not in post_flush_set: if a not in post_flush_set:
post_flush.appendleft(a) post_flush.appendleft(a)
if dedup == 2: if dedup is Dedup.OVERRIDEN:
post_flush_set.add(a) post_flush_set.add(a)
#pre and post will overwrite every element that is in the container #pre and post will overwrite every element that is in the container
@ -551,29 +574,15 @@ class CompilerArgs(collections.abc.MutableSequence):
@classmethod @classmethod
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
def _can_dedup(cls, arg): def _can_dedup(cls, arg: str) -> Dedup:
''' """Returns whether the argument can be safely de-duped.
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. In addition to these, we handle library arguments specially.
With GNU ld, we surround library arguments with -Wl,--start/end-group With GNU ld, we surround library arguments with -Wl,--start/end-gr -> Dedupoup
to recursively search for symbols in the libraries. This is not needed to recursively search for symbols in the libraries. This is not needed
with other linkers. with other linkers.
''' """
# A standalone argument must never be deduplicated because it is # A standalone argument must never be deduplicated because it is
# defined by what comes _after_ it. Thus dedupping this: # defined by what comes _after_ it. Thus dedupping this:
# -D FOO -D BAR # -D FOO -D BAR
@ -583,7 +592,7 @@ class CompilerArgs(collections.abc.MutableSequence):
# FOO -D BAR # FOO -D BAR
# both of which are invalid. # both of which are invalid.
if arg in cls.dedup2_prefixes: if arg in cls.dedup2_prefixes:
return 0 return Dedup.NO_DEDUP
if arg.startswith('-L='): if arg.startswith('-L='):
# DMD and LDC proxy all linker arguments using -L=; in conjunction # DMD and LDC proxy all linker arguments using -L=; in conjunction
# with ld64 on macOS this can lead to command line arguments such # with ld64 on macOS this can lead to command line arguments such
@ -592,17 +601,17 @@ class CompilerArgs(collections.abc.MutableSequence):
# spaces and quoting does not work. if we deduplicate these then # spaces and quoting does not work. if we deduplicate these then
# one of the -L=0 arguments will be removed and the version # one of the -L=0 arguments will be removed and the version
# argument will consume the next argument instead. # argument will consume the next argument instead.
return 0 return Dedup.NO_DEDUP
if arg in cls.dedup2_args or \ if arg in cls.dedup2_args or \
arg.startswith(cls.dedup2_prefixes) or \ arg.startswith(cls.dedup2_prefixes) or \
arg.endswith(cls.dedup2_suffixes): arg.endswith(cls.dedup2_suffixes):
return 2 return Dedup.OVERRIDEN
if arg in cls.dedup1_args or \ if arg in cls.dedup1_args or \
arg.startswith(cls.dedup1_prefixes) or \ arg.startswith(cls.dedup1_prefixes) or \
arg.endswith(cls.dedup1_suffixes) or \ arg.endswith(cls.dedup1_suffixes) or \
re.search(cls.dedup1_regex, arg): re.search(cls.dedup1_regex, arg):
return 1 return Dedup.UNIQUE
return 0 return Dedup.NO_DEDUP
@classmethod @classmethod
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
@ -725,7 +734,7 @@ class CompilerArgs(collections.abc.MutableSequence):
# previous occurrence of it and adding a new one, or not adding the # previous occurrence of it and adding a new one, or not adding the
# new occurrence. # new occurrence.
dedup = self._can_dedup(arg) dedup = self._can_dedup(arg)
if dedup == 1: if dedup is Dedup.UNIQUE:
# Argument already exists and adding a new instance is useless # 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 continue

Loading…
Cancel
Save