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.
pull/8159/head
Dylan Baker 4 years ago
parent f202da0689
commit 4b0b44afac
  1. 3
      mesonbuild/compilers/c.py
  2. 75
      mesonbuild/compilers/compilers.py
  3. 3
      mesonbuild/compilers/cpp.py
  4. 2
      mesonbuild/coredata.py
  5. 83
      mesonbuild/environment.py
  6. 17
      mesonbuild/linkers.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,

@ -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

@ -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,

@ -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:

@ -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

@ -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."""

Loading…
Cancel
Save