diff options
author | Tristan Partin <tristan@partin.io> | 2024-04-24 19:51:35 -0500 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2024-05-01 11:20:27 -0700 |
commit | a0ff14551266c87919f5b4b1469b7be0ef0a052e (patch) | |
tree | 0313a2d220f02957d48bd83f3094de43b1413485 | |
parent | f1f24816a912bacbb32931bfbd034be36138e3e4 (diff) | |
download | meson-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.
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; +} |