-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add devenv.nix
enheritance mode (instead of composition)
#1675
Comments
I feel what you're looking for should be possible. I guess we'd need to see your Devenv configuration to say for sure, but it sounds like your root project's Looking at how drupal-devenv works might help. I think it has a very similar objective to your root config + sub-projects idea. That is, it provides a root config that any project can build on (but override if necessary). Besides the way that project sets up its imports, it uses Does this help? If not, it would be good to see your actual config, or at least a cut-down sample of it, to get more context. |
I think my last post may not be helpful after all, sorry. Assuming the desired setup includes importing nix config from a parent directory, a limitation with Nix Flakes stops this currently. See #1239 Does the configuration in that issue demonstrate the problem you're having? Edit: it may still be possible to use parent config, as long as you can add an input for the parent directory like this example Also, damn this is confusing. |
I don't know if I can use relative path in The example is huge, but I don't see how I can import the base config, which is the main problem. Because of this, I had to move to a flake, and with a bit of help from people I realized that I can define all devshells in a single flake and then just choose the right one in different directories. Though I don't know if I can inherit with flake, maybe by using proper module system, but I was able to achieve the same result with a template function. The function produces the base config, subdirs can override stuff in it, but if they don't need something, then it will be added separately to the base config when calling the function. So the subdirs will also call the same function and add something else. I actually later realized that I only need the same config for all subdirs, so in total I only need 2 devshells. flake{
inputs = {
nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling";
systems.url = "github:nix-systems/default";
devenv.url = "github:cachix/devenv";
devenv.inputs.nixpkgs.follows = "nixpkgs";
};
nixConfig = {
extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
extra-substituters = "https://devenv.cachix.org";
};
outputs = { nixpkgs, devenv, systems, ... }@inputs:
let
configTemplate = system: overrideFunction: devenv.lib.mkShell {
inherit inputs;
pkgs = nixpkgs.legacyPackages.${system};
modules = [
(
{ pkgs, lib, ... }@localInputs:
let
overridesFor = x: (overrideFunction localInputs).${x} or { };
in
rec {
env = {
main = "src/main.typ";
out-dir = "dist";
pdf = "${env.out-dir}/out-name.pdf";
} // (overridesFor "env");
packages = with pkgs; with env; [
git
mupdf
] ++ (with builtins; (lib.mapAttrsToList
(name: value: writeShellScriptBin name value.exec)
(lib.filterAttrs (name: _: !elem name [ "setup:init" ]) tasks)
));
enterShell = ''
echo Available aliases:
${builtins.concatStringsSep "\n" (
lib.mapAttrsToList
(name: value: "echo ${name} = ${lib.escapeShellArg value.exec}")
scripts
)}
echo
'';
scripts = with env; rec {
edit.exec = ''"$EDITOR" ${root}/${main}'';
compile.exec = "app:compile";
clean.exec = "clean:everything";
e = edit;
co = compile; # Can't unalias c, r, w, cl, ca, cln
cle = clean;
# ...
} // (overridesFor "scripts");
tasks = lib.recursiveUpdate
(with env; {
"app:compile".exec = ''
mkdir -p ${root}/${out-dir}
compile --root ${root} ${root}/${main} ${root}/${pdf}
'';
# ...
"clean:everything".exec = "rm -rf ${root}/${out-dir}";
"setup:init".before = [ "devenv:enterShell" ];
})
(overridesFor "tasks");
}
)
];
};
root = ''"$DEVENV_ROOT"'';
forEachSystem = nixpkgs.lib.genAttrs (import systems);
in
{
devShells = forEachSystem (system:
rec {
default = base;
base = configTemplate system ({ pkgs, config, ... }:
{
scripts = rec {
zip-all.exec = "zip:all";
zi = zip-all;
za = zip-all;
};
tasks = with config.env; {
"zip:all".exec = ''
cd ${root} || exit 1
mkdir -p ${out-dir}/${out-name}
cp ${pdf} ${out-dir}/${out-name}
${pkgs.fd}/bin/fd '.*' ${root}/src -It f -e pdf -X cp '{}' ${out-dir}/${out-name}
rm -rf ${out-dir}/${out-name}.zip
${pkgs.zip}/bin/zip -r ${out-dir}/${out-name}.zip ${out-dir}/${out-name}
rm -rf ${out-dir}/${out-name}
'';
};
});
lab = configTemplate system ({ config, ... }: {
env.pdf = ''...'';
});
});
};
} The boilerplate is pretty big, since I practically do everything myself, but it does work. Then I just use But having a more native approach would be nice, as it will not only significantly cut down on the LoC, but also return the ability to run tasks, since with flake version there is no |
Yeah, I think so.
Uhhh, I cannot comprehend what that file does. Truly a peak of hackery. |
Ah, I didn't explain myself very well. In the example of drupal-devenv: drupal-devenv is the root config and the user's project is the sub-project. The Getting Started section shows how to import that root config into your sub-project. The difference in your case: the root project is inputs:
nixpkgs:
url: github:cachix/devenv-nixpkgs/rolling
rootProject:
url: ../
flake: false
imports:
- rootProject When I tried this, however, it resulted in some buggy behaviour from rootProject:
url: /home/liam/code/devenvtest
flake: false Which worked! For context, the full path to my sub-project So, I think the reason it didn't work is a bug in Devenv when using a relative path for an input, and a workaround is to use an absolute path instead. That's unsatisfying and not portable, but it may be less complex than using a Flake. I like that usage of an override function in your Flake. It's a clever solution to the problem 👍 |
Thanks. Yeah, I don't want to use the absolute path, since it's all version-tracked. From #1239 (comment), I guess it confirms that this is due to flake shenanigans (rules). So unless something clever is done, I don't think this will be possible. |
That's understandable. Another workaround might be to reference the repo by URL, using access-tokens to allow access (assuming it's private), that's also not the best and probably involves too much manual setup.
Yeah, my attempt at importing the parent directory did it slightly differently than that comment, and didn't hit that rule. However, it still didn't work. In case you (or anyone else reading this) is interested: instead of concat-ing the lines from the two devenv's So, given these enterShell = ''
echo "hello from parent";
''; enterShell = ''
echo "hello from sub-project";
'';
hello from sub-project
hello from sub-project Hopefully this issue will be fixed by #1548. |
In my project, I have the root config and a few sub-projects. The sub-projects are basically a copy of the root, but with some changes. So I want to switch from composing sub-config into main one to inheriting the things from the main config into sub-projects. The easiest example is the use of same packages and same scripts/aliases.
Currently, I need to duplicate everything in all config, but in the root one additionally use
lib.mkForce
. This is super bloated, even worse than having separate configs (because you don't have to uselib.mkForce
).What is the best way to "reverse" the current behavior? Maybe there is another tool for this?
The text was updated successfully, but these errors were encountered: