Override the [[bin]] path parameter in `cargo run` - rust

I have a local playground setup with a bunch of experiment files (each with a main()), where my Cargo.toml looks like this:
[package]
name = "playground"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "playground"
path = "./experiment42.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
Right now, I'm manually changing the path parameter when I want to debug one or the other experiment and I want to override it in cargo run command.
I tried variants of --config <KEY=VALUE> based from the docs to no avail:
$ cargo run --config "bin.path = \"./experiment69.rs\""
# still runs experiment42.rs
$ cargo run --config "bin.'cfg(all(name = \"playground\"))'.path = \"./experiment69.rs\""
# still runs experiment42.rs
The overall goal is to run different files based on the currently opened file in my editor (which I can send to cargo run args). Adding new experiment files without editing Cargo.toml would be a nice bonus.

Since you want cargo to pick up your binary files automatically you could use cargos automatic binary detection by adding them to the directory cargo picks binaries up automatically, src/bin/ then you can remove all [[bin]] sections and run it with cargo run --bin yourbinaryfilename for the file src/bin/yourbinaryfilename.rs
For how to do this automatically for the file you've opened in your editor we'd have to know what editor you're using, but for vim you can call cargo with :!cargo run --bin %:t:r where %:t:r is the root of the current filename.

Cargo configurations (.cargo/config.toml) are different from the manifest files (Cargo.toml). --config <KEY=VALUE> is meant to override the former. A mechanism for overriding manifest values is proposed, but not yet implemented.
I ended up running a sed command before cargo for now, similar to the person in the linked issue:
sed -i -e 's/^path= .*/path = "%file_path%"/' Cargo.toml

Related

How can I run a command::new(...) during cargo clean?

