rustc_target/spec/
json.rs

1use std::collections::BTreeMap;
2use std::str::FromStr;
3
4use rustc_abi::{Align, AlignFromBytesError};
5
6use super::crt_objects::CrtObjects;
7use super::{
8    Abi, Arch, BinaryFormat, CodeModel, DebuginfoKind, Env, FloatAbi, FramePointer, LinkArgsCli,
9    LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFlavorCli, LldFlavor,
10    MergeFunctions, Os, PanicStrategy, RelocModel, RelroLevel, RustcAbi, SanitizerSet,
11    SmallDataThresholdSupport, SplitDebuginfo, StackProbeType, StaticCow, SymbolVisibility, Target,
12    TargetKind, TargetOptions, TargetWarnings, TlsModel,
13};
14use crate::json::{Json, ToJson};
15use crate::spec::AbiMap;
16
17impl Target {
18    /// Loads a target descriptor from a JSON object.
19    pub fn from_json(json: &str) -> Result<(Target, TargetWarnings), String> {
20        let json_deserializer = &mut serde_json::Deserializer::from_str(json);
21
22        let json: TargetSpecJson =
23            serde_path_to_error::deserialize(json_deserializer).map_err(|err| err.to_string())?;
24
25        let mut base = Target {
26            llvm_target: json.llvm_target,
27            metadata: Default::default(),
28            pointer_width: json.target_pointer_width,
29            data_layout: json.data_layout,
30            arch: json.arch,
31            options: Default::default(),
32        };
33
34        // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid.
35        // That's okay for now, the only use of this is when generating docs, which we don't do for
36        // custom targets.
37        if let Some(metadata) = json.metadata {
38            base.metadata.description = metadata.description;
39            base.metadata.tier = metadata.tier.filter(|tier| (1..=3).contains(tier));
40            base.metadata.host_tools = metadata.host_tools;
41            base.metadata.std = metadata.std;
42        }
43
44        let alignment_error = |field_name: &str, error: AlignFromBytesError| -> String {
45            let msg = match error {
46                AlignFromBytesError::NotPowerOfTwo(_) => "not a power of 2 number of bytes",
47                AlignFromBytesError::TooLarge(_) => "too large",
48            };
49            format!("`{}` bits is not a valid value for {field_name}: {msg}", error.align() * 8)
50        };
51
52        macro_rules! forward {
53            ($name:ident) => {
54                if let Some($name) = json.$name {
55                    base.$name = $name;
56                }
57            };
58        }
59        macro_rules! forward_opt {
60            ($name:ident) => {
61                if let Some($name) = json.$name {
62                    base.$name = Some($name);
63                }
64            };
65        }
66
67        if let Some(target_endian) = json.target_endian {
68            base.endian = target_endian.0;
69        }
70
71        forward!(frame_pointer);
72        forward!(c_int_width);
73        forward_opt!(c_enum_min_bits); // if None, matches c_int_width
74        forward!(os);
75        forward!(env);
76        forward!(abi);
77        forward!(vendor);
78        forward_opt!(linker);
79        forward!(linker_flavor_json);
80        forward!(lld_flavor_json);
81        forward!(linker_is_gnu_json);
82        forward!(pre_link_objects);
83        forward!(post_link_objects);
84        forward!(pre_link_objects_self_contained);
85        forward!(post_link_objects_self_contained);
86
87        // Deserializes the backwards-compatible variants of `-Clink-self-contained`
88        if let Some(link_self_contained) = json.link_self_contained_backwards_compatible {
89            base.link_self_contained = link_self_contained;
90        }
91        // Deserializes the components variant of `-Clink-self-contained`
92        if let Some(link_self_contained) = json.link_self_contained {
93            let components = link_self_contained
94                .components
95                .into_iter()
96                .fold(LinkSelfContainedComponents::empty(), |a, b| a | b);
97            base.link_self_contained = LinkSelfContainedDefault::WithComponents(components);
98        }
99
100        forward!(pre_link_args_json);
101        forward!(late_link_args_json);
102        forward!(late_link_args_dynamic_json);
103        forward!(late_link_args_static_json);
104        forward!(post_link_args_json);
105        forward_opt!(link_script);
106
107        if let Some(link_env) = json.link_env {
108            for s in link_env {
109                if let [k, v] = *s.split('=').collect::<Vec<_>>() {
110                    base.link_env.to_mut().push((k.to_string().into(), v.to_string().into()))
111                } else {
112                    return Err(format!("link-env value '{s}' must be of the pattern 'KEY=VALUE'"));
113                }
114            }
115        }
116
117        forward!(link_env_remove);
118        forward!(asm_args);
119        forward!(cpu);
120        forward!(need_explicit_cpu);
121        forward!(features);
122        forward!(dynamic_linking);
123        forward_opt!(direct_access_external_data);
124        forward!(dll_tls_export);
125        forward!(only_cdylib);
126        forward!(executables);
127        forward!(relocation_model);
128        forward_opt!(code_model);
129        forward!(tls_model);
130        forward!(disable_redzone);
131        forward!(function_sections);
132        forward!(dll_prefix);
133        forward!(dll_suffix);
134        forward!(exe_suffix);
135        forward!(staticlib_prefix);
136        forward!(staticlib_suffix);
137
138        if let Some(target_family) = json.target_family {
139            match target_family {
140                TargetFamiliesJson::Array(families) => base.families = families,
141                TargetFamiliesJson::String(family) => base.families = vec![family].into(),
142            }
143        }
144
145        forward!(abi_return_struct_as_int);
146        forward!(is_like_aix);
147        forward!(is_like_darwin);
148        forward!(is_like_solaris);
149        forward!(is_like_windows);
150        forward!(is_like_gpu);
151        forward!(is_like_msvc);
152        forward!(is_like_wasm);
153        forward!(is_like_android);
154        forward!(is_like_vexos);
155        forward!(binary_format);
156        forward!(default_dwarf_version);
157        forward!(allows_weak_linkage);
158        forward!(has_rpath);
159        forward!(no_default_libraries);
160        forward!(position_independent_executables);
161        forward!(static_position_independent_executables);
162        forward!(plt_by_default);
163        forward!(relro_level);
164        forward!(archive_format);
165        forward!(allow_asm);
166        forward!(static_initializer_must_be_acyclic);
167        forward!(main_needs_argc_argv);
168        forward!(has_thread_local);
169        forward!(obj_is_bitcode);
170        forward_opt!(max_atomic_width);
171        forward_opt!(min_atomic_width);
172        forward!(atomic_cas);
173        forward!(panic_strategy);
174        forward!(crt_static_allows_dylibs);
175        forward!(crt_static_default);
176        forward!(crt_static_respected);
177        forward!(stack_probes);
178
179        if let Some(min_global_align) = json.min_global_align {
180            match Align::from_bits(min_global_align) {
181                Ok(align) => base.min_global_align = Some(align),
182                Err(e) => return Err(alignment_error("min-global-align", e)),
183            }
184        }
185
186        forward_opt!(default_codegen_units);
187        forward_opt!(default_codegen_backend);
188        forward!(trap_unreachable);
189        forward!(requires_lto);
190        forward!(singlethread);
191        forward!(no_builtins);
192        forward_opt!(default_visibility);
193        forward!(emit_debug_gdb_scripts);
194        forward!(requires_uwtable);
195        forward!(default_uwtable);
196        forward!(simd_types_indirect);
197        forward!(limit_rdylib_exports);
198        forward_opt!(override_export_symbols);
199        forward!(merge_functions);
200        forward!(mcount);
201        forward_opt!(llvm_mcount_intrinsic);
202        forward!(llvm_abiname);
203        forward_opt!(llvm_floatabi);
204        forward_opt!(rustc_abi);
205        forward!(relax_elf_relocations);
206        forward!(llvm_args);
207        forward!(use_ctors_section);
208        forward!(eh_frame_header);
209        forward!(has_thumb_interworking);
210        forward!(debuginfo_kind);
211        forward!(split_debuginfo);
212        forward!(supported_split_debuginfo);
213
214        if let Some(supported_sanitizers) = json.supported_sanitizers {
215            base.supported_sanitizers =
216                supported_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b);
217        }
218
219        if let Some(default_sanitizers) = json.default_sanitizers {
220            base.default_sanitizers =
221                default_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b);
222        }
223
224        forward!(generate_arange_section);
225        forward!(supports_stack_protector);
226        forward!(small_data_threshold_support);
227        forward!(entry_name);
228        forward!(supports_xray);
229
230        // we're going to run `update_from_cli`, but that won't change the target's AbiMap
231        // FIXME: better factor the Target definition so we enforce this on a type level
232        let abi_map = AbiMap::from_target(&base);
233        if let Some(entry_abi) = json.entry_abi {
234            base.options.entry_abi = abi_map.canonize_abi(entry_abi.0, false).unwrap();
235        }
236
237        base.update_from_cli();
238        base.check_consistency(TargetKind::Json)?;
239
240        Ok((base, TargetWarnings { unused_fields: vec![] }))
241    }
242}
243
244impl ToJson for Target {
245    fn to_json(&self) -> Json {
246        let mut d = serde_json::Map::new();
247        let default: TargetOptions = Default::default();
248        let mut target = self.clone();
249        target.update_to_cli();
250
251        macro_rules! target_val {
252            ($attr:ident) => {
253                target_val!($attr, (stringify!($attr)).replace("_", "-"))
254            };
255            ($attr:ident, $json_name:expr) => {{
256                let name = $json_name;
257                d.insert(name.into(), target.$attr.to_json());
258            }};
259        }
260
261        macro_rules! target_option_val {
262            ($attr:ident) => {{ target_option_val!($attr, (stringify!($attr)).replace("_", "-")) }};
263            ($attr:ident, $json_name:expr) => {{
264                let name = $json_name;
265                #[allow(rustc::bad_opt_access)]
266                if default.$attr != target.$attr {
267                    d.insert(name.into(), target.$attr.to_json());
268                }
269            }};
270            (link_args - $attr:ident, $json_name:expr) => {{
271                let name = $json_name;
272                if default.$attr != target.$attr {
273                    let obj = target
274                        .$attr
275                        .iter()
276                        .map(|(k, v)| (k.desc().to_string(), v.clone()))
277                        .collect::<BTreeMap<_, _>>();
278                    d.insert(name.to_string(), obj.to_json());
279                }
280            }};
281            (env - $attr:ident) => {{
282                let name = (stringify!($attr)).replace("_", "-");
283                if default.$attr != target.$attr {
284                    let obj = target
285                        .$attr
286                        .iter()
287                        .map(|&(ref k, ref v)| format!("{k}={v}"))
288                        .collect::<Vec<_>>();
289                    d.insert(name, obj.to_json());
290                }
291            }};
292        }
293
294        target_val!(llvm_target);
295        target_val!(metadata);
296        target_val!(pointer_width, "target-pointer-width");
297        target_val!(arch);
298        target_val!(data_layout);
299
300        target_option_val!(endian, "target-endian");
301        target_option_val!(c_int_width, "target-c-int-width");
302        target_option_val!(os);
303        target_option_val!(env);
304        target_option_val!(abi);
305        target_option_val!(vendor);
306        target_option_val!(linker);
307        target_option_val!(linker_flavor_json, "linker-flavor");
308        target_option_val!(lld_flavor_json, "lld-flavor");
309        target_option_val!(linker_is_gnu_json, "linker-is-gnu");
310        target_option_val!(pre_link_objects);
311        target_option_val!(post_link_objects);
312        target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback");
313        target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback");
314        target_option_val!(link_args - pre_link_args_json, "pre-link-args");
315        target_option_val!(link_args - late_link_args_json, "late-link-args");
316        target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic");
317        target_option_val!(link_args - late_link_args_static_json, "late-link-args-static");
318        target_option_val!(link_args - post_link_args_json, "post-link-args");
319        target_option_val!(link_script);
320        target_option_val!(env - link_env);
321        target_option_val!(link_env_remove);
322        target_option_val!(asm_args);
323        target_option_val!(cpu);
324        target_option_val!(need_explicit_cpu);
325        target_option_val!(features);
326        target_option_val!(dynamic_linking);
327        target_option_val!(direct_access_external_data);
328        target_option_val!(dll_tls_export);
329        target_option_val!(only_cdylib);
330        target_option_val!(executables);
331        target_option_val!(relocation_model);
332        target_option_val!(code_model);
333        target_option_val!(tls_model);
334        target_option_val!(disable_redzone);
335        target_option_val!(frame_pointer);
336        target_option_val!(function_sections);
337        target_option_val!(dll_prefix);
338        target_option_val!(dll_suffix);
339        target_option_val!(exe_suffix);
340        target_option_val!(staticlib_prefix);
341        target_option_val!(staticlib_suffix);
342        target_option_val!(families, "target-family");
343        target_option_val!(abi_return_struct_as_int);
344        target_option_val!(is_like_aix);
345        target_option_val!(is_like_darwin);
346        target_option_val!(is_like_solaris);
347        target_option_val!(is_like_windows);
348        target_option_val!(is_like_gpu);
349        target_option_val!(is_like_msvc);
350        target_option_val!(is_like_wasm);
351        target_option_val!(is_like_android);
352        target_option_val!(is_like_vexos);
353        target_option_val!(binary_format);
354        target_option_val!(default_dwarf_version);
355        target_option_val!(allows_weak_linkage);
356        target_option_val!(has_rpath);
357        target_option_val!(no_default_libraries);
358        target_option_val!(position_independent_executables);
359        target_option_val!(static_position_independent_executables);
360        target_option_val!(plt_by_default);
361        target_option_val!(relro_level);
362        target_option_val!(archive_format);
363        target_option_val!(allow_asm);
364        target_option_val!(static_initializer_must_be_acyclic);
365        target_option_val!(main_needs_argc_argv);
366        target_option_val!(has_thread_local);
367        target_option_val!(obj_is_bitcode);
368        target_option_val!(min_atomic_width);
369        target_option_val!(max_atomic_width);
370        target_option_val!(atomic_cas);
371        target_option_val!(panic_strategy);
372        target_option_val!(crt_static_allows_dylibs);
373        target_option_val!(crt_static_default);
374        target_option_val!(crt_static_respected);
375        target_option_val!(stack_probes);
376        target_option_val!(min_global_align);
377        target_option_val!(default_codegen_units);
378        target_option_val!(default_codegen_backend);
379        target_option_val!(trap_unreachable);
380        target_option_val!(requires_lto);
381        target_option_val!(singlethread);
382        target_option_val!(no_builtins);
383        target_option_val!(default_visibility);
384        target_option_val!(emit_debug_gdb_scripts);
385        target_option_val!(requires_uwtable);
386        target_option_val!(default_uwtable);
387        target_option_val!(simd_types_indirect);
388        target_option_val!(limit_rdylib_exports);
389        target_option_val!(override_export_symbols);
390        target_option_val!(merge_functions);
391        target_option_val!(mcount, "target-mcount");
392        target_option_val!(llvm_mcount_intrinsic);
393        target_option_val!(llvm_abiname);
394        target_option_val!(llvm_floatabi);
395        target_option_val!(rustc_abi);
396        target_option_val!(relax_elf_relocations);
397        target_option_val!(llvm_args);
398        target_option_val!(use_ctors_section);
399        target_option_val!(eh_frame_header);
400        target_option_val!(has_thumb_interworking);
401        target_option_val!(debuginfo_kind);
402        target_option_val!(split_debuginfo);
403        target_option_val!(supported_split_debuginfo);
404        target_option_val!(supported_sanitizers);
405        target_option_val!(default_sanitizers);
406        target_option_val!(c_enum_min_bits);
407        target_option_val!(generate_arange_section);
408        target_option_val!(supports_stack_protector);
409        target_option_val!(small_data_threshold_support);
410        target_option_val!(entry_name);
411        target_option_val!(entry_abi);
412        target_option_val!(supports_xray);
413
414        // Serializing `-Clink-self-contained` needs a dynamic key to support the
415        // backwards-compatible variants.
416        d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json());
417
418        Json::Object(d)
419    }
420}
421
422#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
423struct LinkSelfContainedComponentsWrapper {
424    components: Vec<LinkSelfContainedComponents>,
425}
426
427#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
428#[serde(untagged)]
429enum TargetFamiliesJson {
430    Array(StaticCow<[StaticCow<str>]>),
431    String(StaticCow<str>),
432}
433
434/// `Endian` is in `rustc_abi`, which doesn't have access to the macro and serde.
435struct EndianWrapper(rustc_abi::Endian);
436impl FromStr for EndianWrapper {
437    type Err = String;
438    fn from_str(s: &str) -> Result<Self, Self::Err> {
439        rustc_abi::Endian::from_str(s).map(Self)
440    }
441}
442crate::json::serde_deserialize_from_str!(EndianWrapper);
443impl schemars::JsonSchema for EndianWrapper {
444    fn schema_name() -> std::borrow::Cow<'static, str> {
445        "Endian".into()
446    }
447    fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
448        schemars::json_schema! ({
449            "type": "string",
450            "enum": ["big", "little"]
451        })
452        .into()
453    }
454}
455
456/// `ExternAbi` is in `rustc_abi`, which doesn't have access to the macro and serde.
457struct ExternAbiWrapper(rustc_abi::ExternAbi);
458impl FromStr for ExternAbiWrapper {
459    type Err = String;
460    fn from_str(s: &str) -> Result<Self, Self::Err> {
461        rustc_abi::ExternAbi::from_str(s)
462            .map(Self)
463            .map_err(|_| format!("{s} is not a valid extern ABI"))
464    }
465}
466crate::json::serde_deserialize_from_str!(ExternAbiWrapper);
467impl schemars::JsonSchema for ExternAbiWrapper {
468    fn schema_name() -> std::borrow::Cow<'static, str> {
469        "ExternAbi".into()
470    }
471    fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
472        let all =
473            rustc_abi::ExternAbi::ALL_VARIANTS.iter().map(|abi| abi.as_str()).collect::<Vec<_>>();
474        schemars::json_schema! ({
475            "type": "string",
476            "enum": all,
477        })
478        .into()
479    }
480}
481
482#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
483struct TargetSpecJsonMetadata {
484    description: Option<StaticCow<str>>,
485    tier: Option<u64>,
486    host_tools: Option<bool>,
487    std: Option<bool>,
488}
489
490#[derive(serde_derive::Deserialize, schemars::JsonSchema)]
491#[serde(rename_all = "kebab-case")]
492// Ensure that all unexpected fields get turned into errors.
493// This helps users stay up to date when the schema changes instead of silently
494// ignoring their old values.
495#[serde(deny_unknown_fields)]
496struct TargetSpecJson {
497    llvm_target: StaticCow<str>,
498    target_pointer_width: u16,
499    data_layout: StaticCow<str>,
500    arch: Arch,
501
502    metadata: Option<TargetSpecJsonMetadata>,
503
504    // options:
505    target_endian: Option<EndianWrapper>,
506    frame_pointer: Option<FramePointer>,
507    #[serde(rename = "target-c-int-width")]
508    c_int_width: Option<u16>,
509    c_enum_min_bits: Option<u64>,
510    os: Option<Os>,
511    env: Option<Env>,
512    abi: Option<Abi>,
513    vendor: Option<StaticCow<str>>,
514    linker: Option<StaticCow<str>>,
515    #[serde(rename = "linker-flavor")]
516    linker_flavor_json: Option<LinkerFlavorCli>,
517    #[serde(rename = "lld-flavor")]
518    lld_flavor_json: Option<LldFlavor>,
519    #[serde(rename = "linker-is-gnu")]
520    linker_is_gnu_json: Option<bool>,
521    #[serde(rename = "pre-link-objects")]
522    pre_link_objects: Option<CrtObjects>,
523    #[serde(rename = "post-link-objects")]
524    post_link_objects: Option<CrtObjects>,
525    #[serde(rename = "pre-link-objects-fallback")]
526    pre_link_objects_self_contained: Option<CrtObjects>,
527    #[serde(rename = "post-link-objects-fallback")]
528    post_link_objects_self_contained: Option<CrtObjects>,
529    #[serde(rename = "crt-objects-fallback")]
530    link_self_contained_backwards_compatible: Option<LinkSelfContainedDefault>,
531    link_self_contained: Option<LinkSelfContainedComponentsWrapper>,
532    #[serde(rename = "pre-link-args")]
533    pre_link_args_json: Option<LinkArgsCli>,
534    #[serde(rename = "late-link-args")]
535    late_link_args_json: Option<LinkArgsCli>,
536    #[serde(rename = "late-link-args-dynamic")]
537    late_link_args_dynamic_json: Option<LinkArgsCli>,
538    #[serde(rename = "late-link-args-static")]
539    late_link_args_static_json: Option<LinkArgsCli>,
540    #[serde(rename = "post-link-args")]
541    post_link_args_json: Option<LinkArgsCli>,
542    link_script: Option<StaticCow<str>>,
543    link_env: Option<Vec<StaticCow<str>>>,
544    link_env_remove: Option<StaticCow<[StaticCow<str>]>>,
545    asm_args: Option<StaticCow<[StaticCow<str>]>>,
546    cpu: Option<StaticCow<str>>,
547    need_explicit_cpu: Option<bool>,
548    features: Option<StaticCow<str>>,
549    dynamic_linking: Option<bool>,
550    direct_access_external_data: Option<bool>,
551    dll_tls_export: Option<bool>,
552    only_cdylib: Option<bool>,
553    executables: Option<bool>,
554    relocation_model: Option<RelocModel>,
555    code_model: Option<CodeModel>,
556    tls_model: Option<TlsModel>,
557    disable_redzone: Option<bool>,
558    function_sections: Option<bool>,
559    dll_prefix: Option<StaticCow<str>>,
560    dll_suffix: Option<StaticCow<str>>,
561    exe_suffix: Option<StaticCow<str>>,
562    staticlib_prefix: Option<StaticCow<str>>,
563    staticlib_suffix: Option<StaticCow<str>>,
564    target_family: Option<TargetFamiliesJson>,
565    abi_return_struct_as_int: Option<bool>,
566    is_like_aix: Option<bool>,
567    is_like_darwin: Option<bool>,
568    is_like_solaris: Option<bool>,
569    is_like_windows: Option<bool>,
570    is_like_gpu: Option<bool>,
571    is_like_msvc: Option<bool>,
572    is_like_wasm: Option<bool>,
573    is_like_android: Option<bool>,
574    is_like_vexos: Option<bool>,
575    binary_format: Option<BinaryFormat>,
576    default_dwarf_version: Option<u32>,
577    allows_weak_linkage: Option<bool>,
578    has_rpath: Option<bool>,
579    no_default_libraries: Option<bool>,
580    position_independent_executables: Option<bool>,
581    static_position_independent_executables: Option<bool>,
582    plt_by_default: Option<bool>,
583    relro_level: Option<RelroLevel>,
584    archive_format: Option<StaticCow<str>>,
585    allow_asm: Option<bool>,
586    static_initializer_must_be_acyclic: Option<bool>,
587    main_needs_argc_argv: Option<bool>,
588    has_thread_local: Option<bool>,
589    obj_is_bitcode: Option<bool>,
590    max_atomic_width: Option<u64>,
591    min_atomic_width: Option<u64>,
592    atomic_cas: Option<bool>,
593    panic_strategy: Option<PanicStrategy>,
594    crt_static_allows_dylibs: Option<bool>,
595    crt_static_default: Option<bool>,
596    crt_static_respected: Option<bool>,
597    stack_probes: Option<StackProbeType>,
598    min_global_align: Option<u64>,
599    default_codegen_units: Option<u64>,
600    default_codegen_backend: Option<StaticCow<str>>,
601    trap_unreachable: Option<bool>,
602    requires_lto: Option<bool>,
603    singlethread: Option<bool>,
604    no_builtins: Option<bool>,
605    default_visibility: Option<SymbolVisibility>,
606    emit_debug_gdb_scripts: Option<bool>,
607    requires_uwtable: Option<bool>,
608    default_uwtable: Option<bool>,
609    simd_types_indirect: Option<bool>,
610    limit_rdylib_exports: Option<bool>,
611    override_export_symbols: Option<StaticCow<[StaticCow<str>]>>,
612    merge_functions: Option<MergeFunctions>,
613    #[serde(rename = "target-mcount")]
614    mcount: Option<StaticCow<str>>,
615    llvm_mcount_intrinsic: Option<StaticCow<str>>,
616    llvm_abiname: Option<StaticCow<str>>,
617    llvm_floatabi: Option<FloatAbi>,
618    rustc_abi: Option<RustcAbi>,
619    relax_elf_relocations: Option<bool>,
620    llvm_args: Option<StaticCow<[StaticCow<str>]>>,
621    use_ctors_section: Option<bool>,
622    eh_frame_header: Option<bool>,
623    has_thumb_interworking: Option<bool>,
624    debuginfo_kind: Option<DebuginfoKind>,
625    split_debuginfo: Option<SplitDebuginfo>,
626    supported_split_debuginfo: Option<StaticCow<[SplitDebuginfo]>>,
627    supported_sanitizers: Option<Vec<SanitizerSet>>,
628    default_sanitizers: Option<Vec<SanitizerSet>>,
629    generate_arange_section: Option<bool>,
630    supports_stack_protector: Option<bool>,
631    small_data_threshold_support: Option<SmallDataThresholdSupport>,
632    entry_name: Option<StaticCow<str>>,
633    supports_xray: Option<bool>,
634    entry_abi: Option<ExternAbiWrapper>,
635}
636
637pub fn json_schema() -> schemars::Schema {
638    schemars::schema_for!(TargetSpecJson)
639}