I want the submodule (which is not a flake) to be included in the flake source directory. What’s the best way to do this? I’ve tried the various permutations of url options from “nix flakes: add support for git submodules”.
What’s the input url supposed to be for a submodule in the flake’s directory? Checking out from remote works (very inefficient), and this specific combination of:
url = "file:///[snip]/submodule?submodules=1";
type = "git";
The only way I am aware of that would remove the necessity of specifying submodules=1 is to remove the submodule.
And I do not consider this unintuitive. You have to specify the argument to the input that has the submodules, if this input is self, then the only place where you can specify that is the CLI.
I’m definitely a nix novice, so you probably know more than me. But, I don’t think I’ve ever passed ?something to the nix CLI before and it’s undocumented AFAIK (excluding the github issue where people are similarly confused).
I guess “intuitive” is in the eye of the beholder, because the only place I specify self’s url is… nowhere. I don’t specify it. I expect nix develop (and direnv’s use flake) to just work.
Ok, I understand, but I do consider this to mean that flakes just don’t properly support git submodules and will work around it to the best of my ability.
In a real-world context, requiring users of my flake to know that they must add a “special” command-line parameter ?submodules=1 creates a condition where things “don’t work” by default.
I imagine it should be possible to set submodules=truewithin the flake, but my attempt so far yields an error:
outputs = {
self
} @ inputs: let
# error: attribute 'override' missing
self = inputs.self.override (old: { submodules = true; }); # overrideAttrs also doesn't work
in
{
# outputs
}
Another approach might be to specify the local directory as an input, and give it a submodules=1 parameter there.
This input specification works, but without including the submodule:
inputs = {
src = {
url = "file:.?submodules=1";
type = "git";
flake = false; # not including this results in inifite recursion
};
};
Another approach (and this may be the cleanest?) would be to set submodules as a toplevel flake variable, eg:
{
submodules = true;
inputs = {};
}
Interestingly, a nix replalready sees the submoduels toplevel attribute:
I think the fact that there’s no way to make self include submodules without having to inform the developer/user to specify ?submodules=1 is both unintuitive and inconvenient.
A normal behavior would be to call:
nix build github:example-org/example-pkg
And receive a built example-pkg binary. But instead you get errors about missing submodules.
Yes, it is unintuitive and this should be configurable in the flake.nix file.
I see someone has made an attempt to support this, but it’s not really moving:
I’ve realized that one way to avoid the .?submodules=1# UX nightmare is to declare the submodule as a discrete file-based input:
inputs = {
# ...
subproject = {
url = "git+file:subproject"; # the submodule is in the ./subproject dir
flake = false;
};
}
Then, any derivation(s) which rely on the submodule need to be extended to take the submodule as an input and need to deal with it manually; eg:
buildPhase = let
prefix = python3.sitePackages; # eg: lib/python3.11/site-packages
in ''
# copy entire package as a library
mkdir -p $out/${prefix}
${rsync}/bin/rsync -rl ${src}/ $out/${prefix}/
# same for 'subproject' submodule
mkdir -p $out/${prefix}/subproject
${rsync}/bin/rsync -rl ${subproject}/ $out/${prefix}/subproject/
# rest of build phase
This will work locally and in CI, as long as the submodule is checked out.
Then, when passing this toplevel project flake as an input to another flake, use submodules=1, eg:
url = "github:owner/project_name?ref=branch/name/with/slashes&submodules=1";
# this alternative also works:
url = "git+ssh://git@github.com/owner/project_name.git?ref=branch/name/with/slashes&submodules=1";
hmm, this really should work as long as the submodule:
is present in .gitmodules (git submodule add URL)
the commit adding the submodule to .gitmodules and pinning its version is present in the superproject’s git history (git add ./submodule && git commit)
the submodule is checked out (files present on disk: git submodule update --init)
Thanks for your response. Tried everything you have listed and a lot more but did not got it working unfortunately. Fixed it with a workaround fetching the git repo now from remote instead using a submodules, works flawlessly for my purpose.