-
-
Notifications
You must be signed in to change notification settings - Fork 15k
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
Enhancing lib.makeScope
#68967
Comments
I still don't quite get what splicing is and what it's necessary for. What prevents these dependencies from being resolved through |
Splicing is mentioned but not explained in the manual. I provide a quick explanation here.
Derivations expressed using When not cross-compiling, every derivation's build, host, and target platforms are the same. However, when cross-compiling, they differ. For example, a package which is cross-compiled from When I'm cross compiling a package which uses CMake and links against OpenSSL, I need to provide One way to deal with this would be explicit references to Instead, top-level Nixpkgs attrsets of every relevant (build, host, target) are "spliced" together into one attrset where each package has the extra attribute
(Note: currently |
Wow, it's always impressive when someone has thoroughly reverse engineered your undocumented abomination—great job figuring out splicing! As you point out the big question is whether we can avoid passing in the scopes own binding, which leads to odd behavior if the scope is, let's say, bound and overriden under a new name. As Alan Kay might say "...late binding...". We usually solve these sorts of issues by delaying when the not is tied. Unfortunately, the solution here is pretty dirastic: we'd need package sets of functions rather than functions applied to the rest of the set via callPackage. Then in one big pass we'd crawl the thing tying the knot and adding sub package sets to the scope. Instead of functions we could use nix's "functors" so we could tell what was a sub package set and what is a package function. (I'd write some example code but I'm on my phone.) |
For what it's worth, I think splicing is a clever technique! Thanks for your input. I'll give this some more thought. |
hehe it may be clever, but that doesn't make me hate it any less! Good luck mulling it over :) |
Regarding splicing, I noticed that an evaluation like
calls the function |
I'm interested in enhancing
lib.makeScope
or adding similar functions with more features.I have three features in mind:
I seek your thoughts on the features themselves and whether they belong in Nixpkgs. Nixpkgs does not use scopes heavily, so these features may be overkill.
For reference, here is
lib.makeScope
:nixpkgs/lib/customisation.nix
Lines 185 to 204 in 83686eb
Splicing
Currently, scopes created with
lib.makeScope
are not spliced. If one member of a scope depends on another member of that same scope as a native build input, it cannot resolve that dependency directly throughcallPackage
. As a workaround, I've been usingbuildPackages
to indirectly resolve such dependencies (e.g. referring tobuildPackages.myScope.myPackage
from withinmyScope
).I've come up with an unsatisfying but useful version of
lib.makeScope
which splices using the top-levelpkgs${offset}${offset}
attributes. As arguments, it takes a function for accessing its own result from the current scope, and a normal scope function:In the example usage below,
foo
andbar
are spliced withinmyScope
, sofoo
can use{ bar }: { nativeBuildInputs = [ bar ]; }
as it would in the top-level Nixpkgs scope.I believe that the splicing of scopes can be accomplished in a way which does not require passing the scope's path from its parent's top-level, but I haven't found one yet.
Member access control
Features to organize scope members would allow for finer-grained access to members and more precise overriding. I'm not proposing that the definition of
makeScope
presented in this section should replacelib.makeScope
. I'm only using it to illustrate some ideas.The following definition of
makeScope
organizes scope members into three classes: public, protected, and private. Members defined at the scope function's top-level are public. Those specified within the_protected
(resp._private
) attribute are protected (resp. private). The resulting scope attrset contains, at its top-level, all public members, the attributes added bymakeScope
(e.g.callPackage
), and an attrset at_public
(resp._protected
,_private
) containing only the scope's public (resp. protected, private) members.All members (public, protected, and private) are available to the scope via its
callPackage
function. However, only public and protected members are available via descendant scopes'callPackage
functions.Better organization of scope members prevents issues like #68525.
The example below illustrates another benefit of member access control:
Ability to override ancestor scopes
This feature is easier to explain. If scope attrsets provided access to their ancestors, perhaps via a
_parent
attribute, ancestors could be modified using theiroverrideScope
attributes. This would allow for precise overriding in deeply-nested scenarios.The text was updated successfully, but these errors were encountered: