What is the difference between Cargo's environment variables RUSTC and RUSTC_WRAPPER? - rust

Cargo's environment variables are explained here.
RUSTC - Instead of running rustc, Cargo will execute this specified compiler instead.
RUSTC_WRAPPER - Instead of simply running rustc, Cargo will execute this specified wrapper instead, passing as its commandline arguments the rustc invocation, with the first argument being rustc.
RUSTC and RUSTC_WRAPPER variables look like they are doing the same thing. How are they different?

As the documentation states:
If RUSTC is defined, Cargo will not execute this line:
rustc <parameters>
but this one:
$RUSTC <parameters>
That is like the variable CC in Makefiles to set an alternative compiler.
If RUSTC_WRAPPER is defined, Cargo will not call the compiler itself. It will instead call the following line:
$RUSTC_WRAPPER rustc <parameters>
You can add the options you want, or do whatever you want before the compilation, but you have to call the compiler yourself. Well, that's the purpose of a wrapper.

Related

How to add custom llvm pass into rustc

I am trying to add my llvm pass into Rustc. Rustc has one compiling option -C passes=val where we could add extra LLVM passes to run. However, as my try, this option can only accept the pass when the pass code is placed inside the LLVM code tree, but I want to add my pass out-of-tree into Rustc.
When I add my pass via this option:
RUSTFLAGS="-C passes=my-pass" cargo build
Compiler reports errors:
error: failed to run LLVM passes: unknown pass name 'my-pass'
Then I try to load my pass via -C llvm-args=-fpass-plugin=/opt/new-pass/mypass.so -C passes=my-pass in the clang way. It reports: rustc -Cllvm-args="..." with: Unknown command line argument '-fpass-plugin=/opt/new-pass/mypass.so'. Also tried to replace -fpass-plugin with other options like -load and -load-pass-plugin, but they still cannot be recognized by rustc.
How could I add my custom pass into Rustc?
I was trying to find a solution to this exact problem too. According to a rust developer on their Zulip Chat, it looks like you need to build a custom rustc with plugin support.

What's the different between "cargo build" and "cargo -- build"?

I got a problem by using this command cargo -- build --features ffi, and the built library does not contain symbols I want.
I debugged a whole day and finally found that cargo build --features ffi (no -- before build) will work.
I searched for a while and didn't find what is the usage of a single --, so any help on when it is used and what's the different with or without this --?
As #Sergio already point out, the double dash (--) is commonly indicates the end of options argument after which only positional arguments may follow (also see this answer for more details).
In this particular case, the double dash between cargo and build seems quite buggy as it behaviors inconsistently:
# Intended behavior, `--features ffi` is an option
cargo build --features ffi --
# Fails because no positional arguments are expected
cargo build -- --features ffi
# Silently ignores the positional `--features ffi`
cargo -- build --features ffi
However, thanks to #Inline's bug fix, we should expect this pit-fall to become an issue of the past.

Using multiple flags with cargo

I want to run tests with release optimisations using 1 test thread.
I can do these individually:
cargo test -- --test-threads=1
cargo test --release
How would I put these together?
You can use both in a single command like this:
cargo test --release -- --test-threads=1
How Cargo interprets these arguments ?
According to test subcommand's synopsis in reference :
cargo test [OPTIONS] [TESTNAME] [-- TEST-OPTIONS]
Cargo interprets input as :
Arguments before separator (--) will be used as an option for test subcommand. In your case cargo test accepts profile parameter as an option since it builds the project. Available options can be found under this title, or by running cargo test --help.
Arguments after the separator will be passed to the test binaries. In Rust project, Cargo uses rustc's libtest to run unit tests. In your case --test-threads=1 will be an argument for libtest.
This interpretation might not be valid for other subcommands, it is best to check other cargo commands from here. Checking synopsis section will give you a huge hint about capabilities of cargo's subcommands.
See also:
Since arguments after the dash will be sent to the rustc's libtest you can see available options for testing by: cargo test -- --help.
Profile options can be found under this title

