stdenv: add stdenv.isAvailable pkg#245322
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
piegamesde
left a comment
There was a problem hiding this comment.
Since it looks like you touched that code so you might know, why is assertValidity having both attrs and meta parameters? What's the difference between attrs.meta and meta?
Oh man was this frustrating.
So for example, The reason why This is mainly because We could probably make this into a lot less of a footgun by arranging things so that the attrnames of |
pkgs/stdenv/generic/default.nix
Outdated
There was a problem hiding this comment.
I don't understand why this is desirable.
So far we have been trying to deprecate the various stdenv.is* in favor of the more accurate stdenv.*Platform.is.
There was a problem hiding this comment.
Note the && in the code above.
I don't understand why this is desirable.
Because availability isn't a function of just the hostPlatform (or just the buildPlatform, or just the targetPlatform). You need all three in order to decide.
Perhaps a more-perfect solution would be to have stdenv.platform.{build,host,target} and then add stdenv.platform.isAvailable. That would place isAvailable the smallest attrset containing all the needed information. @Artturin, would this resolve your concern?
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
There was a problem hiding this comment.
This pr has big performance impacts too (current ofborg eval time is ~11 minutes)
Percentages are more useful here: ~5% on all but one metric (and that one metric at +10% is not an allocation metric).
That said, there are still lots of optimization opportunities. If performance is the only remaining obstacle I will implement those. I believe the overhead can be brought down to ~1% but I don't want to put in that effort if it's going to be wasted.
There was a problem hiding this comment.
1c68dedefcb5ac3c2b2757fc076a1f9850c4c1a1 should improve this. Let's see what OfBorg says.
There was a problem hiding this comment.
|
Squashed. |
|
It turns out that most of the eval overhead is due to people making wacky choices for In practice, So I'm going to leave |
This commit adds `stdenv.isAvailable pkg`, which checks `meta`
availability not only for the hostPlatform, but also for the
`buildPlatform` and `targetPlatform` using
`lib.meta.checkAvailability`.
Our current meta.{platforms,badPlatforms} scheme isn't capable of
expressing constraints that apply to anything other than the
hostPlatform. For example:
- LLVM can't be used with targetPlatform.isMips64n32, but GCC can
The clumsy way of working around this is to have `buildRustPackage`
inject `meta.badPlatforms` values into the packages it creates, but
that covers only Rust (not other LLVM-based compilers) and only
those which use `buildRustPackage`. Really, it's the wrong layer at
which to express these things.
This commit adds `meta.availability.{build,host,target}.{bad,only}`
which are computed automatically based on a package's dependencies.
This is done in a backwards-compatible way for the hostPlatform:
`meta.availability.host` will incorporate
`meta.{platforms,badPlatforms}` from both the package as well as all
of its `buildInputs`. The constraints are cumulative, so deep
recursion (like checkMetaRecursively) is not needed; each package's
`meta.availability` only needs to look at that package's immediate
inputs.
This commit also causes check-meta.nix to utilize the information in
meta.badBuildPlatforms and meta.badTargetPlatforms.
In particular, the following test commands now behave correctly:
# XFAIL: golang can't build *on* MIPS, but it can cross compile to it
nix-instantiate . -A pkgsCross.mipsel-linux-gnu.go
# SUCCESS: golang can't build *on* MIPS, but it can cross compile to it
nix-instantiate . -A pkgsCross.mipsel-linux-gnu.dnscrypt-proxy2
# XFAIL: golang can't target Mips64n32
nix-instantiate . -A pkgsCross.mips64el-linux-gnuabin32.dnscrypt-proxy2
# XFAIL: rust can't target Mips64n32
nix-instantiate . -A pkgsCross.mips64el-linux-gnuabin32.tiny
We can't build a `go` compiler on MIPS due to lack of bootstrap binaries. However, go is in fact capable of emitting code for MIPS, so we can cross compile to a MIPS target (useful for embedded routers!).
|
Squashed. |
|
Latest eval report, at 4141be0. It's basically neutral; a mixed bag of under-5% changes (about half faster, half slower). The only thing that stands out is the +12% on That But the The far more important metric is |
|
Next push will be an experiment with having hashing replace sorting, to see which wins. |
|
The PR is still in draft, what is missing before being ready for review? |
|
Why did you closed it? |
|
NixOS/nixpkgs-committers#60 (comment) somebody else will have to pick up the work probably |
|
Adam has closed many of his PRs. I don't think that was necessary, and I hope he's doing well. |
I'm fine, Robert. Thanks for your concern. |


Motivation
The current
meta.availableOnhas two problems:buildInputsare nothostPlatform. For example, a package is "available" even when:hostPlatformbuildPlatformhostPlatformbinaries but!buildPlatform.canExecute hostPlatformThis PR fixes both problems.
Specific examples of multi-platform constraints
buildPlatform.canExecute hostPlatform, and we have no clean way to express this. Often (xdg-open,p11-kit, and others) these packages are optional dependencies, and the depending package needs to detect their unavailability so they can be omitted rather than simply failing the build.targetPlatform.isMips64n32, but GCC cangois missing bootstrap binaries for a few platforms yet can generate code for those platforms, so we can cross-compile to these platforms but can't build a native compiler for them.ghcis missing usable bootstrap binaries forpowerpc64*, although it can emit code for (and even compile itself for) that platform.Description of changes
This commit adds
meta.availability.{build,host,target}.{bad,only}, which are computed automatically, and updatesmeta.availableOnto use these attributes.For the hostPlatform this is done in a backwards-compatible way:
meta.availability.hostincorporatesmeta.{platforms,badPlatforms}from the package as well asmeta.availability.host.{bad,only}from itsbuildInputs. Because the constraints are cumulative at each package, deep recursion (like checkMetaRecursively) is not needed; each package'smeta.availabilityonly looks at that package's immediate inputs.For the buildPlatform and targetPlatform two additional package-provided
metaattributes are needed:meta.badBuildPlatformsandmeta.badTargetPlatforms. The latter is needed only for compiler-like packages.badBuildPlatformsis useful; I don't have an example for it yet. Howevermeta.availability.build.badis definitely useful when we have a compiler written in its own language that can generate code for a platform but upstream doesn't provide "bootstrap binaries" for that platform. Two real-life examples: GHC on powerpc64le and golang on all flavors of MIPS.This PR also adds a boolean,
meta.requiresBuildCanExecuteHost, to signal a very common cross-compilation problem: build processes that assume the build platform can execute host platform binaries.This PR also adds
stdenv.isAvailable pkgwhich checks availability constraints for all three platforms (build, host, and target) as well asmeta.requiresBuildCanExecuteHost -> buildPlatform.canExecute hostPlatform. This should be preferred overmeta.availableOn platform pkg.Concrete example
One use-case for this is being able to automatically compile all eligible packages using the
mips64n32ABI (which cuts memory usage dramatically for pointer-intensive data structures) and build onmips64n64only those few packages which don't supportn32(usually because they're written in Rust or useboost-context).The clumsy way of working around this would be to have
buildRustPackageinjectmeta.badPlatformsvalues into the packages it creates, but that covers only Rust (not other LLVM-based compilers) and even then covers only those which usebuildRustPackage. Really, it's the wrong layer at which to express these things.meta.brokenisn't helpful here either. It is shallow, and its "deep" versionmeta.availableis based onthrow, so it can't be used to do anything other than to abort eval (see example below). This is whymeta.availableOndoesn't (and can't ever) understandmeta.broken.Includes
Things done
sandbox = trueset innix.conf? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/)