Skip to content

Commit

Permalink
Fix build hook error for libstore library users
Browse files Browse the repository at this point in the history
A library shouldn't require changes to the caller's argument handling,
especially if it doesn't have to, and indeed we don't have to.

This changes the lookup order to prioritize the hardcoded path to nix
if it exists. The static executable still finds itself through /proc
and the like.
  • Loading branch information
roberth committed Jun 14, 2023
1 parent 9c6ede8 commit b231749
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ perl/Makefile.config
/tests/ca/config.nix
/tests/dyn-drv/config.nix
/tests/repl-result-out
/tests/test-libstoreconsumer/test-libstoreconsumer

# /tests/lang/
/tests/lang/*.out
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ makefiles += \
src/libstore/tests/local.mk \
src/libexpr/tests/local.mk \
tests/local.mk \
tests/test-libstoreconsumer/local.mk \
tests/plugins/local.mk
else
makefiles += \
Expand Down
25 changes: 24 additions & 1 deletion src/libstore/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,30 @@ Settings::Settings()
allowedImpureHostPrefixes = tokenizeString<StringSet>("/System/Library /usr/lib /dev /bin/sh");
#endif

buildHook = getSelfExe().value_or("nix") + " __build-remote";
/* 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()
Expand Down
2 changes: 2 additions & 0 deletions tests/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ nix_tests = \
flakes/show.sh \
impure-derivations.sh \
path-from-hash-part.sh \
test-libstoreconsumer.sh \
toString-path.sh

ifeq ($(HAVE_LIBCPUID), 1)
Expand All @@ -152,6 +153,7 @@ test-deps += \
tests/common/vars-and-functions.sh \
tests/config.nix \
tests/ca/config.nix \
tests/test-libstoreconsumer/test-libstoreconsumer \
tests/dyn-drv/config.nix

ifeq ($(BUILD_SHARED_LIBS), 1)
Expand Down
5 changes: 5 additions & 0 deletions tests/test-libstoreconsumer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source common.sh

drv="$(nix-instantiate simple.nix)"
cat "$drv"
./test-libstoreconsumer/test-libstoreconsumer "$drv"
6 changes: 6 additions & 0 deletions tests/test-libstoreconsumer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

A very simple C++ consumer of the libstore library.

- Keep it simple. Library consumers expect something simple.
- No build hook, or any other reinvocations.
- No more global state than necessary.
12 changes: 12 additions & 0 deletions tests/test-libstoreconsumer/local.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
programs += test-libstoreconsumer

test-libstoreconsumer_DIR := $(d)

test-libstoreconsumer_SOURCES := \
$(wildcard $(d)/*.cc) \

test-libstoreconsumer_CXXFLAGS += -I src/libutil -I src/libstore

test-libstoreconsumer_LIBS = libstore libutil

test-libstoreconsumer_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS)
34 changes: 34 additions & 0 deletions tests/test-libstoreconsumer/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "globals.hh"
#include "store-api.hh"
#include <iostream>

using namespace nix;

int main (int argc, char **argv)
{
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " store/path/to/something.drv\n";
return 1;
}

std::string drvPath = argv[1];

initLibStore();

auto store = nix::openStore();

// build the derivation

std::vector<DerivedPath> paths {
DerivedPath::Built(
store->parseStorePath(drvPath),
OutputsSpec::Names{"out"}
)
};

store->buildPaths(paths, bmNormal, store);

// print the out path maybe?

return 0;
}

0 comments on commit b231749

Please sign in to comment.