diff options
-rw-r--r-- | mesonbuild/compilers/compilers.py | 179 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 21 | ||||
-rw-r--r-- | mesonbuild/environment.py | 1 |
3 files changed, 102 insertions, 99 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 713a9e7..9631bd2 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 bb1d277..58ccae0 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 8443a47..dc269d2 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 |