Skip to content

Commit f157ce9

Browse files
committed
Add --print target-spec-json-schema
This schema is helpful for people writing custom target spec JSON. It can provide autocomplete in the editor, and also serves as documentation when there are documentation comments on the structs, as `schemars` will put them in the schema.
1 parent a0bb9cc commit f157ce9

File tree

19 files changed

+229
-16
lines changed

19 files changed

+229
-16
lines changed

Cargo.lock

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,12 @@ version = "1.0.10"
11911191
source = "registry+https://github.com/rust-lang/crates.io-index"
11921192
checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
11931193

1194+
[[package]]
1195+
name = "dyn-clone"
1196+
version = "1.0.19"
1197+
source = "registry+https://github.com/rust-lang/crates.io-index"
1198+
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
1199+
11941200
[[package]]
11951201
name = "either"
11961202
version = "1.15.0"
@@ -3122,6 +3128,26 @@ dependencies = [
31223128
"thiserror 2.0.15",
31233129
]
31243130

3131+
[[package]]
3132+
name = "ref-cast"
3133+
version = "1.0.24"
3134+
source = "registry+https://github.com/rust-lang/crates.io-index"
3135+
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
3136+
dependencies = [
3137+
"ref-cast-impl",
3138+
]
3139+
3140+
[[package]]
3141+
name = "ref-cast-impl"
3142+
version = "1.0.24"
3143+
source = "registry+https://github.com/rust-lang/crates.io-index"
3144+
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
3145+
dependencies = [
3146+
"proc-macro2",
3147+
"quote",
3148+
"syn 2.0.106",
3149+
]
3150+
31253151
[[package]]
31263152
name = "regex"
31273153
version = "1.11.1"
@@ -4577,6 +4603,7 @@ dependencies = [
45774603
"rustc_macros",
45784604
"rustc_serialize",
45794605
"rustc_span",
4606+
"schemars",
45804607
"serde",
45814608
"serde_derive",
45824609
"serde_json",
@@ -4900,6 +4927,31 @@ dependencies = [
49004927
"windows-sys 0.59.0",
49014928
]
49024929

4930+
[[package]]
4931+
name = "schemars"
4932+
version = "1.0.4"
4933+
source = "registry+https://github.com/rust-lang/crates.io-index"
4934+
checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
4935+
dependencies = [
4936+
"dyn-clone",
4937+
"ref-cast",
4938+
"schemars_derive",
4939+
"serde",
4940+
"serde_json",
4941+
]
4942+
4943+
[[package]]
4944+
name = "schemars_derive"
4945+
version = "1.0.4"
4946+
source = "registry+https://github.com/rust-lang/crates.io-index"
4947+
checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80"
4948+
dependencies = [
4949+
"proc-macro2",
4950+
"quote",
4951+
"serde_derive_internals",
4952+
"syn 2.0.106",
4953+
]
4954+
49034955
[[package]]
49044956
name = "scoped-tls"
49054957
version = "1.0.1"
@@ -4974,6 +5026,17 @@ dependencies = [
49745026
"syn 2.0.106",
49755027
]
49765028

5029+
[[package]]
5030+
name = "serde_derive_internals"
5031+
version = "0.29.1"
5032+
source = "registry+https://github.com/rust-lang/crates.io-index"
5033+
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
5034+
dependencies = [
5035+
"proc-macro2",
5036+
"quote",
5037+
"syn 2.0.106",
5038+
]
5039+
49775040
[[package]]
49785041
name = "serde_json"
49795042
version = "1.0.142"

compiler/rustc_codegen_ssa/src/back/command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl Command {
109109
}
110110
Program::Lld(ref p, flavor) => {
111111
let mut c = process::Command::new(p);
112-
c.arg("-flavor").arg(flavor.as_str());
112+
c.arg("-flavor").arg(flavor.desc());
113113
c
114114
}
115115
};

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,10 @@ fn print_crate_info(
668668
TargetSpecJson => {
669669
println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
670670
}
671+
TargetSpecJsonSchema => {
672+
let schema = rustc_target::spec::json_schema();
673+
println_info!("{}", serde_json::to_string_pretty(&schema).unwrap());
674+
}
671675
AllTargetSpecsJson => {
672676
let mut targets = BTreeMap::new();
673677
for name in rustc_target::spec::TARGETS {

compiler/rustc_session/src/config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
7070
("target-libdir", PrintKind::TargetLibdir),
7171
("target-list", PrintKind::TargetList),
7272
("target-spec-json", PrintKind::TargetSpecJson),
73+
("target-spec-json-schema", PrintKind::TargetSpecJsonSchema),
7374
("tls-models", PrintKind::TlsModels),
7475
// tidy-alphabetical-end
7576
];
@@ -1043,6 +1044,7 @@ pub enum PrintKind {
10431044
TargetLibdir,
10441045
TargetList,
10451046
TargetSpecJson,
1047+
TargetSpecJsonSchema,
10461048
TlsModels,
10471049
// tidy-alphabetical-end
10481050
}
@@ -2323,7 +2325,8 @@ fn is_print_request_stable(print_kind: PrintKind) -> bool {
23232325
| PrintKind::CheckCfg
23242326
| PrintKind::CrateRootLintLevels
23252327
| PrintKind::SupportedCrateTypes
2326-
| PrintKind::TargetSpecJson => false,
2328+
| PrintKind::TargetSpecJson
2329+
| PrintKind::TargetSpecJsonSchema => false,
23272330
_ => true,
23282331
}
23292332
}

compiler/rustc_target/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
1414
rustc_macros = { path = "../rustc_macros" }
1515
rustc_serialize = { path = "../rustc_serialize" }
1616
rustc_span = { path = "../rustc_span" }
17+
schemars = "1.0.4"
1718
serde = "1.0.219"
1819
serde_derive = "1.0.219"
1920
serde_json = "1.0.59"

compiler/rustc_target/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ macro_rules! target_spec_enum {
8686
) => {
8787
$( #[$attr] )*
8888
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
89+
#[derive(schemars::JsonSchema)]
8990
pub enum $name {
9091
$(
9192
$( #[$variant_attr] )*
93+
#[serde(rename = $string)] // for JSON schema generation only
9294
$variant,
9395
)*
9496
}

compiler/rustc_target/src/spec/json.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,12 +408,12 @@ impl ToJson for Target {
408408
}
409409
}
410410

411-
#[derive(serde_derive::Deserialize)]
411+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
412412
struct LinkSelfContainedComponentsWrapper {
413413
components: Vec<LinkSelfContainedComponents>,
414414
}
415415

416-
#[derive(serde_derive::Deserialize)]
416+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
417417
#[serde(untagged)]
418418
enum TargetFamiliesJson {
419419
Array(StaticCow<[StaticCow<str>]>),
@@ -429,6 +429,18 @@ impl FromStr for EndianWrapper {
429429
}
430430
}
431431
crate::json::serde_deserialize_from_str!(EndianWrapper);
432+
impl schemars::JsonSchema for EndianWrapper {
433+
fn schema_name() -> std::borrow::Cow<'static, str> {
434+
"Endian".into()
435+
}
436+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
437+
schemars::json_schema! ({
438+
"type": "string",
439+
"enum": ["big", "little"]
440+
})
441+
.into()
442+
}
443+
}
432444

433445
/// `ExternAbi` is in `rustc_abi`, which doesn't have access to the macro and serde.
434446
struct ExternAbiWrapper(rustc_abi::ExternAbi);
@@ -441,16 +453,30 @@ impl FromStr for ExternAbiWrapper {
441453
}
442454
}
443455
crate::json::serde_deserialize_from_str!(ExternAbiWrapper);
456+
impl schemars::JsonSchema for ExternAbiWrapper {
457+
fn schema_name() -> std::borrow::Cow<'static, str> {
458+
"ExternAbi".into()
459+
}
460+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
461+
let all =
462+
rustc_abi::ExternAbi::ALL_VARIANTS.iter().map(|abi| abi.as_str()).collect::<Vec<_>>();
463+
schemars::json_schema! ({
464+
"type": "string",
465+
"enum": all,
466+
})
467+
.into()
468+
}
469+
}
444470

