Introducing envcache
One thing that has always bugged me with Rust is when you are interacting with
complex non-Rust software. Yes LLVM, I’m looking at you! LLVM nearly always
requires you to either a) have llvm-config
on the path already, or b) find an
LLVM install in some random place on the filesystem. I generally like to have a
version of LLVM built myself (using RelWithDebInfo
and forcing asserts on)
that will naturally live at some arbitrary point in the filesystem - and then I
want to somehow point my Rust code that is using LLVM at that folder.
The general way to do this in Rust is to use an environment variable, and then
in a build.rs
you can grab all the paths to the LLVM libraries for linking in.
For instance the llvm-sys crate has an
optional feature no-llvm-linking
that lets you control where LLVM is sourced
from. I use this in a project I’m cooking up to control how LLVM is brought into
my project. At present my workflow is something like:
LLVM_INSTALL_DIR=llvm-install cargo test
cargo clippy
If you can see the problem already - when I run other commands on auto-pilot
like running cargo clippy
, and I do not specify the LLVM_INSTALL_DIR
,
the command fails to run because it requires LLVM_INSTALL_DIR
to be specified.
Coming from a primarily CMake based workflow with my day-to-day job working with LLVM, this completely does my head in. CMake has a way to cache variables and then subsequent commands re-use the cached value. So I got thinking - why can’t I do something similar in Rust?
I’d like to introduce a simple, dumb, but useful little crate -
envcache. This crate lets you cache any
environment variables you want so they can be used across cargo commands. For
example, in a build.rs
:
extern crate envcache;
use envcache::EnvCache;
fn main() {
let mut envcache = EnvCache::new();
envcache.cache("LLVM_INSTALL_DIR");
}
By doing this simple thing above, it’ll let me specify LLVM_INSTALL_DIR
once,
and then have this cached value used thereafter for subsequent commands.
This works by saving a file in the OUT_DIR
that you can write to with
build.rs
- envcache.config
. Crucially this means that if you run
cargo clean
it’ll wipe out the cache, and you’ll need to re-specify the
environment variable. But it does mean you have to specify the environment
variable much less in general development which I find to be much nicer.
The source code is available here, and I hope this is useful to some of you.