1 # Hydra build file for coccinelle
3 { nixpkgs ? /etc/nixos/nixpkgs
4 , cocciSrc ? { outPath = ./.; revCount = 1234; gitTag = "abcdef"; }
5 , testsSrc ? { outPath = ../big-tests; rev = 1234; }
6 , officialRelease ? false
12 version = builtins.readFile ./version;
13 versionSuffix = if officialRelease then "" else "pre${toString cocciSrc.revCount}-${cocciSrc.gitTag}";
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.
21 pkgs = import nixpkgs {
23 config.packageOverrides =
25 { ocaml = pkgs.ocaml_3_12_1;
26 ocamlPackages = pkgs.ocamlPackages_3_12_1;
30 in with pkgs; with ocamlPackages; releaseTools.sourceTarball {
31 name = "coccinelle-tarball";
33 inherit officialRelease;
35 inherit versionSuffix;
38 perl python texLiveFull
40 ocaml_pcre ocaml_sexplib
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
55 export HOME=$TMPDIR # the latex installation needs to write to the $HOME directory, so rename it here
58 dontCopyDist = 1; # we'll copy the tarball to the tarballs folder ourselves (and rename it)
60 export HOME=$PREVHOME # restore the home directory
62 ensureDir "$out/tarballs"
64 # rename the tarball to give it a version-specific name
65 cp coccinelle-*.tar.gz "$out/tarballs/coccinelle-${version}${versionSuffix}.tar.gz"
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 {
76 config.packageOverrides = ocamlVer;
79 ocamlEnv = mkEnv pkgs;
80 in with pkgs; releaseTools.nixBuild {
84 # ocamlEnv contains the ocaml libraries in scope.
86 lib.optional inclPython python
87 ++ [ perl texLiveFull ncurses makeWrapper ocamlEnv ];
89 # patch the files for use with nix
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"
96 configureFlags = lib.optional (!inclPython) "--without-python";
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)
104 # run checking after installation.
105 # also, the test phase may require a yes/no input.
108 wrapProgram "$out/bin/spatch" \
109 --prefix "LD_LIBRARY_PATH" ":" "$out/lib" \
110 --prefix "PYTHONPATH" ":" "$out/share/coccinelle/python"
112 wrapProgram "$out/bin/spatch.opt" \
113 --prefix "LD_LIBRARY_PATH" ":" "$out/lib" \
114 --prefix "PYTHONPATH" ":" "$out/share/coccinelle/python"
121 # selects which version of ocaml and ocamlPackages to use in nixpkgs.
123 { ocaml = pkgs.ocaml_3_12_1;
124 ocamlPackages = pkgs.ocamlPackages_3_12_1;
127 { ocaml = pkgs.ocaml_3_11_1;
128 ocamlPackages = pkgs.ocamlPackages_3_11_1;
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:
136 name = "cocci-ocamlenv";
137 paths = with pkgs.ocamlPackages; [ pkgs.ocaml findlib menhir ] ++ mkList pkgs.ocamlPackages;
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: []);
146 # package builder for Debian-based OS'ses
148 system: diskImageFun:
150 with import nixpkgs { inherit system; };
151 releaseTools.debBuild {
152 name = "coccinelle-deb";
154 diskImage = diskImageFun vmTools.diskImageFuns {
155 extraPackages = [ "python" "python-support" "ocaml-nox" "ocaml-findlib" ];
157 debRequires = [ "python" "python-support" "ocaml-nox" "ocaml-findlib" ];
167 makeDeb_i686 = makeDeb "i686-linux";
168 makeDeb_x86_64 = makeDeb "x86_64-linux";
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" ];
180 ensureDir "$out/nix-support"
181 touch "$TMPDIR/result.log"
182 exec > >(tee -a "$TMPDIR/result.log") 2> >(tee -a "$TMPDIR/result.log" >&2)
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"
190 description = "Coccinelle post-build task";
191 schedulingPriority = 8;
193 } // args // { inherit name; });
195 mkReport = inputs: mkTask (pkgs: _: with pkgs; {
197 builds = map (i: i {}) inputs;
200 echo "collecting logs"
201 for build in $builds; do
202 echo "$build/nix-support/make.log"
203 cat "$build/nix-support/make.log"
206 echo "grepping OCaml warnings"
207 if grep -2 "Warning " "$TMPDIR/result.log"
209 echo "found warnings!"
212 echo "there are apparently no significant warnings"
217 description = "Analysis of the coccinelle build reports";
218 schedulingPriority = 5;
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
227 mkRegress = cocciSelect: mkTask (pkgs: system: with pkgs;
228 let coccinelle = cocciSelect { inherit system; };
230 name = "regression-${toString testsSrc.rev}";
231 buildInputs = [ coccinelle ];
234 # prepare a writeable tests directory
235 # as this directory contains large
236 # files, we'll create links to the
238 ensureDir "$TMPDIR/tests"
239 cp -rs ${testsSrc}/* "$TMPDIR/tests/"
240 chmod -R u+w "$TMPDIR/tests/"
243 # initialize essential environment variables
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
250 # generate the test outcomes
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.
257 tar -czf "$out/results.tar.gz" ./tests
258 echo "file binary-dist $out/results.tar.gz" >> "$out/nix-support/hydra-build-products"
262 description = "Regression test of Coccinelle";
263 schedulingPriority = 8;
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; };
273 name = "test-${toString testsSrc.rev}";
276 # prepare a writeable tests directory
277 # as this directory contains large
278 # files, we'll create links to the
280 ensureDir "$TMPDIR/tests"
281 cp -rs ${testsSrc}/* "$TMPDIR/tests/"
282 chmod -R u+w "$TMPDIR/tests/"
284 # extract the outcome of the regression test over it
285 echo "reconstructing regression directory"
287 tar xfz "${regress}/results.tar.gz"
290 echo "analyzing results"
293 echo "verifying the outcome"
298 description = "Regression test of Coccinelle";
299 schedulingPriority = 8;
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; };
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 ];
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);
324 regress = mkRegress build;
325 test = checkRegress regress;