I have trouble understanding Nix overlays and the override pattern. What I want to do is add something to "patches" of gdb without copy/pasting
the whole derivation.
From Nix Pills I kind of see that override just mimics OOP, in reality it is just another attribute of the set. But how does it work then? Override is a function from the original attribute set to a transformed one that again has a predefined override function?
And as Nix is a functional language you also don't have variables only bindings which you can shadow in a different scope. But that still doesn't explain how overlays achieve their "magic".
Through ~/.config/nixpkgs I have configured a test overlay approximately like this:
self: super:
{
test1 = super.gdb // { name = "test1"; buildInputs = [ super.curl ]; };
test2 = super.gdb // { name = "test2"; buildInputs = [ super.coreutils ]; };
test3 = super.gdb.override { pythonSupport = false; };
};
And I get:
nix-repl> "${test1}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test2}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test3}"
"/nix/store/vqlrphs3a2jfw69v8kwk60vhdsadv3k5-gdb-8.3"
But then
$ nix-env -iA nixpkgs.test1
replacing old 'test1'
installing 'test1'
Can you explain me those results please? Am I correct that override can just alter the "defined interface" - that is all parameters of the function and as "patches" isn't a parameter of gdb I won't be able to change it? What is the best alternative then?
I will write an answer in case anyone else stumbles on this.
Edit 21.8.2019:
what I actually wanted is described in https://nixos.org/nixpkgs/manual/#sec-overrides
overrideDerivation and overrideAttrs
overrideDerivation is basically "derivation (drv.drvAttrs // (f drv))" and overrideAttrs is defined as part of mkDerivation in https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/make-derivation.nix
And my code then looks like:
gdb = super.gdb.overrideAttrs (oldAttrs: rec {
patches = oldAttrs.patches ++ [
(super.fetchpatch {
name = "...";
url = "...";
sha256 = "...";
})
];
});
The question title is misleading and comes from my fundamental misunderstanding of derivations. Overlays work exactly as advertised. And they are probably also not that magic. Just some recursion where endresult is result of previous step // output of last overlay function.
What is the purpose of nix-instantiate? What is a store-derivation?
Correct me please wherever I am wrong.
But basically when you evaluate Nix code the "derivation function" turns a descriptive attribute set (name, system, builder) into an "actual derivation". That "actual derivation" is again an attribute set, but the trick is that it is backed by a .drv file in the store. So in some sense derivation has side-effects. The drv encodes how the building is supposed to take place and what dependencies are required. The hash of this file also determines the directory name for the artefacts (despite nothing was built yet). So implicitly the name in the nix store also depends on all build inputs.
When I was creating a new derivation sort of like Frankenstein based on tying together existing derivations all I did was create multiple references to the same .drv file. As if I was copying a pointer with the result of getting two pointers pointing to the same value on the heap. I was able to change some metadata but in the end the build procedure was still the same. Infact as Nix is pure I bet there is no way to even write to the filesystem (to change the .drv file) - except again with something that wraps the derivation function.
Override on the other hand allows you to create a "new instance". Due to "inputs pattern" every package in Nix is a function from a dependencies attribute set to the actual code that in the end invokes the "derivation function". With override you are able to call that function again which makes "derivation function" get different parameters.
Related
I'm working to understand as much as I can about Nix flakes. I'm puzzled by the fact that a nixpkgs input is usually imported, and the imported value is called as a function. How does the result of import nixpkgs map to code in the nixpkgs flake?
It looks like this use of nixpkgs is common practice in flakes:
# flake.nix
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
/* ... */
};
outputs = { self, flake-utils, nixpkgs /*, ... */ }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = (import nixpkgs) {
inherit system;
};
in
{
/* ... */
}
);
}
My understanding is that the nixpkgs value in this flake's outputs function is the attribute set produced by the nixpkgs flake. I understand that flake output is a derivation, and a derivation can be imported. But how does the imported value become a function? I expected it to be an attribute set.
I see that the nixpkgs flake includes a lib output. Is there some mechanism where an attribute with a lib attribute path is callable? I have been looking for information on this, but I have not found anything.
If (import nixpkgs) {} is effectively calling that lib attribute, then how does importing differ from calling nixpkgs.lib directly? From what I've read importing a derivation has some effect on either forcing evaluating, or not forcing evaluation of something. I don't understand the details yet.
Flakes behave like paths because of their .outPath attribute, which contains the flake source path that is automatically added to all flakes by Nix.
This lets import load the file as a Nix value.
Specifically, because the path is a directory, it loads the default.nix in it, which then loads impure.nix, which contains a function.
Note that the way flakes are evaluated (without --impure), the evaluation is always pure, despite the "impure.nix" file name above.
The .outPath attribute got its name because it is also responsible for making derivations coercible to strings.
I would like to do something like:
DEFAULT_CLUSTER_ALIASES = {
"local": "$(DEFAULT_LOCAL_CLUSTER)",
}
def helm_action(**kwargs):
if not "$(DEFAULT_LOCAL_CLUSTER)":
DEFAULT_LOCAL_CLUSTER = "docker-desktop"
_helm_action(
cluster_aliases = DEFAULT_CLUSTER_ALIASES,
**kwargs
)
IOW, if DEFAULT_LOCAL_CLUSTER is not defined, DEFAULT_CLUSTER_ALIASES will be dict("local": "docker-desktop").
and if --define=DEFAULT_LOCAL_CLUSTER=minikube, DEFAULT_CLUSTER_ALIASES will be dict("local": "minikube").
So far, I haven't been able to get the Make variable to be evaluated and DEFAULT_CLUSTER_ALIASES is dict("local": "$(DEFAULT_LOCAL_CLUSTER)").
What's needed so the Make variable is evaluated?
"make variables" are only evaluated in the context of rule attributes that support make variable substitution. See https://bazel.build/reference/be/make-variables#use
If helm_action is a macro, or is used from a macro, then this won't work because macros don't have access to configuration information (e.g. values from flags). If helm_action is used from a rule implementation, then you can access values set using --define from ctx.var: https://bazel.build/rules/lib/ctx#var
Another way to do this is to use Starlark flags: https://bazel.build/rules/config#user-defined-build-settings Though again, it depends on if you're writing a macro or a rule.
There seems to be no examples online, according to the documentation Path, ParentMap's constructor accepts "Stmt *ASTRoot", which may means that later the ParentMap instance will find parents under the AST subtree under "ASTRoot". But how to get the root node of a translation unit? I tried
virtual bool VisitTranslationUnitDecl(TranslationUnitDecl *decl) {
//decl->dump();
Stmt *stmt = decl->getBody();
mParentMap = new ParentMap(stmt);
return true;
}
The goal is to create a ParentMap around the root nood then use it in other Visit*** callbacks during the scan process. But decl->getBody() is null. decl->dump() will print everything, and even scan the AST for the second time decl->getBody() is still null.
How to get the root Stmt of an AST? What is the right/better way to use ParentMap?
ParentMap is not really intended to be used on its own. You can use ASTContext::getParents, which constructs and maintains ParentMap.
I am having difficulty referring to parameterless functions in Fable.
With this example:
let f1 () =
1
let someRefTof1 = f1
I'd expect the generated js to look something like this:
function f1() {
return 1;
}
var someRefTof1 = f1;
but what I actually get is:
function f1() {
return 1;
}
var someRefTof1 = exports.someRefTof1 = function someRefTof1(arg00_) {
return f1(arg00_);
};
I'm unclear on the purpose of arg00_ or how to avoid it being generated?
(As a bit of background, I am struggling to call a function in an external js library which expects a function to be passed as a parameter)
Edit:
Background
The above is what i believe to be a minimal, verifiable, reproduction of my question but, after comments, I thought it may be useful to provide a touch more context on why this is causing issues. What I am actually trying to do is use angularjs from Fable.
So my example looks more like this:
let app = AngularFable.NgFable.angular.``module``("app",[||])
type TestCtrl() =
member this.Val1() = "boom";
app?controller("test", TestCtrl)
which gets compiled to:
var app = exports.app = angular.module("app", []);
var TestCtrl = exports.TestCtrl = function () {
function TestCtrl() {
_classCallCheck(this, TestCtrl);
}
TestCtrl.prototype.Val1 = function Val1() {
return "boom";
};
return TestCtrl;
}();
_fableCore.Util.setInterfaces(TestCtrl.prototype, [], "App.TestCtrl");
app.controller("test", function (unitVar) {
return new TestCtrl();
});
with unitVar being the problematic parameter introduced in this example. When I use this in my html with something like:
<div ng-app="app">
<div ng-controller="test as vm">
{{vm.Val1()}}
</div>
</div>
I run into an unknown provider error whereas if I simply change the compiled javascript to remove the unitVar parameter from the last line like this:
app.controller("test", function () {
return new TestCtrl();
});
then my example works as expected.
I'd really like to know if there is a way to avoid having the Fable compiler generate this parameter. I'm 99% sure this reduces to the same problem as in my original question but I've included this additional context to better explain why this is an issue
Thank you very much for your question and detailed explanations. There're two things here that are a bit tricky and are caused by optimisations both of the F# compiler and Fable.
In the AST provided by the F# compiler, methods (functions that are members of a type or module) are compiled as usual methods as in C#. This is for optimization.
However, when you create an anonymous lambda or make a reference to a method, the F# compiler will keep F# semantics, that is, all functions have a single argument (as John Palmer says, unit is an argument too) and can be curried.
Ok, this info is just to make clear why the F# compiler/Fable represent methods and lambdas differently. Let's go with the issue of argumentless functions: the obvious solution would be of course to remove the F# compiler generated argument for functions accepting unit (as it's already done for methods). In fact, I also had problems with libraries like Mocha because of this.
I did try to remove the unit argument at the beginning but I got fails in some scenarios because of this. TBH, I don't remember now exactly which tests were failing but because of the expectation that there'll be always an argument, in some cases function composition or inlining was failing when the unit argument was removed.
Other attempts to modify the semantics of F# functions in the JS runtime have always failed because they don't cover all scenarios. However, we can be more lenient with delegates (System.Func<>) as it's usually safe to assume these ones should behave more like functions in languages like C# or F#. I can try to remove the unit argument just for delegates and see what happens :)
For more info about sending F# functions to JS code you can check the documentation.
UPDATE: Scratch all that, please try fable-compiler#0.6.12 and fable-core#0.6.8. This version eliminates unit arguments, the solution was actually simpler than I thought and (hopefully) shouldn't create issues with existing projects. (The explanation about methods and lambdas compiled differently still applies.)
So, in Haskell, it's really easy to do this:
data Foo = Bar | Baz
deriving (Read, Show)
This is great, but I'd like to be able to pass some data as a string from Haskell to the Elm language. The languages are similar enough that, if I had a Haskell implementation of Read, I could easily convert it to Elm by hand.
The problem is, when I use deriving, the function is automatically generated, but I can't actually see what it does.
I'm wondering, is there a way to automatically generate the code for parsing and showing using Read and Show, so that I could actually see the code itself?
You can use the the -ddump-deriv GHC option to see the code for derived instances:
ghc -ddump-deriv test.hs
[1 of 1] Compiling Test ( test.hs, test.o )
==================== Derived instances ====================
Derived instances:
instance GHC.Show.Show Test.FooBar where
GHC.Show.showsPrec _ Test.Foo = GHC.Show.showString "Foo"
GHC.Show.showsPrec _ Test.Bar = GHC.Show.showString "Bar"
GHC.Show.showList = GHC.Show.showList__ (GHC.Show.showsPrec 0)
Generic representation:
Generated datatypes for meta-information:
Representation types:
For stack:
stack build --ghc-options="-ddump-deriv"
Output in my specific case is: .stack-work/dist/x86_64-linux-nix/Cabal-2.4.0.1/build/app/app-tmp/src/