diff options
| author | Jussi Pakkanen <jpakkane@gmail.com> | 2023-06-27 23:57:13 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-27 23:57:13 +0300 |
| commit | a4fb8dcc4111575c670c384e52bf1abb119879b9 (patch) | |
| tree | bdf995d017f7452d7b96f17829d022a208243aba | |
| parent | 8946bc05f7f9cdd16dce3613c481a66f7835fc7f (diff) | |
| parent | 6bfb47a455af60dc975e21dd82943d5baa2bea83 (diff) | |
| download | meson-a4fb8dcc4111575c670c384e52bf1abb119879b9.tar.gz | |
Merge pull request #11902 from dcbaker/submit/rust-module-enhancements
Rust module enhancements for mesa
| -rw-r--r-- | docs/markdown/Machine-files.md | 2 | ||||
| -rw-r--r-- | docs/markdown/Rust-module.md | 16 | ||||
| -rw-r--r-- | docs/markdown/snippets/rust_bindegen_extra_args.md | 3 | ||||
| -rw-r--r-- | docs/markdown/snippets/rust_extra_clang_bindgen_arguments.md | 8 | ||||
| -rw-r--r-- | docs/markdown/snippets/rust_test_link_with.md | 4 | ||||
| -rw-r--r-- | mesonbuild/backend/ninjabackend.py | 60 | ||||
| -rw-r--r-- | mesonbuild/build.py | 31 | ||||
| -rw-r--r-- | mesonbuild/envconfig.py | 6 | ||||
| -rw-r--r-- | mesonbuild/modules/rust.py | 29 | ||||
| -rw-r--r-- | test cases/rust/20 rust and cpp/lib.cpp | 18 | ||||
| -rw-r--r-- | test cases/rust/20 rust and cpp/lib.hpp | 8 | ||||
| -rw-r--r-- | test cases/rust/20 rust and cpp/main.rs | 19 | ||||
| -rw-r--r-- | test cases/rust/20 rust and cpp/meson.build | 14 | ||||
| -rw-r--r-- | test cases/rust/20 rust and cpp/test.json | 15 | ||||
| -rw-r--r-- | test cases/rust/9 unit tests/helper.rs | 3 | ||||
| -rw-r--r-- | test cases/rust/9 unit tests/meson.build | 10 | ||||
| -rw-r--r-- | test cases/rust/9 unit tests/test3.rs | 23 | ||||
| -rw-r--r-- | unittests/machinefiletests.py | 33 |
18 files changed, 275 insertions, 27 deletions
diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index ecdb8b47a..9e4b0c2a5 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -237,6 +237,8 @@ section. subprojects. This setting has no effect if the `exe_wrapper` was not specified. The default value is `true`. (*new in 0.56.0*) - `java_home` is an absolute path pointing to the root of a Java installation. +- `bindgen_clang_arguments` an array of extra arguments to pass to clang when + calling bindgen ### CMake variables diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 7617dbb61..d3891bfc3 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -18,7 +18,7 @@ like Meson, rather than Meson work more like rust. ## Functions -### test(name: string, target: library | executable, dependencies: []Dependency) +### test(name: string, target: library | executable, dependencies: []Dependency, link_with: []targets, rust_args: []string) This function creates a new rust unittest target from an existing rust based target, which may be a library or executable. It does this by @@ -33,6 +33,11 @@ that automatically. Additional, test only dependencies may be passed via the dependencies argument. +*(since 1.2.0)* the link_with argument can be used to pass additional build +targets to link with +*(since 1.2.0)* the `rust_args` keyword argument can be ussed to pass extra +arguments to the Rust compiler. + ### bindgen(*, input: string | BuildTarget | [](string | BuildTarget), output: string, include_directories: [](include_directories | string), c_args: []string, args: []string, dependencies: []Dependency) This function wraps bindgen to simplify creating rust bindings around C @@ -83,10 +88,17 @@ r1 = rust.bindgen( ) ``` - *Since 1.1.0* Meson will synchronize assertions for Rust and C/C++ when the `b_ndebug` option is set (via `-DNDEBUG` for C/C++, and `-C debug-assertions=on` for Rust), and will pass `-DNDEBUG` as an extra argument to clang. This allows for reliable wrapping of `-DNDEBUG` controlled behavior with `#[cfg(debug_asserions)]` and or `cfg!()`. Before 1.1.0, assertions for Rust were never turned on by Meson. + +*Since 1.2.0* Additional arguments to pass to clang may be specified in a +*machine file in the properties section: + +```ini +[properties] +bindgen_clang_arguments = ['--target', 'x86_64-linux-gnu'] +``` diff --git a/docs/markdown/snippets/rust_bindegen_extra_args.md b/docs/markdown/snippets/rust_bindegen_extra_args.md new file mode 100644 index 000000000..209d0bcb0 --- /dev/null +++ b/docs/markdown/snippets/rust_bindegen_extra_args.md @@ -0,0 +1,3 @@ +## rust.bindgen allows passing extra arguments to rustc + +This may be necessary to pass extra `cfg`s or to change warning levels. diff --git a/docs/markdown/snippets/rust_extra_clang_bindgen_arguments.md b/docs/markdown/snippets/rust_extra_clang_bindgen_arguments.md new file mode 100644 index 000000000..71268d43a --- /dev/null +++ b/docs/markdown/snippets/rust_extra_clang_bindgen_arguments.md @@ -0,0 +1,8 @@ +## A machine file may be used to pass extra arguments to clang in a bindgen call + +Because of the way that bindgen proxies arguments to clang the only choice to +add extra arguments currently is to wrap bindgen in a script, since the +arguments must come after a `--`. This is inelegant, and not very portable. Now +a `bindgen_clang_arguments` field may be placed in the machine file for the host +machine, and these arguments will be added to every bindgen call for clang. This +is intended to be useful for things like injecting `--target` arguments. diff --git a/docs/markdown/snippets/rust_test_link_with.md b/docs/markdown/snippets/rust_test_link_with.md new file mode 100644 index 000000000..9c2b7d6c9 --- /dev/null +++ b/docs/markdown/snippets/rust_test_link_with.md @@ -0,0 +1,4 @@ +## Add a `link_with` keyword to `rust.test()` + +This can already be be worked around by creating `declare_dependency()` objects +to pass to the `dependencies` keyword, but this cuts out the middle man. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 29cc8c605..ba614fd56 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1948,6 +1948,49 @@ class NinjaBackend(backends.Backend): args += output linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() + + # Have we already injected msvc-crt args? + # + # If we don't have A C, C++, or Fortran compiler that is + # VisualStudioLike treat this as if we've already injected them + # + # We handle this here rather than in the rust compiler because in + # general we don't want to link rust targets to a non-default crt. + # However, because of the way that MSCRTs work you can only link to one + # per target, so if A links to the debug one, and B links to the normal + # one you can't link A and B. Rust is hardcoded to the default one, + # so if we compile C/C++ code and link against a non-default MSCRT then + # linking will fail. We can work around this by injecting MSCRT link + # arguments early in the rustc command line + # https://github.com/rust-lang/rust/issues/39016 + crt_args_injected = not any(x is not None and x.get_argument_syntax() == 'msvc' for x in + (self.environment.coredata.compilers[target.for_machine].get(l) + for l in ['c', 'cpp', 'fortran'])) + + crt_link_args: T.List[str] = [] + try: + buildtype = self.environment.coredata.options[OptionKey('buildtype')].value + crt = self.environment.coredata.options[OptionKey('b_vscrt')].value + is_debug = buildtype == 'debug' + + if crt == 'from_buildtype': + crt = 'mdd' if is_debug else 'md' + elif crt == 'static_from_buildtype': + crt = 'mtd' if is_debug else 'mt' + + if crt == 'mdd': + crt_link_args = ['-l', 'static=msvcrtd'] + elif crt == 'md': + # this is the default, no need to inject anything + crt_args_injected = True + elif crt == 'mtd': + crt_link_args = ['-l', 'static=libcmtd'] + elif crt == 'mt': + crt_link_args = ['-l', 'static=libcmt'] + + except KeyError: + crt_args_injected = True + # TODO: we likely need to use verbatim to handle name_prefix and name_suffix for d in target.link_targets: linkdirs.add(d.subdir) @@ -1961,7 +2004,13 @@ class NinjaBackend(backends.Backend): d_name = self._get_rust_dependency_name(target, d) args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) - elif isinstance(d, build.StaticLibrary): + continue + + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + args += crt_link_args + crt_args_injected = True + + if isinstance(d, build.StaticLibrary): # Rustc doesn't follow Meson's convention that static libraries # are called .a, and import libraries are .lib, so we have to # manually handle that. @@ -2001,6 +2050,10 @@ class NinjaBackend(backends.Backend): args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) else: + if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): + crt_args_injected = True + crt_args_injected = True + if rustc.linker.id in {'link', 'lld-link'}: if verbatim: # If we can use the verbatim modifier, then everything is great @@ -2045,6 +2098,11 @@ class NinjaBackend(backends.Backend): if d == '': d = '.' args += ['-L', d] + + # Because of the way rustc links, this must come after any potential + # library need to link with their stdlibs (C++ and Fortran, for example) + args.extend(target.get_used_stdlib_args('rust')) + target_deps = target.get_dependencies() has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps) has_rust_shared_deps = any(dep.uses_rust() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index b9525987d..1ecab0d7d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -698,6 +698,15 @@ class BuildTarget(Target): install_dir: T.List[T.Union[str, Literal[False]]] + # This set contains all the languages a linker can link natively + # without extra flags. For instance, nvcc (cuda) can link C++ + # without injecting -lc++/-lstdc++, see + # https://github.com/mesonbuild/meson/issues/10570 + _MASK_LANGS: T.FrozenSet[T.Tuple[str, str]] = frozenset([ + # (language, linker) + ('cpp', 'cuda'), + ]) + def __init__( self, name: str, @@ -1579,14 +1588,6 @@ You probably should put it in link_with instead.''') # Languages used by dependencies dep_langs = self.get_langs_used_by_deps() - # This set contains all the languages a linker can link natively - # without extra flags. For instance, nvcc (cuda) can link C++ - # without injecting -lc++/-lstdc++, see - # https://github.com/mesonbuild/meson/issues/10570 - MASK_LANGS = frozenset([ - # (language, linker) - ('cpp', 'cuda'), - ]) # Pick a compiler based on the language priority-order for l in clink_langs: if l in self.compilers or l in dep_langs: @@ -1597,10 +1598,7 @@ You probably should put it in link_with instead.''') f'Could not get a dynamic linker for build target {self.name!r}. ' f'Requires a linker for language "{l}", but that is not ' 'a project language.') - stdlib_args: T.List[str] = [] - for dl in itertools.chain(self.compilers, dep_langs): - if dl != linker.language and (dl, linker.language) not in MASK_LANGS: - stdlib_args += all_compilers[dl].language_stdlib_only_link_flags(self.environment) + stdlib_args: T.List[str] = self.get_used_stdlib_args(linker.language) # Type of var 'linker' is Compiler. # Pretty hard to fix because the return value is passed everywhere return linker, stdlib_args @@ -1616,6 +1614,15 @@ You probably should put it in link_with instead.''') raise AssertionError(f'Could not get a dynamic linker for build target {self.name!r}') + def get_used_stdlib_args(self, link_language: str) -> T.List[str]: + all_compilers = self.environment.coredata.compilers[self.for_machine] + all_langs = set(all_compilers).union(self.get_langs_used_by_deps()) + stdlib_args: T.List[str] = [] + for dl in all_langs: + if dl != link_language and (dl, link_language) not in self._MASK_LANGS: + stdlib_args.extend(all_compilers[dl].language_stdlib_only_link_flags(self.environment)) + return stdlib_args + def uses_rust(self) -> bool: return 'rust' in self.compilers diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 24c185506..7e0c56703 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -237,6 +237,12 @@ class Properties: value = T.cast('T.Optional[str]', self.properties.get('java_home')) return Path(value) if value else None + def get_bindgen_clang_args(self) -> T.List[str]: + value = mesonlib.listify(self.properties.get('bindgen_clang_arguments', [])) + if not all(isinstance(v, str) for v in value): + raise EnvironmentException('bindgen_clang_arguments must be a string or an array of strings') + return T.cast('T.List[str]', value) + def __eq__(self, other: object) -> bool: if isinstance(other, type(self)): return self.properties == other.properties diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index bf1fd1dda..92b0470d9 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -1,4 +1,4 @@ -# Copyright © 2020-2022 Intel Corporation +# Copyright © 2020-2023 Intel Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,15 +18,16 @@ import typing as T from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, StructuredSources +from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, InvalidArguments, Jar, StructuredSources from ..compilers.compilers import are_asserts_disabled from ..dependencies import Dependency, ExternalLibrary -from ..interpreter.type_checking import DEPENDENCIES_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES +from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs from ..mesonlib import File if T.TYPE_CHECKING: from . import ModuleState + from ..build import LibTypes from ..interpreter import Interpreter from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs @@ -38,6 +39,8 @@ if T.TYPE_CHECKING: dependencies: T.List[T.Union[Dependency, ExternalLibrary]] is_parallel: bool + link_with: T.List[LibTypes] + rust_args: T.List[str] class FuncBindgen(TypedDict): @@ -68,6 +71,14 @@ class RustModule(ExtensionModule): 'rust.test', *TEST_KWS, DEPENDENCIES_KW, + LINK_WITH_KW.evolve(since='1.2.0'), + KwargInfo( + 'rust_args', + ContainerTypeInfo(list, str), + listify=True, + default=[], + since='1.2.0', + ), KwargInfo('is_parallel', bool, default=False), ) def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: FuncTest) -> ModuleReturnValue: @@ -112,6 +123,9 @@ class RustModule(ExtensionModule): rust.test('rust_lib_test', rust_lib) ``` """ + if any(isinstance(t, Jar) for t in kwargs.get('link_with', [])): + raise InvalidArguments('Rust tests cannot link with Jar targets') + name = args[0] base_target: BuildTarget = args[1] if not base_target.uses_rust(): @@ -142,9 +156,11 @@ class RustModule(ExtensionModule): new_target_kwargs = base_target.kwargs.copy() # Don't mutate the shallow copied list, instead replace it with a new # one - new_target_kwargs['rust_args'] = new_target_kwargs.get('rust_args', []) + ['--test'] + new_target_kwargs['rust_args'] = \ + new_target_kwargs.get('rust_args', []) + kwargs['rust_args'] + ['--test'] new_target_kwargs['install'] = False new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies'] + new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with'] sources = T.cast('T.List[SourceOutputs]', base_target.sources.copy()) sources.extend(base_target.generated) @@ -194,7 +210,10 @@ class RustModule(ExtensionModule): else: depends.append(d) - clang_args: T.List[str] = [] + # Copy to avoid subsequent calls mutating the original + # TODO: if we want this to be per-machine we'll need a native kwarg + clang_args = state.environment.properties.host.get_bindgen_clang_args().copy() + for i in state.process_include_dirs(kwargs['include_directories']): # bindgen always uses clang, so it's safe to hardcode -I here clang_args.extend([f'-I{x}' for x in i.to_string_list( diff --git a/test cases/rust/20 rust and cpp/lib.cpp b/test cases/rust/20 rust and cpp/lib.cpp new file mode 100644 index 000000000..b08f870e2 --- /dev/null +++ b/test cases/rust/20 rust and cpp/lib.cpp @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#include "lib.hpp" + +#include <string> + +namespace { + +uint64_t priv_length(const std::string & str) { + return str.length(); +} + +} + +extern "C" uint64_t lib_length(const char * str) { + return priv_length(str); +} diff --git a/test cases/rust/20 rust and cpp/lib.hpp b/test cases/rust/20 rust and cpp/lib.hpp new file mode 100644 index 000000000..63093c4c1 --- /dev/null +++ b/test cases/rust/20 rust and cpp/lib.hpp @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#include <cstddef> +#include <cstdint> + +extern "C" uint64_t lib_length(const char * str); + diff --git a/test cases/rust/20 rust and cpp/main.rs b/test cases/rust/20 rust and cpp/main.rs new file mode 100644 index 000000000..b048cac2b --- /dev/null +++ b/test cases/rust/20 rust and cpp/main.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright © 2023 Intel Corporation + +use std::ffi::CString; +use std::os::raw::c_char; + +extern "C" { + fn lib_length(s: *const c_char) -> u64; +} + +fn main() { + let len: u64; + unsafe { + let c_str = CString::new("Hello, world!").unwrap(); + len = lib_length(c_str.as_ptr()); + } + + std::process::exit(if len == 13 { 0 } else { 1 }) +} diff --git a/test cases/rust/20 rust and cpp/meson.build b/test cases/rust/20 rust and cpp/meson.build new file mode 100644 index 000000000..c3010123a --- /dev/null +++ b/test cases/rust/20 rust and cpp/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2023 Intel Corporation + +project( + 'Rust and C++', + 'rust', 'cpp', + default_options : ['cpp_std=c++14'], + meson_version : '>= 1.2.0', +) + +cpplib = static_library('cpp', 'lib.cpp') +exe = executable('main', 'main.rs', link_with : cpplib) + +test('main', exe) diff --git a/test cases/rust/20 rust and cpp/test.json b/test cases/rust/20 rust and cpp/test.json new file mode 100644 index 000000000..c072a6c94 --- /dev/null +++ b/test cases/rust/20 rust and cpp/test.json @@ -0,0 +1,15 @@ +{ + "matrix": { + "options": { + "b_vscrt": [ + { "val": "none" }, + { "val": "mdd" }, + { "val": "md" }, + { "val": "mtd" }, + { "val": "mt" }, + { "val": "from_buildtype" }, + { "val": "static_from_buildtype" } + ] + } + } +} diff --git a/test cases/rust/9 unit tests/helper.rs b/test cases/rust/9 unit tests/helper.rs new file mode 100644 index 000000000..afe3233e4 --- /dev/null +++ b/test cases/rust/9 unit tests/helper.rs @@ -0,0 +1,3 @@ +pub fn subtract(a: i32, b: i32) -> i32 { + a - b +} diff --git a/test cases/rust/9 unit tests/meson.build b/test cases/rust/9 unit tests/meson.build index b649abb85..94cc400d4 100644 --- a/test cases/rust/9 unit tests/meson.build +++ b/test cases/rust/9 unit tests/meson.build @@ -31,13 +31,17 @@ test( suite : ['foo'], ) -exe = executable('rust_exe', ['test2.rs', 'test.rs']) +exe = executable('rust_exe', ['test2.rs', 'test.rs'], build_by_default : false) rust = import('unstable-rust') rust.test('rust_test_from_exe', exe, should_fail : true) -lib = static_library('rust_static', ['test.rs']) +lib = static_library('rust_static', ['test.rs'], build_by_default : false) rust.test('rust_test_from_static', lib, args: ['--skip', 'test_add_intentional_fail']) -lib = shared_library('rust_shared', ['test.rs']) +lib = shared_library('rust_shared', ['test.rs'], build_by_default : false) rust.test('rust_test_from_shared', lib, args: ['--skip', 'test_add_intentional_fail']) + +helper = static_library('helper', 'helper.rs') +lib = static_library('rust_link_with', 'test3.rs', build_by_default : false) +rust.test('rust_test_link_with', lib, link_with : helper, rust_args : ['--cfg', 'broken="false"']) diff --git a/test cases/rust/9 unit tests/test3.rs b/test cases/rust/9 unit tests/test3.rs new file mode 100644 index 000000000..6d538a059 --- /dev/null +++ b/test cases/rust/9 unit tests/test3.rs @@ -0,0 +1,23 @@ +pub fn add(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod tests { + extern crate helper; + + use super::*; + + // This is an intentinally broken test that should be turned off by extra rust arguments + #[cfg(not(broken = "false"))] + #[test] + fn test_broken() { + assert_eq!(0, 5); + } + + #[test] + fn test_add_sub() { + let x = helper::subtract(6, 5); + assert_eq!(add(x, 5), 6); + } +} diff --git a/unittests/machinefiletests.py b/unittests/machinefiletests.py index 5a9c01d04..3807c8806 100644 --- a/unittests/machinefiletests.py +++ b/unittests/machinefiletests.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import subprocess import tempfile import textwrap @@ -67,7 +69,7 @@ class NativeFileTests(BasePlatformTests): self.current_config = 0 self.current_wrapper = 0 - def helper_create_native_file(self, values): + def helper_create_native_file(self, values: T.Dict[str, T.Dict[str, T.Union[str, int, float, bool, T.Sequence[T.Union[str, int, float, bool]]]]]) -> str: """Create a config file as a temporary file. values should be a nested dictionary structure of {section: {key: @@ -81,10 +83,10 @@ class NativeFileTests(BasePlatformTests): for k, v in entries.items(): if isinstance(v, (bool, int, float)): f.write(f"{k}={v}\n") - elif isinstance(v, list): - f.write("{}=[{}]\n".format(k, ', '.join([f"'{w}'" for w in v]))) - else: + elif isinstance(v, str): f.write(f"{k}='{v}'\n") + else: + f.write("{}=[{}]\n".format(k, ', '.join([f"'{w}'" for w in v]))) return filename def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): @@ -622,6 +624,29 @@ class NativeFileTests(BasePlatformTests): else: self.fail('Did not find bindir in build options?') + @skip_if_not_language('rust') + def test_bindgen_clang_arguments(self) -> None: + if self.backend is not Backend.ninja: + raise SkipTest('Rust is only supported with Ninja') + + testcase = os.path.join(self.rust_test_dir, '12 bindgen') + config = self.helper_create_native_file({ + 'properties': {'bindgen_clang_arguments': 'sentinal'} + }) + + self.init(testcase, extra_args=['--native-file', config]) + targets: T.List[T.Dict[str, T.Any]] = self.introspect('--targets') + for t in targets: + if t['id'].startswith('rustmod-bindgen'): + args: T.List[str] = t['target_sources'][0]['compiler'] + self.assertIn('sentinal', args, msg="Did not find machine file value") + cargs_start = args.index('--') + sent_arg = args.index('sentinal') + self.assertLess(cargs_start, sent_arg, msg='sentinal argument does not come after "--"') + break + else: + self.fail('Did not find a bindgen target') + class CrossFileTests(BasePlatformTests): |
