diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build index 727f4e14d..07747e0a3 100644 --- a/src/libcmd/meson.build +++ b/src/libcmd/meson.build @@ -44,27 +44,18 @@ if readline_flavor == 'editline' elif readline_flavor == 'readline' readline = dependency('readline') deps_private += readline - configdata.set( - 'USE_READLINE', - 1, - description: 'Use readline instead of editline', - ) else error('illegal editline flavor', readline_flavor) endif - -config_h = configure_file( - configuration : configdata, - output : 'cmd-config-private.hh', +configdata.set( + 'USE_READLINE', + (readline_flavor == 'readline').to_int(), + description: 'Use readline instead of editline', ) -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - language : 'cpp', +config_priv_h = configure_file( + configuration : configdata, + output : 'cmd-config-private.hh', ) subdir('nix-meson-build-support/common') @@ -96,7 +87,7 @@ subdir('nix-meson-build-support/windows-version') this_library = library( 'nixcmd', sources, - config_h, + config_priv_h, dependencies : deps_public + deps_private + deps_other, include_directories : include_dirs, link_args: linker_export_flags, diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc index 773e111b2..093cc2b29 100644 --- a/src/libcmd/repl-interacter.cc +++ b/src/libcmd/repl-interacter.cc @@ -2,7 +2,7 @@ #include -#ifdef USE_READLINE +#if USE_READLINE #include #include #else @@ -37,7 +37,7 @@ void sigintHandler(int signo) static detail::ReplCompleterMixin * curRepl; // ugly -#ifndef USE_READLINE +#if !USE_READLINE static char * completionCallback(char * s, int * match) { auto possible = curRepl->completePrefix(s); @@ -115,14 +115,14 @@ ReadlineLikeInteracter::Guard ReadlineLikeInteracter::init(detail::ReplCompleter } catch (SystemError & e) { logWarning(e.info()); } -#ifndef USE_READLINE +#if !USE_READLINE el_hist_size = 1000; #endif read_history(historyFile.c_str()); auto oldRepl = curRepl; curRepl = repl; Guard restoreRepl([oldRepl] { curRepl = oldRepl; }); -#ifndef USE_READLINE +#if !USE_READLINE rl_set_complete_func(completionCallback); rl_set_list_possib_func(listPossibleCallback); #endif @@ -185,7 +185,7 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT // quite useful for reading the test output, so we add it here. if (auto e = getEnv("_NIX_TEST_REPL_ECHO"); s && e && *e == "1") { -#ifndef USE_READLINE +#if !USE_READLINE // This is probably not right for multi-line input, but we don't use that // in the characterisation tests, so it's fine. std::cout << promptForType(promptType) << s << std::endl; diff --git a/src/libexpr-c/meson.build b/src/libexpr-c/meson.build index 8b00b8d70..7c11ca9cb 100644 --- a/src/libexpr-c/meson.build +++ b/src/libexpr-c/meson.build @@ -25,18 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('nix-meson-build-support/subprojects') -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', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libexpr-c/nix_api_expr.cc b/src/libexpr-c/nix_api_expr.cc index b5d2c6199..47eca4e65 100644 --- a/src/libexpr-c/nix_api_expr.cc +++ b/src/libexpr-c/nix_api_expr.cc @@ -15,7 +15,7 @@ #include "nix_api_util.h" #include "nix_api_util_internal.h" -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC # include #endif @@ -207,7 +207,7 @@ void nix_state_free(EvalState * state) delete state; } -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC std::unordered_map< const void *, unsigned int, @@ -283,7 +283,7 @@ nix_err nix_value_decref(nix_c_context * context, nix_value *x) void nix_gc_register_finalizer(void * obj, void * cd, void (*finalizer)(void * obj, void * cd)) { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC GC_REGISTER_FINALIZER(obj, finalizer, cd, 0, 0); #endif } diff --git a/src/libexpr-c/nix_api_external.cc b/src/libexpr-c/nix_api_external.cc index 7f4cd6a8c..ab124b73b 100644 --- a/src/libexpr-c/nix_api_external.cc +++ b/src/libexpr-c/nix_api_external.cc @@ -168,7 +168,7 @@ ExternalValue * nix_create_external_value(nix_c_context * context, NixCExternalV context->last_err_code = NIX_OK; try { auto ret = new -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC (GC) #endif NixCExternalValue(*desc, v); diff --git a/src/libexpr-c/nix_api_value.cc b/src/libexpr-c/nix_api_value.cc index 3116cb59f..4c2fdee42 100644 --- a/src/libexpr-c/nix_api_value.cc +++ b/src/libexpr-c/nix_api_value.cc @@ -125,7 +125,7 @@ PrimOp * nix_alloc_primop( try { using namespace std::placeholders; auto p = new -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC (GC) #endif nix::PrimOp{ @@ -497,7 +497,7 @@ ListBuilder * nix_make_list_builder(nix_c_context * context, EvalState * state, try { auto builder = state->state.buildList(capacity); return new -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC (NoGC) #endif ListBuilder{std::move(builder)}; @@ -519,7 +519,7 @@ nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, uns void nix_list_builder_free(ListBuilder * list_builder) { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC GC_FREE(list_builder); #else delete list_builder; @@ -578,7 +578,7 @@ BindingsBuilder * nix_make_bindings_builder(nix_c_context * context, EvalState * try { auto bb = state->state.buildBindings(capacity); return new -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC (NoGC) #endif BindingsBuilder{std::move(bb)}; @@ -600,7 +600,7 @@ nix_err nix_bindings_builder_insert(nix_c_context * context, BindingsBuilder * b void nix_bindings_builder_free(BindingsBuilder * bb) { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC GC_FREE((nix::BindingsBuilder *) bb); #else delete (nix::BindingsBuilder *) bb; diff --git a/src/libexpr-test-support/meson.build b/src/libexpr-test-support/meson.build index b68adb2c2..3409dbf20 100644 --- a/src/libexpr-test-support/meson.build +++ b/src/libexpr-test-support/meson.build @@ -29,15 +29,6 @@ subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libexpr-tests/meson.build b/src/libexpr-tests/meson.build index 3fc726cb2..f7822edfd 100644 --- a/src/libexpr-tests/meson.build +++ b/src/libexpr-tests/meson.build @@ -35,13 +35,12 @@ deps_private += gtest gtest = dependency('gmock') deps_private += gtest -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - language : 'cpp', +configdata = configuration_data() +configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) + +config_priv_h = configure_file( + configuration : configdata, + output : 'expr-tests-config.hh', ) subdir('nix-meson-build-support/common') @@ -69,6 +68,7 @@ include_dirs = [include_directories('.')] this_exe = executable( meson.project_name(), sources, + config_priv_h, dependencies : deps_private_subproject + deps_private + deps_other, include_directories : include_dirs, # TODO: -lrapidcheck, see ../libutil-support/build.meson diff --git a/src/libexpr-tests/nix_api_expr.cc b/src/libexpr-tests/nix_api_expr.cc index 903c7a239..55893488f 100644 --- a/src/libexpr-tests/nix_api_expr.cc +++ b/src/libexpr-tests/nix_api_expr.cc @@ -12,6 +12,8 @@ #include #include +#include "expr-tests-config.hh" + namespace nixC { TEST_F(nix_api_store_test, nix_eval_state_lookup_path) diff --git a/src/libexpr/eval-gc.cc b/src/libexpr/eval-gc.cc index defa4e9d2..1166548f6 100644 --- a/src/libexpr/eval-gc.cc +++ b/src/libexpr/eval-gc.cc @@ -5,7 +5,9 @@ #include "nix/serialise.hh" #include "nix/eval-gc.hh" -#if HAVE_BOEHMGC +#include "expr-config-private.hh" + +#if NIX_USE_BOEHMGC # include # if __FreeBSD__ @@ -24,7 +26,7 @@ namespace nix { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC /* Called when the Boehm GC runs out of memory. */ static void * oomHandler(size_t requested) { @@ -94,7 +96,7 @@ void initGC() if (gcInitialised) return; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC initGCReal(); gcCyclesAfterInit = GC_get_gc_no(); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index f534cc494..41b64a90a 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -295,7 +295,7 @@ EvalState::EvalState( , debugStop(false) , trylevel(0) , regexCache(makeRegexCache()) -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC , valueAllocCache(std::allocate_shared(traceable_allocator(), nullptr)) , env1AllocCache(std::allocate_shared(traceable_allocator(), nullptr)) , baseEnvP(std::allocate_shared(traceable_allocator(), &allocEnv(BASE_ENV_SIZE))) @@ -2812,7 +2812,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v } bool EvalState::fullGC() { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC GC_gcollect(); // Check that it ran. We might replace this with a version that uses more // of the boehm API to get this reliably, at a maintenance cost. @@ -2831,7 +2831,7 @@ void EvalState::maybePrintStats() if (showStats) { // Make the final heap size more deterministic. -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC if (!fullGC()) { warn("failed to perform a full GC before reporting stats"); } @@ -2853,7 +2853,7 @@ void EvalState::printStatistics() uint64_t bValues = nrValues * sizeof(Value); uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr); -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC GC_word heapSize, totalBytes; GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes); double gcFullOnlyTime = ({ @@ -2875,7 +2875,7 @@ void EvalState::printStatistics() #ifndef _WIN32 // TODO implement {"cpu", cpuTime}, #endif -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC {GC_is_incremental_mode() ? "gcNonIncremental" : "gc", gcFullOnlyTime}, #ifndef _WIN32 // TODO implement {GC_is_incremental_mode() ? "gcNonIncrementalFraction" : "gcFraction", gcFullOnlyTime / cpuTime}, @@ -2919,7 +2919,7 @@ void EvalState::printStatistics() topObj["nrLookups"] = nrLookups; topObj["nrPrimOpCalls"] = nrPrimOpCalls; topObj["nrFunctionCalls"] = nrFunctionCalls; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC topObj["gc"] = { {"heapSize", heapSize}, {"totalBytes", totalBytes}, diff --git a/src/libexpr/include/nix/eval-gc.hh b/src/libexpr/include/nix/eval-gc.hh index f3b699b54..8f28fe0e2 100644 --- a/src/libexpr/include/nix/eval-gc.hh +++ b/src/libexpr/include/nix/eval-gc.hh @@ -3,7 +3,10 @@ #include -#if HAVE_BOEHMGC +// For `NIX_USE_BOEHMGC`, and if that's set, `GC_THREADS` +#include "nix/expr-config.hh" + +#if NIX_USE_BOEHMGC # define GC_INCLUDE_NEW @@ -43,7 +46,7 @@ void initGC(); */ void assertGCInitialized(); -#ifdef HAVE_BOEHMGC +#if NIX_USE_BOEHMGC /** * The number of GC cycles since initGC(). */ diff --git a/src/libexpr/include/nix/eval-inline.hh b/src/libexpr/include/nix/eval-inline.hh index c00b06006..09a85db06 100644 --- a/src/libexpr/include/nix/eval-inline.hh +++ b/src/libexpr/include/nix/eval-inline.hh @@ -6,6 +6,9 @@ #include "nix/eval-error.hh" #include "nix/eval-settings.hh" +// For `NIX_USE_BOEHMGC`, and if that's set, `GC_THREADS` +#include "nix/expr-config.hh" + namespace nix { /** @@ -15,7 +18,7 @@ namespace nix { inline void * allocBytes(size_t n) { void * p; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC p = GC_MALLOC(n); #else p = calloc(n, 1); @@ -28,7 +31,7 @@ inline void * allocBytes(size_t n) [[gnu::always_inline]] Value * EvalState::allocValue() { -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC /* We use the boehm batch allocator to speed up allocations of Values (of which there are many). GC_malloc_many returns a linked list of objects of the given size, where the first word of each object is also the pointer to the next object in the list. This also means that we @@ -60,7 +63,7 @@ Env & EvalState::allocEnv(size_t size) Env * env; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC if (size == 1) { /* see allocValue for explanations. */ if (!*env1AllocCache) { diff --git a/src/libexpr/include/nix/eval.hh b/src/libexpr/include/nix/eval.hh index 42091b9ba..7a3ec065d 100644 --- a/src/libexpr/include/nix/eval.hh +++ b/src/libexpr/include/nix/eval.hh @@ -16,6 +16,9 @@ #include "nix/repl-exit-status.hh" #include "nix/ref.hh" +// For `NIX_USE_BOEHMGC`, and if that's set, `GC_THREADS` +#include "nix/expr-config.hh" + #include #include #include @@ -369,7 +372,7 @@ private: */ std::shared_ptr regexCache; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC /** * Allocation cache for GC'd Value objects. */ @@ -596,7 +599,7 @@ public: */ SingleDerivedPath coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx); -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC /** A GC root for the baseEnv reference. */ std::shared_ptr baseEnvP; #endif diff --git a/src/libexpr/include/nix/meson.build b/src/libexpr/include/nix/meson.build index d712cc798..89422004a 100644 --- a/src/libexpr/include/nix/meson.build +++ b/src/libexpr/include/nix/meson.build @@ -2,12 +2,12 @@ include_dirs = [include_directories('..')] -config_h = configure_file( - configuration : configdata, - output : 'config-expr.hh', +config_pub_h = configure_file( + configuration : configdata_pub, + output : 'expr-config.hh', ) -headers = [config_h] + files( +headers = [config_pub_h] + files( 'attr-path.hh', 'attr-set.hh', 'eval-cache.hh', diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 3fd4dca7f..02873f4db 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -14,7 +14,8 @@ cxx = meson.get_compiler('cpp') subdir('nix-meson-build-support/deps-lists') -configdata = configuration_data() +configdata_pub = configuration_data() +configdata_priv = configuration_data() deps_private_maybe_subproject = [ ] @@ -26,6 +27,16 @@ deps_public_maybe_subproject = [ subdir('nix-meson-build-support/subprojects') subdir('nix-meson-build-support/big-objs') +# Check for each of these functions, and create a define like `#define HAVE_LCHOWN 1`. +check_funcs = [ + 'sysconf', +] +foreach funcspec : check_funcs + define_name = 'HAVE_' + funcspec.underscorify().to_upper() + define_value = cxx.has_function(funcspec).to_int() + configdata_priv.set(define_name, define_value) +endforeach + boost = dependency( 'boost', modules : ['container', 'context'], @@ -47,11 +58,13 @@ if bdw_gc.found() ] define_name = 'HAVE_' + funcspec.underscorify().to_upper() define_value = cxx.has_function(funcspec).to_int() - configdata.set(define_name, define_value) + configdata_priv.set(define_name, define_value) endforeach - configdata.set('GC_THREADS', 1) + # Affects ABI, because it changes what bdw_gc itself does! + configdata_pub.set('GC_THREADS', 1) endif -configdata.set('HAVE_BOEHMGC', bdw_gc.found().to_int()) +# Used in public header. Affects ABI! +configdata_pub.set('NIX_USE_BOEHMGC', bdw_gc.found().to_int()) toml11 = dependency( 'toml11', @@ -61,14 +74,9 @@ toml11 = dependency( ) deps_other += toml11 -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - # '-include', 'nix_api_fetchers_config.h', - '-include', 'nix/config-expr.hh', - language : 'cpp', +config_priv_h = configure_file( + configuration : configdata_priv, + output : 'expr-config-private.hh', ) subdir('nix-meson-build-support/common') @@ -158,6 +166,7 @@ subdir('nix-meson-build-support/windows-version') this_library = library( 'nixexpr', sources, + config_priv_h, parser_tab, lexer_tab, generated_headers, diff --git a/src/libfetchers-tests/meson.build b/src/libfetchers-tests/meson.build index 80f99c859..12b748e65 100644 --- a/src/libfetchers-tests/meson.build +++ b/src/libfetchers-tests/meson.build @@ -34,15 +34,6 @@ deps_private += gtest libgit2 = dependency('libgit2') deps_private += libgit2 -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - # '-include', 'nix_api_fetchers_config.h', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libfetchers/meson.build b/src/libfetchers/meson.build index aaf52ff74..14a2647d5 100644 --- a/src/libfetchers/meson.build +++ b/src/libfetchers/meson.build @@ -30,15 +30,6 @@ deps_public += nlohmann_json libgit2 = dependency('libgit2') deps_private += libgit2 -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - # '-include', 'nix_api_fetchers_config.h', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libflake-c/meson.build b/src/libflake-c/meson.build index ec754dfaa..fd3cdd01b 100644 --- a/src/libflake-c/meson.build +++ b/src/libflake-c/meson.build @@ -27,20 +27,6 @@ deps_public_maybe_subproject = [ ] subdir('nix-meson-build-support/subprojects') -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', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - # not generated (yet?) - # '-include', 'nix/config-flake.hh', - - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libflake-tests/meson.build b/src/libflake-tests/meson.build index 4012582f2..593b0e18d 100644 --- a/src/libflake-tests/meson.build +++ b/src/libflake-tests/meson.build @@ -32,15 +32,6 @@ deps_private += rapidcheck gtest = dependency('gtest', main : true) deps_private += gtest -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libflake/meson.build b/src/libflake/meson.build index e231de9c1..de880c28d 100644 --- a/src/libflake/meson.build +++ b/src/libflake/meson.build @@ -27,16 +27,6 @@ subdir('nix-meson-build-support/subprojects') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') deps_public += nlohmann_json -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - # '-include', 'nix_api_fetchers_config.h', - '-include', 'nix/config-expr.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') subdir('nix-meson-build-support/generate-header') diff --git a/src/libmain-c/meson.build b/src/libmain-c/meson.build index 0229ef86b..e420520e6 100644 --- a/src/libmain-c/meson.build +++ b/src/libmain-c/meson.build @@ -25,17 +25,6 @@ deps_public_maybe_subproject = [ ] subdir('nix-meson-build-support/subprojects') -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', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libmain/include/nix/meson.build b/src/libmain/include/nix/meson.build index 8584b9042..e29981d3f 100644 --- a/src/libmain/include/nix/meson.build +++ b/src/libmain/include/nix/meson.build @@ -2,12 +2,7 @@ include_dirs = [include_directories('..')] -config_h = configure_file( - configuration : configdata, - output : 'config-main.hh', -) - -headers = [config_h] + files( +headers = files( 'common-args.hh', 'loggers.hh', 'plugin.hh', diff --git a/src/libmain/meson.build b/src/libmain/meson.build index 08b0bdb4f..f7ff93b66 100644 --- a/src/libmain/meson.build +++ b/src/libmain/meson.build @@ -42,13 +42,9 @@ configdata.set( description: 'Optionally used for buffering on standard error' ) -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-main.hh', - language : 'cpp', +config_priv_h = configure_file( + configuration : configdata, + output : 'main-config-private.hh', ) subdir('nix-meson-build-support/common') @@ -75,7 +71,7 @@ subdir('nix-meson-build-support/windows-version') this_library = library( 'nixmain', sources, - config_h, + config_priv_h, dependencies : deps_public + deps_private + deps_other, include_directories : include_dirs, link_args: linker_export_flags, diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 639977efc..0643e20ed 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -25,6 +25,8 @@ #include "nix/exit.hh" #include "nix/strings.hh" +#include "main-config-private.hh" + namespace nix { char * * savedArgv; @@ -297,7 +299,7 @@ void printVersion(const std::string & programName) std::cout << fmt("%1% (Nix) %2%", programName, nixVersion) << std::endl; if (verbosity > lvlInfo) { Strings cfg; -#if HAVE_BOEHMGC +#if NIX_USE_BOEHMGC cfg.push_back("gc"); #endif cfg.push_back("signed-caches"); diff --git a/src/libstore-c/meson.build b/src/libstore-c/meson.build index f7e192f3a..eb5563161 100644 --- a/src/libstore-c/meson.build +++ b/src/libstore-c/meson.build @@ -23,17 +23,6 @@ deps_public_maybe_subproject = [ ] subdir('nix-meson-build-support/subprojects') -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', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libstore-test-support/meson.build b/src/libstore-test-support/meson.build index c7d9689bf..a1f6777e4 100644 --- a/src/libstore-test-support/meson.build +++ b/src/libstore-test-support/meson.build @@ -27,14 +27,6 @@ subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libstore-tests/meson.build b/src/libstore-tests/meson.build index 0dcfeaacd..1822a3520 100644 --- a/src/libstore-tests/meson.build +++ b/src/libstore-tests/meson.build @@ -37,17 +37,17 @@ deps_private += rapidcheck gtest = dependency('gtest', main : true) deps_private += gtest +configdata = configuration_data() +configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) + +config_priv_h = configure_file( + configuration : configdata, + output : 'store-tests-config.hh', +) + gtest = dependency('gmock') deps_private += gtest -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( @@ -84,6 +84,7 @@ include_dirs = [include_directories('.')] this_exe = executable( meson.project_name(), sources, + config_priv_h, dependencies : deps_private_subproject + deps_private + deps_other, include_directories : include_dirs, # TODO: -lrapidcheck, see ../libutil-support/build.meson diff --git a/src/libstore-tests/nix_api_store.cc b/src/libstore-tests/nix_api_store.cc index b7d9860fb..293547c95 100644 --- a/src/libstore-tests/nix_api_store.cc +++ b/src/libstore-tests/nix_api_store.cc @@ -6,6 +6,8 @@ #include "nix/tests/nix_api_store.hh" #include "nix/tests/string_callback.hh" +#include "store-tests-config.hh" + namespace nixC { std::string PATH_SUFFIX = "/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-name"; diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 81294a5b9..43b5c7891 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -6,6 +6,8 @@ #include "nix/signals.hh" #include "nix/posix-fs-canonicalise.hh" +#include "store-config-private.hh" + #if !defined(__linux__) // For shelling out to lsof # include "nix/processes.hh" diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 4f8c53ca8..70feaf311 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -6,6 +6,7 @@ #include "nix/abstract-setting-to-json.hh" #include "nix/compute-levels.hh" #include "nix/signals.hh" +#include "nix/strings.hh" #include #include @@ -35,7 +36,8 @@ #include #endif -#include "nix/strings.hh" +#include "store-config-private.hh" + namespace nix { @@ -202,7 +204,7 @@ StringSet Settings::getDefaultExtraPlatforms() { StringSet extraPlatforms; - if (std::string{SYSTEM} == "x86_64-linux" && !isWSL1()) + if (std::string{NIX_LOCAL_SYSTEM} == "x86_64-linux" && !isWSL1()) extraPlatforms.insert("i686-linux"); #if __linux__ @@ -214,7 +216,7 @@ StringSet Settings::getDefaultExtraPlatforms() // machines. Note that we can’t force processes from executing // x86_64 in aarch64 environments or vice versa since they can // always exec with their own binary preferences. - if (std::string{SYSTEM} == "aarch64-darwin" && + if (std::string{NIX_LOCAL_SYSTEM} == "aarch64-darwin" && runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0) extraPlatforms.insert("x86_64-darwin"); #endif diff --git a/src/libstore/include/nix/globals.hh b/src/libstore/include/nix/globals.hh index bda883890..1630c0ae7 100644 --- a/src/libstore/include/nix/globals.hh +++ b/src/libstore/include/nix/globals.hh @@ -1,16 +1,18 @@ #pragma once ///@file +#include +#include + +#include + #include "nix/types.hh" #include "nix/config.hh" #include "nix/environment-variables.hh" #include "nix/experimental-features.hh" #include "nix/users.hh" -#include -#include - -#include +#include "nix/store-config.hh" namespace nix { @@ -181,7 +183,7 @@ public: bool readOnlyMode = false; Setting thisSystem{ - this, SYSTEM, "system", + this, NIX_LOCAL_SYSTEM, "system", R"( The system type of the current Nix installation. Nix will only build a given [store derivation](@docroot@/glossary.md#gloss-store-derivation) locally when its `system` attribute equals any of the values specified here or in [`extra-platforms`](#conf-extra-platforms). @@ -1089,7 +1091,7 @@ public: )"}; #endif -#if HAVE_ACL_SUPPORT +#if NIX_SUPPORT_ACL Setting ignoredAcls{ this, {"security.selinux", "system.nfs4_acl", "security.csm"}, "ignored-acls", R"( diff --git a/src/libstore/include/nix/meson.build b/src/libstore/include/nix/meson.build index 85ea75685..d29efe50e 100644 --- a/src/libstore/include/nix/meson.build +++ b/src/libstore/include/nix/meson.build @@ -4,12 +4,12 @@ include_dirs = [ include_directories('..'), ] -config_h = configure_file( - configuration : configdata, - output : 'config-store.hh', +config_pub_h = configure_file( + configuration : configdata_pub, + output : 'store-config.hh', ) -headers = [config_h] + files( +headers = [config_pub_h] + files( 'binary-cache-store.hh', 'build-result.hh', 'build/derivation-goal.hh', diff --git a/src/libstore/linux/include/nix/fchmodat2-compat.hh b/src/libstore/linux/include/nix/fchmodat2-compat.hh index fd03b9ed5..42b3f3a35 100644 --- a/src/libstore/linux/include/nix/fchmodat2-compat.hh +++ b/src/libstore/linux/include/nix/fchmodat2-compat.hh @@ -1,3 +1,5 @@ +#include "store-config-private.hh" + /* * Determine the syscall number for `fchmodat2`. * diff --git a/src/libstore/linux/personality.cc b/src/libstore/linux/personality.cc index bbff765de..452bd3e4b 100644 --- a/src/libstore/linux/personality.cc +++ b/src/libstore/linux/personality.cc @@ -15,7 +15,7 @@ void setPersonality(std::string_view system) struct utsname utsbuf; uname(&utsbuf); if ((system == "i686-linux" - && (std::string_view(SYSTEM) == "x86_64-linux" + && (std::string_view(NIX_LOCAL_SYSTEM) == "x86_64-linux" || (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) || system == "armv7l-linux" || system == "armv6l-linux" diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index cf6644804..7d4f8e5c7 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -54,6 +54,8 @@ #include "nix/strings.hh" +#include "store-config-private.hh" + namespace nix { diff --git a/src/libstore/meson.build b/src/libstore/meson.build index dd6d7b404..b558c3bc9 100644 --- a/src/libstore/meson.build +++ b/src/libstore/meson.build @@ -15,12 +15,20 @@ cxx = meson.get_compiler('cpp') subdir('nix-meson-build-support/deps-lists') -configdata = configuration_data() +configdata_pub = configuration_data() +configdata_priv = configuration_data() # TODO rename, because it will conflict with downstream projects -configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) +configdata_priv.set_quoted('PACKAGE_VERSION', meson.project_version()) -configdata.set_quoted('SYSTEM', host_machine.cpu_family() + '-' + host_machine.system()) +# Used in public header. +configdata_pub.set_quoted( + 'NIX_LOCAL_SYSTEM', + host_machine.cpu_family() + '-' + host_machine.system(), + description : + 'This is the system name Nix expects for local running instance of Nix.\n\n' + + 'See the "system" setting for additional details', +) deps_private_maybe_subproject = [ ] @@ -47,28 +55,30 @@ run_command('rm', '-f', check : true, ) summary('can hardlink to symlink', can_link_symlink, bool_yn : true) -configdata.set('CAN_LINK_SYMLINK', can_link_symlink.to_int()) +configdata_priv.set('CAN_LINK_SYMLINK', can_link_symlink.to_int()) # Check for each of these functions, and create a define like `#define HAVE_LCHOWN 1`. -# -# Only need to do functions that deps (like `libnixutil`) didn't already -# check for. check_funcs = [ # Optionally used for canonicalising files from the build 'lchown', + 'posix_fallocate', 'statvfs', ] foreach funcspec : check_funcs define_name = 'HAVE_' + funcspec.underscorify().to_upper() define_value = cxx.has_function(funcspec).to_int() - configdata.set(define_name, define_value) + configdata_priv.set(define_name, define_value) endforeach has_acl_support = cxx.has_header('sys/xattr.h') \ and cxx.has_function('llistxattr') \ and cxx.has_function('lremovexattr') -# TODO: used in header - make proper public header and make sure it's included. Affects ABI! -configdata.set('HAVE_ACL_SUPPORT', has_acl_support.to_int()) +# Used in public header. Affects ABI! +configdata_pub.set( + 'NIX_SUPPORT_ACL', + has_acl_support.to_int(), + description : 'FIXME: It\'s a bit peculiar that this needs to be exposed. The reason is that that it effects whether the settings struct in a header has a particular field. This is also odd, because it means when there is no ACL support one will just get an "unknown setting" warning from their configuration.', +) if host_machine.system() == 'darwin' sandbox = cxx.find_library('sandbox') @@ -104,7 +114,7 @@ seccomp = dependency('libseccomp', 'seccomp', required : seccomp_required, versi if is_linux and not seccomp.found() warning('Sandbox security is reduced because libseccomp has not been found! Please provide libseccomp if it supports your CPU architecture.') endif -configdata.set('HAVE_SECCOMP', seccomp.found().to_int()) +configdata_priv.set('HAVE_SECCOMP', seccomp.found().to_int()) deps_private += seccomp nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') @@ -116,7 +126,7 @@ deps_private += sqlite # AWS C++ SDK has bad pkg-config. See # https://github.com/aws/aws-sdk-cpp/issues/2673 for details. aws_s3 = dependency('aws-cpp-sdk-s3', required : false) -configdata.set('ENABLE_S3', aws_s3.found().to_int()) +configdata_priv.set('ENABLE_S3', aws_s3.found().to_int()) if aws_s3.found() aws_s3 = declare_dependency( include_directories: include_directories(aws_s3.get_variable('includedir')), @@ -148,7 +158,7 @@ if get_option('embedded-sandbox-shell') # The path to busybox is passed as a -D flag when compiling this_library. # This solution is inherited from the old make buildsystem # TODO: do this differently? - configdata.set('HAVE_EMBEDDED_SANDBOX_SHELL', 1) + configdata_priv.set('HAVE_EMBEDDED_SANDBOX_SHELL', 1) hexdump = find_program('hexdump', native : true) embedded_sandbox_shell_gen = custom_target( 'embedded-sandbox-shell.gen.hh', @@ -166,12 +176,9 @@ if get_option('embedded-sandbox-shell') generated_headers += embedded_sandbox_shell_gen endif -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - language : 'cpp', +config_priv_h = configure_file( + configuration : configdata_priv, + output : 'store-config-private.hh', ) subdir('nix-meson-build-support/common') @@ -346,6 +353,7 @@ this_library = library( 'nixstore', generated_headers, sources, + config_priv_h, dependencies : deps_public + deps_private + deps_other, include_directories : include_dirs, cpp_args : cpp_args, diff --git a/src/libstore/posix-fs-canonicalise.cc b/src/libstore/posix-fs-canonicalise.cc index 5fddae42f..c1b451324 100644 --- a/src/libstore/posix-fs-canonicalise.cc +++ b/src/libstore/posix-fs-canonicalise.cc @@ -1,13 +1,16 @@ -#if HAVE_ACL_SUPPORT -# include -#endif - #include "nix/posix-fs-canonicalise.hh" #include "nix/file-system.hh" #include "nix/signals.hh" #include "nix/util.hh" #include "nix/globals.hh" #include "nix/store-api.hh" +#include "nix/store-config.hh" + +#include "store-config-private.hh" + +#if NIX_SUPPORT_ACL +# include +#endif namespace nix { @@ -72,7 +75,7 @@ static void canonicalisePathMetaData_( if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) throw Error("file '%1%' has an unsupported type", path); -#if HAVE_ACL_SUPPORT +#if NIX_SUPPORT_ACL /* Remove extended attributes / ACLs. */ ssize_t eaSize = llistxattr(path.c_str(), nullptr, 0); diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc index 74186242b..afffe8e71 100644 --- a/src/libstore/unix/build/local-derivation-goal.cc +++ b/src/libstore/unix/build/local-derivation-goal.cc @@ -19,6 +19,7 @@ #include "nix/unix-domain-socket.hh" #include "nix/posix-fs-canonicalise.hh" #include "nix/posix-source-accessor.hh" +#include "nix/store-config.hh" #include #include @@ -31,6 +32,8 @@ #include #include +#include "store-config-private.hh" + #if HAVE_STATVFS #include #endif @@ -1701,7 +1704,7 @@ void setupSeccomp() seccomp_release(ctx); }); - constexpr std::string_view nativeSystem = SYSTEM; + constexpr std::string_view nativeSystem = NIX_LOCAL_SYSTEM; if (nativeSystem == "x86_64-linux" && seccomp_arch_add(ctx, SCMP_ARCH_X86) != 0) diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index cd53bc585..3414a6d31 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -25,21 +25,11 @@ subdir('nix-meson-build-support/subprojects') configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) -config_h = configure_file( +config_priv_h = configure_file( configuration : configdata, output : 'nix_api_util_config.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', 'nix/config-util.hh', - - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( @@ -61,7 +51,7 @@ subdir('nix-meson-build-support/windows-version') this_library = library( 'nixutilc', sources, - config_h, + config_priv_h, dependencies : deps_public + deps_private + deps_other, include_directories : include_dirs, link_args: linker_export_flags, diff --git a/src/libutil-test-support/meson.build b/src/libutil-test-support/meson.build index f235af9eb..265bdc249 100644 --- a/src/libutil-test-support/meson.build +++ b/src/libutil-test-support/meson.build @@ -25,13 +25,6 @@ subdir('nix-meson-build-support/subprojects') rapidcheck = dependency('rapidcheck') deps_public += rapidcheck -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. - '-include', 'nix/config-util.hh', - language : 'cpp', -) - subdir('nix-meson-build-support/common') sources = files( diff --git a/src/libutil-tests/meson.build b/src/libutil-tests/meson.build index f982d6cf6..8f9c18eed 100644 --- a/src/libutil-tests/meson.build +++ b/src/libutil-tests/meson.build @@ -35,14 +35,9 @@ deps_private += gtest configdata = configuration_data() configdata.set_quoted('PACKAGE_VERSION', meson.project_version()) -config_h = configure_file( +config_priv_h = configure_file( configuration : configdata, - output : 'config-util-tests.hh', -) - -add_project_arguments( - '-include', 'config-util-tests.hh', - language : 'cpp', + output : 'util-tests-config.hh', ) subdir('nix-meson-build-support/common') @@ -84,7 +79,7 @@ include_dirs = [include_directories('.')] this_exe = executable( meson.project_name(), sources, - config_h, + config_priv_h, dependencies : deps_private_subproject + deps_private + deps_other, include_directories : include_dirs, # TODO: -lrapidcheck, see ../libutil-support/build.meson diff --git a/src/libutil-tests/nix_api_util.cc b/src/libutil-tests/nix_api_util.cc index f768de011..f2d198aac 100644 --- a/src/libutil-tests/nix_api_util.cc +++ b/src/libutil-tests/nix_api_util.cc @@ -9,6 +9,8 @@ #include +#include "util-tests-config.hh" + namespace nixC { TEST_F(nix_api_util_context, nix_context_error) diff --git a/src/libutil/compute-levels.cc b/src/libutil/compute-levels.cc index 8cc3def18..2e3c84404 100644 --- a/src/libutil/compute-levels.cc +++ b/src/libutil/compute-levels.cc @@ -1,5 +1,7 @@ #include "nix/types.hh" +#include "util-config-private.hh" + #if HAVE_LIBCPUID #include #endif diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 6a63e0242..8a309d120 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -27,6 +27,8 @@ #include "nix/strings-inline.hh" +#include "util-config-private.hh" + namespace nix { namespace fs { using namespace std::filesystem; } @@ -630,62 +632,6 @@ void replaceSymlink(const fs::path & target, const fs::path & link) } } -void setWriteTime( - const fs::path & path, - time_t accessedTime, - time_t modificationTime, - std::optional optIsSymlink) -{ -#ifdef _WIN32 - // FIXME use `fs::last_write_time`. - // - // Would be nice to use std::filesystem unconditionally, but - // doesn't support access time just modification time. - // - // System clock vs File clock issues also make that annoying. - warn("Changing file times is not yet implemented on Windows, path is %s", path); -#elif HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW - struct timespec times[2] = { - { - .tv_sec = accessedTime, - .tv_nsec = 0, - }, - { - .tv_sec = modificationTime, - .tv_nsec = 0, - }, - }; - if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1) - throw SysError("changing modification time of %s (using `utimensat`)", path); -#else - struct timeval times[2] = { - { - .tv_sec = accessedTime, - .tv_usec = 0, - }, - { - .tv_sec = modificationTime, - .tv_usec = 0, - }, - }; -#if HAVE_LUTIMES - if (lutimes(path.c_str(), times) == -1) - throw SysError("changing modification time of %s", path); -#else - bool isSymlink = optIsSymlink - ? *optIsSymlink - : fs::is_symlink(path); - - if (!isSymlink) { - if (utimes(path.c_str(), times) == -1) - throw SysError("changing modification time of %s (not a symlink)", path); - } else { - throw Error("Cannot change modification time of symlink %s", path); - } -#endif -#endif -} - void setWriteTime(const fs::path & path, const struct stat & st) { setWriteTime(path, st.st_atime, st.st_mtime, S_ISLNK(st.st_mode)); diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index 5e7c2e9fd..7b8ba1189 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -10,6 +10,8 @@ # include "nix/windows-error.hh" #endif +#include "util-config-private.hh" + namespace nix { void copyRecursive( diff --git a/src/libutil/include/nix/meson.build b/src/libutil/include/nix/meson.build index 798d49828..3da9837ed 100644 --- a/src/libutil/include/nix/meson.build +++ b/src/libutil/include/nix/meson.build @@ -2,12 +2,7 @@ include_dirs = [include_directories('..')] -config_h = configure_file( - configuration : configdata, - output : 'config-util.hh', -) - -headers = [config_h] + files( +headers = files( 'abstract-setting-to-json.hh', 'ansicolor.hh', 'archive.hh', diff --git a/src/libutil/meson.build b/src/libutil/meson.build index e34bce0d5..c7509f030 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -23,36 +23,20 @@ deps_public_maybe_subproject = [ subdir('nix-meson-build-support/subprojects') # Check for each of these functions, and create a define like `#define -# HAVE_LUTIMES 1`. The `#define` is unconditional, 0 for not found and 1 -# for found. One therefore uses it with `#if` not `#ifdef`. +# HAVE_POSIX_FALLOCATE 1`. The `#define` is unconditional, 0 for not +# found and 1 for found. One therefore uses it with `#if` not `#ifdef`. check_funcs = [ - 'close_range', - # Optionally used for changing the mtime of symlinks. - 'lutimes', - # Optionally used for creating pipes on Unix - 'pipe2', - # Optionally used to preallocate files to be large enough before - # writing to them. - # WARNING: define also used in libstore - 'posix_fallocate', - # Optionally used to get more information about processes failing due - # to a signal on Unix. - 'strsignal', - # Optionally used to try to close more file descriptors (e.g. before - # forking) on Unix. - # WARNING: also used in libexpr - 'sysconf', - # Optionally used for changing the mtime of files and symlinks. - 'utimensat', + [ + 'posix_fallocate', + 'Optionally used to preallocate files to be large enough before writing to them.', + ], ] foreach funcspec : check_funcs - define_name = 'HAVE_' + funcspec.underscorify().to_upper() - define_value = cxx.has_function(funcspec).to_int() - configdata.set(define_name, define_value) + define_name = 'HAVE_' + funcspec[0].underscorify().to_upper() + define_value = cxx.has_function(funcspec[0]).to_int() + configdata.set(define_name, define_value, description: funcspec[1]) endforeach -configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int()) - subdir('nix-meson-build-support/libatomic') if host_machine.system() == 'windows' @@ -116,16 +100,14 @@ deps_public += nlohmann_json cxx = meson.get_compiler('cpp') -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. - '-include', 'nix/config-util.hh', - language : 'cpp', +config_priv_h = configure_file( + configuration : configdata, + output : 'util-config-private.hh', ) subdir('nix-meson-build-support/common') -sources = files( +sources = [config_priv_h] + files( 'archive.cc', 'args.cc', 'canon-path.cc', diff --git a/src/libutil/unix/file-descriptor.cc b/src/libutil/unix/file-descriptor.cc index 566675349..2911df54f 100644 --- a/src/libutil/unix/file-descriptor.cc +++ b/src/libutil/unix/file-descriptor.cc @@ -7,6 +7,9 @@ #include #include +#include "util-config-private.hh" +#include "util-unix-config-private.hh" + namespace nix { namespace { diff --git a/src/libutil/unix/file-system.cc b/src/libutil/unix/file-system.cc index 119e8a277..d79f4c64c 100644 --- a/src/libutil/unix/file-system.cc +++ b/src/libutil/unix/file-system.cc @@ -1,10 +1,72 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + #include "nix/file-system.hh" +#include "util-unix-config-private.hh" + namespace nix { +namespace fs { +using namespace std::filesystem; +} + Descriptor openDirectory(const std::filesystem::path & path) { return open(path.c_str(), O_RDONLY | O_DIRECTORY); } +void setWriteTime(const fs::path & path, time_t accessedTime, time_t modificationTime, std::optional optIsSymlink) +{ + // Would be nice to use std::filesystem unconditionally, but + // doesn't support access time just modification time. + // + // System clock vs File clock issues also make that annoying. +#if HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW + struct timespec times[2] = { + { + .tv_sec = accessedTime, + .tv_nsec = 0, + }, + { + .tv_sec = modificationTime, + .tv_nsec = 0, + }, + }; + if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1) + throw SysError("changing modification time of %s (using `utimensat`)", path); +#else + struct timeval times[2] = { + { + .tv_sec = accessedTime, + .tv_usec = 0, + }, + { + .tv_sec = modificationTime, + .tv_usec = 0, + }, + }; +# if HAVE_LUTIMES + if (lutimes(path.c_str(), times) == -1) + throw SysError("changing modification time of %s", path); +# else + bool isSymlink = optIsSymlink ? *optIsSymlink : fs::is_symlink(path); + + if (!isSymlink) { + if (utimes(path.c_str(), times) == -1) + throw SysError("changing modification time of %s (not a symlink)", path); + } else { + throw Error("Cannot change modification time of symlink %s", path); + } +# endif +#endif +} + } diff --git a/src/libutil/unix/meson.build b/src/libutil/unix/meson.build index 1373ed17a..ee0c19aff 100644 --- a/src/libutil/unix/meson.build +++ b/src/libutil/unix/meson.build @@ -1,3 +1,53 @@ +include_dirs += include_directories('.') + +configdata_unix = configuration_data() + +configdata_unix.set( + 'HAVE_DECL_AT_SYMLINK_NOFOLLOW', + cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int(), + description : 'Optionally used for changing the files and symlinks.' +) + +# Check for each of these functions, and create a define like `#define +# HAVE_CLOSE_RANGE 1`. +check_funcs_unix = [ + [ + 'close_range', + 'For closing many file descriptors after forking.', + ], + [ + 'lutimes', + 'Optionally used for changing the mtime of symlinks.', + ], + [ + 'pipe2', + 'Optionally used for creating pipes on Unix.', + ], + [ + 'strsignal', + 'Optionally used to get more information about processes failing due to a signal on Unix.', + ], + [ + 'sysconf', + 'Optionally used to try to close more file descriptors (e.g. before forking) on Unix.', + ], + [ + 'utimensat', + 'Optionally used for changing the mtime of files and symlinks.', + ], +] +foreach funcspec : check_funcs_unix + define_name = 'HAVE_' + funcspec[0].underscorify().to_upper() + define_value = cxx.has_function(funcspec[0]).to_int() + configdata_unix.set(define_name, define_value, description: funcspec[1]) +endforeach + +config_unix_priv_h = configure_file( + configuration : configdata_unix, + output : 'util-unix-config-private.hh', +) +sources += config_unix_priv_h + sources += files( 'environment-variables.cc', 'file-descriptor.cc', diff --git a/src/libutil/unix/processes.cc b/src/libutil/unix/processes.cc index 032992a2f..06beacb87 100644 --- a/src/libutil/unix/processes.cc +++ b/src/libutil/unix/processes.cc @@ -28,6 +28,9 @@ # include #endif +#include "util-config-private.hh" +#include "util-unix-config-private.hh" + namespace nix { diff --git a/src/libutil/windows/file-system.cc b/src/libutil/windows/file-system.cc index 22f1f89ab..3c2a57bcd 100644 --- a/src/libutil/windows/file-system.cc +++ b/src/libutil/windows/file-system.cc @@ -3,6 +3,21 @@ #ifdef _WIN32 namespace nix { +namespace fs { +using namespace std::filesystem; +} + +void setWriteTime(const fs::path & path, time_t accessedTime, time_t modificationTime, std::optional optIsSymlink) +{ + // FIXME use `fs::last_write_time`. + // + // Would be nice to use std::filesystem unconditionally, but + // doesn't support access time just modification time. + // + // System clock vs File clock issues also make that annoying. + warn("Changing file times is not yet implemented on Windows, path is %s", path); +} + Descriptor openDirectory(const std::filesystem::path & path) { return CreateFileW( diff --git a/src/nix/main.cc b/src/nix/main.cc index 3d57263df..330cafce6 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -23,6 +23,7 @@ #include "self-exe.hh" #include "crash-handler.hh" +#include "cli-config-private.hh" #include #include diff --git a/src/nix/meson.build b/src/nix/meson.build index adcf80a25..b258778cc 100644 --- a/src/nix/meson.build +++ b/src/nix/meson.build @@ -46,25 +46,15 @@ if not fs.is_absolute(bindir) endif configdata.set_quoted('NIX_BIN_DIR', bindir) -config_h = configure_file( +config_priv_h = configure_file( configuration : configdata, - output : 'config-nix-cli.hh', -) - -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. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - '-include', 'config-nix-cli.hh', - language : 'cpp', + output : 'cli-config-private.hh', ) subdir('nix-meson-build-support/common') subdir('nix-meson-build-support/generate-header') -nix_sources = [config_h] + files( +nix_sources = [config_priv_h] + files( 'add-to-store.cc', 'app.cc', 'self-exe.cc', diff --git a/src/nix/self-exe.cc b/src/nix/self-exe.cc index c9ab566ce..f9439dfd9 100644 --- a/src/nix/self-exe.cc +++ b/src/nix/self-exe.cc @@ -1,7 +1,9 @@ #include "nix/current-process.hh" #include "nix/file-system.hh" #include "nix/globals.hh" + #include "self-exe.hh" +#include "cli-config-private.hh" namespace nix { diff --git a/src/perl/lib/Nix/Store.xs b/src/perl/lib/Nix/Store.xs index f368a2e42..49bf8bd79 100644 --- a/src/perl/lib/Nix/Store.xs +++ b/src/perl/lib/Nix/Store.xs @@ -1,6 +1,3 @@ -#include "nix/config-util.hh" -#include "nix/config-store.hh" - #include "EXTERN.h" #include "perl.h" #include "XSUB.h" diff --git a/tests/functional/plugins/meson.build b/tests/functional/plugins/meson.build index cee43f0b5..ae66e3036 100644 --- a/tests/functional/plugins/meson.build +++ b/tests/functional/plugins/meson.build @@ -1,13 +1,6 @@ libplugintest = shared_module( 'plugintest', 'plugintest.cc', - cpp_args : [ - # TODO(Qyriad): Yes this is how the autoconf+Make system did it. - # It would be nice for our headers to be idempotent instead. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - '-include', 'nix/config-expr.hh', - ], dependencies : [ dependency('nix-expr'), ], diff --git a/tests/functional/test-libstoreconsumer/meson.build b/tests/functional/test-libstoreconsumer/meson.build index 13a7f6d6f..e5a1cc182 100644 --- a/tests/functional/test-libstoreconsumer/meson.build +++ b/tests/functional/test-libstoreconsumer/meson.build @@ -1,12 +1,6 @@ libstoreconsumer_tester = executable( 'test-libstoreconsumer', 'main.cc', - cpp_args : [ - # TODO(Qyriad): Yes this is how the autoconf+Make system did it. - # It would be nice for our headers to be idempotent instead. - '-include', 'nix/config-util.hh', - '-include', 'nix/config-store.hh', - ], dependencies : [ dependency('nix-store'), ],