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
rustPlatform: Allow impure cache. #98813
Conversation
I hope this isn't too controversial. Right now if you make any change to your rust source (including any non-source files) a subsequent Nix build will recompile all of your dependencies and do a full compile of your crate. This change allows using a directory of your choice to cache cargo's artifacts. This allows incremental rebuilds. The intent of this is that it can be used in CI, and possibly local development to reduce full rebuilds. This is especially useful if you depend on a large number of crates. This is not intended to be used for production releases and other cases where complete correctness is required. Concerns: - I think executables that have been removed from the source will be grabbed by the installPhase so might not be removed from the package output.
Why do this rather than using
|
I didn't know about https://github.com/edolstra/import-cargo and all the rest require generating files instead just just using the regular cargo setup for development. I guess I'll have to check out the status of flakes to see if that one will work well. However IIUC even in that case it won't cache the incremental build of the crate itself. However as long as I don't need to rebuild dependencies it will be fast enough for my CI. |
I also tested edolstra's and it doesn't appear to avoid recompiling dependencies (or I set it up wrong). |
Sorry but I still don't understand why you would want to use |
I don't know. This feels like an invitation for people to disable sandboxing, which will lead to more breakage of Nix' model [1] and potentially more incorrect PR submissions. As @zowoq says, there are proper solutions to this. E.g. I would prefer to see crate2nix added to nixpkgs (ping @kolloch, any objections?) and steering people who need incremental builds in that direction. [1] Which |
The author should look at naersk https://github.com/nmattia/naersk as that
does a two stage compilation. One for the dependencies and another for your
crate.
…On Sat, Sep 26, 2020, 08:20 Daniël de Kok ***@***.***> wrote:
* I think executables that have been removed from the source will be grabbed by the installPhase so might not be removed from the package output.
cargo clean -p SPEC could be used to (only) clean the main package, which
would avoid surch left-overs.
I hope this isn't too controversial. Right now if you make any change to
your rust source (including any non-source files)
I don't know. This feels like an invitation for people to disable
sandboxing, which will lead to more breakage of Nix' model [1] and
potentially more incorrect PR submissions. As @zowoq
<https://github.com/zowoq> mentions, there are proper solutions to this.
E.g. buildRustCrate+crate2nix build every transitive (crate) dependency
as a Nix derivation, giving you fully incremental builds. As a bonus, built
outputs are shared between projects. We have been using crate2nix with a
binary cache in CI over year and it works great.
I would prefer to see crate2nix added to nixpkgs (ping @kolloch
<https://github.com/kolloch>, any objections?) and steering people in
that direction.
[1] Which buildRustPackage already is, since it doesn't use proper
fixed-output derivations.
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#98813 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAE365HXBYZOMRMI5OSB6LTSHWB23ANCNFSM4R2QOSEQ>
.
|
naerks is nice too, but the caveat is that all the dependencies are recompiled when So I guess it depends a bit on your CI capacity and how often you expect to make changes that affect (Yes, I should get an enterprise plan or set up my own GH Actions runner ;).) |
I think I'll finally work on a comparison blog post for all those
approaches that I used in the past. There are always a few trade offs to
make.
…On Sat, Sep 26, 2020, 11:08 Daniël de Kok ***@***.***> wrote:
The author should look at naersk https://github.com/nmattia/naersk as
that does a two stage compilation. One for the dependencies and another for
your crate.
naerks is nice too, but the caveat is that all the dependencies are
recompiled when Cargo.lock is modified. My experience is that even with
modest projects using the async ecosystem (lots of dependencies), this
generally leads to ~8 minute rebuilds on GitHub actions. For an early-stage
project with quickly-changing dependencies I quickly burned through my GH
Actions minutes in a few days ;).
So I guess it depends a bit on your CI capacity and how often you expect
to make changes that affect Cargo.lock.
(Yes, I should get an enterprise plan or use my GH Actions runner ;).)
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#98813 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAE365A5FKV4ZIBG7LWPCBLSHWVRJANCNFSM4R2QOSEQ>
.
|
That would be really nice! |
The nixpkgs manual is also quite outdated when it comes to comparing approaches. E.g., it still suggest Carnix for |
Just to be clear I don't think this option should ever be used in nixpkgs. However there are cases where perfect purity are not worth the cost. This is why every CI system I am aware of except hydra has support for caching. Sure, it would be more correct if you built from source, but the time and resource cost isn't worth it. |
My primary use case here is speeding up my CI. I have found nix very helpful in CI however full rebuilds are a source of pain. I have resorted to useing This PR makes an option that is very similar to a regular build with just the addition of allowing caching. |
Why not define the build once and import it into both |
releaseDirPrefix = if impureCacheDir == null | ||
then "target" | ||
else | ||
assert | ||
stdenv.lib.assertMsg (stdenv.lib.hasPrefix "/" impureCacheDir) | ||
"impureCacheDir must be an absolute path."; | ||
impureCacheDir; |
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.
Maybe impureCacheDir
could just be renamed cacheDir
(or perhaps targetDir
) with the default set to "target"
? Then this absolute path check is not necessary.
I think this would be a good compromise, because then the derivation does not encourage impure use, but anyone who is willing to disable the Nix sandbox could still set it to an absolute directory. I guess setting CARGO_TARGET_DIR
to target
as a result does not have a negative impact, except for causing a lot of rebuilds ;).
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.
Maybe impureCacheDir could just be renamed cacheDir with the default set
to "target"? Then this absolute path check is not necessary.
That could be done.
...because then the derivation does not encourage impure use
I'm not sure. This just sounds like hiding the true purpose because I can't
think another reason to set the cache directory.
One possible alternative would be allow passing in the cache directory
manually and provide the resulting cache directory as a separate output.
This is weirder to use and technically pure. However I decided against this
solution as it didn't seem to add any real value other than working without
sandboxing.
This comment has been minimized.
This comment has been minimized.
# If set the CARGO_TARGET_DIR will be set to this directory. This will allow | ||
# you to avoid rebuilding dependencies. | ||
# This setting is *incompatible* with sandboxing. | ||
, impureCacheDir ? null |
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.
This also should be in the manual, ideally with an example. I assume one could use a relaxed sandbox, where only the rust package is built impure (__noChroot = true;
)
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.
I checked the docs and there isn't an obvious place to put this as there is no attribute reference. Is there a spot that you would recomend?
I'm closing this for now because naersk was good enough for me. However I think the approach is still viable when impute benefits such as caching are desired. |
I hope this isn't too controversial. Right now if you make any change to your rust source (including any non-source files) a subsequent Nix build will recompile all of your dependencies and do a full compile of your crate. This change allows using a directory of your choice to cache cargo's artifacts. This allows incremental rebuilds.
The intent of this is that it can be used in CI, and possibly local development to reduce full rebuilds. This is especially useful if you depend on a large number of crates.
This is not intended to be used for production releases and other cases where complete correctness is required.
Concerns:
Motivation for this change
Reduce development and CI time while being able to use the same Nix build process for CI and deployment.
Things done
sandbox
innix.conf
on non-NixOS linux)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)nix path-info -S
before and after)