@@ -99,9 +99,30 @@ def _clippy_aspect_impl(target, ctx):
99
99
if hasattr (target [OutputGroupInfo ], "clippy_checks" ):
100
100
return []
101
101
102
+ output_format = "stderr-to-file" if ctx .attr ._capture_output [CaptureClippyOutputInfo ].capture_output else "stderr-and-touch-file"
103
+
104
+ clippy_info = rust_clippy_action (target , ctx , output_format , capture_exit_code = False )
105
+
106
+ return [
107
+ OutputGroupInfo (clippy_checks = clippy_info .output ),
108
+ clippy_info ,
109
+ ]
110
+
111
+ def rust_clippy_action (target , ctx , output_format , capture_exit_code ):
112
+ """Generate an action to run clippy.
113
+
114
+ Args:
115
+ target (Target): The target the aspect is running on.
116
+ ctx (ctx, optional): The aspect's context object.
117
+ output_format (str): One of "stderr-and-touch-file", "stderr-to-file", or "json-to-file"
118
+ capture_exit_code (boolean): If true, write the exit code to a file and exit 0.
119
+
120
+ Returns:
121
+ ClippyInfo: A `ClippyInfo` provider.
122
+ """
102
123
crate_info = _get_clippy_ready_crate_info (target , ctx )
103
124
if not crate_info :
104
- return [ ClippyInfo (output = depset ([]))]
125
+ return ClippyInfo (output = depset ([]))
105
126
106
127
toolchain = find_toolchain (ctx )
107
128
cc_toolchain , feature_configuration = find_cc_toolchain (ctx )
@@ -171,7 +192,7 @@ def _clippy_aspect_impl(target, ctx):
171
192
172
193
# For remote execution purposes, the clippy_out file must be a sibling of crate_info.output
173
194
# or rustc may fail to create intermediate output files because the directory does not exist.
174
- if ctx . attr . _capture_output [ CaptureClippyOutputInfo ]. capture_output :
195
+ if output_format == "stderr-to-file" :
175
196
clippy_out = ctx .actions .declare_file (ctx .label .name + ".clippy.out" , sibling = crate_info .output )
176
197
args .process_wrapper_flags .add ("--stderr-file" , clippy_out )
177
198
@@ -181,7 +202,7 @@ def _clippy_aspect_impl(target, ctx):
181
202
# If we are capturing the output, we want the build system to be able to keep going
182
203
# and consume the output. Some clippy lints are denials, so we cap everything at warn.
183
204
args .rustc_flags .add ("--cap-lints=warn" )
184
- else :
205
+ elif output_format == "stderr-and-touch-file" :
185
206
# A marker file indicating clippy has executed successfully.
186
207
# This file is necessary because "ctx.actions.run" mandates an output.
187
208
clippy_out = ctx .actions .declare_file (ctx .label .name + ".clippy.ok" , sibling = crate_info .output )
@@ -196,6 +217,24 @@ def _clippy_aspect_impl(target, ctx):
196
217
# Bazel will consider the execution result of the aspect to be "success",
197
218
# and Clippy won't be re-triggered unless the source file is modified.
198
219
args .rustc_flags .add ("-Dwarnings" )
220
+ elif output_format == "json-to-file" :
221
+ clippy_out = ctx .actions .declare_file (ctx .label .name + ".clippy.out" , sibling = crate_info .output )
222
+ args .process_wrapper_flags .add ("--stderr-file" , clippy_out )
223
+
224
+ if clippy_flags or lint_files :
225
+ args .rustc_flags .add_all (clippy_flags )
226
+ args .rustc_flags .add ("--error-format=json" )
227
+ else :
228
+ fail ("clippy output_format must be one of stderr-to-file|stderr-and-touch-file|json-to-file but was {}" .format (output_format ))
229
+
230
+ outputs = [clippy_out ]
231
+
232
+ if capture_exit_code :
233
+ exit_code_file = ctx .actions .declare_file (ctx .label .name + ".clippy.exit_code" , sibling = crate_info .output )
234
+ args .process_wrapper_flags .add ("--exit-code-file" , exit_code_file )
235
+ outputs .append (exit_code_file )
236
+ else :
237
+ exit_code_file = None
199
238
200
239
# Upstream clippy requires one of these two filenames or it silently uses
201
240
# the default config. Enforce the naming so users are not confused.
@@ -208,7 +247,7 @@ def _clippy_aspect_impl(target, ctx):
208
247
ctx .actions .run (
209
248
executable = ctx .executable ._process_wrapper ,
210
249
inputs = compile_inputs ,
211
- outputs = [ clippy_out ] ,
250
+ outputs = outputs ,
212
251
env = env ,
213
252
tools = [toolchain .clippy_driver ],
214
253
arguments = args .all ,
@@ -217,10 +256,7 @@ def _clippy_aspect_impl(target, ctx):
217
256
toolchain = "@rules_rust//rust:toolchain_type" ,
218
257
)
219
258
220
- return [
221
- OutputGroupInfo (clippy_checks = depset ([clippy_out ])),
222
- ClippyInfo (output = depset ([clippy_out ])),
223
- ]
259
+ return ClippyInfo (output = depset ([clippy_out ]), exit_code_file = exit_code_file )
224
260
225
261
# Example: Run the clippy checker on all targets in the codebase.
226
262
# bazel build --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect \
0 commit comments