|
7 | 7 | #include "nix/store/store-api.hh"
|
8 | 8 | #include "nix/store/store-open.hh"
|
9 | 9 | #include "nix/store/build-result.hh"
|
| 10 | +#include "nix/store/build/derivation-builder.hh" |
| 11 | +#include "nix/store/build/derivation-env-desugar.hh" |
10 | 12 |
|
11 | 13 | #include "nix/store/globals.hh"
|
12 | 14 |
|
@@ -126,6 +128,28 @@ StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const c
|
126 | 128 | NIXC_CATCH_ERRS_NULL
|
127 | 129 | }
|
128 | 130 |
|
| 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 | + |
129 | 153 | nix_err nix_store_realise(
|
130 | 154 | nix_c_context * context,
|
131 | 155 | Store * store,
|
@@ -176,16 +200,18 @@ StorePath * nix_store_path_clone(const StorePath * p)
|
176 | 200 | return new StorePath{p->path};
|
177 | 201 | }
|
178 | 202 |
|
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) |
180 | 204 | {
|
181 | 205 | if (context)
|
182 | 206 | context->last_err_code = NIX_OK;
|
183 | 207 | 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)); |
187 | 211 |
|
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); |
189 | 215 |
|
190 | 216 | return new nix_derivation{drv};
|
191 | 217 | }
|
@@ -216,4 +242,135 @@ nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store
|
216 | 242 | NIXC_CATCH_ERRS
|
217 | 243 | }
|
218 | 244 |
|
| 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 | + |
219 | 376 | } // extern "C"
|
0 commit comments