Skip to content

Commit

Permalink
Properly scope NIX_BIN_DIR just to the nix CLI
Browse files Browse the repository at this point in the history
It is no longer feasible to define it in libnixstore, and that's good.
  • Loading branch information
Ericson2314 committed Jul 24, 2024
1 parent 3519e78 commit 349a2ef
Show file tree
Hide file tree
Showing 21 changed files with 154 additions and 79 deletions.
40 changes: 18 additions & 22 deletions src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#include "ansicolor.hh"
#include "shared.hh"
#include "config-global.hh"
#include "eval.hh"
#include "eval-settings.hh"
#include "attr-path.hh"
Expand Down Expand Up @@ -77,10 +76,14 @@ struct NixRepl
int displ;
StringSet varNames;

RunNix * runNixPtr;

void runNix(Path program, const Strings & args, const std::optional<std::string> & input = {});

std::unique_ptr<ReplInteracter> interacter;

NixRepl(const LookupPath & lookupPath, nix::ref<Store> store,ref<EvalState> state,
std::function<AnnotatedValues()> getValues);
std::function<AnnotatedValues()> getValues, RunNix * runNix);
virtual ~NixRepl() = default;

ReplExitStatus mainLoop() override;
Expand Down Expand Up @@ -125,32 +128,16 @@ std::string removeWhitespace(std::string s)


NixRepl::NixRepl(const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<NixRepl::AnnotatedValues()> getValues)
std::function<NixRepl::AnnotatedValues()> getValues, RunNix * runNix = nullptr)
: AbstractNixRepl(state)
, debugTraceIndex(0)
, getValues(getValues)
, staticEnv(new StaticEnv(nullptr, state->staticBaseEnv.get()))
, runNixPtr{runNix}
, interacter(make_unique<ReadlineLikeInteracter>(getDataDir() + "/nix/repl-history"))
{
}

void runNix(Path program, const Strings & args,
const std::optional<std::string> & input = {})
{
auto subprocessEnv = getEnv();
subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue();
//isInteractive avoid grabling interactive commands
runProgram2(RunOptions {
.program = settings.nixBinDir+ "/" + program,
.args = args,
.environment = subprocessEnv,
.input = input,
.isInteractive = true,
});

return;
}

static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positions, const DebugTrace & dt)
{
if (dt.isError)
Expand Down Expand Up @@ -635,7 +622,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
// When missing, trigger the normal exception
// e.g. :doc builtins.foo
// behaves like
// nix-repl> builtins.foo
// nix-repl> builtins.foo
// error: attribute 'foo' missing
evalString(arg, v);
assert(false);
Expand Down Expand Up @@ -836,9 +823,18 @@ void NixRepl::evalString(std::string s, Value & v)
}


void NixRepl::runNix(Path program, const Strings & args, const std::optional<std::string> & input)
{
if (runNixPtr)
(*runNixPtr)(program, args, input);
else
throw Error("Cannot run '%s', no method of calling the Nix CLI provided", program);
}


