Set toolchain when using cargo's API

Hello,

I am compiling some code using the cargo crate. The code is very basic and looks like this:

fn compile_application(app_path: &str) -> anyhow::Result<(String, Vec<PathBuf>)> {
    let app_path = std::path::absolute(app_path)?;
    let context = GlobalContext::default()?;
    context.shell().set_verbosity(Verbosity::Normal);

    let manifest_path = if let Some(file) = app_path.file_name()
        && file == OsStr::new("Cargo.toml")
    {
        app_path
    } else {
        app_path.join("Cargo.toml")
    };

    let workspace = Workspace::new(&manifest_path, &context).unwrap();
    let workspace_name = workspace
        .root()
        .file_name()
        .unwrap()
        .to_str()
        .unwrap()
        .to_string();
    let wasm_target = CompileTarget::new("wasm32-unknown-unknown")?;

    let mut compile_opts = CompileOptions::new(&context, CompileMode::Build).unwrap();
    compile_opts.spec = Packages::All;
    compile_opts.build_config.requested_kinds = vec![CompileKind::Target(wasm_target)];
    compile_opts.build_config.message_format = MessageFormat::Human;

    match compile(&workspace, &compile_opts) {
        Ok(comp) => {
            let binaries = comp.binaries.iter().map(|u| u.path.clone()).collect();
            Ok((workspace_name, binaries))
        }
        Err(err) => bail!("Failed to compile the application: {err}"),
    }
}

It works fine, but always uses my default toolchain (unless I set RUSTUP_TOOLCHAIN). How can I programmatically set the toolchain, or simply use whatever is in the workspace's rust-toolchain.toml file?

I cannot find anything about this in the cargo crate's documentation...

rust-toolchain.toml is handled by rustup, not cargo. rustup provides special wrappers around cargo and rustc that then execute the actual program based on toolchain selection rules.

when you invoke cargo as a library, you bypass the wrapper around cargo, but cargo then spawns rustc as a command, invoking the rustc wrapper, which then reads RUSTUP_TOOLCHAIN, exec-ing rustc accordingly.

if you want to go through rustup, consider calling cargo via std::process::Command.

I understood most of this by looking at the rustup code, but I appreciate the explanation.

My question was more if the code that reads rust-toolchain.toml is exposed somewhere. I could always parse the file myself and set RUSTUP_TOOLCHAIN, or invoke cargo using Command as you said, but both do not seem like elegant solutions.

Do you want to control whether to use nightly or stable? In that case a cargo +nightly build would suffice for Cargo to use the nightly toolchain instead of the default stable one (if that is your setup). If you want to cross-compile and control which target to compile to, you can set it via your Cargo configuration file with the build.target key.

If I invoke cargo through std::process instead, what is a straightforward way to get a list of all binaries it created?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.