uboot: (firmwareOdroidC2/C4) don't invoke patch tool, use patches = [] instead
https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh#L948 this can do it nicely. Signed-off-by: Anton Arapov <anton@deadbeef.mx>
This commit is contained in:
commit
56de2bcd43
30691 changed files with 3076956 additions and 0 deletions
291
lib/debug.nix
Normal file
291
lib/debug.nix
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/* Collection of functions useful for debugging
|
||||
broken nix expressions.
|
||||
|
||||
* `trace`-like functions take two values, print
|
||||
the first to stderr and return the second.
|
||||
* `traceVal`-like functions take one argument
|
||||
which both printed and returned.
|
||||
* `traceSeq`-like functions fully evaluate their
|
||||
traced value before printing (not just to “weak
|
||||
head normal form” like trace does by default).
|
||||
* Functions that end in `-Fn` take an additional
|
||||
function as their first argument, which is applied
|
||||
to the traced value before it is printed.
|
||||
*/
|
||||
{ lib }:
|
||||
let
|
||||
inherit (lib)
|
||||
isInt
|
||||
attrNames
|
||||
isList
|
||||
isAttrs
|
||||
substring
|
||||
addErrorContext
|
||||
attrValues
|
||||
concatLists
|
||||
concatStringsSep
|
||||
const
|
||||
elem
|
||||
generators
|
||||
head
|
||||
id
|
||||
isDerivation
|
||||
isFunction
|
||||
mapAttrs
|
||||
trace;
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
# -- TRACING --
|
||||
|
||||
/* Conditionally trace the supplied message, based on a predicate.
|
||||
|
||||
Type: traceIf :: bool -> string -> a -> a
|
||||
|
||||
Example:
|
||||
traceIf true "hello" 3
|
||||
trace: hello
|
||||
=> 3
|
||||
*/
|
||||
traceIf =
|
||||
# Predicate to check
|
||||
pred:
|
||||
# Message that should be traced
|
||||
msg:
|
||||
# Value to return
|
||||
x: if pred then trace msg x else x;
|
||||
|
||||
/* Trace the supplied value after applying a function to it, and
|
||||
return the original value.
|
||||
|
||||
Type: traceValFn :: (a -> b) -> a -> a
|
||||
|
||||
Example:
|
||||
traceValFn (v: "mystring ${v}") "foo"
|
||||
trace: mystring foo
|
||||
=> "foo"
|
||||
*/
|
||||
traceValFn =
|
||||
# Function to apply
|
||||
f:
|
||||
# Value to trace and return
|
||||
x: trace (f x) x;
|
||||
|
||||
/* Trace the supplied value and return it.
|
||||
|
||||
Type: traceVal :: a -> a
|
||||
|
||||
Example:
|
||||
traceVal 42
|
||||
# trace: 42
|
||||
=> 42
|
||||
*/
|
||||
traceVal = traceValFn id;
|
||||
|
||||
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
|
||||
|
||||
Type: traceSeq :: a -> b -> b
|
||||
|
||||
Example:
|
||||
trace { a.b.c = 3; } null
|
||||
trace: { a = <CODE>; }
|
||||
=> null
|
||||
traceSeq { a.b.c = 3; } null
|
||||
trace: { a = { b = { c = 3; }; }; }
|
||||
=> null
|
||||
*/
|
||||
traceSeq =
|
||||
# The value to trace
|
||||
x:
|
||||
# The value to return
|
||||
y: trace (builtins.deepSeq x x) y;
|
||||
|
||||
/* Like `traceSeq`, but only evaluate down to depth n.
|
||||
This is very useful because lots of `traceSeq` usages
|
||||
lead to an infinite recursion.
|
||||
|
||||
Example:
|
||||
traceSeqN 2 { a.b.c = 3; } null
|
||||
trace: { a = { b = {…}; }; }
|
||||
=> null
|
||||
*/
|
||||
traceSeqN = depth: x: y:
|
||||
let snip = v: if isList v then noQuotes "[…]" v
|
||||
else if isAttrs v then noQuotes "{…}" v
|
||||
else v;
|
||||
noQuotes = str: v: { __pretty = const str; val = v; };
|
||||
modify = n: fn: v: if (n == 0) then fn v
|
||||
else if isList v then map (modify (n - 1) fn) v
|
||||
else if isAttrs v then mapAttrs
|
||||
(const (modify (n - 1) fn)) v
|
||||
else v;
|
||||
in trace (generators.toPretty { allowPrettyValues = true; }
|
||||
(modify depth snip x)) y;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeq` that applies a
|
||||
provided function to the value to be traced after `deepSeq`ing
|
||||
it.
|
||||
*/
|
||||
traceValSeqFn =
|
||||
# Function to apply
|
||||
f:
|
||||
# Value to trace
|
||||
v: traceValFn f (builtins.deepSeq v v);
|
||||
|
||||
/* A combination of `traceVal` and `traceSeq`. */
|
||||
traceValSeq = traceValSeqFn id;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeqN` that applies a
|
||||
provided function to the value to be traced. */
|
||||
traceValSeqNFn =
|
||||
# Function to apply
|
||||
f:
|
||||
depth:
|
||||
# Value to trace
|
||||
v: traceSeqN depth (f v) v;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeqN`. */
|
||||
traceValSeqN = traceValSeqNFn id;
|
||||
|
||||
/* Trace the input and output of a function `f` named `name`,
|
||||
both down to `depth`.
|
||||
|
||||
This is useful for adding around a function call,
|
||||
to see the before/after of values as they are transformed.
|
||||
|
||||
Example:
|
||||
traceFnSeqN 2 "id" (x: x) { a.b.c = 3; }
|
||||
trace: { fn = "id"; from = { a.b = {…}; }; to = { a.b = {…}; }; }
|
||||
=> { a.b.c = 3; }
|
||||
*/
|
||||
traceFnSeqN = depth: name: f: v:
|
||||
let res = f v;
|
||||
in lib.traceSeqN
|
||||
(depth + 1)
|
||||
{
|
||||
fn = name;
|
||||
from = v;
|
||||
to = res;
|
||||
}
|
||||
res;
|
||||
|
||||
|
||||
# -- TESTING --
|
||||
|
||||
/* Evaluate a set of tests. A test is an attribute set `{expr,
|
||||
expected}`, denoting an expression and its expected result. The
|
||||
result is a list of failed tests, each represented as `{name,
|
||||
expected, actual}`, denoting the attribute name of the failing
|
||||
test and its expected and actual results.
|
||||
|
||||
Used for regression testing of the functions in lib; see
|
||||
tests.nix for an example. Only tests having names starting with
|
||||
"test" are run.
|
||||
|
||||
Add attr { tests = ["testName"]; } to run these tests only.
|
||||
*/
|
||||
runTests =
|
||||
# Tests to run
|
||||
tests: concatLists (attrValues (mapAttrs (name: test:
|
||||
let testsToRun = if tests ? tests then tests.tests else [];
|
||||
in if (substring 0 4 name == "test" || elem name testsToRun)
|
||||
&& ((testsToRun == []) || elem name tests.tests)
|
||||
&& (test.expr != test.expected)
|
||||
|
||||
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
||||
else [] ) tests));
|
||||
|
||||
/* Create a test assuming that list elements are `true`.
|
||||
|
||||
Example:
|
||||
{ testX = allTrue [ true ]; }
|
||||
*/
|
||||
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
|
||||
|
||||
|
||||
# -- DEPRECATED --
|
||||
|
||||
traceShowVal = x: trace (showVal x) x;
|
||||
traceShowValMarked = str: x: trace (str + showVal x) x;
|
||||
|
||||
attrNamesToStr = a:
|
||||
trace ( "Warning: `attrNamesToStr` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please use more specific concatenation "
|
||||
+ "for your uses (`lib.concat(Map)StringsSep`)." )
|
||||
(concatStringsSep "; " (map (x: "${x}=") (attrNames a)));
|
||||
|
||||
showVal =
|
||||
trace ( "Warning: `showVal` is deprecated "
|
||||
+ "and will be removed in the next release, "
|
||||
+ "please use `traceSeqN`" )
|
||||
(let
|
||||
modify = v:
|
||||
let pr = f: { __pretty = f; val = v; };
|
||||
in if isDerivation v then pr
|
||||
(drv: "<δ:${drv.name}:${concatStringsSep ","
|
||||
(attrNames drv)}>")
|
||||
else if [] == v then pr (const "[]")
|
||||
else if isList v then pr (l: "[ ${go (head l)}, … ]")
|
||||
else if isAttrs v then pr
|
||||
(a: "{ ${ concatStringsSep ", " (attrNames a)} }")
|
||||
else v;
|
||||
go = x: generators.toPretty
|
||||
{ allowPrettyValues = true; }
|
||||
(modify x);
|
||||
in go);
|
||||
|
||||
traceXMLVal = x:
|
||||
trace ( "Warning: `traceXMLVal` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please use `traceValFn builtins.toXML`." )
|
||||
(trace (builtins.toXML x) x);
|
||||
traceXMLValMarked = str: x:
|
||||
trace ( "Warning: `traceXMLValMarked` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please use `traceValFn (x: str + builtins.toXML x)`." )
|
||||
(trace (str + builtins.toXML x) x);
|
||||
|
||||
# trace the arguments passed to function and its result
|
||||
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
|
||||
traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
|
||||
traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
|
||||
traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
|
||||
|
||||
traceValIfNot = c: x:
|
||||
trace ( "Warning: `traceValIfNot` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please use `if/then/else` and `traceValSeq 1`.")
|
||||
(if c x then true else traceSeq (showVal x) false);
|
||||
|
||||
|
||||
addErrorContextToAttrs = attrs:
|
||||
trace ( "Warning: `addErrorContextToAttrs` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please use `builtins.addErrorContext` directly." )
|
||||
(mapAttrs (a: v: addErrorContext "while evaluating ${a}" v) attrs);
|
||||
|
||||
# example: (traceCallXml "myfun" id 3) will output something like
|
||||
# calling myfun arg 1: 3 result: 3
|
||||
# this forces deep evaluation of all arguments and the result!
|
||||
# note: if result doesn't evaluate you'll get no trace at all (FIXME)
|
||||
# args should be printed in any case
|
||||
traceCallXml = a:
|
||||
trace ( "Warning: `traceCallXml` is deprecated "
|
||||
+ "and will be removed in the next release. "
|
||||
+ "Please complain if you use the function regularly." )
|
||||
(if !isInt a then
|
||||
traceCallXml 1 "calling ${a}\n"
|
||||
else
|
||||
let nr = a;
|
||||
in (str: expr:
|
||||
if isFunction expr then
|
||||
(arg:
|
||||
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (builtins.seq arg arg)}" (expr arg)
|
||||
)
|
||||
else
|
||||
let r = builtins.seq expr expr;
|
||||
in trace "${str}\n result:\n${builtins.toXML r}" r
|
||||
));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue