forked from lix-project/lix
Make <nix/buildenv.nix> a builtin builder
This avoids sandbox annoyances.
This commit is contained in:
parent
9d40787938
commit
668ac3ea2c
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -13,9 +13,6 @@ perl/Makefile.config
|
||||||
|
|
||||||
/corepkgs/config.nix
|
/corepkgs/config.nix
|
||||||
|
|
||||||
# /corepkgs/buildenv/
|
|
||||||
/corepkgs/buildenv/builder.pl
|
|
||||||
|
|
||||||
# /corepkgs/channels/
|
# /corepkgs/channels/
|
||||||
/corepkgs/channels/unpack.sh
|
/corepkgs/channels/unpack.sh
|
||||||
|
|
||||||
|
@ -72,9 +69,6 @@ perl/Makefile.config
|
||||||
# /src/nix-channel/
|
# /src/nix-channel/
|
||||||
/src/nix-channel/nix-channel
|
/src/nix-channel/nix-channel
|
||||||
|
|
||||||
# /src/buildenv/
|
|
||||||
/src/buildenv/buildenv
|
|
||||||
|
|
||||||
# /src/nix-build/
|
# /src/nix-build/
|
||||||
/src/nix-build/nix-build
|
/src/nix-build/nix-build
|
||||||
|
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -12,7 +12,6 @@ makefiles = \
|
||||||
src/nix-collect-garbage/local.mk \
|
src/nix-collect-garbage/local.mk \
|
||||||
src/nix-copy-closure/local.mk \
|
src/nix-copy-closure/local.mk \
|
||||||
src/nix-prefetch-url/local.mk \
|
src/nix-prefetch-url/local.mk \
|
||||||
src/buildenv/local.mk \
|
|
||||||
src/resolve-system-dependencies/local.mk \
|
src/resolve-system-dependencies/local.mk \
|
||||||
src/nix-channel/local.mk \
|
src/nix-channel/local.mk \
|
||||||
src/nix-build/local.mk \
|
src/nix-build/local.mk \
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
with import <nix/config.nix>;
|
|
||||||
|
|
||||||
{ derivations, manifest }:
|
{ derivations, manifest }:
|
||||||
|
|
||||||
derivation {
|
derivation {
|
||||||
name = "user-environment";
|
name = "user-environment";
|
||||||
system = builtins.currentSystem;
|
system = "builtin";
|
||||||
builder = nixLibexecDir + "/nix/buildenv";
|
builder = "builtin:buildenv";
|
||||||
|
|
||||||
inherit manifest;
|
inherit manifest;
|
||||||
|
|
||||||
|
@ -24,21 +22,4 @@ derivation {
|
||||||
|
|
||||||
# Also don't bother substituting.
|
# Also don't bother substituting.
|
||||||
allowSubstitutes = false;
|
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")
|
if (drv->builder == "builtin:fetchurl")
|
||||||
builtinFetchurl(drv2, netrcData);
|
builtinFetchurl(drv2, netrcData);
|
||||||
|
else if (drv->builder == "builtin:buildenv")
|
||||||
|
builtinBuildenv(drv2);
|
||||||
else
|
else
|
||||||
throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
|
throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
// TODO: make pluggable.
|
||||||
void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData);
|
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/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace nix;
|
namespace nix {
|
||||||
|
|
||||||
typedef std::map<Path,int> Priorities;
|
typedef std::map<Path,int> Priorities;
|
||||||
|
|
||||||
static bool isDirectory (const Path & path)
|
static bool isDirectory(const Path & path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(path.c_str(), &st) == -1)
|
if (stat(path.c_str(), &st) == -1)
|
||||||
|
@ -16,9 +17,11 @@ static bool isDirectory (const Path & path)
|
||||||
return S_ISDIR(st.st_mode);
|
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 */
|
/* For each activated package, create symlinks */
|
||||||
static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
|
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;
|
typedef std::set<Path> FileProp;
|
||||||
|
|
||||||
static auto done = FileProp{};
|
static FileProp done;
|
||||||
static auto postponed = FileProp{};
|
static FileProp postponed = FileProp{};
|
||||||
|
|
||||||
static auto out = string{};
|
static Path out;
|
||||||
|
|
||||||
static void addPkg(const Path & pkgDir, int priority)
|
static void addPkg(const Path & pkgDir, int priority)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +110,7 @@ static void addPkg(const Path & pkgDir, int priority)
|
||||||
done.insert(pkgDir);
|
done.insert(pkgDir);
|
||||||
createLinks(pkgDir, out, priority);
|
createLinks(pkgDir, out, priority);
|
||||||
auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages";
|
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);
|
AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC);
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
|
@ -126,62 +129,65 @@ struct Package {
|
||||||
Path path;
|
Path path;
|
||||||
bool active;
|
bool active;
|
||||||
int priority;
|
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;
|
typedef std::vector<Package> Packages;
|
||||||
|
|
||||||
int main(int argc, char ** argv)
|
void builtinBuildenv(const BasicDerivation & drv)
|
||||||
{
|
{
|
||||||
return handleExceptions(argv[0], [&]() {
|
auto getAttr = [&](const string & name) {
|
||||||
initNix();
|
auto i = drv.env.find(name);
|
||||||
out = getEnv("out");
|
if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
|
||||||
if (mkdir(out.c_str(), 0755) == -1)
|
return i->second;
|
||||||
throw SysError(format("creating %1%") % out);
|
};
|
||||||
|
|
||||||
/* Convert the stuff we get from the environment back into a coherent
|
out = getAttr("out");
|
||||||
* data type.
|
createDirs(out);
|
||||||
*/
|
|
||||||
auto pkgs = Packages{};
|
/* Convert the stuff we get from the environment back into a
|
||||||
auto derivations = tokenizeString<Strings>(getEnv("derivations"));
|
* coherent data type. */
|
||||||
while (!derivations.empty()) {
|
Packages pkgs;
|
||||||
/* !!! We're trusting the caller to structure derivations env var correctly */
|
auto derivations = tokenizeString<Strings>(getAttr("derivations"));
|
||||||
auto active = derivations.front(); derivations.pop_front();
|
while (!derivations.empty()) {
|
||||||
auto priority = stoi(derivations.front()); derivations.pop_front();
|
/* !!! We're trusting the caller to structure derivations env var correctly */
|
||||||
auto outputs = stoi(derivations.front()); derivations.pop_front();
|
auto active = derivations.front(); derivations.pop_front();
|
||||||
for (auto n = 0; n < outputs; n++) {
|
auto priority = stoi(derivations.front()); derivations.pop_front();
|
||||||
auto path = derivations.front(); derivations.pop_front();
|
auto outputs = stoi(derivations.front()); derivations.pop_front();
|
||||||
pkgs.emplace_back(path, active != "false", priority);
|
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
|
/* Symlink to the packages that have been installed explicitly by the
|
||||||
* user. Process in priority order to reduce unnecessary
|
* user. Process in priority order to reduce unnecessary
|
||||||
* symlink/unlink steps.
|
* symlink/unlink steps.
|
||||||
*/
|
*/
|
||||||
std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
|
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);
|
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");
|
|
||||||
});
|
});
|
||||||
|
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…
Reference in a new issue