1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 14:21:48 +02:00

Merge pull request #11940 from NixOS/c-api-libflake

C API: Add libflake-c
This commit is contained in:
Robert Hensing 2024-11-25 10:00:56 +01:00 committed by GitHub
commit 46b0f7755f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 522 additions and 25 deletions

View file

@ -23,7 +23,9 @@ jobs:
- uses: cachix/install-nix-action@v30 - uses: cachix/install-nix-action@v30
with: with:
# The sandbox would otherwise be disabled by default on Darwin # The sandbox would otherwise be disabled by default on Darwin
extra_nix_config: "sandbox = true" extra_nix_config: |
sandbox = true
max-jobs = 1
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v15 - uses: cachix/cachix-action@v15
if: needs.check_secrets.outputs.cachix == 'true' if: needs.check_secrets.outputs.cachix == 'true'

View file

@ -34,6 +34,7 @@ endif
subproject('libutil-c') subproject('libutil-c')
subproject('libstore-c') subproject('libstore-c')
subproject('libexpr-c') subproject('libexpr-c')
subproject('libflake-c')
subproject('libmain-c') subproject('libmain-c')
# Language Bindings # Language Bindings

View file

@ -44,6 +44,7 @@ in
nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { }; nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { };
nix-flake = callPackage ../src/libflake/package.nix { }; nix-flake = callPackage ../src/libflake/package.nix { };
nix-flake-c = callPackage ../src/libflake-c/package.nix { };
nix-flake-tests = callPackage ../src/libflake-tests/package.nix { }; nix-flake-tests = callPackage ../src/libflake-tests/package.nix { };
nix-main = callPackage ../src/libmain/package.nix { }; nix-main = callPackage ../src/libmain/package.nix { };

View file

@ -19,6 +19,7 @@
nix-expr-tests, nix-expr-tests,
nix-flake, nix-flake,
nix-flake-c,
nix-flake-tests, nix-flake-tests,
nix-main, nix-main,
@ -53,6 +54,7 @@ let
nix-expr-c nix-expr-c
nix-fetchers nix-fetchers
nix-flake nix-flake
nix-flake-c
nix-main nix-main
nix-main-c nix-main-c
nix-store nix-store
@ -86,6 +88,7 @@ let
"nix-expr-c" "nix-expr-c"
"nix-fetchers" "nix-fetchers"
"nix-flake" "nix-flake"
"nix-flake-c"
"nix-main" "nix-main"
"nix-main-c" "nix-main-c"
"nix-store" "nix-store"
@ -169,6 +172,7 @@ in
nix-expr nix-expr
nix-expr-c nix-expr-c
nix-flake nix-flake
nix-flake-c
nix-main nix-main
nix-main-c nix-main-c
; ;

View file

@ -40,6 +40,7 @@ GENERATE_LATEX = NO
INPUT = \ INPUT = \
@src@/src/libutil-c \ @src@/src/libutil-c \
@src@/src/libexpr-c \ @src@/src/libexpr-c \
@src@/src/libflake-c \
@src@/src/libstore-c \ @src@/src/libstore-c \
@src@/src/external-api-docs/README.md @src@/src/external-api-docs/README.md

View file

@ -30,6 +30,7 @@ mkMesonDerivation (finalAttrs: {
# Source is not compiled, but still must be available for Doxygen # Source is not compiled, but still must be available for Doxygen
# to gather comments. # to gather comments.
(cpp ../libexpr-c) (cpp ../libexpr-c)
(cpp ../libflake-c)
(cpp ../libstore-c) (cpp ../libstore-c)
(cpp ../libutil-c) (cpp ../libutil-c)
]; ];

View file

