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

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.

Related

How do I remove the dependency on libunwind when cross-compiling Rust programs with the panic_abort option?

I'm specifying the -Cpanic=abort and -Zbuild-std=panic_abort when compiling. Why does the linker still say it needs libunwind to compile a program?
I'm experimenting with various ways to cross-compile Rust programs as small as possible (using the min-sized-rust repo as a reference). Right now I'm trying to compile the powerpc64-unknown-linux-musl target and I'm stuck on trying to remove a dependency on libunwind.
Here's my setup:
# 1. Install the Rust std source code
rustup component add rust-src --toolchain nightly
# 2. Setup a simple rust repo
cargo init testing
cd testing
# 3. Download a musl toolchain
wget https://musl.cc/powerpc64-linux-musl-cross.tgz
tar xzf powerpc64-linux-musl-cross.tgz
# 4. Try to compile the project (options on the command line instead of in files for
# maximum obviousness).
# RUSTFLAGS:
# -Cpanic=abort - abort immediately on panic
# -Clink-self-contained=no - don't use rustc's builtin libraries and objects (this
# is needed because powerpc64-unknown-linux-musl is a tier 3 target)
# -Clink-arg=--sysroot and -Clink-arg=/path/to/sysroot - pass the option to the linker
# to specify the sysroot of cross-compilation toolchain
# Cargo options:
# --config target.<triple>.linker - specify the linker to use
# -Zbuild-std=std,panic_abort - build the standard library from source. Specify
# panic_abort to make the abort on panic work
RUSTFLAGS="-Cpanic=abort -Clink-self-contained=no -Clink-arg=--sysroot -Clink-arg=powerpc64-linux-musl-cross/powerpc64-linux-musl/" \
cargo +nightly build \
--config "target.powerpc64-unknown-linux-musl.linker=\"powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc\"" \
--target powerpc64-unknown-linux-musl -Zbuild-std=panic_abort,std --release
This fails with the following error:
error: linking with `/home/user/Projects/testing/powerpc64-linux-musl-cross/bin/powerpc64-linux-musl-gcc` failed: exit status: 1
<output snipped>
= note: /home/user/Projects/testing/powerpc64-linux-musl-cross/bin/../lib/gcc/powerpc64-linux-musl/11.2.1/../../../../powerpc64-linux-musl/bin/ld: cannot find -lunwind
From min-size-rust repository:
"Even if panic = "abort" is specified in Cargo.toml, rustc will still include panic strings and formatting code in final binary by default. An unstable panic_immediate_abort feature has been merged into the nightly rustc compiler to address this.
To use this, repeat the instructions above to use build-std, but also pass the following -Z build-std-features=panic_immediate_abort option."
Still, you will get "cannot find -lunwind", because the linker still uses libunwind, even though it's truly unneeded,why! I do not know, maybe it's a bug.(Maybe someone with fair knowledge about linkers can easily solve that.I tried a naive solution which is "cargo .... --verbose", copy , remove "libunwind" then relinking which failed)
I verified that is indeed the missing piece by build from source(--target=x86_64-unknown-linux-musl) AND using an old simple trick which is "touch libunwind.a" in the "self-contained" directory inside a target lib folder.(because the linker would still use it even though it's now truly unneeded, then I gave him a dummy libunwind.a)
In your case, I really tried to build it to your target until I got a headache, but couldn't and stopped, but here is possible solutions:
Giving that you're using "-Z build-std-features=panic_immediate_abort"
-If you can custom the linking process, then solve it (until what seems to be a bug is solved)
-Create a dummy(empty) libunwind.a where it should be in your toolchain

cargo run --example exaple_name causes "no example target named 'example_name'"

I am studying the following code and cannot wrap my head around why cargo run --example abigen wouldn't work. The docs state that package has to be specified like so cargo run -p ethers --example abigen. Indeed, this fixes the issue. But according to Rust docs, I should be able to use the first version. Why doesn't this first version work?

Compile rust dependency with debug flag during test

I am using a Rust dependency which allows being built with a --debug or --verbose flag.
I am running my test as follows:
cargo test --package mw-btc-swap --bin mw-btc-swap -- grin::grin_core::test::test_fin_tx --exact --nocapture
Now my question is how can I configure cargo to only compile this specific dependency with the desired flag. I tried using RUSTFLAGS=--debug environment variable but then the flag seems to be passed to all compilations which makes most of them fail, as they don't support this flag.
I have also looked through https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html in hope I could somehow specify the flags in the cargo.toml which doesn't seem to be the case.

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).

Resources