Run `rustc` to check a program without generating any files

As cargo check shows, it's often useful to check if your program is well-formed without actually generating code (an often pretty time-consuming task). I want to check a single (library) Rust file with rustc directly (I cannot use Cargo!).
cargo check apparently works by calling this:
rustc --emit=metadata -Z no-codegen
This only emits metadata, a .rmeta file. Cargo actually needs that to check crates dependent on the checked crate. In my case I really don't need the metadata file.
I tried the following:
rustc --crate-type=lib --emit=
rustc --crate-type=lib --emit=nothing
But both didn't work. I use --crate-type=lib because my file doesn't have a main function. I need a platform-independent solution (I don't just want to use it on my machine, but use it in a public script).
How do I make rustc not write a single file?
You can just skip the --emit flag.
The final command would then be: rustc -Z no-codegen rust.rs
To quote my own GitHub comment about this very question, there are a few options for stable Rust:
rustc --emit=mir -o /dev/null seems to work in 1.18 and newer, writing nothing. (--emit=mir is the only helpful --emit option—the others try to create silly files like /dev/null.foo0.rcgu.o, except --emit=dep-info, which does no checking.)
rustc -C extra-filename=-tmp -C linker=true (i.e. use /bin/true as a “linker”) seems to work in all versions, writing some intermediate files but cleaning them up.
rustc --out-dir=<new empty temporary directory> is less clever and therefore perhaps less likely to break?
Note that linker errors, if any, will not be found by the first two options (nor by the nightly-only -Zno-codegen option).

How can the location of Cargo's configuration directory be overridden?

It seems that the default behavior of Cargo when searching for its configuration directory is to look in the current user's home directory (~/.cargo on my system). How can this behavior be modified to make Cargo look in a user-supplied directory instead?
Environment variables Cargo reads
You can override these environment variables to change Cargo's
behavior on your system:
CARGO_HOME — Cargo maintains a local cache of the registry index and of git checkouts of crates. By default these are stored under
$HOME/.cargo, but this variable overrides the location of this
directory. Once a crate is cached it is not removed by the clean
command.
CARGO_TARGET_DIR — Location of where to place all generated artifacts, relative to the current working directory.
RUSTC — Instead of running rustc, Cargo will execute this specified compiler instead.
RUSTC_WRAPPER — Instead of simply running rustc, Cargo will execute this specified wrapper instead, passing as its commandline
arguments the rustc invocation, with the first argument being rustc.
RUSTDOC — Instead of running rustdoc, Cargo will execute this specified rustdoc instance instead.
RUSTDOCFLAGS — A space-separated list of custom flags to pass to all rustdoc invocations that Cargo performs. In contrast with
cargo rustdoc, this is useful for passing a flag to all
rustdoc instances.
RUSTFLAGS — A space-separated list of custom flags to pass to all compiler invocations that Cargo performs. In contrast with cargo rustc,
this is useful for passing a flag to all compiler
instances.
CARGO_INCREMENTAL — If this is set to 1 then Cargo will force incremental compilation to be enabled for the current compilation,
and when set to 0 it will force disabling it. If this env var isn't
present then cargo's defaults will otherwise be used.
CARGO_CACHE_RUSTC_INFO — If this is set to 0 then Cargo will not try to cache compiler version information.
The Cargo documentation
Hierarchical structure
Cargo allows local configuration for a particular package as well as
global configuration, like git. Cargo extends this to a hierarchical
strategy. If, for example, Cargo were invoked in
/projects/foo/bar/baz, then the following configuration files would
be probed for and unified in this order:
/projects/foo/bar/baz/.cargo/config
/projects/foo/bar/.cargo/config
/projects/foo/.cargo/config
/projects/.cargo/config
/.cargo/config
$HOME/.cargo/config
With this structure, you can specify configuration per-package, and
even possibly check it into version control. You can also specify
personal defaults with a configuration file in your home directory.
The Cargo documentation
The default location can be changed by means of the environment variable $CARGO_HOME, it overrides the default location which is $HOME/.cargo.

Resources