ignore tests in crate nested in workpace - rust

I have a crate nested in a workspace as a git subtree folder, and I don't want to run any tests on that nested crate whenever I run cargo test in the workspace. Is there a way to tell it to ignore this particular crate?

Related

Can we use my own crate repository url in Cargo.toml to download the dependencies

I have my own repository, where I have list of rust crates. When I run the command "cargo run", i want cargo to download all the dependencies from my crate repository url instead of crates.io. To achieve this what configuration need to be done
Looking for some suggestion or code snippet for the same

What's the best way to declare a non-rust repository as a dependency in a rust project?

I have a rust project where I want to use protobuf definitions that exist in another, non-rust repository.
I'm planning to download the protobuf repository, create a src/common_protobuf module in my main repository, use cargo build to generate all the rust implementations of each protobuf into the common_protobuf module, then selectively re-export the generated structures into their intended modules with pub use.
I can't seem to find the best way to specify the dependency. Using
[build-dependencies]
pbrepo = { git="https://github.com/username/pbrepo" }
results in
Caused by:
Could not find Cargo.toml in `/Users/username/.cargo/git/checkouts/pbrepo-33abcde7dddd6356/fdefgd9`
I can't commit a Cargo.toml into the external repository. I considered using a git submodule or making a sys-crate with the submodule and Cargo.toml but I prefer to have my build dependencies in a single place and not have to synchronize multiple repos during a build.
I could download the repository manually in the the build scripts and set the commit to pull in my build.rs but again I would like to have all my build dependencies in one place.
Is there a mechanism to accomplish this or is this a better way to use remote protobuf definitions?
Cargo does not support downloading non-Rust dependencies. The only things that you can have Cargo download for you are Cargo packages (loosely “crates”).
Even if you added a Cargo.toml to your non-Rust repository, that would not help, since there is no way to ask for the location of that dependency to read from it. Cargo's dependencies mechanism lets you depend on a built library only, not its source files (as far as I know; I could have missed something).
You will have to use some separate procedure that downloads the dependency (custom script, git submodule…) before running cargo build.
I'd use cargo-make
It allows for more complex dependency tracking and building things from other languages.
Since you can't use Cargo directly, you have to resort to a higher-level mechanism, such as Git submodules, which can be downloaded automatically before building via build.rs. This way cargo build will both fetch the submodule and build your project in a single command.

How to find the current version of a Rust library?

The Cargo.toml file requires me to state the version of a dependency, e.g. rand = "0.6".
I want to use the package rand_pcg, but don't know the version. How may I find it?
Use the web
crates.io
Navigate to https://crates.io/, type your crate name into the search box, and see the version. You can also click the clipboard icon to copy the complete dependency to add to Cargo.toml.
docs.rs
Navigate to https://docs.rs/, type your crate name into the search box, and see the version. If you click through to the crate, you can then click the clipboard icon to copy the complete dependency to add to Cargo.toml.
lib.rs
Navigate to https://lib.rs/, type your crate name into the search box, and see the version. If you click through to the crate, you can then click on the "installation" tab to see the complete dependency to add to Cargo.toml.
Use the command line
cargo build
Add the wildcard dependency to your Cargo.toml (e.g. rand_pcg = "*"). Run cargo build and note the version it picked (e.g. Compiling rand_pcg v...) or look in Cargo.lock for the entry for the crate. Edit Cargo.toml to use this version.
cargo add
Install cargo edit then run cargo add rand_pcg. This is my preferred route.
See Is there a command to automatically add a crate to my Cargo.toml? for more.
cargo search
As mentioned by user2722968, you can run cargo search rand-pcg and it will output the dependency line.

How can I force `build.rs` to run again without cleaning my whole project?

