Commit | Line | Data |
---|---|---|
17ba0788 C |
1 | # Hydra build file for coccinelle |
2 | ||
3 | { nixpkgs ? /etc/nixos/nixpkgs | |
4 | , cocciSrc ? { outPath = ./.; revCount = 1234; gitTag = "abcdef"; } | |
5 | , testsSrc ? { outPath = ../big-tests; rev = 1234; } | |
6 | , officialRelease ? false | |
7 | }: | |
8 | ||
9 | let | |
10 | ||
11 | # version information | |
12 | version = builtins.readFile ./version; | |
13 | versionSuffix = if officialRelease then "" else "pre${toString cocciSrc.revCount}-${cocciSrc.gitTag}"; | |
14 | ||
15 | # The source tarball taken from the repository. | |
16 | # The tarball should actually be compilable using | |
17 | # ./configure && make depend && make opt && make install | |
18 | # on systems other than nix. | |
19 | tarball = | |
20 | let | |
21 | pkgs = import nixpkgs { | |
22 | # use ocaml 3.12 | |
23 | config.packageOverrides = | |
24 | pkgs: | |
25 | { ocaml = pkgs.ocaml_3_12_1; | |
26 | ocamlPackages = pkgs.ocamlPackages_3_12_1; | |
27 | }; | |
28 | }; | |
29 | ||
30 | in with pkgs; with ocamlPackages; releaseTools.sourceTarball { | |
31 | name = "coccinelle-tarball"; | |
32 | src = cocciSrc; | |
33 | inherit officialRelease; | |
34 | inherit version; | |
35 | inherit versionSuffix; | |
36 | ||
37 | buildInputs = [ | |
38 | perl python texLiveFull | |
39 | ocaml findlib menhir | |
40 | ocaml_pcre ocaml_sexplib | |
41 | ocaml_extlib pycaml | |
42 | ]; | |
43 | ||
44 | configurePhase = '' | |
45 | # explicitly run perl because the configure script references a perl outside the nix store | |
46 | # substituting the path to perl is not a good idea as it would invalidate the tarball on | |
47 | # non-nix machines. | |
48 | perl -w ./configure | |
49 | ||
50 | make depend | |
51 | ''; | |
52 | ||
53 | preDist = '' | |
54 | local PREVHOME=$HOME | |
55 | export HOME=$TMPDIR # the latex installation needs to write to the $HOME directory, so rename it here | |
56 | ''; | |
57 | ||
58 | dontCopyDist = 1; # we'll copy the tarball to the tarballs folder ourselves (and rename it) | |
59 | postDist = '' | |
60 | export HOME=$PREVHOME # restore the home directory | |
61 | ||
62 | ensureDir "$out/tarballs" | |
63 | ||
64 | # rename the tarball to give it a version-specific name | |
65 | cp coccinelle-*.tar.gz "$out/tarballs/coccinelle-${version}${versionSuffix}.tar.gz" | |
66 | ''; | |
67 | }; | |
68 | ||
69 | ||
70 | # builds coccinelle, given a ocaml selector function and an ocaml environment builder. | |
71 | # the build procedure itself is largely the same as the coccinelle expression in nixpkgs. | |
72 | # the result should be a usable nix-expression | |
73 | mkBuild = { name, ocamlVer, mkEnv, inclPython }: { system ? builtins.currentSystem }: | |
74 | let pkgs = import nixpkgs { | |
75 | inherit system; | |
76 | config.packageOverrides = ocamlVer; | |
77 | }; | |
78 | ||
79 | ocamlEnv = mkEnv pkgs; | |
80 | in with pkgs; releaseTools.nixBuild { | |
81 | inherit name; | |
82 | src = tarball; | |
83 | ||
84 | # ocamlEnv contains the ocaml libraries in scope. | |
85 | buildInputs = | |
86 | lib.optional inclPython python | |
87 | ++ [ perl texLiveFull ncurses makeWrapper ocamlEnv ]; | |
88 | ||
89 | # patch the files for use with nix | |
90 | preConfigure = '' | |
91 | sed -i "configure" -e's|/usr/bin/perl|${perl}/bin/perl|g' | |
92 | sed -i "globals/config.ml.in" \ | |
93 | -e"s|/usr/local/share|$out/share|g" | |
94 | ''; | |
95 | ||
96 | configureFlags = lib.optional (!inclPython) "--without-python"; | |
97 | ||
98 | buildPhase = '' | |
99 | make depend 2> >(tee -a "$out/nix-support/make.log" >&2) | |
100 | make all 2> >(tee -a "$out/nix-support/make.log" >&2) | |
101 | make all.opt 2> >(tee -a "$out/nix-support/make.log" >&2) | |
102 | ''; | |
103 | ||
104 | # run checking after installation. | |
105 | # also, the test phase may require a yes/no input. | |
106 | doCheck = false; | |
107 | postInstall = '' | |
108 | wrapProgram "$out/bin/spatch" \ | |
109 | --prefix "LD_LIBRARY_PATH" ":" "$out/lib" \ | |
110 | --prefix "PYTHONPATH" ":" "$out/share/coccinelle/python" | |
111 | ||
112 | wrapProgram "$out/bin/spatch.opt" \ | |
113 | --prefix "LD_LIBRARY_PATH" ":" "$out/lib" \ | |
114 | --prefix "PYTHONPATH" ":" "$out/share/coccinelle/python" | |
115 | ||
116 | yes | make test | |
117 | ''; | |
118 | }; | |
119 | ||
120 | ||
121 | # selects which version of ocaml and ocamlPackages to use in nixpkgs. | |
122 | selOcaml312 = pkgs: | |
123 | { ocaml = pkgs.ocaml_3_12_1; | |
124 | ocamlPackages = pkgs.ocamlPackages_3_12_1; | |
125 | }; | |
126 | selOcaml311 = pkgs: | |
127 | { ocaml = pkgs.ocaml_3_11_1; | |
128 | ocamlPackages = pkgs.ocamlPackages_3_11_1; | |
129 | }; | |
130 | ||
131 | ||
132 | # builds an environment with the ocaml packages needed to build coccinelle | |
133 | # the mkList function selects which additional packages to include | |
134 | mkOcamlEnv = mkList: pkgs: | |
135 | pkgs.buildEnv { | |
136 | name = "cocci-ocamlenv"; | |
137 | paths = with pkgs.ocamlPackages; [ pkgs.ocaml findlib menhir ] ++ mkList pkgs.ocamlPackages; | |
138 | }; | |
139 | ||
140 | # selections of ocaml libraries | |
141 | libs_full = mkOcamlEnv (libs: with libs; [ ocaml_pcre ocaml_sexplib ocaml_extlib pycaml ]); | |
142 | libs_rse = mkOcamlEnv (libs: with libs; [ ocaml_pcre ocaml_sexplib ocaml_extlib ]); | |
143 | libs_se = mkOcamlEnv (libs: with libs; [ ocaml_sexplib ocaml_extlib ]); | |
144 | libs_null = mkOcamlEnv (libs: []); | |
145 | ||
146 | # package builder for Debian-based OS'ses | |
147 | makeDeb = | |
148 | system: diskImageFun: | |
149 | ||
150 | with import nixpkgs { inherit system; }; | |
151 | releaseTools.debBuild { | |
152 | name = "coccinelle-deb"; | |
153 | src = tarball; | |
154 | diskImage = diskImageFun vmTools.diskImageFuns { | |
155 | extraPackages = [ "python" "python-support" "ocaml-nox" "ocaml-findlib" ]; | |
156 | }; | |
157 | debRequires = [ "python" "python-support" "ocaml-nox" "ocaml-findlib" ]; | |
158 | doCheck = false; | |
159 | ||
160 | buildPhase = '' | |
161 | make depend | |
162 | make all | |
163 | make all.opt | |
164 | ''; | |
165 | }; | |
166 | ||
167 | makeDeb_i686 = makeDeb "i686-linux"; | |
168 | makeDeb_x86_64 = makeDeb "x86_64-linux"; | |
169 | ||
170 | mkTask = | |
171 | argsfun: { system ? builtins.currentSystem }: | |
172 | let pkgs = import nixpkgs { inherit system; }; | |
173 | args = argsfun pkgs system; | |
174 | name = "${args.name}-${version}${versionSuffix}"; | |
175 | in pkgs.stdenv.mkDerivation ({ | |
176 | phases = [ "runPhase" ]; | |
177 | ||
178 | runPhase = '' | |
179 | ensureDir "$out" | |
180 | ensureDir "$out/nix-support" | |
181 | touch "$TMPDIR/result.log" | |
182 | exec > >(tee -a "$TMPDIR/result.log") 2> >(tee -a "$TMPDIR/result.log" >&2) | |
183 | runHook execPhase | |
184 | cp "$TMPDIR/result.log" "$out/" | |
185 | echo "report log $out/result.log" >> "$out/nix-support/hydra-build-products" | |
186 | echo "$name" > "$out/nix-support/hydra-release-name" | |
187 | ''; | |
188 | ||
189 | meta = { | |
190 | description = "Coccinelle post-build task"; | |
191 | schedulingPriority = 8; | |
192 | }; | |
193 | } // args // { inherit name; }); | |
194 | ||
195 | mkReport = inputs: mkTask (pkgs: _: with pkgs; { | |
196 | name = "report"; | |
197 | builds = map (i: i {}) inputs; | |
198 | ||
199 | execPhase = '' | |
200 | echo "collecting logs" | |
201 | for build in $builds; do | |
202 | echo "$build/nix-support/make.log" | |
203 | cat "$build/nix-support/make.log" | |
204 | done | |
205 | ||
206 | echo "grepping OCaml warnings" | |
207 | if grep -2 "Warning " "$TMPDIR/result.log" | |
208 | then | |
209 | echo "found warnings!" | |
210 | false | |
211 | else | |
212 | echo "there are apparently no significant warnings" | |
213 | fi | |
214 | ''; | |
215 | ||
216 | meta = { | |
217 | description = "Analysis of the coccinelle build reports"; | |
218 | schedulingPriority = 5; | |
219 | }; | |
220 | }); | |
221 | ||
222 | # Produces regression test results, which can be positive or | |
223 | # negative. The build should succeed regardless of the outcome | |
224 | # of individual tests unless coccinelle is horribly broken. | |
225 | # The resulting files are stored in a tarball so that it allows | |
226 | # manual inspection. | |
227 | mkRegress = cocciSelect: mkTask (pkgs: system: with pkgs; | |
228 | let coccinelle = cocciSelect { inherit system; }; | |
229 | in { | |
230 | name = "regression-${toString testsSrc.rev}"; | |
231 | buildInputs = [ coccinelle ]; | |
232 | ||
233 | execPhase = '' | |
234 | # prepare a writeable tests directory | |
235 | # as this directory contains large | |
236 | # files, we'll create links to the | |
237 | # individual files. | |
238 | ensureDir "$TMPDIR/tests" | |
239 | cp -rs ${testsSrc}/* "$TMPDIR/tests/" | |
240 | chmod -R u+w "$TMPDIR/tests/" | |
241 | cd "$TMPDIR/tests" | |
242 | ||
243 | # initialize essential environment variables | |
244 | # for the makefile | |
245 | export COCCIDIR=$TMPDIR | |
246 | export SPATCH=${coccinelle}/bin/spatch.opt | |
247 | export ISO=${coccinelle}/share/coccinelle/standard.iso | |
248 | export DEFS=${coccinelle}/share/coccinelle/standard.h | |
249 | ||
250 | # generate the test outcomes | |
251 | make -e all | |
252 | ||
253 | # collect the results | |
254 | # note: the tarball is likely to contain useless | |
255 | # symbolic links to files in the nix store. So be it. | |
256 | cd "$TMPDIR" | |
257 | tar -czf "$out/results.tar.gz" ./tests | |
258 | echo "file binary-dist $out/results.tar.gz" >> "$out/nix-support/hydra-build-products" | |
259 | ''; | |
260 | ||
261 | meta = { | |
262 | description = "Regression test of Coccinelle"; | |
263 | schedulingPriority = 8; | |
264 | }; | |
265 | }); | |
266 | ||
267 | # Checks whether the regression tests meet our expectations. | |
268 | # If the set of failed tests is different than specified in | |
269 | # the tests repository, this check fails. | |
270 | checkRegress = regressSelect: mkTask (pkgs: system: with pkgs; | |
271 | let regress = regressSelect { inherit system; }; | |
272 | in { | |
273 | name = "test-${toString testsSrc.rev}"; | |
274 | ||
275 | execPhase = '' | |
276 | # prepare a writeable tests directory | |
277 | # as this directory contains large | |
278 | # files, we'll create links to the | |
279 | # individual files. | |
280 | ensureDir "$TMPDIR/tests" | |
281 | cp -rs ${testsSrc}/* "$TMPDIR/tests/" | |
282 | chmod -R u+w "$TMPDIR/tests/" | |
283 | ||
284 | # extract the outcome of the regression test over it | |
285 | echo "reconstructing regression directory" | |
286 | cd "$TMPDIR" | |
287 | tar xfz "${regress}/results.tar.gz" | |
288 | cd "$TMPDIR/tests" | |
289 | ||
290 | echo "analyzing results" | |
291 | make failedlog | |
292 | ||
293 | echo "verifying the outcome" | |
294 | make check | |
295 | ''; | |
296 | ||
297 | meta = { | |
298 | description = "Regression test of Coccinelle"; | |
299 | schedulingPriority = 8; | |
300 | }; | |
301 | }); | |
302 | ||
303 | in # list of jobs | |
304 | rec { | |
305 | inherit tarball; | |
306 | ||
307 | # different configurations of coccinelle builds based on different ocamls/available libraries | |
308 | build = mkBuild { name = "coccinelle"; ocamlVer = selOcaml312; mkEnv = libs_full; inclPython = true; }; | |
309 | build_rse = mkBuild { name = "coccinelle_config1"; ocamlVer = selOcaml312; mkEnv = libs_rse; inclPython = true; }; | |
310 | build_se = mkBuild { name = "coccinelle_config2"; ocamlVer = selOcaml312; mkEnv = libs_se; inclPython = true; }; | |
311 | build_null_12 = mkBuild { name = "coccinelle_config3"; ocamlVer = selOcaml312; mkEnv = libs_null; inclPython = true; }; | |
312 | build_null_11 = mkBuild { name = "coccinelle_config4"; ocamlVer = selOcaml311; mkEnv = libs_null; inclPython = true; }; | |
313 | build_null_12_np = mkBuild { name = "coccinelle_config5"; ocamlVer = selOcaml312; mkEnv = libs_null; inclPython = false; }; | |
314 | build_null_11_np = mkBuild { name = "coccinelle_config6"; ocamlVer = selOcaml311; mkEnv = libs_null; inclPython = false; }; | |
315 | build_rse_np = mkBuild { name = "coccinelle_config7"; ocamlVer = selOcaml312; mkEnv = libs_rse; inclPython = false; }; | |
316 | ||
317 | report = mkReport [ build build_rse build_se build_null_12 build_null_11 build_null_12_np build_null_11_np build_rse_np ]; | |
318 | ||
319 | # different debian builds | |
320 | # deb_ubuntu1010_i386 = makeDeb_i686 (disk: disk.ubuntu1010i386); | |
321 | # deb_ubuntu1010_x86_64 = makeDeb_x86_64 (disk: disk.ubuntu1010x86_64); | |
322 | ||
323 | # extensive tests | |
324 | regress = mkRegress build; | |
325 | test = checkRegress regress; | |
326 | } |