Skip to content

Commit baf151d

Browse files
committed
Derivation builder via C via test
1 parent 47b3cf3 commit baf151d

File tree

7 files changed

+319
-36
lines changed

7 files changed

+319
-36
lines changed

src/libstore-c/nix_api_store.cc

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "nix/store/store-api.hh"
88
#include "nix/store/store-open.hh"
99
#include "nix/store/build-result.hh"
10+
#include "nix/store/build/derivation-builder.hh"
11+
#include "nix/store/build/derivation-env-desugar.hh"
1012

1113
#include "nix/store/globals.hh"
1214

@@ -126,6 +128,28 @@ StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const c
126128
NIXC_CATCH_ERRS_NULL
127129
}
128130

131+
StorePath * nix_store_parse_path2(nix_c_context * context, StoreDir store_dir, const char * path)
132+
{
133+
if (context)
134+
context->last_err_code = NIX_OK;
135+
try {
136+
nix::Path sdInner = store_dir.store_directory;
137+
nix::StoreDirConfig sd{sdInner};
138+
nix::StorePath s = sd.parseStorePath(path);
139+
return new StorePath{std::move(s)};
140+
}
141+
NIXC_CATCH_ERRS_NULL
142+
}
143+
144+
void
145+
nix_print_store_path(StoreDir store_dir, const StorePath * path, nix_get_string_callback callback, void * user_data)
146+
{
147+
nix::Path sdInner = store_dir.store_directory;
148+
nix::StoreDirConfig sd{sdInner};
149+
std::string s = sd.printStorePath(path->path);
150+
callback(s.c_str(), s.size(), user_data);
151+
}
152+
129153
nix_err nix_store_realise(
130154
nix_c_context * context,
131155
Store * store,
@@ -176,16 +200,18 @@ StorePath * nix_store_path_clone(const StorePath * p)
176200
return new StorePath{p->path};
177201
}
178202

179-
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json)
203+
nix_derivation * nix_derivation_from_json(nix_c_context * context, StoreDir store_dir, const char * json)
180204
{
181205
if (context)
182206
context->last_err_code = NIX_OK;
183207
try {
184-
auto drv = nix::Derivation::fromJSON(*store->ptr, nlohmann::json::parse(json));
185-
186-
auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
208+
nix::Path sdInner = store_dir.store_directory;
209+
nix::StoreDirConfig sd{sdInner};
210+
auto drv = nix::Derivation::fromJSON(sd, nlohmann::json::parse(json));
187211

188-
drv.checkInvariants(*store->ptr, drvPath);
212+
// auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
213+
//
214+
// drv.checkInvariants(*store->ptr, drvPath);
189215

190216
return new nix_derivation{drv};
191217
}
@@ -216,4 +242,135 @@ nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store
216242
NIXC_CATCH_ERRS
217243
}
218244

245+
struct nix_derivation_builder
246+
{
247+
nix::BuildResult buildResult;
248+
nix::DerivationOptions drvOptions;
249+
const nix::StorePathSet inputPaths;
250+
std::map<std::string, nix::InitialOutput> initialOutputs;
251+
nix::AutoCloseFD builderOut;
252+
std::unique_ptr<nix::DerivationBuilder> builder;
253+
};
254+
255+
nix_derivation_builder * nix_make_derivation_builder(
256+
nix_c_context * context,
257+
StoreDir storeDir,
258+
const char * buildDir,
259+
const nix_derivation * drv,
260+
const StorePath * drvPath,
261+
const StorePath * inputPaths[])
262+
{
263+
if (context)
264+
context->last_err_code = NIX_OK;
265+
try {
266+
struct CBuildingStore : nix::BuildingStore
267+
{
268+
nix::Path storeDir;
269+
nix::Path buildDir;
270+
271+
CBuildingStore(StoreDir storeDir_, const char * buildDir_)
272+
: nix::BuildingStore{this->storeDir}
273+
, storeDir{storeDir_.store_directory}
274+
, buildDir{buildDir_}
275+
{
276+
}
277+
278+
virtual nix::Path getRealStoreDir() const override
279+
{
280+
return storeDir;
281+
}
282+
283+
virtual nix::Path getBuildDir() const override
284+
{
285+
return buildDir;
286+
}
287+
288+
std::thread startDaemon(
289+
nix::Descriptor daemonListeningSocket,
290+
nix::RestrictionContext & ctx,
291+
std::vector<std::thread> & daemonWorkerThreads) override
292+
{
293+
throw nix::Unsupported("Recursive Nix is not yet supported from C builder interface");
294+
}
295+
};
296+
297+
void * p = ::operator new(sizeof(nix_derivation_builder));
298+
auto & ref = *static_cast<nix_derivation_builder *>(p);
299+
return new (p) nix_derivation_builder{
300+
.builder = nix::makeDerivationBuilder(
301+
std::make_unique<CBuildingStore>(storeDir, buildDir),
302+
std::make_unique<nix::DerivationBuilderCallbacks>(),
303+
nix::DerivationBuilderParams{
304+
.drvPath{drvPath->path},
305+
.buildResult = ref.buildResult,
306+
.drv = drv->drv,
307+
.drvOptions = ref.drvOptions,
308+
.inputPaths = ref.inputPaths,
309+
.initialOutputs = ref.initialOutputs,
310+
.buildMode = nix::bmNormal,
311+
// TODO
312+
.defaultPathsInChroot{nix::settings.sandboxPaths.get()},
313+
// TODO
314+
.desugaredEnv{[&] {
315+
nix::DesugaredEnv res;
316+
for (auto & [n, v] : drv->drv.env) {
317+
res.variables.insert_or_assign(n, nix::DesugaredEnv::EnvEntry{.value = v});
318+
}
319+
return res;
320+
}()},
321+
}),
322+
};
323+
}
324+
NIXC_CATCH_ERRS_NULL
325+
}
326+
327+
nix_err nix_derivation_builder_start(nix_c_context * context, nix_derivation_builder * builder)
328+
{
329+
try {
330+
if (auto optD = builder->builder->startBuild())
331+
builder->builderOut = *std::move(optD);
332+
else
333+
throw nix::Error("Could not get build user");
334+
}
335+
NIXC_CATCH_ERRS
336+
}
337+
338+
nix_err nix_derivation_builder_finish(
339+
nix_c_context * context,
340+
nix_derivation_builder * builder,
341+
void * userdata,
342+
void (*callback)(void * userdata, const char * outname, const StorePath * out))
343+
{
344+
try {
345+
nix::StringSink sink;
346+
try {
347+
nix::drainFD(builder->builderOut.get(), sink);
348+
} catch (nix::SysError &) {
349+
if (errno == EIO)
350+
builder->builderOut.release();
351+
else
352+
throw;
353+
}
354+
355+
std::cout << sink.s;
356+
357+
auto [status, diskFull] = builder->builder->unprepareBuild();
358+
359+
nix::warn("RESULT: %s", nix::statusToString(status));
360+
361+
if (callback) {
362+
for (const auto & [outputName, realisation] : builder->buildResult.builtOutputs) {
363+
StorePath p{realisation.outPath};
364+
callback(userdata, outputName.c_str(), &p);
365+
}
366+
}
367+
}
368+
NIXC_CATCH_ERRS
369+
}
370+
371+
void nix_derivation_builder_free(nix_derivation_builder * builder)
372+
{
373+
delete builder;
374+
}
375+
219376
} // extern "C"

