Make <nix/buildenv.nix> a builtin builder
This avoids sandbox annoyances.
This commit is contained in:
		
							parent
							
								
									9d40787938
								
							
						
					
					
						commit
						668ac3ea2c
					
				
					 7 changed files with 69 additions and 94 deletions
				
			
		
							
								
								
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -13,9 +13,6 @@ perl/Makefile.config
 | 
			
		|||
 | 
			
		||||
/corepkgs/config.nix
 | 
			
		||||
 | 
			
		||||
# /corepkgs/buildenv/
 | 
			
		||||
/corepkgs/buildenv/builder.pl
 | 
			
		||||
 | 
			
		||||
# /corepkgs/channels/
 | 
			
		||||
/corepkgs/channels/unpack.sh
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -72,9 +69,6 @@ perl/Makefile.config
 | 
			
		|||
# /src/nix-channel/
 | 
			
		||||
/src/nix-channel/nix-channel
 | 
			
		||||
 | 
			
		||||
# /src/buildenv/
 | 
			
		||||
/src/buildenv/buildenv
 | 
			
		||||
 | 
			
		||||
# /src/nix-build/
 | 
			
		||||
/src/nix-build/nix-build
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,7 +12,6 @@ makefiles = \
 | 
			
		|||
  src/nix-collect-garbage/local.mk \
 | 
			
		||||
  src/nix-copy-closure/local.mk \
 | 
			
		||||
  src/nix-prefetch-url/local.mk \
 | 
			
		||||
  src/buildenv/local.mk \
 | 
			
		||||
  src/resolve-system-dependencies/local.mk \
 | 
			
		||||
  src/nix-channel/local.mk \
 | 
			
		||||
  src/nix-build/local.mk \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,9 @@
 | 
			
		|||
with import <nix/config.nix>;
 | 
			
		||||
 | 
			
		||||
{ derivations, manifest }:
 | 
			
		||||
 | 
			
		||||
