Skip to content

Handle rust-toolchain file more gracefully #25

@disconnect3d

Description

@disconnect3d

The PR #22 added a workaround for issue #14.

However, this solution is not ideal as:

  • it does not detect/respect rust-toolchain in a project itself (it will use whatever toolchain is the default one, which is good enough for most cases)
  • it is implemented as a workaround in a bash script: we simply pass an environment variable.

I tried to track this issue more deeply, but I could not find the proper solution. Anyway here is some info that can be useful for further investigation into it:

  • Siderophile runs cargo clean and cargo check through Cargo API:

    siderophile/src/deps.rs

    Lines 244 to 270 in c3e6c76

    /// Trigger a `cargo clean` + `cargo check` and listen to the cargo/rustc
    /// communication to figure out which source files were used by the build.
    pub(crate) fn resolve_rs_file_deps(
    copt: &CompileOptions,
    ws: &Workspace,
    ) -> Result<HashMap<PathBuf, u32>, RsResolveError> {
    let config = ws.config();
    // Need to run a cargo clean to identify all new .d deps files.
    // TODO: Figure out how this can be avoided to improve performance, clean
    // Rust builds are __slow__.
    let clean_opt = CleanOptions {
    config: &config,
    spec: vec![],
    target: None,
    release: false,
    doc: false,
    };
    cargo::ops::clean(ws, &clean_opt).map_err(|e| RsResolveError::Cargo(e.to_string()))?;
    let inner_arc = Arc::new(Mutex::new(CustomExecutorInnerContext::default()));
    {
    let cust_exec = CustomExecutor {
    cwd: config.cwd().to_path_buf(),
    inner_ctx: inner_arc.clone(),
    };
    let exec: Arc<Executor> = Arc::new(cust_exec);
    cargo::ops::compile_with_exec(ws, &copt, &exec)
    .map_err(|e| RsResolveError::Cargo(e.to_string()))?;
  • It uses a custom Cargo executor for that where it calls the underlying rustc compilation by itself - this is the point where it fails to compile a dependency (on the .exec(..) call) as it tries to do it with the toolchain specified in the dependency's rust-toolchain file:

    siderophile/src/deps.rs

    Lines 389 to 434 in c3e6c76

    fn exec(
    &self,
    cmd: ProcessBuilder,
    _id: PackageId,
    _target: &Target,
    _mode: CompileMode,
    ) -> CargoResult<()> {
    let args = cmd.get_args();
    let out_dir_key = OsString::from("--out-dir");
    let out_dir_key_idx = args
    .iter()
    .position(|s| *s == out_dir_key)
    .ok_or_else(|| CustomExecutorError::OutDirKeyMissing(cmd.to_string()))?;
    let out_dir = args
    .get(out_dir_key_idx + 1)
    .ok_or_else(|| CustomExecutorError::OutDirValueMissing(cmd.to_string()))
    .map(PathBuf::from)?;
    // This can be different from the cwd used to launch the wrapping cargo
    // plugin. Discovered while fixing
    // https://github.com/anderejd/cargo-geiger/issues/19
    let cwd = cmd
    .get_cwd()
    .map(PathBuf::from)
    .unwrap_or_else(|| self.cwd.to_owned());
    {
    // Scope to drop and release the mutex before calling rustc.
    let mut ctx = self
    .inner_ctx
    .lock()
    .map_err(|e| CustomExecutorError::InnerContextMutex(e.to_string()))?;
    for tuple in args
    .iter()
    .map(|s| (s, s.to_string_lossy().to_lowercase()))
    .filter(|t| t.1.ends_with(".rs"))
    {
    let raw_path = cwd.join(tuple.0);
    let p = raw_path
    .canonicalize()
    .map_err(|e| CustomExecutorError::Io(e, raw_path))?;
    ctx.rs_file_args.insert(p);
    }
    ctx.out_dir_args.insert(out_dir);
    }
    cmd.exec()?;

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions