about summary refs log tree commit diff
path: root/third_party/nix/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/default.nix')
-rw-r--r--third_party/nix/default.nix270
1 files changed, 270 insertions, 0 deletions
diff --git a/third_party/nix/default.nix b/third_party/nix/default.nix
new file mode 100644
index 0000000000..ad50ac6b7f
--- /dev/null
+++ b/third_party/nix/default.nix
@@ -0,0 +1,270 @@
+args@{ depot ? (import ../.. { })
+, pkgs ? depot.third_party.nixpkgs
+, lib
+, buildType ? "release"
+, ...
+}:
+
+let
+  # Override some external dependencies for C++17 & clang compat.
+  abseil-cpp = pkgs.abseil-cpp.override {
+    stdenv = pkgs.fullLlvm11Stdenv;
+    cxxStandard = "17";
+  };
+
+  protobuf = pkgs.callPackage (pkgs.path + "/pkgs/development/libraries/protobuf/generic-v3.nix") {
+    version = "3.12.2";
+    sha256 = "1lp368aa206vpic9fmax4k6llnmf28plfvkkm4vqhgphmjqykvl2";
+    stdenv = pkgs.fullLlvm11Stdenv;
+    buildPackages = {
+      inherit (pkgs.buildPackages) which;
+      stdenv = pkgs.buildPackages.fullLlvm11Stdenv;
+    };
+  };
+
+  re2 = pkgs.re2.override {
+    stdenv = pkgs.fullLlvm11Stdenv;
+  };
+
+  grpc = (pkgs.grpc.override {
+    inherit abseil-cpp protobuf re2;
+    stdenv = pkgs.fullLlvm11Stdenv;
+  }).overrideAttrs (orig: rec {
+    cmakeFlags = orig.cmakeFlags ++ [
+      "-DCMAKE_CXX_STANDARD_REQUIRED=ON"
+      "-DCMAKE_CXX_STANDARD=17"
+    ];
+  });
+
+  aws-s3-cpp = pkgs.aws-sdk-cpp.override {
+    apis = [ "s3" "transfer" ];
+    customMemoryManagement = false;
+  };
+
+  src =
+    let
+      srcDir = ./.;
+      # create relative paths for all the sources we are filtering
+      asRelative = path:
+        let
+          srcS = toString srcDir;
+          pathS = toString path;
+        in
+        if ! lib.hasPrefix srcS pathS then
+          throw "Path is outside of the working directory."
+        else
+          lib.removePrefix srcS pathS;
+
+    in
+    builtins.filterSource
+      (path: type:
+        # Strip out .nix files that are in the root of the repository.  Changing
+        # the expression of tvix shouldn't cause a rebuild of tvix unless really
+        # required.
+        !(dirOf (asRelative path) == "/" && lib.hasSuffix ".nix" path) &&
+
+        # remove the proto files from the repo as those are compiled separately
+        !(lib.hasPrefix "src/proto" (asRelative path)) &&
+
+        # ignore result symlinks
+        !(type == "symlink" && lib.hasPrefix "result" (baseNameOf path))
+      )
+      srcDir;
+
+  # Proto generation in CMake is theoretically possible, but that is
+  # very theoretical - this does it in Nix instead.
+  protoSrcs = pkgs.runCommand "nix-proto-srcs" { } ''
+    export PROTO_SRCS=${./src/proto}
+    mkdir -p $out/libproto
+    ${protobuf}/bin/protoc -I=$PROTO_SRCS \
+      --cpp_out=$out/libproto \
+      --plugin=protoc-gen-grpc=${grpc}/bin/grpc_cpp_plugin \
+        --grpc_out=$out/libproto \
+        $PROTO_SRCS/*.proto
+  '';
+
+  # Derivation for busybox that just has the `busybox` binary in bin/, not all
+  # the symlinks, so cmake can find it
+  busybox = pkgs.runCommand "busybox" { } ''
+    mkdir -p $out/bin
+    cp ${pkgs.busybox}/bin/busybox $out/bin
+  '';
+
+in
+lib.fix (self: pkgs.fullLlvm11Stdenv.mkDerivation {
+  pname = "tvix";
+  version = "2.3.4";
+  inherit src;
+
+  nativeBuildInputs = with pkgs; [
+    bison
+    clang-tools_11
+    cmake
+    libxml2
+    libxslt
+    pkgconfig
+    (import ./clangd.nix pkgs)
+  ];
+
+  # TODO(tazjin): Some of these might only be required for native inputs
+  buildInputs = (with pkgs; [
+    aws-s3-cpp
+    brotli
+    bzip2
+    c-ares
+    curl
+    editline
+    flex
+    glog
+    libseccomp
+    libsodium
+    openssl
+    sqlite
+    systemd.dev
+    xz
+
+    # dependencies with custom overrides
+    abseil-cpp
+    grpc
+    protobuf
+  ]);
+
+  doCheck = false;
+  doInstallCheck = true;
+
+  # Preserve debug symbols, for core dumps + other live debugging
+  dontStrip = true;
+
+  installCheckInputs = with depot.third_party; [
+    gtest
+    pkgs.fd
+    rapidcheck
+  ];
+
+  propagatedBuildInputs = with pkgs; [
+    boost
+  ];
+
+  configurePhase = ''
+    mkdir build
+    cd build
+    cmake .. \
+      -DCMAKE_INSTALL_PREFIX=$out \
+      -DCMAKE_BUILD_TYPE=RelWithDebInfo \
+      -DCMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY=OFF \
+      -DCMAKE_FIND_USE_PACKAGE_REGISTRY=OFF \
+      -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON
+  '';
+
+  installCheckPhase = ''
+    export NIX_DATA_DIR=$out/share
+    export NIX_TEST_VAR=foo # this is required by a language test
+    make test
+  '';
+
+  preBuild = ''
+    if [ -n "$NIX_BUILD_CORES" ]; then
+      makeFlags+="-j$NIX_BUILD_CORES "
+      makeFlags+="-l$NIX_BUILD_CORES "
+    fi
+  '';
+
+  # Forward the location of the generated Protobuf / gRPC files so
+  # that they can be included by CMake.
+  NIX_PROTO_SRCS = protoSrcs;
+
+  # Work around broken system header include flags in the cxx toolchain.
+  LIBCXX_INCLUDE = "${pkgs.llvmPackages_11.libcxx}/include/c++/v1";
+
+  SANDBOX_SHELL = "${pkgs.busybox}/bin/busybox";
+
+  # Install the various symlinks to the Nix binary which users expect
+  # to exist.
+  postInstall = ''
+    ln -s $out/bin/nix $out/bin/nix-build
+    ln -s $out/bin/nix $out/bin/nix-channel
+    ln -s $out/bin/nix $out/bin/nix-collect-garbage
+    ln -s $out/bin/nix $out/bin/nix-copy-closure
+    ln -s $out/bin/nix $out/bin/nix-env
+    ln -s $out/bin/nix $out/bin/nix-hash
+    ln -s $out/bin/nix $out/bin/nix-instantiate
+    ln -s $out/bin/nix $out/bin/nix-prefetch-url
+    ln -s $out/bin/nix $out/bin/nix-shell
+    ln -s $out/bin/nix $out/bin/nix-store
+
+    mkdir -p $out/libexec/nix
+    ln -s $out/bin/nix $out/libexec/nix/build-remote
+
+    # configuration variables for templated files
+    export storedir=/nix/store
+    export localstatedir=/nix/var
+    export bindir=$out/bin
+
+    mkdir -p $out/lib/systemd/system
+    substituteAll \
+      ${src}/misc/systemd/nix-daemon.service.in \
+      $out/lib/systemd/system/nix-daemon.service
+    substituteAll \
+      ${src}/misc/systemd/nix-daemon.socket.in \
+      $out/lib/systemd/system/nix-daemon.socket
+
+    mkdir -p $out/etc/profile.d
+    substituteAll \
+      ${src}/scripts/nix-profile.sh.in $out/etc/profile.d/nix.sh
+    substituteAll \
+      ${src}/scripts/nix-profile-daemon.sh.in $out/etc/profile.d/nix-daemon.sh
+  '';
+
+  # TODO(tazjin): integration test setup?
+  # TODO(tazjin): docs generation?
+
+  passthru = {
+    build-shell = self.overrideAttrs (up: rec {
+      run_clang_tidy = pkgs.writeShellScriptBin "run-clang-tidy" ''
+        test -f compile_commands.json || (echo "run from build output directory"; exit 1) || exit 1
+        ${pkgs.jq}/bin/jq < compile_commands.json -r 'map(.file)|.[]' | grep -v '/generated/' | ${pkgs.parallel}/bin/parallel ${pkgs.clang-tools}/bin/clang-tidy -p compile_commands.json $@
+      '';
+
+      installCheckInputs = up.installCheckInputs ++ [ run_clang_tidy ];
+
+      shellHook = ''
+        export NIX_DATA_DIR="${toString depot.path}/third_party"
+        export NIX_TEST_VAR=foo
+      '';
+    });
+
+    # Ensure formatting is coherent,
+    # but do this in parallel to the main build because:
+    #  - (in favor of building this after tvix)
+    #    tests run so that developers get all the useful feedback
+    #  - (in favor of building this before tvix)
+    #    if the formatting is broken, and this build was submitted to CI
+    #    it would be a good idea to get this feedback rather sooner than later
+    #  - we don't want builds to differ between local and CI runs
+    checkfmt = pkgs.fullLlvm11Stdenv.mkDerivation {
+      name = "tvix-checkfmt";
+      inherit src;
+      nativeBuildInputs = with pkgs; [ clang-tools_11 fd ];
+      SANDBOX_SHELL = "${pkgs.busybox}/bin/busybox";
+
+      buildPhase = ''
+        set -e
+        runHook preBuild
+        fd . $src -e hh -e cc | xargs clang-format --dry-run --Werror
+        runHook postBuild
+      '';
+
+      installPhase = ''
+        runHook preInstall
+        touch $out
+        runHook postInstall
+      '';
+    };
+
+    test-vm = import ./test-vm.nix args;
+  };
+
+  meta.ci.targets = [
+    "checkfmt"
+  ];
+})