445-
#[derive(serde_derive::Deserialize)]
471+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
446472
struct TargetSpecJsonMetadata {
447473
description: Option<StaticCow<str>>,
448474
tier: Option<u64>,
449475
host_tools: Option<bool>,
450476
std: Option<bool>,
451477
}
452478

453-
#[derive(serde_derive::Deserialize)]
479+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
454480
#[serde(rename_all = "kebab-case")]
455481
// Ensure that all unexpected fields get turned into errors.
456482
// This helps users stay up to date when the schema changes instead of silently
@@ -593,3 +619,7 @@ struct TargetSpecJson {
593619
supports_xray: Option<bool>,
594620
entry_abi: Option<ExternAbiWrapper>,
595621
}
622+
623+
pub fn json_schema() -> schemars::Schema {
624+
schemars::schema_for!(TargetSpecJson)
625+
}

compiler/rustc_target/src/spec/mod.rs

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ mod json;
7070
pub use abi_map::{AbiMap, AbiMapping};
7171
pub use base::apple;
7272
pub use base::avr::ef_avr_arch;
73+
pub use json::json_schema;
7374

7475
/// Linker is called through a C/C++ compiler.
7576
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -523,6 +524,20 @@ linker_flavor_cli_impls! {
523524
}
524525

525526
crate::json::serde_deserialize_from_str!(LinkerFlavorCli);
527+
impl schemars::JsonSchema for LinkerFlavorCli {
528+
fn schema_name() -> std::borrow::Cow<'static, str> {
529+
"LinkerFlavor".into()
530+
}
531+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
532+
let all: Vec<&'static str> =
533+
Self::all().iter().map(|flavor| flavor.desc()).collect::<Vec<_>>();
534+
schemars::json_schema! ({
535+
"type": "string",
536+
"enum": all
537+
})
538+
.into()
539+
}
540+
}
526541

