]> git.proxmox.com Git - cargo.git/blame - tests/testsuite/profile_config.rs
Add named config profiles.
[cargo.git] / tests / testsuite / profile_config.rs
CommitLineData
83571aee
EH
1//! Tests for profiles defined in config files.
2
77ee608d 3use cargo_test_support::paths::CargoPathExt;
61fb34b0 4use cargo_test_support::{basic_lib_manifest, paths, project};
2f7b5225 5
0e0d9688 6#[cargo_test]
2f7b5225 7fn profile_config_gated() {
7fe2fbc8 8 let p = project()
2f7b5225
EH
9 .file("Cargo.toml", &basic_lib_manifest("foo"))
10 .file("src/lib.rs", "")
11 .file(
12 ".cargo/config",
13 r#"
14 [profile.dev]
15 debug = 1
16 "#,
fecb7246
AC
17 )
18 .build();
2f7b5225 19
85984a87
DW
20 p.cargo("build -v")
21 .with_stderr_contains(
22 "\
77ee608d
EH
23[WARNING] config profiles require the `-Z config-profile` command-line option \
24 (found profile `dev` in [..]/foo/.cargo/config)
2f7b5225 25",
fecb7246
AC
26 )
27 .with_stderr_contains("[..]-C debuginfo=2[..]")
85984a87 28 .run();
2f7b5225
EH
29}
30
77ee608d
EH
31#[cargo_test]
32fn named_profile_gated() {
33 // Named profile in config requires enabling in Cargo.toml.
34 let p = project()
35 .file("src/lib.rs", "")
36 .file(
37 ".cargo/config",
38 r#"
39 [profile.foo]
40 inherits = 'dev'
41 opt-level = 1
42 "#,
43 )
44 .build();
45 p.cargo("build --profile foo -Zunstable-options -Zconfig-profile")
46 .masquerade_as_nightly_cargo()
47 .with_stderr(
48 "\
49[ERROR] config profile `foo` is not valid (defined in `[..]/foo/.cargo/config`)
50
51Caused by:
52 feature `named-profiles` is required
53
54consider adding `cargo-features = [\"named-profiles\"]` to the manifest
55",
56 )
57 .with_status(101)
58 .run();
59}
60
0e0d9688 61#[cargo_test]
2f7b5225 62fn profile_config_validate_warnings() {
7fe2fbc8 63 let p = project()
dda81d31 64 .file("Cargo.toml", &basic_lib_manifest("foo"))
fecb7246 65 .file("src/lib.rs", "")
2f7b5225
EH
66 .file(
67 ".cargo/config",
68 r#"
69 [profile.test]
70 opt-level = 3
71
72 [profile.asdf]
73 opt-level = 3
74
75 [profile.dev]
76 bad-key = true
77
78 [profile.dev.build-override]
79 bad-key-bo = true
80
fcfe0b89 81 [profile.dev.package.bar]
2f7b5225
EH
82 bad-key-bar = true
83 "#,
fecb7246
AC
84 )
85 .build();
2f7b5225 86
85984a87
DW
87 p.cargo("build -Z config-profile")
88 .masquerade_as_nightly_cargo()
89 .with_stderr_unordered(
84a80d8f 90 "\
91015d52
EH
91[WARNING] unused config key `profile.dev.bad-key` in `[..].cargo/config`
92[WARNING] unused config key `profile.dev.package.bar.bad-key-bar` in `[..].cargo/config`
93[WARNING] unused config key `profile.dev.build-override.bad-key-bo` in `[..].cargo/config`
84a80d8f
EH
94[COMPILING] foo [..]
95[FINISHED] [..]
2f7b5225 96",
fecb7246
AC
97 )
98 .run();
2f7b5225
EH
99}
100
0e0d9688 101#[cargo_test]
2f7b5225 102fn profile_config_error_paths() {
77ee608d 103 // Errors in config show where the error is located.
7fe2fbc8 104 let p = project()
2f7b5225
EH
105 .file("Cargo.toml", &basic_lib_manifest("foo"))
106 .file("src/lib.rs", "")
107 .file(
108 ".cargo/config",
109 r#"
110 [profile.dev]
111 opt-level = 3
112 "#,
fecb7246
AC
113 )
114 .file(
2f7b5225
EH
115 paths::home().join(".cargo/config"),
116 r#"
117 [profile.dev]
118 rpath = "foo"
119 "#,
fecb7246
AC
120 )
121 .build();
2f7b5225 122
85984a87
DW
123 p.cargo("build -Z config-profile")
124 .masquerade_as_nightly_cargo()
125 .with_status(101)
126 .with_stderr(
2f7b5225 127 "\
77ee608d
EH
128[ERROR] error in [..]/foo/.cargo/config: \
129 could not load config key `profile.dev`: \
130 error in [..]/home/.cargo/config: \
131 `profile.dev.rpath` expected true/false, but found a string
2f7b5225 132",
fecb7246
AC
133 )
134 .run();
2f7b5225
EH
135}
136
0e0d9688 137#[cargo_test]
2f7b5225 138fn profile_config_validate_errors() {
7fe2fbc8 139 let p = project()
dda81d31 140 .file("Cargo.toml", &basic_lib_manifest("foo"))
fecb7246 141 .file("src/lib.rs", "")
2f7b5225
EH
142 .file(
143 ".cargo/config",
144 r#"
fcfe0b89 145 [profile.dev.package.foo]
2f7b5225
EH
146 panic = "abort"
147 "#,
fecb7246
AC
148 )
149 .build();
2f7b5225 150
85984a87
DW
151 p.cargo("build -Z config-profile")
152 .masquerade_as_nightly_cargo()
153 .with_status(101)
154 .with_stderr(
2f7b5225 155 "\
77ee608d 156[ERROR] config profile `dev` is not valid (defined in `[..]/foo/.cargo/config`)
2f7b5225
EH
157
158Caused by:
fcfe0b89 159 `panic` may not be specified in a `package` profile
2f7b5225 160",
fecb7246
AC
161 )
162 .run();
2f7b5225
EH
163}
164
0e0d9688 165#[cargo_test]
2f7b5225 166fn profile_config_syntax_errors() {
7fe2fbc8 167 let p = project()
2f7b5225
EH
168 .file("Cargo.toml", &basic_lib_manifest("foo"))
169 .file("src/lib.rs", "")
170 .file(
171 ".cargo/config",
172 r#"
173 [profile.dev]
174 codegen-units = "foo"
175 "#,
fecb7246
AC
176 )
177 .build();
2f7b5225 178
85984a87
DW
179 p.cargo("build -Z config-profile")
180 .masquerade_as_nightly_cargo()
181 .with_status(101)
182 .with_stderr(
2f7b5225 183 "\
77ee608d
EH
184[ERROR] error in [..]/foo/.cargo/config: \
185 could not load config key `profile.dev`: \
186 error in [..]/foo/.cargo/config: \
187 `profile.dev.codegen-units` expected an integer, but found a string
2f7b5225 188",
fecb7246
AC
189 )
190 .run();
2f7b5225
EH
191}
192
0e0d9688 193#[cargo_test]
2f7b5225 194fn profile_config_override_spec_multiple() {
7fe2fbc8 195 let p = project()
2f7b5225
EH
196 .file(
197 "Cargo.toml",
198 r#"
2f7b5225
EH
199 [package]
200 name = "foo"
201 version = "0.0.1"
202
203 [dependencies]
204 bar = { path = "bar" }
205 "#,
fecb7246
AC
206 )
207 .file(
2f7b5225
EH
208 ".cargo/config",
209 r#"
fcfe0b89 210 [profile.dev.package.bar]
2f7b5225
EH
211 opt-level = 3
212
fcfe0b89 213 [profile.dev.package."bar:0.5.0"]
2f7b5225
EH
214 opt-level = 3
215 "#,
fecb7246
AC
216 )
217 .file("src/lib.rs", "")
dda81d31 218 .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
fecb7246 219 .file("bar/src/lib.rs", "")
2f7b5225
EH
220 .build();
221
222 // Unfortunately this doesn't tell you which file, hopefully it's not too
223 // much of a problem.
85984a87
DW
224 p.cargo("build -v -Z config-profile")
225 .masquerade_as_nightly_cargo()
226 .with_status(101)
227 .with_stderr(
2f7b5225 228 "\
fcfe0b89
EH
229[ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([..])`
230found package specs: bar, bar:0.5.0",
fecb7246
AC
231 )
232 .run();
2f7b5225
EH
233}
234
0e0d9688 235#[cargo_test]
2f7b5225
EH
236fn profile_config_all_options() {
237 // Ensure all profile options are supported.
7fe2fbc8 238 let p = project()
2b6fd6f0 239 .file("src/main.rs", "fn main() {}")
2f7b5225
EH
240 .file(
241 ".cargo/config",
242 r#"
243 [profile.release]
244 opt-level = 1
245 debug = true
246 debug-assertions = true
247 overflow-checks = false
248 rpath = true
249 lto = true
250 codegen-units = 2
251 panic = "abort"
252 incremental = true
253 "#,
fecb7246
AC
254 )
255 .build();
2f7b5225 256
85984a87
DW
257 p.cargo("build --release -v -Z config-profile")
258 .masquerade_as_nightly_cargo()
2b6fd6f0 259 .env_remove("CARGO_INCREMENTAL")
85984a87 260 .with_stderr(
2f7b5225
EH
261 "\
262[COMPILING] foo [..]
263[RUNNING] `rustc --crate-name foo [..] \
264 -C opt-level=1 \
265 -C panic=abort \
2b6fd6f0 266 -C lto \
2f7b5225
EH
267 -C codegen-units=2 \
268 -C debuginfo=2 \
269 -C debug-assertions=on \
270 -C overflow-checks=off [..]\
2b6fd6f0
EH
271 -C rpath [..]\
272 -C incremental=[..]
2f7b5225
EH
273[FINISHED] release [optimized + debuginfo] [..]
274",
fecb7246
AC
275 )
276 .run();
2f7b5225
EH
277}
278
0e0d9688 279#[cargo_test]
2f7b5225
EH
280fn profile_config_override_precedence() {
281 // Config values take precedence over manifest values.
7fe2fbc8 282 let p = project()
2f7b5225
EH
283 .file(
284 "Cargo.toml",
285 r#"
2f7b5225
EH
286 [package]
287 name = "foo"
288 version = "0.0.1"
289
290 [dependencies]
291 bar = {path = "bar"}
292
293 [profile.dev]
294 codegen-units = 2
295
fcfe0b89 296 [profile.dev.package.bar]
2f7b5225
EH
297 opt-level = 3
298 "#,
fecb7246
AC
299 )
300 .file("src/lib.rs", "")
dda81d31 301 .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
fecb7246 302 .file("bar/src/lib.rs", "")
2f7b5225
EH
303 .file(
304 ".cargo/config",
305 r#"
fcfe0b89 306 [profile.dev.package.bar]
2f7b5225
EH
307 opt-level = 2
308 "#,
fecb7246
AC
309 )
310 .build();
2f7b5225 311
85984a87
DW
312 p.cargo("build -v -Z config-profile")
313 .masquerade_as_nightly_cargo()
314 .with_stderr(
2f7b5225
EH
315 "\
316[COMPILING] bar [..]
317[RUNNING] `rustc --crate-name bar [..] -C opt-level=2 -C codegen-units=2 [..]
318[COMPILING] foo [..]
319[RUNNING] `rustc --crate-name foo [..]-C codegen-units=2 [..]
320[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
fecb7246
AC
321 )
322 .run();
2f7b5225
EH
323}
324
0e0d9688 325#[cargo_test]
2f7b5225 326fn profile_config_no_warn_unknown_override() {
7fe2fbc8 327 let p = project()
dda81d31 328 .file("Cargo.toml", &basic_lib_manifest("foo"))
fecb7246 329 .file("src/lib.rs", "")
2f7b5225
EH
330 .file(
331 ".cargo/config",
332 r#"
fcfe0b89 333 [profile.dev.package.bar]
2f7b5225
EH
334 codegen-units = 4
335 "#,
fecb7246
AC
336 )
337 .build();
2f7b5225 338
85984a87
DW
339 p.cargo("build -Z config-profile")
340 .masquerade_as_nightly_cargo()
341 .with_stderr_does_not_contain("[..]warning[..]")
342 .run();
2f7b5225
EH
343}
344
0e0d9688 345#[cargo_test]
2f7b5225 346fn profile_config_mixed_types() {
7fe2fbc8 347 let p = project()
2f7b5225
EH
348 .file("Cargo.toml", &basic_lib_manifest("foo"))
349 .file("src/lib.rs", "")
350 .file(
351 ".cargo/config",
352 r#"
353 [profile.dev]
354 opt-level = 3
355 "#,
fecb7246
AC
356 )
357 .file(
2f7b5225
EH
358 paths::home().join(".cargo/config"),
359 r#"
360 [profile.dev]
361 opt-level = 's'
362 "#,
fecb7246
AC
363 )
364 .build();
2f7b5225 365
85984a87
DW
366 p.cargo("build -v -Z config-profile")
367 .masquerade_as_nightly_cargo()
368 .with_stderr_contains("[..]-C opt-level=3 [..]")
369 .run();
2f7b5225 370}
77ee608d
EH
371
372#[cargo_test]
373fn named_config_profile() {
374 // Exercises config named profies.
375 // foo -> middle -> bar -> dev
376 // middle exists in Cargo.toml, the others in .cargo/config
377 use super::config::ConfigBuilder;
378 use cargo::core::compiler::CompileMode;
379 use cargo::core::enable_nightly_features;
380 use cargo::core::features::Features;
381 use cargo::core::profiles::{Profiles, UnitFor};
382 use cargo::core::{InternedString, PackageId};
383 use cargo::util::toml::TomlProfiles;
384 use std::fs;
385 enable_nightly_features();
386 paths::root().join(".cargo").mkdir_p();
387 fs::write(
388 paths::root().join(".cargo/config"),
389 r#"
390 [profile.foo]
391 inherits = "middle"
392 codegen-units = 2
393 [profile.foo.build-override]
394 codegen-units = 6
395 [profile.foo.package.dep]
396 codegen-units = 7
397
398 [profile.middle]
399 inherits = "bar"
400 codegen-units = 3
401
402 [profile.bar]
403 inherits = "dev"
404 codegen-units = 4
405 debug = 1
406 "#,
407 )
408 .unwrap();
409 let config = ConfigBuilder::new().unstable_flag("config-profile").build();
410 let mut warnings = Vec::new();
411 let features = Features::new(&["named-profiles".to_string()], &mut warnings).unwrap();
412 assert_eq!(warnings.len(), 0);
413 let profile_name = InternedString::new("foo");
414 let toml = r#"
415 [profile.middle]
416 inherits = "bar"
417 codegen-units = 1
418 opt-level = 1
419 [profile.middle.package.dep]
420 overflow-checks = false
421
422 [profile.foo.build-override]
423 codegen-units = 5
424 debug-assertions = false
425 [profile.foo.package.dep]
426 codegen-units = 8
427 "#;
428 #[derive(serde::Deserialize)]
429 struct TomlManifest {
430 profile: Option<TomlProfiles>,
431 }
432 let manifest: TomlManifest = toml::from_str(toml).unwrap();
433 let profiles =
434 Profiles::new(manifest.profile.as_ref(), &config, profile_name, &features).unwrap();
435
436 let crates_io = cargo::core::source::SourceId::crates_io(&config).unwrap();
437 let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
438 let dep_pkg = PackageId::new("dep", "0.1.0", crates_io).unwrap();
439
440 // normal package
441 let p = profiles.get_profile(a_pkg, true, UnitFor::new_normal(), CompileMode::Build);
442 assert_eq!(p.name, "foo");
443 assert_eq!(p.codegen_units, Some(2)); // "foo" from config
444 assert_eq!(p.opt_level, "1"); // "middle" from manifest
445 assert_eq!(p.debuginfo, Some(1)); // "bar" from config
446 assert_eq!(p.debug_assertions, true); // "dev" built-in (ignore build-override)
447 assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
448
449 // build-override
450 let bo = profiles.get_profile(a_pkg, true, UnitFor::new_build(), CompileMode::Build);
451 assert_eq!(bo.name, "foo");
452 assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
453 assert_eq!(bo.opt_level, "1"); // SAME as normal
454 assert_eq!(bo.debuginfo, Some(1)); // SAME as normal
455 assert_eq!(bo.debug_assertions, false); // "foo" build override from manifest
456 assert_eq!(bo.overflow_checks, true); // SAME as normal
457
458 // package overrides
459 let po = profiles.get_profile(dep_pkg, false, UnitFor::new_normal(), CompileMode::Build);
460 assert_eq!(po.name, "foo");
461 assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
462 assert_eq!(po.opt_level, "1"); // SAME as normal
463 assert_eq!(po.debuginfo, Some(1)); // SAME as normal
464 assert_eq!(po.debug_assertions, true); // SAME as normal
465 assert_eq!(po.overflow_checks, false); // "middle" package override from manifest
466}
467
468#[cargo_test]
469fn named_env_profile() {
470 // Environment variables used to define a named profile.
471 let p = project()
472 .file(
473 "Cargo.toml",
474 r#"
475 cargo-features = ["named-profiles"]
476 [package]
477 name = "foo"
478 version = "0.1.0"
479 "#,
480 )
481 .file("src/lib.rs", "")
482 .build();
483
484 p.cargo("build -v -Zconfig-profile -Zunstable-options --profile=other")
485 .masquerade_as_nightly_cargo()
486 .env("CARGO_PROFILE_OTHER_CODEGEN_UNITS", "1")
487 .env("CARGO_PROFILE_OTHER_INHERITS", "dev")
488 .with_stderr_contains("[..]-C codegen-units=1 [..]")
489 .run();
490}