]> git.proxmox.com Git - rustc.git/blame - src/tools/tidy/src/deps.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / tidy / src / deps.rs
CommitLineData
ba9703b0 1//! Checks the licenses of third-party dependencies.
476ff2be 2
e8be2606 3use cargo_metadata::{Metadata, Package, PackageId};
9c376795 4use std::collections::HashSet;
476ff2be
SL
5use std::path::Path;
6
ba9703b0
XL
7/// These are licenses that are allowed for all crates, including the runtime,
8/// rustc, tools, etc.
49aad941 9#[rustfmt::skip]
b7449926 10const LICENSES: &[&str] = &[
49aad941
FG
11 // tidy-alphabetical-start
12 "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident
13 "0BSD OR MIT OR Apache-2.0", // adler license
14 "0BSD",
3b2f2976 15 "Apache-2.0 / MIT",
c620b35d 16 "Apache-2.0 OR ISC OR MIT",
416331ca 17 "Apache-2.0 OR MIT",
e1599b0c 18 "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
c620b35d 19 "Apache-2.0",
49aad941 20 "Apache-2.0/MIT",
4b012472 21 "BSD-2-Clause OR Apache-2.0 OR MIT", // zerocopy
a2a8927a 22 "ISC",
49aad941 23 "MIT / Apache-2.0",
781aab86 24 "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc
49aad941
FG
25 "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros
26 "MIT OR Apache-2.0",
27 "MIT OR Zlib OR Apache-2.0", // miniz_oxide
28 "MIT",
29 "MIT/Apache-2.0",
30 "Unicode-DFS-2016", // tinystr and icu4x
8faf50e0 31 "Unlicense OR MIT",
49aad941
FG
32 "Unlicense/MIT",
33 "Zlib OR Apache-2.0 OR MIT", // tinyvec
34 // tidy-alphabetical-end
8bb4bdeb
XL
35];
36
ed00b5ec
FG
37type ExceptionList = &'static [(&'static str, &'static str)];
38
39/// The workspaces to check for licensing and optionally permitted dependencies.
40///
41/// Each entry consists of a tuple with the following elements:
42///
43/// * The path to the workspace root Cargo.toml file.
44/// * The list of license exceptions.
45/// * Optionally a tuple of:
46/// * A list of crates for which dependencies need to be explicitly allowed.
47/// * The list of allowed dependencies.
48// FIXME auto detect all cargo workspaces
49pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)] = &[
50 // The root workspace has to be first for check_rustfix to work.
51 (".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES))),
52 // Outside of the alphabetical section because rustfmt formats it using multiple lines.
53 (
54 "compiler/rustc_codegen_cranelift",
55 EXCEPTIONS_CRANELIFT,
56 Some((&["rustc_codegen_cranelift"], PERMITTED_CRANELIFT_DEPENDENCIES)),
57 ),
58 // tidy-alphabetical-start
e8be2606 59 ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None),
ed00b5ec
FG
60 //("library/backtrace", &[], None), // FIXME uncomment once rust-lang/backtrace#562 has been synced back to the rust repo
61 //("library/portable-simd", &[], None), // FIXME uncomment once rust-lang/portable-simd#363 has been synced back to the rust repo
62 //("library/stdarch", EXCEPTIONS_STDARCH, None), // FIXME uncomment once rust-lang/stdarch#1462 has been synced back to the rust repo
63 ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None),
64 ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None),
65 //("src/etc/test-float-parse", &[], None), // FIXME uncomment once all deps are vendored
66 ("src/tools/cargo", EXCEPTIONS_CARGO, None),
67 //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
68 //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
69 ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
70 ("src/tools/x", &[], None),
71 // tidy-alphabetical-end
72];
73
0531ce1d
XL
74/// These are exceptions to Rust's permissive licensing policy, and
75/// should be considered bugs. Exceptions are only allowed in Rust
76/// tooling. It is _crucial_ that no exception crates be dependencies
9fa01778 77/// of the Rust runtime (std/test).
49aad941 78#[rustfmt::skip]
ed00b5ec 79const EXCEPTIONS: ExceptionList = &[
49aad941 80 // tidy-alphabetical-start
487cf647 81 ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc
487cf647 82 ("colored", "MPL-2.0"), // rustfmt
49aad941
FG
83 ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
84 ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
85 ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above.
86 ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
87 ("mdbook", "MPL-2.0"), // mdbook
ed00b5ec 88 ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`)
add651ee 89 ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), // rustc (license is the same as LLVM uses)
ed00b5ec 90 ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 // cargo/... (because of serde)
49aad941
FG
91 ("self_cell", "Apache-2.0"), // rustc (fluent translations)
92 ("snap", "BSD-3-Clause"), // rustc
c620b35d
FG
93 ("wasm-encoder", "Apache-2.0 WITH LLVM-exception"), // rustc
94 ("wasmparser", "Apache-2.0 WITH LLVM-exception"), // rustc
49aad941
FG
95 // tidy-alphabetical-end
96];
97
ed00b5ec
FG
98// FIXME uncomment once rust-lang/stdarch#1462 lands
99/*
100const EXCEPTIONS_STDARCH: ExceptionList = &[
101 // tidy-alphabetical-start
102 ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
103 ("wasmparser", "Apache-2.0 WITH LLVM-exception"),
104 ("wasmprinter", "Apache-2.0 WITH LLVM-exception"),
105 // tidy-alphabetical-end
106];
107*/
108
109const EXCEPTIONS_CARGO: ExceptionList = &[
49aad941
FG
110 // tidy-alphabetical-start
111 ("bitmaps", "MPL-2.0+"),
112 ("bytesize", "Apache-2.0"),
add651ee
FG
113 ("ciborium", "Apache-2.0"),
114 ("ciborium-io", "Apache-2.0"),
115 ("ciborium-ll", "Apache-2.0"),
fe692bf9 116 ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"),
781aab86 117 ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"),
49aad941
FG
118 ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
119 ("im-rc", "MPL-2.0+"),
49aad941
FG
120 ("normalize-line-endings", "Apache-2.0"),
121 ("openssl", "Apache-2.0"),
ed00b5ec 122 ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
49aad941
FG
123 ("sha1_smol", "BSD-3-Clause"),
124 ("similar", "Apache-2.0"),
125 ("sized-chunks", "MPL-2.0+"),
126 ("subtle", "BSD-3-Clause"),
ed00b5ec 127 ("supports-hyperlinks", "Apache-2.0"),
49aad941
FG
128 ("unicode-bom", "Apache-2.0"),
129 // tidy-alphabetical-end
0531ce1d
XL
130];
131
ed00b5ec
FG
132const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
133 // tidy-alphabetical-start
ed00b5ec 134 ("dissimilar", "Apache-2.0"),
ed00b5ec 135 ("notify", "CC0-1.0"),
31ef2f64 136 ("option-ext", "MPL-2.0"),
ed00b5ec 137 ("pulldown-cmark-to-cmark", "Apache-2.0"),
c0240ec0 138 ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"),
ed00b5ec
FG
139 ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
140 ("scip", "Apache-2.0"),
141 ("snap", "BSD-3-Clause"),
142 // tidy-alphabetical-end
143];
144
145const EXCEPTIONS_CRANELIFT: ExceptionList = &[
49aad941 146 // tidy-alphabetical-start
17df50a5
XL
147 ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
148 ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
149 ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
150 ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
fe692bf9 151 ("cranelift-control", "Apache-2.0 WITH LLVM-exception"),
17df50a5
XL
152 ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
153 ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
064997fb 154 ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
17df50a5
XL
155 ("cranelift-jit", "Apache-2.0 WITH LLVM-exception"),
156 ("cranelift-module", "Apache-2.0 WITH LLVM-exception"),
157 ("cranelift-native", "Apache-2.0 WITH LLVM-exception"),
158 ("cranelift-object", "Apache-2.0 WITH LLVM-exception"),
17df50a5 159 ("mach", "BSD-2-Clause"),
064997fb 160 ("regalloc2", "Apache-2.0 WITH LLVM-exception"),
17df50a5 161 ("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
9c376795 162 ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
49aad941 163 // tidy-alphabetical-end
17df50a5
XL
164];
165
ed00b5ec
FG
166const EXCEPTIONS_GCC: ExceptionList = &[
167 // tidy-alphabetical-start
168 ("gccjit", "GPL-3.0"),
169 ("gccjit_sys", "GPL-3.0"),
170 // tidy-alphabetical-end
171];
ed00b5ec
FG
172
173const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[
174 ("ryu", "Apache-2.0 OR BSL-1.0"), // through serde. BSL is not acceptble, but we use it under Apache-2.0
175];
176
177const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
178 ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptible, but we use it under MIT OR Apache-2.0
064997fb
FG
179];
180
ba9703b0
XL
181/// These are the root crates that are part of the runtime. The licenses for
182/// these and all their dependencies *must not* be in the exception list.
183const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
184
fe692bf9
FG
185const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
186
f035d41b 187/// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
ba9703b0
XL
188///
189/// This list is here to provide a speed-bump to adding a new dependency to
190/// rustc. Please check with the compiler team before adding an entry.
2b03887a 191const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
49aad941 192 // tidy-alphabetical-start
e8be2606 193 "addr2line",
3dfed10e 194 "adler",
5099ac24 195 "ahash",
ba9703b0 196 "aho-corasick",
fe692bf9 197 "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801
ba9703b0 198 "annotate-snippets",
c0240ec0 199 "anstyle",
487cf647 200 "ar_archive_writer",
ba9703b0 201 "arrayvec",
ba9703b0 202 "autocfg",
ba9703b0
XL
203 "bitflags",
204 "block-buffer",
49aad941 205 "byteorder", // via ruzstd in object in thorin-dwp
ba9703b0
XL
206 "cc",
207 "cfg-if",
e8be2606 208 "cfg_aliases",
ba9703b0 209 "compiler_builtins",
5099ac24 210 "cpufeatures",
ba9703b0 211 "crc32fast",
923072b8 212 "crossbeam-channel",
ba9703b0
XL
213 "crossbeam-deque",
214 "crossbeam-epoch",
ba9703b0 215 "crossbeam-utils",
5099ac24 216 "crypto-common",
e8be2606 217 "ctrlc",
add651ee
FG
218 "darling",
219 "darling_core",
220 "darling_macro",
ba9703b0 221 "datafrog",
c620b35d 222 "deranged",
ed00b5ec 223 "derivative",
487cf647 224 "derive_more",
add651ee 225 "derive_setters",
ba9703b0 226 "digest",
487cf647
FG
227 "displaydoc",
228 "dissimilar",
ba9703b0
XL
229 "dlmalloc",
230 "either",
9ffffee4 231 "elsa",
ba9703b0 232 "ena",
fe692bf9 233 "equivalent",
add651ee 234 "errno",
3dfed10e 235 "expect-test",
a2a8927a 236 "fallible-iterator", // dependency of `thorin`
487cf647 237 "fastrand",
49aad941 238 "field-offset",
ba9703b0 239 "flate2",
04454e1e
FG
240 "fluent-bundle",
241 "fluent-langneg",
242 "fluent-syntax",
add651ee 243 "fnv",
ba9703b0 244 "fortanix-sgx-abi",
ba9703b0
XL
245 "generic-array",
246 "getopts",
247 "getrandom",
3dfed10e 248 "gimli",
fc512014 249 "gsgdt",
ba9703b0
XL
250 "hashbrown",
251 "hermit-abi",
487cf647 252 "icu_list",
ed00b5ec 253 "icu_list_data",
487cf647 254 "icu_locid",
ed00b5ec
FG
255 "icu_locid_transform",
256 "icu_locid_transform_data",
487cf647
FG
257 "icu_provider",
258 "icu_provider_adapters",
259 "icu_provider_macros",
add651ee 260 "ident_case",
ba9703b0 261 "indexmap",
04454e1e
FG
262 "intl-memoizer",
263 "intl_pluralrules",
ba9703b0 264 "itertools",
17df50a5 265 "itoa",
ed00b5ec 266 "jemalloc-sys",
ba9703b0 267 "jobserver",
ba9703b0 268 "lazy_static",
c620b35d 269 "leb128",
ba9703b0 270 "libc",
a2a8927a 271 "libloading",
fe692bf9 272 "linux-raw-sys",
487cf647 273 "litemap",
ba9703b0
XL
274 "lock_api",
275 "log",
17df50a5 276 "matchers",
ba9703b0
XL
277 "md-5",
278 "measureme",
279 "memchr",
6a06907d 280 "memmap2",
ba9703b0
XL
281 "memoffset",
282 "miniz_oxide",
e8be2606 283 "nix",
fe692bf9 284 "nu-ansi-term",
c620b35d 285 "num-conv",
3c0e092e 286 "num_cpus",
3dfed10e 287 "object",
c295e0f8 288 "odht",
f9f354fc 289 "once_cell",
fe692bf9 290 "overload",
ba9703b0
XL
291 "parking_lot",
292 "parking_lot_core",
3dfed10e 293 "pathdiff",
6a06907d
XL
294 "perf-event-open-sys",
295 "pin-project-lite",
ba9703b0 296 "polonius-engine",
ed00b5ec 297 "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std
c620b35d 298 "powerfmt",
ba9703b0 299 "ppv-lite86",
04454e1e 300 "proc-macro-hack",
ba9703b0 301 "proc-macro2",
f9f354fc 302 "psm",
49aad941 303 "pulldown-cmark",
ba9703b0 304 "punycode",
ba9703b0 305 "quote",
781aab86
FG
306 "r-efi",
307 "r-efi-alloc",
ba9703b0
XL
308 "rand",
309 "rand_chacha",
310 "rand_core",
ba9703b0 311 "rand_xorshift",
c295e0f8 312 "rand_xoshiro",
ba9703b0 313 "redox_syscall",
ba9703b0 314 "regex",
17df50a5 315 "regex-automata",
ba9703b0 316 "regex-syntax",
ba9703b0
XL
317 "rustc-demangle",
318 "rustc-hash",
319 "rustc-rayon",
320 "rustc-rayon-core",
add651ee 321 "rustc_apfloat",
ba9703b0 322 "rustc_version",
fe692bf9 323 "rustix",
49aad941 324 "ruzstd", // via object in thorin-dwp
17df50a5 325 "ryu",
ba9703b0
XL
326 "scoped-tls",
327 "scopeguard",
04454e1e 328 "self_cell",
ba9703b0 329 "semver",
ba9703b0
XL
330 "serde",
331 "serde_derive",
17df50a5 332 "serde_json",
9c376795 333 "sha1",
29967ef6 334 "sha2",
17df50a5 335 "sharded-slab",
c0240ec0 336 "shlex",
3c0e092e 337 "smallvec",
1b1a35ee 338 "snap",
ba9703b0 339 "stable_deref_trait",
f9f354fc 340 "stacker",
9c376795 341 "static_assertions",
add651ee 342 "strsim",
ba9703b0
XL
343 "syn",
344 "synstructure",
345 "tempfile",
346 "termcolor",
ba9703b0 347 "termize",
49aad941 348 "thin-vec",
04454e1e
FG
349 "thiserror",
350 "thiserror-impl",
a2a8927a 351 "thorin-dwp",
ba9703b0 352 "thread_local",
add651ee
FG
353 "time",
354 "time-core",
355 "time-macros",
04454e1e 356 "tinystr",
17df50a5 357 "tinyvec",
2b03887a 358 "tinyvec_macros",
3dfed10e
XL
359 "tracing",
360 "tracing-attributes",
361 "tracing-core",
17df50a5 362 "tracing-log",
17df50a5
XL
363 "tracing-subscriber",
364 "tracing-tree",
9c376795 365 "twox-hash",
04454e1e 366 "type-map",
ba9703b0 367 "typenum",
04454e1e
FG
368 "unic-langid",
369 "unic-langid-impl",
370 "unic-langid-macros",
371 "unic-langid-macros-impl",
9ffffee4 372 "unicase",
2b03887a 373 "unicode-ident",
ba9703b0 374 "unicode-normalization",
add651ee 375 "unicode-properties",
ba9703b0
XL
376 "unicode-script",
377 "unicode-security",
378 "unicode-width",
379 "unicode-xid",
4b012472 380 "unwinding",
f2b60f7d 381 "valuable",
ba9703b0
XL
382 "version_check",
383 "wasi",
c620b35d
FG
384 "wasm-encoder",
385 "wasmparser",
ba9703b0 386 "winapi",
ba9703b0
XL
387 "winapi-i686-pc-windows-gnu",
388 "winapi-util",
389 "winapi-x86_64-pc-windows-gnu",
49aad941 390 "windows",
c620b35d 391 "windows-core",
fe692bf9 392 "windows-sys",
49aad941
FG
393 "windows-targets",
394 "windows_aarch64_gnullvm",
395 "windows_aarch64_msvc",
396 "windows_i686_gnu",
31ef2f64 397 "windows_i686_gnullvm",
49aad941
FG
398 "windows_i686_msvc",
399 "windows_x86_64_gnu",
400 "windows_x86_64_gnullvm",
401 "windows_x86_64_msvc",
487cf647 402 "writeable",
487cf647
FG
403 "yoke",
404 "yoke-derive",
4b012472
FG
405 "zerocopy",
406 "zerocopy-derive",
487cf647
FG
407 "zerofrom",
408 "zerofrom-derive",
409 "zerovec",
410 "zerovec-derive",
49aad941 411 // tidy-alphabetical-end
0531ce1d
XL
412];
413
ed00b5ec
FG
414// These crates come from ICU4X and are licensed under the unicode license.
415// It currently doesn't have an SPDX identifier, so they cannot put one there.
416// See https://github.com/unicode-org/icu4x/pull/3875
417// FIXME: This should be removed once ICU4X crates update.
418const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[
419 // tidy-alphabetical-start
420 "icu_list",
421 "icu_list_data",
422 "icu_locid",
423 "icu_locid_transform",
424 "icu_locid_transform_data",
425 "icu_provider",
426 "icu_provider_adapters",
427 "icu_provider_macros",
428 "litemap",
429 "tinystr",
430 "writeable",
431 "yoke",
432 "yoke-derive",
433 "zerofrom",
434 "zerofrom-derive",
435 "zerovec",
436 "zerovec-derive",
437 // tidy-alphabetical-end
438];
439
17df50a5 440const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
49aad941 441 // tidy-alphabetical-start
064997fb 442 "ahash",
17df50a5 443 "anyhow",
fe692bf9 444 "arbitrary",
17df50a5 445 "bitflags",
49aad941 446 "bumpalo",
17df50a5
XL
447 "cfg-if",
448 "cranelift-bforest",
449 "cranelift-codegen",
450 "cranelift-codegen-meta",
451 "cranelift-codegen-shared",
fe692bf9 452 "cranelift-control",
17df50a5
XL
453 "cranelift-entity",
454 "cranelift-frontend",
064997fb 455 "cranelift-isle",
17df50a5
XL
456 "cranelift-jit",
457 "cranelift-module",
458 "cranelift-native",
459 "cranelift-object",
460 "crc32fast",
add651ee 461 "equivalent",
9c376795 462 "fallible-iterator",
17df50a5
XL
463 "gimli",
464 "hashbrown",
465 "indexmap",
466 "libc",
467 "libloading",
468 "log",
469 "mach",
136023e0 470 "memchr",
17df50a5 471 "object",
e8be2606 472 "once_cell",
c620b35d
FG
473 "proc-macro2",
474 "quote",
064997fb 475 "regalloc2",
17df50a5 476 "region",
fe692bf9 477 "rustc-hash",
064997fb 478 "slice-group-by",
17df50a5 479 "smallvec",
9c376795 480 "stable_deref_trait",
c620b35d 481 "syn",
17df50a5 482 "target-lexicon",
c620b35d 483 "unicode-ident",
064997fb 484 "version_check",
9c376795 485 "wasmtime-jit-icache-coherence",
17df50a5
XL
486 "winapi",
487 "winapi-i686-pc-windows-gnu",
488 "winapi-x86_64-pc-windows-gnu",
f2b60f7d 489 "windows-sys",
fe692bf9
FG
490 "windows-targets",
491 "windows_aarch64_gnullvm",
492 "windows_aarch64_msvc",
493 "windows_i686_gnu",
e8be2606 494 "windows_i686_gnullvm",
fe692bf9
FG
495 "windows_i686_msvc",
496 "windows_x86_64_gnu",
497 "windows_x86_64_gnullvm",
498 "windows_x86_64_msvc",
c620b35d
FG
499 "zerocopy",
500 "zerocopy-derive",
49aad941 501 // tidy-alphabetical-end
17df50a5
XL
502];
503
ba9703b0
XL
504/// Dependency checks.
505///
3dfed10e
XL
506/// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path
507/// to the cargo executable.
508pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
ed00b5ec 509 let mut checked_runtime_licenses = false;
ed00b5ec
FG
510
511 for &(workspace, exceptions, permitted_deps) in WORKSPACES {
512 if !root.join(workspace).join("Cargo.lock").exists() {
513 tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
514 continue;
515 }
516
517 let mut cmd = cargo_metadata::MetadataCommand::new();
518 cmd.cargo_path(cargo)
519 .manifest_path(root.join(workspace).join("Cargo.toml"))
520 .features(cargo_metadata::CargoOpt::AllFeatures)
521 .other_options(vec!["--locked".to_owned()]);
522 let metadata = t!(cmd.exec());
49aad941 523
ed00b5ec
FG
524 check_license_exceptions(&metadata, exceptions, bad);
525 if let Some((crates, permitted_deps)) = permitted_deps {
526 check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad);
527 }
17df50a5 528
ed00b5ec
FG
529 if workspace == "." {
530 let runtime_ids = compute_runtime_crates(&metadata);
531 check_runtime_license_exceptions(&metadata, runtime_ids, bad);
532 checked_runtime_licenses = true;
ed00b5ec
FG
533 }
534 }
064997fb 535
ed00b5ec
FG
536 // Sanity check to ensure we don't accidentally remove the workspace containing the runtime
537 // crates.
538 assert!(checked_runtime_licenses);
0531ce1d
XL
539}
540
ed00b5ec 541/// Check that all licenses of runtime dependencies are in the valid list in `LICENSES`.
ba9703b0 542///
ed00b5ec
FG
543/// Unlike for tools we don't allow exceptions to the `LICENSES` list for the runtime with the sole
544/// exception of `fortanix-sgx-abi` which is only used on x86_64-fortanix-unknown-sgx.
545fn check_runtime_license_exceptions(
17df50a5 546 metadata: &Metadata,
17df50a5
XL
547 runtime_ids: HashSet<&PackageId>,
548 bad: &mut bool,
549) {
ed00b5ec
FG
550 for pkg in &metadata.packages {
551 if !runtime_ids.contains(&pkg.id) {
552 // Only checking dependencies of runtime libraries here.
553 continue;
554 }
555 if pkg.source.is_none() {
556 // No need to check local packages.
557 continue;
558 }
559 let license = match &pkg.license {
560 Some(license) => license,
561 None => {
562 tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
563 continue;
564 }
565 };
566 if !LICENSES.contains(&license.as_str()) {
567 // This is a specific exception because SGX is considered "third party".
568 // See https://github.com/rust-lang/rust/issues/62620 for more.
569 // In general, these should never be added and this exception
570 // should not be taken as precedent for any new target.
571 if pkg.name == "fortanix-sgx-abi" && pkg.license.as_deref() == Some("MPL-2.0") {
572 continue;
573 }
c620b35d
FG
574
575 // This exception is due to the fact that the feature set of the
576 // `object` crate is different between rustc and libstd. In the
577 // standard library only a conservative set of features are enabled
578 // which notably does not include the `wasm` feature which pulls in
579 // this dependency. In the compiler, however, the `wasm` feature is
580 // enabled. This exception is intended to be here so long as the
581 // `EXCEPTIONS` above contains `wasmparser`, but once that goes away
582 // this can be removed.
583 if pkg.name == "wasmparser"
584 && pkg.license.as_deref() == Some("Apache-2.0 WITH LLVM-exception")
585 {
586 continue;
587 }
588
ed00b5ec
FG
589 tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
590 }
591 }
592}
593
594/// Check that all licenses of tool dependencies are in the valid list in `LICENSES`.
595///
596/// Packages listed in `exceptions` are allowed for tools.
597fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], bad: &mut bool) {
ba9703b0 598 // Validate the EXCEPTIONS list hasn't changed.
17df50a5 599 for (name, license) in exceptions {
ba9703b0
XL
600 // Check that the package actually exists.
601 if !metadata.packages.iter().any(|p| p.name == *name) {
fc512014
XL
602 tidy_error!(
603 bad,
ba9703b0
XL
604 "could not find exception package `{}`\n\
605 Remove from EXCEPTIONS list if it is no longer used.",
606 name
607 );
ba9703b0
XL
608 }
609 // Check that the license hasn't changed.
610 for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
ba9703b0
XL
611 match &pkg.license {
612 None => {
fc512014
XL
613 tidy_error!(
614 bad,
ba9703b0
XL
615 "dependency exception `{}` does not declare a license expression",
616 pkg.id
617 );
ba9703b0
XL
618 }
619 Some(pkg_license) => {
620 if pkg_license.as_str() != *license {
5e7ed085
FG
621 println!("dependency exception `{name}` license has changed");
622 println!(" previously `{license}` now `{pkg_license}`");
ba9703b0
XL
623 println!(" update EXCEPTIONS for the new license");
624 *bad = true;
625 }
626 }
627 }
628 }
0531ce1d 629 }
0531ce1d 630
17df50a5 631 let exception_names: Vec<_> = exceptions.iter().map(|(name, _license)| *name).collect();
8bb4bdeb 632
ba9703b0
XL
633 // Check if any package does not have a valid license.
634 for pkg in &metadata.packages {
635 if pkg.source.is_none() {
636 // No need to check local packages.
0531ce1d 637 continue;
8bb4bdeb 638 }
ed00b5ec 639 if exception_names.contains(&pkg.name.as_str()) {
ba9703b0
XL
640 continue;
641 }
642 let license = match &pkg.license {
643 Some(license) => license,
644 None => {
ed00b5ec
FG
645 if ICU4X_UNICODE_LICENSE_DEPENDENCIES.contains(&pkg.name.as_str()) {
646 // See the comment on ICU4X_UNICODE_LICENSE_DEPENDENCIES.
647 continue;
648 }
fc512014 649 tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
ba9703b0
XL
650 continue;
651 }
652 };
653 if !LICENSES.contains(&license.as_str()) {
fc512014 654 tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
ba9703b0 655 }
476ff2be 656 }
476ff2be
SL
657}
658
2b03887a 659/// Checks the dependency of `restricted_dependency_crates` at the given path. Changes `bad` to
f035d41b 660/// `true` if a check failed.
0531ce1d 661///
2b03887a
FG
662/// Specifically, this checks that the dependencies are on the `permitted_dependencies`.
663fn check_permitted_dependencies(
17df50a5 664 metadata: &Metadata,
064997fb 665 descr: &str,
17df50a5
XL
666 permitted_dependencies: &[&'static str],
667 restricted_dependency_crates: &[&'static str],
668 bad: &mut bool,
669) {
fe692bf9 670 let mut has_permitted_dep_error = false;
9c376795
FG
671 let mut deps = HashSet::new();
672 for to_check in restricted_dependency_crates {
673 let to_check = pkg_from_name(metadata, to_check);
e8be2606 674 deps_of(metadata, &to_check.id, &mut deps);
9c376795
FG
675 }
676
f035d41b 677 // Check that the PERMITTED_DEPENDENCIES does not have unused entries.
9c376795
FG
678 for permitted in permitted_dependencies {
679 if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
fc512014
XL
680 tidy_error!(
681 bad,
9c376795 682 "could not find allowed package `{permitted}`\n\
f035d41b 683 Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
ba9703b0 684 );
fe692bf9 685 has_permitted_dep_error = true;
ba9703b0
XL
686 }
687 }
0531ce1d 688
9c376795
FG
689 // Get in a convenient form.
690 let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
0531ce1d 691
9c376795
FG
692 for dep in deps {
693 let dep = pkg_from_id(metadata, dep);
694 // If this path is in-tree, we don't require it to be explicitly permitted.
695 if dep.source.is_some() {
696 if !permitted_dependencies.contains(dep.name.as_str()) {
697 tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
fe692bf9 698 has_permitted_dep_error = true;
9c376795 699 }
0531ce1d 700 }
0531ce1d 701 }
fe692bf9
FG
702
703 if has_permitted_dep_error {
704 eprintln!("Go to `{PERMITTED_DEPS_LOCATION}` for the list.");
705 }
0531ce1d
XL
706}
707
ba9703b0
XL
708/// Finds a package with the given name.
709fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
710 let mut i = metadata.packages.iter().filter(|p| p.name == name);
711 let result =
5e7ed085
FG
712 i.next().unwrap_or_else(|| panic!("could not find package `{name}` in package list"));
713 assert!(i.next().is_none(), "more than one package found for `{name}`");
ba9703b0
XL
714 result
715}
716
9c376795
FG
717fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package {
718 metadata.packages.iter().find(|p| &p.id == id).unwrap()
719}
720
ba9703b0
XL
721/// Finds all the packages that are in the rust runtime.
722fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
ba9703b0
XL
723 let mut result = HashSet::new();
724 for name in RUNTIME_CRATES {
725 let id = &pkg_from_name(metadata, name).id;
e8be2606 726 deps_of(metadata, id, &mut result);
ba9703b0
XL
727 }
728 result
729}
730
9c376795 731/// Recursively find all dependencies.
e8be2606 732fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId, result: &mut HashSet<&'a PackageId>) {
ba9703b0
XL
733 if !result.insert(pkg_id) {
734 return;
735 }
9c376795
FG
736 let node = metadata
737 .resolve
738 .as_ref()
739 .unwrap()
ba9703b0
XL
740 .nodes
741 .iter()
742 .find(|n| &n.id == pkg_id)
5e7ed085 743 .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
17df50a5 744 for dep in &node.deps {
e8be2606 745 deps_of(metadata, &dep.pkg, result);
b7449926
XL
746 }
747}