Environment: Fix passing envrionment variables CPPFLAGS and CFLAGS

Or other language flags that use CPPFLAGS (like CXXFLAGS). The problem
here is actually rather simple, `dict.setdefault()` doesn't work like I
thought it did, I thought it created a weak entry, but it actually is
equivalent to:
```python
if k not in dict:
    dict[k] = v
```
Instead we'll use an intermediate dictionary (a default dictionary
actually, since that makes things a little cleaner) and then add the
keys from that dict to self.options as applicable.

Test case written by Jussi, Fix by Dylan

Co-authored-by: Jussi Pakkanen
Fixes: #8361
Fixes: #8345
pull/8380/head
Dylan Baker 4 years ago committed by Jussi Pakkanen
parent 7812ceec5f
commit 10d94a12b8
  1. 19
      mesonbuild/environment.py
  2. 1
      mesonbuild/mesonlib/universal.py
  3. 8
      run_unittests.py
  4. 4
      test cases/unit/90 multiple envvars/meson.build
  5. 18
      test cases/unit/90 multiple envvars/prog.c
  6. 18
      test cases/unit/90 multiple envvars/prog.cpp

@ -788,6 +788,8 @@ class Environment:
]
)
env_opts: T.DefaultDict[OptionKey, T.List[str]] = collections.defaultdict(list)
for (evar, keyname), for_machine in itertools.product(opts, MachineChoice):
p_env = _get_env_var(for_machine, self.is_cross_build(), evar)
if p_env is not None:
@ -805,7 +807,7 @@ class Environment:
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
p_list = [e for e in p_list if e] # filter out any empty elements
# Take env vars only on first invocation, if the env changes when
# reconfiguring it gets ignored.
@ -816,18 +818,21 @@ class Environment:
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)
env_opts[key].extend(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)
env_opts[key].extend(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)
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
def _set_default_binaries_from_env(self) -> None:
"""Set default binaries from the environment.

@ -2023,7 +2023,6 @@ class OptionKey:
This takes strings like `mysubproject:build.myoption` and Creates an
OptionKey out of them.
"""
try:
subproject, raw2 = raw.split(':')
except ValueError:

@ -5476,6 +5476,14 @@ class AllPlatformTests(BasePlatformTests):
projinfo = self.introspect('--projectinfo')
self.assertEqual(projinfo['version'], '1.0.0')
def test_cflags_cppflags(self):
envs = {'CPPFLAGS': '-DCPPFLAG',
'CFLAGS': '-DCFLAG',
'CXXFLAGS': '-DCXXFLAG'}
srcdir = os.path.join(self.unit_test_dir, '90 multiple envvars')
self.init(srcdir, override_envvars=envs)
self.build()
class FailureTests(BasePlatformTests):
'''

@ -0,0 +1,4 @@
project('multienv', 'c', 'cpp')
executable('cexe', 'prog.c')
executable('cppexe', 'prog.cpp')

@ -0,0 +1,18 @@
#include<stdio.h>
#ifndef CPPFLAG
#error CPPFLAG not set
#endif
#ifndef CFLAG
#error CFLAGS not set
#endif
#ifdef CXXFLAG
#error CXXFLAG is set
#endif
int main(int argc, char **argv) {
printf("%d %s\n", argc, argv[0]);
return 0;
}

@ -0,0 +1,18 @@
#include<cstdio>
#ifndef CPPFLAG
#error CPPFLAG not set
#endif
#ifdef CFLAG
#error CFLAG is set
#endif
#ifndef CXXFLAG
#error CXXFLAG not set
#endif
int main(int argc, char **argv) {
printf("%d %s\n", argc, argv[0]);
return 0;
}
Loading…
Cancel
Save