diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2024-11-16 16:05:05 +0100 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2024-12-19 09:25:20 -0800 |
| commit | 5768ccba6eb77167da96712c20a4e042efb31d03 (patch) | |
| tree | 274bba153b1cdf9f5826d559681bd6be918b86b3 | |
| parent | 27c567de5d1807ac72708ea48018a21f0c6b8dd2 (diff) | |
| download | meson-5768ccba6eb77167da96712c20a4e042efb31d03.tar.gz | |
ninjabackend: add support for "ninja clippy"
Add a target that builds all crates that could be extern to others,
and then reruns clippy.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
| -rw-r--r-- | docs/markdown/howtox.md | 20 | ||||
| -rw-r--r-- | docs/markdown/snippets/clippy.md | 5 | ||||
| -rw-r--r-- | docs/markdown/snippets/num-processes.md | 2 | ||||
| -rw-r--r-- | mesonbuild/backend/backends.py | 6 | ||||
| -rw-r--r-- | mesonbuild/backend/ninjabackend.py | 22 | ||||
| -rw-r--r-- | unittests/allplatformstests.py | 18 |
6 files changed, 71 insertions, 2 deletions
diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index 4a57e8569..ba6a3b8f8 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -239,6 +239,26 @@ And then pass it through the variable (remember to use absolute path): $ SCANBUILD=$(pwd)/my-scan-build.sh ninja -C builddir scan-build ``` +## Use clippy + +If your project includes Rust targets, you can invoke clippy like this: + +```console +$ meson setup builddir +$ ninja -C builddir clippy +``` + +Clippy will also obey the `werror` [builtin option](Builtin-options.md#core-options). + +By default Meson uses as many concurrent processes as there are cores +on the test machine. You can override this with the environment +variable `MESON_NUM_PROCESSES`. + +Meson will look for `clippy-driver` in the same directory as `rustc`, +or try to invoke it using `rustup` if `rustc` points to a `rustup` +binary. If `clippy-driver` is not detected properly, you can add it to +a [machine file](Machine-files.md). + ## Use profile guided optimization Using profile guided optimization with GCC is a two phase diff --git a/docs/markdown/snippets/clippy.md b/docs/markdown/snippets/clippy.md new file mode 100644 index 000000000..14bcc7742 --- /dev/null +++ b/docs/markdown/snippets/clippy.md @@ -0,0 +1,5 @@ +## Meson can run "clippy" on Rust projects + +Meson now defines a `clippy` target if the project uses the Rust programming +language. The target runs clippy on all Rust sources, using the `clippy-driver` +program from the same Rust toolchain as the `rustc` compiler. diff --git a/docs/markdown/snippets/num-processes.md b/docs/markdown/snippets/num-processes.md index c484d930f..533637790 100644 --- a/docs/markdown/snippets/num-processes.md +++ b/docs/markdown/snippets/num-processes.md @@ -5,4 +5,4 @@ the amount of parallel jobs to run; this was useful when `meson test` is invoked through `ninja test` for example. With this version, a new variable `MESON_NUM_PROCESSES` is supported with a broader scope: in addition to `meson test`, it is also used by the `external_project` module and by -Ninja targets that invoke `clang-tidy` and `clang-format`. +Ninja targets that invoke `clang-tidy`, `clang-format` and `clippy`. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index d2c6a4696..970fb82f2 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -2040,6 +2040,12 @@ class Backend: commands += [input] return commands + def have_language(self, langname: str) -> bool: + for for_machine in MachineChoice: + if langname in self.environment.coredata.compilers[for_machine]: + return True + return False + def compiler_to_generator(self, target: build.BuildTarget, compiler: 'Compiler', sources: _ALL_SOURCES_TYPE, diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 81b8bb51a..0c34e08de 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -463,6 +463,8 @@ class RustCrate: display_name: str root_module: str + crate_type: str + target_name: str edition: RUST_EDITIONS deps: T.List[RustDep] cfg: T.List[str] @@ -1878,6 +1880,7 @@ class NinjaBackend(backends.Backend): return orderdeps, first_file def _add_rust_project_entry(self, name: str, main_rust_file: str, args: CompilerArgs, + crate_type: str, target_name: str, from_subproject: bool, proc_macro_dylib_path: T.Optional[str], deps: T.List[RustDep]) -> None: raw_edition: T.Optional[str] = mesonlib.first(reversed(args), lambda x: x.startswith('--edition')) @@ -1895,6 +1898,8 @@ class NinjaBackend(backends.Backend): len(self.rust_crates), name, main_rust_file, + crate_type, + target_name, edition, deps, cfg, @@ -2134,7 +2139,7 @@ class NinjaBackend(backends.Backend): self._add_rust_project_entry(target.name, os.path.abspath(os.path.join(self.environment.build_dir, main_rust_file)), - args, + args, cratetype, target_name, bool(target.subproject), proc_macro_dylib_path, project_deps) @@ -3640,6 +3645,20 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('pool', 'console') self.add_build(elem) + def generate_clippy(self) -> None: + if 'clippy' in self.all_outputs or not self.have_language('rust'): + return + + cmd = self.environment.get_build_command() + \ + ['--internal', 'clippy', self.environment.build_dir] + elem = self.create_phony_target('clippy', 'CUSTOM_COMMAND', 'PHONY') + elem.add_item('COMMAND', cmd) + elem.add_item('pool', 'console') + for crate in self.rust_crates.values(): + if crate.crate_type in {'rlib', 'dylib', 'proc-macro'}: + elem.add_dep(crate.target_name) + self.add_build(elem) + def generate_scanbuild(self) -> None: if not environment.detect_scanbuild(): return @@ -3707,6 +3726,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.generate_scanbuild() self.generate_clangformat() self.generate_clangtidy() + self.generate_clippy() self.generate_tags('etags', 'TAGS') self.generate_tags('ctags', 'ctags') self.generate_tags('cscope', 'cscope') diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 1b1e16928..6544bcce1 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -4892,6 +4892,24 @@ class AllPlatformTests(BasePlatformTests): # When clippy is used, we should get an exception since a variable named # "foo" is used, but is on our denylist testdir = os.path.join(self.rust_test_dir, '1 basic') + self.init(testdir) + self.build('clippy') + + self.wipe() + self.init(testdir, extra_args=['--werror', '-Db_colorout=never']) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.build('clippy') + self.assertTrue('error: use of a blacklisted/placeholder name `foo`' in cm.exception.stdout or + 'error: use of a disallowed/placeholder name `foo`' in cm.exception.stdout) + + @skip_if_not_language('rust') + @unittest.skipIf(not shutil.which('clippy-driver'), 'Test requires clippy-driver') + def test_rust_clippy_as_rustc(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + # When clippy is used, we should get an exception since a variable named + # "foo" is used, but is on our denylist + testdir = os.path.join(self.rust_test_dir, '1 basic') self.init(testdir, extra_args=['--werror'], override_envvars={'RUSTC': 'clippy-driver'}) with self.assertRaises(subprocess.CalledProcessError) as cm: self.build() |
