Skip to content

Commit a07cfd1

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 ef608f1 commit a07cfd1

File tree

12 files changed

+233
-9
lines changed

12 files changed

+233
-9
lines changed

Cargo.lock

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

1136+
[[package]]
1137+
name = "dyn-clone"
1138+
version = "1.0.19"
1139+
source = "registry+https://github.com/rust-lang/crates.io-index"
1140+
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
1141+
11361142
[[package]]
11371143
name = "either"
11381144
version = "1.15.0"
@@ -3077,6 +3083,26 @@ dependencies = [
30773083
"thiserror 2.0.12",
30783084
]
30793085

3086+
[[package]]
3087+
name = "ref-cast"
3088+
version = "1.0.24"
3089+
source = "registry+https://github.com/rust-lang/crates.io-index"
3090+
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
3091+
dependencies = [
3092+
"ref-cast-impl",
3093+
]
3094+
3095+
[[package]]
3096+
name = "ref-cast-impl"
3097+
version = "1.0.24"
3098+
source = "registry+https://github.com/rust-lang/crates.io-index"
3099+
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
3100+
dependencies = [
3101+
"proc-macro2",
3102+
"quote",
3103+
"syn 2.0.104",
3104+
]
3105+
30803106
[[package]]
30813107
name = "regex"
30823108
version = "1.11.1"
@@ -4563,6 +4589,7 @@ dependencies = [
45634589
"rustc_macros",
45644590
"rustc_serialize",
45654591
"rustc_span",
4592+
"schemars",
45664593
"serde",
45674594
"serde_derive",
45684595
"serde_json",
@@ -4878,6 +4905,31 @@ dependencies = [
48784905
"windows-sys 0.59.0",
48794906
]
48804907

4908+
[[package]]
4909+
name = "schemars"
4910+
version = "1.0.4"
4911+
source = "registry+https://github.com/rust-lang/crates.io-index"
4912+
checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
4913+
dependencies = [
4914+
"dyn-clone",
4915+
"ref-cast",
4916+
"schemars_derive",
4917+
"serde",
4918+
"serde_json",
4919+
]
4920+
4921+
[[package]]
4922+
name = "schemars_derive"
4923+
version = "1.0.4"
4924+
source = "registry+https://github.com/rust-lang/crates.io-index"
4925+
checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80"
4926+
dependencies = [
4927+
"proc-macro2",
4928+
"quote",
4929+
"serde_derive_internals",
4930+
"syn 2.0.104",
4931+
]
4932+
48814933
[[package]]
48824934
name = "scoped-tls"
48834935
version = "1.0.1"
@@ -4946,6 +4998,17 @@ dependencies = [
49464998
"syn 2.0.104",
49474999
]
49485000

5001+
[[package]]
5002+
name = "serde_derive_internals"
5003+
version = "0.29.1"
5004+
source = "registry+https://github.com/rust-lang/crates.io-index"
5005+
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
5006+
dependencies = [
5007+
"proc-macro2",
5008+
"quote",
5009+
"syn 2.0.104",
5010+
]
5011+
49495012
[[package]]
49505013
name = "serde_json"
49515014
version = "1.0.141"

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
@@ -667,6 +667,10 @@ fn print_crate_info(
667667
TargetSpecJson => {
668668
println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
669669
}
670+
TargetSpecJsonSchema => {
671+
let schema = rustc_target::spec::json_schema();
672+
println_info!("{}", serde_json::to_string_pretty(&schema).unwrap());
673+
}
670674
AllTargetSpecsJson => {
671675
let mut targets = BTreeMap::new();
672676
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
@@ -69,6 +69,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
6969
("target-libdir", PrintKind::TargetLibdir),
7070
("target-list", PrintKind::TargetList),
7171
("target-spec-json", PrintKind::TargetSpecJson),
72+
("target-spec-json-schema", PrintKind::TargetSpecJsonSchema),
7273
("tls-models", PrintKind::TlsModels),
7374
// tidy-alphabetical-end
7475
];
@@ -1052,6 +1053,7 @@ pub enum PrintKind {
10521053
TargetLibdir,
10531054
TargetList,
10541055
TargetSpecJson,
1056+
TargetSpecJsonSchema,
10551057
TlsModels,
10561058
// tidy-alphabetical-end
10571059
}
@@ -2314,7 +2316,8 @@ fn is_print_request_stable(print_kind: PrintKind) -> bool {
23142316
| PrintKind::CheckCfg
23152317
| PrintKind::CrateRootLintLevels
23162318
| PrintKind::SupportedCrateTypes
2317-
| PrintKind::TargetSpecJson => false,
2319+
| PrintKind::TargetSpecJson
2320+
| PrintKind::TargetSpecJsonSchema => false,
23182321
_ => true,
23192322
}
23202323
}

compiler/rustc_target/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
1212
rustc_macros = { path = "../rustc_macros" }
1313
rustc_serialize = { path = "../rustc_serialize" }
1414
rustc_span = { path = "../rustc_span" }
15+
schemars = "1.0.4"
1516
serde = "1.0.219"
1617
serde_derive = "1.0.219"
1718
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
@@ -413,12 +413,12 @@ impl ToJson for Target {
413413
}
414414
}
415415

416-
#[derive(serde_derive::Deserialize)]
416+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
417417
struct LinkSelfContainedComponentsWrapper {
418418
components: Vec<LinkSelfContainedComponents>,
419419
}
420420

