-
-
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
Figure out how to make IFD work properly #954
Comments
I'd prefer to use substitutes instead of sub-channels, i.e. solve 3. and thereby bypass 2.ii. Different people will be interested in different autogenerated parts. A least intrusive mode might just abort during evaluation if the autogenerated data isn't present locally (with a useful message), and users could regenerate them explicitly for particular nixpkgs revisions and/or there could be hooks for such to be done during For my personal usage, it's acceptable for nix to fetch not-too-big data during evaluation but not to auto-run some complex generator. |
If @shlevy's work is hard to rebase or review, then yes I would do the abort-generate thing in a heartbeat to unstick this. |
Note that unless we are OK with pegging a specific version of hackage/npm/whatever (and updating that manually when we want to update it), we'll have to go beyond just improving IFD into abandoning the idea that nix evaluation is deterministic (while keeping nix building deterministic). One possible way to do that is to have some way to specify non-deterministic inputs to the top level eval, and have hydra extract those as inputs and have command line nix fetch the latest and have arbitrary callers able to pass in fixed revs or fetch the latest as they wish. |
(I have some ideas on how to do that well, if I get a pre-approval from @edolstra I can get started on that after the perl stuff is done) |
I was proposing to peg specifically to an exact version, since I don't think we should abandon the determinism (except in my #520 thing which should behave quite differently). My ideal would be as follows:
|
To clarify, I'd then see the periodic updates that @peti makes to |
Please note that we have a concrete use-case in Nixpkgs
The expression used to build that
This feature allows to support, basically, all of Hackage without having to check all of Hackage into the Nixpkgs repository. The only drawback is that -- as of now -- Hydra won't build a single binary that depends on this feature. |
[aside question]
and get:
This is correct because these deps are not available in stackage nightly yet but there are in hackage |
@PierreR, I'd rather not get into discussions here that are off-topic for the issue since I'm worried it might derail the thread. |
@peti AFAIK, Hydra will build such packages. The Hydra evaluator does not prevent import-from-derivation, in fact it's used by the RPM/Debian closure generation functions. However, it's probably not a good idea to use this "feature", since the build (including its dependencies) will be done by the evaluator rather than the queue runner. |
Sounds like the next step sending such derivations to the queue runner? |
@edolstra: it's been reported NOT to work due to restricted mode: NixOS/nixpkgs#16130 (comment) |
The problem I encountered (NixOS/nixpkgs#15480) is that it doesn't allow network access during evaluation, and therefore cannot retrieve the repo with hashes. |
I'd really like to see this worked out. From reading around the associated issues, the most egregious problem with restricted mode is that while network access is allowed in fixed-output derivations used normally, network access is not allowed in fixed-output derivations being imported, right? I consider removing this restriction priority number 1 here because there is no impact to purity or other such downside. |
(@peti I fixed the typos if that was whats confusing—sorry there were so many in the first place.) |
I reacted with confusion because I felt your summary of the situation does not represent very well what's been discussed in the thread. |
@peti Oh! Well I wrote my summery because I didn't see one so far and this was the best I could come up with. Is the restricted-mode issue that prevents |
Putting in a big 👍 for this. opam2nix is probably not yet in a state to be merged in nixpkgs proper, but this issue is one of my big worries - reworking all of my code to live inside nixpkgs and manage it there instead of in its own tree is a big switch to make, and it's not clear how I'd maintain both going forwards. I assume any big self-contained work on bulk-importing third party language dependencies could benefit from this approach, instead of having to be managed in-tree. |
Garbage collections seems to delete import-from-derivation sources. 😕 Are there any workarounds applicable right now or do we have to wait for a fix in Nix? |
@michalrus They get gc'd during an evaluation? |
@shlevy, no, no. I have a few {
nix.gc = {
automatic = true;
dates = "daily";
options = "--delete-older-than 30d";
};
} After I added this auto GC, each morning, when starting nix-shell for that project, I have to redownload all Nixpkgs versions that it’s pinning (they got GC’d during the night) and some other sources that we add by That This feels a bit awful. :C What if I want to go for a semi-vacation to a place where there’s no or very limited Internet, and I forget to turn off that auto GC the day before? 😭 Please, these are real use cases, however grotesque they might seem. 🙏 |
I see. There's no easy way currently to do this, sadly, you'll need to manually lift up all the imported derivations to add them as roots somewhere. Would be a good feature though. |
Okay, thank you for this idea. 😢 |
I also make heavy use of import-from-derivation, so this would be very nice to solve/fix (I hadn't noticed this myself since I garbage collect so infrequently).
It seems like there are two conflicting desires here: Importing from a derivation lets us avoid depending on the expression used to define somethingFor example, we can use I personally use this to check for the latest commit in a git repo: I put If imported values did depend on the derivations that generated them, then my projects would keep getting rebuilt all the time, despite having no changes, due to the Importing from a derivation should cause the generated files (and their dependents) to last as long as dependencies do, in terms of garbage collectionThis is the issue @michalrus has just described. Note that there are two parts to consider: surviving garbage collection when a resulting derivation is referenced by a GC root; and getting garbage collected when those derivations aren't being kept any more. I don't know too much about the GC mechanism, but I wouldn't want old derivations to build up in the store due to "stale" auto-generated GC roots keeping them alive. For example, if I my user profile depends on a package built using this latest-git-revision function, then I update to a new profile and GC the old one, I would want that old |
@Warbo ++ @shlevy, it also seems that neither haskellPackages.override {
overrides = self: super: {
cryptonite = haskell.lib.overrideCabal (super.cryptonite) (…);
};
} … then Similarly for: haskellPackages.override {
overrides = self: super: {
steeloverseer = self.callCabal2nix "steeloverseer" sources.steeloverseer {};
};
} … here, after GC, |
Perhaps IFD could "infect" .drvs derived from them, without changing the output hashes, somehow? |
#1052 ;) |
@shlevy I think that's a slightly different sort of infection that I also wouldn't mind contracting 😄 |
But the same mechanism could be used. |
I like the look of 1052. Note that it can be useful to generate-and-import more than just derivations, e.g. we might generate an attrset of names/hashes from some other tool (cabal, npm, etc.), or we might have a script which checks for some condition and outputs a boolean; etc. The ability to "poison" arbitrary values would presumably require trickier changes in Nix. Maybe an easier approach would be to only support attrsets: this would include derivations "for free", and for other values we can just wrap them up, e.g. to get a boolean we could wrap it up as |
Re Importing from a derivation should cause the generated files (and their dependents) to last as long as dependencies do, in terms of garbage collectionhere is the fix for this problem { pkgs, ... }:
{
# This function makes a copy of package and adds `.nix_runtime_deps_references` file containing links to other packages
# This function can be used to prevent garbage-collection of packages that were generated/downloaded during import from derivation (IFD) and make them last as long as the imported package do.
# Check https://github.com/NixOS/nix/issues/954#issuecomment-365281661 for more.
# Check https://stackoverflow.com/questions/34769296/build-versus-runtime-dependencies-in-nix how runtime dependencies work.
# Example:
# {
# environment.systemPackages =
# let
# packageSrc = fetchFromGitHub { owner = ..., .... };
# package = import "${packageSrc}/release.nix";
# in
# [
# package
# ]
# }
# Here the `package` will not be garbage-collected on next `sudo nix-collect-garbage -d`, but `packageSrc` do
# But with
# {
# environment.systemPackages =
# let
# packageSrc = fetchFromGitHub { owner = ..., .... };
# package = import "${packageSrc}/release.nix";
# imrovedPackage = addAsRuntimeDeps [packageSrc] package;
# in
# [
# imrovedPackage
# ]
# }
# neither `package`, not `packageSrc` will not be garbage-collected
# TODO:
# make addAsRuntimeDeps composable with itself by appending links if drv already contains nix_runtime_deps_references
# E.g. addAsRuntimeDeps [src2] (addAsRuntimeDeps [src1] drv)
addAsRuntimeDeps = deps: drv:
let
fileWithLinks = pkgs.writeText "fileWithLinks" (
pkgs.lib.concatMapStringsSep "\n" toString deps + "\n"
);
drvName = drv: builtins.unsafeDiscardStringContext (pkgs.lib.substring 33 (pkgs.lib.stringLength (builtins.baseNameOf drv)) (builtins.baseNameOf drv));
in
pkgs.runCommand (drvName drv) { } ''
${pkgs.coreutils}/bin/mkdir -p $out
${pkgs.coreutils}/bin/cp ${fileWithLinks} $out/.nix_runtime_deps_references
${pkgs.rsync}/bin/rsync -a ${drv}/ $out/
'';
} Usage example # it's utils, not lib, because nixpkgs lib doesn't depend on pkgs
pkgs: pkgsOld:
let
callUtil = file: import file { inherit pkgs; };
in
(callUtil ./addAsRuntimeDeps.nix) nixpkgs = {
overlays = [
(import ../utils/overlay.nix)
];
}; |
I marked this as stale due to inactivity. → More info |
I closed this issue due to inactivity. → More info |
Given the emphasis of the original issue on Nixpkgs, I think it is worth mentioning NixOS/rfcs#109 |
See the whole thread at NixOS/nixpkgs#16130 plus the ensuing IRC discussion.
As a quick recap: I and several other people see IFD as a pretty important prerequisite for Nix's continued growth, but there are a few technical issues standing in its way right now that we don't have clean answers for.
What we'd like to be able to do:
What hinders it right now:
stdenv
or similar during evaluation?nixpkgs
evaluation involves, and whether a rebuild will be necessary? Definitely, but we could write tooling...?stdenv
itself depends on one of these things? The darwin stdenv uses llvm, which depends on python. It currently doesn't use any pythonPackages but who knows what might happen in future?The text was updated successfully, but these errors were encountered: