18

I want to override a build script, which means adding a configuration section that looks like this:

[target.x86_64-unknown-linux-gnu.foo]
rustc-link-search = ["/path/to/foo"]
rustc-link-lib = ["foo"]
root = "/path/to/foo"
key = "value"

But I'm using a Mac, so x86_64-unknown-linux-gnu isn't the correct target triple.

How do I discover which target triple rustc or cargo are currently using?

rustc --print cfg prints a list of values that don't seem to correspond to the triple (there's no unknown in there, in particular).

rustc --print target-list displays all available targets; I just want the default.

James Mishra
  • 4,249
  • 4
  • 30
  • 35
Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
  • 2
    The target triple for your Mac probably is `x86_64-apple-darwin`. The middle part is the vendor, which for Linux is `unknown`, but for a Mac it's `apple`. However, it appears you want to configure the build script independent of the target, so you shouldn't need the target triple at all. – Sven Marnach Oct 25 '18 at 20:13
  • Yeah, I found the correct answer by looking at the list -- found the two `darwin` targets, and knew I was on `x86_64`, but that still requires me to think. Can you expand on "shouldn't need the target triple at all"? – Roger Lipscombe Oct 26 '18 at 07:33

7 Answers7

9

Based on @konstin answer:

$ rustc -vV | sed -n 's|host: ||p'

which gives you something like:

x86_64-unknown-linux-gnu
gauteh
  • 16,435
  • 4
  • 30
  • 34
8

cargo uses rustc -vV to detect the default target triple (source). We can do the same thing:

use std::process::Command;

use anyhow::{format_err, Context, Result};
use std::str;

fn get_target() -> Result<String> {
    let output = Command::new("rustc")
        .arg("-vV")
        .output()
        .context("Failed to run rustc to get the host target")?;
    let output = str::from_utf8(&output.stdout).context("`rustc -vV` didn't return utf8 output")?;

    let field = "host: ";
    let host = output
        .lines()
        .find(|l| l.starts_with(field))
        .map(|l| &l[field.len()..])
        .ok_or_else(|| {
            format_err!(
                "`rustc -vV` didn't have a line for `{}`, got:\n{}",
                field.trim(),
                output
            )
        })?
        .to_string();
    Ok(host)
}

fn main() -> Result<()> {
    let host = get_target()?;
    println!("target triple: {}", host);
    Ok(())
}
konstin
  • 476
  • 7
  • 16
  • 1
    Pass the compiler output through awk for the triple: $ rustc -vV | awk '/host/ { print $2 }' x86_64-unknown-linux-gnu – Frank P Oct 16 '21 at 21:56
3

I write a lot of cross-platform shell scripts or Python programs that need to check my current Rust default target triple. I don't like manually grepping the string value, though.

To make it easier to get the default target triple, I packaged konstin's answer into a command line tool.

You can install it with:

cargo install default-target

and then you can use the program just by running:

default-target

and it'll return your current target triple. Something like x86_64-apple-darwin or x86_64-unknown-linux-gnu.

You can find more details about the crate on crates.io, docs.rs, and GitHub.

James Mishra
  • 4,249
  • 4
  • 30
  • 35
  • You might want to switch it from calling `rustc -vV` to using https://crates.io/crates/current_platform - that's faster and does not require you to locate the rustc binary. – Shnatsel Apr 14 '22 at 13:37
  • @Shnatsel, it's an interesting idea. But if I embed the target triple in `default-target` at compile time, is it possible that the `rustc` target triple becomes different? e.g. Could the same machine have some binaries as `x86_64-unknown-linux-musl` and other binaries as `x86_64-unknown-linux-gnu`? – James Mishra Apr 20 '22 at 03:50
  • Yes, that's possible - if you use rustup, you can switch what your default target is. rust-lang.github.io/rustup/overrides.html I'm not sure if that shows up in `rustc -vV` either – Shnatsel Apr 21 '22 at 13:50
3

You can use the current_platform crate:

use current_platform::CURRENT_PLATFORM;

fn main() {
    println!("Running on {}", CURRENT_PLATFORM);
}

This will print Running on x86_64-unknown-linux-gnu on desktop Linux.

Unlike all the other answers, this is zero cost: the platform is determined at compile time, so there is no runtime overhead. By contrast, calls to rustc are expensive: if Rust is installed through rustup.rs, any rustc command takes ~100ms.

Shnatsel
  • 4,008
  • 1
  • 24
  • 25
2

With a recent enough rustc compiler:

$ rustc -Z unstable-options --print target-spec-json | grep llvm-target
rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • 1
    Hmm. `error: the option \`Z\` is only accepted on the nightly compiler` (rustc 1.42.0). – Jens Apr 10 '20 at 07:42
2

What worked for me (inspired by rodrigo's answer)

RUSTC_BOOTSTRAP=1 rustc -Z unstable-options --print target-spec-json | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["llvm-target"])'

RUSTC_BOOTSTRAP=1 bypasses the check that normally allows certain features to only be used on the nightly branch. I also used a proper json parser rather than grep.

plugwash
  • 9,724
  • 2
  • 38
  • 51
2

It's not particularly elegant perhaps, but I found this to work:

rustup show | grep default | grep -Po "^[^-]+-\K\S+"
Alex
  • 3,429
  • 4
  • 36
  • 66