How to set an env variable that lasts until the building finishes? - rust

How to set an env variable using config.toml or Cargo.toml that lasts for the end of the building time.
Setting it in config.toml doesn't help because I want to use some combined values as follows.
[env]
VAR="${pwd}/d --g ${pwd}/aaa"
Note that I can't use build.rs too because I want the env var to be set until the building finishes.
I think rust devs shoulld add some more thing like build.rs but execut it before building the dependencies.

Related

Can a Rust crate dependencies be installed globally?

I'm creating a monorepo using Nx, Rust and TS. The Rust code is divided in crates, and since I'm using Nx, I've not used Cargo Workspaces. The problem I'm facing now is that every re-install the dependencies of the crates it depends on, needlessly increasing the size of target/debug/deps.
I'm looking for a way to install/store the dependencies in a unified – probably global – location, that can reduce this dependency duplication, like pnpm does for javascript. I know that cargo already caches the packages' source code globally, which is great, but it still stores the compiled objects in the target/debug/deps.
Its not possible but as #drewtato said you can use sccache to cache the crates to speed up build times. You can also try using a faster linker like mold to speed up linking
To use sccache (after installed):
(adapted from sccache readme)
Add this to your global cargo config $HOME/.cargo/config.toml or project cargo config project/.cargo/config.toml
[build]
rustc-wrapper = "/path/to/sccache"
You can also use the env var export RUSTC_WRAPPER=/path/to/sccache

What the difference between Cargo.toml and .cargo/config.toml

I am learning to write a kernel by using Rust.
I added [dependencies] bootloader = "0.9.8" to .cargo/config.toml, but I got an error.
I forgot the specific error, but when I move [dependencies] bootloader = "0.9.8" to Cargo.toml and then run "cargo bootimage" on terminal, everything goes well.
Cargo.toml is where you put everything your project need. Dependencies, project details, project settings etc..
cargo/config.toml is a configuration file for Cargo. You usually don't need to touch it, and it usually uses more advanced things. It can be configured per project, although also globally. It sets for example what commands Cargo will run, what environment variables it will set, etc..
All details about both are in the documentation - Cargo.toml, config.toml.

How to cargo build only target but not dependencies

I work on a Rust project that has a lot of packages as explicit or implicit dependencies (~420). When I want to rebuild the target after changing the .env file (that configures things like IP to download files from), I would like to rebuild only the packages that I authored, not all the dependencies.
How can I tell cargo build to use the previously compiled dependencies, but not use the previously compiled package that uses the .env file as input?
Ideally, cargo build would realize that the .env file has changed and automatically decide to rebuild only the parts that use the .env file, but unfortunately this doesn't seem to be the case.
So the second best solution is to manually tell cargo build at which point in the build graph to start off again.
We're using the dotenv crate https://crates.io/crates/dotenv crate to read the .env file.
I tried cargo clean -p nextclade to tell it to clean only the package in question that I'm working on - but that still cleans up all the dependencies which cause my build to take 5 minutes rather than 2 minutes (if using compiled dependencies).
There's a question that seems to ask a similar question, but that question is actually a different use case/set up, so it's not a duplicate: How does cargo decide whether to rebuild the deps or not?

How to I use env variables in npm scripts

I'm building and signing an Electron app and I'm trying to contain my certificate location and sha pass to an environment variable.
Is this how I pass the env variables to an npm script?
"electron-pack-win": "CSC_LINK=process.env.REACT_APP_CSC_LINK CSC_KEY_PASSWORD=process.env.REACT_APP_CSC_KEY_PASSWORD build --win
Worth mentioning that I'm using create-react-app
Based on the comments,
Your .env already contains REACT_APP_CSC_LINK.
All you need to do is define a variable in the .env
For example,
REACT_APP_CSC_LINK=some_value
CSC_LINK=some_value
Electron will be able to access the environment variables using process.env.CSC_LINK
The ambient environment variables will be passed through to the script/program being run by npm, so if you set something in your shell - on Windows,
set CSC_KEY_PASSWORD=hello
or in Bash shells,
export CSC_KEY_PASSWORD=hello
, they will be available to the program being run.
Only if you want to override some values would you use the syntax you mentioned (or cross-env to be cross-platform compatible).

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");

Resources