Skip to content

Cargo will always invoke the 'true' rustc on Windows, rather than a rustc shim #5960

Closed as not planned
@aidanhs

Description

@aidanhs

(by a 'rustc shim' I'm referring to things like rustup - it puts a shim rustc on the path which invokes the true rustc)

As part of invoking rustc for compilations, cargo will put a number of paths in the 'library environment', performed here (called from Compilation::rustc_process, which is called from prepare_rustc): https://github.com/rust-lang/cargo/blob/d4ee795/src/cargo/core/compiler/compilation.rs#L188-L204

However, a few things conspire against us:

  • the paths are added to the beginning of the variable, i.e. with the highest priority
  • on Windows the environment variable these new paths get added to (util::dylib_path_envvar()) is the same as the binary search path (i.e. PATH)
  • on Windows, the sysroot dylibs for the compiler are in the same directory as the actual binaries (i.e. rustc.exe lives alongside dylibs like rustc_typeck-4d5d5a72bda8f430.dll)

This means that when actually performing the compilation, an attempted invocation of rustc will jump straight to the sysroot binaries rather than using the shim - anything that the shim does (like telemetry, in the case of the rustup) gets completely skipped for any compilations. You can observe this with a build plan on Windows:

{
    "invocations": [
        {
            "package_name": "cde",
            "package_version": "0.1.0",
            "target_kind": [
                "bin"
            ],
            "kind": "Host",
            "deps": [],
            "outputs": [
                "C:\\X\\cde\\target\\release\\deps\\cde-63a3117d8b95571a.exe",
                "C:\\X\\cde\\target\\release\\deps\\cde-63a3117d8b95571a.pdb"
            ],
            "links": {
                "C:\\X\\cde\\target\\release\\cde.exe": "C:\\X\\cde\\target\\release\\deps\\cde-63a3117d8b95571a.exe",
                "C:\\X\\cde\\target\\release\\cde.pdb": "C:\\X\\cde\\target\\release\\deps\\cde-63a3117d8b95571a.pdb"
            },
            "program": "rustc",
            "args": [
                "--crate-name",
                "cde",
                "src\\main.rs",
                "--crate-type",
                "bin",
                "--emit=dep-info,link",
                "-C",
                "opt-level=3",
                "-C",
                "metadata=63a3117d8b95571a",
                "-C",
                "extra-filename=-63a3117d8b95571a",
                "--out-dir",
                "C:\\X\\cde\\target\\release\\deps",
                "-L",
                "dependency=C:\\X\\cde\\target\\release\\deps"
            ],
            "env": {
                "CARGO": "\\\\?\\C:\\Users\\aidanhs\\.rustup\\toolchains\\nightly-2018-08-19-x86_64-pc-windows-msvc\\bin\\cargo.exe",
                "CARGO_MANIFEST_DIR": "C:\\X\\cde",
                [...]
                "CARGO_PRIMARY_PACKAGE": "1",
                "PATH": "C:\\X\\cde\\target\\release\\deps;C:\\Users\\aidanhs\\.rustup\\toolchains\\nightly-2018-08-19-x86_64-pc-windows-msvc\\bin;C:\\Users\\aidanhs\\.cargo\\bin;C:\\Users\\aidanhs\\.rustup\\toolchains\\nightly-2018-08-19-x86_64-pc-windows-msvc\\bin;[...]"
            },
            "cwd": "C:\\X\\cde"
        }
    ],
    "inputs": [
        "C:\\X\\cde\\Cargo.toml"
    ]
}

Note the C:\\Users\\aidanhs\\.rustup\\toolchains\\nightly-2018-08-19-x86_64-pc-windows-msvc\\bin with a higher priority than C:\\Users\\aidanhs\\.cargo\\bin in the PATH.

There is an additional oddity though - when performing configuration tests at cargo startup (

let mut process = rustc.process();
process
.arg("-")
.arg("--crate-name")
.arg("___")
.arg("--print=file-names")
.args(&rustflags)
.env_remove("RUST_LOG");
), cargo will use the correct binary, i.e. the shim. This makes sense (this is the way it actually discovers the sysroot to add to the environment), but is a bit odd (since you then get two entries in rustup telemetry).

Quick thoughts:

  • I'm not clear why we need to add the sysroot dylib path to the environment - on Linux the rustc binary has an rpath, and Windows will apparently attempt to use the directory of the executable first (https://msdn.microsoft.com/en-us/library/7d83bc18.aspx)
  • Adding paths at the end of the variable could cause oddities with unusual setups, but I would imagine the risks are fairly low given the hashes added to the end of rustc-generated dylibs.
  • Move dylibs into a different directory in the rust distribution - likely to make standalone rustc calls fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions