about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/tools/build-managers/bazel
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/tools/build-managers/bazel')
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/0.4.nix100
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/bash-tools-test.nix42
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-deps/default.nix81
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-remote/default.nix81
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/default.nix25
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/deps.nix21
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/default.nix346
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks-0.4.patch51
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks.patch37
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/python-bin-path-test.nix57
-rw-r--r--nixpkgs/pkgs/development/tools/build-managers/bazel/python-stub-path-fix.patch13
11 files changed, 854 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/0.4.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/0.4.nix
new file mode 100644
index 000000000000..1018abd6ee9c
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/0.4.nix
@@ -0,0 +1,100 @@
+{ stdenv, lib, fetchurl, jdk, zip, unzip, bash, makeWrapper, which, coreutils
+# Always assume all markers valid (don't redownload dependencies).
+# Also, don't clean up environment variables.
+, enableNixHacks ? false
+}:
+
+stdenv.mkDerivation rec {
+
+  version = "0.4.5";
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/bazelbuild/bazel/;
+    description = "Build tool that builds code quickly and reliably";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ cstrahan philandstuff ];
+    platforms = platforms.linux;
+    broken = true; # 2018-08-07
+  };
+
+  name = "bazel-${version}";
+
+  src = fetchurl {
+    url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";
+    sha256 = "0asmq3kxnl4326zhgh13mvcrc8jvmiswjj4ymrq0943q4vj7nwrb";
+  };
+
+  preUnpack = ''
+    mkdir bazel
+    cd bazel
+  '';
+  sourceRoot = ".";
+
+  patches = lib.optional enableNixHacks ./nix-hacks-0.4.patch;
+
+  postPatch = ''
+    for f in $(grep -l -r '/bin/bash'); do
+      substituteInPlace "$f" --replace '/bin/bash' '${bash}/bin/bash'
+    done
+    for f in $(grep -l -r '/usr/bin/env'); do
+      substituteInPlace "$f" --replace '/usr/bin/env' '${coreutils}/bin/env'
+    done
+  '' + lib.optionalString stdenv.isDarwin ''
+    sed -i 's,/usr/bin/xcrun clang,clang,g' \
+      scripts/bootstrap/compile.sh \
+      src/tools/xcode/realpath/BUILD \
+      src/tools/xcode/stdredirect/BUILD \
+      src/tools/xcode/xcrunwrapper/xcrunwrapper.sh
+    sed -i 's,/usr/bin/xcrun "''${TOOLNAME}","''${TOOLNAME}",g' \
+      src/tools/xcode/xcrunwrapper/xcrunwrapper.sh
+    sed -i 's/"xcrun", "clang"/"clang"/g' tools/osx/xcode_configure.bzl
+  '';
+
+  buildInputs = [
+    jdk
+    zip
+    unzip
+    makeWrapper
+    which
+  ];
+
+  # These must be propagated since the dependency is hidden in a compressed
+  # archive.
+
+  propagatedBuildInputs = [
+    bash
+  ];
+
+  buildPhase = ''
+    export TMPDIR=/tmp/.bazel-$UID
+    ./compile.sh
+    ./output/bazel --output_user_root=$TMPDIR/.bazel build //scripts:bash_completion \
+      --spawn_strategy=standalone \
+      --genrule_strategy=standalone
+    cp bazel-bin/scripts/bazel-complete.bash output/
+  '';
+
+  # Build the CPP and Java examples to verify that Bazel works.
+
+  doCheck = true;
+  checkPhase = ''
+    export TEST_TMPDIR=$(pwd)
+    ./output/bazel test --test_output=errors \
+        examples/cpp:hello-success_test \
+        examples/java-native/src/test/java/com/example/myproject:hello
+  '';
+
+  # Bazel expects gcc and java to be in the path.
+
+  installPhase = ''
+    mkdir -p $out/bin
+    mv output/bazel $out/bin
+    wrapProgram "$out/bin/bazel" --prefix PATH : "${stdenv.cc}/bin:${jdk}/bin"
+    mkdir -p $out/share/bash-completion/completions $out/share/zsh/site-functions
+    mv output/bazel-complete.bash $out/share/bash-completion/completions/
+    cp scripts/zsh_completion/_bazel $out/share/zsh/site-functions/
+  '';
+
+  dontStrip = true;
+  dontPatchELF = true;
+}
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/bash-tools-test.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/bash-tools-test.nix
new file mode 100644
index 000000000000..3bbab475c573
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/bash-tools-test.nix
@@ -0,0 +1,42 @@
+{ stdenv, writeText, runCommandCC, bazel }:
+
+# Tests that certain executables are available in bazel-executed bash shells.
+
+let
+  WORKSPACE = writeText "WORKSPACE" ''
+    workspace(name = "our_workspace")
+  '';
+
+  fileIn = writeText "input.txt" ''
+  one
+  two
+  three
+  '';
+
+  fileBUILD = writeText "BUILD" ''
+    genrule(
+      name = "tool_usage",
+      srcs = [ ":input.txt" ],
+      outs = [ "output.txt" ],
+      cmd = "cat $(location :input.txt) | gzip - | gunzip - | awk '/t/' > $@",
+    )
+  '';
+
+  runLocal = name: script: runCommandCC name { preferLocalBuild = true; } script;
+
+  workspaceDir = runLocal "our_workspace" ''
+    mkdir $out
+    cp ${WORKSPACE} $out/WORKSPACE
+    cp ${fileIn} $out/input.txt
+    cp ${fileBUILD} $out/BUILD
+  '';
+
+  testBazel = runLocal "bazel-test-bash-tools" ''
+    export HOME=$(mktemp -d)
+    cp -r ${workspaceDir} wd && chmod +w wd && cd wd
+    ${bazel}/bin/bazel build :tool_usage
+    cp bazel-genfiles/output.txt $out
+    echo "Testing content" && [ "$(cat $out | wc -l)" == "2" ] && echo "OK"
+  '';
+
+in testBazel
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-deps/default.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-deps/default.nix
new file mode 100644
index 000000000000..6fdb57345072
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-deps/default.nix
@@ -0,0 +1,81 @@
+{ stdenv, buildBazelPackage, lib, fetchFromGitHub, git, jre, makeWrapper }:
+
+buildBazelPackage rec {
+  name = "bazel-deps-${version}";
+  version = "2019-02-01";
+
+  meta = with stdenv.lib; {
+    homepage = "https://github.com/johnynek/bazel-deps";
+    description = "Generate bazel dependencies for maven artifacts";
+    license = licenses.mit;
+    maintainers = [ maintainers.uri-canva ];
+    platforms = platforms.all;
+  };
+
+  src = fetchFromGitHub {
+    owner = "johnynek";
+    repo = "bazel-deps";
+    rev = "6585033409e09028852403ec15ec0c77851234be";
+    sha256 = "0hypf7mcbpx2djqm92k82vn1k6pbnv564xbnazx8nw60f6ns0x87";
+  };
+
+  bazelTarget = "//src/scala/com/github/johnynek/bazel_deps:parseproject_deploy.jar";
+
+  buildInputs = [ git makeWrapper ];
+
+  fetchAttrs = {
+    preInstall = ''
+      # Remove all built in external workspaces, Bazel will recreate them when building
+      rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker,embedded_jdk,\@embedded_jdk.marker,local_*,\@local_*}
+      # For each external workspace, remove all files that aren't referenced by Bazel
+      # Many of these files are non-hermetic (for example .git/refs/remotes/origin/HEAD)
+      files_to_delete=()
+      for workspace in $(find $bazelOut/external -maxdepth 2 -name "WORKSPACE" -print0 | xargs -0L1 dirname); do
+        workspaceOut="$NIX_BUILD_TOP/workspaces/$(basename workspace)/output"
+        workspaceUserRoot="$NIX_BUILD_TOP/workspaces/$(basename workspace)/tmp"
+        rm -rf $workspace/.git
+        if ! targets_and_files=$(cd "$workspace" && bazel --output_base="$workspaceOut" --output_user_root="$workspaceUserRoot" query '//...:*' 2> /dev/null | sort -u); then
+          continue
+        fi
+        if ! targets=$(cd "$workspace" && bazel --output_base="$workspaceOut" --output_user_root="$workspaceUserRoot" query '//...:all' 2> /dev/null | sort -u); then
+          continue
+        fi
+        mapfile -t referenced_files < <(comm -23 <(printf '%s' "$targets_and_files") <(printf '%s' "$targets") | sed -e 's,^//:,,g' | sed -e 's,^//,,g' | sed -e 's,:,/,g')
+        referenced_files+=( "WORKSPACE" )
+        for referenced_file in "''${referenced_files[@]}"; do
+          # Some of the referenced files are symlinks to non-referenced files.
+          # The symlink targets have deterministic contents, but non-deterministic
+          # paths. Copy them to the referenced path, which is deterministic.
+          if target=$(readlink "$workspace/$referenced_file"); then
+            rm "$workspace/$referenced_file"
+            cp -a "$target" "$workspace/$referenced_file"
+          fi
+        done
+        mapfile -t workspace_files_to_delete < <(find "$workspace" -type f -or -type l | sort -u | comm -23 - <(printf "$workspace/%s\n" "''${referenced_files[@]}" | sort -u))
+        for workspace_file_to_delete in "''${workspace_files_to_delete[@]}"; do
+          files_to_delete+=("$workspace_file_to_delete")
+        done
+        # We're running bazel in many different workspaces in a loop. Letting the
+        # daemon shut down on its own would leave several daemons alive at the
+        # same time, using up a lot of memory. Shut them down explicitly instead.
+        bazel --output_base="$workspaceOut" --output_user_root="$workspaceUserRoot" shutdown 2> /dev/null
+      done
+      for file_to_delete in "''${files_to_delete[@]}"; do
+        rm "$file_to_delete"
+      done
+      find . -type d -empty -delete
+    '';
+
+    sha256 = "1yirrzhhrsmbgd27fg709plhrhyi8pzwqv84yg72sd3799kswh9m";
+  };
+
+  buildAttrs = {
+    installPhase = ''
+      mkdir -p $out/bin/bazel-bin/src/scala/com/github/johnynek/bazel_deps
+
+      cp gen_maven_deps.sh $out/bin
+      wrapProgram "$out/bin/gen_maven_deps.sh" --set JAVA_HOME "${jre}" --prefix PATH : ${lib.makeBinPath [ jre ]}
+      cp bazel-bin/src/scala/com/github/johnynek/bazel_deps/parseproject_deploy.jar $out/bin/bazel-bin/src/scala/com/github/johnynek/bazel_deps
+    '';
+  };
+}
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-remote/default.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-remote/default.nix
new file mode 100644
index 000000000000..dbbc0d11ff1a
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/bazel-remote/default.nix
@@ -0,0 +1,81 @@
+{ buildBazelPackage
+, cacert
+, fetchFromGitHub
+, fetchpatch
+, git
+, go
+, stdenv
+}:
+
+buildBazelPackage rec {
+  name = "bazel-remote-${version}";
+  version = "2019-01-12";
+
+  src = fetchFromGitHub {
+    owner = "buchgr";
+    repo = "bazel-remote";
+    rev = "3f65b6ccf69e223950c77275a743d0d3a04a8583";
+    sha256 = "0fklrlylmc55yzhm3m1f211x5gmk7hpqjb7k5kml7n3gw3npbjda";
+  };
+
+  nativeBuildInputs = [ go git ];
+
+  bazelTarget = "//:bazel-remote";
+
+  fetchAttrs = {
+    preBuild = ''
+      patchShebangs .
+
+      # tell rules_go to use the Go binary found in the PATH
+      sed -e 's:go_register_toolchains():go_register_toolchains(go_version = "host"):g' -i WORKSPACE
+
+      # update gazelle to work around https://github.com/golang/go/issues/29850
+      sed -e 's,https://github.com/bazelbuild/bazel-gazelle/releases/download/0.15.0/bazel-gazelle-0.15.0.tar.gz,https://github.com/bazelbuild/bazel-gazelle/releases/download/0.16.0/bazel-gazelle-0.16.0.tar.gz,g' -i WORKSPACE
+      sed -e 's,6e875ab4b6bf64a38c352887760f21203ab054676d9c1b274963907e0768740d,7949fc6cc17b5b191103e97481cf8889217263acf52e00b560683413af204fcb,g' -i WORKSPACE
+
+      # tell rules_go to invoke GIT with custom CAINFO path
+      export GIT_SSL_CAINFO="${cacert}/etc/ssl/certs/ca-bundle.crt"
+    '';
+
+    preInstall = ''
+      # Remove the go_sdk (it's just a copy of the go derivation) and all
+      # references to it from the marker files. Bazel does not need to download
+      # this sdk because we have patched the WORKSPACE file to point to the one
+      # currently present in PATH. Without removing the go_sdk from the marker
+      # file, the hash of it will change anytime the Go derivation changes and
+      # that would lead to impurities in the marker files which would result in
+      # a different sha256 for the fetch phase.
+      rm -rf $bazelOut/external/{go_sdk,\@go_sdk.marker}
+      sed -e '/^FILE:@go_sdk.*/d' -i $bazelOut/external/\@*.marker
+
+      # Remove the gazelle tools, they contain go binaries that are built
+      # non-deterministically. As long as the gazelle version matches the tools
+      # should be equivalent.
+      rm -rf $bazelOut/external/{bazel_gazelle_go_repository_tools,\@bazel_gazelle_go_repository_tools.marker}
+      sed -e '/^FILE:@bazel_gazelle_go_repository_tools.*/d' -i $bazelOut/external/\@*.marker
+    '';
+
+    sha256 = "1wvyv3w5y6vj6qs6v5qyd356j1lxc3mf7n3j2pcib1bqmx3igw35";
+  };
+
+  buildAttrs = {
+    preBuild = ''
+      patchShebangs .
+
+      # tell rules_go to use the Go binary found in the PATH
+      sed -e 's:go_register_toolchains():go_register_toolchains(go_version = "host"):g' -i WORKSPACE
+    '';
+
+    installPhase = ''
+      install -Dm755 bazel-bin/*_pure_stripped/bazel-remote $out/bin/bazel-remote
+    '';
+  };
+
+  meta = with stdenv.lib; {
+    homepage = https://github.com/buchgr/bazel-remote;
+    description = "A remote HTTP/1.1 cache for Bazel.";
+    license = licenses.asl20;
+    maintainers = [ maintainers.uri-canva ];
+    platforms = platforms.darwin;
+  };
+}
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/default.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/default.nix
new file mode 100644
index 000000000000..2e8f806d53aa
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/default.nix
@@ -0,0 +1,25 @@
+{ stdenv, buildGoPackage, fetchFromGitHub }:
+
+buildGoPackage rec {
+  name = "bazel-buildtools-${version}";
+  version = "0.22.0";
+
+  goPackagePath = "github.com/bazelbuild/buildtools";
+
+  src = fetchFromGitHub {
+    owner = "bazelbuild";
+    repo = "buildtools";
+    rev = "55b64c3d2ddfb57f06477c1d94ef477419c96bd6";
+    sha256 = "0n6q8pkgy3vvmwyrxvkmjfbcxc31i31czg2bjdzq7awwrr4fdbwy";
+  };
+
+  goDeps = ./deps.nix;
+
+  meta = with stdenv.lib; {
+    description = "Tools for working with Google's bazel buildtool. Includes buildifier, buildozer, and unused_deps.";
+    homepage = https://github.com/bazelbuild/buildtools;
+    license = licenses.asl20;
+    maintainers = with maintainers; [ elasticdog uri-canva ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/deps.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/deps.nix
new file mode 100644
index 000000000000..d7cd02c12b8b
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/buildtools/deps.nix
@@ -0,0 +1,21 @@
+# This file was generated by https://github.com/kamilchm/go2nix v1.3.0
+[
+  {
+    goPackagePath = "github.com/golang/protobuf";
+    fetch = {
+      type = "git";
+      url = "https://github.com/golang/protobuf";
+      rev = "b5d812f8a3706043e23a9cd5babf2e5423744d30";
+      sha256 = "15am4s4646qy6iv0g3kkqq52rzykqjhm4bf08dk0fy2r58knpsyl";
+    };
+  }
+  {
+    goPackagePath = "github.com/google/skylark";
+    fetch = {
+      type = "git";
+      url = "https://github.com/google/skylark";
+      rev = "a5f7082aabed29c0e429c722292c66ec8ecf9591";
+      sha256 = "16vsa6ngsby27n6indj441r1glcdfgipjcwcb0rs6zl2dqlqr286";
+    };
+  }
+]
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/default.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/default.nix
new file mode 100644
index 000000000000..1e29e4b34f08
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/default.nix
@@ -0,0 +1,346 @@
+{ stdenv, callPackage, lib, fetchurl, fetchpatch, runCommand, makeWrapper
+, zip, unzip, bash, writeCBin, coreutils
+, which, python, perl, gawk, gnused, gnutar, gnugrep, gzip, findutils
+# Apple dependencies
+, cctools, clang, libcxx, CoreFoundation, CoreServices, Foundation
+# Allow to independently override the jdks used to build and run respectively
+, buildJdk, runJdk
+, buildJdkName
+, runtimeShell
+# Always assume all markers valid (don't redownload dependencies).
+# Also, don't clean up environment variables.
+, enableNixHacks ? false
+}:
+
+let
+  srcDeps = [
+    (fetchurl {
+      url = "https://github.com/google/desugar_jdk_libs/archive/915f566d1dc23bc5a8975320cd2ff71be108eb9c.zip";
+      sha256 = "0b926df7yxyyyiwm9cmdijy6kplf0sghm23sf163zh8wrk87wfi7";
+    })
+
+    (fetchurl {
+        url = "https://mirror.bazel.build/bazel_java_tools/java_tools_pkg-0.5.1.tar.gz";
+        sha256 = "1ld8m5cj9j0r474f56pixcfi0xvx3w7pzwahxngs8f6ns0yimz5w";
+    })
+  ];
+
+  distDir = runCommand "bazel-deps" {} ''
+    mkdir -p $out
+    for i in ${builtins.toString srcDeps}; do cp $i $out/$(stripHash $i); done
+  '';
+
+  defaultShellPath = lib.makeBinPath
+    # Keep this list conservative. For more exotic tools, prefer to use
+    # @rules_nixpkgs to pull in tools from the nix repository. Example:
+    #
+    # WORKSPACE:
+    #
+    #     nixpkgs_git_repository(
+    #         name = "nixpkgs",
+    #         revision = "def5124ec8367efdba95a99523dd06d918cb0ae8",
+    #     )
+    #
+    #     # This defines an external Bazel workspace.
+    #     nixpkgs_package(
+    #         name = "bison",
+    #         repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
+    #     )
+    #
+    # some/BUILD.bazel:
+    #
+    #     genrule(
+    #        ...
+    #        cmd = "$(location @bison//:bin/bison) -other -args",
+    #        tools = [
+    #            ...
+    #            "@bison//:bin/bison",
+    #        ],
+    #     )
+    #
+    [ bash coreutils findutils gawk gnugrep gnutar gnused gzip which unzip ];
+
+  # Java toolchain used for the build and tests
+  javaToolchain = "@bazel_tools//tools/jdk:toolchain_host${buildJdkName}";
+
+in
+stdenv.mkDerivation rec {
+
+  version = "0.24.0";
+
+  meta = with lib; {
+    homepage = "https://github.com/bazelbuild/bazel/";
+    description = "Build tool that builds code quickly and reliably";
+    license = licenses.asl20;
+    maintainers = [ maintainers.mboes ];
+    platforms = platforms.linux ++ platforms.darwin;
+  };
+
+  # Additional tests that check bazel’s functionality. Execute
+  #
+  #     nix-build . -A bazel.tests
+  #
+  # in the nixpkgs checkout root to exercise them locally.
+  passthru.tests = {
+    pythonBinPath = callPackage ./python-bin-path-test.nix {};
+    bashTools = callPackage ./bash-tools-test.nix {};
+  };
+
+  name = "bazel-${version}";
+
+  src = fetchurl {
+    url = "https://github.com/bazelbuild/bazel/releases/download/${version}/${name}-dist.zip";
+    sha256 = "11gsc00ghxqkbci8nrflkwq1lcvqawlgkaryj458b24si6bjl7b2";
+  };
+
+  # Necessary for the tests to pass on Darwin with sandbox enabled.
+  # Bazel starts a local server and needs to bind a local address.
+  __darwinAllowLocalNetworking = true;
+
+  sourceRoot = ".";
+
+  patches = [
+    ./python-stub-path-fix.patch
+  ] ++ lib.optional enableNixHacks ./nix-hacks.patch;
+
+  # Bazel expects several utils to be available in Bash even without PATH. Hence this hack.
+
+  customBash = writeCBin "bash" ''
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <unistd.h>
+
+    extern char **environ;
+
+    int main(int argc, char *argv[]) {
+      char *path = getenv("PATH");
+      char *pathToAppend = "${defaultShellPath}";
+      char *newPath;
+      if (path != NULL) {
+        int length = strlen(path) + 1 + strlen(pathToAppend) + 1;
+        newPath = malloc(length * sizeof(char));
+        snprintf(newPath, length, "%s:%s", path, pathToAppend);
+      } else {
+        newPath = pathToAppend;
+      }
+      setenv("PATH", newPath, 1);
+      execve("${bash}/bin/bash", argv, environ);
+      return 0;
+    }
+  '';
+
+  postPatch = let
+
+    darwinPatches = ''
+      # Disable Bazel's Xcode toolchain detection which would configure compilers
+      # and linkers from Xcode instead of from PATH
+      export BAZEL_USE_CPP_ONLY_TOOLCHAIN=1
+
+      # Explicitly configure gcov since we don't have it on Darwin, so autodetection fails
+      export GCOV=${coreutils}/bin/false
+
+      # Framework search paths aren't added by bintools hook
+      # https://github.com/NixOS/nixpkgs/pull/41914
+      export NIX_LDFLAGS="$NIX_LDFLAGS -F${CoreFoundation}/Library/Frameworks -F${CoreServices}/Library/Frameworks -F${Foundation}/Library/Frameworks"
+
+      # libcxx includes aren't added by libcxx hook
+      # https://github.com/NixOS/nixpkgs/pull/41589
+      export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -isystem ${libcxx}/include/c++/v1"
+
+      # 10.10 apple_sdk Foundation doesn't have type arguments on classes
+      # Remove this when we update apple_sdk
+      sed -i -e 's/<.*\*>//g' tools/osx/xcode_locator.m
+
+      # don't use system installed Xcode to run clang, use Nix clang instead
+      sed -i -e "s;/usr/bin/xcrun clang;${clang}/bin/clang $NIX_CFLAGS_COMPILE $NIX_LDFLAGS -framework CoreFoundation;g" \
+        scripts/bootstrap/compile.sh \
+        src/tools/xcode/realpath/BUILD \
+        src/tools/xcode/stdredirect/BUILD \
+        tools/osx/BUILD
+
+      # clang installed from Xcode has a compatibility wrapper that forwards
+      # invocations of gcc to clang, but vanilla clang doesn't
+      sed -i -e 's;_find_generic(repository_ctx, "gcc", "CC", overriden_tools);_find_generic(repository_ctx, "clang", "CC", overriden_tools);g' tools/cpp/unix_cc_configure.bzl
+
+      sed -i -e 's;/usr/bin/libtool;${cctools}/bin/libtool;g' tools/cpp/unix_cc_configure.bzl
+      wrappers=( tools/cpp/osx_cc_wrapper.sh tools/cpp/osx_cc_wrapper.sh.tpl )
+      for wrapper in "''${wrappers[@]}"; do
+        sed -i -e "s,/usr/bin/install_name_tool,${cctools}/bin/install_name_tool,g" $wrapper
+      done
+    '';
+
+    genericPatches = ''
+      # Substitute python's stub shebang to plain python path. (see TODO add pr URL)
+      # See also `postFixup` where python is added to $out/nix-support
+      substituteInPlace src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt\
+          --replace "/usr/bin/env python" "${python}/bin/python" \
+          --replace "NIX_STORE_PYTHON_PATH" "${python}/bin/python" \
+
+      # md5sum is part of coreutils
+      sed -i 's|/sbin/md5|md5sum|' \
+        src/BUILD
+
+      # substituteInPlace is rather slow, so prefilter the files with grep
+      grep -rlZ /bin src/main/java/com/google/devtools | while IFS="" read -r -d "" path; do
+        # If you add more replacements here, you must change the grep above!
+        # Only files containing /bin are taken into account.
+        substituteInPlace "$path" \
+          --replace /bin/bash ${customBash}/bin/bash \
+          --replace /usr/bin/env ${coreutils}/bin/env \
+          --replace /bin/true ${coreutils}/bin/true
+      done
+
+      # Fixup scripts that generate scripts. Not fixed up by patchShebangs below.
+      substituteInPlace scripts/bootstrap/compile.sh \
+          --replace /bin/sh ${customBash}/bin/bash
+
+      # add nix environment vars to .bazelrc
+      cat >> .bazelrc <<EOF
+      build --experimental_distdir=${distDir}
+      fetch --experimental_distdir=${distDir}
+      build --copt="$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --copt="/g')"
+      build --host_copt="$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --host_copt="/g')"
+      build --linkopt="-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --linkopt="-Wl,/g')"
+      build --host_linkopt="-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --host_linkopt="-Wl,/g')"
+      build --host_javabase='@local_jdk//:jdk'
+      build --host_java_toolchain='${javaToolchain}'
+      EOF
+
+      # add the same environment vars to compile.sh
+      sed -e "/\$command \\\\$/a --copt=\"$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --copt=\"/g')\" \\\\" \
+          -e "/\$command \\\\$/a --host_copt=\"$(echo $NIX_CFLAGS_COMPILE | sed -e 's/ /" --host_copt=\"/g')\" \\\\" \
+          -e "/\$command \\\\$/a --linkopt=\"-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --linkopt=\"-Wl,/g')\" \\\\" \
+          -e "/\$command \\\\$/a --host_linkopt=\"-Wl,$(echo $NIX_LDFLAGS | sed -e 's/ /" --host_linkopt=\"-Wl,/g')\" \\\\" \
+          -e "/\$command \\\\$/a --host_javabase='@local_jdk//:jdk' \\\\" \
+          -e "/\$command \\\\$/a --host_java_toolchain='${javaToolchain}' \\\\" \
+          -i scripts/bootstrap/compile.sh
+
+      # --experimental_strict_action_env (which will soon become the
+      # default, see bazelbuild/bazel#2574) hardcodes the default
+      # action environment to a value that on NixOS at least is bogus.
+      # So we hardcode it to something useful.
+      substituteInPlace \
+        src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java \
+        --replace /bin:/usr/bin ${defaultShellPath}
+
+      # This is necessary to avoid:
+      # "error: no visible @interface for 'NSDictionary' declares the selector
+      # 'initWithContentsOfURL:error:'"
+      # This can be removed when the apple_sdk is upgraded beyond 10.13+
+      sed -i '/initWithContentsOfURL:versionPlistUrl/ {
+        N
+        s/error:nil\];/\];/
+      }' tools/osx/xcode_locator.m
+
+      # append the PATH with defaultShellPath in tools/bash/runfiles/runfiles.bash
+      echo "PATH=\$PATH:${defaultShellPath}" >> runfiles.bash.tmp
+      cat tools/bash/runfiles/runfiles.bash >> runfiles.bash.tmp
+      mv runfiles.bash.tmp tools/bash/runfiles/runfiles.bash
+
+      patchShebangs .
+    '';
+    in lib.optionalString stdenv.hostPlatform.isDarwin darwinPatches
+     + genericPatches;
+
+  buildInputs = [
+    buildJdk
+  ];
+
+  # when a command can’t be found in a bazel build, you might also
+  # need to add it to `defaultShellPath`.
+  nativeBuildInputs = [
+    zip
+    python
+    unzip
+    makeWrapper
+    which
+    customBash
+  ] ++ lib.optionals (stdenv.isDarwin) [ cctools clang libcxx CoreFoundation CoreServices Foundation ];
+
+  # Bazel makes extensive use of symlinks in the WORKSPACE.
+  # This causes problems with infinite symlinks if the build output is in the same location as the
+  # Bazel WORKSPACE. This is why before executing the build, the source code is moved into a
+  # subdirectory.
+  # Failing to do this causes "infinite symlink expansion detected"
+  preBuildPhases = ["preBuildPhase"];
+  preBuildPhase = ''
+    mkdir bazel_src
+    shopt -s dotglob extglob
+    mv !(bazel_src) bazel_src
+  '';
+
+  buildPhase = ''
+    # Increasing memory during compilation might be necessary.
+    # export BAZEL_JAVAC_OPTS="-J-Xmx2g -J-Xms200m"
+    ./bazel_src/compile.sh
+    ./bazel_src/scripts/generate_bash_completion.sh \
+        --bazel=./bazel_src/output/bazel \
+        --output=./bazel_src/output/bazel-complete.bash \
+        --prepend=./bazel_src/scripts/bazel-complete-header.bash \
+        --prepend=./bazel_src/scripts/bazel-complete-template.bash
+  '';
+
+  installPhase = ''
+    mkdir -p $out/bin
+
+    # official wrapper scripts that searches for $WORKSPACE_ROOT/tools/bazel
+    # if it can’t find something in tools, it calls $out/bin/bazel-real
+    cp ./bazel_src/scripts/packages/bazel.sh $out/bin/bazel
+    mv ./bazel_src/output/bazel $out/bin/bazel-real
+
+    wrapProgram "$out/bin/bazel" --add-flags --server_javabase="${runJdk}"
+
+    # shell completion files
+    mkdir -p $out/share/bash-completion/completions $out/share/zsh/site-functions
+    mv ./bazel_src/output/bazel-complete.bash $out/share/bash-completion/completions/bazel
+    cp ./bazel_src/scripts/zsh_completion/_bazel $out/share/zsh/site-functions/
+  '';
+
+  doInstallCheck = true;
+  installCheckPhase = ''
+    export TEST_TMPDIR=$(pwd)
+
+    hello_test () {
+      $out/bin/bazel test \
+        --test_output=errors \
+        --java_toolchain='${javaToolchain}' \
+        examples/cpp:hello-success_test \
+        examples/java-native/src/test/java/com/example/myproject:hello
+    }
+
+    cd ./bazel_src
+
+    # test whether $WORKSPACE_ROOT/tools/bazel works
+
+    mkdir -p tools
+    cat > tools/bazel <<"EOF"
+    #!${runtimeShell} -e
+    exit 1
+    EOF
+    chmod +x tools/bazel
+
+    # first call should fail if tools/bazel is used
+    ! hello_test
+
+    cat > tools/bazel <<"EOF"
+    #!${runtimeShell} -e
+    exec "$BAZEL_REAL" "$@"
+    EOF
+
+    # second call succeeds because it defers to $out/bin/bazel-real
+    hello_test
+  '';
+
+  # Save paths to hardcoded dependencies so Nix can detect them.
+  postFixup = ''
+    mkdir -p $out/nix-support
+    echo "${customBash} ${defaultShellPath}" >> $out/nix-support/depends
+    # The templates get tar’d up into a .jar,
+    # so nix can’t detect python is needed in the runtime closure
+    echo "${python}" >> $out/nix-support/depends
+  '';
+
+  dontStrip = true;
+  dontPatchELF = true;
+}
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks-0.4.patch b/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks-0.4.patch
new file mode 100644
index 000000000000..563fe635e6b0
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks-0.4.patch
@@ -0,0 +1,51 @@
+diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
+index eafa09fb5..d2d5e40e8 100644
+--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
++++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
+@@ -287,21 +287,8 @@ public final class RepositoryDelegatorFunction implements SkyFunction {
+           markerData.put(key, value);
+         }
+       }
+-      boolean result = false;
+-      if (markerRuleKey.equals(ruleKey)) {
+-        result = handler.verifyMarkerData(rule, markerData, env);
+-        if (env.valuesMissing()) {
+-          return null;
+-        }
+-      }
+ 
+-      if (result) {
+-        return new Fingerprint().addString(content).digestAndReset();
+-      } else {
+-        // So that we are in a consistent state if something happens while fetching the repository
+-        markerPath.delete();
+-        return null;
+-      }
++      return new Fingerprint().addString(content).digestAndReset();
+ 
+     } catch (IOException e) {
+       throw new RepositoryFunctionException(e, Transience.TRANSIENT);
+diff --git a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
+index a7ebc8f7a..40f2049fa 100644
+--- a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
++++ b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
+@@ -129,7 +129,6 @@ public class JavaSubprocessFactory implements SubprocessFactory {
+     ProcessBuilder builder = new ProcessBuilder();
+     builder.command(params.getArgv());
+     if (params.getEnv() != null) {
+-      builder.environment().clear();
+       builder.environment().putAll(params.getEnv());
+     }
+ 
+diff --git a/src/main/java/com/google/devtools/build/lib/worker/Worker.java b/src/main/java/com/google/devtools/build/lib/worker/Worker.java
+index 0268d1b2b..637364657 100644
+--- a/src/main/java/com/google/devtools/build/lib/worker/Worker.java
++++ b/src/main/java/com/google/devtools/build/lib/worker/Worker.java
+@@ -77,7 +77,6 @@ class Worker {
+         new ProcessBuilder(command)
+             .directory(workDir.getPathFile())
+             .redirectError(Redirect.appendTo(logFile.getPathFile()));
+-    processBuilder.environment().clear();
+     processBuilder.environment().putAll(workerKey.getEnv());
+ 
+     this.process = processBuilder.start();
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks.patch b/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks.patch
new file mode 100644
index 000000000000..da3f6248f220
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/nix-hacks.patch
@@ -0,0 +1,37 @@
+diff -Naur a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
+--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java	1980-01-01 00:00:00.000000000 -0500
++++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java	2018-01-18 08:17:22.420459162 -0500
+@@ -287,21 +287,8 @@
+           markerData.put(key, value);
+         }
+       }
+-      boolean result = false;
+-      if (markerRuleKey.equals(ruleKey)) {
+-        result = handler.verifyMarkerData(rule, markerData, env);
+-        if (env.valuesMissing()) {
+-          return null;
+-        }
+-      }
+ 
+-      if (result) {
+-        return new Fingerprint().addString(content).digestAndReset();
+-      } else {
+-        // So that we are in a consistent state if something happens while fetching the repository
+-        markerPath.delete();
+-        return null;
+-      }
++      return new Fingerprint().addString(content).digestAndReset();
+ 
+     } catch (IOException e) {
+       throw new RepositoryFunctionException(e, Transience.TRANSIENT);
+diff -Naur a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java
+--- a/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java	1980-01-01 00:00:00.000000000 -0500
++++ b/src/main/java/com/google/devtools/build/lib/shell/JavaSubprocessFactory.java	2018-01-18 08:17:53.274877980 -0500
+@@ -129,7 +129,6 @@
+     ProcessBuilder builder = new ProcessBuilder();
+     builder.command(params.getArgv());
+     if (params.getEnv() != null) {
+-      builder.environment().clear();
+       builder.environment().putAll(params.getEnv());
+     }
+ 
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/python-bin-path-test.nix b/nixpkgs/pkgs/development/tools/build-managers/bazel/python-bin-path-test.nix
new file mode 100644
index 000000000000..54ae154a6207
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/python-bin-path-test.nix
@@ -0,0 +1,57 @@
+{ stdenv, lib, writeText, runCommandCC, bazel }:
+
+let
+  WORKSPACE = writeText "WORKSPACE" ''
+    workspace(name = "our_workspace")
+  '';
+
+  pythonLib = writeText "lib.py" ''
+    def foo():
+      return 43
+  '';
+
+  pythonBin = writeText "bin.py" ''
+    from lib import foo
+
+    assert foo() == 43
+  '';
+
+  pythonBUILD = writeText "BUILD" ''
+    py_library(
+      name = "lib",
+      srcs = [ "lib.py" ],
+    )
+
+    py_test(
+      name = "bin",
+      srcs = [ "bin.py" ],
+      deps = [ ":lib" ],
+    )
+  '';
+
+  runLocal = name: script: runCommandCC name { preferLocalBuild = true; } script;
+
+  workspaceDir = runLocal "our_workspace" ''
+    mkdir $out
+    cp ${WORKSPACE} $out/WORKSPACE
+    mkdir $out/python
+    cp ${pythonLib} $out/python/lib.py
+    cp ${pythonBin} $out/python/bin.py
+    cp ${pythonBUILD} $out/python/BUILD.bazel
+  '';
+
+  testBazel = runLocal "bazel-test-builtin-rules" ''
+    export HOME=$(mktemp -d)
+    # Note https://github.com/bazelbuild/bazel/issues/5763#issuecomment-456374609
+    # about why to create a subdir for the workspace.
+    cp -r ${workspaceDir} wd && chmod u+w wd && cd wd
+    ${bazel}/bin/bazel \
+      test \
+        --test_output=errors \
+        --host_javabase='@local_jdk//:jdk' \
+        //...
+
+    touch $out
+  '';
+
+in testBazel
diff --git a/nixpkgs/pkgs/development/tools/build-managers/bazel/python-stub-path-fix.patch b/nixpkgs/pkgs/development/tools/build-managers/bazel/python-stub-path-fix.patch
new file mode 100644
index 000000000000..cbc4192d2d9b
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/build-managers/bazel/python-stub-path-fix.patch
@@ -0,0 +1,13 @@
+diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt
+index dac21c9a83..69b11c283f 100644
+--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt
++++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt
+@@ -67,7 +67,7 @@ def FindPythonBinary(module_space):
+     return os.path.join(module_space, PYTHON_BINARY)
+   else:
+     # Case 4: Path has to be looked up in the search path.
+-    return SearchPath(PYTHON_BINARY)
++    return "NIX_STORE_PYTHON_PATH"
+ 
+ def CreatePythonPathEntries(python_imports, module_space):
+   parts = python_imports.split(':');