mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-04 10:12:28 +02:00
Merge bitcoin/bitcoin#31375: multiprocess: Add bitcoin wrapper executable
a5ac43d98ddoc: Add release notes describing bitcoin wrapper executable (Ryan Ofsky)258bda80c0doc: Mention bitcoin wrapper executable in documentation (Ryan Ofsky)d2739d75c9build: add bitcoin.exe to windows installer (Sjors Provoost)ba649c0006ci: Run multiprocess tests through wrapper executable (Ryan Ofsky)29bdd743bbtest: Support BITCOIN_CMD environment variable (Ryan Ofsky)9c8c68891bmultiprocess: Add bitcoin wrapper executable (Ryan Ofsky)5076d20fdbutil: Add cross-platform ExecVp and GetExePath functions (Ryan Ofsky) Pull request description: Intended to make bitcoin command line features more discoverable and allow installing new multiprocess binaries in libexec/ instead of bin/ so they don't cause confusion. Idea and implementation of this were discussed in https://github.com/bitcoin/bitcoin/issues/30983. --- Initial implementation of this feature is deliberately minimal so the UX can evolve in response to feedback and there are not too many details to debate and discuss in a single PR. But many improvements are possible or planned: - Adding manpage and bash completions. - Showing nicer error messages that detect if an executable isn't installed and suggest how to fix [(comment)](https://github.com/bitcoin/bitcoin/pull/31375#discussion_r2073194474) - Showing wrapper command lines in subcommand in help output [(comment)](https://github.com/bitcoin/bitcoin/pull/31375#discussion_r2077800405). This could be done conditionally as suggested in the comment or be unconditional. - Showing wrapper command lines in subcommand error output. There is a bitcoin-cli error pointed out in [(comment)](https://github.com/bitcoin/bitcoin/pull/31375#discussion_r2091152243) that is needlessly confusing. - Integrating help so `bitcoin help subcommand` invokes `bitcoin subcommand -h`. `bitcoin -h subcommand` should also be supported and be equivalent [(comment)](https://github.com/bitcoin/bitcoin/pull/31375#discussion_r2093116725) - Adding support for `bitcoin-util` subcommands. Ideal interface would probably be more like `bitcoin grind` not `bitcoin util grind` but this has been punted for now. Supporting subcommands directly would require some ArgsManager modifications - Adding a dedicated python functional test for the wrapper. Right now there is some CI coverage by setting the `BITCOIN_CMD` variable, but this doesn't cover things like the help output and version output, and support for different directory layouts. - Better `--multiprocess` (`-m`) / `--monolithic` (`-M`) default selection. Right now, default is monolithic but it probably makes sense to chose more intelligently depending on whether -ipc options are enabled and what binaries are available. - Maybe parsing `bitcoin.conf` and supporting options to control wrapper behavior like custom locations or preferences or aliases. - Better command command line usability. Allow combining short options like (`-ah`). Allow fuzzy matching of subcommands or suggestions if you misspell. (suggested by stickies in review club) - Not directly related to this PR but `bitcoin-cli named` implementation used by the wrapper should do a better job disambiguating named arguments from base64 arguments ending in = as pointed out in [(comment)](https://github.com/bitcoin/bitcoin/pull/31375#discussion_r2091886628) --- This PR is part of the [process separation project](https://github.com/bitcoin/bitcoin/issues/28722). A review club meeting for it took place in https://bitcoincore.reviews/31375 ACKs for top commit: Sjors: utACKa5ac43d98dachow101: ACKa5ac43d98dvasild: ACKa5ac43d98dtheStack: ACKa5ac43d98dismaelsadeeq: fwiw my last review implied an ACKa5ac43d98dhodlinator: ACKa5ac43d98dTree-SHA512: 570e6a4ff8bd79ef6554da3d01f36c0a7c6d2dd7dace8f8732eca98f4a8bc2284474a9beadeba783114fe2f3dd08b2041b3da7753bae0b7f881ec50668cb821f
This commit is contained in:
@@ -9,6 +9,7 @@ add_library(bitcoin_util STATIC EXCLUDE_FROM_ALL
|
||||
bytevectorhash.cpp
|
||||
chaintype.cpp
|
||||
check.cpp
|
||||
exec.cpp
|
||||
exception.cpp
|
||||
feefrac.cpp
|
||||
fs.cpp
|
||||
|
||||
75
src/util/exec.cpp
Normal file
75
src/util/exec.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2025 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <util/exec.h>
|
||||
|
||||
#include <util/fs.h>
|
||||
#include <util/subprocess.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace util {
|
||||
int ExecVp(const char* file, char* const argv[])
|
||||
{
|
||||
#ifndef WIN32
|
||||
return execvp(file, argv);
|
||||
#else
|
||||
std::vector<std::wstring> escaped_args;
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
for (char* const* arg_ptr{argv}; *arg_ptr; ++arg_ptr) {
|
||||
subprocess::util::quote_argument(converter.from_bytes(*arg_ptr), escaped_args.emplace_back(), false);
|
||||
}
|
||||
|
||||
std::vector<const wchar_t*> new_argv;
|
||||
new_argv.reserve(escaped_args.size() + 1);
|
||||
for (const auto& s : escaped_args) new_argv.push_back(s.c_str());
|
||||
new_argv.push_back(nullptr);
|
||||
return _wexecvp(converter.from_bytes(file).c_str(), new_argv.data());
|
||||
#endif
|
||||
}
|
||||
|
||||
fs::path GetExePath(std::string_view argv0)
|
||||
{
|
||||
// Try to figure out where executable is located. This does a simplified
|
||||
// search that won't work perfectly on every platform and doesn't need to,
|
||||
// as it is only currently being used in a convenience wrapper binary to try
|
||||
// to prioritize locally built or installed executables over system
|
||||
// executables.
|
||||
const fs::path argv0_path{fs::PathFromString(std::string{argv0})};
|
||||
fs::path path{argv0_path};
|
||||
std::error_code ec;
|
||||
#ifndef WIN32
|
||||
// If argv0 doesn't contain a path separator, it was invoked from the system
|
||||
// PATH and can be searched for there.
|
||||
if (!argv0_path.has_parent_path()) {
|
||||
if (const char* path_env = std::getenv("PATH")) {
|
||||
size_t start{0}, end{0};
|
||||
for (std::string_view paths{path_env}; end != std::string_view::npos; start = end + 1) {
|
||||
end = paths.find(':', start);
|
||||
fs::path candidate = fs::path(paths.substr(start, end - start)) / argv0_path;
|
||||
if (fs::is_regular_file(candidate, ec)) {
|
||||
path = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
wchar_t module_path[MAX_PATH];
|
||||
if (GetModuleFileNameW(nullptr, module_path, MAX_PATH) > 0) {
|
||||
path = fs::path{module_path};
|
||||
}
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
23
src/util/exec.h
Normal file
23
src/util/exec.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2025 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_UTIL_EXEC_H
|
||||
#define BITCOIN_UTIL_EXEC_H
|
||||
|
||||
#include <util/fs.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace util {
|
||||
//! Cross-platform wrapper for POSIX execvp function.
|
||||
//! Arguments and return value are the same as for POSIX execvp, and the argv
|
||||
//! array should consist of null terminated strings and be null terminated
|
||||
//! itself, like the POSIX function.
|
||||
int ExecVp(const char* file, char* const argv[]);
|
||||
//! Return path to current executable assuming it was invoked with argv0.
|
||||
//! If path could not be determined, returns an empty path.
|
||||
fs::path GetExePath(std::string_view argv0);
|
||||
} // namespace util
|
||||
|
||||
#endif // BITCOIN_UTIL_EXEC_H
|
||||
Reference in New Issue
Block a user