1 //! Tests for custom json target specifications.
2
3 use cargo_test_support::is_nightly;
4 use cargo_test_support::{basic_manifest, project};
5 use std::fs;
6
7 const MINIMAL_LIB: &str = r#"
8 #![feature(no_core)]
9 #![feature(lang_items)]
10 #![no_core]
11
12 #[lang = "sized"]
13 pub trait Sized {
14 // Empty.
15 }
16 #[lang = "copy"]
17 pub trait Copy {
18 // Empty.
19 }
20 "#;
21
22 const SIMPLE_SPEC: &str = r#"
23 {
24 "llvm-target": "x86_64-unknown-none-gnu",
25 "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
26 "arch": "x86_64",
27 "target-endian": "little",
28 "target-pointer-width": "64",
29 "target-c-int-width": "32",
30 "os": "none",
31 "linker-flavor": "ld.lld",
32 "linker": "rust-lld",
33 "executables": true
34 }
35 "#;
36
37 #[cargo_test]
custom_target_minimal()38 fn custom_target_minimal() {
39 if !is_nightly() {
40 // Requires features no_core, lang_items
41 return;
42 }
43 let p = project()
44 .file(
45 "src/lib.rs",
46 &"
47 __MINIMAL_LIB__
48
49 pub fn foo() -> u32 {
50 42
51 }
52 "
53 .replace("__MINIMAL_LIB__", MINIMAL_LIB),
54 )
55 .file("custom-target.json", SIMPLE_SPEC)
56 .build();
57
58 p.cargo("build --lib --target custom-target.json -v").run();
59 p.cargo("build --lib --target src/../custom-target.json -v")
60 .run();
61
62 // Ensure that the correct style of flag is passed to --target with doc tests.
63 p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile")
64 .masquerade_as_nightly_cargo()
65 .with_stderr_contains("[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]")
66 .run();
67 }
68
69 #[cargo_test]
custom_target_dependency()70 fn custom_target_dependency() {
71 if !is_nightly() {
72 // Requires features no_core, lang_items, auto_traits
73 return;
74 }
75 let p = project()
76 .file(
77 "Cargo.toml",
78 r#"
79 [package]
80
81 name = "foo"
82 version = "0.0.1"
83 authors = ["author@example.com"]
84
85 [dependencies]
86 bar = { path = "bar" }
87 "#,
88 )
89 .file(
90 "src/lib.rs",
91 r#"
92 #![feature(no_core)]
93 #![feature(lang_items)]
94 #![feature(auto_traits)]
95 #![no_core]
96
97 extern crate bar;
98
99 pub fn foo() -> u32 {
100 bar::bar()
101 }
102
103 #[lang = "freeze"]
104 unsafe auto trait Freeze {}
105 "#,
106 )
107 .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1"))
108 .file(
109 "bar/src/lib.rs",
110 &"
111 __MINIMAL_LIB__
112
113 pub fn bar() -> u32 {
114 42
115 }
116 "
117 .replace("__MINIMAL_LIB__", MINIMAL_LIB),
118 )
119 .file("custom-target.json", SIMPLE_SPEC)
120 .build();
121
122 p.cargo("build --lib --target custom-target.json -v").run();
123 }
124
125 #[cargo_test]
custom_bin_target()126 fn custom_bin_target() {
127 if !is_nightly() {
128 // Requires features no_core, lang_items
129 return;
130 }
131 let p = project()
132 .file(
133 "src/main.rs",
134 &"
135 #![no_main]
136 __MINIMAL_LIB__
137 "
138 .replace("__MINIMAL_LIB__", MINIMAL_LIB),
139 )
140 .file("custom-bin-target.json", SIMPLE_SPEC)
141 .build();
142
143 p.cargo("build --target custom-bin-target.json -v").run();
144 }
145
146 #[cargo_test]
changing_spec_rebuilds()147 fn changing_spec_rebuilds() {
148 // Changing the .json file will trigger a rebuild.
149 if !is_nightly() {
150 // Requires features no_core, lang_items
151 return;
152 }
153 let p = project()
154 .file(
155 "src/lib.rs",
156 &"
157 __MINIMAL_LIB__
158
159 pub fn foo() -> u32 {
160 42
161 }
162 "
163 .replace("__MINIMAL_LIB__", MINIMAL_LIB),
164 )
165 .file("custom-target.json", SIMPLE_SPEC)
166 .build();
167
168 p.cargo("build --lib --target custom-target.json -v").run();
169 p.cargo("build --lib --target custom-target.json -v")
170 .with_stderr(
171 "\
172 [FRESH] foo [..]
173 [FINISHED] [..]
174 ",
175 )
176 .run();
177 let spec_path = p.root().join("custom-target.json");
178 let spec = fs::read_to_string(&spec_path).unwrap();
179 // Some arbitrary change that I hope is safe.
180 let spec = spec.replace('{', "{\n\"vendor\": \"unknown\",\n");
181 fs::write(&spec_path, spec).unwrap();
182 p.cargo("build --lib --target custom-target.json -v")
183 .with_stderr(
184 "\
185 [COMPILING] foo v0.0.1 [..]
186 [RUNNING] `rustc [..]
187 [FINISHED] [..]
188 ",
189 )
190 .run();
191 }
192
193 #[cargo_test]
changing_spec_relearns_crate_types()194 fn changing_spec_relearns_crate_types() {
195 // Changing the .json file will invalidate the cache of crate types.
196 if !is_nightly() {
197 // Requires features no_core, lang_items
198 return;
199 }
200 let p = project()
201 .file(
202 "Cargo.toml",
203 r#"
204 [package]
205 name = "foo"
206 version = "0.1.0"
207
208 [lib]
209 crate-type = ["cdylib"]
210 "#,
211 )
212 .file("src/lib.rs", MINIMAL_LIB)
213 .file("custom-target.json", SIMPLE_SPEC)
214 .build();
215
216 p.cargo("build --lib --target custom-target.json -v")
217 .with_status(101)
218 .with_stderr("error: cannot produce cdylib for `foo [..]")
219 .run();
220
221 // Enable dynamic linking.
222 let spec_path = p.root().join("custom-target.json");
223 let spec = fs::read_to_string(&spec_path).unwrap();
224 let spec = spec.replace('{', "{\n\"dynamic-linking\": true,\n");
225 fs::write(&spec_path, spec).unwrap();
226
227 p.cargo("build --lib --target custom-target.json -v")
228 .with_stderr(
229 "\
230 [COMPILING] foo [..]
231 [RUNNING] `rustc [..]
232 [FINISHED] [..]
233 ",
234 )
235 .run();
236 }
237