mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-29 09:06:15 +02:00
Merge pull request #11014 from obsidiansystems/plugins-libmain
Move plugins infra to `libnixmain`
This commit is contained in:
commit
b230c01f73
20 changed files with 365 additions and 131 deletions
|
@ -26,6 +26,7 @@ subproject('external-api-docs')
|
||||||
subproject('libutil-c')
|
subproject('libutil-c')
|
||||||
subproject('libstore-c')
|
subproject('libstore-c')
|
||||||
subproject('libexpr-c')
|
subproject('libexpr-c')
|
||||||
|
subproject('libmain-c')
|
||||||
|
|
||||||
# Language Bindings
|
# Language Bindings
|
||||||
subproject('perl')
|
subproject('perl')
|
||||||
|
|
|
@ -29,6 +29,7 @@ in
|
||||||
nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { };
|
nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { };
|
||||||
|
|
||||||
nix-main = callPackage ../src/libmain/package.nix { };
|
nix-main = callPackage ../src/libmain/package.nix { };
|
||||||
|
nix-main-c = callPackage ../src/libmain-c/package.nix { };
|
||||||
|
|
||||||
nix-cmd = callPackage ../src/libcmd/package.nix { };
|
nix-cmd = callPackage ../src/libcmd/package.nix { };
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ let
|
||||||
"nix-flake"
|
"nix-flake"
|
||||||
"nix-flake-tests"
|
"nix-flake-tests"
|
||||||
"nix-main"
|
"nix-main"
|
||||||
|
"nix-main-c"
|
||||||
"nix-cmd"
|
"nix-cmd"
|
||||||
"nix-ng"
|
"nix-ng"
|
||||||
];
|
];
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "machines.hh"
|
#include "machines.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
|
#include "plugin.hh"
|
||||||
#include "pathlocks.hh"
|
#include "pathlocks.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "serialise.hh"
|
#include "serialise.hh"
|
||||||
|
|
1
src/libmain-c/.version
Symbolic link
1
src/libmain-c/.version
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../.version
|
1
src/libmain-c/build-utils-meson
Symbolic link
1
src/libmain-c/build-utils-meson
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../build-utils-meson
|
84
src/libmain-c/meson.build
Normal file
84
src/libmain-c/meson.build
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
project('nix-main-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-main'),
|
||||||
|
]
|
||||||
|
deps_public_maybe_subproject = [
|
||||||
|
dependency('nix-util-c'),
|
||||||
|
dependency('nix-store-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-main.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-main.hh',
|
||||||
|
|
||||||
|
# From C libraries, for our public, installed headers too
|
||||||
|
'-include', 'config-util.h',
|
||||||
|
'-include', 'config-store.h',
|
||||||
|
'-include', 'config-main.h',
|
||||||
|
language : 'cpp',
|
||||||
|
)
|
||||||
|
|
||||||
|
subdir('build-utils-meson/diagnostics')
|
||||||
|
|
||||||
|
sources = files(
|
||||||
|
'nix_api_main.cc',
|
||||||
|
)
|
||||||
|
|
||||||
|
include_dirs = [include_directories('.')]
|
||||||
|
|
||||||
|
headers = [config_h] + files(
|
||||||
|
'nix_api_main.h',
|
||||||
|
)
|
||||||
|
|
||||||
|
subdir('build-utils-meson/export-all-symbols')
|
||||||
|
|
||||||
|
this_library = library(
|
||||||
|
'nixmainc',
|
||||||
|
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')
|
16
src/libmain-c/nix_api_main.cc
Normal file
16
src/libmain-c/nix_api_main.cc
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "nix_api_store.h"
|
||||||
|
#include "nix_api_store_internal.h"
|
||||||
|
#include "nix_api_util.h"
|
||||||
|
#include "nix_api_util_internal.h"
|
||||||
|
|
||||||
|
#include "plugin.hh"
|
||||||
|
|
||||||
|
nix_err nix_init_plugins(nix_c_context * context)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
nix::initPlugins();
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
40
src/libmain-c/nix_api_main.h
Normal file
40
src/libmain-c/nix_api_main.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef NIX_API_MAIN_H
|
||||||
|
#define NIX_API_MAIN_H
|
||||||
|
/**
|
||||||
|
* @defgroup libmain libmain
|
||||||
|
* @brief C bindings for nix libmain
|
||||||
|
*
|
||||||
|
* libmain has misc utilities for CLI commands
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** @file
|
||||||
|
* @brief Main entry for the libmain C bindings
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nix_api_util.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
// cffi start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads the plugins specified in Nix's plugin-files setting.
|
||||||
|
*
|
||||||
|
* Call this once, after calling your desired init functions and setting
|
||||||
|
* relevant settings.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @return NIX_OK if the initialization was successful, an error code otherwise.
|
||||||
|
*/
|
||||||
|
nix_err nix_init_plugins(nix_c_context * context);
|
||||||
|
|
||||||
|
// cffi end
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif // NIX_API_MAIN_H
|
83
src/libmain-c/package.nix
Normal file
83
src/libmain-c/package.nix
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, mkMesonDerivation
|
||||||
|
, releaseTools
|
||||||
|
|
||||||
|
, meson
|
||||||
|
, ninja
|
||||||
|
, pkg-config
|
||||||
|
|
||||||
|
, nix-util-c
|
||||||
|
, nix-store
|
||||||
|
, nix-store-c
|
||||||
|
, nix-main
|
||||||
|
|
||||||
|
# Configuration Options
|
||||||
|
|
||||||
|
, version
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) fileset;
|
||||||
|
in
|
||||||
|
|
||||||
|
mkMesonDerivation (finalAttrs: {
|
||||||
|
pname = "nix-main-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") ./.)
|
||||||
|
];
|
||||||
|
|
||||||
|
outputs = [ "out" "dev" ];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
nix-util-c
|
||||||
|
nix-store
|
||||||
|
nix-store-c
|
||||||
|
nix-main
|
||||||
|
];
|
||||||
|
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
|
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||||
|
|
||||||
|
strictDeps = true;
|
||||||
|
|
||||||
|
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
|
@ -5,6 +5,7 @@
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "loggers.hh"
|
#include "loggers.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
#include "plugin.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ subdir('build-utils-meson/diagnostics')
|
||||||
sources = files(
|
sources = files(
|
||||||
'common-args.cc',
|
'common-args.cc',
|
||||||
'loggers.cc',
|
'loggers.cc',
|
||||||
|
'plugin.cc',
|
||||||
'progress-bar.cc',
|
'progress-bar.cc',
|
||||||
'shared.cc',
|
'shared.cc',
|
||||||
)
|
)
|
||||||
|
@ -79,6 +80,7 @@ include_dirs = [include_directories('.')]
|
||||||
headers = [config_h] + files(
|
headers = [config_h] + files(
|
||||||
'common-args.hh',
|
'common-args.hh',
|
||||||
'loggers.hh',
|
'loggers.hh',
|
||||||
|
'plugin.hh',
|
||||||
'progress-bar.hh',
|
'progress-bar.hh',
|
||||||
'shared.hh',
|
'shared.hh',
|
||||||
)
|
)
|
||||||
|
|
117
src/libmain/plugin.cc
Normal file
117
src/libmain/plugin.cc
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#ifndef _WIN32
|
||||||
|
# include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "config-global.hh"
|
||||||
|
#include "signals.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
struct PluginFilesSetting : public BaseSetting<Paths>
|
||||||
|
{
|
||||||
|
bool pluginsLoaded = false;
|
||||||
|
|
||||||
|
PluginFilesSetting(
|
||||||
|
Config * options,
|
||||||
|
const Paths & def,
|
||||||
|
const std::string & name,
|
||||||
|
const std::string & description,
|
||||||
|
const std::set<std::string> & aliases = {})
|
||||||
|
: BaseSetting<Paths>(def, true, name, description, aliases)
|
||||||
|
{
|
||||||
|
options->addSetting(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Paths parse(const std::string & str) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
Paths PluginFilesSetting::parse(const std::string & str) const
|
||||||
|
{
|
||||||
|
if (pluginsLoaded)
|
||||||
|
throw UsageError(
|
||||||
|
"plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
|
||||||
|
return BaseSetting<Paths>::parse(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PluginSettings : Config
|
||||||
|
{
|
||||||
|
PluginFilesSetting pluginFiles{
|
||||||
|
this,
|
||||||
|
{},
|
||||||
|
"plugin-files",
|
||||||
|
R"(
|
||||||
|
A list of plugin files to be loaded by Nix. Each of these files will
|
||||||
|
be dlopened by Nix. If they contain the symbol `nix_plugin_entry()`,
|
||||||
|
this symbol will be called. Alternatively, they can affect execution
|
||||||
|
through static initialization. In particular, these plugins may construct
|
||||||
|
static instances of RegisterPrimOp to add new primops or constants to the
|
||||||
|
expression language, RegisterStoreImplementation to add new store
|
||||||
|
implementations, RegisterCommand to add new subcommands to the `nix`
|
||||||
|
command, and RegisterSetting to add new nix config settings. See the
|
||||||
|
constructors for those types for more details.
|
||||||
|
|
||||||
|
Warning! These APIs are inherently unstable and may change from
|
||||||
|
release to release.
|
||||||
|
|
||||||
|
Since these files are loaded into the same address space as Nix
|
||||||
|
itself, they must be DSOs compatible with the instance of Nix
|
||||||
|
running at the time (i.e. compiled against the same headers, not
|
||||||
|
linked to any incompatible libraries). They should not be linked to
|
||||||
|
any Nix libs directly, as those will be available already at load
|
||||||
|
time.
|
||||||
|
|
||||||
|
If an entry in the list is a directory, all files in the directory
|
||||||
|
are loaded as plugins (non-recursively).
|
||||||
|
)"};
|
||||||
|
};
|
||||||
|
|
||||||
|
static PluginSettings pluginSettings;
|
||||||
|
|
||||||
|
static GlobalConfig::Register rPluginSettings(&pluginSettings);
|
||||||
|
|
||||||
|
void initPlugins()
|
||||||
|
{
|
||||||
|
assert(!pluginSettings.pluginFiles.pluginsLoaded);
|
||||||
|
for (const auto & pluginFile : pluginSettings.pluginFiles.get()) {
|
||||||
|
std::vector<std::filesystem::path> pluginFiles;
|
||||||
|
try {
|
||||||
|
auto ents = std::filesystem::directory_iterator{pluginFile};
|
||||||
|
for (const auto & ent : ents) {
|
||||||
|
checkInterrupt();
|
||||||
|
pluginFiles.emplace_back(ent.path());
|
||||||
|
}
|
||||||
|
} catch (std::filesystem::filesystem_error & e) {
|
||||||
|
if (e.code() != std::errc::not_a_directory)
|
||||||
|
throw;
|
||||||
|
pluginFiles.emplace_back(pluginFile);
|
||||||
|
}
|
||||||
|
for (const auto & file : pluginFiles) {
|
||||||
|
checkInterrupt();
|
||||||
|
/* handle is purposefully leaked as there may be state in the
|
||||||
|
DSO needed by the action of the plugin. */
|
||||||
|
#ifndef _WIN32 // TODO implement via DLL loading on Windows
|
||||||
|
void * handle = dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (!handle)
|
||||||
|
throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
|
||||||
|
|
||||||
|
/* Older plugins use a statically initialized object to run their code.
|
||||||
|
Newer plugins can also export nix_plugin_entry() */
|
||||||
|
void (*nix_plugin_entry)() = (void (*)()) dlsym(handle, "nix_plugin_entry");
|
||||||
|
if (nix_plugin_entry)
|
||||||
|
nix_plugin_entry();
|
||||||
|
#else
|
||||||
|
throw Error("could not dynamically open plugin file '%s'", file);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since plugins can add settings, try to re-apply previously
|
||||||
|
unknown settings. */
|
||||||
|
globalConfig.reapplyUnknownSettings();
|
||||||
|
globalConfig.warnUnknownSettings();
|
||||||
|
|
||||||
|
/* Tell the user if they try to set plugin-files after we've already loaded */
|
||||||
|
pluginSettings.pluginFiles.pluginsLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/libmain/plugin.hh
Normal file
12
src/libmain/plugin.hh
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
///@file
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be called after settings are initialized, but before
|
||||||
|
* anything else
|
||||||
|
*/
|
||||||
|
void initPlugins();
|
||||||
|
|
||||||
|
}
|
|
@ -29,16 +29,6 @@ nix_err nix_libstore_init_no_load_config(nix_c_context * context)
|
||||||
NIXC_CATCH_ERRS
|
NIXC_CATCH_ERRS
|
||||||
}
|
}
|
||||||
|
|
||||||
nix_err nix_init_plugins(nix_c_context * context)
|
|
||||||
{
|
|
||||||
if (context)
|
|
||||||
context->last_err_code = NIX_OK;
|
|
||||||
try {
|
|
||||||
nix::initPlugins();
|
|
||||||
}
|
|
||||||
NIXC_CATCH_ERRS
|
|
||||||
}
|
|
||||||
|
|
||||||
Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params)
|
Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
|
|
|
@ -42,17 +42,6 @@ nix_err nix_libstore_init(nix_c_context * context);
|
||||||
*/
|
*/
|
||||||
nix_err nix_libstore_init_no_load_config(nix_c_context * context);
|
nix_err nix_libstore_init_no_load_config(nix_c_context * context);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Loads the plugins specified in Nix's plugin-files setting.
|
|
||||||
*
|
|
||||||
* Call this once, after calling your desired init functions and setting
|
|
||||||
* relevant settings.
|
|
||||||
*
|
|
||||||
* @param[out] context Optional, stores error information
|
|
||||||
* @return NIX_OK if the initialization was successful, an error code otherwise.
|
|
||||||
*/
|
|
||||||
nix_err nix_init_plugins(nix_c_context * context);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Open a nix store.
|
* @brief Open a nix store.
|
||||||
*
|
*
|
||||||
|
|
|
@ -246,10 +246,9 @@ struct ClientSettings
|
||||||
// the daemon, as that could cause some pretty weird stuff
|
// the daemon, as that could cause some pretty weird stuff
|
||||||
if (parseFeatures(tokenizeString<StringSet>(value)) != experimentalFeatureSettings.experimentalFeatures.get())
|
if (parseFeatures(tokenizeString<StringSet>(value)) != experimentalFeatureSettings.experimentalFeatures.get())
|
||||||
debug("Ignoring the client-specified experimental features");
|
debug("Ignoring the client-specified experimental features");
|
||||||
} else if (name == settings.pluginFiles.name) {
|
} else if (name == "plugin-files") {
|
||||||
if (tokenizeString<Paths>(value) != settings.pluginFiles.get())
|
warn("Ignoring the client-specified plugin-files.\n"
|
||||||
warn("Ignoring the client-specified plugin-files.\n"
|
"The client specifying plugins to the daemon never made sense, and was removed in Nix >=2.14.");
|
||||||
"The client specifying plugins to the daemon never made sense, and was removed in Nix >=2.14.");
|
|
||||||
}
|
}
|
||||||
else if (trusted
|
else if (trusted
|
||||||
|| name == settings.buildTimeout.name
|
|| name == settings.buildTimeout.name
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <dlfcn.h>
|
|
||||||
# include <sys/utsname.h>
|
# include <sys/utsname.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -335,60 +334,6 @@ unsigned int MaxBuildJobsSetting::parse(const std::string & str) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Paths PluginFilesSetting::parse(const std::string & str) const
|
|
||||||
{
|
|
||||||
if (pluginsLoaded)
|
|
||||||
throw UsageError("plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
|
|
||||||
return BaseSetting<Paths>::parse(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void initPlugins()
|
|
||||||
{
|
|
||||||
assert(!settings.pluginFiles.pluginsLoaded);
|
|
||||||
for (const auto & pluginFile : settings.pluginFiles.get()) {
|
|
||||||
std::vector<std::filesystem::path> pluginFiles;
|
|
||||||
try {
|
|
||||||
auto ents = std::filesystem::directory_iterator{pluginFile};
|
|
||||||
for (const auto & ent : ents) {
|
|
||||||
checkInterrupt();
|
|
||||||
pluginFiles.emplace_back(ent.path());
|
|
||||||
}
|
|
||||||
} catch (std::filesystem::filesystem_error & e) {
|
|
||||||
if (e.code() != std::errc::not_a_directory)
|
|
||||||
throw;
|
|
||||||
pluginFiles.emplace_back(pluginFile);
|
|
||||||
}
|
|
||||||
for (const auto & file : pluginFiles) {
|
|
||||||
checkInterrupt();
|
|
||||||
/* handle is purposefully leaked as there may be state in the
|
|
||||||
DSO needed by the action of the plugin. */
|
|
||||||
#ifndef _WIN32 // TODO implement via DLL loading on Windows
|
|
||||||
void *handle =
|
|
||||||
dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
|
||||||
if (!handle)
|
|
||||||
throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
|
|
||||||
|
|
||||||
/* Older plugins use a statically initialized object to run their code.
|
|
||||||
Newer plugins can also export nix_plugin_entry() */
|
|
||||||
void (*nix_plugin_entry)() = (void (*)())dlsym(handle, "nix_plugin_entry");
|
|
||||||
if (nix_plugin_entry)
|
|
||||||
nix_plugin_entry();
|
|
||||||
#else
|
|
||||||
throw Error("could not dynamically open plugin file '%s'", file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Since plugins can add settings, try to re-apply previously
|
|
||||||
unknown settings. */
|
|
||||||
globalConfig.reapplyUnknownSettings();
|
|
||||||
globalConfig.warnUnknownSettings();
|
|
||||||
|
|
||||||
/* Tell the user if they try to set plugin-files after we've already loaded */
|
|
||||||
settings.pluginFiles.pluginsLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void preloadNSS()
|
static void preloadNSS()
|
||||||
{
|
{
|
||||||
/* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of
|
/* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of
|
||||||
|
|
|
@ -31,23 +31,6 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
|
||||||
unsigned int parse(const std::string & str) const override;
|
unsigned int parse(const std::string & str) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PluginFilesSetting : public BaseSetting<Paths>
|
|
||||||
{
|
|
||||||
bool pluginsLoaded = false;
|
|
||||||
|
|
||||||
PluginFilesSetting(Config * options,
|
|
||||||
const Paths & def,
|
|
||||||
const std::string & name,
|
|
||||||
const std::string & description,
|
|
||||||
const std::set<std::string> & aliases = {})
|
|
||||||
: BaseSetting<Paths>(def, true, name, description, aliases)
|
|
||||||
{
|
|
||||||
options->addSetting(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Paths parse(const std::string & str) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t maxIdsPerBuild =
|
const uint32_t maxIdsPerBuild =
|
||||||
#if __linux__
|
#if __linux__
|
||||||
1 << 16
|
1 << 16
|
||||||
|
@ -1158,33 +1141,6 @@ public:
|
||||||
Setting<uint64_t> minFreeCheckInterval{this, 5, "min-free-check-interval",
|
Setting<uint64_t> minFreeCheckInterval{this, 5, "min-free-check-interval",
|
||||||
"Number of seconds between checking free disk space."};
|
"Number of seconds between checking free disk space."};
|
||||||
|
|
||||||
PluginFilesSetting pluginFiles{
|
|
||||||
this, {}, "plugin-files",
|
|
||||||
R"(
|
|
||||||
A list of plugin files to be loaded by Nix. Each of these files will
|
|
||||||
be dlopened by Nix. If they contain the symbol `nix_plugin_entry()`,
|
|
||||||
this symbol will be called. Alternatively, they can affect execution
|
|
||||||
through static initialization. In particular, these plugins may construct
|
|
||||||
static instances of RegisterPrimOp to add new primops or constants to the
|
|
||||||
expression language, RegisterStoreImplementation to add new store
|
|
||||||
implementations, RegisterCommand to add new subcommands to the `nix`
|
|
||||||
command, and RegisterSetting to add new nix config settings. See the
|
|
||||||
constructors for those types for more details.
|
|
||||||
|
|
||||||
Warning! These APIs are inherently unstable and may change from
|
|
||||||
release to release.
|
|
||||||
|
|
||||||
Since these files are loaded into the same address space as Nix
|
|
||||||
itself, they must be DSOs compatible with the instance of Nix
|
|
||||||
running at the time (i.e. compiled against the same headers, not
|
|
||||||
linked to any incompatible libraries). They should not be linked to
|
|
||||||
any Nix libs directly, as those will be available already at load
|
|
||||||
time.
|
|
||||||
|
|
||||||
If an entry in the list is a directory, all files in the directory
|
|
||||||
are loaded as plugins (non-recursively).
|
|
||||||
)"};
|
|
||||||
|
|
||||||
Setting<size_t> narBufferSize{this, 32 * 1024 * 1024, "nar-buffer-size",
|
Setting<size_t> narBufferSize{this, 32 * 1024 * 1024, "nar-buffer-size",
|
||||||
"Maximum size of NARs before spilling them to disk."};
|
"Maximum size of NARs before spilling them to disk."};
|
||||||
|
|
||||||
|
@ -1278,12 +1234,6 @@ public:
|
||||||
// FIXME: don't use a global variable.
|
// FIXME: don't use a global variable.
|
||||||
extern Settings settings;
|
extern Settings settings;
|
||||||
|
|
||||||
/**
|
|
||||||
* This should be called after settings are initialized, but before
|
|
||||||
* anything else
|
|
||||||
*/
|
|
||||||
void initPlugins();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the configuration (from `nix.conf`, `NIX_CONFIG`, etc.) into the
|
* Load the configuration (from `nix.conf`, `NIX_CONFIG`, etc.) into the
|
||||||
* given configuration object.
|
* given configuration object.
|
||||||
|
|
|
@ -128,7 +128,7 @@ void RemoteStore::setOptions(Connection & conn)
|
||||||
overrides.erase(settings.useSubstitutes.name);
|
overrides.erase(settings.useSubstitutes.name);
|
||||||
overrides.erase(loggerSettings.showTrace.name);
|
overrides.erase(loggerSettings.showTrace.name);
|
||||||
overrides.erase(experimentalFeatureSettings.experimentalFeatures.name);
|
overrides.erase(experimentalFeatureSettings.experimentalFeatures.name);
|
||||||
overrides.erase(settings.pluginFiles.name);
|
overrides.erase("plugin-files");
|
||||||
conn.to << overrides.size();
|
conn.to << overrides.size();
|
||||||
for (auto & i : overrides)
|
for (auto & i : overrides)
|
||||||
conn.to << i.first << i.second.value;
|
conn.to << i.first << i.second.value;
|
||||||
|
|
Loading…
Reference in a new issue