1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
;; sui-spec/specs/derivation.lisp — CppNix derivation path algorithm,
;; authored as Lisp data instead of as imperative Rust code.
;;
;; This spec is THE source of truth for how `builtins.derivation`
;; computes `.drv` paths and output store paths. Both the sui
;; tree-walker and the sui bytecode VM interpret this spec. Four
;; spec bugs this session were fixes at this layer — each bug, if
;; we had been authoring here, would have been a one-line edit.
;;
;; ── Algorithm intuition ──────────────────────────────────────────
;;
;; CppNix constructs a derivation's identity in four phases:
;;
;; 1. Mask: empty every output's path, plus any env entry
;; whose name matches an output name. This is the
;; "unresolved form".
;; 2. Inner hash: sha256 of the unresolved ATerm serialization.
;; Call the hex digest `inner-hex`.
;; 3. Fill: from `inner-hex` + output name, compute each
;; output's store path and write it back into BOTH
;; `outputs[name].path` AND `env[name]`. The
;; derivation is now in "final form".
;; 4. Drv hash: sha256 of the final ATerm → build the `.drv`
;; store path via `compute_drv_path`.
;;
;; Two bugs we fixed — #12 and #13 — were both in phase 1/2: sui
;; was hashing the unresolved form for BOTH the output paths AND
;; the .drv path, and was dropping env.out entirely instead of
;; masking it to "". Here the two hashes are visibly distinct
;; slots (`inner-hex` vs `final-hex`) and the mask step is named.
;; ── Fixed-output derivation algorithm ─────────────────────────────
;;
;; Used by builtins.fetchurl, fetchTarball, fetchGit when an output
;; hash is supplied up front. The output's store path derives from
;; the *content hash*, not the recipe. This means an FOD's store
;; path is stable across recipe permutations as long as the resulting
;; bytes are identical — the property that makes binary caches work.
;;
;; The M3 implementation wires SeedFixedOutputHash to
;; sui_compat::store_path::compute_fixed_output_path; the rest of
;; the pipeline shares phases with input-addressed.
;; ── Content-addressed derivation algorithm ────────────────────────
;;
;; CA derivations defer output-path computation to build-time — the
;; output's store path is derived from the actually-realised content
;; hash, not the recipe. At recipe time we emit *placeholders* the
;; builder rewrites once it knows the real hash. Enabled by the
;; `ca-derivations` experimental feature on cppnix.
;;
;; M4 implementation wires MarkContentAddressed +
;; EmitCaPlaceholders to sui_compat::store_path.