-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
provide getDerivationEnvironment
as a primop to reference nix develop
drv from Nix code
#7468
Comments
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/what-would-you-like-to-see-improved-in-nix-cli-experience/24012/9 |
I would actually be very much against that precise proposal, because I would like to push for the exact opposite: move the logic behind
It's actually not that hard. IIRC |
This already exists in nixpkgs as |
looks like
I didn't think that it would be hard, just that it would randomly drift from the C++ implementation as time moves forward. Having the canonical implementation in Nix sounds reasonable though. I might even be able to implement it myself to close this. We already have |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/what-would-you-like-to-see-improved-in-nix-cli-experience/24012/14 |
@infinisil, the edit |
A derivation can't be sourced. It's nothing more than an instruction to run any builder. What you're looking for needs to be done at the Nixpkgs level. That's the component that is aware of what is inside some derivations, and it may perhaps let you query such things. Or you could assume that it's stdenv-based and just If nix shells were implemented this way in the first place, your use case would have been trivially easy: just return that "specific package attribute". Let's call it |
Well I've already almost reproduced the same derivation (same output, but not same derivation hash due to minor differences) as What I got so far is without any dependency on nixpkgs by calling I was already thinking that maybe we should attach this at the attribute level as meta-data, to do basically exactly what you suggest. But devshells are so prominent in Nix, it seems to make sense to do this as a built in functionality. That is, basically every derivation has to be build, that build has some sort of environment, so every derivation could have a If the end result is referencable in Nix code, it seems to me that it matters less if the implementation is in Nix or C++. |
libc is also very prominent in Nix, but we don't build it in, so that we can change it out and customize it to fit our needs. This has worked out rather well, spawning an entire ecosystem of very successful projects, each maintaining their own libc without our involvement, to fit the needs of various libc-consuming niches. We've grown accustomed to |
I'm not voting for one way or the other, just that we at least have a canonical implementation which the cli uses, but can also be referenced from in plain old Nix code. Relying on all of nixpkgs feels like a mistake when its so simple to do it raw nix, but maybe its not, or maybe we can just have it live somewhere else. |
I copy @roberth 's principled appreciations and the assertion that we've become path-dependent on architectural mistakes. I would hope that this subject may even enter the Nixpkgs Architecture Team in its appropriate moment. I can follow the argument of the The layer violation might be actually one of layer collapse. Such that there isn't a layer for canonical implementations in between Being able to swap that for That means an implementation in |
I suppose that would be an alternate reality where |
Not at all. Apologies for my impure speech: my argument is that |
The idea here is that future Nix first tries to "`nix run`" the `pkg.devShell` package, and only if that fails, fall back to the legacy `nix develop` (or `nix-shell`) behavior. This allows the development shell to evolve with stdenv, and it allows packages to individually customize the `devShell` attribute, by setting `passthru.devShell`. Furthermore, these shell behaviors will be pinned to the expressions, allowing changes to be made in a more agile manner, unlike Nix, which has to be very careful not to break old expressions, as users can not revert Nix. To give it a try: nix run .#hello.devShell In the future this will be equivalent to: nix develop .#hello Isn't this the responsibility of Nix? It is not. `nix-shell` and `nix develop` are a great user interface, that everyone loves, but their implementation is a pile of hacks on top of stdenv. Instead of coercing stdenv to do what `nix-shell` needs it to, we can ask stdenv politely to provide a shell. Now that Nix doesn't have to assume a package comes from stdenv, there's a possibility for experimental builders to provide shells too. What does this break? Only packages that define a `devShell` attribute (for some reason?) have to adapt to the suggested new Nix behavior. Note that a `devShell` value for the builder can be overridden by `passthru` without affecting the build or shell. Packages and shells pinned to older versions can still be loaded because Nix keeps the legacy behavior as a fallback. But this still relies on `nix-shell` to provide a shell??? Fair enough. This is only a proof of concept. The goal is to replace that invocation by a script or program with the same or better behavior, without relying on `nix-shell` as its implementation. Does this solve the need for `.env` for Haskell package shells? Not in this commit, but Haskell packages will be able to produce their own `devShell` attribute, which is derived from the .env derivation rather than the regular derivation. Refs - NixOS/nix#7468 and a bunch of other issues where I've preached about this idea.
I figured I can't just keep preaching about this idea forever, so here's some code to illustrate the idea. |
Is there some document already that explains why this is an architectural mistake? Also, how do you account for the fact that the Although I accept that isn't always what we want either. Some times I want the build environment, sometimes I want a more convenient interface like numtide/devshell. Assuming we can find some solutions though, I'm not against just evaluating a derivation attribute, but then I'm not entirely convinced that shells built into Nix is neccesarily a mistake either, just that the current implementation definitely is. Derivations already produce some meta attributes that are built in, not dependant on nixpkgs, such as the It's possible that we need to mimic the flakes API here and do a |
So, the way I see it is that @nrdxp, you would like to see language level contracts on the
A broken
That is an interesting idea and maybe NixOS/nixpkgs#206728 would want to consider and adopt or discard this? |
I guess, it's a fair answer to reference (still very fresh): divnix/std@c54501e |
Closest thing is my analysis of shell uses cases buried here #4715 (comment)
This can be part of the contract, as blaggacao suggests.
My use of this in the proof of concept is as an implementation detail. A shell could equally well be constructed from the I'd like to focus on the interface alone: a |
Is your feature request related to a problem? Please describe.
Say I want to write a script that first enters a devShell with
nix print-dev-env
before executing its task. There is currently no way to make the*-env
drv produced bynix develop
andnix print-dev-env
referencable in the Nix code so as to make the devshell a proper dependency of the script.This may seem like a non-issue since the act of running
nix print-dev-env
will simply eval and build the shell deriation at runtime, but what if we want a clean separation between buildtime and runtime for environments like CI that want to track the build step for caching, etc?You might think that you could just place a comment with a reference to the outpath of the derivation itself, but what if that derivation is a heavy build and you don't actually need the binary, you just need its build env? Also, your script will be that much lighter if it doesn't have to depend on the nix binary to make a single call.
Describe the solution you'd like
A simple primop that basically executes getDerivationEnvironment (modified appropriately) on any derivation passed to it, returning the resulting environment drv seems like it should do the trick.
Describe alternatives you've considered
Perhaps there is already a way to do this that I'm just not aware of? If we carefully craft a function in Nix code that does the same thing as
getDerivationEnvironment
we could theoretically end up with the exact same result, but that seems more error prone.Additional context
In divnix/std-action we make a clear separation between eval time, build time, and run time. The build time dependencies are tracked, and that's how we can ensure they are always sent to our binary cache, even in the event that the task runtime fails. We also track packages that are already built and skip builds if possible. If we don't have an accurate representation of the dependency graph, this logic can be less effective, where the goal is to do as little work as possible.
I am finding it tricky to solve this for some of our tasks at work that call
nix print-dev-env
from a script. For now I have a comment referencing the derivation, but this isn't exactly right since the derivation isn't the same as the onenix print-dev-env
actually calls.The text was updated successfully, but these errors were encountered: