I have a recurring problem that has taken two shapes now:
In a simple Nix configuration for a project, I have repeatedly created a shell script called project-root in shell.nix that determines the project root by recursively walking backwards until shell.nix / .git occur. I think this is a recurring problem, e.g. Cargo solves it with cargo locate-project.
When transitioning to dendritic flake-parts modules using import-tree, I’ll have e.g. ./nix/devshell/flake-module.nix (or just ./nix/dev-shell.nix) that might refer to some file at the project root:
{ inputs, ... }: {
perSystem = { pkgs, ... }:
let
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml;
in
...
}
And I can’t help but think that those relative paths are sensitive to refactoring, as well as a little ugly.
I can imagine a similar custom job of having a flake-parts module that exports a project-root output that other flake-parts modules can rely on. But I can’t help but wonder: Since I have this problem repeatedly, is there a standard way to do it with Nix (with or without flake-parts modules)?
And that will re-copy that file to the store, so don’t do that. (Not to mention it will cause rebuilds every time you change the flake if you use that path in a derivation.)
You can use (self + "/path/to/thing") but in many modules and in derivations that path will get silently stringified (leading back to said issues). The only place this really works is in imports, but that doesn’t seem to be what OP is using here.
You’re right, those were just local assumptions. In one current case I’m hosting various projects in a subdirectory, but thinking about it, it’s probably more stable to use "$(git rev-parse --show-toplevel)/subdir" and let git figure out the traversal, since git is a common denominator.
Thanks a lot for chiming in, because I would have went with this (very aesthetic solution) and learned of the cost the hard way.
For any future readers: “silently stringified” means: even though it will resolve to an absolute path outside of the nix store, e.g. /home/sshine/Projects/foo/rust-toolchain.toml, when used directly in my flake, the moment this flake gets imported into some other context, it might end up in the Nix store anyway, resulting in the same copying of the flake.