1
1
//! Checks the licenses of third-party dependencies.
2
2
3
- use cargo_metadata:: { Metadata , Package , PackageId , Resolve } ;
4
- use std:: collections:: { BTreeSet , HashSet } ;
3
+ use cargo_metadata:: { DepKindInfo , Metadata , Package , PackageId } ;
4
+ use std:: collections:: HashSet ;
5
5
use std:: path:: Path ;
6
6
7
7
/// These are licenses that are allowed for all crates, including the runtime,
@@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
98
98
"autocfg" ,
99
99
"bitflags" ,
100
100
"block-buffer" ,
101
- "bumpalo" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
102
101
"cc" ,
103
102
"cfg-if" ,
104
103
"chalk-derive" ,
105
104
"chalk-engine" ,
106
105
"chalk-ir" ,
107
106
"chalk-solve" ,
108
- "chrono" ,
109
107
"convert_case" , // dependency of derive_more
110
108
"compiler_builtins" ,
111
109
"cpufeatures" ,
@@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
124
122
"dlmalloc" ,
125
123
"either" ,
126
124
"ena" ,
127
- "env_logger" ,
128
125
"expect-test" ,
129
126
"fallible-iterator" , // dependency of `thorin`
130
127
"fastrand" ,
131
- "filetime" ,
132
128
"fixedbitset" ,
133
129
"flate2" ,
134
130
"fluent-bundle" ,
@@ -142,21 +138,18 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
142
138
"gsgdt" ,
143
139
"hashbrown" ,
144
140
"hermit-abi" ,
145
- "humantime" ,
146
141
"icu_list" ,
147
142
"icu_locid" ,
148
143
"icu_provider" ,
149
144
"icu_provider_adapters" ,
150
145
"icu_provider_macros" ,
151
- "if_chain" ,
152
146
"indexmap" ,
153
147
"instant" ,
154
148
"intl-memoizer" ,
155
149
"intl_pluralrules" ,
156
150
"itertools" ,
157
151
"itoa" ,
158
152
"jobserver" ,
159
- "js-sys" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
160
153
"lazy_static" ,
161
154
"libc" ,
162
155
"libloading" ,
@@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
171
164
"memmap2" ,
172
165
"memoffset" ,
173
166
"miniz_oxide" ,
174
- "num-integer" ,
175
- "num-traits" ,
176
167
"num_cpus" ,
177
168
"object" ,
178
169
"odht" ,
@@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
190
181
"proc-macro2" ,
191
182
"psm" ,
192
183
"punycode" ,
193
- "quick-error" ,
194
184
"quote" ,
195
185
"rand" ,
196
186
"rand_chacha" ,
@@ -236,7 +226,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
236
226
"thiserror-impl" ,
237
227
"thorin-dwp" ,
238
228
"thread_local" ,
239
- "time" ,
240
229
"tinystr" ,
241
230
"tinyvec" ,
242
231
"tinyvec_macros" ,
@@ -269,13 +258,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
269
258
"valuable" ,
270
259
"version_check" ,
271
260
"wasi" ,
272
- // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
273
- "wasm-bindgen" ,
274
- "wasm-bindgen-backend" ,
275
- "wasm-bindgen-macro" ,
276
- "wasm-bindgen-macro-support" ,
277
- "wasm-bindgen-shared" ,
278
- // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
279
261
"winapi" ,
280
262
"winapi-i686-pc-windows-gnu" ,
281
263
"winapi-util" ,
@@ -486,73 +468,55 @@ fn check_permitted_dependencies(
486
468
restricted_dependency_crates : & [ & ' static str ] ,
487
469
bad : & mut bool ,
488
470
) {
471
+ let mut deps = HashSet :: new ( ) ;
472
+ for to_check in restricted_dependency_crates {
473
+ let to_check = pkg_from_name ( metadata, to_check) ;
474
+ use cargo_platform:: Cfg ;
475
+ use std:: str:: FromStr ;
476
+ // We don't expect the compiler to ever run on wasm32, so strip
477
+ // out those dependencies to avoid polluting the permitted list.
478
+ deps_of_filtered ( metadata, & to_check. id , & mut deps, & |dep_kinds| {
479
+ dep_kinds. iter ( ) . any ( |dep_kind| {
480
+ dep_kind
481
+ . target
482
+ . as_ref ( )
483
+ . map ( |target| {
484
+ !target. matches (
485
+ "wasm32-unknown-unknown" ,
486
+ & [
487
+ Cfg :: from_str ( "target_arch=\" wasm32\" " ) . unwrap ( ) ,
488
+ Cfg :: from_str ( "target_os=\" unknown\" " ) . unwrap ( ) ,
489
+ ] ,
490
+ )
491
+ } )
492
+ . unwrap_or ( true )
493
+ } )
494
+ } ) ;
495
+ }
496
+
489
497
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
490
- for name in permitted_dependencies {
491
- if !metadata . packages . iter ( ) . any ( |p| p . name == * name ) {
498
+ for permitted in permitted_dependencies {
499
+ if !deps . iter ( ) . any ( |dep_id| & pkg_from_id ( metadata , dep_id ) . name == permitted ) {
492
500
tidy_error ! (
493
501
bad,
494
- "could not find allowed package `{}`\n \
502
+ "could not find allowed package `{permitted }`\n \
495
503
Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
496
- name
497
504
) ;
498
505
}
499
506
}
500
- // Get the list in a convenient form.
501
- let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
502
-
503
- // Check dependencies.
504
- let mut visited = BTreeSet :: new ( ) ;
505
- let mut unapproved = BTreeSet :: new ( ) ;
506
- for & krate in restricted_dependency_crates. iter ( ) {
507
- let pkg = pkg_from_name ( metadata, krate) ;
508
- let mut bad =
509
- check_crate_dependencies ( & permitted_dependencies, metadata, & mut visited, pkg) ;
510
- unapproved. append ( & mut bad) ;
511
- }
512
-
513
- if !unapproved. is_empty ( ) {
514
- tidy_error ! ( bad, "Dependencies for {} not explicitly permitted:" , descr) ;
515
- for dep in unapproved {
516
- println ! ( "* {dep}" ) ;
517
- }
518
- }
519
- }
520
-
521
- /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
522
- /// the list of permitted dependencies. Returns a list of disallowed dependencies.
523
- fn check_crate_dependencies < ' a > (
524
- permitted_dependencies : & ' a HashSet < & ' static str > ,
525
- metadata : & ' a Metadata ,
526
- visited : & mut BTreeSet < & ' a PackageId > ,
527
- krate : & ' a Package ,
528
- ) -> BTreeSet < & ' a PackageId > {
529
- // This will contain bad deps.
530
- let mut unapproved = BTreeSet :: new ( ) ;
531
-
532
- // Check if we have already visited this crate.
533
- if visited. contains ( & krate. id ) {
534
- return unapproved;
535
- }
536
507
537
- visited. insert ( & krate. id ) ;
508
+ // Get in a convenient form.
509
+ let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
538
510
539
- // If this path is in-tree, we don't require it to be explicitly permitted.
540
- if krate. source . is_some ( ) {
541
- // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
542
- if !permitted_dependencies. contains ( krate. name . as_str ( ) ) {
543
- unapproved. insert ( & krate. id ) ;
511
+ for dep in deps {
512
+ let dep = pkg_from_id ( metadata, dep) ;
513
+ // If this path is in-tree, we don't require it to be explicitly permitted.
514
+ if dep. source . is_some ( ) {
515
+ if !permitted_dependencies. contains ( dep. name . as_str ( ) ) {
516
+ tidy_error ! ( bad, "Dependency for {descr} not explicitly permitted: {}" , dep. id) ;
517
+ }
544
518
}
545
519
}
546
-
547
- // Do a DFS in the crate graph.
548
- let to_check = deps_of ( metadata, & krate. id ) ;
549
-
550
- for dep in to_check {
551
- let mut bad = check_crate_dependencies ( permitted_dependencies, metadata, visited, dep) ;
552
- unapproved. append ( & mut bad) ;
553
- }
554
-
555
- unapproved
556
520
}
557
521
558
522
/// Prevents multiple versions of some expensive crates.
@@ -589,24 +553,6 @@ fn check_crate_duplicate(
589
553
}
590
554
}
591
555
592
- /// Returns a list of dependencies for the given package.
593
- fn deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
594
- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
595
- let node = resolve
596
- . nodes
597
- . iter ( )
598
- . find ( |n| & n. id == pkg_id)
599
- . unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
600
- node. deps
601
- . iter ( )
602
- . map ( |dep| {
603
- metadata. packages . iter ( ) . find ( |pkg| pkg. id == dep. pkg ) . unwrap_or_else ( || {
604
- panic ! ( "could not find dep `{}` for pkg `{}` in resolve" , dep. pkg, pkg_id)
605
- } )
606
- } )
607
- . collect ( )
608
- }
609
-
610
556
/// Finds a package with the given name.
611
557
fn pkg_from_name < ' a > ( metadata : & ' a Metadata , name : & ' static str ) -> & ' a Package {
612
558
let mut i = metadata. packages . iter ( ) . filter ( |p| p. name == name) ;
@@ -616,41 +562,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package
616
562
result
617
563
}
618
564
565
+ fn pkg_from_id < ' a > ( metadata : & ' a Metadata , id : & PackageId ) -> & ' a Package {
566
+ metadata. packages . iter ( ) . find ( |p| & p. id == id) . unwrap ( )
567
+ }
568
+
619
569
/// Finds all the packages that are in the rust runtime.
620
570
fn compute_runtime_crates < ' a > ( metadata : & ' a Metadata ) -> HashSet < & ' a PackageId > {
621
- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
622
571
let mut result = HashSet :: new ( ) ;
623
572
for name in RUNTIME_CRATES {
624
573
let id = & pkg_from_name ( metadata, name) . id ;
625
- normal_deps_of_r ( resolve , id, & mut result) ;
574
+ deps_of_filtered ( metadata , id, & mut result, & |_| true ) ;
626
575
}
627
576
result
628
577
}
629
578
630
- /// Recursively find all normal dependencies.
631
- fn normal_deps_of_r < ' a > (
632
- resolve : & ' a Resolve ,
579
+ /// Recursively find all dependencies.
580
+ fn deps_of_filtered < ' a > (
581
+ metadata : & ' a Metadata ,
633
582
pkg_id : & ' a PackageId ,
634
583
result : & mut HashSet < & ' a PackageId > ,
584
+ filter : & dyn Fn ( & [ DepKindInfo ] ) -> bool ,
635
585
) {
636
586
if !result. insert ( pkg_id) {
637
587
return ;
638
588
}
639
- let node = resolve
589
+ let node = metadata
590
+ . resolve
591
+ . as_ref ( )
592
+ . unwrap ( )
640
593
. nodes
641
594
. iter ( )
642
595
. find ( |n| & n. id == pkg_id)
643
596
. unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
644
597
for dep in & node. deps {
645
- normal_deps_of_r ( resolve, & dep. pkg , result) ;
598
+ if !filter ( & dep. dep_kinds ) {
599
+ continue ;
600
+ }
601
+ deps_of_filtered ( metadata, & dep. pkg , result, filter) ;
646
602
}
647
603
}
648
604
605
+ fn direct_deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
606
+ let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
607
+ let node = resolve. nodes . iter ( ) . find ( |n| & n. id == pkg_id) . unwrap ( ) ;
608
+ node. deps . iter ( ) . map ( |dep| pkg_from_id ( metadata, & dep. pkg ) ) . collect ( )
609
+ }
610
+
649
611
fn check_rustfix ( metadata : & Metadata , bad : & mut bool ) {
650
612
let cargo = pkg_from_name ( metadata, "cargo" ) ;
651
613
let compiletest = pkg_from_name ( metadata, "compiletest" ) ;
652
- let cargo_deps = deps_of ( metadata, & cargo. id ) ;
653
- let compiletest_deps = deps_of ( metadata, & compiletest. id ) ;
614
+ let cargo_deps = direct_deps_of ( metadata, & cargo. id ) ;
615
+ let compiletest_deps = direct_deps_of ( metadata, & compiletest. id ) ;
654
616
let cargo_rustfix = cargo_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
655
617
let compiletest_rustfix = compiletest_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
656
618
if cargo_rustfix. version != compiletest_rustfix. version {
0 commit comments