421-
#[derive(serde_derive::Deserialize)]
421+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
422422
#[serde(untagged)]
423423
enum TargetFamiliesJson {
424424
Array(StaticCow<[StaticCow<str>]>),
@@ -434,6 +434,18 @@ impl FromStr for EndianWrapper {
434434
}
435435
}
436436
crate::json::serde_deserialize_from_str!(EndianWrapper);
437+
impl schemars::JsonSchema for EndianWrapper {
438+
fn schema_name() -> std::borrow::Cow<'static, str> {
439+
"Endian".into()
440+
}
441+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
442+
schemars::json_schema! ({
443+
"type": "string",
444+
"enum": ["big", "little"]
445+
})
446+
.into()
447+
}
448+
}
437449

438450
/// `ExternAbi` is in `rustc_abi`, which doesn't have access to the macro and serde.
439451
struct ExternAbiWrapper(rustc_abi::ExternAbi);
@@ -446,16 +458,30 @@ impl FromStr for ExternAbiWrapper {
446458
}
447459
}
448460
crate::json::serde_deserialize_from_str!(ExternAbiWrapper);
461+
impl schemars::JsonSchema for ExternAbiWrapper {
462+
fn schema_name() -> std::borrow::Cow<'static, str> {
463+
"ExternAbi".into()
464+
}
465+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
466+
let all =
467+
rustc_abi::ExternAbi::ALL_VARIANTS.iter().map(|abi| abi.as_str()).collect::<Vec<_>>();
468+
schemars::json_schema! ({
469+
"type": "string",
470+
"enum": all,
471+
})
472+
.into()
473+
}
474+
}
449475

450-
#[derive(serde_derive::Deserialize)]
476+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
451477
struct TargetSpecJsonMetadata {
452478
description: Option<StaticCow<str>>,
453479
tier: Option<u64>,
454480
host_tools: Option<bool>,
455481
std: Option<bool>,
456482
}
457483

458-
#[derive(serde_derive::Deserialize)]
484+
#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
459485
#[serde(rename_all = "kebab-case")]
460486
// Ensure that all unexpected fields get turned into errors.
461487
// This helps users stay up to date when the schema changes instead of silently
@@ -598,3 +624,7 @@ struct TargetSpecJson {
598624
supports_xray: Option<bool>,
599625
entry_abi: Option<ExternAbiWrapper>,
600626
}
627+
628+
pub fn json_schema() -> schemars::Schema {
629+
schemars::schema_for!(TargetSpecJson)
630+
}

compiler/rustc_target/src/spec/mod.rs

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ mod json;
6969
pub use abi_map::{AbiMap, AbiMapping};
7070
pub use base::apple;
7171
pub use base::avr::ef_avr_arch;
72+
pub use json::json_schema;
7273

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

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

526541
impl ToJson for LinkerFlavorCli {
527542
fn to_json(&self) -> Json {
@@ -575,6 +590,18 @@ impl FromStr for LinkSelfContainedDefault {
575590
}
576591

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

579606
impl ToJson for LinkSelfContainedDefault {
580607
fn to_json(&self) -> Json {
@@ -707,6 +734,20 @@ impl FromStr for LinkSelfContainedComponents {
707734
}
708735

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

711752
impl ToJson for LinkSelfContainedComponents {
712753
fn to_json(&self) -> Json {
@@ -839,7 +880,6 @@ crate::target_spec_enum! {
839880
parse_error_type = "symbol visibility";
840881
}
841882

842-
843883
#[derive(Clone, Debug, PartialEq, Hash)]
844884
pub enum SmallDataThresholdSupport {
845885
None,
@@ -867,6 +907,17 @@ impl FromStr for SmallDataThresholdSupport {
867907
}
868908

869909
crate::json::serde_deserialize_from_str!(SmallDataThresholdSupport);
910+
impl schemars::JsonSchema for SmallDataThresholdSupport {
911+
fn schema_name() -> std::borrow::Cow<'static, str> {
912+
"SmallDataThresholdSupport".into()
913+
}
914+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
915+
schemars::json_schema! ({
916+
"type": "string",
917+
})
918+
.into()
919+
}
920+
}
870921

871922
impl ToJson for SmallDataThresholdSupport {
872923
fn to_json(&self) -> Value {
@@ -1065,7 +1116,7 @@ crate::target_spec_enum! {
10651116
parse_error_type = "split debuginfo";
10661117
}
10671118

1068-
#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize)]
1119+
#[derive(Clone, Debug, PartialEq, Eq, serde_derive::Deserialize, schemars::JsonSchema)]
10691120
#[serde(tag = "kind")]
10701121
#[serde(rename_all = "kebab-case")]
10711122
pub enum StackProbeType {
@@ -1226,6 +1277,19 @@ impl FromStr for SanitizerSet {
12261277
}
12271278

12281279
crate::json::serde_deserialize_from_str!(SanitizerSet);
1280+
impl schemars::JsonSchema for SanitizerSet {
1281+
fn schema_name() -> std::borrow::Cow<'static, str> {
1282+
"SanitizerSet".into()
1283+
}
1284+
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
1285+
let all = Self::all().iter().map(|sanitizer| sanitizer.as_str()).collect::<Vec<_>>();
1286+
schemars::json_schema! ({
1287+
"type": "string",
1288+
"enum": all,
1289+
})
1290+
.into()
1291+
}
1292+
}
12291293

12301294
impl ToJson for SanitizerSet {
12311295
fn to_json(&self) -> Json {
@@ -1317,7 +1381,6 @@ impl BinaryFormat {
13171381
}
13181382
}
13191383

1320-
13211384
impl ToJson for Align {
13221385
fn to_json(&self) -> Json {
13231386
self.bits().to_json()

0 commit comments

Comments
 (0)