From 5f9d2d95721cdf20ace744f2db75ad70a7aedd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 13 Nov 2024 20:37:55 +0100 Subject: [PATCH] nixos-option: fix build against nix 2.24 --- pkgs/tools/nix/nixos-option/default.nix | 27 +++-- pkgs/tools/nix/nixos-option/meson.build | 15 +++ .../tools/nix/nixos-option/src/CMakeLists.txt | 11 -- .../nix/nixos-option/src/libnix-copy-paste.cc | 76 ++---------- .../nix/nixos-option/src/libnix-copy-paste.hh | 6 +- pkgs/tools/nix/nixos-option/src/meson.build | 20 ++++ .../nix/nixos-option/src/nixos-option.cc | 113 +++++++++--------- pkgs/top-level/all-packages.nix | 4 +- 8 files changed, 115 insertions(+), 157 deletions(-) create mode 100644 pkgs/tools/nix/nixos-option/meson.build delete mode 100644 pkgs/tools/nix/nixos-option/src/CMakeLists.txt create mode 100644 pkgs/tools/nix/nixos-option/src/meson.build diff --git a/pkgs/tools/nix/nixos-option/default.nix b/pkgs/tools/nix/nixos-option/default.nix index b01ee138170f..db6c974288c8 100644 --- a/pkgs/tools/nix/nixos-option/default.nix +++ b/pkgs/tools/nix/nixos-option/default.nix @@ -1,24 +1,28 @@ -{ lib -, stdenv -, boost -, cmake -, pkg-config -, installShellFiles -, nix +{ + lib, + stdenv, + boost, + meson, + ninja, + pkg-config, + installShellFiles, + nix, }: stdenv.mkDerivation { name = "nixos-option"; - src = ./src; + src = ./.; postInstall = '' - installManPage ${./nixos-option.8} + installManPage ../nixos-option.8 ''; strictDeps = true; + nativeBuildInputs = [ - cmake + meson + ninja pkg-config installShellFiles ]; @@ -26,9 +30,6 @@ stdenv.mkDerivation { boost nix ]; - cmakeFlags = [ - "-DNIX_DEV_INCLUDEPATH=${nix.dev}/include/nix" - ]; meta = with lib; { license = licenses.lgpl2Plus; diff --git a/pkgs/tools/nix/nixos-option/meson.build b/pkgs/tools/nix/nixos-option/meson.build new file mode 100644 index 000000000000..ff88cf3fbf89 --- /dev/null +++ b/pkgs/tools/nix/nixos-option/meson.build @@ -0,0 +1,15 @@ +project('nixos-option', 'cpp', + version : '0.1.6', + license : 'GPL-3.0', +) + +nix_main_dep = dependency('nix-main', required: true) +nix_store_dep = dependency('nix-store', required: true) +nix_expr_dep = dependency('nix-expr', required: true) +nix_cmd_dep = dependency('nix-cmd', required: true) +nix_flake_dep = dependency('nix-flake', required: true) +threads_dep = dependency('threads', required: true) +nlohmann_json_dep = dependency('nlohmann_json', required: true) +boost_dep = dependency('boost', required: true) + +subdir('src') diff --git a/pkgs/tools/nix/nixos-option/src/CMakeLists.txt b/pkgs/tools/nix/nixos-option/src/CMakeLists.txt deleted file mode 100644 index 9aee9e6ccada..000000000000 --- a/pkgs/tools/nix/nixos-option/src/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required (VERSION 2.6) -project (nixos-option) - -set(NIX_DEV_INCLUDEPATH "" CACHE STRING "path to nix include directory") - -add_executable(nixos-option nixos-option.cc libnix-copy-paste.cc) -target_include_directories(nixos-option PUBLIC "${NIX_DEV_INCLUDEPATH}") -target_link_libraries(nixos-option PRIVATE -lnixmain -lnixexpr -lnixstore -lnixutil -lnixcmd) -target_compile_features(nixos-option PRIVATE cxx_std_20) - -install (TARGETS nixos-option DESTINATION bin) diff --git a/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.cc b/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.cc index ad6084844e57..b5ae1b495884 100644 --- a/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.cc +++ b/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.cc @@ -2,79 +2,21 @@ // Since they are not, copy/paste them here. // TODO: Delete these and use the ones in the library as they become available. -#include // for nix/globals.hh's reference to SYSTEM - #include "libnix-copy-paste.hh" -#include // for basic_altstringbuf... -#include // for basic_altstringbuf... -#include // for get_pointer -#include // for operator<<, basic_... -#include // for Strings -#include // for Error -#include // for string, basic_string - -using nix::Error; -using nix::Strings; -using std::string; - -// From nix/src/libexpr/attr-path.cc -Strings parseAttrPath(const string & s) -{ - Strings res; - string cur; - string::const_iterator i = s.begin(); - while (i != s.end()) { - if (*i == '.') { - res.push_back(cur); - cur.clear(); - } else if (*i == '"') { - ++i; - while (1) { - if (i == s.end()) - throw Error("missing closing quote in selection path '%1%'", s); - if (*i == '"') - break; - cur.push_back(*i++); - } - } else - cur.push_back(*i); - ++i; - } - if (!cur.empty()) - res.push_back(cur); - return res; -} +#include // for Strings // From nix/src/nix/repl.cc -bool isVarName(const string & s) +bool isVarName(const std::string_view & s) { - if (s.size() == 0) - return false; + if (s.size() == 0) return false; + if (nix::isReservedKeyword(s)) return false; char c = s[0]; - if ((c >= '0' && c <= '9') || c == '-' || c == '\'') - return false; + if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false; for (auto & i : s) - if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-' || - i == '\'')) + if (!((i >= 'a' && i <= 'z') || + (i >= 'A' && i <= 'Z') || + (i >= '0' && i <= '9') || + i == '_' || i == '-' || i == '\'')) return false; return true; } - -// From nix/src/nix/repl.cc -std::ostream & printStringValue(std::ostream & str, const char * string) -{ - str << "\""; - for (const char * i = string; *i; i++) - if (*i == '\"' || *i == '\\') - str << "\\" << *i; - else if (*i == '\n') - str << "\\n"; - else if (*i == '\r') - str << "\\r"; - else if (*i == '\t') - str << "\\t"; - else - str << *i; - str << "\""; - return str; -} diff --git a/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.hh b/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.hh index 2274e9a0f853..f680b4c1a718 100644 --- a/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.hh +++ b/pkgs/tools/nix/nixos-option/src/libnix-copy-paste.hh @@ -1,9 +1,5 @@ #pragma once -#include #include -#include -nix::Strings parseAttrPath(const std::string & s); -bool isVarName(const std::string & s); -std::ostream & printStringValue(std::ostream & str, const char * string); +bool isVarName(const std::string_view & s); diff --git a/pkgs/tools/nix/nixos-option/src/meson.build b/pkgs/tools/nix/nixos-option/src/meson.build new file mode 100644 index 000000000000..8ee9765ce239 --- /dev/null +++ b/pkgs/tools/nix/nixos-option/src/meson.build @@ -0,0 +1,20 @@ +src = [ + 'nixos-option.cc', + 'libnix-copy-paste.cc', +] + +cc = meson.get_compiler('cpp') + +executable('nixos-option', src, + dependencies : [ + nix_main_dep, + nix_store_dep, + nix_expr_dep, + nix_cmd_dep, + nix_flake_dep, + boost_dep, + nlohmann_json_dep, + threads_dep + ], + install: true, + cpp_args: ['-std=c++2a', '--include', 'nix/config.h']) diff --git a/pkgs/tools/nix/nixos-option/src/nixos-option.cc b/pkgs/tools/nix/nixos-option/src/nixos-option.cc index 658b836d491a..977ea83d1973 100644 --- a/pkgs/tools/nix/nixos-option/src/nixos-option.cc +++ b/pkgs/tools/nix/nixos-option/src/nixos-option.cc @@ -1,16 +1,8 @@ -#include // for nix/globals.hh's reference to SYSTEM - -#include // for exception_ptr, current_exception -#include // for function -#include // for operator<<, basic_ostream, ostrin... -#include // for next -#include // for _List_iterator -#include // for allocator, unique_ptr, make_unique -#include // for operator new #include // for argvToStrings, UsageError -#include // for findAlongAttrPath +#include // for findAlongAttrPath, parseAttrPath #include // for Attr, Bindings, Bindings::iterator #include // for MixEvalArgs +#include // for initGC, initNix #include // for EvalState::forceValue #include // for EvalState, initGC, operator<< #include // for initPlugins, Settings, settings @@ -23,8 +15,6 @@ #include // for Value, Value::(anonymous), Value:... #include // for string, operator+, operator== #include // for move -#include // for get, holds_alternative, variant -#include // for vector<>::iterator, vector #include "libnix-copy-paste.hh" @@ -119,7 +109,7 @@ Out::Out(Out & o, const std::string & start, const std::string & end, LinePolicy Value evaluateValue(Context & ctx, Value & v) { - ctx.state.forceValue(v, [&]() { return v.determinePos(nix::noPos); }); + ctx.state.forceValue(v, v.determinePos(nix::noPos)); if (ctx.autoArgs.empty()) { return v; } @@ -133,8 +123,8 @@ bool isOption(Context & ctx, const Value & v) if (v.type() != nAttrs) { return false; } - const auto & actualType = v.attrs->find(ctx.underscoreType); - if (actualType == v.attrs->end()) { + const auto & actualType = v.attrs()->find(ctx.underscoreType); + if (actualType == v.attrs()->end()) { return false; } try { @@ -142,7 +132,7 @@ bool isOption(Context & ctx, const Value & v) if (evaluatedType.type() != nString) { return false; } - return static_cast(evaluatedType.string.s) == "option"; + return evaluatedType.string_view() == "option"; } catch (Error &) { return false; } @@ -152,17 +142,17 @@ bool isOption(Context & ctx, const Value & v) // These are needed for paths like: // fileSystems."/".fsType // systemd.units."dbus.service".text -std::string quoteAttribute(const std::string & attribute) +std::string quoteAttribute(const std::string_view & attribute) { if (isVarName(attribute)) { - return attribute; + return std::string(attribute); } std::ostringstream buf; - printStringValue(buf, attribute.c_str()); + nix::printLiteralString(buf, attribute); return buf.str(); } -const std::string appendPath(const std::string & prefix, const std::string & suffix) +const std::string appendPath(const std::string & prefix, const std::string_view & suffix) { if (prefix.empty()) { return quoteAttribute(suffix); @@ -174,7 +164,7 @@ bool forbiddenRecursionName(const nix::Symbol symbol, const nix::SymbolTable & s // note: this is created from a pointer // According to standard, it may never point to null, and hence attempts to check against nullptr are not allowed. // However, at the time of writing, I am not certain about the full implications of the omission of a nullptr check here. - const std::string & name = symbolTable[symbol]; + const std::string_view & name = symbolTable[symbol]; // TODO: figure out why haskellPackages is not recursed here return (!name.empty() && name[0] == '_') || name == "haskellPackages"; } @@ -198,34 +188,35 @@ void recurse(const std::functionlexicographicOrder(ctx.state.symbols)) { + for (const auto & child : evaluated_value.attrs()->lexicographicOrder(ctx.state.symbols)) { if (forbiddenRecursionName(child->name, ctx.state.symbols)) { continue; } - recurse(f, ctx, *child->value, appendPath(path, ctx.state.symbols[child->name])); + std::string_view name = ctx.state.symbols[child->name]; + recurse(f, ctx, *child->value, appendPath(path, name)); } } bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType) { try { - const auto & typeLookup = v.attrs->find(ctx.state.sType); - if (typeLookup == v.attrs->end()) { + const auto & typeLookup = v.attrs()->find(ctx.state.sType); + if (typeLookup == v.attrs()->end()) { return false; } Value type = evaluateValue(ctx, *typeLookup->value); if (type.type() != nAttrs) { return false; } - const auto & nameLookup = type.attrs->find(ctx.state.sName); - if (nameLookup == type.attrs->end()) { + const auto & nameLookup = type.attrs()->find(ctx.state.sName); + if (nameLookup == type.attrs()->end()) { return false; } Value name = evaluateValue(ctx, *nameLookup->value); if (name.type() != nString) { return false; } - return name.string.s == soughtType; + return name.string_view() == soughtType; } catch (Error &) { return false; } @@ -242,7 +233,7 @@ Value getSubOptions(Context & ctx, Value & option) { Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option).first); if (getSubOptions.isLambda()) { - throw OptionPathError("Option's type.getSubOptions isn't a function"); + throw OptionPathError(ctx.state, "Option's type.getSubOptions isn't a function"); } Value emptyString{}; emptyString.mkString(""); @@ -260,40 +251,40 @@ struct FindAlongOptionPathRet }; FindAlongOptionPathRet findAlongOptionPath(Context & ctx, const std::string & path) { - Strings tokens = parseAttrPath(path); + std::vector tokens = nix::parseAttrPath(ctx.state, path); Value v = ctx.optionsRoot; std::string processedPath; for (auto i = tokens.begin(); i != tokens.end(); i++) { - const auto & attr = *i; + const std::string_view attr = ctx.state.symbols[*i]; try { bool lastAttribute = std::next(i) == tokens.end(); v = evaluateValue(ctx, v); if (attr.empty()) { - throw OptionPathError("empty attribute name"); + throw OptionPathError(ctx.state, "empty attribute name"); } if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) { v = getSubOptions(ctx, v); } if (isOption(ctx, v) && isAggregateOptionType(ctx, v)) { auto subOptions = getSubOptions(ctx, v); - if (lastAttribute && subOptions.attrs->empty()) { + if (lastAttribute && subOptions.attrs()->empty()) { break; } v = subOptions; // Note that we've consumed attr, but didn't actually use it. This is the path component that's looked // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name". } else if (v.type() != nAttrs) { - throw OptionPathError("Value is %s while a set was expected", showType(v)); + throw OptionPathError(ctx.state, "Value is %s while a set was expected", showType(v)); } else { - const auto & next = v.attrs->find(ctx.state.symbols.create(attr)); - if (next == v.attrs->end()) { - throw OptionPathError("Attribute not found", attr, path); + const auto & next = v.attrs()->find(ctx.state.symbols.create(attr)); + if (next == v.attrs()->end()) { + throw OptionPathError(ctx.state, "Attribute not found", attr, path); } v = *next->value; } processedPath = appendPath(processedPath, attr); } catch (OptionPathError & e) { - throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg()); + throw OptionPathError(ctx.state, "At '%s' in path '%s': %s", attr, path, e.msg()); } } return {v, processedPath}; @@ -367,21 +358,23 @@ std::string describeError(const Error & e) { return "«error: " + e.msg() + "»" void describeDerivation(Context & ctx, Out & out, Value v) { - // Copy-pasted from nix/src/nix/repl.cc :( + // Copy-pasted from nix/src/nix/repl.cc printDerivation() :( + std::optional storePath = std::nullopt; + if (auto i = v.attrs()->get(ctx.state.sDrvPath)) { + nix::NixStringContext context; + storePath = ctx.state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"); + } out << "«derivation "; - Bindings::iterator i = v.attrs->find(ctx.state.sDrvPath); - nix::NixStringContext strContext; - if (i != v.attrs->end()) - out << ctx.state.store->printStorePath(ctx.state.coerceToStorePath(i->pos, *i->value, strContext, "while evaluating the drvPath of a derivation")); - else - out << "???"; + if (storePath) { + out << " " << ctx.state.store->printStorePath(*storePath); + } out << "»"; } Value parseAndEval(EvalState & state, const std::string & expression, const std::string & path) { Value v{}; - state.eval(state.parseExprFromString(expression, nix::SourcePath(nix::CanonPath::fromCwd(path))), v); + state.eval(state.parseExprFromString(expression, state.rootPath(".")), v); return v; } @@ -398,10 +391,10 @@ void printList(Context & ctx, Out & out, Value & v) void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path) { - Out attrsOut(out, "{", "}", v.attrs->size()); - for (const auto & a : v.attrs->lexicographicOrder(ctx.state.symbols)) { + Out attrsOut(out, "{", "}", v.attrs()->size()); + for (const auto & a : v.attrs()->lexicographicOrder(ctx.state.symbols)) { if (!forbiddenRecursionName(a->name, ctx.state.symbols)) { - const std::string name = ctx.state.symbols[a->name]; + std::string_view name = ctx.state.symbols[a->name]; attrsOut << name << " = "; printValue(ctx, attrsOut, *a->value, appendPath(path, name)); attrsOut << ";" << Out::sep; @@ -409,9 +402,9 @@ void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path) } } -void multiLineStringEscape(Out & out, const std::string & s) +void multiLineStringEscape(Out & out, const std::string_view & s) { - int i; + size_t i; for (i = 1; i < s.size(); i++) { if (s[i - 1] == '$' && s[i] == '{') { out << "''${"; @@ -430,7 +423,7 @@ void multiLineStringEscape(Out & out, const std::string & s) void printMultiLineString(Out & out, const Value & v) { - std::string s = v.string.s; + std::string_view s = v.string_view(); Out strOut(out, "''", "''", Out::MULTI_LINE); std::string::size_type begin = 0; while (begin < s.size()) { @@ -458,11 +451,11 @@ void printValue(Context & ctx, Out & out, std::variantlexicographicOrder(ctx.state.symbols)) { - const std::string & name = ctx.state.symbols[a->name]; + for (const auto & a : v.attrs()->lexicographicOrder(ctx.state.symbols)) { + const std::string_view & name = ctx.state.symbols[a->name]; if (!name.empty() && name[0] != '_') { out << name << "\n"; } @@ -630,7 +623,11 @@ int main(int argc, char ** argv) nix::initGC(); nix::settings.readOnlyMode = true; auto store = nix::openStore(); - auto state = std::make_unique(myArgs.searchPath, store); + + auto evalStore = myArgs.evalStoreUrl ? nix::openStore(*myArgs.evalStoreUrl) + : nix::openStore(); + auto state = nix::make_ref( + myArgs.lookupPath, evalStore, nix::fetchSettings, nix::evalSettings); Value optionsRoot = parseAndEval(*state, optionsExpr, path); Value configRoot = parseAndEval(*state, configExpr, path); @@ -646,7 +643,7 @@ int main(int argc, char ** argv) print(ctx, out, arg); } - ctx.state.printStats(); + ctx.state.maybePrintStats(); return 0; } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c54b3abe186d..1f3f473f2ac6 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -18681,9 +18681,7 @@ with pkgs; nix-linter = haskell.lib.compose.justStaticExecutables (haskellPackages.nix-linter); - nixos-option = callPackage ../tools/nix/nixos-option { - nix = nixVersions.nix_2_18; - }; + nixos-option = callPackage ../tools/nix/nixos-option { }; nix-pin = callPackage ../tools/package-management/nix-pin { };