tvl-depot/third_party/nix/default.nix
Griffin Smith c5f3b12f04 feat(tvix): Support systemd socket activation
When the nix daemon starts up, first check (using sd_listen_fds) whether
we have been systemd socket-activated. If so, instead of passing the nix
daemon socket path to grpc, start a manual accept(2) loop, passing the
client file descriptors to grpc via AddInsecureChannelFromFd. There's an
open grpc issue at https://github.com/grpc/grpc/issues/19133 for
building support into grpc to do this automatically, but as of right now
this appears to be the only way to make this happen.

Making this happen, by the way, was a bit of a journey - at one point I
attempted to ServerBuilder's experimental AddExternalConnectionAcceptor
API, and that didn't work either - it appears that the final missing
piece to getting this working was explicitly fcntl(2)ing the client file
descriptors to set O_NONBLOCK before passing them into gRPC. With that
set, this all works inside of the test vm.

Fixes: b/56
Change-Id: I5d2ab2b5b02eb570249b30a9674e115c61b0ab0e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1882
Reviewed-by: kanepyork <rikingcoding@gmail.com>
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
2020-09-01 01:07:11 +00:00

177 lines
4.7 KiB
Nix

args@{
pkgs ? (import ../.. {}).third_party
, lib
, buildType ? "release"
, depotPath ? ../..
, ...
}:
let
aws-s3-cpp = pkgs.aws-sdk-cpp.override {
apis = ["s3" "transfer"];
customMemoryManagement = false;
};
src = ./.;
# 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 + "/src/proto"}
mkdir -p $out/libproto
${pkgs.protobuf}/bin/protoc -I=$PROTO_SRCS \
--cpp_out=$out/libproto \
--plugin=protoc-gen-grpc=${pkgs.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.llvmPackages.libcxxStdenv.mkDerivation {
pname = "tvix";
version = "2.3.4";
inherit src;
nativeBuildInputs = with pkgs; [
bison
clang-tools
cmake
libxml2
libxslt
pkgconfig
(import ./clangd.nix pkgs)
];
# TODO(tazjin): Some of these might only be required for native inputs
buildInputs = with pkgs; [
abseil_cpp
aws-s3-cpp
brotli
bzip2
c-ares
curl
editline
flex
glog
grpc
libseccomp
libsodium
systemd.lib.dev
openssl
protobuf
sqlite
xz
];
doCheck = false;
doInstallCheck = true;
installCheckInputs = with pkgs; [
fd
gtest
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
# Ensure formatting is coherent, but do this after the rest of the
# tests run so that developers get all the useful feedback
fd . $src -e hh -e cc | xargs clang-format --dry-run --Werror
'';
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.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 depotPath}/third_party"
export NIX_TEST_VAR=foo
'';
});
test-vm = import ./test-vm.nix args;
};
})