-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
Description
This is a long-term goal; none of this can happen overnight. This is also an incomplete work-in-progress.
TL;DR: Short Example
{ pkgsOnHost # simple dependencies
, pkgsOnBuild # build tools that don't emit code (`grep`, `jq`...)
, pkgsOnBuildForHost # build tools that emit code for the hostPlatform
}:
{
# setup.sh will put this stuff in the $PATH at compile time
depsInPATH = with pkgsOnBuild; [
cmake
makeWrapper
pkgsOnBuildForHost.gfortran # to compile fortran code for use at run time
];
# setup.sh will not put any of this stuff into the $PATH
deps = with pkgsOnHost; [
openssl
];
}Wishlist
Eliminate splicing
I made splicing (nativeDrv and crossDrv are older, but were done differently). Splicing is bad. I never wanted it. I causes major headaches when getting anywhere near bootstrapping. It is gross. It is probably slow. It should be removed. -- #204303 (comment)
Splicing is too magical. Probably three1 people really understand it. Dozens of people think they understand it but really don't, and get pissed off when it breaks in weird ways. This is a major part of why people hate on cross compilation.
Eliminating splicing likely means that package expressions will need to take package sets explicitly as top-level arguments. See next section.
Eliminate special exceptions to depsFooBar naming
Basically, do this (thanks @Artturin):
targetPlatform==null for packages that do not emit code
The vast majority of packages in nixpkgs don't emit code. Instead of setting their targetPlatform equal to their hostPlatform, we should set it to null.
Using targetPlatform==hostPlatform erases the distinction between packages that emit code for their hostPlatform and packages that don't emit code. It also creates ambiguity: these packages can be moved freely between (say) depsBuildHost and depsBuildTarget with no change in behavior, so the difference between depsBuildHost and depsBuildTarget is harder for people to learn.
Prefix all binaries that have a targetPlatform
AKA resurrect this PR:
Right now we have an artificial distinction between:
pkgsBuildTargetfor build=X target=YpkgsHostTargetfor host=X target=Y
The first kind won't have a aarch64-linux- prefix on their code-emitting binaries (like gcc). The latter kind will. This is silly. Prefix all the binaries, eliminate the distinction.
For compilers (clang, rust) that have a single binary entry point for all platforms and use some kind of --target= flag, we simply wrap that entry point with a wrapper for each targetPlatform which adds the --target= flag.
Use the pythonPackages onBuildForHost naming
pkgsFooBar is extremely unergonomic. Nobody can remember what Foo is for and what Bar is for. These should be changed to pkgsOnBuildForHost like pythonPackages does; with pkgsOnFooForBar least that way there is a reminder of what Foo and Bar are: pkgsOnFooForBar runs on Foo and emits code for Bar.
Packages with no target (see previous heading) get shorter names: pkgsOnBuild and pkgsOnHost.
No more depsOnXForY, only pkgsOnXForY
The distinction between the various depsFooBar attributes of a derivation serves two purposes:
- "Desplicing" the correct derivation from the spliced package
- Ensuring that only
depsBuildXstuff goes in the$PATHat build time
Instead of (six? more?) different derivation attributes we only need two:
depsInPATH = [ ... ] # stuff that is put into $PATH
deps = [ ... ] # stuff that is not put into $PATH
Long Example
This example might look complicated, but it exercises all possible arguments and attributes. Think about that. This is the most complicated attrset you'll ever see.
Non-code-emitting packages will only have, at most, the first five attributes (one of which is never used in practice). In practice most packages will have only three arguments: pkgsOnHost, pkgsOnBuild, and pkgsOnBuildForHost.
{ pkgsOnHost # simple dependencies
, pkgsOnBuild # build tools that don't emit code (`grep`, `jq`...)
, pkgsOnBuildForHost # build tools that emit code for the hostPlatform
# the three arguments above are enough for nearly all packages in nixpkgs
, pkgsOnHostForHost # theoretical possibility only: zero uses in nixpkgs
, pkgsOnBuildForBuild # build tools that emit code for the buildPlatform
# **only code-emitting packages** (compilers) will have the following:
, pkgsOnHostForTarget # theoretical posibility only: canadian cross
, pkgsOnBuildForTarget # e.g. the bintools used to link the libraries bundled with gcc
, pkgsOnTarget # target libraries bundled with the compiler (eg libstdc++)
, pkgsOnTargetForTarget # code-emitting target libraries (JITs), like libgccjit
}:
{
# setup.sh will put this stuff in the $PATH at compile time
depsInPATH = with pkgsOnBuild; [
cmake
makeWrapper
pkgsOnBuildForHost.gfortran # to compile fortran code for use at run time
pkgsOnBuildForBuild.stdenv.cc # to compile+run a C program at build time
];
# setup.sh will not put any of this stuff into the $PATH
deps = with pkgsOnHost; [
openssl
pkgsOnTarget.libstdc++
];
}Problems
-
Note: there is a possible solution to both of the following two problems, which brings additional benefits.
-
This needs to be harmonized with
callPackage. It is really unfortunate that the Nix language does not let functions declare deep attributes as arguments, like{foo.bar, ...}: .... -
In its current form this makes
.overridevery painful to use, since it don't cope well with overriding a sub-attribute of an argument. It should be extended to provide an ergonomic way to override sub-attributes of an argument.
-
Questions
-
Should
depsanddepsInPATHbe combined into a single attribute?mkDerivationcould decide whether or not to put each dependency into the$PATHbased on whetherstdenv.buildPlatform.canExecutethat dependency'shostPlatform.In practice there are very very very few situations where you don't want all the possibly-executable dependencies put into the path; we could provide an "escape hatch" to mark specific dependencies as "don't belong in the
$PATHeven if we could execute them". -
withis a footgun, and this scheme encourageswith pkgsOnBuild. We could makedepsanddepsOnBuildbe attrsets (whose attrnames are ignored); this would allow the use of the much-saferinheritsyntax. A better long-term solution would be RFC 110. -
Should
pkgsOnBuildForHostbe an attribute within thepkgsOnBuildattrset? For example,pkgsOnBuild.forHost. This would mean only two arguments for non-compiler-like packages.
Footnotes
-
I am not one of these people. But I'm also aware that I don't fully understand splicing. ↩
Metadata
Metadata
Assignees
Labels
Projects
Status