diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-12-08 11:08:37 -0800 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2021-01-11 11:15:06 -0800 |
commit | 4b0b44aface1cd9ed073733dd80b040b5aaf4c99 (patch) | |
tree | 3150d4f22c7f179edc276b3f9a707c7b74dd9ab4 | |
parent | f202da0689795ba4330581e69a879f089e169f6c (diff) | |
download | meson-4b0b44aface1cd9ed073733dd80b040b5aaf4c99.zip meson-4b0b44aface1cd9ed073733dd80b040b5aaf4c99.tar.gz meson-4b0b44aface1cd9ed073733dd80b040b5aaf4c99.tar.bz2 |
move handling of CFLAGS and friends to environment
This has a bunch of nice features. It obviously centralizes everything,
which is nice. It also means that env is only re-read at `meson --wipe`,
not `meson --reconfigure`. And it's going to allow more cleanups.
-rw-r--r-- | mesonbuild/compilers/c.py | 3 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 75 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 3 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 2 | ||||
-rw-r--r-- | mesonbuild/environment.py | 83 | ||||
-rw-r--r-- | mesonbuild/linkers.py | 17 |
6 files changed, 72 insertions, 111 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 311e65a..4a55b46 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -17,7 +17,6 @@ import typing as T from .. import coredata from ..mesonlib import MachineChoice, MesonException, mlog, version_compare, OptionKey -from ..linkers import LinkerEnvVarsMixin from .c_function_attributes import C_FUNC_ATTRIBUTES from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler @@ -195,7 +194,7 @@ class AppleClangCCompiler(ClangCCompiler): _C2X_VERSION = '>=11.0.0' -class EmscriptenCCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCCompiler): +class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 23a3bc5..cf9f35b 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -22,13 +22,9 @@ from functools import lru_cache from .. import coredata from .. import mlog from .. import mesonlib -from ..linkers import LinkerEnvVarsMixin from ..mesonlib import ( EnvironmentException, MachineChoice, MesonException, - Popen_safe, split_args, LibType, TemporaryDirectoryWinProof, OptionKey, -) -from ..envconfig import ( - get_env_var + Popen_safe, LibType, TemporaryDirectoryWinProof, OptionKey, ) from ..arglist import CompilerArgs @@ -105,7 +101,7 @@ CFLAGS_MAPPING: T.Mapping[str, str] = { CEXE_MAPPING: T.Mapping = { 'c': 'CC', - 'cpp': 'CXX', + 'cpp': 'CXX', } # All these are only for C-linkable languages; see `clink_langs` above. @@ -591,11 +587,6 @@ class Compiler(metaclass=abc.ABCMeta): """ return [] - def get_linker_args_from_envvars(self, - for_machine: MachineChoice, - is_cross: bool) -> T.List[str]: - return self.linker.get_args_from_envvars(for_machine, is_cross) - def get_options(self) -> 'KeyedOptionDictType': return {} @@ -1203,68 +1194,32 @@ class Compiler(metaclass=abc.ABCMeta): def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]: raise EnvironmentException('{} does not know how to do prelinking.'.format(self.id)) -def get_args_from_envvars(lang: str, - for_machine: MachineChoice, - is_cross: bool, - use_linker_args: bool) -> T.Tuple[T.List[str], T.List[str]]: - """ - Returns a tuple of (compile_flags, link_flags) for the specified language - from the inherited environment - """ - if lang not in CFLAGS_MAPPING: - return [], [] - - compile_flags = [] # type: T.List[str] - link_flags = [] # type: T.List[str] - - env_compile_flags = get_env_var(for_machine, is_cross, CFLAGS_MAPPING[lang]) - if env_compile_flags is not None: - compile_flags += split_args(env_compile_flags) - - # Link flags (same for all languages) - if lang in LANGUAGES_USING_LDFLAGS: - link_flags += LinkerEnvVarsMixin.get_args_from_envvars(for_machine, is_cross) - if use_linker_args: - # When the compiler is used as a wrapper around the linker (such as - # with GCC and Clang), the compile flags can be needed while linking - # too. This is also what Autotools does. However, we don't want to do - # this when the linker is stand-alone such as with MSVC C/C++, etc. - link_flags = compile_flags + link_flags - - # Pre-processor flags for certain languages - if lang in LANGUAGES_USING_CPPFLAGS: - env_preproc_flags = get_env_var(for_machine, is_cross, 'CPPFLAGS') - if env_preproc_flags is not None: - compile_flags += split_args(env_preproc_flags) - - return compile_flags, link_flags - def get_global_options(lang: str, comp: T.Type[Compiler], for_machine: MachineChoice, - is_cross: bool) -> 'KeyedOptionDictType': + env: 'Environment') -> 'KeyedOptionDictType': """Retreive options that apply to all compilers for a given language.""" description = 'Extra arguments passed to the {}'.format(lang) argkey = OptionKey('args', lang=lang, machine=for_machine) largkey = argkey.evolve('link_args') + + # We shouldn't need listify here, but until we have a separate + # linker-driver representation and can have that do the combine we have to + # do it htis way. + compile_args = mesonlib.listify(env.options.get(argkey, [])) + link_args = mesonlib.listify(env.options.get(largkey, [])) + + if comp.INVOKES_LINKER: + link_args = compile_args + link_args + opts: 'KeyedOptionDictType' = { argkey: coredata.UserArrayOption( description + ' compiler', - [], split_args=True, user_input=True, allow_dups=True), + compile_args, split_args=True, user_input=True, allow_dups=True), largkey: coredata.UserArrayOption( description + ' linker', - [], split_args=True, user_input=True, allow_dups=True), + link_args, split_args=True, user_input=True, allow_dups=True), } - # Get from env vars. - compile_args, link_args = get_args_from_envvars( - lang, - for_machine, - is_cross, - comp.INVOKES_LINKER) - - opts[argkey].set_value(compile_args) - opts[largkey].set_value(link_args) - return opts diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 2e94e48..ebe3a4f 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -21,7 +21,6 @@ from .. import coredata from .. import mlog from ..mesonlib import MesonException, MachineChoice, version_compare, OptionKey -from ..linkers import LinkerEnvVarsMixin from .compilers import ( gnu_winlibs, msvc_winlibs, @@ -256,7 +255,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler): return ['-lc++'] -class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompiler): +class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index cda0566..f2aba80 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -759,7 +759,7 @@ class CoreData: for_machine: MachineChoice, env: 'Environment') -> None: """Add global language arguments that are needed before compiler/linker detection.""" from .compilers import compilers - options = compilers.get_global_options(lang, comp, for_machine, env.is_cross_build()) + options = compilers.get_global_options(lang, comp, for_machine, env) self.add_compiler_options(options, lang, for_machine, env) def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7555be5..12b9dbb 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import itertools import os, platform, re, sys, shutil, subprocess import tempfile import shlex @@ -605,7 +606,7 @@ class Environment: # # Note that order matters because of 'buildtype', if it is after # 'optimization' and 'debug' keys, it override them. - self.options: T.MutableMapping[OptionKey, str] = collections.OrderedDict() + self.options: T.MutableMapping[OptionKey, T.Union[str, T.List[str]]] = collections.OrderedDict() ## Read in native file(s) to override build machine configuration @@ -750,36 +751,58 @@ class Environment: self.options[key] = v def set_default_options_from_env(self) -> None: - for for_machine in MachineChoice: - for evar, keyname in [('PKG_CONFIG_PATH', 'pkg_config_path'), - ('CMAKE_PREFIX_PATH', 'cmake_prefix_path')]: - p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), evar) - if p_env_pair is not None: - _, p_env = p_env_pair - - # these may contain duplicates, which must be removed, else - # a duplicates-in-array-option warning arises. - if keyname == 'cmake_prefix_path': - if self.machines[for_machine].is_windows(): - # Cannot split on ':' on Windows because its in the drive letter - _p_env = p_env.split(os.pathsep) - else: - # https://github.com/mesonbuild/meson/issues/7294 - _p_env = re.split(r':|;', p_env) - p_list = list(mesonlib.OrderedSet(_p_env)) - elif keyname == 'pkg_config_path': - p_list = list(mesonlib.OrderedSet(p_env.split(':'))) + opts: T.List[T.Tuple[str, str]] = ( + [(v, f'{k}_args') for k, v in compilers.compilers.CFLAGS_MAPPING.items()] + + [ + ('PKG_CONFIG_PATH', 'pkg_config_path'), + ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'), + ('LDFLAGS', 'ldflags'), + ('CPPFLAGS', 'cppflags'), + ] + ) + + for (evar, keyname), for_machine in itertools.product(opts, MachineChoice): + p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), evar) + if p_env_pair is not None: + _, p_env = p_env_pair + + # these may contain duplicates, which must be removed, else + # a duplicates-in-array-option warning arises. + if keyname == 'cmake_prefix_path': + if self.machines[for_machine].is_windows(): + # Cannot split on ':' on Windows because its in the drive letter + _p_env = p_env.split(os.pathsep) else: - raise RuntimeError('Should be unreachable') - p_list = [e for e in p_list if e] # filter out any empty eelemnts - - # Take env vars only on first invocation, if the env changes when - # reconfiguring it gets ignored. - # FIXME: We should remember if we took the value from env to warn - # if it changes on future invocations. - if self.first_invocation: - key = OptionKey(keyname, machine=for_machine) - self.options.setdefault(key, p_list) + # https://github.com/mesonbuild/meson/issues/7294 + _p_env = re.split(r':|;', p_env) + p_list = list(mesonlib.OrderedSet(_p_env)) + elif keyname == 'pkg_config_path': + p_list = list(mesonlib.OrderedSet(p_env.split(':'))) + else: + p_list = split_args(p_env) + p_list = [e for e in p_list if e] # filter out any empty eelemnts + + # Take env vars only on first invocation, if the env changes when + # reconfiguring it gets ignored. + # FIXME: We should remember if we took the value from env to warn + # if it changes on future invocations. + if self.first_invocation: + if keyname == 'ldflags': + key = OptionKey('link_args', machine=for_machine, lang='c') # needs a language to initialize properly + for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS: + key = key.evolve(lang=lang) + v = mesonlib.listify(self.options.get(key, [])) + self.options.setdefault(key, v + p_list) + elif keyname == 'cppflags': + key = OptionKey('args', machine=for_machine, lang='c') + for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS: + key = key.evolve(lang=lang) + v = mesonlib.listify(self.options.get(key, [])) + self.options.setdefault(key, v + p_list) + else: + key = OptionKey.from_string(keyname).evolve(machine=for_machine) + v = mesonlib.listify(self.options.get(key, [])) + self.options.setdefault(key, v + p_list) def create_new_coredata(self, options: 'argparse.Namespace') -> None: # WARNING: Don't use any values from coredata in __init__. It gets diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 8dae94c..86e6aac 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -18,7 +18,6 @@ import typing as T from . import mesonlib from .arglist import CompilerArgs -from .envconfig import get_env_var if T.TYPE_CHECKING: from .coredata import KeyedOptionDictType @@ -301,21 +300,7 @@ def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str: else: return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) - -class LinkerEnvVarsMixin(metaclass=abc.ABCMeta): - - """Mixin reading LDFLAGS from the environment.""" - - @staticmethod - def get_args_from_envvars(for_machine: mesonlib.MachineChoice, - is_cross: bool) -> T.List[str]: - raw_value = get_env_var(for_machine, is_cross, 'LDFLAGS') - if raw_value is not None: - return mesonlib.split_args(raw_value) - else: - return [] - -class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta): +class DynamicLinker(metaclass=abc.ABCMeta): """Base class for dynamic linkers.""" |