@ -6,6 +6,7 @@
#include "eval-gc.hh" #include "eval-gc.hh"
#include "globals.hh" #include "globals.hh"
#include "eval-settings.hh" #include "eval-settings.hh"
#include "ref.hh"
#include "nix_api_expr.h" #include "nix_api_expr.h"
#include "nix_api_expr_internal.h" #include "nix_api_expr_internal.h"
@ -18,6 +19,29 @@
# include <mutex> # include <mutex>
#endif #endif
/**
* @brief Allocate and initialize using self-reference
*
* This allows a brace initializer to reference the object being constructed.
*
* @warning Use with care, as the pointer points to an object that is not fully constructed yet.
*
* @tparam T Type to allocate
* @tparam F A function type for `init`, taking a T* and returning the initializer for T
* @param init Function that takes a T* and returns the initializer for T
* @return Pointer to allocated and initialized object
*/
template <typename T, typename F>
static T * unsafe_new_with_self(F && init)
{
// Allocate
void * p = ::operator new(
sizeof(T),
static_cast<std::align_val_t>(alignof(T)));
// Initialize with placement new
return new (p) T(init(static_cast<T *>(p)));
}
nix_err nix_libexpr_init(nix_c_context * context) nix_err nix_libexpr_init(nix_c_context * context)
{ {
if (context) if (context)
@ -93,7 +117,42 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_val
NIXC_CATCH_ERRS NIXC_CATCH_ERRS
} }
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store) nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store)
{
if (context)
context->last_err_code = NIX_OK;
try {
return unsafe_new_with_self<nix_eval_state_builder>([&](auto * self) {
return nix_eval_state_builder{
.store = nix::ref<nix::Store>(store->ptr),
.settings = nix::EvalSettings{/* &bool */ self->readOnlyMode},
.fetchSettings = nix::fetchers::Settings{},
.readOnlyMode = true,
};
});
}
NIXC_CATCH_ERRS_NULL
}
void nix_eval_state_builder_free(nix_eval_state_builder * builder)
{
delete builder;
}
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder)
{
if (context)
context->last_err_code = NIX_OK;
try {
// TODO: load in one go?
builder->settings.readOnlyMode = nix::settings.readOnlyMode;
loadConfFile(builder->settings);
loadConfFile(builder->fetchSettings);
}
NIXC_CATCH_ERRS
}
nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c)
{ {
if (context) if (context)
context->last_err_code = NIX_OK; context->last_err_code = NIX_OK;
@ -102,28 +161,47 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
if (lookupPath_c != nullptr) if (lookupPath_c != nullptr)
for (size_t i = 0; lookupPath_c[i] != nullptr; i++) for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
lookupPath.push_back(lookupPath_c[i]); lookupPath.push_back(lookupPath_c[i]);
builder->lookupPath = nix::LookupPath::parse(lookupPath);
}
NIXC_CATCH_ERRS
}
void * p = ::operator new( EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder)
sizeof(EvalState), {
static_cast<std::align_val_t>(alignof(EvalState))); if (context)
auto * p2 = static_cast<EvalState *>(p); context->last_err_code = NIX_OK;
new (p) EvalState { try {
.fetchSettings = nix::fetchers::Settings{}, return unsafe_new_with_self<EvalState>([&](auto * self) {
.settings = nix::EvalSettings{ return EvalState{
nix::settings.readOnlyMode, .fetchSettings = std::move(builder->fetchSettings),
}, .settings = std::move(builder->settings),
.state = nix::EvalState( .state = nix::EvalState(
nix::LookupPath::parse(lookupPath), builder->lookupPath,
store->ptr, builder->store,
p2->fetchSettings, self->fetchSettings,
p2->settings), self->settings),
}; };
loadConfFile(p2->settings); });
return p2;
} }
NIXC_CATCH_ERRS_NULL NIXC_CATCH_ERRS_NULL
} }
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
{
auto builder = nix_eval_state_builder_new(context, store);
if (builder == nullptr)
return nullptr;
if (nix_eval_state_builder_load(context, builder) != NIX_OK)
return nullptr;
if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c)
!= NIX_OK)
return nullptr;
return nix_eval_state_build(context, builder);
}
void nix_state_free(EvalState * state) void nix_state_free(EvalState * state)
{ {
delete state; delete state;

View file

@ -30,6 +30,11 @@ extern "C" {
// cffi start // cffi start
// Type definitions // Type definitions
/**
* @brief Builder for EvalState
*/
typedef struct nix_eval_state_builder nix_eval_state_builder;
/** /**
* @brief Represents a state of the Nix language evaluator. * @brief Represents a state of the Nix language evaluator.
* *
@ -174,12 +179,70 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value *
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value); nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);
/** /**
* @brief Create a new Nix language evaluator state. * @brief Create a new nix_eval_state_builder
*
* The settings are initialized to their default value.
* Values can be sourced elsewhere with nix_eval_state_builder_load.
*
* @param[out] context Optional, stores error information
* @param[in] store The Nix store to use.
* @return A new nix_eval_state_builder or NULL on failure.
*/
nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store);
/**
* @brief Read settings from the ambient environment
*
* Settings are sourced from environment variables and configuration files,
* as documented in the Nix manual.
*
* @param[out] context Optional, stores error information
* @param[out] builder The builder to modify.
* @return NIX_OK if successful, an error code otherwise.
*/
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder);
/**
* @brief Set the lookup path for `<...>` expressions
*
* @param[in] context Optional, stores error information
* @param[in] builder The builder to modify.
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
*/
nix_err nix_eval_state_builder_set_lookup_path(
nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath);
/**
* @brief Create a new Nix language evaluator state
*
* Remember to nix_eval_state_builder_free after building the state.
*
* @param[out] context Optional, stores error information
* @param[in] builder The builder to use and free
* @return A new Nix state or NULL on failure.
* @see nix_eval_state_builder_new, nix_eval_state_builder_free
*/
EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder);
/**
* @brief Free a nix_eval_state_builder
*
* Does not fail.
*
* @param[in] builder The builder to free.
*/
void nix_eval_state_builder_free(nix_eval_state_builder * builder);
/**
* @brief Create a new Nix language evaluator state
*
* For more control, use nix_eval_state_builder
* *
* @param[out] context Optional, stores error information * @param[out] context Optional, stores error information
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH. * @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
* @param[in] store The Nix store to use. * @param[in] store The Nix store to use.
* @return A new Nix state or NULL on failure. * @return A new Nix state or NULL on failure.
* @see nix_state_builder_new
*/ */
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store); EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);

