This is a pretty old thread, but I found myself here today while looking for something similar.
Rust workspace projects are tough, because in order to run workspace commands, cargo
needs all of the entrypoints for all of the workspace packages present, e.g. the main.rs
and lib.rs
files usually. It does not need all of the rust files though: it only needs those for the package it’s building and any of its dependencies. Previously, I was including a ton of unneeded stuff from the repo root in the nix sources with a big, nasty filter function, which led to a lot of unnecessary rebuilds when changing unrelated files, and I was looking for a better way to do it.
I wound up combining the logic of sourceByRegex
and sourceFilesBySuffices
to make a function I could use to filter files by regex pattern, rather than needing to worry about making sure that each directory and nested directory was included. This allowed me to set up a standard list of regexes needed for all rust projects in the workspace, like:
# Regular expressions for files relative to the workspace root
rustWorkspaceSrcRegexes = [
# Cargo.lock at the workspace root
"^Cargo\.lock$"
# Any cargo.toml file anywhere
"^(.*/)?Cargo.toml$"
# Any main.rs file anywhere
".*/main\.rs$"
# Any lib.rs file anywhere
".*/lib\.rs$"
];
Which list I could expand on when generating sources for an individual package to include what it needed. Here’s the function I wound up with, almost identical to sourceByRegex
except for the type == "directory"
condition. This might be bad in various ways, but it’s super useful to us.
srcByRegex = src: regexes:
let
isFiltered = src ? _isLibCleanSourceWith;
origSrc = if isFiltered then src.origSrc else src;
in
lib.cleanSourceWith {
filter = (path: type:
let relPath = lib.removePrefix (toString origSrc + "/") (toString path);
in
type == "directory" || lib.any (re: builtins.match re relPath != null) regexes);
inherit src;
};
You can then use it like
# pass the path to the workspace root and regex patterns for anything you want to include
src = srcByRegex ./../.. (rustWorkspaceSrcRegexes ++ [ "regex-for-this-project's-files" ])
I actually ultimately wound up generating dependency regexes to pass to this function for local dependencies (i.e. foo = { path = "../../some-other-lib" }
) automagically from the Cargo.toml
, but that code is a bit hackier, so not including here.