std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create(
const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<AnnotatedValues()> getValues)
std::function<AnnotatedValues()> getValues, RunNix * runNix)
{
return std::make_unique<NixRepl>(
lookupPath,
Expand Down
14 changes: 12 additions & 2 deletions src/libcmd/repl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,19 @@ struct AbstractNixRepl

typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;

using RunNix = void(Path program, const Strings & args, const std::optional<std::string> & input);

/**
* @param runNix Function to run the nix CLI to support various
* `:<something>` commands. Can not be provided, in which case
* everything else will still work fine, but those commands won't.
*/
static std::unique_ptr<AbstractNixRepl> create(
const LookupPath & lookupPath, nix::ref<Store> store, ref<EvalState> state,
std::function<AnnotatedValues()> getValues);
const LookupPath & lookupPath,
nix::ref<Store> store,
ref<EvalState> state,
std::function<AnnotatedValues()> getValues,
RunNix * runNix = nullptr);

static ReplExitStatus runSimple(
ref<EvalState> evalState,
Expand Down
4 changes: 4 additions & 0 deletions src/libexpr/primops/fromTOML.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
#include "eval-inline.hh"

#include <sstream>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
#include <toml.hpp>
#pragma GCC diagnostic pop

namespace nix {

Expand Down
29 changes: 0 additions & 29 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ Settings::Settings()
, nixStateDir(canonPath(getEnvNonEmpty("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
, nixConfDir(canonPath(getEnvNonEmpty("NIX_CONF_DIR").value_or(NIX_CONF_DIR)))
, nixUserConfFiles(getUserConfigFiles())
, nixBinDir(canonPath(getEnvNonEmpty("NIX_BIN_DIR").value_or(NIX_BIN_DIR)))
, nixManDir(canonPath(NIX_MAN_DIR))
, nixDaemonSocketFile(canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
{
Expand Down Expand Up @@ -95,34 +94,6 @@ Settings::Settings()
sandboxPaths = tokenizeString<StringSet>("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib");
allowedImpureHostPrefixes = tokenizeString<StringSet>("/System/Library /usr/lib /dev /bin/sh");
#endif

/* Set the build hook location
For builds we perform a self-invocation, so Nix has to be self-aware.
That is, it has to know where it is installed. We don't think it's sentient.
Normally, nix is installed according to `nixBinDir`, which is set at compile time,
but can be overridden. This makes for a great default that works even if this
code is linked as a library into some other program whose main is not aware
that it might need to be a build remote hook.
However, it may not have been installed at all. For example, if it's a static build,
there's a good chance that it has been moved out of its installation directory.
That makes `nixBinDir` useless. Instead, we'll query the OS for the path to the
current executable, using `getSelfExe()`.
As a last resort, we resort to `PATH`. Hopefully we find a `nix` there that's compatible.
If you're porting Nix to a new platform, that might be good enough for a while, but
you'll want to improve `getSelfExe()` to work on your platform.
*/
std::string nixExePath = nixBinDir + "/nix";
if (!pathExists(nixExePath)) {
nixExePath = getSelfExe().value_or("nix");
}
buildHook = {
nixExePath,
"__build-remote",
};
}

void loadConfFile(AbstractConfig & config)
Expand Down
5 changes: 0 additions & 5 deletions src/libstore/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ public:
*/
std::vector<Path> nixUserConfFiles;

/**
* The directory where the main programs are stored.
*/
Path nixBinDir;

/**
* The directory where the man pages are stored.
*/
Expand Down
1 change: 0 additions & 1 deletion src/libstore/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ libstore_CXXFLAGS += \
-DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \
-DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \
-DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \
-DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" \
-DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \
-DLSOF=\"$(NIX_ROOT)$(lsof)\"

Expand Down
2 changes: 0 additions & 2 deletions src/libstore/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ prefix = get_option('prefix')
path_opts = [
# Meson built-ins.
'datadir',
'bindir',
'mandir',
'libdir',
'includedir',
Expand Down Expand Up @@ -372,7 +371,6 @@ cpp_str_defines = {
'NIX_STATE_DIR': state_dir / 'nix',
'NIX_LOG_DIR': log_dir,
'NIX_CONF_DIR': sysconfdir / 'nix',
'NIX_BIN_DIR': bindir,
'NIX_MAN_DIR': mandir,
}

Expand Down
3 changes: 3 additions & 0 deletions src/libstore/s3-binary-cache-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "compression.hh"
#include "filetransfer.hh"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
#include <aws/core/Aws.h>
#include <aws/core/VersionConfig.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
Expand All @@ -25,6 +27,7 @@
#include <aws/s3/model/ListObjectsRequest.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <aws/transfer/TransferManager.h>
#pragma GCC diagnostic pop

using namespace Aws::Transfer;

Expand Down
2 changes: 1 addition & 1 deletion src/libstore/s3.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <optional>
#include <string>

namespace Aws { namespace Client { class ClientConfiguration; } }
namespace Aws { namespace Client { struct ClientConfiguration; } }
namespace Aws { namespace S3 { class S3Client; } }

namespace nix {
Expand Down
11 changes: 6 additions & 5 deletions src/nix-channel/nix-channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "eval-settings.hh" // for defexpr
#include "users.hh"
#include "tarball.hh"
#include "bin-dir.hh"

#include <fcntl.h>
#include <regex>
Expand Down Expand Up @@ -67,7 +68,7 @@ static void removeChannel(const std::string & name)
channels.erase(name);
writeChannels();

runProgram(settings.nixBinDir + "/nix-env", true, { "--profile", profile, "--uninstall", name });
runProgram(getNixBinDir() + "/nix-env", true, { "--profile", profile, "--uninstall", name });
}

static Path nixDefExpr;
Expand Down Expand Up @@ -118,7 +119,7 @@ static void update(const StringSet & channelNames)

bool unpacked = false;
if (std::regex_search(filename, std::regex("\\.tar\\.(gz|bz2|xz)$"))) {
runProgram(settings.nixBinDir + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath +
runProgram(getNixBinDir() + "/nix-build", false, { "--no-out-link", "--expr", "import " + unpackChannelPath +
"{ name = \"" + cname + "\"; channelName = \"" + name + "\"; src = builtins.storePath \"" + filename + "\"; }" });
unpacked = true;
}
Expand All @@ -143,7 +144,7 @@ static void update(const StringSet & channelNames)
for (auto & expr : exprs)
envArgs.push_back(std::move(expr));
envArgs.push_back("--quiet");
runProgram(settings.nixBinDir + "/nix-env", false, envArgs);
runProgram(getNixBinDir() + "/nix-env", false, envArgs);

// Make the channels appear in nix-env.
struct stat st;
Expand Down Expand Up @@ -244,7 +245,7 @@ static int main_nix_channel(int argc, char ** argv)
case cListGenerations:
if (!args.empty())
throw UsageError("'--list-generations' expects no arguments");
std::cout << runProgram(settings.nixBinDir + "/nix-env", false, {"--profile", profile, "--list-generations"}) << std::flush;
std::cout << runProgram(getNixBinDir() + "/nix-env", false, {"--profile", profile, "--list-generations"}) << std::flush;
break;
case cRollback:
if (args.size() > 1)
Expand All @@ -256,7 +257,7 @@ static int main_nix_channel(int argc, char ** argv)
} else {
envArgs.push_back("--rollback");
}
runProgram(settings.nixBinDir + "/nix-env", false, envArgs);
runProgram(getNixBinDir() + "/nix-env", false, envArgs);
break;
}

Expand Down
28 changes: 28 additions & 0 deletions src/nix/bin-dir.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "current-process.hh"
#include "file-system.hh"
#include "globals.hh"
#include "bin-dir.hh"

namespace nix {

const Path & getNixBinDir()
{
static const Path nixBinDir = canonPath(getEnvNonEmpty("NIX_BIN_DIR").value_or(NIX_BIN_DIR));

return nixBinDir;
}

void setNixBuildRemoteLocation()
{
std::string nixExePath = getNixBinDir() + "/nix";
if (!pathExists(nixExePath)) {
nixExePath = getSelfExe().value_or("nix");
}
settings.buildHook = {
nixExePath,
"__build-remote",
};
}


}
37 changes: 37 additions & 0 deletions src/nix/bin-dir.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once
///@file

#include "types.hh"

namespace nix {

/**
* The directory where the main programs are stored.
*/
const Path & getNixBinDir();

/**
* @TODO update docs to match status quo, where NIX_BIN_DIR is not defined for libraries
*
* Set the build hook location
*
* For builds we perform a self-invocation, so Nix has to be self-aware.
* That is, it has to know where it is installed. We don't think it's sentient.
*
* Normally, nix is installed according to `nixBinDir`, which is set at compile time,
* but can be overridden. This makes for a great default that works even if this
* code is linked as a library into some other program whose main is not aware
* that it might need to be a build remote hook.
*
* However, it may not have been installed at all. For example, if it's a static build,
* there's a good chance that it has been moved out of its installation directory.
* That makes `nixBinDir` useless. Instead, we'll query the OS for the path to the
* current executable, using `getSelfExe()`.
*
* As a last resort, we resort to `PATH`. Hopefully we find a `nix` there that's compatible.
* If you're porting Nix to a new platform, that might be good enough for a while, but
* you'll want to improve `getSelfExe()` to work on your platform.
*/
void setNixBuildRemoteLocation();

}
2 changes: 2 additions & 0 deletions src/nix/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ endif

nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix)

nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\"

nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd

nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS)
Expand Down
2 changes: 2 additions & 0 deletions src/nix/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "network-proxy.hh"
#include "eval-cache.hh"
#include "flake/flake.hh"
#include "bin-dir.hh"

#include <sys/types.h>
#include <regex>
Expand Down Expand Up @@ -365,6 +366,7 @@ void mainWrapped(int argc, char * * argv)
initNix();
initGC();
flake::initLib(flakeSettings);
setNixBuildRemoteLocation();

#if __linux__
if (isRootUser()) {
Expand Down
Loading

0 comments on commit 349a2ef

Please sign in to comment.