1 use cargo::core::compiler::Lto;
2 use cargo_test_support::registry::Package;
3 use cargo_test_support::{basic_manifest, project, Project};
4 use std::process::Output;
5
6 #[cargo_test]
with_deps()7 fn with_deps() {
8 Package::new("bar", "0.0.1").publish();
9
10 let p = project()
11 .file(
12 "Cargo.toml",
13 r#"
14 [package]
15 name = "test"
16 version = "0.0.0"
17
18 [dependencies]
19 bar = "*"
20
21 [profile.release]
22 lto = true
23 "#,
24 )
25 .file("src/main.rs", "extern crate bar; fn main() {}")
26 .build();
27 p.cargo("build -v --release")
28 .with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C linker-plugin-lto[..]`")
29 .with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
30 .run();
31 }
32
33 #[cargo_test]
shared_deps()34 fn shared_deps() {
35 Package::new("bar", "0.0.1").publish();
36
37 let p = project()
38 .file(
39 "Cargo.toml",
40 r#"
41 [package]
42 name = "test"
43 version = "0.0.0"
44
45 [dependencies]
46 bar = "*"
47
48 [build-dependencies]
49 bar = "*"
50
51 [profile.release]
52 lto = true
53 "#,
54 )
55 .file("build.rs", "extern crate bar; fn main() {}")
56 .file("src/main.rs", "extern crate bar; fn main() {}")
57 .build();
58 p.cargo("build -v --release")
59 .with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
60 .run();
61 }
62
63 #[cargo_test]
build_dep_not_ltod()64 fn build_dep_not_ltod() {
65 Package::new("bar", "0.0.1").publish();
66
67 let p = project()
68 .file(
69 "Cargo.toml",
70 r#"
71 [package]
72 name = "test"
73 version = "0.0.0"
74
75 [build-dependencies]
76 bar = "*"
77
78 [profile.release]
79 lto = true
80 "#,
81 )
82 .file("build.rs", "extern crate bar; fn main() {}")
83 .file("src/main.rs", "fn main() {}")
84 .build();
85 p.cargo("build -v --release")
86 .with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C embed-bitcode=no[..]`")
87 .with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
88 .run();
89 }
90
91 #[cargo_test]
complicated()92 fn complicated() {
93 Package::new("dep-shared", "0.0.1")
94 .file("src/lib.rs", "pub fn foo() {}")
95 .publish();
96 Package::new("dep-normal2", "0.0.1")
97 .file("src/lib.rs", "pub fn foo() {}")
98 .publish();
99 Package::new("dep-normal", "0.0.1")
100 .dep("dep-shared", "*")
101 .dep("dep-normal2", "*")
102 .file(
103 "src/lib.rs",
104 "
105 pub fn foo() {
106 dep_shared::foo();
107 dep_normal2::foo();
108 }
109 ",
110 )
111 .publish();
112 Package::new("dep-build2", "0.0.1")
113 .file("src/lib.rs", "pub fn foo() {}")
114 .publish();
115 Package::new("dep-build", "0.0.1")
116 .dep("dep-shared", "*")
117 .dep("dep-build2", "*")
118 .file(
119 "src/lib.rs",
120 "
121 pub fn foo() {
122 dep_shared::foo();
123 dep_build2::foo();
124 }
125 ",
126 )
127 .publish();
128 Package::new("dep-proc-macro2", "0.0.1")
129 .file("src/lib.rs", "pub fn foo() {}")
130 .publish();
131 Package::new("dep-proc-macro", "0.0.1")
132 .proc_macro(true)
133 .dep("dep-shared", "*")
134 .dep("dep-proc-macro2", "*")
135 .file(
136 "src/lib.rs",
137 "
138 extern crate proc_macro;
139 use proc_macro::TokenStream;
140
141 #[proc_macro_attribute]
142 pub fn foo(_: TokenStream, a: TokenStream) -> TokenStream {
143 dep_shared::foo();
144 dep_proc_macro2::foo();
145 a
146 }
147 ",
148 )
149 .publish();
150
151 let p = project()
152 .file(
153 "Cargo.toml",
154 r#"
155 [package]
156 name = "test"
157 version = "0.0.0"
158
159 [lib]
160 crate-type = ['cdylib', 'staticlib']
161
162 [dependencies]
163 dep-normal = "*"
164 dep-proc-macro = "*"
165
166 [build-dependencies]
167 dep-build = "*"
168
169 [profile.release]
170 lto = true
171
172 # force build deps to share an opt-level with the rest of the
173 # graph so they only get built once.
174 [profile.release.build-override]
175 opt-level = 3
176 "#,
177 )
178 .file("build.rs", "fn main() { dep_build::foo() }")
179 .file(
180 "src/main.rs",
181 "#[dep_proc_macro::foo] fn main() { dep_normal::foo() }",
182 )
183 .file(
184 "src/lib.rs",
185 "#[dep_proc_macro::foo] pub fn foo() { dep_normal::foo() }",
186 )
187 .build();
188 p.cargo("build -v --release")
189 // normal deps and their transitive dependencies do not need object
190 // code, so they should have linker-plugin-lto specified
191 .with_stderr_contains(
192 "[..]`rustc[..]--crate-name dep_normal2 [..]-C linker-plugin-lto[..]`",
193 )
194 .with_stderr_contains("[..]`rustc[..]--crate-name dep_normal [..]-C linker-plugin-lto[..]`")
195 // build dependencies and their transitive deps don't need any bitcode,
196 // so embedding should be turned off
197 .with_stderr_contains("[..]`rustc[..]--crate-name dep_build2 [..]-C embed-bitcode=no[..]`")
198 .with_stderr_contains("[..]`rustc[..]--crate-name dep_build [..]-C embed-bitcode=no[..]`")
199 .with_stderr_contains(
200 "[..]`rustc[..]--crate-name build_script_build [..]-C embed-bitcode=no[..]`",
201 )
202 // proc macro deps are the same as build deps here
203 .with_stderr_contains(
204 "[..]`rustc[..]--crate-name dep_proc_macro2 [..]-C embed-bitcode=no[..]`",
205 )
206 .with_stderr_contains(
207 "[..]`rustc[..]--crate-name dep_proc_macro [..]-C embed-bitcode=no[..]`",
208 )
209 .with_stderr_contains("[..]`rustc[..]--crate-name test [..]--crate-type bin[..]-C lto[..]`")
210 .with_stderr_contains(
211 "[..]`rustc[..]--crate-name test [..]--crate-type cdylib[..]-C lto[..]`",
212 )
213 .with_stderr_contains("[..]`rustc[..]--crate-name dep_shared [..]`")
214 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C lto[..]")
215 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C linker-plugin-lto[..]")
216 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C embed-bitcode[..]")
217 .run();
218 }
219
220 #[cargo_test]
off_in_manifest_works()221 fn off_in_manifest_works() {
222 Package::new("bar", "0.0.1")
223 .file("src/lib.rs", "pub fn foo() {}")
224 .publish();
225
226 let p = project()
227 .file(
228 "Cargo.toml",
229 r#"
230 [package]
231 name = "test"
232 version = "0.0.0"
233
234 [dependencies]
235 bar = "*"
236
237 [profile.release]
238 lto = "off"
239 "#,
240 )
241 .file("src/lib.rs", "pub fn foo() {}")
242 .file(
243 "src/main.rs",
244 "fn main() {
245 test::foo();
246 bar::foo();
247 }",
248 )
249 .build();
250 p.cargo("build -v --release")
251 .with_stderr(
252 "\
253 [UPDATING] [..]
254 [DOWNLOADING] [..]
255 [DOWNLOADED] [..]
256 [COMPILING] bar v0.0.1
257 [RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
258 [COMPILING] test [..]
259 [RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
260 [RUNNING] `rustc --crate-name test src/main.rs [..]--crate-type bin [..]-C lto=off[..]
261 [FINISHED] [..]
262 ",
263 )
264 .run();
265 }
266
267 #[cargo_test]
between_builds()268 fn between_builds() {
269 let p = project()
270 .file(
271 "Cargo.toml",
272 r#"
273 [package]
274 name = "test"
275 version = "0.0.0"
276
277 [profile.release]
278 lto = true
279 "#,
280 )
281 .file("src/lib.rs", "pub fn foo() {}")
282 .file("src/main.rs", "fn main() { test::foo() }")
283 .build();
284 p.cargo("build -v --release --lib")
285 .with_stderr(
286 "\
287 [COMPILING] test [..]
288 [RUNNING] `rustc [..]--crate-type lib[..]-C linker-plugin-lto[..]
289 [FINISHED] [..]
290 ",
291 )
292 .run();
293 p.cargo("build -v --release")
294 .with_stderr_contains(
295 "\
296 [COMPILING] test [..]
297 [RUNNING] `rustc [..]--crate-type bin[..]-C lto[..]
298 [FINISHED] [..]
299 ",
300 )
301 .run();
302 }
303
304 #[cargo_test]
test_all()305 fn test_all() {
306 let p = project()
307 .file(
308 "Cargo.toml",
309 r#"
310 [package]
311 name = "foo"
312 version = "0.0.0"
313
314 [profile.release]
315 lto = true
316 "#,
317 )
318 .file("src/main.rs", "fn main() {}")
319 .file("tests/a.rs", "")
320 .file("tests/b.rs", "")
321 .build();
322 p.cargo("test --release -v")
323 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
324 .run();
325 }
326
327 #[cargo_test]
test_all_and_bench()328 fn test_all_and_bench() {
329 let p = project()
330 .file(
331 "Cargo.toml",
332 r#"
333 [package]
334 name = "foo"
335 version = "0.0.0"
336
337 [profile.release]
338 lto = true
339 [profile.bench]
340 lto = true
341 "#,
342 )
343 .file("src/main.rs", "fn main() {}")
344 .file("tests/a.rs", "")
345 .file("tests/b.rs", "")
346 .build();
347 p.cargo("test --release -v")
348 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name a[..]-C lto[..]")
349 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name b[..]-C lto[..]")
350 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
351 .run();
352 }
353
354 /// Basic setup:
355 ///
356 /// foo v0.0.0
357 /// ├── bar v0.0.0
358 /// │ ├── registry v0.0.1
359 /// │ └── registry-shared v0.0.1
360 /// └── registry-shared v0.0.1
361 ///
362 /// Where `bar` will have the given crate types.
project_with_dep(crate_types: &str) -> Project363 fn project_with_dep(crate_types: &str) -> Project {
364 Package::new("registry", "0.0.1")
365 .file("src/lib.rs", r#"pub fn foo() { println!("registry"); }"#)
366 .publish();
367 Package::new("registry-shared", "0.0.1")
368 .file("src/lib.rs", r#"pub fn foo() { println!("shared"); }"#)
369 .publish();
370
371 project()
372 .file(
373 "Cargo.toml",
374 r#"
375 [package]
376 name = "foo"
377 version = "0.0.0"
378
379 [workspace]
380
381 [dependencies]
382 bar = { path = 'bar' }
383 registry-shared = "*"
384
385 [profile.release]
386 lto = true
387 "#,
388 )
389 .file(
390 "src/main.rs",
391 "
392 fn main() {
393 bar::foo();
394 registry_shared::foo();
395 }
396 ",
397 )
398 .file(
399 "bar/Cargo.toml",
400 &format!(
401 r#"
402 [package]
403 name = "bar"
404 version = "0.0.0"
405
406 [dependencies]
407 registry = "*"
408 registry-shared = "*"
409
410 [lib]
411 crate-type = [{}]
412 "#,
413 crate_types
414 ),
415 )
416 .file(
417 "bar/src/lib.rs",
418 r#"
419 pub fn foo() {
420 println!("bar");
421 registry::foo();
422 registry_shared::foo();
423 }
424 "#,
425 )
426 .file("tests/a.rs", "")
427 .file("bar/tests/b.rs", "")
428 .build()
429 }
430
431 /// Helper for checking which LTO behavior is used for a specific crate.
432 ///
433 /// `krate_info` is extra compiler flags used to distinguish this if the same
434 /// crate name is being built multiple times.
verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto)435 fn verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto) {
436 let stderr = std::str::from_utf8(&output.stderr).unwrap();
437 let mut matches = stderr.lines().filter(|line| {
438 line.contains("Running")
439 && line.contains(&format!("--crate-name {} ", krate))
440 && line.contains(krate_info)
441 });
442 let line = matches.next().unwrap_or_else(|| {
443 panic!(
444 "expected to find crate `{}` info: `{}`, not found in output:\n{}",
445 krate, krate_info, stderr
446 );
447 });
448 if let Some(line2) = matches.next() {
449 panic!(
450 "found multiple lines matching crate `{}` info: `{}`:\nline1:{}\nline2:{}\noutput:\n{}",
451 krate, krate_info, line, line2, stderr
452 );
453 }
454 let actual_lto = if let Some(index) = line.find("-C lto=") {
455 let s = &line[index..];
456 let end = s.find(' ').unwrap();
457 let mode = &line[index..index + end];
458 if mode == "off" {
459 Lto::Off
460 } else {
461 Lto::Run(Some(mode.into()))
462 }
463 } else if line.contains("-C lto") {
464 Lto::Run(None)
465 } else if line.contains("-C linker-plugin-lto") {
466 Lto::OnlyBitcode
467 } else if line.contains("-C embed-bitcode=no") {
468 Lto::OnlyObject
469 } else {
470 Lto::ObjectAndBitcode
471 };
472 assert_eq!(
473 actual_lto, expected_lto,
474 "did not find expected LTO in line: {}",
475 line
476 );
477 }
478
479 #[cargo_test]
cdylib_and_rlib()480 fn cdylib_and_rlib() {
481 let p = project_with_dep("'cdylib', 'rlib'");
482 let output = p.cargo("build --release -v").exec_with_output().unwrap();
483 // `registry` is ObjectAndBitcode because because it needs Object for the
484 // rlib, and Bitcode for the cdylib (which doesn't support LTO).
485 verify_lto(
486 &output,
487 "registry",
488 "--crate-type lib",
489 Lto::ObjectAndBitcode,
490 );
491 // Same as `registry`
492 verify_lto(
493 &output,
494 "registry_shared",
495 "--crate-type lib",
496 Lto::ObjectAndBitcode,
497 );
498 // Same as `registry`
499 verify_lto(
500 &output,
501 "bar",
502 "--crate-type cdylib --crate-type rlib",
503 Lto::ObjectAndBitcode,
504 );
505 verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
506 p.cargo("test --release -v")
507 .with_stderr_unordered(
508 "\
509 [FRESH] registry v0.0.1
510 [FRESH] registry-shared v0.0.1
511 [FRESH] bar v0.0.0 [..]
512 [COMPILING] foo [..]
513 [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
514 [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
515 [FINISHED] [..]
516 [RUNNING] [..]
517 [RUNNING] [..]
518 ",
519 )
520 .run();
521 p.cargo("build --release -v --manifest-path bar/Cargo.toml")
522 .with_stderr_unordered(
523 "\
524 [FRESH] registry-shared v0.0.1
525 [FRESH] registry v0.0.1
526 [FRESH] bar v0.0.0 [..]
527 [FINISHED] [..]
528 ",
529 )
530 .run();
531 p.cargo("test --release -v --manifest-path bar/Cargo.toml")
532 .with_stderr_unordered(
533 "\
534 [FRESH] registry-shared v0.0.1
535 [FRESH] registry v0.0.1
536 [COMPILING] bar [..]
537 [RUNNING] `rustc --crate-name bar [..]-C lto[..]--test[..]
538 [RUNNING] `rustc --crate-name b [..]-C lto[..]--test[..]
539 [FINISHED] [..]
540 [RUNNING] [..]target/release/deps/bar-[..]
541 [RUNNING] [..]target/release/deps/b-[..]
542 [DOCTEST] bar
543 [RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --crate-name bar --test [..]-C lto[..]
544 ",
545 )
546 .run();
547 }
548
549 #[cargo_test]
dylib()550 fn dylib() {
551 let p = project_with_dep("'dylib'");
552 let output = p.cargo("build --release -v").exec_with_output().unwrap();
553 // `registry` is OnlyObject because rustc doesn't support LTO with dylibs.
554 verify_lto(&output, "registry", "--crate-type lib", Lto::OnlyObject);
555 // `registry_shared` is both because it is needed by both bar (Object) and
556 // foo (Bitcode for LTO).
557 verify_lto(
558 &output,
559 "registry_shared",
560 "--crate-type lib",
561 Lto::ObjectAndBitcode,
562 );
563 // `bar` is OnlyObject because rustc doesn't support LTO with dylibs.
564 verify_lto(&output, "bar", "--crate-type dylib", Lto::OnlyObject);
565 // `foo` is LTO because it is a binary, and the profile specifies `lto=true`.
566 verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
567 // `cargo test` should not rebuild dependencies. It builds the test
568 // executables with `lto=true` because the tests are built with the
569 // `--release` flag.
570 p.cargo("test --release -v")
571 .with_stderr_unordered(
572 "\
573 [FRESH] registry v0.0.1
574 [FRESH] registry-shared v0.0.1
575 [FRESH] bar v0.0.0 [..]
576 [COMPILING] foo [..]
577 [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
578 [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
579 [FINISHED] [..]
580 [RUNNING] [..]
581 [RUNNING] [..]
582 ",
583 )
584 .run();
585 // Building just `bar` causes `registry-shared` to get rebuilt because it
586 // switches to OnlyObject because it is now only being used with a dylib
587 // which does not support LTO.
588 //
589 // `bar` gets rebuilt because `registry_shared` got rebuilt.
590 p.cargo("build --release -v --manifest-path bar/Cargo.toml")
591 .with_stderr_unordered(
592 "\
593 [COMPILING] registry-shared v0.0.1
594 [FRESH] registry v0.0.1
595 [RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..]
596 [COMPILING] bar [..]
597 [RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
598 [FINISHED] [..]
599 ",
600 )
601 .run();
602 // Testing just `bar` causes `registry` to get rebuilt because it switches
603 // to needing both Object (for the `bar` dylib) and Bitcode (for the test
604 // built with LTO).
605 //
606 // `bar` the dylib gets rebuilt because `registry` got rebuilt.
607 p.cargo("test --release -v --manifest-path bar/Cargo.toml")
608 .with_stderr_unordered(
609 "\
610 [FRESH] registry-shared v0.0.1
611 [COMPILING] registry v0.0.1
612 [RUNNING] `rustc --crate-name registry [..]
613 [COMPILING] bar [..]
614 [RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
615 [RUNNING] `rustc --crate-name bar [..]-C lto [..]--test[..]
616 [RUNNING] `rustc --crate-name b [..]-C lto [..]--test[..]
617 [FINISHED] [..]
618 [RUNNING] [..]
619 [RUNNING] [..]
620 ",
621 )
622 .run();
623 }
624
625 #[cargo_test]
test_profile()626 fn test_profile() {
627 Package::new("bar", "0.0.1")
628 .file("src/lib.rs", "pub fn foo() -> i32 { 123 } ")
629 .publish();
630
631 let p = project()
632 .file(
633 "Cargo.toml",
634 r#"
635 [package]
636 name = "foo"
637 version = "0.1.0"
638 edition = "2018"
639
640 [profile.test]
641 lto = 'thin'
642
643 [dependencies]
644 bar = "*"
645 "#,
646 )
647 .file(
648 "src/lib.rs",
649 r#"
650 #[test]
651 fn t1() {
652 assert_eq!(123, bar::foo());
653 }
654 "#,
655 )
656 .build();
657
658 p.cargo("test -v")
659 // unordered because the two `foo` builds start in parallel
660 .with_stderr_unordered("\
661 [UPDATING] [..]
662 [DOWNLOADING] [..]
663 [DOWNLOADED] [..]
664 [COMPILING] bar v0.0.1
665 [RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
666 [COMPILING] foo [..]
667 [RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..]
668 [RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..]
669 [FINISHED] [..]
670 [RUNNING] [..]
671 [DOCTEST] foo
672 [RUNNING] `rustdoc [..]
673 ")
674 .run();
675 }
676
677 #[cargo_test]
doctest()678 fn doctest() {
679 let p = project()
680 .file(
681 "Cargo.toml",
682 r#"
683 [package]
684 name = "foo"
685 version = "0.1.0"
686 edition = "2018"
687
688 [profile.release]
689 lto = true
690
691 [dependencies]
692 bar = { path = "bar" }
693 "#,
694 )
695 .file(
696 "src/lib.rs",
697 r#"
698 /// Foo!
699 ///
700 /// ```
701 /// foo::foo();
702 /// ```
703 pub fn foo() { bar::bar(); }
704 "#,
705 )
706 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
707 .file(
708 "bar/src/lib.rs",
709 r#"
710 pub fn bar() { println!("hi!"); }
711 "#,
712 )
713 .build();
714
715 p.cargo("test --doc --release -v")
716 .with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]")
717 .with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]")
718 // embed-bitcode should be harmless here
719 .with_stderr_contains("[..]`rustdoc [..]-C lto[..]")
720 .run();
721
722 // Try with bench profile.
723 p.cargo("test --doc --release -v")
724 .env("CARGO_PROFILE_BENCH_LTO", "true")
725 .with_stderr_unordered(
726 "\
727 [FRESH] bar v0.1.0 [..]
728 [FRESH] foo v0.1.0 [..]
729 [FINISHED] release [..]
730 [DOCTEST] foo
731 [RUNNING] `rustdoc [..]-C lto[..]
732 ",
733 )
734 .run();
735 }
736
737 #[cargo_test]
dylib_rlib_bin()738 fn dylib_rlib_bin() {
739 // dylib+rlib linked with a binary
740 let p = project()
741 .file(
742 "Cargo.toml",
743 r#"
744 [package]
745 name = "foo"
746 version = "0.1.0"
747
748 [lib]
749 crate-type = ["dylib", "rlib"]
750
751 [profile.release]
752 lto = true
753 "#,
754 )
755 .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
756 .file("src/main.rs", "fn main() { foo::foo(); }")
757 .build();
758
759 let output = p.cargo("build --release -v").exec_with_output().unwrap();
760 verify_lto(
761 &output,
762 "foo",
763 "--crate-type dylib --crate-type rlib",
764 Lto::ObjectAndBitcode,
765 );
766 verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
767 }
768
769 #[cargo_test]
fresh_swapping_commands()770 fn fresh_swapping_commands() {
771 // In some rare cases, different commands end up building dependencies
772 // with different LTO settings. This checks that it doesn't cause the
773 // cache to thrash in that scenario.
774 Package::new("bar", "1.0.0").publish();
775
776 let p = project()
777 .file(
778 "Cargo.toml",
779 r#"
780 [package]
781 name = "foo"
782 version = "0.1.0"
783
784 [dependencies]
785 bar = "1.0"
786
787 [profile.release]
788 lto = true
789 "#,
790 )
791 .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
792 .build();
793
794 p.cargo("build --release -v")
795 .with_stderr(
796 "\
797 [UPDATING] [..]
798 [DOWNLOADING] crates ...
799 [DOWNLOADED] bar v1.0.0 [..]
800 [COMPILING] bar v1.0.0
801 [RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto[..]
802 [COMPILING] foo v0.1.0 [..]
803 [RUNNING] `rustc --crate-name foo src/lib.rs [..]-C linker-plugin-lto[..]
804 [FINISHED] [..]
805 ",
806 )
807 .run();
808 p.cargo("test --release -v")
809 .with_stderr_unordered(
810 "\
811 [FRESH] bar v1.0.0
812 [COMPILING] foo v0.1.0 [..]
813 [RUNNING] `rustc --crate-name foo src/lib.rs [..]-C lto[..]--test[..]
814 [FINISHED] [..]
815 [RUNNING] `[..]/foo[..]`
816 [DOCTEST] foo
817 [RUNNING] `rustdoc [..]-C lto[..]
818 ",
819 )
820 .run();
821
822 p.cargo("build --release -v")
823 .with_stderr(
824 "\
825 [FRESH] bar v1.0.0
826 [FRESH] foo [..]
827 [FINISHED] [..]
828 ",
829 )
830 .run();
831 p.cargo("test --release -v --no-run -v")
832 .with_stderr(
833 "\
834 [FRESH] bar v1.0.0
835 [FRESH] foo [..]
836 [FINISHED] [..]
837 ",
838 )
839 .run();
840 }
841