aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/environment.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/environment.py')
-rw-r--r--mesonbuild/environment.py116
1 files changed, 85 insertions, 31 deletions
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index f322cda..489ef50 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -12,6 +12,7 @@ import collections
from . import coredata
from . import mesonlib
from . import machinefile
+from . import options
CmdLineFileParser = machinefile.CmdLineFileParser
@@ -34,6 +35,7 @@ from .compilers import (
is_library,
is_llvm_ir,
is_object,
+ is_separate_compile,
is_source,
)
@@ -43,13 +45,20 @@ from mesonbuild import envconfig
if T.TYPE_CHECKING:
from .compilers import Compiler
from .compilers.mixins.visualstudio import VisualStudioLikeCompiler
- from .options import ElementaryOptionValues
+ from .options import OptionDict, ElementaryOptionValues
from .wrap.wrap import Resolver
from . import cargo
CompilersDict = T.Dict[str, Compiler]
+NON_LANG_ENV_OPTIONS = [
+ ('PKG_CONFIG_PATH', 'pkg_config_path'),
+ ('CMAKE_PREFIX_PATH', 'cmake_prefix_path'),
+ ('LDFLAGS', 'ldflags'),
+ ('CPPFLAGS', 'cppflags'),
+]
+
build_filename = 'meson.build'
@@ -639,7 +648,12 @@ 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, ElementaryOptionValues] = collections.OrderedDict()
+ self.options: OptionDict = collections.OrderedDict()
+
+ # Environment variables with the name converted into an OptionKey type.
+ # These have subtly different behavior compared to machine files, so do
+ # not store them in self.options. See _set_default_options_from_env.
+ self.env_opts: OptionDict = {}
self.machinestore = machinefile.MachineFileStore(self.coredata.config_files, self.coredata.cross_files, self.source_dir)
@@ -716,13 +730,14 @@ class Environment:
def mfilestr2key(self, machine_file_string: str, section: T.Optional[str], section_subproject: T.Optional[str], machine: MachineChoice) -> OptionKey:
key = OptionKey.from_string(machine_file_string)
- assert key.machine == MachineChoice.HOST
if key.subproject:
suggestion = section if section == 'project options' else 'built-in options'
raise MesonException(f'Do not set subproject options in [{section}] section, use [subproject:{suggestion}] instead.')
if section_subproject:
key = key.evolve(subproject=section_subproject)
if machine == MachineChoice.BUILD:
+ if key.machine == MachineChoice.BUILD:
+ mlog.deprecation('Setting build machine options in the native file does not need the "build." prefix', once=True)
return key.evolve(machine=machine)
return key
@@ -777,12 +792,7 @@ class Environment:
def _set_default_options_from_env(self) -> None:
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'),
- ]
+ NON_LANG_ENV_OPTIONS
)
env_opts: T.DefaultDict[OptionKey, T.List[str]] = collections.defaultdict(list)
@@ -817,35 +827,35 @@ class Environment:
env_opts[key].extend(p_list)
elif keyname == 'cppflags':
for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
- key = OptionKey(f'{lang}_env_args', machine=for_machine)
+ key = OptionKey(f'{lang}_args', machine=for_machine)
env_opts[key].extend(p_list)
else:
key = OptionKey.from_string(keyname).evolve(machine=for_machine)
if evar in compilers.compilers.CFLAGS_MAPPING.values():
- # If this is an environment variable, we have to
- # store it separately until the compiler is
- # instantiated, as we don't know whether the
- # compiler will want to use these arguments at link
- # time and compile time (instead of just at compile
- # time) until we're instantiating that `Compiler`
- # object. This is required so that passing
- # `-Dc_args=` on the command line and `$CFLAGS`
- # have subtly different behavior. `$CFLAGS` will be
- # added to the linker command line if the compiler
- # acts as a linker driver, `-Dc_args` will not.
- #
- # We still use the original key as the base here, as
- # we want to inherit the machine and the compiler
- # language
lang = key.name.split('_', 1)[0]
- key = key.evolve(f'{lang}_env_args')
+ key = key.evolve(f'{lang}_args')
env_opts[key].extend(p_list)
- # Only store options that are not already in self.options,
- # otherwise we'd override the machine files
- for k, v in env_opts.items():
- if k not in self.options:
- self.options[k] = v
+ # If this is an environment variable, we have to
+ # store it separately until the compiler is
+ # instantiated, as we don't know whether the
+ # compiler will want to use these arguments at link
+ # time and compile time (instead of just at compile
+ # time) until we're instantiating that `Compiler`
+ # object. This is required so that passing
+ # `-Dc_args=` on the command line and `$CFLAGS`
+ # have subtly different behavior. `$CFLAGS` will be
+ # added to the linker command line if the compiler
+ # acts as a linker driver, `-Dc_args` will not.
+ for (_, keyname), for_machine in itertools.product(NON_LANG_ENV_OPTIONS, MachineChoice):
+ key = OptionKey.from_string(keyname).evolve(machine=for_machine)
+ # Only store options that are not already in self.options,
+ # otherwise we'd override the machine files
+ if key in env_opts and key not in self.options:
+ self.options[key] = env_opts[key]
+ del env_opts[key]
+
+ self.env_opts.update(env_opts)
def _set_default_binaries_from_env(self) -> None:
"""Set default binaries from the environment.
@@ -928,6 +938,9 @@ class Environment:
def is_assembly(self, fname: 'mesonlib.FileOrString') -> bool:
return is_assembly(fname)
+ def is_separate_compile(self, fname: 'mesonlib.FileOrString') -> bool:
+ return is_separate_compile(fname)
+
def is_llvm_ir(self, fname: 'mesonlib.FileOrString') -> bool:
return is_llvm_ir(fname)
@@ -1064,3 +1077,44 @@ class Environment:
if extra_paths:
env.prepend('PATH', list(extra_paths))
return env
+
+ def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
+ for_machine: MachineChoice) -> None:
+ """Add global language arguments that are needed before compiler/linker detection."""
+ description = f'Extra arguments passed to the {lang}'
+ argkey = OptionKey(f'{lang}_args', machine=for_machine)
+ largkey = OptionKey(f'{lang}_link_args', machine=for_machine)
+
+ comp_args_from_envvar = False
+ comp_options = self.coredata.optstore.get_pending_value(argkey)
+ if comp_options is None:
+ comp_args_from_envvar = True
+ comp_options = self.env_opts.get(argkey, [])
+
+ link_options = self.coredata.optstore.get_pending_value(largkey)
+ if link_options is None:
+ link_options = self.env_opts.get(largkey, [])
+
+ assert isinstance(comp_options, (str, list)), 'for mypy'
+ assert isinstance(link_options, (str, list)), 'for mypy'
+
+ cargs = options.UserStringArrayOption(
+ argkey.name,
+ description + ' compiler',
+ comp_options, split_args=True, allow_dups=True)
+
+ largs = options.UserStringArrayOption(
+ largkey.name,
+ description + ' linker',
+ link_options, split_args=True, allow_dups=True)
+
+ self.coredata.optstore.add_compiler_option(lang, argkey, cargs)
+ self.coredata.optstore.add_compiler_option(lang, largkey, largs)
+
+ if comp.INVOKES_LINKER and comp_args_from_envvar:
+ # If the compiler acts as a linker driver, and we're using the
+ # environment variable flags for both the compiler and linker
+ # arguments, then put the compiler flags in the linker flags as well.
+ # This is how autotools works, and the env vars feature is for
+ # autotools compatibility.
+ largs.extend_value(comp_options)