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" ,
@@ -235,7 +225,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
235
225
"thiserror-impl" ,
236
226
"thorin-dwp" ,
237
227
"thread_local" ,
238
- "time" ,
239
228
"tinystr" ,
240
229
"tinyvec" ,
241
230
"tinyvec_macros" ,
@@ -268,13 +257,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
268
257
"valuable" ,
269
258
"version_check" ,
270
259
"wasi" ,
271
- // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
272
- "wasm-bindgen" ,
273
- "wasm-bindgen-backend" ,
274
- "wasm-bindgen-macro" ,
275
- "wasm-bindgen-macro-support" ,
276
- "wasm-bindgen-shared" ,
277
- // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
278
260
"winapi" ,
279
261
"winapi-i686-pc-windows-gnu" ,
280
262
"winapi-util" ,
@@ -485,73 +467,55 @@ fn check_permitted_dependencies(
485
467
restricted_dependency_crates : & [ & ' static str ] ,
486
468
bad : & mut bool ,
487
469
) {
470
+ let mut deps = HashSet :: new ( ) ;
471
+ for to_check in restricted_dependency_crates {
472
+ let to_check = pkg_from_name ( metadata, to_check) ;
473
+ use cargo_platform:: Cfg ;
474
+ use std:: str:: FromStr ;
475
+ // We don't expect the compiler to ever run on wasm32, so strip
476
+ // out those dependencies to avoid polluting the permitted list.
477
+ deps_of_filtered ( metadata, & to_check. id , & mut deps, & |dep_kinds| {
478
+ dep_kinds. iter ( ) . any ( |dep_kind| {
479
+ dep_kind
480
+ . target
481
+ . as_ref ( )
482
+ . map ( |target| {
483
+ !target. matches (
484
+ "wasm32-unknown-unknown" ,
485
+ & [
486
+ Cfg :: from_str ( "target_arch=\" wasm32\" " ) . unwrap ( ) ,
487
+ Cfg :: from_str ( "target_os=\" unknown\" " ) . unwrap ( ) ,
488
+ ] ,
489
+ )
490
+ } )
491
+ . unwrap_or ( true )
492
+ } )
493
+ } ) ;
494
+ }
495
+
488
496
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
489
- for name in permitted_dependencies {
490
- if !metadata . packages . iter ( ) . any ( |p| p . name == * name ) {
497
+ for permitted in permitted_dependencies {
498
+ if !deps . iter ( ) . any ( |dep_id| & pkg_from_id ( metadata , dep_id ) . name == permitted ) {
491
499
tidy_error ! (
492
500
bad,
493
- "could not find allowed package `{}`\n \
501
+ "could not find allowed package `{permitted }`\n \
494
502
Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
495
- name
496
503
) ;
497
504
}
498
505
}
499
- // Get the list in a convenient form.
500
- let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
501
-
502
- // Check dependencies.
503
- let mut visited = BTreeSet :: new ( ) ;
504
- let mut unapproved = BTreeSet :: new ( ) ;
505
- for & krate in restricted_dependency_crates. iter ( ) {
506
- let pkg = pkg_from_name ( metadata, krate) ;
507
- let mut bad =
508
- check_crate_dependencies ( & permitted_dependencies, metadata, & mut visited, pkg) ;
509
- unapproved. append ( & mut bad) ;
510
- }
511
-
512
- if !unapproved. is_empty ( ) {
513
- tidy_error ! ( bad, "Dependencies for {} not explicitly permitted:" , descr) ;
514
- for dep in unapproved {
515
- println ! ( "* {dep}" ) ;
516
- }
517
- }
518
- }
519
-
520
- /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
521
- /// the list of permitted dependencies. Returns a list of disallowed dependencies.
522
- fn check_crate_dependencies < ' a > (
523
- permitted_dependencies : & ' a HashSet < & ' static str > ,
524
- metadata : & ' a Metadata ,
525
- visited : & mut BTreeSet < & ' a PackageId > ,
526
- krate : & ' a Package ,
527
- ) -> BTreeSet < & ' a PackageId > {
528
- // This will contain bad deps.
529
- let mut unapproved = BTreeSet :: new ( ) ;
530
-
531
- // Check if we have already visited this crate.
532
- if visited. contains ( & krate. id ) {
533
- return unapproved;
534
- }
535
506
536
- visited. insert ( & krate. id ) ;
507
+ // Get in a convenient form.
508
+ let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
537
509
538
- // If this path is in-tree, we don't require it to be explicitly permitted.
539
- if krate. source . is_some ( ) {
540
- // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
541
- if !permitted_dependencies. contains ( krate. name . as_str ( ) ) {
542
- unapproved. insert ( & krate. id ) ;
510
+ for dep in deps {
511
+ let dep = pkg_from_id ( metadata, dep) ;
512
+ // If this path is in-tree, we don't require it to be explicitly permitted.
513
+ if dep. source . is_some ( ) {
514
+ if !permitted_dependencies. contains ( dep. name . as_str ( ) ) {
515
+ tidy_error ! ( bad, "Dependency for {descr} not explicitly permitted: {}" , dep. id) ;
516
+ }
543
517
}
544
518
}
545
-
546
- // Do a DFS in the crate graph.
547
- let to_check = deps_of ( metadata, & krate. id ) ;
548
-
549
- for dep in to_check {
550
- let mut bad = check_crate_dependencies ( permitted_dependencies, metadata, visited, dep) ;
551
- unapproved. append ( & mut bad) ;
552
- }
553
-
554
- unapproved
555
519
}
556
520
557
521
/// Prevents multiple versions of some expensive crates.
@@ -588,24 +552,6 @@ fn check_crate_duplicate(
588
552
}
589
553
}
590
554
591
- /// Returns a list of dependencies for the given package.
592
- fn deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
593
- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
594
- let node = resolve
595
- . nodes
596
- . iter ( )
597
- . find ( |n| & n. id == pkg_id)
598
- . unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
599
- node. deps
600
- . iter ( )
601
- . map ( |dep| {
602
- metadata. packages . iter ( ) . find ( |pkg| pkg. id == dep. pkg ) . unwrap_or_else ( || {
603
- panic ! ( "could not find dep `{}` for pkg `{}` in resolve" , dep. pkg, pkg_id)
604
- } )
605
- } )
606
- . collect ( )
607
- }
608
-
609
555
/// Finds a package with the given name.
610
556
fn pkg_from_name < ' a > ( metadata : & ' a Metadata , name : & ' static str ) -> & ' a Package {
611
557
let mut i = metadata. packages . iter ( ) . filter ( |p| p. name == name) ;
@@ -615,41 +561,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package
615
561
result
616
562
}
617
563
564
+ fn pkg_from_id < ' a > ( metadata : & ' a Metadata , id : & PackageId ) -> & ' a Package {
565
+ metadata. packages . iter ( ) . find ( |p| & p. id == id) . unwrap ( )
566
+ }
567
+
618
568
/// Finds all the packages that are in the rust runtime.
619
569
fn compute_runtime_crates < ' a > ( metadata : & ' a Metadata ) -> HashSet < & ' a PackageId > {
620
- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
621
570
let mut result = HashSet :: new ( ) ;
622
571
for name in RUNTIME_CRATES {
623
572
let id = & pkg_from_name ( metadata, name) . id ;
624
- normal_deps_of_r ( resolve , id, & mut result) ;
573
+ deps_of_filtered ( metadata , id, & mut result, & |_| true ) ;
625
574
}
626
575
result
627
576
}
628
577
629
- /// Recursively find all normal dependencies.
630
- fn normal_deps_of_r < ' a > (
631
- resolve : & ' a Resolve ,
578
+ /// Recursively find all dependencies.
579
+ fn deps_of_filtered < ' a > (
580
+ metadata : & ' a Metadata ,
632
581
pkg_id : & ' a PackageId ,
633
582
result : & mut HashSet < & ' a PackageId > ,
583
+ filter : & dyn Fn ( & [ DepKindInfo ] ) -> bool ,
634
584
) {
635
585
if !result. insert ( pkg_id) {
636
586
return ;
637
587
}
638
- let node = resolve
588
+ let node = metadata
589
+ . resolve
590
+ . as_ref ( )
591
+ . unwrap ( )
639
592
. nodes
640
593
. iter ( )
641
594
. find ( |n| & n. id == pkg_id)
642
595
. unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
643
596
for dep in & node. deps {
644
- normal_deps_of_r ( resolve, & dep. pkg , result) ;
597
+ if !filter ( & dep. dep_kinds ) {
598
+ continue ;
599
+ }
600
+ deps_of_filtered ( metadata, & dep. pkg , result, filter) ;
645
601
}
646
602
}
647
603
604
+ fn direct_deps_of < ' a > ( metadata : & ' a Metadata , pkg_id : & ' a PackageId ) -> Vec < & ' a Package > {
605
+ let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
606
+ let node = resolve. nodes . iter ( ) . find ( |n| & n. id == pkg_id) . unwrap ( ) ;
607
+ node. deps . iter ( ) . map ( |dep| pkg_from_id ( metadata, & dep. pkg ) ) . collect ( )
608
+ }
609
+
648
610
fn check_rustfix ( metadata : & Metadata , bad : & mut bool ) {
649
611
let cargo = pkg_from_name ( metadata, "cargo" ) ;
650
612
let compiletest = pkg_from_name ( metadata, "compiletest" ) ;
651
- let cargo_deps = deps_of ( metadata, & cargo. id ) ;
652
- let compiletest_deps = deps_of ( metadata, & compiletest. id ) ;
613
+ let cargo_deps = direct_deps_of ( metadata, & cargo. id ) ;
614
+ let compiletest_deps = direct_deps_of ( metadata, & compiletest. id ) ;
653
615
let cargo_rustfix = cargo_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
654
616
let compiletest_rustfix = compiletest_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
655
617
if cargo_rustfix. version != compiletest_rustfix. version {
0 commit comments