flowey_trampoline/main.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Crate used to fix up environment variables before running another cargo
5//! command, to be used in cargo aliases.
6//!
7//! This crate is used to work around a bug in the `linkme` crate on macOS,
8//! <https://github.com/dtolnay/linkme/issues/61>. If a binary is built without
9//! LTO on macOS, sometimes `linkme` will fail to include all the elements of a
10//! distributed slice. This causes flowey runs to fail.
11//!
12//! To work around this, we set the `CARGO_PROFILE_FLOWEY_LTO` environment
13//! variable to `thin` before running the `cargo` binary. This will cause the
14//! `flowey_hvlite` binary to be built with thin LTO, which will work around the
15//! `linkme` bug.
16//!
17//! We don't want to set this for non-macOS environments because it slows down
18//! builds.
19//!
20//! This crate can be removed when the `linkme` bug is fixed or when cargo gains
21//! enough support to do this kind of thing natively.
22
23use std::process::Command;
24
25fn main() {
26 let args = std::env::args_os().collect::<Vec<_>>();
27 let cargo = std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
28 let mut cmd = Command::new(cargo);
29 cmd.args(&args[1..]);
30
31 // Conditionally set LTO via environment variable. Note that this inherits
32 // to any child invocations of cargo, which is what we want.
33 //
34 // This check isn't completely accurate, since we might be cross compiling
35 // flowey from or to a different OS. But it's good enough for now.
36 if cfg!(target_os = "macos") {
37 cmd.env("CARGO_PROFILE_FLOWEY_LTO", "thin");
38 }
39
40 #[cfg(unix)]
41 {
42 let err = std::os::unix::process::CommandExt::exec(&mut cmd);
43 panic!("failed to exec: {:?}", err);
44 }
45 #[cfg(not(unix))]
46 {
47 let status = cmd.status().expect("failed to run command");
48 std::process::exit(status.code().unwrap_or(1));
49 }
50}