@@ -2,7 +2,7 @@ use anyhow::*;
2
2
use clap:: Parser ;
3
3
use itertools:: Itertools ;
4
4
use log:: * ;
5
- use std:: { collections:: HashMap , ffi:: OsStr , process:: Command , str:: FromStr } ;
5
+ use std:: { collections:: HashMap , ffi:: OsStr , path :: Path , process:: Command , str:: FromStr } ;
6
6
use strum:: VariantNames ;
7
7
8
8
#[ derive(
@@ -177,6 +177,8 @@ enum Xtasks {
177
177
Build ,
178
178
/// Build the main workspace, apply all prefferred lints
179
179
Check ,
180
+ /// Build the rust crates.io docs as well as any other docs
181
+ Docs ,
180
182
/// Build the main workspace, and then run all tests
181
183
Test ,
182
184
/// Perform a full check as it would be done in CI
@@ -188,6 +190,7 @@ impl Xtasks {
188
190
match self {
189
191
Xtasks :: Build => Self :: build ( features) ,
190
192
Xtasks :: Check => Self :: check ( features) ,
193
+ Xtasks :: Docs => Self :: docs ( ) ,
191
194
Xtasks :: Test => Self :: test ( features) ,
192
195
Xtasks :: CiCheck => Self :: cicd ( ) ,
193
196
Xtasks :: Init => Self :: init ( ) ,
@@ -240,6 +243,7 @@ impl Xtasks {
240
243
context : & str ,
241
244
features : Features ,
242
245
add_args : I ,
246
+ dir : Option < & Path > ,
243
247
) -> Result < ( ) > {
244
248
info ! ( "Running workspace command: {}" , command) ;
245
249
@@ -253,12 +257,17 @@ impl Xtasks {
253
257
. expect ( "invalid command argument" )
254
258
. to_owned ( )
255
259
} ) ) ;
260
+ let workspace_dir = Self :: workspace_dir ( ) ?;
261
+ let workspace_dir = match dir {
262
+ Some ( d) => workspace_dir. join ( d) ,
263
+ None => workspace_dir,
264
+ } ;
256
265
257
266
let mut cmd = Command :: new ( "cargo" ) ;
258
267
cmd. args ( args)
259
268
. stdout ( std:: process:: Stdio :: inherit ( ) )
260
269
. stderr ( std:: process:: Stdio :: inherit ( ) )
261
- . current_dir ( Self :: workspace_dir ( ) ? ) ;
270
+ . current_dir ( workspace_dir) ;
262
271
263
272
info ! ( "Using command: {:?}" , cmd) ;
264
273
@@ -280,6 +289,7 @@ impl Xtasks {
280
289
"Failed to build workspace" ,
281
290
features,
282
291
vec ! [ "--all-targets" ] ,
292
+ None ,
283
293
) ?;
284
294
Ok ( ( ) )
285
295
}
@@ -291,6 +301,7 @@ impl Xtasks {
291
301
"Failed to run clippy" ,
292
302
features,
293
303
vec ! [ "--all-targets" , "--" , "-D" , "warnings" ] ,
304
+ None ,
294
305
) ?;
295
306
296
307
// run cargo fmt checks
@@ -303,21 +314,64 @@ impl Xtasks {
303
314
Ok ( ( ) )
304
315
}
305
316
317
+ fn docs ( ) -> Result < ( ) > {
318
+ // find [package.metadata."docs.rs"] key in Cargo.toml
319
+ let metadata = Self :: cargo_metadata ( ) ?;
320
+ let package = metadata. root_package ( ) . expect ( "no root package" ) ;
321
+ let docs_rs = package
322
+ . metadata
323
+ . get ( "docs.rs" )
324
+ . expect ( "no docs.rs metadata" ) ;
325
+
326
+ let string_list = docs_rs
327
+ . as_array ( )
328
+ . expect ( "docs.rs metadata is not an array" )
329
+ . iter ( )
330
+ . map ( |v| v. as_str ( ) . expect ( "docs.rs metadata is not a string" ) )
331
+ . map ( |s| Feature :: from_str ( s) . expect ( "invalid feature" ) )
332
+ . collect :: < Vec < _ > > ( ) ;
333
+
334
+ let features = Features ( string_list) ;
335
+
336
+ Self :: run_workspace_command (
337
+ "doc" ,
338
+ "Failed to build crates.io docs" ,
339
+ features. clone ( ) ,
340
+ vec ! [ "--all" ] ,
341
+ None ,
342
+ ) ?;
343
+
344
+ // build mdbook
345
+ Self :: run_workspace_command (
346
+ "mdbook" ,
347
+ "Failed to build mdbook docs" ,
348
+ features,
349
+ vec ! [ "--all" ] ,
350
+ Some ( Path :: new ( "docs" ) ) ,
351
+ ) ?;
352
+ Ok ( ( ) )
353
+ }
354
+
306
355
fn test ( features : Features ) -> Result < ( ) > {
307
356
// run cargo test with instrumentation
308
357
std:: env:: set_var ( "CARGO_INCREMENTAL" , "0" ) ;
309
358
std:: env:: set_var ( "RUSTFLAGS" , "-Cinstrument-coverage" ) ;
310
359
let target_dir = std:: env:: var ( "CARGO_TARGET_DIR" ) . unwrap_or_else ( |_| "target" . to_owned ( ) ) ;
311
- let coverage_file = std:: path:: PathBuf :: from ( target_dir)
312
- . join ( "coverage" )
313
- . join ( "cargo-test-%p-%m.profraw" ) ;
360
+ let coverage_dir = std:: path:: PathBuf :: from ( target_dir) . join ( "coverage" ) ;
361
+ let coverage_file = coverage_dir. join ( "cargo-test-%p-%m.profraw" ) ;
362
+
363
+ // clear coverage directory
364
+ assert ! ( coverage_dir != std:: path:: Path :: new( "/" ) ) ;
365
+ std:: fs:: remove_dir_all ( coverage_dir) ?;
366
+
314
367
std:: env:: set_var ( "LLVM_PROFILE_FILE" , coverage_file) ;
315
368
316
369
Self :: run_workspace_command (
317
370
"test" ,
318
371
"Failed to run tests" ,
319
372
features,
320
373
vec ! [ "--exclude" , "xtask" ] ,
374
+ None ,
321
375
) ?;
322
376
323
377
// generate coverage report and lcov file
0 commit comments