Merge branch 'shlevy-import-native'
This commit is contained in:
commit
d7be6d45d9
4 changed files with 50 additions and 0 deletions
|
@ -8,6 +8,8 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc
|
||||||
|
|
||||||
libexpr_LIBS = libutil libstore libformat
|
libexpr_LIBS = libutil libstore libformat
|
||||||
|
|
||||||
|
libexpr_LDFLAGS = -ldl
|
||||||
|
|
||||||
# The dependency on libgc must be propagated (i.e. meaning that
|
# The dependency on libgc must be propagated (i.e. meaning that
|
||||||
# programs/libraries that use libexpr must explicitly pass -lgc),
|
# programs/libraries that use libexpr must explicitly pass -lgc),
|
||||||
# because inline functions in libexpr's header files call libgc.
|
# because inline functions in libexpr's header files call libgc.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -129,6 +130,46 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Want reasonable symbol names, so extern C */
|
||||||
|
/* !!! Should we pass the Pos or the file name too? */
|
||||||
|
extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
|
||||||
|
|
||||||
|
/* Load a ValueInitializer from a dso and return whatever it initializes */
|
||||||
|
static void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
PathSet context;
|
||||||
|
Path path = state.coerceToPath(pos, *args[0], context);
|
||||||
|
|
||||||
|
try {
|
||||||
|
realiseContext(context);
|
||||||
|
} catch (InvalidPathError & e) {
|
||||||
|
throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%")
|
||||||
|
% path % e.path % pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
string sym = state.forceStringNoCtx(*args[1], pos);
|
||||||
|
|
||||||
|
void *handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (!handle)
|
||||||
|
throw EvalError(format("could not open `%1%': %2%") % path % dlerror());
|
||||||
|
|
||||||
|
dlerror();
|
||||||
|
ValueInitializer func = (ValueInitializer) dlsym(handle, sym.c_str());
|
||||||
|
if(!func) {
|
||||||
|
char *message = dlerror();
|
||||||
|
if (message)
|
||||||
|
throw EvalError(format("could not load symbol `%1%' from `%2%': %3%") % sym % path % message);
|
||||||
|
else
|
||||||
|
throw EvalError(format("symbol `%1%' from `%2%' resolved to NULL when a function pointer was expected")
|
||||||
|
% sym % path);
|
||||||
|
}
|
||||||
|
|
||||||
|
(func)(state, v);
|
||||||
|
|
||||||
|
/* We don't dlclose because v may be a primop referencing a function in the shared object file */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return a string representing the type of the expression. */
|
/* Return a string representing the type of the expression. */
|
||||||
static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
|
@ -1327,6 +1368,8 @@ void EvalState::createBaseEnv()
|
||||||
mkApp(v, *baseEnv.values[baseEnvDispl - 1], *v2);
|
mkApp(v, *baseEnv.values[baseEnvDispl - 1], *v2);
|
||||||
forceValue(v);
|
forceValue(v);
|
||||||
addConstant("import", v);
|
addConstant("import", v);
|
||||||
|
if (settings.enableImportNative)
|
||||||
|
addPrimOp("__importNative", 2, prim_importNative);
|
||||||
addPrimOp("__typeOf", 1, prim_typeOf);
|
addPrimOp("__typeOf", 1, prim_typeOf);
|
||||||
addPrimOp("isNull", 1, prim_isNull);
|
addPrimOp("isNull", 1, prim_isNull);
|
||||||
addPrimOp("__isFunction", 1, prim_isFunction);
|
addPrimOp("__isFunction", 1, prim_isFunction);
|
||||||
|
|
|
@ -61,6 +61,7 @@ Settings::Settings()
|
||||||
envKeepDerivations = false;
|
envKeepDerivations = false;
|
||||||
lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";
|
lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";
|
||||||
showTrace = false;
|
showTrace = false;
|
||||||
|
enableImportNative = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,6 +149,7 @@ void Settings::update()
|
||||||
get(sshSubstituterHosts, "ssh-substituter-hosts");
|
get(sshSubstituterHosts, "ssh-substituter-hosts");
|
||||||
get(useSshSubstituter, "use-ssh-substituter");
|
get(useSshSubstituter, "use-ssh-substituter");
|
||||||
get(logServers, "log-servers");
|
get(logServers, "log-servers");
|
||||||
|
get(enableImportNative, "allow-arbitrary-code-during-evaluation");
|
||||||
|
|
||||||
string subs = getEnv("NIX_SUBSTITUTERS", "default");
|
string subs = getEnv("NIX_SUBSTITUTERS", "default");
|
||||||
if (subs == "default") {
|
if (subs == "default") {
|
||||||
|
|
|
@ -200,6 +200,9 @@ struct Settings {
|
||||||
/* A list of URL prefixes that can return Nix build logs. */
|
/* A list of URL prefixes that can return Nix build logs. */
|
||||||
Strings logServers;
|
Strings logServers;
|
||||||
|
|
||||||
|
/* Whether the importNative primop should be enabled */
|
||||||
|
bool enableImportNative;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SettingsMap settings, overrides;
|
SettingsMap settings, overrides;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue