diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix index 3407229e921..d5338bc04ca 100644 --- a/nixos/lib/testing.nix +++ b/nixos/lib/testing.nix @@ -67,62 +67,16 @@ rec { }; - # Generate a coverage report from the coverage data produced by - # runTests. - makeReport = x: runCommand "report" { buildInputs = [rsync]; } - '' - mkdir -p $TMPDIR/gcov/ - - for d in ${x}/coverage-data/*; do - echo "doing $d" - [ -n "$(ls -A "$d")" ] || continue - - for i in $(cd $d/nix/store && ls); do - if ! test -e $TMPDIR/gcov/nix/store/$i; then - echo "copying $i" - mkdir -p $TMPDIR/gcov/$(echo $i | cut -c34-) - rsync -rv /nix/store/$i/.build/* $TMPDIR/gcov/ - fi - done - - chmod -R u+w $TMPDIR/gcov - - find $TMPDIR/gcov -name "*.gcda" -exec rm {} \; - - for i in $(cd $d/nix/store && ls); do - rsync -rv $d/nix/store/$i/.build/* $TMPDIR/gcov/ - done - - find $TMPDIR/gcov -name "*.gcda" -exec chmod 644 {} \; - - echo "producing info..." - ${pkgs.lcov}/bin/geninfo --ignore-errors source,gcov $TMPDIR/gcov --output-file $TMPDIR/app.info - cat $TMPDIR/app.info >> $TMPDIR/full.info - done - - echo "making report..." - mkdir -p $out/coverage - ${pkgs.lcov}/bin/genhtml --show-details $TMPDIR/full.info -o $out/coverage - cp $TMPDIR/full.info $out/coverage/ - - mkdir -p $out/nix-support - cat ${x}/nix-support/hydra-build-products >> $out/nix-support/hydra-build-products - echo "report coverage $out/coverage" >> $out/nix-support/hydra-build-products - [ ! -e ${x}/nix-support/failed ] || touch $out/nix-support/failed - ''; # */ - - makeTest = testFun: complete (call testFun); makeTests = testsFun: lib.mapAttrs (name: complete) (call testsFun); apply = makeTest; # compatibility call = f: f { inherit pkgs system; }; - complete = t: t // rec { + complete = { testScript, ... } @ t: t // rec { + nodes = buildVirtualNetwork ( - if t ? nodes then t.nodes else - if t ? machine then { machine = t.machine; } - else { } ); + t.nodes or (if t ? machine then { machine = t.machine; } else { })); testScript = # Call the test script with the computed nodes. @@ -162,7 +116,7 @@ rec { test = runTests driver; - report = makeReport test; + report = releaseTools.gcovReport { coverageRuns = [ test ]; }; }; diff --git a/nixos/release.nix b/nixos/release.nix index ff094cce05f..b98976c2cce 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -213,7 +213,8 @@ in rec { with lib; let testsFor = system: - mapAttrsRecursiveCond (x: !x ? test) (n: v: listToAttrs [(nameValuePair system v.test)]) + mapAttrsRecursiveCond (x: !x ? test) + (n: v: listToAttrs [(nameValuePair system (if v.makeCoverageReport or false then v.report else v.test))]) (import ./tests { inherit nixpkgs system; }); in fold recursiveUpdate {} (map testsFor systems); } diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix index 92501107780..fefbd75b4a3 100644 --- a/nixos/tests/quake3.nix +++ b/nixos/tests/quake3.nix @@ -14,11 +14,13 @@ in rec { + makeCoverageReport = true; + client = { config, pkgs, ... }: { imports = [ ./common/x11.nix ]; - services.xserver.driSupport = true; + hardware.opengl.driSupport = true; services.xserver.defaultDepth = pkgs.lib.mkOverride 0 16; environment.systemPackages = [ pkgs.quake3demo ]; nixpkgs.config.packageOverrides = overrides; diff --git a/nixos/tests/subversion.nix b/nixos/tests/subversion.nix index 309da90c5df..49450c78f3b 100644 --- a/nixos/tests/subversion.nix +++ b/nixos/tests/subversion.nix @@ -20,7 +20,7 @@ let # To build the kernel with coverage instrumentation, we need a # special patch to make coverage data available under /proc. linux = pkgs.linux.override (orig: { - stdenv = cleanupBuildTree (keepBuildTree orig.stdenv); + stdenv = overrideInStdenv pkgs.stdenv [ pkgs.keepBuildTree ]; extraConfig = '' GCOV_KERNEL y diff --git a/pkgs/build-support/release/default.nix b/pkgs/build-support/release/default.nix index acad3487dad..6288935ec2a 100644 --- a/pkgs/build-support/release/default.nix +++ b/pkgs/build-support/release/default.nix @@ -27,10 +27,14 @@ rec { } // args); coverageAnalysis = args: nixBuild ( - { inherit lcov enableCoverageInstrumentation makeCoverageAnalysisReport; + { inherit lcov enableGCOVInstrumentation makeGCOVReport; doCoverageAnalysis = true; } // args); + gcovReport = args: import ./gcov-report.nix ( + { inherit runCommand lcov rsync; + } // args); + rpmBuild = args: import ./rpm-build.nix ( { inherit vmTools; } // args); diff --git a/pkgs/build-support/release/gcov-report.nix b/pkgs/build-support/release/gcov-report.nix new file mode 100644 index 00000000000..8ce5c0488a7 --- /dev/null +++ b/pkgs/build-support/release/gcov-report.nix @@ -0,0 +1,49 @@ +{ runCommand, lcov, rsync, coverageRuns, lcovFilter ? [ "/nix/store/*" ], baseDirHack ? false }: + +runCommand "coverage" + { buildInputs = [ lcov rsync ]; + inherit lcovFilter baseDirHack; + } + '' + mkdir -p $TMPDIR/gcov $out/nix-support $out/coverage + info=$out/coverage/full.info + + for p in ${toString coverageRuns}; do + if [ -f $p/nix-support/hydra-build-products ]; then + cat $p/nix-support/hydra-build-products >> $out/nix-support/hydra-build-products + fi + + [ ! -e $p/nix-support/failed ] || touch $out/nix-support/failed + + opts= + for d in $p/coverage-data/*; do + for i in $(cd $d/nix/store && ls); do + if ! [ -e /nix/store/$i/.build ]; then continue; fi + if [ -e $TMPDIR/gcov/nix/store/$i ]; then continue; fi + echo "copying $i..." + rsync -a /nix/store/$i/.build/* $TMPDIR/gcov/ + if [ -n "$baseDirHack" ]; then + opts="-b $TMPDIR/gcov/$(cd /nix/store/$i/.build && ls)" + fi + done + + for i in $(cd $d/nix/store && ls); do + rsync -a $d/nix/store/$i/.build/* $TMPDIR/gcov/ --include '*/' --include '*.gcda' --exclude '*' + done + done + + chmod -R u+w $TMPDIR/gcov + + echo "producing info..." + geninfo --ignore-errors source,gcov $TMPDIR/gcov --output-file $TMPDIR/app.info $opts + cat $TMPDIR/app.info >> $info + done + + echo "making report..." + set -o noglob + lcov --remove $info ''$lcovFilter > $info.tmp + set +o noglob + mv $info.tmp $info + genhtml --show-details $info -o $out/coverage + echo "report coverage $out/coverage" >> $out/nix-support/hydra-build-products + '' diff --git a/pkgs/build-support/release/nix-build.nix b/pkgs/build-support/release/nix-build.nix index 993f12bc300..8ebae24c673 100644 --- a/pkgs/build-support/release/nix-build.nix +++ b/pkgs/build-support/release/nix-build.nix @@ -79,7 +79,7 @@ stdenv.mkDerivation ( prePhases = ["initPhase"] ++ prePhases; - buildInputs = buildInputs ++ stdenv.lib.optional doCoverageAnalysis args.makeCoverageAnalysisReport; + buildInputs = buildInputs ++ stdenv.lib.optional doCoverageAnalysis args.makeGCOVReport; lcovFilter = ["/nix/store/*"] ++ lcovFilter; diff --git a/pkgs/build-support/setup-hooks/enable-coverage-instrumentation.sh b/pkgs/build-support/setup-hooks/enable-coverage-instrumentation.sh index 08ef490e244..7175b408b02 100644 --- a/pkgs/build-support/setup-hooks/enable-coverage-instrumentation.sh +++ b/pkgs/build-support/setup-hooks/enable-coverage-instrumentation.sh @@ -1,3 +1,5 @@ +postPhases+=" cleanupBuildDir" + # Force GCC to build with coverage instrumentation. Also disable # optimisation, since it may confuse things. export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -O0 --coverage" @@ -12,3 +14,18 @@ postUnpack() { substituteInPlace $i --replace '*.$objext)' '*.$objext | *.gcno)' done } + +# Get rid of everything that isn't a gcno file or a C source file. +# Also strip the `.tmp_' prefix from gcno files. (The Linux kernel +# creates these.) +cleanupBuildDir() { + if ! [ -e $out/.build ]; then return; fi + + find $out/.build/ -type f -a ! \ + \( -name "*.c" -o -name "*.cc" -o -name "*.cpp" -o -name "*.h" -o -name "*.hh" -o -name "*.y" -o -name "*.l" -o -name "*.gcno" \) \ + | xargs rm -f -- + + for i in $(find $out/.build/ -name ".tmp_*.gcno"); do + mv "$i" "$(echo $i | sed s/.tmp_//)" + done +} diff --git a/pkgs/build-support/setup-hooks/keep-build-tree.sh b/pkgs/build-support/setup-hooks/keep-build-tree.sh new file mode 100644 index 00000000000..754900bfc33 --- /dev/null +++ b/pkgs/build-support/setup-hooks/keep-build-tree.sh @@ -0,0 +1,6 @@ +prePhases+=" moveBuildDir" + +moveBuildDir() { + mkdir -p $out/.build + cd $out/.build +} diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix index cb7e3ba925f..0e45ad05531 100644 --- a/pkgs/stdenv/adapters.nix +++ b/pkgs/stdenv/adapters.nix @@ -187,51 +187,13 @@ rec { { mkDerivation = args: stdenv.mkDerivation (args // extraAttrs); }; - /* Return a modified stdenv that performs the build under $out/.build - instead of in $TMPDIR. Thus, the sources are kept available. - This is useful for things like debugging or generation of - dynamic analysis reports. */ - keepBuildTree = stdenv: - addAttrsToDerivation - { prePhases = "moveBuildDir"; - - moveBuildDir = - '' - mkdir -p $out/.build - cd $out/.build - ''; - } stdenv; - - - cleanupBuildTree = stdenv: - addAttrsToDerivation - { postPhases = "cleanupBuildDir"; - - # Get rid of everything that isn't a gcno file or a C source - # file. This also includes the gcda files; we're not - # interested in coverage resulting from the package's own test - # suite. Also strip the `.tmp_' prefix from gcno files. (The - # Linux kernel creates these.) - cleanupBuildDir = - '' - find $out/.build/ -type f -a ! \ - \( -name "*.c" -o -name "*.h" -o -name "*.gcno" \) \ - | xargs rm -f -- - - for i in $(find $out/.build/ -name ".tmp_*.gcno"); do - mv "$i" "$(echo $i | sed s/.tmp_//)" - done - ''; - } stdenv; - - /* Return a modified stdenv that builds packages with GCC's coverage instrumentation. The coverage note files (*.gcno) are stored in $out/.build, along with the source code of the package, to enable programs like lcov to produce pretty-printed reports. */ addCoverageInstrumentation = stdenv: - cleanupBuildTree (keepBuildTree (overrideInStdenv stdenv [ pkgs.enableCoverageInstrumentation ])); + overrideInStdenv stdenv [ pkgs.enableGCOVInstrumentation pkgs.keepBuildTree ]; /* Replace the meta.maintainers field of a derivation. This is useful diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 0d22468e5ec..a79317cd6ba 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -396,10 +396,12 @@ let fixDarwinDylibNames = makeSetupHook { } ../build-support/setup-hooks/fix-darwin-dylib-names.sh; - enableCoverageInstrumentation = makeSetupHook { } ../build-support/setup-hooks/enable-coverage-instrumentation.sh; + keepBuildTree = makeSetupHook { } ../build-support/setup-hooks/keep-build-tree.sh; - makeCoverageAnalysisReport = makeSetupHook - { deps = [ pkgs.lcov pkgs.enableCoverageInstrumentation ]; } + enableGCOVInstrumentation = makeSetupHook { } ../build-support/setup-hooks/enable-coverage-instrumentation.sh; + + makeGCOVReport = makeSetupHook + { deps = [ pkgs.lcov pkgs.enableGCOVInstrumentation ]; } ../build-support/setup-hooks/make-coverage-analysis-report.sh;