How can I force build.rs to run again without cleaning my whole project? I checked cargo build --help but I couldn't find anything related to build.rs.
If you print
"cargo:rerun-if-changed=<FILE>"
the build will be triggered every time the file has changed.
rerun-if-changed=PATH is a path to a file or directory which indicates that the build script should be re-run if it changes (detected by a more-recent last-modified timestamp on the file). Normally build scripts are re-run if any file inside the crate root changes, but this can be used to scope changes to just a small set of files. -- source
I'm not aware of a solution without changing a file manually (I just put a whitespace anywhere in my build.rs, it will be removed by rustfmt though).
I have several buildscripts in my projects, and mostly these two lines give me a nice solution:
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=path/to/Cargo.lock");
but I guess you are looking for a command rustc/cargo command. Anyway, you can put in a small script, which will edit a certain file, which will trigger the build-process.
Register build.rs as a crate's bin target:
Add this to your Cargo.toml file:
[package]
edition = "2018"
build = "build.rs"
[[bin]]
name = "force-build"
path = "build.rs"
required-features = ["build_deps"] # only needed for build-dependencies
If you have any [build-dependencies] (e.g. some_crate = "1.2.3"), you need to add those to (the main) [dependencies] (sadly no [bin-dependencies] as of yet), but you can make them optional:
[dependencies]
some_crate = { version = "1.2.3", optional = true }
[features]
build_deps = ["some_crate"]
Then you can run the build script with:
$ cargo run --bin force-build --features build_deps
(or $ cargo run --bin force-build when no [build-dependencies])
You can even disable the automatic call of the build script by replacing the build = "build.rs" line in Cargo.toml with build = false
Note: since the OUT_DIR env var is not present for bin targets, if your build.rs script uses env!("OUT_DIR"), you may "fix this" by using concat!(env!("CARGO_MANIFEST_DIR"), "/target/") instead.
If build.rs changes, Cargo already rebuilds the project:
Note that if the build script itself (or one of its dependencies) changes, then it's rebuilt and rerun unconditionally, so cargo:rerun-if-changed=build.rs is almost always redundant (unless you want to ignore changes in all other files except for build.rs). doc
On Linux, I will just do touch build.rs && cargo build. For Windows, see Windows equivalent of the Linux command 'touch'?
If you got target under gitignore (which you should) this might be useful for any file changes when you're developing and testing the build script.
if Path::new(".git/HEAD").exists() {
println!("cargo:rerun-if-changed=.git/HEAD");
}
if you're trying to rebuild based on non-rust or include!() files that might've changed, you can use
const _: &[u8] = include_bytes!("foobar.baz");
to ensure that any changes to those files will trigger a new build. pretty sure this solution adds neither time nor filesize.
you can shove this into a macro too, so its easy to do a bunch of files.
macro_rules! build_on{($file:literal) => {
const _: &[u8] = include_bytes!($file);
}
build_on!("foobar.baz");

How to package source code from outside the project directory with Cargo?

I am trying to create Rust bindings for the C++ library cryptominisat. The actual code works, but I'm not sure how to properly package it up with Cargo.
The git repository looks like
src/
c++ code here
.gitignore
readme, etc.
I added a rust directory, and created my Cargo project inside of it like so
rust/
cryptominisat/
Cargo.toml
build.rs
src/
rust code here
src/
c++ code here
.gitignore
readme, etc.
Unfortunately, cargo package doesn't seem to want to package up anything outside of the rust/cryptominisat directory, which means it doesn't include the C++ code needed to actually build the library. What can I do? I don't want to move the entire repository into the rust directory if I can avoid it, since that would make it impossible to merge upstream.
The way it's generally solved:
Use a git submodule (or a script run before publishing) to embed a copy of the C++ repo inside the Rust repo (e.g. in rust/cryptominisat/vendor/). During development you could use a symlink instead to avoid having two copies of the C++ code.
Use build.rs to download a tarball/clone/rsync the code at build time. You can dump it into OUT_DIR env var specified by Cargo to avoid polluting user-visible directories.
Make the C++ code a system-level library. The Rust package would not build it, but expect it's already installed, and only search for it and specify link flags for it. That's how most *-sys crates work.

Resources