While I am learning rust, I have a crude means of building a non-rust c/c++ library that lives in a submodule. My build script (build.rs) now looks like:
use std::process::Command;
fn main() {
// EXTERN_C
// Build the c-library
Command::new("make").args(&["-C", "cadd"]).status().unwrap();
// The name of the library to link to, i.e. like: -l<lib>
println!("cargo:rustc-link-lib=dylib=add_x64Linuxd");
// The library search path for linking, i.e. like -L<path>
println!("cargo:rustc-link-search=native=cadd/lib");
// The run-time library search path (LD_LIBRARY_PATH)
println!("cargo:rustc-env=LD_LIBRARY_PATH=cadd/lib");
}
This is working nicely, the makefile within cadd/ sorts out any build/re-build deps etc. The only thing I can't do at the moment is hook in make -C cadd clean when I run cargo clean. Ideally I would like it to run the clean make target at the same time. The command would look like:
Command::new("make").args(&["-C", "cadd", "clean"]).status().unwrap();
But I don't know how to get such a command to run during cargo clean. Is there a "clean script" like there is a "build script" - or another method?
Eventually I will get around to learning how to wrap up my makefile project into a cargo crate (I think that's the right terminology) - so I know this is not the optimal way to do this, but I want to get this working in a basic way first (so my head does not explode!).
The cargo clean command simply deletes the cargo target directory.
One solution is for your Makefile to output its compilation artifacts(all files it generates) into the target directory.
You could also change the directory cargo outputs its artifacts to, either via the --target-dir CLI option or by adding the following to the .cargo/config:
[build]
target-dir = "some/path"

How to set feature options for cargo build?

I use this kind of things:
#[cfg(feature = "myfeature")]
When I click "Build - Build Project" it calls cargo build. How can I specify that I want myfeature to be used? I found that I can specify it for my Run configuration but still it doesn't work for "Build".
On the command line, you'd use cargo build --features myfeature. In clion using the IntelliJ Rust plugin, you should be able to open the Cargo.toml file and tick the box next to the feature definition to enable it within the IDE, as demonstrated in this blog post.

How do I make a Rust program which can be executed without using `cargo run`?

How can I make a program in Rust which can be executed from anywhere without using cargo run, by just clicking on the file?
Is there any crate? I have written code for snake game and I want to run it by just clicking on a file.
If you compile a Rust application with:
cargo build --release
it will place a binary file in ./target/release. So if your application is called snake_game, you can run it with ./target/release/snake_game, or by double-clicking on that file.
This binary is completely self-contained, so you can move or copy it to somewhere else on your computer.
First build your binary for release
cargo build --release
Next handle permissions
Typically chmod +x target/release/whateverYourProgramIsCalled to make executable, but cargo did this for us already
You can check it's Octal Permissions
ls -l target/release/whateverYourProgramIsCalled
chmod +x target/release/whateverYourProgramIsCalled
ls -l target/release/whateverYourProgramIsCalled
As you can see nothing has changed... the permissions were already correct for executing
Run that executable
./whateverYourProgramIsCalled
Optional: run from anywhere
You can run that binary anywhere from the command line
To do this you need to add it to your path
For mac you can add to your path from /etc/paths
whatever editor you prefer.... vi, code, etc...
sudo code /etc/paths
I added a path like this, saved and authenticated with a password
/Users/`whoami`/code/rust/binaries
whoami command is surrounded by `
next copy your new binary over to where it needs to be, in that binaries folder
cp whateverYourProgramIsCalled /Users/`whoami`/code/rust/binaries
Then open a new terminal window
Check your command is in your path
where whateverYourProgramIsCalled
Run your command from anywhere
whateverYourProgramIsCalled
Rejoice
There is another method you can do by using rustc. It will create an executable binary file in the same directory where your file exists.
Make sure you are in the src directory and the name of your file is main.rs.
rustc main.rs
./main
The advantage of using rustc is that you can run any file not only main.rs. just do:
rustc filename.rs
./filename
You can run it from terminal and also by clicking on that file.
Just wanted to add another answer here, not sure if it's related to a more recent version of rust.
If in the root of your project you just run the command cargo install --path . it will add it to cargo and allow you to run the binary just with project name.

Using Cargo with my project's own directory structure

Can I use Cargo to build Rust code without using its standard project layout?
My source files are not in a directory called src and this will not change. My binaries must end up in the current directory (or, in some other projects, in a different directory that is not called target/SOMETHING). Can I tell Cargo that executable foo must be built from foo.rs and bar.rs in the same directory as Cargo.toml, and qux from foo.rs?
I don't care about Cargo as a build system or as a deployment system. I'm only interested in it as a library management system. Apparently Cargo is the only game in the Rust town for this.
Not really. You can control where the source files are by explicitly specifying them in the manifest:
[[bin]]
name = "foo"
src = "foo.rs"
[[bin]]
name = "qux"
src = "splong.rs"
I don't know what you mean by foo being built from foo.rs and bar.rs, whilst qux is built only from foo.rs. You can't just arbitrarily glob source files together: either foo.rs uses bar.rs, or it doesn't.
But you can't control the target directory from within the manifest. There's the build.target-dir setting (in Cargo's configuration, not the manifest), but that only lets you change the target directory, not the second level inside of it. You can change it using the CARGO_TARGET_DIR environment variable, though you can't set environment variables from within the manifest, either.
That said, setting CARGO_TARGET_DIR to the root of the project will also change where all the intermediate files go, and it'll mean every time you switch between debug and release builds, you'll have to do a full recompile.
You may want to consider opening an issue on the Cargo issue tracker about making this an option.

Where does Cargo put the git requirements?

When compiling a project, cargo automatically downloads the requirements, specified in the Cargo.toml, given as a git-repository.
E.g.
[dependencies.piston]
git = "https://github.com/PistonDevelopers/piston"
will result in
Updating git repository 'https://github.com/PistonDevelopers/opengl_graphics'
when compiling. Where does it save those repositories on my disk? I'm using Windows, does this change anything?
man cargo gives:
FILES
~/.cargo
Directory in which Cargo stores repository data. Cargo can
be instructed to use a .cargo subdirectory in a different
location by setting the CARGO_HOME environment variable.
Doing a git grep for CARGO_HOME finds https://github.com/rust-lang/cargo/blob/3533ff11c505017751d1e466685efe7084cbd96b/src/cargo/util/config.rs#L380-L384
which uses http://doc.rust-lang.org/nightly/std/os/fn.homedir.html

Resources