-
-
Notifications
You must be signed in to change notification settings - Fork 159
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
[RFC 0014] Improve import from derivation #14
Closed
Closed
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
e837055
import-from-derivation: Copy template
Ericson2314 aa324c3
import-from-derivation: WIP draft
Ericson2314 d2b9b55
import-from-derivation: Add @expipiplus1 as coauthor!
Ericson2314 0c17f04
import-from-derivation: Add note about hydra.nixos.org to summary
Ericson2314 8736c3f
import-from-derivation: Mention that layering is preserved
Ericson2314 7311ed9
import-from-derivation: Add mention of the ultimate goal of less churn
Ericson2314 43caba7
import-from-derivation: Tweak wording
Ericson2314 16517a2
import-from-derivation: Fix misc typos, wording, formatting
Ericson2314 ec99095
import-from-derivation: Fix spelling of "shlevy", sorry!
Ericson2314 a8a5007
import-from-derivation: Fill in missing issue number
Ericson2314 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
--- | ||
feature: import-from-derivation | ||
start-date: 2017-05-19 | ||
author: John Ericson (@Ericson2314) | ||
co-authors: Joe Hermaszewski (@expipiplus1) | ||
related-issues: (will contain links to implementation PRs) | ||
--- | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Fix some issues with importing from derivations so it is nicer to use both manually and with CI. | ||
Once this RFC is implemented, hydra.nixos.org should allow importing from derivations. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Sometimes the entire dependent graph cannot be known statically (before any building). | ||
Examples of this would be a package with its own Nix-based build system—the dependency must be downloaded first, | ||
or leveraging a language specific build tool (Cabal, Cargo, etc) to generate a build plan. | ||
|
||
Import-from-derivation and recursive Nix are two ways to achieve this dynamism—the interleaving of planning the build graph and executing it. | ||
Implementation-wise, however, they are completely orthogonal so there's no reason not to work on both. | ||
|
||
Currently there are some issues with import-from-derivation, however. Per @shlevy's read-only recursive Nix RFC: | ||
|
||
- *Import-from-derivation breaks dry-run evaluation and separation of evaluation-time from build-time.* | ||
|
||
This is solved by simply making dry-run not build imported derivations. | ||
Those imports instead become stuck terms, and the derivations blocking them are enqueued. | ||
Moreover, the conceptual layering of the Nix language and the derivation builder is preserved: | ||
While yes, in non-dry-run mode the evaluator will still need to invoke the builder, the builder need not know anything about evaluation. | ||
|
||
- *Import-from-derivation won't work if your expression-producing build needs to run on a different machine than your evaluating machine, unless you have distributed builds set up at evaluation time* | ||
|
||
By not building during evaluation, we can use remote build machines just as usual. | ||
|
||
This RFC details the fixes to those problems. | ||
With these fixes made, hydra.nixos.org should change policy to allow importing from derivations. | ||
In turn, Nixpkgs can stop including auto-generated code, such as the dumps of Hackage. | ||
This will vastly decrease churn, decreasing growth of that repository. | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
The fundamental change is rather than evaluation unconditionally triggering execution, evaluation will suspend yielding the execution needed to be done so it can make further progress on resumption. | ||
This is probably easier to explain in terms of the implementation steps needed. | ||
|
||
## Black-hole unwinding | ||
|
||
There's currently a bug with `nix-repl` where if computation is interrupted (say with `SIGINT`), and the same computation is begun again, one will get an infinite recursion error despite there being no infinite recursion. | ||
This is because the thunks stay black-holed—the indication that they are currently evaluated—despite the computation being aborted. | ||
To fix this, we want aborted computations to instead unwind their stack, un-black-holing any thunks back the way they were before. | ||
Mathematically, black-hole unwinding ensures that evaluation is idempotent. | ||
|
||
## Partial evaluation | ||
|
||
The next step is to extend the Nix evaluator to support partial evaluation—i.e. evaluation in the presence of *stuck terms* which cannot be normalized. | ||
The partial evaluator, on encountering a stuck term, will unwind (while unblack-holing thunks) until it finds another thunk to force—forcing binary primops for example force both subterms. | ||
Eventually nothing is left to evaluate, and the evaluator returns. | ||
[This is all completely standard for partial evaluation.] | ||
|
||
## Import-from-derivation as stuck terms. | ||
|
||
To leverage our partial evaluator, we deem imports of derivations as stuck terms. | ||
We unconditionally evaluate the argument to `import`, but `import <unbuilt-store-path>` is stuck. | ||
The partial evaluator, on encountering stuck terms, will log the unbuilt derivations, and return the set of all encountered ones (in the case that evaluation is not total). | ||
|
||
## CLI | ||
|
||
This is taken from issue https://github.com/NixOS/nix/issues/666. | ||
`nix-build --dry-run` will do a single round of partial evaluation, and print out the set of unbuilt imported derivations just as it would the build plan in the case that evaluation doesn't complete. | ||
`nix-build --dry-run=n` will perform `n` rounds of evaluation, and then building unbuilt derivations, and then print the build plan or unbuilt imported derivations. | ||
`nix-build --dry-run` is thus a synonym of `nix-build --dry-run=0`. | ||
`nix-build --dry-run=infinity` is the semantics of `--dry-run` today—perform as many rounds as needed to get the final static build plan. | ||
|
||
Because we pause evaluation each round, we can build the imported derivations "normally". | ||
That includes taking advantage of build remotes, which avoids the problem of import from derivation DOSing the hydra evaluator and or imported derivations requiring a different platform than the evaluation machine. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
Overlap with recursive Nix. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have a link to what recursive Nix is? Just so the reader can compare. |
||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
Just do recursive Nix alone. @shlevy raised some other downsides of import-from-derivation, not solved by this RFC, which I'll address below: | ||
|
||
- *Import-from-derivation doesn't keep a connection between the build rule and its dependencies: the expressions imported-from-derivation are not discoverable from the final drv.* | ||
|
||
There is nothing stopping us from logging this as extra metadata, but I'm not sure how this information is useful. | ||
|
||
- *Import-from-derivation requires you to know up front all of the possible branches that involve recursive evaluation, whereas recursive nix can branch based on information derived during the build itself.* | ||
|
||
This is fair. There's a CPS-like encoding where one always imports a derivation, but it's something one would want to write. | ||
But, more importantly, we do not need to choose between improved import-from-derivation and recursive Nix. | ||
|
||
- *Certain far-future goals, such as a gcc frontend that does all compilations as nested derivations to get free distcc and ccache, would be very impractical to shoehorn into an import-from-derivation regime.* | ||
|
||
We can do both. | ||
|
||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions | ||
|
||
None. | ||
|
||
# Future work | ||
[future]: #future-work | ||
|
||
This unlocks lots of future work in Nixpkgs: | ||
|
||
- Leveraging language-specific tools to generate plans Nix builds, rather than reimplementing much of those tools. | ||
|
||
- Simply fetching and importing packages which use Nix for their build system, like Nix itself and hydra, rather than vendoring that build system in. | ||
|
||
Another future project would be some speculative strictness to allow one round of evaluation to return *both* a partial build plan and stuck imported derivations. | ||
Currently the plan must still be evaluated entirely before any building of "actually needed" derivations, i.e. those which *aren't* imported, begins. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought: this seems useful on it's own. Maybe split it in it's own RFC, I suspect smaller RFCs are more likely to make progress. Or just implement it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing that that's just a bug fix, I might just open an issue. That issue can be linked from any tracking the RFC as a whole if it is accepted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened NixOS/nix#1407