Get the --bin argument in build.rs - rust

I'd like to handle each binary differently in build.rs.
I can use env!("CARGO_PKG_VERSION") to get the version info from Cargo.toml.
Is there something similar for getting the bin argument?
I'd like to get binary_name when running cargo run --bin binary_name.

Related

Specify --manifest-path while using cargo watch

A fantastic crate is cargo watch, which allows, for example, for you to execute:
cargo watch -x run
to automatically rebuild/run on src change. This is amazing for development but one issue I have is that it seems to not support the --manifest-path argument that can be used with cargo run to explicitly specify the path to the .toml file of the project such that it can be run from a different pwd than the Cargo.toml file itself:
cargo run --manifest-path /home/user/project/Cargo.toml
The crate documentation doesn't mention anything about this, so I was wondering if anyone who uses this crate has found a way around this. When attempting to use the --manifest-path argument I receive:
error: Found argument '--manifest-path' which wasn't expected, or isn't valid in this context
USAGE:
cargo watch [FLAGS] [OPTIONS]
Which makes some sense as I know not all commands support the --manifest-path arg, but since the crate uses cargo run to run the project itself I'm guessing there is some way around this without using e.g. sh -c 'cd [path to .toml file] && cargo watch -x run'
Yes you can just use the invocation which lets you run arbitrary commands:
cargo watch -- cargo run --manifest-path=path/to/Cargo.toml

How to solve ”Blocking waiting for file lock on build directory“ problem?

I want to generate some .rs code in my rust program, and I create a package gen-proxy-ffi which use bindgen to do that. The following command can generate codes I need.
cargo run --package gen-proxy-ffi --bin gen-proxy-ffi
When the codes are generated, I can then build the whole project by
cargo build
Now, I want cargo build will automaticly generate code by calling cargo run --package gen-proxy-ffi --bin gen-proxy-ffi. I know I can write some code to build.rs to specify rust's compiling routine, so I write the following codes, where make-gen-proxy-ffi.sh encaplsules cargo run --package gen-proxy-ffi --bin gen-proxy-ffi.
// build.rs
use std::process::Command;
use std::io::Write;
fn main() {
let o = Command::new("sh").args(&["make-gen-proxy-ffi.sh"]).output().expect("sh exec error!");
}
However, when running cargo build now, it prints out the following error
+ cargo run --package gen-proxy-ffi --bin gen-proxy-ffi --
Blocking waiting for file lock on build directory
After some searching, I know it is because cargo build on the same project twice at one time.
However, from this post, I found no solution to this, so I wonder if there are any ways I can generate code and build the whole project by one cargo build?

When should I use the --bin option for cargo new?

What is the difference between cargo new <project_name> --bin and cargo new <project_name>?
It seems both commands make exactly the same project; all components are consistent.
I think --bin stands for "binary", but I don't know when to use this option or not.
There is no difference between cargo new and cargo new --bin. From First Steps with Cargo, emphasis mine:
To start a new package with Cargo, use cargo new:
$ cargo new hello_world
Cargo defaults to --bin to make a binary program. To make a library, we would pass --lib, instead.
Likewise, Cargo's command line help tells you the same thing. From cargo new --help, with some irrelevant lines removed:
% cargo new --help
OPTIONS:
--bin Use a binary (application) template [default]
--lib Use a library template
See also
Why does `cargo new` create a binary instead of a library?
What is the difference between library crates and normal crates in Rust?

Is it possible to run a single rust file as a script while linking to other libraries without generating cargo projects

I'd like to run a one off rust "script" without going through creating a cargo project for a single run (since I am providing this script to colleagues).
Ideally I could build directly with the command line avoiding creating cargo projects etc.
for instance:
use serde_json::Value;
use some_private_packege_i_own_locally_in_another_directory;
fn main() {
// do some stuff with these packages and die
}
I would need to depend on the serde_json and my some_private_packege_i_own_locally_in_another_directory.
(A bit similar to rust playground I suppose for a single time use)
Something similar to this from the command line would be great:
rustc /path/to/main.rs --dependency serde_json, my_package ...
You can specify a dependency with with extern flag, and you can specify the location of transitive dependencies, with -L dependency. You will have to compile each dependency, and all of it's dependencies manually:
// compile all of serde's dependencies
// compile all of hyper's dependencies
// compile serde
// compile hyper
rustc script.rs --crate-type bin -L dependency=~/tmp/deps --extern serde_json=~/tmp/deps/serde_json.rlib --extern hyper=~/tmp/deps/hyper.rlib
As you can tell, this would get very difficult, even with two direct dependencies. Instead, you can use cargo-script, which handles all of this for you:
cargo install cargo-script
cargo script -D hyper -D serde_json script.rs

How to run cargo with features flag

I'm trying to learn rust by writing CLI but i can't do cargo run with features passed and i don't understand why. I read docs / stack and i still don't see why this is happening. It feels like it should work this way https://doc.rust-lang.org/cargo/commands/cargo-run.html
I'm trying to run this code
https://github.com/clap-rs/clap/blob/master/examples/17_yaml.rs
with command cargo run --features=yaml or cargo run --features yaml. I tried many combinations, none of them worked.
My Cargo.toml looks like that:
[dependencies.clap]
version = "*"
default-features = false
features = ["yaml"]
When i run i have error:
:!cargo run --features=yaml
error: Package `fun v0.1.0 (/Users/XXX/Projekty/rust/fun)` does not have these fe
atures: `yaml`
shell returned 101
What am i doing wrong?
Their code expects you to have cloned the clap repository, changed into its directory, and then run cargo run --features yaml --example 17_yaml from there. You can read more about how the cargo examples feature works here.
If you’re planning on copying their code, as noted in that example code, you have to remove this conditional compilation attribute:
// Note: If you're using clap as a dependency and don't have a feature for your users called
// "yaml", you'll need to remove the #[cfg(feature = "yaml")] conditional compilation attribute
#[cfg(feature = "yaml")]
fn main() {
Otherwise it will load this other main implementation and emit that error:
#[cfg(not(feature = "yaml"))]
fn main() {
// As stated above, if clap is not compiled with the YAML feature, it is disabled.
println!("YAML feature is disabled.");
println!("Pass --features yaml to cargo when trying this example.");
}
You don’t actually need to pass --features on the command line unless you are running their example within their crate as described above. You should also remove this whole function if you’re copying their code! It is only relevant when run as an example.

Resources