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}