summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2019-11-25 12:34:08 -0800
committerDylan Baker <dylan@pnwbakers.com>2019-12-12 10:52:07 -0800
commit87766b37276164eaf359c9e99522dcd6a53be180 (patch)
tree487e5832508555065f48970d602ea69e51a250e4
parent7460e4ccda339d167402bd077dcaa364fab5e172 (diff)
downloadmeson-87766b37276164eaf359c9e99522dcd6a53be180.tar.gz
Allow setting <lang>_args before the compiler is detected
This is required to be able to pass compiler and linker arguments to the methods that try to guess what linker to use.
-rw-r--r--mesonbuild/compilers/compilers.py179
-rw-r--r--mesonbuild/coredata.py21
-rw-r--r--mesonbuild/environment.py1
3 files changed, 102 insertions, 99 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 713a9e74b..9631bd22a 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -795,106 +795,11 @@ class Compiler:
"""
return []
- def use_preproc_flags(self) -> bool:
- """
- Whether the compiler (or processes it spawns) cares about CPPFLAGS
- """
- return self.get_language() in {'c', 'cpp', 'objc', 'objcpp'}
-
- def use_ldflags(self) -> bool:
- """
- Whether the compiler (or processes it spawns) cares about LDFLAGS
- """
- return self.get_language() in languages_using_ldflags
-
def get_linker_args_from_envvars(self) -> typing.List[str]:
return self.linker.get_args_from_envvars()
- def get_args_from_envvars(self) -> typing.Tuple[typing.List[str], typing.List[str]]:
- """
- Returns a tuple of (compile_flags, link_flags) for the specified language
- from the inherited environment
- """
- def log_var(var, val: typing.Optional[str]):
- if val:
- mlog.log('Appending {} from environment: {!r}'.format(var, val))
- else:
- mlog.debug('No {} in the environment, not changing global flags.'.format(var))
-
- lang = self.get_language()
- compiler_is_linker = self.linker is not None and self.linker.invoked_by_compiler()
-
- if lang not in cflags_mapping:
- return [], []
-
- compile_flags = [] # type: typing.List[str]
- link_flags = [] # type: typing.List[str]
-
- env_compile_flags = os.environ.get(cflags_mapping[lang])
- log_var(cflags_mapping[lang], env_compile_flags)
- if env_compile_flags is not None:
- compile_flags += split_args(env_compile_flags)
-
- # Link flags (same for all languages)
- if self.use_ldflags():
- env_link_flags = self.get_linker_args_from_envvars()
- else:
- env_link_flags = []
- log_var('LDFLAGS', env_link_flags)
- link_flags += env_link_flags
- if compiler_is_linker:
- # 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 self.use_preproc_flags():
- env_preproc_flags = os.environ.get('CPPFLAGS')
- log_var('CPPFLAGS', env_preproc_flags)
- if env_preproc_flags is not None:
- compile_flags += split_args(env_preproc_flags)
-
- return compile_flags, link_flags
-
- def get_options(self):
- opts = {} # build afresh every time
- description = 'Extra arguments passed to the {}'.format(self.get_display_language())
- opts.update({
- self.language + '_args': coredata.UserArrayOption(
- description + ' compiler',
- [], split_args=True, user_input=True, allow_dups=True),
- self.language + '_link_args': coredata.UserArrayOption(
- description + ' linker',
- [], split_args=True, user_input=True, allow_dups=True),
- })
-
- return opts
-
- def get_and_default_options(self, properties: Properties):
- """
- Take default values from env variables and/or config files.
- """
- opts = self.get_options()
-
- if properties.fallback:
- # Get from env vars.
- compile_args, link_args = self.get_args_from_envvars()
- else:
- compile_args = []
- link_args = []
-
- for k, o in opts.items():
- if k in properties:
- # Get from configuration files.
- o.set_value(properties[k])
- elif k == self.language + '_args':
- o.set_value(compile_args)
- elif k == self.language + '_link_args':
- o.set_value(link_args)
-
- return opts
+ def get_options(self) -> typing.Dict[str, coredata.UserOption]:
+ return {}
def get_option_compile_args(self, options):
return []
@@ -1220,3 +1125,83 @@ def get_largefile_args(compiler):
# transitionary features and must be enabled by programs that use
# those features explicitly.
return []
+
+
+def get_args_from_envvars(lang: str, use_linker_args: bool) -> typing.Tuple[typing.List[str], typing.List[str]]:
+ """
+ Returns a tuple of (compile_flags, link_flags) for the specified language
+ from the inherited environment
+ """
+ def log_var(var, val: typing.Optional[str]):
+ if val:
+ mlog.log('Appending {} from environment: {!r}'.format(var, val))
+ else:
+ mlog.debug('No {} in the environment, not changing global flags.'.format(var))
+
+ if lang not in cflags_mapping:
+ return [], []
+
+ compile_flags = [] # type: typing.List[str]
+ link_flags = [] # type: typing.List[str]
+
+ env_compile_flags = os.environ.get(cflags_mapping[lang])
+ log_var(cflags_mapping[lang], env_compile_flags)
+ 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:
+ # This is duplicated between the linkers, but I'm not sure how else
+ # to handle this
+ env_link_flags = split_args(os.environ.get('LDFLAGS', ''))
+ else:
+ env_link_flags = []
+ log_var('LDFLAGS', env_link_flags)
+ link_flags += env_link_flags
+ 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 {'c', 'cpp', 'objc', 'objcpp'}:
+ env_preproc_flags = os.environ.get('CPPFLAGS')
+ log_var('CPPFLAGS', env_preproc_flags)
+ 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, properties: Properties) -> typing.Dict[str, coredata.UserOption]:
+ """Retreive options that apply to all compilers for a given language."""
+ description = 'Extra arguments passed to the {}'.format(lang)
+ opts = {
+ lang + '_args': coredata.UserArrayOption(
+ description + ' compiler',
+ [], split_args=True, user_input=True, allow_dups=True),
+ lang + '_link_args': coredata.UserArrayOption(
+ description + ' linker',
+ [], split_args=True, user_input=True, allow_dups=True),
+ }
+
+ if properties.fallback:
+ # Get from env vars.
+ # XXX: True here is a hack
+ compile_args, link_args = get_args_from_envvars(lang, True)
+ else:
+ compile_args = []
+ link_args = []
+
+ for k, o in opts.items():
+ if k in properties:
+ # Get from configuration files.
+ o.set_value(properties[k])
+ elif k == lang + '_args':
+ o.set_value(compile_args)
+ elif k == lang + '_link_args':
+ o.set_value(link_args)
+
+ return opts
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index bb1d27794..58ccae061 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -35,6 +35,8 @@ import shlex
if TYPE_CHECKING:
from . import dependencies
+ from .compilers import Compiler
+ from .environment import Environment
OptionDictType = Dict[str, 'UserOption[Any]']
@@ -742,13 +744,28 @@ class CoreData:
self.set_options(options, subproject=subproject)
- def process_new_compiler(self, lang: str, comp, env):
+ def add_lang_args(self, lang: str, for_machine: MachineChoice, env: 'Environment') -> None:
+ """Add global language arguments that are needed before compiler/linker detection."""
+ from .compilers import compilers
+
+ optprefix = lang + '_'
+ for k, o in compilers.get_global_options(lang, env.properties[for_machine]).items():
+ if not k.startswith(optprefix):
+ raise MesonException('Internal error, %s has incorrect prefix.' % k)
+ # prefixed compiler options affect just this machine
+ opt_prefix = for_machine.get_prefix()
+ if opt_prefix + k in env.cmd_line_options:
+ o.set_value(env.cmd_line_options[opt_prefix + k])
+ self.compiler_options[for_machine].setdefault(k, o)
+
+ def process_new_compiler(self, lang: str, comp: Type['Compiler'], env: 'Environment') -> None:
from . import compilers
self.compilers[comp.for_machine][lang] = comp
+ enabled_opts = []
optprefix = lang + '_'
- for k, o in comp.get_and_default_options(env.properties[comp.for_machine]).items():
+ for k, o in comp.get_options().items():
if not k.startswith(optprefix):
raise MesonException('Internal error, %s has incorrect prefix.' % k)
# prefixed compiler options affect just this machine
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 8443a47ba..dc269d2a3 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -1538,6 +1538,7 @@ class Environment:
return comp
def detect_compiler_for(self, lang: str, for_machine: MachineChoice):
+ self.coredata.add_lang_args(lang, for_machine, self)
comp = self.compiler_from_language(lang, for_machine)
if comp is not None:
assert comp.for_machine == for_machine