From 0a2bee307b20411f5b0dda0c662b1f9bb9e0e131 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 20 Jul 2015 04:30:16 +0200 Subject: [PATCH] Make a builtin builder This ensures that 1) the derivation doesn't change when Nix changes; 2) the derivation closure doesn't contain Nix and its dependencies; 3) we don't have to rely on ugly chroot hacks. --- corepkgs/config.nix.in | 1 - corepkgs/fetchurl.nix | 15 +------------- src/libexpr/local.mk | 2 +- src/libstore/build.cc | 28 ++++++++++++++++++++++++--- src/libstore/builtins.cc | 24 +++++++++++++++++++++++ src/libstore/builtins.hh | 9 +++++++++ src/{libexpr => libstore}/download.cc | 0 src/{libexpr => libstore}/download.hh | 0 src/libstore/local.mk | 2 +- 9 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 src/libstore/builtins.cc create mode 100644 src/libstore/builtins.hh rename src/{libexpr => libstore}/download.cc (100%) rename src/{libexpr => libstore}/download.hh (100%) diff --git a/corepkgs/config.nix.in b/corepkgs/config.nix.in index 8918f4ddd..90e8edbea 100644 --- a/corepkgs/config.nix.in +++ b/corepkgs/config.nix.in @@ -12,7 +12,6 @@ in rec { tar = "@tar@"; tarFlags = "@tarFlags@"; tr = "@tr@"; - curl = "@curl@"; nixBinDir = fromEnv "NIX_BIN_DIR" "@bindir@"; nixPrefix = "@prefix@"; diff --git a/corepkgs/fetchurl.nix b/corepkgs/fetchurl.nix index 1ce88593c..64d1f121f 100644 --- a/corepkgs/fetchurl.nix +++ b/corepkgs/fetchurl.nix @@ -5,20 +5,9 @@ with import ; assert (outputHash != "" && outputHashAlgo != "") || md5 != "" || sha1 != "" || sha256 != ""; -let - - builder = builtins.toFile "fetchurl.sh" - ('' - echo "downloading $url into $out" - ${curl} --fail --location --max-redirs 20 --insecure "$url" > "$out" - '' + (if executable then "${coreutils}/chmod +x $out" else "")); - -in - derivation { name = baseNameOf (toString url); - builder = shell; - args = [ "-e" builder ]; + builder = "builtin:fetchurl"; # New-style output content requirements. outputHashAlgo = if outputHashAlgo != "" then outputHashAlgo else @@ -39,6 +28,4 @@ derivation { # by definition pure. "http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy" ]; - - inherit chrootDeps; } diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 35e84980a..4c1f4de19 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -8,7 +8,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc libexpr_LIBS = libutil libstore libformat -libexpr_LDFLAGS = -ldl -lcurl +libexpr_LDFLAGS = -ldl # The dependency on libgc must be propagated (i.e. meaning that # programs/libraries that use libexpr must explicitly pass -lgc), diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 61677d1eb..46d2841dc 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -8,6 +8,7 @@ #include "util.hh" #include "archive.hh" #include "affinity.hh" +#include "builtins.hh" #include #include @@ -1269,6 +1270,12 @@ bool substitutesAllowed(const BasicDerivation & drv) } +static bool isBuiltin(const BasicDerivation & drv) +{ + return string(drv.builder, 0, 8) == "builtin:"; +} + + void DerivationGoal::tryToBuild() { trace("trying to build"); @@ -2139,7 +2146,7 @@ void DerivationGoal::startBuilder() #endif { ProcessOptions options; - options.allowVfork = !buildUser.enabled(); + options.allowVfork = !buildUser.enabled() && !isBuiltin(*drv); pid = startProcess([&]() { runChild(); }, options); @@ -2386,7 +2393,9 @@ void DerivationGoal::runChild() const char *builder = "invalid"; string sandboxProfile; - if (useChroot && SANDBOX_ENABLED) { + if (isBuiltin(*drv)) + ; + else if (useChroot && SANDBOX_ENABLED) { /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */ PathSet ancestry; @@ -2413,7 +2422,6 @@ void DerivationGoal::runChild() for (auto & i : inputPaths) dirsInChroot[i] = i; - /* TODO: we should factor out the policy cleanly, so we don't have to repeat the constants every time... */ sandboxProfile += "(version 1)\n"; @@ -2517,6 +2525,20 @@ void DerivationGoal::runChild() } /* Execute the program. This should not return. */ + if (isBuiltin(*drv)) { + try { + logType = ltFlat; + if (drv->builder == "builtin:fetchurl") + builtinFetchurl(*drv); + else + throw Error(format("unsupported builtin function ‘%1%’") % string(drv->builder, 8)); + _exit(0); + } catch (std::exception & e) { + writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n"); + _exit(1); + } + } + execve(builder, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data()); throw SysError(format("executing ‘%1%’") % drv->builder); diff --git a/src/libstore/builtins.cc b/src/libstore/builtins.cc new file mode 100644 index 000000000..97d6cb943 --- /dev/null +++ b/src/libstore/builtins.cc @@ -0,0 +1,24 @@ +#include "builtins.hh" +#include "download.hh" + +namespace nix { + +void builtinFetchurl(const BasicDerivation & drv) +{ + auto url = drv.env.find("url"); + if (url == drv.env.end()) throw Error("attribute ‘url’ missing"); + printMsg(lvlInfo, format("downloading ‘%1%’...") % url->second); + auto data = downloadFile(url->second); // FIXME: show progress + + auto out = drv.env.find("out"); + if (out == drv.env.end()) throw Error("attribute ‘url’ missing"); + writeFile(out->second, data.data); + + auto executable = drv.env.find("out"); + if (executable != drv.env.end() && executable->second == "1") { + if (chmod(out->second.c_str(), 0755) == -1) + throw SysError(format("making ‘%1%’ executable") % out->second); + } +} + +} diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh new file mode 100644 index 000000000..4b2431aa0 --- /dev/null +++ b/src/libstore/builtins.hh @@ -0,0 +1,9 @@ +#pragma once + +#include "derivations.hh" + +namespace nix { + +void builtinFetchurl(const BasicDerivation & drv); + +} diff --git a/src/libexpr/download.cc b/src/libstore/download.cc similarity index 100% rename from src/libexpr/download.cc rename to src/libstore/download.cc diff --git a/src/libexpr/download.hh b/src/libstore/download.hh similarity index 100% rename from src/libexpr/download.hh rename to src/libstore/download.hh diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 771c06753..bf5c256c9 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -8,7 +8,7 @@ libstore_SOURCES := $(wildcard $(d)/*.cc) libstore_LIBS = libutil libformat -libstore_LDFLAGS = -lsqlite3 -lbz2 +libstore_LDFLAGS = -lsqlite3 -lbz2 -lcurl ifeq ($(OS), SunOS) libstore_LDFLAGS += -lsocket