derivation {
 | 
			
		||||
  name = "user-environment";
 | 
			
		||||
  system = builtins.currentSystem;
 | 
			
		||||
  builder = nixLibexecDir + "/nix/buildenv";
 | 
			
		||||
  system = "builtin";
 | 
			
		||||
  builder = "builtin:buildenv";
 | 
			
		||||
 | 
			
		||||
  inherit manifest;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,21 +22,4 @@ derivation {
 | 
			
		|||
 | 
			
		||||
  # Also don't bother substituting.
 | 
			
		||||
  allowSubstitutes = false;
 | 
			
		||||
 | 
			
		||||
  __sandboxProfile = ''
 | 
			
		||||
    (allow sysctl-read)
 | 
			
		||||
    (allow file-read*
 | 
			
		||||
           (literal "/usr/lib/libSystem.dylib")
 | 
			
		||||
           (literal "/usr/lib/libSystem.B.dylib")
 | 
			
		||||
           (literal "/usr/lib/libobjc.A.dylib")
 | 
			
		||||
           (literal "/usr/lib/libobjc.dylib")
 | 
			
		||||
           (literal "/usr/lib/libauto.dylib")
 | 
			
		||||
           (literal "/usr/lib/libc++abi.dylib")
 | 
			
		||||
           (literal "/usr/lib/libc++.1.dylib")
 | 
			
		||||
           (literal "/usr/lib/libDiagnosticMessagesClient.dylib")
 | 
			
		||||
           (subpath "/usr/lib/system")
 | 
			
		||||
           (subpath "/dev"))
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  inherit chrootDeps;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
programs += buildenv
 | 
			
		||||
 | 
			
		||||
buildenv_DIR := $(d)
 | 
			
		||||
 | 
			
		||||
buildenv_INSTALL_DIR := $(libexecdir)/nix
 | 
			
		||||
 | 
			
		||||
buildenv_LIBS = libmain libstore libutil libformat
 | 
			
		||||
 | 
			
		||||
buildenv_SOURCES := $(d)/buildenv.cc
 | 
			
		||||
| 
						 | 
				
			
			@ -2949,6 +2949,8 @@ void DerivationGoal::runChild()
 | 
			
		|||
 | 
			
		||||
                if (drv->builder == "builtin:fetchurl")
 | 
			
		||||
                    builtinFetchurl(drv2, netrcData);
 | 
			
		||||
                else if (drv->builder == "builtin:buildenv")
 | 
			
		||||
                    builtinBuildenv(drv2);
 | 
			
		||||
                else
 | 
			
		||||
                    throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
 | 
			
		||||
                _exit(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,8 @@
 | 
			
		|||
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
// TODO: make pluggable.
 | 
			
		||||
void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData);
 | 
			
		||||
void builtinBuildenv(const BasicDerivation & drv);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,15 @@
 | 
			
		|||
#include "shared.hh"
 | 
			
		||||
#include "builtins.hh"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
using namespace nix;
 | 
			
		||||
namespace nix {
 | 
			
		||||
 | 
			
		||||
typedef std::map<Path,int> Priorities;
 | 
			
		||||
 | 
			
		||||
static bool isDirectory (const Path & path)
 | 
			
		||||
static bool isDirectory(const Path & path)
 | 
			
		||||
{
 | 
			
		||||
    struct stat st;
 | 
			
		||||
    if (stat(path.c_str(), &st) == -1)
 | 
			
		||||
| 
						 | 
				
			
			@ -16,9 +17,11 @@ static bool isDirectory (const Path & path)
 | 
			
		|||
    return S_ISDIR(st.st_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static auto priorities = Priorities{};
 | 
			
		||||
// FIXME: change into local variables.
 | 
			
		||||
 | 
			
		||||
static auto symlinks = 0;
 | 
			
		||||
static Priorities priorities;
 | 
			
		||||
 | 
			
		||||
static unsigned long symlinks;
 | 
			
		||||
 | 
			
		||||
/* For each activated package, create symlinks */
 | 
			
		||||
static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
 | 
			
		||||
| 
						 | 
				
			
			@ -95,10 +98,10 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
 | 
			
		|||
 | 
			
		||||
typedef std::set<Path> FileProp;
 | 
			
		||||
 | 
			
		||||
static auto done = FileProp{};
 | 
			
		||||
static auto postponed = FileProp{};
 | 
			
		||||
static FileProp done;
 | 
			
		||||
static FileProp postponed = FileProp{};
 | 
			
		||||
 | 
			
		||||
static auto out = string{};
 | 
			
		||||
static Path out;
 | 
			
		||||
 | 
			
		||||
static void addPkg(const Path & pkgDir, int priority)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +110,7 @@ static void addPkg(const Path & pkgDir, int priority)
 | 
			
		|||
    done.insert(pkgDir);
 | 
			
		||||
    createLinks(pkgDir, out, priority);
 | 
			
		||||
    auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages";
 | 
			
		||||
    auto propagated = string{};
 | 
			
		||||
    std::string propagated;
 | 
			
		||||
    {
 | 
			
		||||
        AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC);
 | 
			
		||||
        if (!fd) {
 | 
			
		||||
| 
						 | 
				
			
			@ -126,62 +129,65 @@ struct Package {
 | 
			
		|||
    Path path;
 | 
			
		||||
    bool active;
 | 
			
		||||
    int priority;
 | 
			
		||||
    Package(Path path, bool active, int priority) : path{std::move(path)}, active{active}, priority{priority} {}
 | 
			
		||||
    Package(Path path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::vector<Package> Packages;
 | 
			
		||||
 | 
			
		||||
int main(int argc, char ** argv)
 | 
			
		||||
void builtinBuildenv(const BasicDerivation & drv)
 | 
			
		||||
{
 | 
			
		||||
    return handleExceptions(argv[0], [&]() {
 | 
			
		||||
        initNix();
 | 
			
		||||
        out = getEnv("out");
 | 
			
		||||
        if (mkdir(out.c_str(), 0755) == -1)
 | 
			
		||||
            throw SysError(format("creating %1%") % out);
 | 
			
		||||
    auto getAttr = [&](const string & name) {
 | 
			
		||||
        auto i = drv.env.find(name);
 | 
			
		||||
        if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
 | 
			
		||||
        return i->second;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
        /* Convert the stuff we get from the environment back into a coherent
 | 
			
		||||
         * data type.
 | 
			
		||||
         */
 | 
			
		||||
        auto pkgs = Packages{};
 | 
			
		||||
        auto derivations = tokenizeString<Strings>(getEnv("derivations"));
 | 
			
		||||
        while (!derivations.empty()) {
 | 
			
		||||
            /* !!! We're trusting the caller to structure derivations env var correctly */
 | 
			
		||||
            auto active = derivations.front(); derivations.pop_front();
 | 
			
		||||
            auto priority = stoi(derivations.front()); derivations.pop_front();
 | 
			
		||||
            auto outputs = stoi(derivations.front()); derivations.pop_front();
 | 
			
		||||
            for (auto n = 0; n < outputs; n++) {
 | 
			
		||||
                auto path = derivations.front(); derivations.pop_front();
 | 
			
		||||
                pkgs.emplace_back(path, active != "false", priority);
 | 
			
		||||
            }
 | 
			
		||||
    out = getAttr("out");
 | 
			
		||||
    createDirs(out);
 | 
			
		||||
 | 
			
		||||
    /* Convert the stuff we get from the environment back into a
 | 
			
		||||
     * coherent data type. */
 | 
			
		||||
    Packages pkgs;
 | 
			
		||||
    auto derivations = tokenizeString<Strings>(getAttr("derivations"));
 | 
			
		||||
    while (!derivations.empty()) {
 | 
			
		||||
        /* !!! We're trusting the caller to structure derivations env var correctly */
 | 
			
		||||
        auto active = derivations.front(); derivations.pop_front();
 | 
			
		||||
        auto priority = stoi(derivations.front()); derivations.pop_front();
 | 
			
		||||
        auto outputs = stoi(derivations.front()); derivations.pop_front();
 | 
			
		||||
        for (auto n = 0; n < outputs; n++) {
 | 
			
		||||
            auto path = derivations.front(); derivations.pop_front();
 | 
			
		||||
            pkgs.emplace_back(path, active != "false", priority);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        /* Symlink to the packages that have been installed explicitly by the
 | 
			
		||||
         * user. Process in priority order to reduce unnecessary
 | 
			
		||||
         * symlink/unlink steps.
 | 
			
		||||
         */
 | 
			
		||||
        std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
 | 
			
		||||
            return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
 | 
			
		||||
        });
 | 
			
		||||
        for (const auto & pkg : pkgs)
 | 
			
		||||
            if (pkg.active)
 | 
			
		||||
                addPkg(pkg.path, pkg.priority);
 | 
			
		||||
 | 
			
		||||
        /* Symlink to the packages that have been "propagated" by packages
 | 
			
		||||
         * installed by the user (i.e., package X declares that it wants Y
 | 
			
		||||
         * installed as well). We do these later because they have a lower
 | 
			
		||||
         * priority in case of collisions.
 | 
			
		||||
         */
 | 
			
		||||
        auto priorityCounter = 1000;
 | 
			
		||||
        while (!postponed.empty()) {
 | 
			
		||||
            auto pkgDirs = postponed;
 | 
			
		||||
            postponed = FileProp{};
 | 
			
		||||
            for (const auto & pkgDir : pkgDirs)
 | 
			
		||||
                addPkg(pkgDir, priorityCounter++);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::cerr << "created " << symlinks << " symlinks in user environment\n";
 | 
			
		||||
 | 
			
		||||
        createSymlink(getEnv("manifest"), out + "/manifest.nix");
 | 
			
		||||
    /* Symlink to the packages that have been installed explicitly by the
 | 
			
		||||
     * user. Process in priority order to reduce unnecessary
 | 
			
		||||
     * symlink/unlink steps.
 | 
			
		||||
     */
 | 
			
		||||
    std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
 | 
			
		||||
        return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
 | 
			
		||||
    });
 | 
			
		||||
    for (const auto & pkg : pkgs)
 | 
			
		||||
        if (pkg.active)
 | 
			
		||||
            addPkg(pkg.path, pkg.priority);
 | 
			
		||||
 | 
			
		||||
    /* Symlink to the packages that have been "propagated" by packages
 | 
			
		||||
     * installed by the user (i.e., package X declares that it wants Y
 | 
			
		||||
     * installed as well). We do these later because they have a lower
 | 
			
		||||
     * priority in case of collisions.
 | 
			
		||||
     */
 | 
			
		||||
    auto priorityCounter = 1000;
 | 
			
		||||
    while (!postponed.empty()) {
 | 
			
		||||
        auto pkgDirs = postponed;
 | 
			
		||||
        postponed = FileProp{};
 | 
			
		||||
        for (const auto & pkgDir : pkgDirs)
 | 
			
		||||
            addPkg(pkgDir, priorityCounter++);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printError("created %d symlinks in user environment", symlinks);
 | 
			
		||||
 | 
			
		||||
    createSymlink(getAttr("manifest"), out + "/manifest.nix");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue