Package managers like Cargo, pip, and npm are indispensable tools in software development because they quietly handle language-specific dependencies for you. But unfortunately they’re not so great at installing dependencies written in other languages (we call these external dependencies). One of the classic examples is Nokogiri, a widely used XML and HTML parser for Ruby, whose dependency on a C library called libxml2 has caused great consternation for Ruby devs over the years. More recently, external dependencies like OpenSSL and libiconv have proven troublesome for Rust developers.
One half-solution to this problem is to list these external dependencies in the project’s documentation so that developers can install them on their own. Sometimes, projects go a bit beyond that, providing detailed installation instructions for developers in different situations. And occasionally, external dependencies aren’t even mentioned and developers are on their own to provide them, which usually means Googling and StackOverflowing—and wasted time.
Like many of you, we’ve grown weary of half-solutions. We want to be able to
clone a project,
cd in, and have external dependencies quietly taken care of,
and so we built a tool called
Riff that addresses this problem
head on. Today, we at Determinate Systems are
thrilled to announce its initial release.
Introducing Riff #
Riff is powered by Nix, the purely functional language and package manager behind NixOS, Nixpkgs, and many other projects. But don’t worry: we built Riff to solve your problems without requiring you to use, understand, or even care about Nix at all. Riff is powered by Nix but not another Nix tool.
So let’s take a look at Riff in action. Prost is a popular Rust crate that provides a Protocol Buffers implementation for Rust. But on most systems, the build is doomed to fail due to missing external dependencies:
On Linux you get a
linker cc not found error, while on macOS you get
library not found for -liconv errors. Annoying! Even worse, any project that depends
prost produces the same error. Now let’s try it with
riff run cargo build
And it works! So what has happened here? Riff has:
- read your project’s
- determined which external dependencies are necessary based on your crate dependency graph,
- used Nix, with zero user input, to install external dependencies in
/nix/store, and finally
- assembled a shell environment that doesn’t interfere with anything else on your system.
cargo build command here runs inside that Nix-built shell
environment. In fact, you can enter that environment at any time and run arbitrary commands:
# Enter the Riff shell
# Back to your standard shell
The first time we showed Riff to a user, they were quite surprised and even confused: how could it have been so straightforward? What on Earth quietly happened in the background? That’s the energy we’re going for with Riff: development environments that just work and require, at most, a teensy bit of configuration.
We’re confident that Riff will provide lasting benefits to the Rust ecosystem (and other ecosystems later). Rust is a fantastic language with incredible tools but it has its limits. External dependency problems introduce breakage points into the dependency graphs of many Rust projects. With Riff we hope to cover this “last mile” problem in Rust development and make the entire developer experience more robust.
Find out more about how Determinate Systems is transforming the developer experience around Nix
Future horizons #
If you’d like to discuss Riff with other users, you can join the Discord for Riff.