527542
impl ToJson for LinkerFlavorCli {
528543
fn to_json(&self) -> Json {
@@ -576,6 +591,18 @@ impl FromStr for LinkSelfContainedDefault {
576591
}
577592

578593
crate::json::serde_deserialize_from_str!(LinkSelfContainedDefault);
594+
impl schemars::JsonSchema for LinkSelfContainedDefault {
595+
fn schema_name() -> std::borrow::Cow<'static, str> {
596+
"LinkSelfContainedDefault".into()
597+
}
598+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
599+
schemars::json_schema! ({
600+
"type": "string",
601+
"enum": ["false", "true", "wasm", "musl", "mingw"]
602+
})
603+
.into()
604+
}
605+
}
579606

580607
impl ToJson for LinkSelfContainedDefault {
581608
fn to_json(&self) -> Json {
@@ -708,6 +735,20 @@ impl FromStr for LinkSelfContainedComponents {
708735
}
709736

710737
crate::json::serde_deserialize_from_str!(LinkSelfContainedComponents);
738+
impl schemars::JsonSchema for LinkSelfContainedComponents {
739+
fn schema_name() -> std::borrow::Cow<'static, str> {
740+
"LinkSelfContainedComponents".into()
741+
}
742+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
743+
let all =
744+
Self::all_components().iter().map(|component| component.as_str()).collect::<Vec<_>>();
745+
schemars::json_schema! ({
746+
"type": "string",
747+
"enum": all,
748+
})
749+
.into()
750+
}
751+
}
711752

712753
impl ToJson for LinkSelfContainedComponents {
713754
fn to_json(&self) -> Json {
@@ -846,7 +887,6 @@ crate::target_spec_enum! {
846887
parse_error_type = "symbol visibility";
847888
}
848889

849-
850890
#[derive(Clone, Debug, PartialEq, Hash)]
851891
pub enum SmallDataThresholdSupport {
852892
None,
@@ -874,6 +914,18 @@ impl FromStr for SmallDataThresholdSupport {
874914
}
875915

876916
crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
917+
impl schemars::JsonSchema for SmallDataThresholdSupport {
918+
fn schema_name() -> std::borrow::Cow<'static, str> {
919+
"SmallDataThresholdSupport".into()
920+
}
921+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
922+
schemars::json_schema! ({
923+
"type": "string",
924+
"pattern": r#"^none|default-for-arch|llvm-module-flag=.+|llvm-arg=.+$"#,
925+
})
926+
.into()
927+
}
928+
}
877929

878930
impl ToJson for SmallDataThresholdSupport {
879931
fn to_json(&self) -> Value {
@@ -1074,7 +1126,7 @@ crate::target_spec_enum! {
10741126

10751127
into_diag_arg_using_display!(SplitDebuginfo);
10761128

1077-
#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize)]
1129+
#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize, schemars::JsonSchema)]
10781130
#[serde(tag = "kind")]
10791131
#[serde(rename_all = "kebab-case")]
10801132
pub enum StackProbeType {
@@ -1235,6 +1287,19 @@ impl FromStr for SanitizerSet {
12351287
}
12361288

12371289
crate::json::serde_deserialize_from_str!(SanitizerSet);
1290+
impl schemars::JsonSchema for SanitizerSet {
1291+
fn schema_name() -> std::borrow::Cow<'static, str> {
1292+
"SanitizerSet".into()
1293+
}
1294+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1295+
let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1296+
schemars::json_schema! ({
1297+
"type": "string",
1298+
"enum": all,
1299+
})
1300+
.into()
1301+
}
1302+
}
12381303

12391304
impl ToJson for SanitizerSet {
12401305
fn to_json(&self) -> Json {
@@ -1328,7 +1393,6 @@ impl BinaryFormat {
13281393
}
13291394
}
13301395

1331-
13321396
impl ToJson for Align {
13331397
fn to_json(&self) -> Json {
13341398
self.bits().to_json()

0 commit comments

Comments
 (0)