-
-
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
Added builtins.intern primop (WIP) #1502
Conversation
Hmm, I don't quite get what this adds. Can't I get the same behavior as follows? let
pathAsString = "/path/to/some/file/computed/dynamically";
in "${/. + pathAsString}" That evaluates to something like |
|
Okay, after hashing it out with @taktoa on IRC, this makes a lot more sense to me and I'm 👍 My use case is for testing bootstrap tools. I currently have some hackery to plug bootstrap tools from one derivation into another stdenv for easier iteration, but after running a full bootstrap I then need to build everything again before I commit the final bootstrap. This should allow me to avoid that. |
related discussion on
|
💯 |
Haven't looked at the impl yet, does this scan for references? |
|
I was trying to implement something similar in Nix today, but it doesn't work with remote builders: { lib, stdenv, nix }:
# Creates a fixed derivation output that is just based on the
# content of the input.
name: input:
let
drv = stdenv.mkDerivation {
inherit name;
phases = ["installPhase"];
buildInputs = [ nix ];
installPhase = ''
# make a copy so that the name doesn't change
cp -ar ${input} ${name}
# then add to the store
NIX_REMOTE=daemon nix-store --add ${name} > $out
'';
};
casOut = lib.removeSuffix "\n" (builtins.readFile drv);
in
builtins.storePath casOut When using it I get:
It's like the reference to it has been lost |
I just noticed this in {
# Copy a path to the Nix store.
# Nix automatically copies files to the store before stringifying paths.
# If you need the store path of a file, ${copyPathToStore <path>} can be
# shortened to ${<path>}.
copyPathToStore = builtins.filterSource (p: t: true);
} This makes me wonder if |
Any updates fam? |
Maybe it's because I don't understand what the word "intern" means in this context, but I don't really understand the use case here. You already can copy paths as fixed-output (content-addressable) paths in various ways:
|
Is the point to make a copy if and only if the path doesn't refer within store already? @edolstra: "intern" seems a reference to a technique used in some languages. |
@edolstra @vcunat No, the point is to copy even if the path you are interning is inside another store path. All the ways you list are about files not in the store; what I want is something that turns any path to a file into a top-level fixed output store path. This is pretty essential to making incremental builds work properly in Nix. |
Ah, right, I see now, you need per-file nix store paths for incremental builds, and that's hard if they come from a directory in nix store. |
It seems that the following does the same as /*
* Run `cabal sdist` on a directory and import that directory into the Nix
* store. This allows you to clean a directory to just what is depended on
* by a .cabal file, without any dependency on the original directory tree.
*/
dir:
let
pkgs = import ./pkgs {};
src-tree = pkgs.stdenv.mkDerivation {
name = "src-sdist";
buildCommand = ''
mkdir -p $out/src
cd ${dir}
cabal sdist --output-directory=$out/src
'';
buildInputs = [ pkgs.cabal-install ];
};
in
import
( pkgs.stdenv.mkDerivation {
name = "src.nix";
buildCommand = ''echo "${src-tree}"/src > $out'';
}
) Assuming this is in {
src = import ./cabal-sdist.nix ./.;
} |
@ocharles the store path that generates won't be a fixed output path, so all semblance of incremental building will be lost (everything will rebuilt if any one file changes). |
I think that's still doable with |
@vcunat
|
I meant something else. A derivation that uses sha256sum or something to compute and write the hash of file "F" into a text file, then |
@taktoa The result of the final import does produce something that only depends on the contents of Note that the trick is that the final expression is: |
I marked this as stale due to inactivity. → More info |
I closed this issue due to inactivity. → More info |
NOTE: this is a work in progress; in particular, it is untested
This commit adds a new
builtins.intern
primop that allows a fixed-output Nix store path to be made from any given path, as long as it exists. In other words, this primop allows you to do something similar to Nix path references (likesrc = ./.;
), except that the given path could already be in the Nix store.Without an intensional store, this is necessary to make incremental builds work in Nix. You can make a hacky alternative without it --
(path: with builtins; toFile (basename path) (readFile path))
-- but sincebuiltins.readFile
fails on binary files, it cannot be used in all cases.