aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--docs/markdown/Cross-compilation.md20
-rw-r--r--docs/markdown/IDE-integration.md15
-rw-r--r--mesonbuild/backend/backends.py17
-rw-r--r--mesonbuild/backend/ninjabackend.py13
-rw-r--r--mesonbuild/backend/vs2010backend.py18
-rw-r--r--mesonbuild/build.py20
-rw-r--r--mesonbuild/compilers/c.py129
-rw-r--r--mesonbuild/compilers/c_function_attributes.py3
-rw-r--r--mesonbuild/compilers/compilers.py13
-rw-r--r--mesonbuild/compilers/cpp.py233
-rw-r--r--mesonbuild/compilers/fortran.py36
-rw-r--r--mesonbuild/compilers/mixins/clang.py5
-rw-r--r--mesonbuild/compilers/mixins/clike.py11
-rw-r--r--mesonbuild/compilers/mixins/gnu.py5
-rw-r--r--mesonbuild/coredata.py85
-rw-r--r--mesonbuild/envconfig.py10
-rw-r--r--mesonbuild/environment.py12
-rw-r--r--mesonbuild/interpreter.py28
-rw-r--r--mesonbuild/linkers.py12
-rw-r--r--mesonbuild/mconf.py17
-rw-r--r--mesonbuild/mesonmain.py2
-rw-r--r--mesonbuild/mintro.py11
-rw-r--r--mesonbuild/mlog.py2
-rw-r--r--mesonbuild/modules/sourceset.py2
-rw-r--r--mesonbuild/rewriter.py4
-rw-r--r--mesonbuild/scripts/gtkdochelper.py10
-rwxr-xr-xrun_tests.py2
-rwxr-xr-xrun_unittests.py43
-rw-r--r--test cases/unit/74 dep files/foo.c0
-rw-r--r--test cases/unit/74 dep files/meson.build16
31 files changed, 523 insertions, 273 deletions
diff --git a/README.md b/README.md
index 49a1809..9df015c 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ build system.
#### Dependencies
- [Python](https://python.org) (version 3.5 or newer)
- - [Ninja](https://ninja-build.org) (version 1.5 or newer)
+ - [Ninja](https://ninja-build.org) (version 1.7 or newer)
#### Installing from source
diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md
index 9e64a3e..4c4b7bf 100644
--- a/docs/markdown/Cross-compilation.md
+++ b/docs/markdown/Cross-compilation.md
@@ -195,14 +195,18 @@ surprisingly, `build_machine`, `host_machine` and
`target_machine`. Determining the operating system of your host
machine is simply a matter of calling `host_machine.system()`.
-There are two different values for the CPU. The first one is
-`cpu_family`. It is a general type of the CPU. Common values might
-include `x86`, `arm` or `x86_64`. The second value is `cpu` which is a
-more specific subtype for the CPU. Typical values for a `x86` CPU
-family might include `i386` or `i586` and for `arm` family `armv5` or
-`armv7hl`. Note that CPU type strings are very system dependent. You
-might get a different value if you check its value on the same machine
-but with different operating systems.
+There are two different values for the CPU. The first one is `cpu_family`. It
+is a general type of the CPU. This should have a value from [the CPU Family
+table](Reference-tables.md#cpu-families). *Note* that meson does not add
+`el` to end cpu_family value for little endian systems. Big endian and little
+endian mips are both just `mips`, with the `endian` field set approriately.
+
+The second value is `cpu` which is
+a more specific subtype for the CPU. Typical values for a `x86` CPU family
+might include `i386` or `i586` and for `arm` family `armv5` or `armv7hl`.
+Note that CPU type strings are very system dependent. You might get a
+different value if you check its value on the same machine but with different
+operating systems.
If you do not define your host machine, it is assumed to be the build
machine. Similarly if you do not specify target machine, it is assumed
diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md
index f86a818..a6c6f4b 100644
--- a/docs/markdown/IDE-integration.md
+++ b/docs/markdown/IDE-integration.md
@@ -253,6 +253,21 @@ line arguments, environment variable settings and how to process the output.
}
```
+## Build system files
+
+It is also possible to get Meson build files used in your current project. This
+can be done by running `meson introspect --buildsystem-files /path/to/builddir`.
+
+The output format is as follows:
+
+```json
+[
+ "/Path/to/the/targets/meson.build",
+ "/Path/to/the/targets/meson_options.txt",
+ "/Path/to/the/targets/subdir/meson.build"
+]
+```
+
# Programmatic interface
Meson also provides the `meson introspect` for project introspection via the
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 138708d..31ddfb4 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -166,18 +166,21 @@ class Backend:
return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))
def get_base_options_for_target(self, target):
- return OptionOverrideProxy(target.option_overrides,
+ return OptionOverrideProxy(target.option_overrides_base,
self.environment.coredata.builtins,
self.environment.coredata.base_options)
def get_compiler_options_for_target(self, target):
- return OptionOverrideProxy(
- target.option_overrides,
- self.environment.coredata.compiler_options[target.for_machine])
+ comp_reg = self.environment.coredata.compiler_options[target.for_machine]
+ comp_override = target.option_overrides_compiler
+ return {
+ lang: OptionOverrideProxy(comp_override[lang], comp_reg[lang])
+ for lang in set(comp_reg.keys()) | set(comp_override.keys())
+ }
def get_option_for_target(self, option_name, target):
- if option_name in target.option_overrides:
- override = target.option_overrides[option_name]
+ if option_name in target.option_overrides_base:
+ override = target.option_overrides_base[option_name]
return self.environment.coredata.validate_option_value(option_name, override)
return self.environment.coredata.get_builtin_option(option_name, target.subproject)
@@ -581,7 +584,7 @@ class Backend:
# starting from hard-coded defaults followed by build options and so on.
commands = CompilerArgs(compiler)
- copt_proxy = self.get_compiler_options_for_target(target)
+ copt_proxy = self.get_compiler_options_for_target(target)[compiler.language]
# First, the trivial ones that are impossible to override.
#
# Add -nostdinc/-nostdinc++ if needed; can't be overridden
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 03ccd19..e765466 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -294,7 +294,7 @@ int dummy;
def generate(self):
ninja = environment.detect_ninja_command_and_version(log=True)
if ninja is None:
- raise MesonException('Could not detect Ninja v1.5 or newer')
+ raise MesonException('Could not detect Ninja v1.7 or newer')
(self.ninja_command, self.ninja_version) = ninja
outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename)
tempfilename = outfilename + '~'
@@ -303,7 +303,7 @@ int dummy;
self.build.get_project())
outfile.write('# It is autogenerated by the Meson build system.\n')
outfile.write('# Do not edit by hand.\n\n')
- outfile.write('ninja_required_version = 1.5.1\n\n')
+ outfile.write('ninja_required_version = 1.7.1\n\n')
num_pools = self.environment.coredata.backend_options['backend_max_links'].value
if num_pools > 0:
@@ -2560,7 +2560,14 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# to be after all internal and external libraries so that unresolved
# symbols from those can be found here. This is needed when the
# *_winlibs that we want to link to are static mingw64 libraries.
- commands += linker.get_option_link_args(self.environment.coredata.compiler_options[target.for_machine])
+ if hasattr(linker, 'get_language'):
+ # The static linker doesn't know what language it is building, so we
+ # don't know what option. Fortunately, it doesn't care to see the
+ # language-specific options either.
+ #
+ # We shouldn't check whether we are making a static library, because
+ # in the LTO case we do use a real compiler here.
+ commands += linker.get_option_link_args(self.environment.coredata.compiler_options[target.for_machine][linker.get_language()])
dep_targets = []
dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal))
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 9a7ebf2..ef849e1 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -891,8 +891,10 @@ class Vs2010Backend(backends.Backend):
# generate_single_compile() and generate_basic_compiler_args()
for l, comp in target.compilers.items():
if l in file_args:
- file_args[l] += compilers.get_base_compile_args(self.get_base_options_for_target(target), comp)
- file_args[l] += comp.get_option_compile_args(self.environment.coredata.compiler_options[target.for_machine])
+ file_args[l] += compilers.get_base_compile_args(
+ self.get_base_options_for_target(target), comp)
+ file_args[l] += comp.get_option_compile_args(
+ self.environment.coredata.compiler_options[target.for_machine][comp.language])
# Add compile args added using add_project_arguments()
for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items():
@@ -905,10 +907,11 @@ class Vs2010Backend(backends.Backend):
file_args[l] += args
# Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these
# to override all the defaults, but not the per-target compile args.
- for key, opt in self.environment.coredata.compiler_options[target.for_machine].items():
- l, suffix = key.split('_', 1)
- if suffix == 'args' and l in file_args:
- file_args[l] += opt.value
+ for l in file_args.keys():
+ opts = self.environment.coredata.compiler_options[target.for_machine][l]
+ k = 'args'
+ if k in opts:
+ file_args[l] += opts[k].value
for args in file_args.values():
# This is where Visual Studio will insert target_args, target_defines,
# etc, which are added later from external deps (see below).
@@ -1115,7 +1118,8 @@ class Vs2010Backend(backends.Backend):
# to be after all internal and external libraries so that unresolved
# symbols from those can be found here. This is needed when the
# *_winlibs that we want to link to are static mingw64 libraries.
- extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options[compiler.for_machine])
+ extra_link_args += compiler.get_option_link_args(
+ self.environment.coredata.compiler_options[compiler.for_machine][comp.language])
(additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native())
# Add more libraries to be linked if needed
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index b1bf9d4..c200261 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -13,7 +13,7 @@
# limitations under the License.
import copy, os, re
-from collections import OrderedDict
+from collections import OrderedDict, defaultdict
import itertools, pathlib
import hashlib
import pickle
@@ -28,7 +28,10 @@ from .mesonlib import (
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep, unholder
)
-from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes, is_known_suffix
+from .compilers import (
+ Compiler, all_languages, is_object, clink_langs, sort_clink, lang_suffixes,
+ is_known_suffix
+)
from .linkers import StaticLinker
from .interpreterbase import FeatureNew
@@ -358,7 +361,8 @@ a hard error in the future.'''.format(name))
self.for_machine = for_machine
self.install = False
self.build_always_stale = False
- self.option_overrides = {}
+ self.option_overrides_base = {}
+ self.option_overrides_compiler = defaultdict(dict)
if not hasattr(self, 'typename'):
raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__))
@@ -448,7 +452,15 @@ a hard error in the future.'''.format(name))
# set, use the value of 'install' if it's enabled.
self.build_by_default = True
- self.option_overrides = self.parse_overrides(kwargs)
+ option_overrides = self.parse_overrides(kwargs)
+
+ for k, v in option_overrides.items():
+ if '_' in k:
+ lang, k2 = k.split('_', 1)
+ if lang in all_languages:
+ self.option_overrides_compiler[lang][k2] = v
+ continue
+ self.option_overrides_base[k] = v
def parse_overrides(self, kwargs) -> dict:
result = {}
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index eba7131..1bc9e84 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -107,25 +107,32 @@ class ClangCCompiler(ClangCompiler, CCompiler):
if version_compare(self.version, self._C18_VERSION):
c_stds += ['c18']
g_stds += ['gnu18']
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none',
+ ),
+ })
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'c_winlibs': coredata.UserArrayOption('Standard Win libraries to link against',
- gnu_winlibs), })
+ 'winlibs': coredata.UserArrayOption(
+ 'Standard Win libraries to link against',
+ gnu_winlibs,
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
def get_option_link_args(self, options):
if self.info.is_windows() or self.info.is_cygwin():
- return options['c_winlibs'].value[:]
+ return options['winlibs'].value[:]
return []
@@ -166,15 +173,18 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler):
def get_options(self):
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c90', 'c99', 'c11',
- 'gnu90', 'gnu99', 'gnu11'],
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'],
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
@@ -204,25 +214,32 @@ class GnuCCompiler(GnuCompiler, CCompiler):
if version_compare(self.version, v):
c_stds += ['c17', 'c18']
g_stds += ['gnu17', 'gnu18']
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none',
+ ),
+ })
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'c_winlibs': coredata.UserArrayOption('Standard Win libraries to link against',
- gnu_winlibs), })
+ 'winlibs': coredata.UserArrayOption(
+ 'Standard Win libraries to link against',
+ gnu_winlibs,
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
def get_option_link_args(self, options):
if self.info.is_windows() or self.info.is_cygwin():
- return options['c_winlibs'].value[:]
+ return options['winlibs'].value[:]
return []
def get_pch_use_args(self, pch_dir, header):
@@ -248,11 +265,17 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler):
# It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports.
def get_options(self):
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11',
- 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11',
- 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999'],
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ [
+ 'none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11',
+ 'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11',
+ 'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999',
+ ],
+ 'none',
+ ),
+ })
return opts
# Elbrus C compiler does not have lchmod, but there is only linker warning, not compiler error.
@@ -285,14 +308,18 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler):
g_stds = ['gnu89', 'gnu99']
if version_compare(self.version, '>=16.0.0'):
c_stds += ['c11']
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none'] + c_stds + g_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
@@ -304,12 +331,16 @@ class VisualStudioLikeCCompilerMixin:
def get_options(self):
opts = super().get_options()
- opts.update({'c_winlibs': coredata.UserArrayOption('Windows libs to link against.',
- msvc_winlibs)})
+ opts.update({
+ 'winlibs': coredata.UserArrayOption(
+ 'Windows libs to link against.',
+ msvc_winlibs,
+ ),
+ })
return opts
def get_option_link_args(self, options):
- return options['c_winlibs'].value[:]
+ return options['winlibs'].value[:]
class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompiler):
@@ -343,14 +374,18 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM
def get_options(self):
opts = super().get_options()
c_stds = ['none', 'c89', 'c99', 'c11']
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- c_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ c_stds,
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value == 'c89':
mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True)
elif std.value != 'none':
@@ -367,14 +402,18 @@ class ArmCCompiler(ArmCompiler, CCompiler):
def get_options(self):
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c90', 'c99'],
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none', 'c90', 'c99'],
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value != 'none':
args.append('--' + std.value)
return args
@@ -393,9 +432,13 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_options(self):
opts = CCompiler.get_options(self)
- opts.update({'c_std': coredata.UserComboOption('C language standard to use',
- ['none', 'c89', 'c99'],
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C language standard to use',
+ ['none', 'c89', 'c99'],
+ 'none',
+ ),
+ })
return opts
def get_no_stdinc_args(self):
@@ -403,7 +446,7 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_option_compile_args(self, options):
args = []
- std = options['c_std']
+ std = options['std']
if std.value == 'c89':
args.append('-lang=c')
elif std.value == 'c99':
diff --git a/mesonbuild/compilers/c_function_attributes.py b/mesonbuild/compilers/c_function_attributes.py
index 3b9fdf9..e5de485 100644
--- a/mesonbuild/compilers/c_function_attributes.py
+++ b/mesonbuild/compilers/c_function_attributes.py
@@ -127,7 +127,4 @@ CXX_FUNC_ATTRIBUTES = {
'static int (*resolve_foo(void))(void) { return my_foo; }'
'}'
'int foo(void) __attribute__((ifunc("resolve_foo")));'),
- # Clang >= 10 requires the 'extern' keyword
- 'gnu_inline':
- 'extern inline __attribute__((gnu_inline)) int foo(void) { return 0; }',
}
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 52b9592..3d3a503 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -1272,10 +1272,10 @@ def get_global_options(lang: str,
"""Retreive options that apply to all compilers for a given language."""
description = 'Extra arguments passed to the {}'.format(lang)
opts = {
- lang + '_args': coredata.UserArrayOption(
+ 'args': coredata.UserArrayOption(
description + ' compiler',
[], split_args=True, user_input=True, allow_dups=True),
- lang + '_link_args': coredata.UserArrayOption(
+ 'link_args': coredata.UserArrayOption(
description + ' linker',
[], split_args=True, user_input=True, allow_dups=True),
}
@@ -1288,12 +1288,13 @@ def get_global_options(lang: str,
comp.INVOKES_LINKER)
for k, o in opts.items():
- if k in properties:
+ user_k = lang + '_' + k
+ if user_k in properties:
# Get from configuration files.
- o.set_value(properties[k])
- elif k == lang + '_args':
+ o.set_value(properties[user_k])
+ elif k == 'args':
o.set_value(compile_args)
- elif k == lang + '_link_args':
+ elif k == 'link_args':
o.set_value(link_args)
return opts
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 9894cd3..d30017f 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -167,36 +167,45 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
- 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
- 'none')})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
+ 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
+ 'none',
+ ),
+ })
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'cpp_winlibs': coredata.UserArrayOption('Standard Win libraries to link against',
- gnu_winlibs), })
+ 'winlibs': coredata.UserArrayOption(
+ 'Standard Win libraries to link against',
+ gnu_winlibs,
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['cpp_eh'].value, args)
+ non_msvc_eh_options(options['eh'].value, args)
- if not options['cpp_rtti'].value:
+ if not options['rtti'].value:
args.append('-fno-rtti')
return args
def get_option_link_args(self, options):
if self.info.is_windows() or self.info.is_cygwin():
- return options['cpp_winlibs'].value[:]
+ return options['winlibs'].value[:]
return []
def language_stdlib_only_link_flags(self):
@@ -220,7 +229,7 @@ class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompile
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
return args
@@ -239,22 +248,30 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
- 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17'],
- 'none')})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ [
+ 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
+ 'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
+ ],
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
- non_msvc_eh_options(options['cpp_eh'].value, args)
+ non_msvc_eh_options(options['eh'].value, args)
return args
@@ -275,40 +292,51 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
- 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
- 'none'),
- 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode',
- False)})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
+ 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
+ 'none',
+ ),
+ 'debugstl': coredata.UserBooleanOption(
+ 'STL debug mode',
+ False,
+ )
+ })
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'cpp_winlibs': coredata.UserArrayOption('Standard Win libraries to link against',
- gnu_winlibs), })
+ 'winlibs': coredata.UserArrayOption(
+ 'Standard Win libraries to link against',
+ gnu_winlibs,
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['cpp_eh'].value, args)
+ non_msvc_eh_options(options['eh'].value, args)
- if not options['cpp_rtti'].value:
+ if not options['rtti'].value:
args.append('-fno-rtti')
- if options['cpp_debugstl'].value:
+ if options['debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
def get_option_link_args(self, options):
if self.info.is_windows() or self.info.is_cygwin():
- return options['cpp_winlibs'].value[:]
+ return options['winlibs'].value[:]
return []
def get_pch_use_args(self, pch_dir, header):
@@ -337,15 +365,25 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
# It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98.
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y',
- 'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y'],
- 'none'),
- 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode',
- False)})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ [
+ 'none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y',
+ 'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y',
+ ],
+ 'none',
+ ),
+ 'debugstl': coredata.UserBooleanOption(
+ 'STL debug mode',
+ False,
+ ),
+ })
return opts
# Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error.
@@ -361,13 +399,13 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
# Elbrus C++ compiler does not support RTTI, so don't check for it.
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['cpp_eh'].value, args)
+ non_msvc_eh_options(options['eh'].value, args)
- if options['cpp_debugstl'].value:
+ if options['debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -400,31 +438,36 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
c_stds += ['c++17']
if version_compare(self.version, '>=17.0.0'):
g_stds += ['gnu++14']
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none'] + c_stds + g_stds,
- 'none'),
- 'cpp_debugstl': coredata.UserBooleanOption('STL debug mode',
- False)})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ ['none'] + c_stds + g_stds,
+ 'none',
+ ),
+ 'debugstl': coredata.UserBooleanOption('STL debug mode', False),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value != 'none':
remap_cpp03 = {
'c++03': 'c++98',
'gnu++03': 'gnu++98'
}
args.append('-std=' + remap_cpp03.get(std.value, std.value))
- if options['cpp_eh'].value == 'none':
+ if options['eh'].value == 'none':
args.append('-fno-exceptions')
- if not options['cpp_rtti'].value:
+ if not options['rtti'].value:
args.append('-fno-rtti')
- if options['cpp_debugstl'].value:
+ if options['debugstl'].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -449,24 +492,32 @@ class VisualStudioLikeCPPCompilerMixin:
}
def get_option_link_args(self, options):
- return options['cpp_winlibs'].value[:]
+ return options['winlibs'].value[:]
def _get_options_impl(self, opts, cpp_stds: T.List[str]):
- opts.update({'cpp_eh': coredata.UserComboOption('C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default'),
- 'cpp_rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'cpp_std': coredata.UserComboOption('C++ language standard to use',
- cpp_stds,
- 'none'),
- 'cpp_winlibs': coredata.UserArrayOption('Windows libs to link against.',
- msvc_winlibs)})
+ opts.update({
+ 'eh': coredata.UserComboOption(
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default',
+ ),
+ 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ cpp_stds,
+ 'none',
+ ),
+ 'winlibs': coredata.UserArrayOption(
+ 'Windows libs to link against.',
+ msvc_winlibs,
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- eh = options['cpp_eh']
+ eh = options['eh']
if eh.value == 'default':
args.append('/EHsc')
elif eh.value == 'none':
@@ -474,10 +525,10 @@ class VisualStudioLikeCPPCompilerMixin:
else:
args.append('/EH' + eh.value)
- if not options['cpp_rtti'].value:
+ if not options['rtti'].value:
args.append('/GR-')
- permissive, ver = self.VC_VERSION_MAP[options['cpp_std'].value]
+ permissive, ver = self.VC_VERSION_MAP[options['std'].value]
if ver is not None:
args.append('/std:c++{}'.format(ver))
@@ -504,17 +555,17 @@ class CPP11AsCPP14Mixin:
# which means setting the C++ standard version to C++14, in compilers that support it
# (i.e., after VS2015U3)
# if one is using anything before that point, one cannot set the standard.
- if options['cpp_std'].value in {'vc++11', 'c++11'}:
+ if options['std'].value in {'vc++11', 'c++11'}:
mlog.warning(self.id, 'does not support C++11;',
'attempting best effort; setting the standard to C++14', once=True)
# Don't mutate anything we're going to change, we need to use
# deepcopy since we're messing with members, and we can't simply
# copy the members because the option proxy doesn't support it.
options = copy.deepcopy(options)
- if options['cpp_std'].value == 'vc++11':
- options['cpp_std'].value = 'vc++14'
+ if options['std'].value == 'vc++11':
+ options['std'].value = 'vc++14'
else:
- options['cpp_std'].value = 'c++14'
+ options['std'].value = 'c++14'
return super().get_option_compile_args(options)
@@ -537,10 +588,10 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
return self._get_options_impl(super().get_options(), cpp_stds)
def get_option_compile_args(self, options):
- if options['cpp_std'].value != 'none' and version_compare(self.version, '<19.00.24210'):
+ if options['std'].value != 'none' and version_compare(self.version, '<19.00.24210'):
mlog.warning('This version of MSVC does not support cpp_std arguments')
options = copy.copy(options)
- options['cpp_std'].value = 'none'
+ options['std'].value = 'none'
args = super().get_option_compile_args(options)
@@ -588,14 +639,18 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler):
def get_options(self):
opts = CPPCompiler.get_options(self)
- opts.update({'cpp_std': coredata.UserComboOption('C++ language standard to use',
- ['none', 'c++03', 'c++11'],
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'C++ language standard to use',
+ ['none', 'c++03', 'c++11'],
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options):
args = []
- std = options['cpp_std']
+ std = options['std']
if std.value == 'c++11':
args.append('--cpp11')
elif std.value == 'c++03':
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 16a93f5..01283a1 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -186,14 +186,18 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
fortran_stds += ['f2008']
if version_compare(self.version, '>=8.0.0'):
fortran_stds += ['f2018']
- opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options) -> T.List[str]:
args = []
- std = options['fortran_std']
+ std = options['std']
if std.value != 'none':
args.append('-std=' + std.value)
return args
@@ -292,14 +296,18 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
def get_options(self):
opts = FortranCompiler.get_options(self)
fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
- opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options) -> T.List[str]:
args = []
- std = options['fortran_std']
+ std = options['std']
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('-stand=' + stds[std.value])
@@ -342,14 +350,18 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
def get_options(self):
opts = FortranCompiler.get_options(self)
fortran_stds = ['legacy', 'f95', 'f2003', 'f2008', 'f2018']
- opts.update({'fortran_std': coredata.UserComboOption('Fortran language standard to use',
- ['none'] + fortran_stds,
- 'none')})
+ opts.update({
+ 'std': coredata.UserComboOption(
+ 'Fortran language standard to use',
+ ['none'] + fortran_stds,
+ 'none',
+ ),
+ })
return opts
def get_option_compile_args(self, options) -> T.List[str]:
args = []
- std = options['fortran_std']
+ std = options['std']
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('/stand:' + stds[std.value])
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 92f8c5f..1c0ee45 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -112,3 +112,8 @@ class ClangCompiler(GnuLikeCompiler):
'Cannot find linker {}.'.format(linker))
return ['-fuse-ld={}'.format(linker)]
return super().use_linker_args(linker)
+
+ def get_has_func_attribute_extra_args(self, name):
+ # Clang only warns about unknown or ignored attributes, so force an
+ # error.
+ return ['-Werror=attributes']
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 41848bc..24f4796 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -1115,6 +1115,12 @@ class CLikeCompiler:
m = pattern.match(ret)
return ret
+ def get_has_func_attribute_extra_args(self, name):
+ # Most compilers (such as GCC and Clang) only warn about unknown or
+ # ignored attributes, so force an error. Overriden in GCC and Clang
+ # mixins.
+ return ['-Werror']
+
def has_func_attribute(self, name, env):
# Just assume that if we're not on windows that dllimport and dllexport
# don't work
@@ -1123,6 +1129,5 @@ class CLikeCompiler:
if name in ['dllimport', 'dllexport']:
return False, False
- # Clang and GCC both return warnings if the __attribute__ is undefined,
- # so set -Werror
- return self.compiles(self.attribute_check_func(name), env, extra_args='-Werror')
+ return self.compiles(self.attribute_check_func(name), env,
+ extra_args=self.get_has_func_attribute_extra_args(name))
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 29552f3..3526a91 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -369,3 +369,8 @@ class GnuCompiler(GnuLikeCompiler):
if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stde:
result = False
return result, p.cached
+
+ def get_has_func_attribute_extra_args(self, name):
+ # GCC only warns about unknown or ignored attributes, so force an
+ # error.
+ return ['-Werror=attributes']
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index e71d674..0b79084 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -17,7 +17,7 @@ import pickle, os, uuid
import sys
from itertools import chain
from pathlib import PurePath
-from collections import OrderedDict
+from collections import OrderedDict, defaultdict
from .mesonlib import (
MesonException, MachineChoice, PerMachine, OrderedSet,
default_libdir, default_libexecdir, default_prefix, split_args
@@ -370,7 +370,10 @@ class CoreData:
self.builtins_per_machine = PerMachine({}, {})
self.backend_options = {} # : OptionDictType
self.user_options = {} # : OptionDictType
- self.compiler_options = PerMachine({}, {})
+ self.compiler_options = PerMachine(
+ defaultdict(dict),
+ defaultdict(dict),
+ ) # : PerMachine[T.defaultdict[str, OptionDictType]]
self.base_options = {} # : OptionDictType
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.compilers = PerMachine(OrderedDict(), OrderedDict())
@@ -614,28 +617,42 @@ class CoreData:
mode = 'custom'
self.builtins['buildtype'].set_value(mode)
- @staticmethod
+ @classmethod
def get_prefixed_options_per_machine(
+ cls,
options_per_machine # : PerMachine[T.Dict[str, _V]]]
- ) -> T.Iterable[T.Dict[str, _V]]:
- for for_machine in iter(MachineChoice):
- prefix = for_machine.get_prefix()
- yield {
- prefix + k: v
- for k, v in options_per_machine[for_machine].items()
- }
+ ) -> T.Iterable[T.Tuple[str, _V]]:
+ return cls._flatten_pair_iterator(
+ (for_machine.get_prefix(), options_per_machine[for_machine])
+ for for_machine in iter(MachineChoice)
+ )
+
+ @classmethod
+ def flatten_lang_iterator(
+ cls,
+ outer # : T.Iterable[T.Tuple[str, T.Dict[str, _V]]]
+ ) -> T.Iterable[T.Tuple[str, _V]]:
+ return cls._flatten_pair_iterator((lang + '_', opts) for lang, opts in outer)
+
+ @staticmethod
+ def _flatten_pair_iterator(
+ outer # : T.Iterable[T.Tuple[str, T.Dict[str, _V]]]
+ ) -> T.Iterable[T.Tuple[str, _V]]:
+ for k0, v0 in outer:
+ for k1, v1 in v0.items():
+ yield (k0 + k1, v1)
def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
yield self.backend_options
yield self.user_options
- yield from self.get_prefixed_options_per_machine(self.compiler_options)
+ yield dict(self.flatten_lang_iterator(self.get_prefixed_options_per_machine(self.compiler_options)))
yield self.base_options
- def _get_all_builtin_options(self) -> T.Dict[str, UserOption]:
- yield from self.get_prefixed_options_per_machine(self.builtins_per_machine)
+ def _get_all_builtin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
+ yield dict(self.get_prefixed_options_per_machine(self.builtins_per_machine))
yield self.builtins
- def get_all_options(self) -> T.Dict[str, UserOption]:
+ def get_all_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
yield from self._get_all_nonbuiltin_options()
yield from self._get_all_builtin_options()
@@ -651,10 +668,10 @@ class CoreData:
raise MesonException('Tried to validate unknown option %s.' % option_name)
def get_external_args(self, for_machine: MachineChoice, lang):
- return self.compiler_options[for_machine][lang + '_args'].value
+ return self.compiler_options[for_machine][lang]['args'].value
def get_external_link_args(self, for_machine: MachineChoice, lang):
- return self.compiler_options[for_machine][lang + '_link_args'].value
+ return self.compiler_options[for_machine][lang]['link_args'].value
def merge_user_options(self, options):
for (name, value) in options.items():
@@ -680,9 +697,11 @@ class CoreData:
assert(not self.is_cross_build())
for k, o in self.builtins_per_machine.host.items():
self.builtins_per_machine.build[k].set_value(o.value)
- for k, o in self.compiler_options.host.items():
- if k in self.compiler_options.build:
- self.compiler_options.build[k].set_value(o.value)
+ for lang, host_opts in self.compiler_options.host.items():
+ build_opts = self.compiler_options.build[lang]
+ for k, o in host_opts.items():
+ if k in build_opts:
+ build_opts[k].set_value(o.value)
def set_options(self, options, *, subproject='', warn_unknown=True):
if not self.is_cross_build():
@@ -783,13 +802,17 @@ class CoreData:
'path instead.'
)
+ def remove_prefix(text, prefix):
+ if text.startswith(prefix):
+ return text[len(prefix):]
+ return text
+
for k, v in env.cmd_line_options.items():
if subproject:
if not k.startswith(subproject + ':'):
continue
elif k not in builtin_options.keys() \
- and 'build.' + k not in builtin_options_per_machine.keys() \
- and k not in builtin_options_per_machine.keys():
+ and remove_prefix(k, 'build.') not in builtin_options_per_machine.keys():
if ':' in k:
continue
if optinterpreter.is_invalid_name(k, log=False):
@@ -803,20 +826,18 @@ class CoreData:
"""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,
comp,
for_machine,
env.is_cross_build(),
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)
+ user_k = opt_prefix + lang + '_' + k
+ if user_k in env.cmd_line_options:
+ o.set_value(env.cmd_line_options[user_k])
+ self.compiler_options[for_machine][lang].setdefault(k, o)
def process_new_compiler(self, lang: str, comp: T.Type['Compiler'], env: 'Environment') -> None:
from . import compilers
@@ -824,15 +845,13 @@ class CoreData:
self.compilers[comp.for_machine][lang] = comp
enabled_opts = []
- optprefix = lang + '_'
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
opt_prefix = comp.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[comp.for_machine].setdefault(k, o)
+ user_k = opt_prefix + lang + '_' + k
+ if user_k in env.cmd_line_options:
+ o.set_value(env.cmd_line_options[user_k])
+ self.compiler_options[comp.for_machine][lang].setdefault(k, o)
enabled_opts = []
for optname in comp.base_options:
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index 339f980..25b3c7f 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -93,15 +93,15 @@ class MesonConfigFile:
# Windows paths...
value = value.replace('\\', '\\\\')
if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
- raise EnvironmentException('Malformed variable name %s in cross file..' % entry)
+ raise EnvironmentException('Malformed variable name {} in cross file..'.format(entry))
try:
res = eval(value, {'__builtins__': None}, {'true': True, 'false': False})
except Exception:
- raise EnvironmentException('Malformed value in cross file variable %s.' % entry)
+ raise EnvironmentException('Malformed value in cross file variable {}.'.format(entry))
for i in (res if isinstance(res, list) else [res]):
if not isinstance(i, (str, int, bool)):
- raise EnvironmentException('Malformed value in cross file variable %s.' % entry)
+ raise EnvironmentException('Malformed value in cross file variable {}.'.format(entry))
section[entry] = res
@@ -224,11 +224,11 @@ class MachineInfo:
cpu_family = literal['cpu_family']
if cpu_family not in known_cpu_families:
- mlog.warning('Unknown CPU family %s, please report this at https://github.com/mesonbuild/meson/issues/new' % cpu_family)
+ mlog.warning('Unknown CPU family {}, please report this at https://github.com/mesonbuild/meson/issues/new'.format(cpu_family))
endian = literal['endian']
if endian not in ('little', 'big'):
- mlog.warning('Unknown endian %s' % endian)
+ mlog.warning('Unknown endian {}'.format(endian))
return cls(literal['system'], cpu_family, literal['cpu'], endian)
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 11bc76c..64efda6 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -771,7 +771,7 @@ class Environment:
elif isinstance(comp_class.LINKER_PREFIX, list):
check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
- check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
+ check_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
override = [] # type: T.List[str]
value = self.lookup_binary_entry(for_machine, comp_class.language + '_ld')
@@ -833,7 +833,7 @@ class Environment:
"""
self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
extra_args = T.cast(T.List[str], extra_args or [])
- extra_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value
+ extra_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
if isinstance(comp_class.LINKER_PREFIX, str):
check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
@@ -1360,7 +1360,7 @@ class Environment:
try:
p, out, err = Popen_safe(exelist + ['-version'])
except OSError:
- raise EnvironmentException('Could not execute Java compiler "%s"' % ' '.join(exelist))
+ raise EnvironmentException('Could not execute Java compiler "{}"'.format(' '.join(exelist)))
if 'javac' in out or 'javac' in err:
version = search_version(err if 'javac' in err else out)
if not version or version == 'unknown version':
@@ -1408,7 +1408,7 @@ class Environment:
try:
p, out = Popen_safe(exelist + ['--version'])[0:2]
except OSError:
- raise EnvironmentException('Could not execute Vala compiler "%s"' % ' '.join(exelist))
+ raise EnvironmentException('Could not execute Vala compiler "{}"'.format(' '.join(exelist)))
version = search_version(out)
if 'Vala' in out:
comp_class = ValaCompiler
@@ -1610,7 +1610,7 @@ class Environment:
try:
p, _, err = Popen_safe(exelist + ['-v'])
except OSError:
- raise EnvironmentException('Could not execute Swift compiler "%s"' % ' '.join(exelist))
+ raise EnvironmentException('Could not execute Swift compiler "{}"'.format(' '.join(exelist)))
version = search_version(err)
if 'Swift' in err:
# As for 5.0.1 swiftc *requires* a file to check the linker:
@@ -1730,7 +1730,7 @@ class Environment:
if p.returncode == 1 and err.startswith('ar: bad option: --'): # Solaris
return ArLinker(linker)
self._handle_exceptions(popen_exceptions, linkers, 'linker')
- raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linkers))
+ raise EnvironmentException('Unknown static linker "{}"'.format(' '.join(linkers)))
def get_source_dir(self):
return self.source_dir
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c1636d7..48b6bd6 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -42,7 +42,6 @@ import re
import shlex
import subprocess
import collections
-from itertools import chain
import functools
import typing as T
@@ -1112,7 +1111,7 @@ class CompilerHolder(InterpreterObject):
args += self.compiler.get_include_args(idir, False)
if not nobuiltins:
for_machine = Interpreter.machine_from_native_kwarg(kwargs)
- opts = self.environment.coredata.compiler_options[for_machine]
+ opts = self.environment.coredata.compiler_options[for_machine][self.compiler.language]
args += self.compiler.get_option_compile_args(opts)
if mode == 'link':
args += self.compiler.get_option_link_args(opts)
@@ -2422,14 +2421,14 @@ class Interpreter(InterpreterBase):
return
f = os.path.normpath(f.relative_name())
elif os.path.isfile(f) and not f.startswith('/dev'):
- srcdir = self.environment.get_source_dir()
- builddir = self.environment.get_build_dir()
- f = os.path.normpath(f)
- rel_path = mesonlib.relpath(f, start=srcdir)
- if not rel_path.startswith('..'):
- f = rel_path
- elif not mesonlib.relpath(f, start=builddir).startswith('..'):
+ srcdir = Path(self.environment.get_source_dir())
+ builddir = Path(self.environment.get_build_dir())
+ f = Path(f).resolve()
+ if builddir in f.parents:
return
+ if srcdir in f.parents:
+ f = f.relative_to(srcdir)
+ f = str(f)
else:
return
if f not in self.build_def_files:
@@ -2800,11 +2799,12 @@ external dependencies (including libraries) must go to "dependencies".''')
if self.is_subproject():
optname = self.subproject + ':' + optname
- for opts in chain(
- [self.coredata.base_options, compilers.base_options, self.coredata.builtins],
- self.coredata.get_prefixed_options_per_machine(self.coredata.builtins_per_machine),
- self.coredata.get_prefixed_options_per_machine(self.coredata.compiler_options),
- ):
+ for opts in [
+ self.coredata.base_options, compilers.base_options, self.coredata.builtins,
+ dict(self.coredata.get_prefixed_options_per_machine(self.coredata.builtins_per_machine)),
+ dict(self.coredata.flatten_lang_iterator(
+ self.coredata.get_prefixed_options_per_machine(self.coredata.compiler_options))),
+ ]:
v = opts.get(optname)
if v is None or v.yielding:
v = opts.get(raw_optname)
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index fa898d0..44c720f 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -201,7 +201,7 @@ class CcrxLinker(StaticLinker):
return False
def get_output_args(self, target: str) -> T.List[str]:
- return ['-output=%s' % target]
+ return ['-output={}'.format(target)]
def get_linker_always_args(self) -> T.List[str]:
return ['-nologo', '-form=library']
@@ -217,7 +217,7 @@ class Xc16Linker(StaticLinker):
return False
def get_output_args(self, target: str) -> T.List[str]:
- return ['%s' % target]
+ return ['{}'.format(target)]
def get_linker_always_args(self) -> T.List[str]:
return ['rcs']
@@ -233,7 +233,7 @@ class C2000Linker(StaticLinker):
return False
def get_output_args(self, target: str) -> T.List[str]:
- return ['%s' % target]
+ return ['{}'.format(target)]
def get_linker_always_args(self) -> T.List[str]:
return ['-r']
@@ -781,7 +781,7 @@ class CcrxDynamicLinker(DynamicLinker):
return []
def get_output_args(self, outputname: str) -> T.List[str]:
- return ['-output=%s' % outputname]
+ return ['-output={}'.format(outputname)]
def get_search_args(self, dirname: str) -> 'T.NoReturn':
raise EnvironmentError('rlink.exe does not have a search dir argument')
@@ -819,7 +819,7 @@ class Xc16DynamicLinker(DynamicLinker):
return []
def get_output_args(self, outputname: str) -> T.List[str]:
- return ['-o%s' % outputname]
+ return ['-o{}'.format(outputname)]
def get_search_args(self, dirname: str) -> 'T.NoReturn':
raise EnvironmentError('xc16-gcc.exe does not have a search dir argument')
@@ -862,7 +862,7 @@ class C2000DynamicLinker(DynamicLinker):
return []
def get_output_args(self, outputname: str) -> T.List[str]:
- return ['-z', '--output_file=%s' % outputname]
+ return ['-z', '--output_file={}'.format(outputname)]
def get_search_args(self, dirname: str) -> 'T.NoReturn':
raise EnvironmentError('cl2000.exe does not have a search dir argument')
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index cadc1f5..05e9518 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -97,9 +97,9 @@ class Conf:
else:
print('{0:{width[0]}} {1:{width[1]}} {3}'.format(*line, width=col_widths))
- def split_options_per_subproject(self, options):
+ def split_options_per_subproject(self, options_iter):
result = {}
- for k, o in options.items():
+ for k, o in options_iter:
subproject = ''
if ':' in k:
subproject, optname = k.split(':')
@@ -211,10 +211,15 @@ class Conf:
return 'build.' + k
return k[:idx + 1] + 'build.' + k[idx + 1:]
- core_options = self.split_options_per_subproject(core_options)
- host_compiler_options = self.split_options_per_subproject(self.coredata.compiler_options.host)
- build_compiler_options = self.split_options_per_subproject({insert_build_prefix(k): o for k, o in self.coredata.compiler_options.build.items()})
- project_options = self.split_options_per_subproject(self.coredata.user_options)
+ core_options = self.split_options_per_subproject(core_options.items())
+ host_compiler_options = self.split_options_per_subproject(
+ self.coredata.flatten_lang_iterator(
+ self.coredata.compiler_options.host.items()))
+ build_compiler_options = self.split_options_per_subproject(
+ self.coredata.flatten_lang_iterator(
+ (insert_build_prefix(k), o)
+ for k, o in self.coredata.compiler_options.build.items()))
+ project_options = self.split_options_per_subproject(self.coredata.user_options.items())
show_build_options = self.default_values_only or self.build.environment.is_cross_build()
self.add_section('Main project options')
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index b6b11df..fc9d6a6 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -182,7 +182,7 @@ def ensure_stdout_accepts_unicode():
def run(original_args, mainfile):
if sys.version_info < (3, 5):
print('Meson works correctly only with python 3.5+.')
- print('You have python %s.' % sys.version)
+ print('You have python {}.'.format(sys.version))
print('Please update your environment')
return 1
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 9278584..d5516d4 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -253,9 +253,16 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
)
add_keys(coredata.backend_options, 'backend')
add_keys(coredata.base_options, 'base')
- add_keys(coredata.compiler_options.host, 'compiler', machine='host')
add_keys(
- {'build.' + k: o for k, o in coredata.compiler_options.build.items()},
+ dict(coredata.flatten_lang_iterator(coredata.compiler_options.host.items())),
+ 'compiler',
+ machine='host',
+ )
+ add_keys(
+ {
+ 'build.' + k: o for k, o in
+ coredata.flatten_lang_iterator(coredata.compiler_options.build.items())
+ },
'compiler',
machine='build',
)
diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py
index a5fb320..8cbd248 100644
--- a/mesonbuild/mlog.py
+++ b/mesonbuild/mlog.py
@@ -302,7 +302,7 @@ def exception(e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> None:
# Mypy doesn't follow hasattr, and it's pretty easy to visually inspect
# that this is correct, so we'll just ignore it.
path = get_relative_path(Path(e.file), Path(os.getcwd())) # type: ignore
- args.append('%s:%d:%d:' % (path, e.lineno, e.colno)) # type: ignore
+ args.append('{}:{}:{}:'.format(path, e.lineno, e.colno)) # type: ignore
if prefix:
args.append(prefix)
args.append(str(e))
diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py
index a14bd70..e23e12e 100644
--- a/mesonbuild/modules/sourceset.py
+++ b/mesonbuild/modules/sourceset.py
@@ -150,7 +150,7 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder):
if isinstance(config_data, dict):
def _get_from_config_data(key):
if strict and key not in config_data:
- raise InterpreterException('Entry %s not in configuration dictionary.' % key)
+ raise InterpreterException('Entry {} not in configuration dictionary.'.format(key))
return config_data.get(key, False)
else:
config_cache = dict()
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py
index 785451f..7730ab6 100644
--- a/mesonbuild/rewriter.py
+++ b/mesonbuild/rewriter.py
@@ -469,8 +469,8 @@ class Rewriter:
**{'build.' + k: o for k, o in cdata.builtins_per_machine.build.items()},
**cdata.backend_options,
**cdata.base_options,
- **cdata.compiler_options.host,
- **{'build.' + k: o for k, o in cdata.compiler_options.build.items()},
+ **(dict(cdata.flatten_lang_iterator(cdata.compiler_options.host.items()))),
+ **{'build.' + k: o for k, o in cdata.flatten_lang_iterator(cdata.compiler_options.build.items())},
**cdata.user_options,
}
diff --git a/mesonbuild/scripts/gtkdochelper.py b/mesonbuild/scripts/gtkdochelper.py
index ddcc8c0..6b174a6 100644
--- a/mesonbuild/scripts/gtkdochelper.py
+++ b/mesonbuild/scripts/gtkdochelper.py
@@ -59,6 +59,7 @@ def gtkdoc_run_check(cmd, cwd, library_paths=None):
if 'PATH' in env:
library_paths.extend(env['PATH'].split(os.pathsep))
env['PATH'] = os.pathsep.join(library_paths)
+ cmd.insert(0, sys.executable)
else:
if 'LD_LIBRARY_PATH' in env:
library_paths.extend(env['LD_LIBRARY_PATH'].split(os.pathsep))
@@ -73,7 +74,14 @@ def gtkdoc_run_check(cmd, cwd, library_paths=None):
err_msg.append(out)
raise MesonException('\n'.join(err_msg))
elif out:
- print(out)
+ # Unfortunately Windows cmd.exe consoles may be using a codepage
+ # that might choke print() with a UnicodeEncodeError, so let's
+ # ignore such errors for now, as a compromise as we are outputting
+ # console output here...
+ try:
+ print(out)
+ except UnicodeEncodeError:
+ pass
def build_gtkdoc(source_root, build_root, doc_subdir, src_subdirs,
main_file, module, module_version,
diff --git a/run_tests.py b/run_tests.py
index 3237e85..005d9a0 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -126,7 +126,7 @@ def get_fake_env(sdir='', bdir=None, prefix='', opts=None):
if opts is None:
opts = get_fake_options(prefix)
env = Environment(sdir, bdir, opts)
- env.coredata.compiler_options.host['c_args'] = FakeCompilerOptions()
+ env.coredata.compiler_options.host['c']['args'] = FakeCompilerOptions()
env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library
return env
diff --git a/run_unittests.py b/run_unittests.py
index cc294dd..831e53f 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -836,7 +836,7 @@ class InternalTests(unittest.TestCase):
env = get_fake_env()
compiler = env.detect_c_compiler(MachineChoice.HOST)
env.coredata.compilers.host = {'c': compiler}
- env.coredata.compiler_options.host['c_link_args'] = FakeCompilerOptions()
+ env.coredata.compiler_options.host['c']['link_args'] = FakeCompilerOptions()
p1 = Path(tmpdir) / '1'
p2 = Path(tmpdir) / '2'
p1.mkdir()
@@ -3745,11 +3745,11 @@ recommended as it is not supported on some platforms''')
# c_args value should be parsed with split_args
self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"'])
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dfoo', '-Dbar', '-Dthird=one two'])
+ self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dfoo', '-Dbar', '-Dthird=one two'])
self.setconf('-Dc_args="foo bar" one two')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.compiler_options.host['c_args'].value, ['foo bar', 'one', 'two'])
+ self.assertEqual(obj.compiler_options.host['c']['args'].value, ['foo bar', 'one', 'two'])
self.wipe()
self.init(testdir, extra_args=['-Dset_percent_opt=myoption%'])
@@ -3767,7 +3767,7 @@ recommended as it is not supported on some platforms''')
self.assertEqual(obj.builtins['bindir'].value, 'bar')
self.assertEqual(obj.builtins['buildtype'].value, 'release')
self.assertEqual(obj.base_options['b_sanitize'].value, 'thread')
- self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dbar'])
+ self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dbar'])
self.setconf(['--bindir=bar', '--bindir=foo',
'-Dbuildtype=release', '-Dbuildtype=plain',
'-Db_sanitize=thread', '-Db_sanitize=address',
@@ -3776,7 +3776,7 @@ recommended as it is not supported on some platforms''')
self.assertEqual(obj.builtins['bindir'].value, 'foo')
self.assertEqual(obj.builtins['buildtype'].value, 'plain')
self.assertEqual(obj.base_options['b_sanitize'].value, 'address')
- self.assertEqual(obj.compiler_options.host['c_args'].value, ['-Dfoo'])
+ self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dfoo'])
self.wipe()
except KeyError:
# Ignore KeyError, it happens on CI for compilers that does not
@@ -4588,6 +4588,34 @@ recommended as it is not supported on some platforms''')
self._run([*self.meson_command, 'compile', '-C', self.builddir, '--clean'])
self.assertPathDoesNotExist(os.path.join(self.builddir, prog))
+ def test_spurious_reconfigure_built_dep_file(self):
+ testdir = os.path.join(self.unit_test_dir, '74 dep files')
+
+ # Regression test: Spurious reconfigure was happening when build
+ # directory is inside source directory.
+ # See https://gitlab.freedesktop.org/gstreamer/gst-build/-/issues/85.
+ srcdir = os.path.join(self.builddir, 'srctree')
+ shutil.copytree(testdir, srcdir)
+ builddir = os.path.join(srcdir, '_build')
+ self.change_builddir(builddir)
+
+ self.init(srcdir)
+ self.build()
+
+ # During first configure the file did not exist so no dependency should
+ # have been set. A rebuild should not trigger a reconfigure.
+ self.clean()
+ out = self.build()
+ self.assertNotIn('Project configured', out)
+
+ self.init(srcdir, extra_args=['--reconfigure'])
+
+ # During the reconfigure the file did exist, but is inside build
+ # directory, so no dependency should have been set. A rebuild should not
+ # trigger a reconfigure.
+ self.clean()
+ out = self.build()
+ self.assertNotIn('Project configured', out)
class FailureTests(BasePlatformTests):
'''
@@ -5587,8 +5615,6 @@ class LinuxlikeTests(BasePlatformTests):
self.assertEqual(Oargs, [Oflag, '-O0'])
def _test_stds_impl(self, testdir, compiler, p: str):
- lang_std = p + '_std'
-
has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or
compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or
compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0'))
@@ -5601,7 +5627,8 @@ class LinuxlikeTests(BasePlatformTests):
# Check that all the listed -std=xxx options for this compiler work just fine when used
# https://en.wikipedia.org/wiki/Xcode#Latest_versions
# https://www.gnu.org/software/gcc/projects/cxx-status.html
- for v in compiler.get_options()[lang_std].choices:
+ for v in compiler.get_options()['std'].choices:
+ lang_std = p + '_std'
# we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly
# thus, C++ first
if '++17' in v and not has_cpp17:
diff --git a/test cases/unit/74 dep files/foo.c b/test cases/unit/74 dep files/foo.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/unit/74 dep files/foo.c
diff --git a/test cases/unit/74 dep files/meson.build b/test cases/unit/74 dep files/meson.build
new file mode 100644
index 0000000..4829f56
--- /dev/null
+++ b/test cases/unit/74 dep files/meson.build
@@ -0,0 +1,16 @@
+project('test', 'c')
+
+python = import('python').find_installation()
+
+lib = library('foo', 'foo.c')
+
+# The library does not yet exist but we can already use its path during
+# configuration. This should not trigger a reconfigure when the library is
+# rebuilt.
+configure_file(
+ output: 'out.txt',
+ capture: true,
+ command: [python, '-c', 'import sys; print(sys.argv[1])', lib.full_path()],
+)
+
+message('Project configured')