1{
2 pkgs,
3 lib,
4 callPackage,
5 ...
6}:
7
8let
9 inherit (builtins) filterSource;
10
11 inherit (lib)
12 commitIdFromGitRepo
13 concatStringsSep
14 elem
15 elemAt
16 hasSuffix
17 listToAttrs
18 mapAttrs
19 optionalString
20 pathExists
21 readFile
22 removeSuffix
23 substring
24 traceSeqN
25 ;
26
27 inherit (lib.strings) match;
28
29 # Implicitly calls through to this file, similar to `let .. in` or `rec`.
30 inherit (pkgs.gerbil-support)
31 callPpp
32 gerbilLoadPath
33 gerbilPackage
34 gerbilPackages-unstable
35 gerbilSkippableFiles
36 gerbilSourceFilter
37 overrideSrcIfShaDiff
38 ppaToPl
39 pppToKV
40 pppToName
41 ppplToPpa
42 prePackage-defaults
43 prePackages-unstable
44 resolve-pre-src
45 sha256-of-pre-src
46 view
47 ;
48in
49
50{
51 pppToName = ppp: removeSuffix ".nix" (baseNameOf ppp); # from pre-package path to name
52 callPpp = ppp: callPackage ppp prePackage-defaults; # from pre-package path to pre-package
53 pppToKV = ppp: {
54 name = pppToName ppp;
55 value = callPpp ppp;
56 }; # from pre-package path to name
57 ppplToPpa = ppps: listToAttrs (map pppToKV ppps); # from pre-package path list to name/pre-package attr
58
59 prePackages-unstable = ppplToPpa [
60 ./gerbil-leveldb.nix
61 ./gerbil-lmdb.nix
62 ./gerbil-mysql.nix
63 ./gerbil-libxml.nix
64 ./gerbil-libyaml.nix
65 ./smug-gerbil.nix # ./ftw.nix
66 ./gerbil-utils.nix
67 ./gerbil-crypto.nix
68 ./gerbil-poo.nix
69 ./gerbil-persist.nix
70 ./gerbil-ethereum.nix
71 # ./gerbil-libp2p.nix
72 ./glow-lang.nix
73 ];
74
75 prePackage-defaults = {
76 gerbil = pkgs.gerbil-unstable;
77 gambit-params = pkgs.gambit-support.unstable-params;
78 gerbilPackages = gerbilPackages-unstable;
79 git-version = "";
80 version-path = "";
81 gerbilInputs = [ ];
82 nativeBuildInputs = [ ];
83 buildInputs = [ ];
84 buildScript = "./build.ss";
85 postInstall = "";
86 softwareName = "";
87 };
88
89 ppaToPl = mapAttrs (_: gerbilPackage);
90 gerbilPackages-unstable = ppaToPl prePackages-unstable;
91
92 resolve-pre-src = pre-src: pre-src.fun (removeAttrs pre-src [ "fun" ]);
93
94 gerbilVersionFromGit =
95 srcDir: version-path:
96 let
97 version-file = "${srcDir}/${version-path}.ss";
98 in
99 if pathExists version-file then
100 let
101 m = match "\\(import :clan/versioning.*\\)\n\\(register-software \"([-_.A-Za-z0-9]+)\" \"([-_.A-Za-z0-9]+)\"\\) ;; ([-0-9]+)\n" (
102 readFile version-file
103 );
104 in
105 {
106 version = "${elemAt m 2}-git";
107 git-version = elemAt m 1;
108 }
109 else
110 {
111 version = "0.0-git";
112 git-version =
113 let
114 gitpath = "${srcDir}/.git";
115 in
116 if pathExists gitpath then commitIdFromGitRepo gitpath else "0";
117 };
118
119 gerbilSkippableFiles = [
120 ".git"
121 ".build"
122 ".build_outputs"
123 "run"
124 "result"
125 "dep"
126 "BLAH"
127 "tmp.nix"
128 ];
129
130 gerbilSourceFilter =
131 path: type:
132 let
133 baseName = baseNameOf path;
134 in
135 !(elem baseName gerbilSkippableFiles || hasSuffix "~" baseName);
136
137 gerbilFilterSource = filterSource gerbilSourceFilter;
138
139 # Use this function in any package that uses Gerbil libraries, to define the GERBIL_LOADPATH.
140 gerbilLoadPath = gerbilInputs: concatStringsSep ":" (map (x: x + "/gerbil/lib") gerbilInputs);
141
142 path-src = path: { fun = _: path; };
143
144 view = traceSeqN 4;
145
146 sha256-of-pre-src = pre-src: if pre-src ? sha256 then pre-src.sha256 else "none";
147
148 overrideSrcIfShaDiff =
149 name: new-pre-src: super:
150 let
151 old-sha256 = sha256-of-pre-src super.${name}.pre-src;
152 new-sha256 = sha256-of-pre-src new-pre-src;
153 in
154 if old-sha256 == new-sha256 then
155 { }
156 else
157 view "Overriding ${name} old-sha256: ${old-sha256} new-sha256: ${new-sha256}" {
158 ${name} = super.${name} // {
159 pre-src = new-pre-src;
160 version = "override";
161 git-version = if new-pre-src ? rev then substring 0 7 new-pre-src.rev else "unknown";
162 };
163 };
164
165 pkgsOverrideGerbilPackageSrc = name: pre-src: pkgs: super: {
166 gerbil-support =
167 (super-support: {
168 prePackages-unstable =
169 (super-ppu: super-ppu // (overrideSrcIfShaDiff name pre-src super-ppu))
170 super-support.prePackages-unstable;
171 })
172 super.gerbil-support;
173 };
174
175 # Use this function to create a Gerbil library. See gerbil-utils as an example.
176 gerbilPackage =
177 prePackage:
178 let
179 pre-pkg = prePackage-defaults // prePackage;
180 inherit (pre-pkg)
181 pname
182 version
183 pre-src
184 git-version
185 meta
186 softwareName
187 gerbil-package
188 version-path
189 gerbil
190 gambit-params
191 gerbilInputs
192 nativeBuildInputs
193 buildInputs
194 buildScript
195 postInstall
196 ;
197 buildInputs_ = buildInputs;
198 in
199 pkgs.gccStdenv.mkDerivation rec {
200 # See ../gambit/build.nix regarding why we use gccStdenv
201 inherit
202 meta
203 pname
204 version
205 nativeBuildInputs
206 postInstall
207 ;
208 passthru = {
209 inherit pre-pkg;
210 };
211 src = resolve-pre-src pre-src;
212 buildInputs = [ gerbil ] ++ gerbilInputs ++ buildInputs_;
213
214 postPatch = ''
215 set -e ;
216 ${optionalString (version-path != "")
217 ''echo -e '(import :clan/versioning${
218 concatStringsSep "" (
219 map (
220 x:
221 let
222 px = x.passthru.pre-pkg;
223 in
224 optionalString (px.version-path != "") " :${px.gerbil-package}/${px.version-path}"
225 ) gerbilInputs
226 )
227 })\n(register-software "${softwareName}" "v${git-version}")\n' > "${version-path}.ss"''
228 }
229 patchShebangs . ;
230 '';
231
232 postConfigure = ''
233 export GERBIL_BUILD_CORES=$NIX_BUILD_CORES
234 export GERBIL_PATH=$PWD/.build
235 export GERBIL_LOADPATH=${gerbilLoadPath ([ "$out" ] ++ gerbilInputs)}
236 ${pkgs.gambit-support.export-gambopt gambit-params}
237 '';
238
239 buildPhase = ''
240 runHook preBuild
241 ${buildScript}
242 runHook postBuild
243 '';
244
245 installPhase = ''
246 runHook preInstall
247 mkdir -p $out/gerbil
248 cp -fa .build/* $out/gerbil/
249 if [[ -d $out/gerbil/bin ]] ; then
250 ( cd $out/gerbil
251 bins=$(find ../gerbil/bin -type f)
252 if [[ -n $bins ]] ; then
253 ( mkdir -p ../bin
254 cd ..
255 ln -s $bins bin
256 )
257 fi
258 )
259 fi
260 runHook postInstall
261 '';
262
263 dontFixup = true;
264
265 checkPhase = ''
266 runHook preCheck
267 if [[ -f unit-tests.ss ]] ; then
268 export GERBIL_APPLICATION_HOME=$PWD
269 ./unit-tests.ss version
270 ./unit-tests.ss
271 else
272 echo "No gerbil-utils style unit-tests.ss detected for ${pname} ${version}.";
273 fi
274 runHook postCheck
275 '';
276
277 doCheck = true;
278 };
279}