Merge pull request #8517 from hercules-ci/fix-build-hook-error-for-lib-users

Fix build hook error for libstore library users
This commit is contained in:
Eelco Dolstra 2023-06-16 13:20:50 +02:00 committed by GitHub
commit 713836112c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 1 deletions

1
.gitignore vendored
View file

@ -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

View file

@ -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 += \

View file

@ -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()

View file

@ -135,6 +135,7 @@ nix_tests = \
flakes/show.sh \
impure-derivations.sh \
path-from-hash-part.sh \
test-libstoreconsumer.sh \
toString-path.sh
ifeq ($(HAVE_LIBCPUID), 1)
@ -153,6 +154,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)

View file

@ -0,0 +1,6 @@
source common.sh
drv="$(nix-instantiate simple.nix)"
cat "$drv"
out="$(./test-libstoreconsumer/test-libstoreconsumer "$drv")"
cat "$out/hello" | grep -F "Hello World!"

View file

@ -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.

View file

@ -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)

View file

@ -0,0 +1,45 @@
#include "globals.hh"
#include "store-api.hh"
#include "build-result.hh"
#include <iostream>
using namespace nix;
int main (int argc, char **argv)
{
try {
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 {
.drvPath = store->parseStorePath(drvPath),
.outputs = OutputsSpec::Names{"out"}
}
};
const auto results = store->buildPathsWithResults(paths, bmNormal, store);
for (const auto & result : results) {
for (const auto & [outputName, realisation] : result.builtOutputs) {
std::cout << store->printStorePath(realisation.outPath) << "\n";
}
}
return 0;
} catch (const std::exception & e) {
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
}