11//! Checks the licenses of third-party dependencies.
22
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 ;
55use std:: path:: Path ;
66
77/// These are licenses that are allowed for all crates, including the runtime,
@@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
9898 "autocfg" ,
9999 "bitflags" ,
100100 "block-buffer" ,
101- "bumpalo" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
102101 "cc" ,
103102 "cfg-if" ,
104103 "chalk-derive" ,
105104 "chalk-engine" ,
106105 "chalk-ir" ,
107106 "chalk-solve" ,
108- "chrono" ,
109107 "convert_case" , // dependency of derive_more
110108 "compiler_builtins" ,
111109 "cpufeatures" ,
@@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
124122 "dlmalloc" ,
125123 "either" ,
126124 "ena" ,
127- "env_logger" ,
128125 "expect-test" ,
129126 "fallible-iterator" , // dependency of `thorin`
130127 "fastrand" ,
131- "filetime" ,
132128 "fixedbitset" ,
133129 "flate2" ,
134130 "fluent-bundle" ,
@@ -142,21 +138,18 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
142138 "gsgdt" ,
143139 "hashbrown" ,
144140 "hermit-abi" ,
145- "humantime" ,
146141 "icu_list" ,
147142 "icu_locid" ,
148143 "icu_provider" ,
149144 "icu_provider_adapters" ,
150145 "icu_provider_macros" ,
151- "if_chain" ,
152146 "indexmap" ,
153147 "instant" ,
154148 "intl-memoizer" ,
155149 "intl_pluralrules" ,
156150 "itertools" ,
157151 "itoa" ,
158152 "jobserver" ,
159- "js-sys" , // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
160153 "lazy_static" ,
161154 "libc" ,
162155 "libloading" ,
@@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
171164 "memmap2" ,
172165 "memoffset" ,
173166 "miniz_oxide" ,
174- "num-integer" ,
175- "num-traits" ,
176167 "num_cpus" ,
177168 "object" ,
178169 "odht" ,
@@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
190181 "proc-macro2" ,
191182 "psm" ,
192183 "punycode" ,
193- "quick-error" ,
194184 "quote" ,
195185 "rand" ,
196186 "rand_chacha" ,
@@ -236,7 +226,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
236226 "thiserror-impl" ,
237227 "thorin-dwp" ,
238228 "thread_local" ,
239- "time" ,
240229 "tinystr" ,
241230 "tinyvec" ,
242231 "tinyvec_macros" ,
@@ -269,13 +258,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
269258 "valuable" ,
270259 "version_check" ,
271260 "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.
279261 "winapi" ,
280262 "winapi-i686-pc-windows-gnu" ,
281263 "winapi-util" ,
@@ -486,73 +468,55 @@ fn check_permitted_dependencies(
486468 restricted_dependency_crates : & [ & ' static str ] ,
487469 bad : & mut bool ,
488470) {
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+
489497 // 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 ) {
492500 tidy_error ! (
493501 bad,
494- "could not find allowed package `{}`\n \
502+ "could not find allowed package `{permitted }`\n \
495503 Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
496- name
497504 ) ;
498505 }
499506 }
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- }
536507
537- visited. insert ( & krate. id ) ;
508+ // Get in a convenient form.
509+ let permitted_dependencies: HashSet < _ > = permitted_dependencies. iter ( ) . cloned ( ) . collect ( ) ;
538510
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+ }
544518 }
545519 }
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
556520}
557521
558522/// Prevents multiple versions of some expensive crates.
@@ -589,24 +553,6 @@ fn check_crate_duplicate(
589553 }
590554}
591555
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-
610556/// Finds a package with the given name.
611557fn pkg_from_name < ' a > ( metadata : & ' a Metadata , name : & ' static str ) -> & ' a Package {
612558 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
616562 result
617563}
618564
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+
619569/// Finds all the packages that are in the rust runtime.
620570fn compute_runtime_crates < ' a > ( metadata : & ' a Metadata ) -> HashSet < & ' a PackageId > {
621- let resolve = metadata. resolve . as_ref ( ) . unwrap ( ) ;
622571 let mut result = HashSet :: new ( ) ;
623572 for name in RUNTIME_CRATES {
624573 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 ) ;
626575 }
627576 result
628577}
629578
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 ,
633582 pkg_id : & ' a PackageId ,
634583 result : & mut HashSet < & ' a PackageId > ,
584+ filter : & dyn Fn ( & [ DepKindInfo ] ) -> bool ,
635585) {
636586 if !result. insert ( pkg_id) {
637587 return ;
638588 }
639- let node = resolve
589+ let node = metadata
590+ . resolve
591+ . as_ref ( )
592+ . unwrap ( )
640593 . nodes
641594 . iter ( )
642595 . find ( |n| & n. id == pkg_id)
643596 . unwrap_or_else ( || panic ! ( "could not find `{pkg_id}` in resolve" ) ) ;
644597 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) ;
646602 }
647603}
648604
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+
649611fn check_rustfix ( metadata : & Metadata , bad : & mut bool ) {
650612 let cargo = pkg_from_name ( metadata, "cargo" ) ;
651613 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 ) ;
654616 let cargo_rustfix = cargo_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
655617 let compiletest_rustfix = compiletest_deps. iter ( ) . find ( |p| p. name == "rustfix" ) . unwrap ( ) ;
656618 if cargo_rustfix. version != compiletest_rustfix. version {
0 commit comments