aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Partin <tristan@partin.io>2024-04-24 19:51:35 -0500
committerDylan Baker <dylan@pnwbakers.com>2024-05-01 11:20:27 -0700
commita0ff14551266c87919f5b4b1469b7be0ef0a052e (patch)
tree0313a2d220f02957d48bd83f3094de43b1413485
parentf1f24816a912bacbb32931bfbd034be36138e3e4 (diff)
downloadmeson-a0ff14551266c87919f5b4b1469b7be0ef0a052e.zip
meson-a0ff14551266c87919f5b4b1469b7be0ef0a052e.tar.gz
meson-a0ff14551266c87919f5b4b1469b7be0ef0a052e.tar.bz2
Add required kwarg to compiler.{compiles,links,run}
This is a similar commit to the one that added required to all the compiler.has* functions.
-rw-r--r--docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md21
-rw-r--r--docs/yaml/objects/compiler.yaml10
-rw-r--r--mesonbuild/interpreter/compiler.py47
-rw-r--r--test cases/common/275 required keyword in compiles functions/invalid.c7
-rw-r--r--test cases/common/275 required keyword in compiles functions/meson.build41
-rw-r--r--test cases/common/275 required keyword in compiles functions/meson_options.txt1
-rw-r--r--test cases/common/275 required keyword in compiles functions/valid.c5
7 files changed, 124 insertions, 8 deletions
diff --git a/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md b/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md
new file mode 100644
index 0000000..693313c
--- /dev/null
+++ b/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md
@@ -0,0 +1,21 @@
+## Required kwarg on more `compiler` methods
+
+The following `compiler` methods now support the `required` keyword argument:
+
+- `compiler.compiles()`
+- `compiler.links()`
+- `compiler.runs()`
+
+```meson
+cc.compiles(valid, name: 'valid', required : true)
+cc.links(valid, name: 'valid', required : true)
+cc.run(valid, name: 'valid', required : true)
+
+assert(not cc.compiles(valid, name: 'valid', required : opt))
+assert(not cc.links(valid, name: 'valid', required : opt))
+res = cc.run(valid, name: 'valid', required : opt)
+assert(res.compiled())
+assert(res.returncode() == 0)
+assert(res.stdout() == '')
+assert(res.stderr() == '')
+```
diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml
index c86ef7f..cd988a6 100644
--- a/docs/yaml/objects/compiler.yaml
+++ b/docs/yaml/objects/compiler.yaml
@@ -121,6 +121,16 @@ methods:
- name: _compiles
returns: void
description: You have found a bug if you can see this!
+ kwargs:
+ required:
+ type: bool | feature
+ default: false
+ since: 1.5.0
+ description:
+ When set to `true`, Meson will halt if the check fails.
+
+ When set to a [`feature`](Build-options.md#features) option, the feature
+ will control if it is searched and whether to fail if not found.
kwargs_inherit:
- compiler._args
- compiler._include_directories
diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py
index fb43035..50a850a 100644
--- a/mesonbuild/interpreter/compiler.py
+++ b/mesonbuild/interpreter/compiler.py
@@ -15,7 +15,7 @@ from .. import coredata
from .. import dependencies
from .. import mesonlib
from .. import mlog
-from ..compilers import SUFFIX_TO_LANG
+from ..compilers import SUFFIX_TO_LANG, RunResult
from ..compilers.compilers import CompileCheckMode
from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
FeatureNew, FeatureNewKwargs, disablerIfNotFound,
@@ -27,7 +27,7 @@ from .type_checking import REQUIRED_KW, in_set_validator, NoneType
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
- from ..compilers import Compiler, RunResult
+ from ..compilers import Compiler
from ..interpreterbase import TYPE_var, TYPE_kwargs
from .kwargs import ExtractRequired, ExtractSearchDirs
from .interpreter import SourceOutputs
@@ -50,7 +50,7 @@ if T.TYPE_CHECKING:
include_directories: T.List[build.IncludeDirs]
args: T.List[str]
- class CompileKW(BaseCompileKW):
+ class CompileKW(BaseCompileKW, ExtractRequired):
name: str
dependencies: T.List[dependencies.Dependency]
@@ -178,7 +178,8 @@ _COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW,
# Common methods of compiles, links, runs, and similar
_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW,
- _WERROR_KW]
+ _WERROR_KW,
+ REQUIRED_KW.evolve(since='1.5.0', default=False)]
_HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS]
_HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.3.0', default=False)
@@ -306,15 +307,25 @@ class CompilerHolder(ObjectHolder['Compiler']):
FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language',
'1.5.0', self.subproject, location=self.current_node)
code = args[0]
+ testname = kwargs['name']
+
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ if testname:
+ mlog.log('Checking if', mlog.bold(testname, True), 'runs:', 'skipped: feature', mlog.bold(feature), 'disabled')
+ return RunResult(compiled=True, returncode=0, stdout='', stderr='', cached=False)
+
if isinstance(code, mesonlib.File):
self.interpreter.add_build_def_file(code)
code = mesonlib.File.from_absolute_file(
code.rel_to_builddir(self.environment.source_dir))
- testname = kwargs['name']
extra_args = functools.partial(self._determine_args, kwargs)
deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False, endl=None)
result = self.compiler.run(code, self.environment, extra_args=extra_args,
dependencies=deps)
+ if required and result.returncode != 0:
+ raise InterpreterException(f'Could not run {testname if testname else "code"}')
+
if testname:
if not result.compiled:
h = mlog.red('DID NOT COMPILE')
@@ -510,6 +521,14 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_kwargs('compiler.compiles', *_COMPILES_KWS)
def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0]
+ testname = kwargs['name']
+
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ if testname:
+ mlog.log('Checking if', mlog.bold(testname, True), 'compiles:', 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
+
if isinstance(code, mesonlib.File):
if code.is_built:
FeatureNew.single_use('compiler.compiles with file created at setup time', '1.2.0', self.subproject,
@@ -517,12 +536,14 @@ class CompilerHolder(ObjectHolder['Compiler']):
self.interpreter.add_build_def_file(code)
code = mesonlib.File.from_absolute_file(
code.absolute_path(self.environment.source_dir, self.environment.build_dir))
- testname = kwargs['name']
extra_args = functools.partial(self._determine_args, kwargs)
deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None)
result, cached = self.compiler.compiles(code, self.environment,
extra_args=extra_args,
dependencies=deps)
+ if required and not result:
+ raise InterpreterException(f'Could not compile {testname}')
+
if testname:
if result:
h = mlog.green('YES')
@@ -536,6 +557,14 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_kwargs('compiler.links', *_COMPILES_KWS)
def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0]
+ testname = kwargs['name']
+
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ if testname:
+ mlog.log('Checking if', mlog.bold(testname, True), 'links:', 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
+
compiler = None
if isinstance(code, mesonlib.File):
if code.is_built:
@@ -556,19 +585,21 @@ class CompilerHolder(ObjectHolder['Compiler']):
else:
compiler = clist[SUFFIX_TO_LANG[suffix]]
- testname = kwargs['name']
extra_args = functools.partial(self._determine_args, kwargs)
deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False)
result, cached = self.compiler.links(code, self.environment,
compiler=compiler,
extra_args=extra_args,
dependencies=deps)
- cached_msg = mlog.blue('(cached)') if cached else ''
+ if required and not result:
+ raise InterpreterException(f'Could not link {testname if testname else "code"}')
+
if testname:
if result:
h = mlog.green('YES')
else:
h = mlog.red('NO')
+ cached_msg = mlog.blue('(cached)') if cached else ''
mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg)
return result
diff --git a/test cases/common/275 required keyword in compiles functions/invalid.c b/test cases/common/275 required keyword in compiles functions/invalid.c
new file mode 100644
index 0000000..d255a36
--- /dev/null
+++ b/test cases/common/275 required keyword in compiles functions/invalid.c
@@ -0,0 +1,7 @@
+// The error in this file is an homage to the xz incident :)
+//
+int
+main(void)
+{
+. return 0;
+}
diff --git a/test cases/common/275 required keyword in compiles functions/meson.build b/test cases/common/275 required keyword in compiles functions/meson.build
new file mode 100644
index 0000000..d0f5b7f
--- /dev/null
+++ b/test cases/common/275 required keyword in compiles functions/meson.build
@@ -0,0 +1,41 @@
+project('required keyword in compiles functions', 'c')
+
+cc = meson.get_compiler('c')
+opt = get_option('opt')
+
+valid = files('valid.c')
+invalid = files('invalid.c')
+
+cc.compiles(valid, name: 'valid', required : true)
+cc.links(valid, name: 'valid', required : true)
+if meson.can_run_host_binaries()
+ cc.run(valid, name: 'valid', required : true)
+endif
+
+assert(not cc.compiles(valid, name: 'valid', required : opt))
+assert(not cc.links(valid, name: 'valid', required : opt))
+if meson.can_run_host_binaries()
+ res = cc.run(valid, name: 'valid', required : opt)
+ assert(res.compiled())
+ assert(res.returncode() == 0)
+ assert(res.stdout() == '')
+ assert(res.stderr() == '')
+endif
+
+testcase expect_error('''compiler.compiles keyword argument 'required' was of type str but should have been one of: bool, UserFeatureOption''')
+ cc.compiles(valid, name: 'valid', required : 'not a bool')
+endtestcase
+
+testcase expect_error('''Could not compile invalid''')
+ cc.compiles(invalid, name: 'invalid', required : true)
+endtestcase
+
+testcase expect_error('''Could not link invalid''')
+ cc.links(invalid, name: 'invalid', required : true)
+endtestcase
+
+if meson.can_run_host_binaries()
+ testcase expect_error('''Could not run invalid''')
+ cc.run(invalid, name: 'invalid', required : true)
+ endtestcase
+endif
diff --git a/test cases/common/275 required keyword in compiles functions/meson_options.txt b/test cases/common/275 required keyword in compiles functions/meson_options.txt
new file mode 100644
index 0000000..53175af
--- /dev/null
+++ b/test cases/common/275 required keyword in compiles functions/meson_options.txt
@@ -0,0 +1 @@
+option('opt', type: 'feature', value: 'disabled')
diff --git a/test cases/common/275 required keyword in compiles functions/valid.c b/test cases/common/275 required keyword in compiles functions/valid.c
new file mode 100644
index 0000000..8479e67
--- /dev/null
+++ b/test cases/common/275 required keyword in compiles functions/valid.c
@@ -0,0 +1,5 @@
+int
+main(void)
+{
+ return 0;
+}