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/bin/foo-bin.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(
210 "[..]`rustc[..]--crate-name foo_bin [..]--crate-type bin[..]-C lto[..]`",
211 )
212 .with_stderr_contains(
213 "[..]`rustc[..]--crate-name test [..]--crate-type cdylib[..]-C lto[..]`",
214 )
215 .with_stderr_contains("[..]`rustc[..]--crate-name dep_shared [..]`")
216 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C lto[..]")
217 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C linker-plugin-lto[..]")
218 .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C embed-bitcode[..]")
219 .run();
220 }
221
222 #[cargo_test]
off_in_manifest_works()223 fn off_in_manifest_works() {
224 Package::new("bar", "0.0.1")
225 .file("src/lib.rs", "pub fn foo() {}")
226 .publish();
227
228 let p = project()
229 .file(
230 "Cargo.toml",
231 r#"
232 [package]
233 name = "test"
234 version = "0.0.0"
235
236 [dependencies]
237 bar = "*"
238
239 [profile.release]
240 lto = "off"
241 "#,
242 )
243 .file("src/lib.rs", "pub fn foo() {}")
244 .file(
245 "src/main.rs",
246 "fn main() {
247 test::foo();
248 bar::foo();
249 }",
250 )
251 .build();
252 p.cargo("build -v --release")
253 .with_stderr(
254 "\
255 [UPDATING] [..]
256 [DOWNLOADING] [..]
257 [DOWNLOADED] [..]
258 [COMPILING] bar v0.0.1
259 [RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
260 [COMPILING] test [..]
261 [RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
262 [RUNNING] `rustc --crate-name test src/main.rs [..]--crate-type bin [..]-C lto=off[..]
263 [FINISHED] [..]
264 ",
265 )
266 .run();
267 }
268
269 #[cargo_test]
between_builds()270 fn between_builds() {
271 let p = project()
272 .file(
273 "Cargo.toml",
274 r#"
275 [package]
276 name = "test"
277 version = "0.0.0"
278
279 [profile.release]
280 lto = true
281 "#,
282 )
283 .file("src/lib.rs", "pub fn foo() {}")
284 .file("src/main.rs", "fn main() { test::foo() }")
285 .build();
286 p.cargo("build -v --release --lib")
287 .with_stderr(
288 "\
289 [COMPILING] test [..]
290 [RUNNING] `rustc [..]--crate-type lib[..]-C linker-plugin-lto[..]
291 [FINISHED] [..]
292 ",
293 )
294 .run();
295 p.cargo("build -v --release")
296 .with_stderr_contains(
297 "\
298 [COMPILING] test [..]
299 [RUNNING] `rustc [..]--crate-type bin[..]-C lto[..]
300 [FINISHED] [..]
301 ",
302 )
303 .run();
304 }
305
306 #[cargo_test]
test_all()307 fn test_all() {
308 let p = project()
309 .file(
310 "Cargo.toml",
311 r#"
312 [package]
313 name = "foo"
314 version = "0.0.0"
315
316 [profile.release]
317 lto = true
318 "#,
319 )
320 .file("src/main.rs", "fn main() {}")
321 .file("tests/a.rs", "")
322 .file("tests/b.rs", "")
323 .build();
324 p.cargo("test --release -v")
325 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
326 .run();
327 }
328
329 #[cargo_test]
test_all_and_bench()330 fn test_all_and_bench() {
331 let p = project()
332 .file(
333 "Cargo.toml",
334 r#"
335 [package]
336 name = "foo"
337 version = "0.0.0"
338
339 [profile.release]
340 lto = true
341 [profile.bench]
342 lto = true
343 "#,
344 )
345 .file("src/main.rs", "fn main() {}")
346 .file("tests/a.rs", "")
347 .file("tests/b.rs", "")
348 .build();
349 p.cargo("test --release -v")
350 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name a[..]-C lto[..]")
351 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name b[..]-C lto[..]")
352 .with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
353 .run();
354 }
355
356 /// Basic setup:
357 ///
358 /// foo v0.0.0
359 /// ├── bar v0.0.0
360 /// │ ├── registry v0.0.1
361 /// │ └── registry-shared v0.0.1
362 /// └── registry-shared v0.0.1
363 ///
364 /// Where `bar` will have the given crate types.
project_with_dep(crate_types: &str) -> Project365 fn project_with_dep(crate_types: &str) -> Project {
366 Package::new("registry", "0.0.1")
367 .file("src/lib.rs", r#"pub fn foo() { println!("registry"); }"#)
368 .publish();
369 Package::new("registry-shared", "0.0.1")
370 .file("src/lib.rs", r#"pub fn foo() { println!("shared"); }"#)
371 .publish();
372
373 project()
374 .file(
375 "Cargo.toml",
376 r#"
377 [package]
378 name = "foo"
379 version = "0.0.0"
380
381 [workspace]
382
383 [dependencies]
384 bar = { path = 'bar' }
385 registry-shared = "*"
386
387 [profile.release]
388 lto = true
389 "#,
390 )
391 .file(
392 "src/main.rs",
393 "
394 fn main() {
395 bar::foo();
396 registry_shared::foo();
397 }
398 ",
399 )
400 .file(
401 "bar/Cargo.toml",
402 &format!(
403 r#"
404 [package]
405 name = "bar"
406 version = "0.0.0"
407
408 [dependencies]
409 registry = "*"
410 registry-shared = "*"
411
412 [lib]
413 crate-type = [{}]
414 "#,
415 crate_types
416 ),
417 )
418 .file(
419 "bar/src/lib.rs",
420 r#"
421 pub fn foo() {
422 println!("bar");
423 registry::foo();
424 registry_shared::foo();
425 }
426 "#,
427 )
428 .file("tests/a.rs", "")
429 .file("bar/tests/b.rs", "")
430 .build()
431 }
432
433 /// Helper for checking which LTO behavior is used for a specific crate.
434 ///
435 /// `krate_info` is extra compiler flags used to distinguish this if the same
436 /// crate name is being built multiple times.
verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto)437 fn verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto) {
438 let stderr = std::str::from_utf8(&output.stderr).unwrap();
439 let mut matches = stderr.lines().filter(|line| {
440 line.contains("Running")
441 && line.contains(&format!("--crate-name {} ", krate))
442 && line.contains(krate_info)
443 });
444 let line = matches.next().unwrap_or_else(|| {
445 panic!(
446 "expected to find crate `{}` info: `{}`, not found in output:\n{}",
447 krate, krate_info, stderr
448 );
449 });
450 if let Some(line2) = matches.next() {
451 panic!(
452 "found multiple lines matching crate `{}` info: `{}`:\nline1:{}\nline2:{}\noutput:\n{}",
453 krate, krate_info, line, line2, stderr
454 );
455 }
456 let actual_lto = if let Some(index) = line.find("-C lto=") {
457 let s = &line[index..];
458 let end = s.find(' ').unwrap();
459 let mode = &line[index..index + end];
460 if mode == "off" {
461 Lto::Off
462 } else {
463 Lto::Run(Some(mode.into()))
464 }
465 } else if line.contains("-C lto") {
466 Lto::Run(None)
467 } else if line.contains("-C linker-plugin-lto") {
468 Lto::OnlyBitcode
469 } else if line.contains("-C embed-bitcode=no") {
470 Lto::OnlyObject
471 } else {
472 Lto::ObjectAndBitcode
473 };
474 assert_eq!(
475 actual_lto, expected_lto,
476 "did not find expected LTO in line: {}",
477 line
478 );
479 }
480
481 #[cargo_test]
cdylib_and_rlib()482 fn cdylib_and_rlib() {
483 let p = project_with_dep("'cdylib', 'rlib'");
484 let output = p.cargo("build --release -v").exec_with_output().unwrap();
485 // `registry` is ObjectAndBitcode because because it needs Object for the
486 // rlib, and Bitcode for the cdylib (which doesn't support LTO).
487 verify_lto(
488 &output,
489 "registry",
490 "--crate-type lib",
491 Lto::ObjectAndBitcode,
492 );
493 // Same as `registry`
494 verify_lto(
495 &output,
496 "registry_shared",
497 "--crate-type lib",
498 Lto::ObjectAndBitcode,
499 );
500 // Same as `registry`
501 verify_lto(
502 &output,
503 "bar",
504 "--crate-type cdylib --crate-type rlib",
505 Lto::ObjectAndBitcode,
506 );
507 verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
508 p.cargo("test --release -v")
509 .with_stderr_unordered(
510 "\
511 [FRESH] registry v0.0.1
512 [FRESH] registry-shared v0.0.1
513 [FRESH] bar v0.0.0 [..]
514 [COMPILING] foo [..]
515 [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
516 [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
517 [FINISHED] [..]
518 [RUNNING] [..]
519 [RUNNING] [..]
520 ",
521 )
522 .run();
523 p.cargo("build --release -v --manifest-path bar/Cargo.toml")
524 .with_stderr_unordered(
525 "\
526 [FRESH] registry-shared v0.0.1
527 [FRESH] registry v0.0.1
528 [FRESH] bar v0.0.0 [..]
529 [FINISHED] [..]
530 ",
531 )
532 .run();
533 p.cargo("test --release -v --manifest-path bar/Cargo.toml")
534 .with_stderr_unordered(
535 "\
536 [FRESH] registry-shared v0.0.1
537 [FRESH] registry v0.0.1
538 [COMPILING] bar [..]
539 [RUNNING] `rustc --crate-name bar [..]-C lto[..]--test[..]
540 [RUNNING] `rustc --crate-name b [..]-C lto[..]--test[..]
541 [FINISHED] [..]
542 [RUNNING] [..]target/release/deps/bar-[..]
543 [RUNNING] [..]target/release/deps/b-[..]
544 [DOCTEST] bar
545 [RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --crate-name bar --test [..]-C lto[..]
546 ",
547 )
548 .run();
549 }
550
551 #[cargo_test]
dylib()552 fn dylib() {
553 let p = project_with_dep("'dylib'");
554 let output = p.cargo("build --release -v").exec_with_output().unwrap();
555 // `registry` is OnlyObject because rustc doesn't support LTO with dylibs.
556 verify_lto(&output, "registry", "--crate-type lib", Lto::OnlyObject);
557 // `registry_shared` is both because it is needed by both bar (Object) and
558 // foo (Bitcode for LTO).
559 verify_lto(
560 &output,
561 "registry_shared",
562 "--crate-type lib",
563 Lto::ObjectAndBitcode,
564 );
565 // `bar` is OnlyObject because rustc doesn't support LTO with dylibs.
566 verify_lto(&output, "bar", "--crate-type dylib", Lto::OnlyObject);
567 // `foo` is LTO because it is a binary, and the profile specifies `lto=true`.
568 verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
569 // `cargo test` should not rebuild dependencies. It builds the test
570 // executables with `lto=true` because the tests are built with the
571 // `--release` flag.
572 p.cargo("test --release -v")
573 .with_stderr_unordered(
574 "\
575 [FRESH] registry v0.0.1
576 [FRESH] registry-shared v0.0.1
577 [FRESH] bar v0.0.0 [..]
578 [COMPILING] foo [..]
579 [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
580 [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
581 [FINISHED] [..]
582 [RUNNING] [..]
583 [RUNNING] [..]
584 ",
585 )
586 .run();
587 // Building just `bar` causes `registry-shared` to get rebuilt because it
588 // switches to OnlyObject because it is now only being used with a dylib
589 // which does not support LTO.
590 //
591 // `bar` gets rebuilt because `registry_shared` got rebuilt.
592 p.cargo("build --release -v --manifest-path bar/Cargo.toml")
593 .with_stderr_unordered(
594 "\
595 [COMPILING] registry-shared v0.0.1
596 [FRESH] registry v0.0.1
597 [RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..]
598 [COMPILING] bar [..]
599 [RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
600 [FINISHED] [..]
601 ",
602 )
603 .run();
604 // Testing just `bar` causes `registry` to get rebuilt because it switches
605 // to needing both Object (for the `bar` dylib) and Bitcode (for the test
606 // built with LTO).
607 //
608 // `bar` the dylib gets rebuilt because `registry` got rebuilt.
609 p.cargo("test --release -v --manifest-path bar/Cargo.toml")
610 .with_stderr_unordered(
611 "\
612 [FRESH] registry-shared v0.0.1
613 [COMPILING] registry v0.0.1
614 [RUNNING] `rustc --crate-name registry [..]
615 [COMPILING] bar [..]
616 [RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
617 [RUNNING] `rustc --crate-name bar [..]-C lto [..]--test[..]
618 [RUNNING] `rustc --crate-name b [..]-C lto [..]--test[..]
619 [FINISHED] [..]
620 [RUNNING] [..]
621 [RUNNING] [..]
622 ",
623 )
624 .run();
625 }
626
627 #[cargo_test]
test_profile()628 fn test_profile() {
629 Package::new("bar", "0.0.1")
630 .file("src/lib.rs", "pub fn foo() -> i32 { 123 } ")
631 .publish();
632
633 let p = project()
634 .file(
635 "Cargo.toml",
636 r#"
637 [package]
638 name = "foo"
639 version = "0.1.0"
640 edition = "2018"
641
642 [profile.test]
643 lto = 'thin'
644
645 [dependencies]
646 bar = "*"
647 "#,
648 )
649 .file(
650 "src/lib.rs",
651 r#"
652 #[test]
653 fn t1() {
654 assert_eq!(123, bar::foo());
655 }
656 "#,
657 )
658 .build();
659
660 p.cargo("test -v")
661 // unordered because the two `foo` builds start in parallel
662 .with_stderr_unordered("\
663 [UPDATING] [..]
664 [DOWNLOADING] [..]
665 [DOWNLOADED] [..]
666 [COMPILING] bar v0.0.1
667 [RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
668 [COMPILING] foo [..]
669 [RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..]
670 [RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..]
671 [FINISHED] [..]
672 [RUNNING] [..]
673 [DOCTEST] foo
674 [RUNNING] `rustdoc [..]
675 ")
676 .run();
677 }
678
679 #[cargo_test]
doctest()680 fn doctest() {
681 let p = project()
682 .file(
683 "Cargo.toml",
684 r#"
685 [package]
686 name = "foo"
687 version = "0.1.0"
688 edition = "2018"
689
690 [profile.release]
691 lto = true
692
693 [dependencies]
694 bar = { path = "bar" }
695 "#,
696 )
697 .file(
698 "src/lib.rs",
699 r#"
700 /// Foo!
701 ///
702 /// ```
703 /// foo::foo();
704 /// ```
705 pub fn foo() { bar::bar(); }
706 "#,
707 )
708 .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
709 .file(
710 "bar/src/lib.rs",
711 r#"
712 pub fn bar() { println!("hi!"); }
713 "#,
714 )
715 .build();
716
717 p.cargo("test --doc --release -v")
718 .with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]")
719 .with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]")
720 // embed-bitcode should be harmless here
721 .with_stderr_contains("[..]`rustdoc [..]-C lto[..]")
722 .run();
723
724 // Try with bench profile.
725 p.cargo("test --doc --release -v")
726 .env("CARGO_PROFILE_BENCH_LTO", "true")
727 .with_stderr_unordered(
728 "\
729 [FRESH] bar v0.1.0 [..]
730 [FRESH] foo v0.1.0 [..]
731 [FINISHED] release [..]
732 [DOCTEST] foo
733 [RUNNING] `rustdoc [..]-C lto[..]
734 ",
735 )
736 .run();
737 }
738
739 #[cargo_test]
dylib_rlib_bin()740 fn dylib_rlib_bin() {
741 // dylib+rlib linked with a binary
742 let p = project()
743 .file(
744 "Cargo.toml",
745 r#"
746 [package]
747 name = "foo"
748 version = "0.1.0"
749
750 [lib]
751 crate-type = ["dylib", "rlib"]
752
753 [profile.release]
754 lto = true
755 "#,
756 )
757 .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
758 .file("src/bin/ferret.rs", "fn main() { foo::foo(); }")
759 .build();
760
761 let output = p.cargo("build --release -v").exec_with_output().unwrap();
762 verify_lto(
763 &output,
764 "foo",
765 "--crate-type dylib --crate-type rlib",
766 Lto::ObjectAndBitcode,
767 );
768 verify_lto(&output, "ferret", "--crate-type bin", Lto::Run(None));
769 }
770
771 #[cargo_test]
fresh_swapping_commands()772 fn fresh_swapping_commands() {
773 // In some rare cases, different commands end up building dependencies
774 // with different LTO settings. This checks that it doesn't cause the
775 // cache to thrash in that scenario.
776 Package::new("bar", "1.0.0").publish();
777
778 let p = project()
779 .file(
780 "Cargo.toml",
781 r#"
782 [package]
783 name = "foo"
784 version = "0.1.0"
785
786 [dependencies]
787 bar = "1.0"
788
789 [profile.release]
790 lto = true
791 "#,
792 )
793 .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
794 .build();
795
796 p.cargo("build --release -v")
797 .with_stderr(
798 "\
799 [UPDATING] [..]
800 [DOWNLOADING] crates ...
801 [DOWNLOADED] bar v1.0.0 [..]
802 [COMPILING] bar v1.0.0
803 [RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto[..]
804 [COMPILING] foo v0.1.0 [..]
805 [RUNNING] `rustc --crate-name foo src/lib.rs [..]-C linker-plugin-lto[..]
806 [FINISHED] [..]
807 ",
808 )
809 .run();
810 p.cargo("test --release -v")
811 .with_stderr_unordered(
812 "\
813 [FRESH] bar v1.0.0
814 [COMPILING] foo v0.1.0 [..]
815 [RUNNING] `rustc --crate-name foo src/lib.rs [..]-C lto[..]--test[..]
816 [FINISHED] [..]
817 [RUNNING] `[..]/foo[..]`
818 [DOCTEST] foo
819 [RUNNING] `rustdoc [..]-C lto[..]
820 ",
821 )
822 .run();
823
824 p.cargo("build --release -v")
825 .with_stderr(
826 "\
827 [FRESH] bar v1.0.0
828 [FRESH] foo [..]
829 [FINISHED] [..]
830 ",
831 )
832 .run();
833 p.cargo("test --release -v --no-run -v")
834 .with_stderr(
835 "\
836 [FRESH] bar v1.0.0
837 [FRESH] foo [..]
838 [FINISHED] [..]
839 ",
840 )
841 .run();
842 }
843