src/libstore-c/nix_api_store.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ typedef struct StorePath StorePath;
2626
/** @brief Nix Derivation */
2727
typedef struct nix_derivation nix_derivation;
2828

29+
typedef struct StoreDir
30+
{
31+
const char * store_directory;
32+
} StoreDir;
33+
2934
/**
3035
* @brief Initializes the Nix store library
3136
*
@@ -118,6 +123,11 @@ nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_ca
118123
*/
119124
StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path);
120125

126+
StorePath * nix_store_parse_path2(nix_c_context * context, StoreDir store_dir, const char * path);
127+
128+
void nix_print_store_path(
129+
StoreDir store_dir, const StorePath * path, nix_get_string_callback callback, void * user_data);
130+
121131
/**
122132
* @brief Get the path name (e.g. "name" in /nix/store/...-name)
123133
*
@@ -216,7 +226,7 @@ nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_cal
216226
* @param[in] store nix store reference.
217227
* @param[in] json JSON of the derivation as a string.
218228
*/
219-
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json);
229+
nix_derivation * nix_derivation_from_json(nix_c_context * context, StoreDir storeDir, const char * json);
220230

221231
/**
222232
* @brief Add the given `nix_derivation` to the given store
@@ -245,6 +255,27 @@ void nix_derivation_free(nix_derivation * drv);
245255
*/
246256
nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path);
247257

258+
/** @brief Nix Derivation */
259+
typedef struct nix_derivation_builder nix_derivation_builder;
260+
261+
nix_derivation_builder * nix_make_derivation_builder(
262+
nix_c_context * context,
263+
StoreDir storeDir,
264+
const char * buildDir,
265+
const nix_derivation * drv,
266+
const StorePath * drvPath,
267+
const StorePath * inputPaths[]);
268+
269+
nix_err nix_derivation_builder_start(nix_c_context * context, nix_derivation_builder * builder);
270+
271+
nix_err nix_derivation_builder_finish(
272+
nix_c_context * context,
273+
nix_derivation_builder * builder,
274+
void * userdata,
275+
void (*callback)(void * userdata, const char * outname, const StorePath * out));
276+
277+
void nix_derivation_builder_free(nix_derivation_builder * builder);
278+
248279
// cffi end
249280
#ifdef __cplusplus
250281
}

src/libstore-test-support/include/nix/store/tests/nix_api_store.hh

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,7 @@ public:
1919
nix_api_store_test_base()
2020
{
2121
nix_libstore_init(ctx);
22-
};
2322

24-
~nix_api_store_test_base() override
25-
{
26-
if (exists(std::filesystem::path{nixDir})) {
27-
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
28-
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
29-
}
30-
std::filesystem::remove_all(nixDir);
31-
}
32-
}
33-
34-
std::string nixDir;
35-
std::string nixStoreDir;
36-
std::string nixStateDir;
37-
std::string nixLogDir;
38-
39-
protected:
40-
Store * open_local_store()
41-
{
4223
#ifdef _WIN32
4324
// no `mkdtemp` with MinGW
4425
auto tmpl = nix::defaultTempDir() + "/tests_nix-store.";
@@ -57,7 +38,26 @@ protected:
5738
nixStoreDir = nixDir + "/my_nix_store";
5839
nixStateDir = nixDir + "/my_state";
5940
nixLogDir = nixDir + "/my_log";
41+
};
6042

43+
~nix_api_store_test_base() override
44+
{
45+
if (exists(std::filesystem::path{nixDir})) {
46+
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
47+
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
48+
}
49+
std::filesystem::remove_all(nixDir);
50+
}
51+
}
52+
53+
std::string nixDir;
54+
std::string nixStoreDir;
55+
std::string nixStateDir;
56+
std::string nixLogDir;
57+
58+
protected:
59+
Store * open_local_store()
60+
{
6161
// Options documented in `nix help-stores`
6262
const char * p1[] = {"store", nixStoreDir.c_str()};
6363
const char * p2[] = {"state", nixStateDir.c_str()};

0 commit comments

Comments
 (0)