View file

@ -6,6 +6,17 @@
#include "eval-settings.hh" #include "eval-settings.hh"
#include "attr-set.hh" #include "attr-set.hh"
#include "nix_api_value.h" #include "nix_api_value.h"
#include "search-path.hh"
struct nix_eval_state_builder
{
nix::ref<nix::Store> store;
nix::EvalSettings settings;
nix::fetchers::Settings fetchSettings;
nix::LookupPath lookupPath;
// TODO: make an EvalSettings setting own this instead?
bool readOnlyMode;
};
struct EvalState struct EvalState
{ {

View file

@ -213,7 +213,7 @@ nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_
/** @brief Get path as string /** @brief Get path as string
* @param[out] context Optional, stores error information * @param[out] context Optional, stores error information
* @param[in] value Nix value to inspect * @param[in] value Nix value to inspect
* @return string * @return string, if the type is NIX_TYPE_PATH
* @return NULL in case of error. * @return NULL in case of error.
*/ */
const char * nix_get_path_string(nix_c_context * context, const nix_value * value); const char * nix_get_path_string(nix_c_context * context, const nix_value * value);

View file

@ -7,12 +7,49 @@
#include "tests/nix_api_expr.hh" #include "tests/nix_api_expr.hh"
#include "tests/string_callback.hh" #include "tests/string_callback.hh"
#include "file-system.hh"
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
namespace nixC { namespace nixC {
TEST_F(nix_api_store_test, nix_eval_state_lookup_path)
{
auto tmpDir = nix::createTempDir();
auto delTmpDir = std::make_unique<nix::AutoDelete>(tmpDir, true);
auto nixpkgs = tmpDir + "/pkgs";
auto nixos = tmpDir + "/cfg";
std::filesystem::create_directories(nixpkgs);
std::filesystem::create_directories(nixos);
std::string nixpkgsEntry = "nixpkgs=" + nixpkgs;
std::string nixosEntry = "nixos-config=" + nixos;
const char * lookupPath[] = {nixpkgsEntry.c_str(), nixosEntry.c_str(), nullptr};
auto builder = nix_eval_state_builder_new(ctx, store);
assert_ctx_ok();
ASSERT_EQ(NIX_OK, nix_eval_state_builder_set_lookup_path(ctx, builder, lookupPath));
assert_ctx_ok();
auto state = nix_eval_state_build(ctx, builder);
assert_ctx_ok();
nix_eval_state_builder_free(builder);
Value * value = nix_alloc_value(ctx, state);
nix_expr_eval_from_string(ctx, state, "builtins.seq <nixos-config> <nixpkgs>", ".", value);
assert_ctx_ok();
ASSERT_EQ(nix_get_type(ctx, value), NIX_TYPE_PATH);
assert_ctx_ok();
auto pathStr = nix_get_path_string(ctx, value);
assert_ctx_ok();
ASSERT_EQ(0, strcmp(pathStr, nixpkgs.c_str()));
}
TEST_F(nix_api_expr_test, nix_expr_eval_from_string) TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
{ {
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value); nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);

1
src/libflake-c/.version Symbolic link
View file

@ -0,0 +1 @@
../../.version

View file

@ -0,0 +1 @@
../../build-utils-meson/

View file

@ -0,0 +1,93 @@
project('nix-flake-c', 'cpp',
version : files('.version'),
default_options : [
'cpp_std=c++2a',
# TODO(Qyriad): increase the warning level
'warning_level=1',
'debug=true',
'optimization=2',
'errorlogs=true', # Please print logs for tests that fail
],
meson_version : '>= 1.1',
license : 'LGPL-2.1-or-later',
)
cxx = meson.get_compiler('cpp')
subdir('build-utils-meson/deps-lists')
configdata = configuration_data()
deps_private_maybe_subproject = [
dependency('nix-util'),
dependency('nix-store'),
dependency('nix-expr'),
dependency('nix-flake'),
]
deps_public_maybe_subproject = [
dependency('nix-util-c'),
dependency('nix-store-c'),
dependency('nix-expr-c'),
]
subdir('build-utils-meson/subprojects')
# TODO rename, because it will conflict with downstream projects
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
config_h = configure_file(
configuration : configdata,
output : 'config-flake.h',
)
add_project_arguments(
# TODO(Qyriad): Yes this is how the autoconf+Make system did it.
# It would be nice for our headers to be idempotent instead.
# From C++ libraries, only for internals
'-include', 'config-util.hh',
'-include', 'config-store.hh',
'-include', 'config-expr.hh',
# not generated (yet?)
# '-include', 'config-flake.hh',
# From C libraries, for our public, installed headers too
'-include', 'config-util.h',
'-include', 'config-store.h',
'-include', 'config-expr.h',
'-include', 'config-flake.h',
language : 'cpp',
)
subdir('build-utils-meson/common')
sources = files(
'nix_api_flake.cc',
)
include_dirs = [include_directories('.')]
headers = [config_h] + files(
'nix_api_flake.h',
)
# TODO move this header to libexpr, maybe don't use it in tests?
headers += files('nix_api_flake.h')
subdir('build-utils-meson/export-all-symbols')
subdir('build-utils-meson/windows-version')
this_library = library(
'nixflakec',
sources,
dependencies : deps_public + deps_private + deps_other,
include_directories : include_dirs,
link_args: linker_export_flags,
prelink : true, # For C++ static initializers
install : true,
)
install_headers(headers, subdir : 'nix', preserve_path : true)
libraries_private = []
subdir('build-utils-meson/export')

View file

@ -0,0 +1,32 @@
#include "nix_api_flake.h"
#include "nix_api_flake_internal.hh"
#include "nix_api_util_internal.h"
#include "flake/flake.hh"
nix_flake_settings * nix_flake_settings_new(nix_c_context * context)
{
try {
auto settings = nix::make_ref<nix::flake::Settings>();
return new nix_flake_settings{settings};
}
NIXC_CATCH_ERRS_NULL
}
void nix_flake_settings_free(nix_flake_settings * settings)
{
delete settings;
}
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings)
{
static std::shared_ptr<nix::flake::Settings> registeredSettings;
try {
if (registeredSettings)
throw nix::Error("nix_flake_init_global already initialized");
registeredSettings = settings->settings;
nix::flake::initLib(*registeredSettings);
}
NIXC_CATCH_ERRS
}

View file

@ -0,0 +1,46 @@
#ifndef NIX_API_FLAKE_H
#define NIX_API_FLAKE_H
/** @defgroup libflake libflake
* @brief Bindings to the Nix Flakes library
*
* @{
*/
/** @file
* @brief Main entry for the libflake C bindings
*/
#include "nix_api_store.h"
#include "nix_api_util.h"
#include "nix_api_expr.h"
#ifdef __cplusplus
extern "C" {
#endif
// cffi start
typedef struct nix_flake_settings nix_flake_settings;
// Function prototypes
/**
* Create a nix_flake_settings initialized with default values.
* @param[out] context Optional, stores error information
* @return A new nix_flake_settings or NULL on failure.
* @see nix_flake_settings_free
*/
nix_flake_settings * nix_flake_settings_new(nix_c_context * context);
/**
* @brief Release the resources associated with a nix_flake_settings.
*/
void nix_flake_settings_free(nix_flake_settings * settings);
/**
* @brief Register Flakes support process-wide.
*/
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -0,0 +1,9 @@
#pragma once
#include "ref.hh"
#include "flake/settings.hh"
struct nix_flake_settings
{
nix::ref<nix::flake::Settings> settings;
};

View file

@ -0,0 +1,60 @@
{ lib
, stdenv
, mkMesonLibrary
, nix-store-c
, nix-expr-c
, nix-flake
# Configuration Options
, version
}:
let
inherit (lib) fileset;
in
mkMesonLibrary (finalAttrs: {
pname = "nix-flake-c";
inherit version;
workDir = ./.;
fileset = fileset.unions [
../../build-utils-meson
./build-utils-meson
../../.version
./.version
./meson.build
# ./meson.options
(fileset.fileFilter (file: file.hasExt "cc") ./.)
(fileset.fileFilter (file: file.hasExt "hh") ./.)
(fileset.fileFilter (file: file.hasExt "h") ./.)
];
propagatedBuildInputs = [
nix-expr-c
nix-store-c
nix-flake
];
preConfigure =
# "Inline" .version so it's not a symlink, and includes the suffix.
# Do the meson utils, without modification.
''
chmod u+w ./.version
echo ${version} > ../../.version
'';
mesonFlags = [
];
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
LDFLAGS = "-fuse-ld=gold";
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
};
})

View file

@ -19,6 +19,7 @@ subdir('build-utils-meson/deps-lists')
deps_private_maybe_subproject = [ deps_private_maybe_subproject = [
dependency('nix-expr-test-support'), dependency('nix-expr-test-support'),
dependency('nix-flake'), dependency('nix-flake'),
dependency('nix-flake-c'),
] ]
deps_public_maybe_subproject = [ deps_public_maybe_subproject = [
] ]
@ -46,6 +47,7 @@ subdir('build-utils-meson/common')
sources = files( sources = files(
'flakeref.cc', 'flakeref.cc',
'nix_api_flake.cc',
'url-name.cc', 'url-name.cc',
) )
@ -68,6 +70,7 @@ test(
this_exe, this_exe,
env : { env : {
'_NIX_TEST_UNIT_DATA': meson.current_source_dir() / 'data', '_NIX_TEST_UNIT_DATA': meson.current_source_dir() / 'data',
'NIX_CONFIG': 'extra-experimental-features = flakes',
}, },
protocol : 'gtest', protocol : 'gtest',
) )

View file

@ -0,0 +1,51 @@
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include "nix_api_util.h"
#include "nix_api_util_internal.h"
#include "nix_api_expr.h"
#include "nix_api_value.h"
#include "nix_api_flake.h"
#include "tests/nix_api_expr.hh"
#include "tests/string_callback.hh"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace nixC {
TEST_F(nix_api_store_test, nix_api_init_global_getFlake_exists)
{
nix_libstore_init(ctx);
assert_ctx_ok();
nix_libexpr_init(ctx);
assert_ctx_ok();
auto settings = nix_flake_settings_new(ctx);
assert_ctx_ok();
ASSERT_NE(nullptr, settings);
nix_flake_init_global(ctx, settings);
assert_ctx_ok();
nix_eval_state_builder * builder = nix_eval_state_builder_new(ctx, store);
ASSERT_NE(nullptr, builder);
assert_ctx_ok();
auto state = nix_eval_state_build(ctx, builder);
assert_ctx_ok();
ASSERT_NE(nullptr, state);
nix_eval_state_builder_free(builder);
auto value = nix_alloc_value(ctx, state);
assert_ctx_ok();
ASSERT_NE(nullptr, value);
nix_err err = nix_expr_eval_from_string(ctx, state, "builtins.getFlake", ".", value);
assert_ctx_ok();
ASSERT_EQ(NIX_OK, err);
ASSERT_EQ(NIX_TYPE_FUNCTION, nix_get_type(ctx, value));
}
} // namespace nixC

View file

@ -4,6 +4,7 @@
, mkMesonExecutable , mkMesonExecutable
, nix-flake , nix-flake
, nix-flake-c
, nix-expr-test-support , nix-expr-test-support
, rapidcheck , rapidcheck
@ -38,6 +39,7 @@ mkMesonExecutable (finalAttrs: {
buildInputs = [ buildInputs = [
nix-flake nix-flake
nix-flake-c
nix-expr-test-support nix-expr-test-support
rapidcheck rapidcheck
gtest gtest
@ -67,6 +69,7 @@ mkMesonExecutable (finalAttrs: {
mkdir -p "$HOME" mkdir -p "$HOME"
'' + '' '' + ''
export _NIX_TEST_UNIT_DATA=${resolvePath ./data} export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
export NIX_CONFIG="extra-experimental-features = flakes"
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage} ${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out touch $out
''); '');

View file

@ -40,7 +40,7 @@ void checkGTestWith(Testable && testable, MakeTestParams makeTestParams)
} else { } else {
std::ostringstream ss; std::ostringstream ss;
printResultMessage(result, ss); printResultMessage(result, ss);
FAIL() << ss.str() << std::endl; throw std::runtime_error(ss.str());
} }
} }
} }

View file

@ -26,14 +26,13 @@ protected:
inline void assert_ctx_ok() inline void assert_ctx_ok()
{ {
if (nix_err_code(ctx) == NIX_OK) { if (nix_err_code(ctx) == NIX_OK) {
return; return;
} }
unsigned int n; unsigned int n;
const char * p = nix_err_msg(nullptr, ctx, &n); const char * p = nix_err_msg(nullptr, ctx, &n);
std::string msg(p, n); std::string msg(p, n);
FAIL() << "nix_err_code(ctx) != NIX_OK, message: " << msg; throw std::runtime_error(std::string("nix_err_code(ctx) != NIX_OK, message: ") + msg);
} }
inline void assert_ctx_err() inline void assert_ctx_err()
@ -41,7 +40,7 @@ protected:
if (nix_err_code(ctx) != NIX_OK) { if (nix_err_code(ctx) != NIX_OK) {
return; return;
} }
FAIL() << "Got NIX_OK, but expected an error!"; throw std::runtime_error("Got NIX_OK, but expected an error!");
} }
}; };