Merge bitcoin/bitcoin#32380: Modernize use of UTF-8 in Windows code
53e4951a5bSwitch to ANSI Windows API in `fsbridge::fopen()` function (Hennadii Stepanov)dbe770d921Switch to ANSI Windows API in `Win32ErrorString()` function (Hennadii Stepanov)06d0be4e22Remove no longer necessary `WinCmdLineArgs` class (Hennadii Stepanov)f366408492cmake: Set process code page to UTF-8 on Windows (Hennadii Stepanov)dccbb17806Set minimum supported Windows version to 1903 (May 2019 Update) (Hennadii Stepanov) Pull request description: The main goal is to remove [deprecated](https://github.com/bitcoin/bitcoin/issues/32361) code (removed in C++26). This PR employs Microsoft's modern [approach](https://learn.microsoft.com/en-us/windows/apps/design/globalizing/use-utf8-code-page) to handling UTF-8: > Until recently, Windows has emphasized "Unicode" -W variants over -A APIs. However, recent releases have used the ANSI code page and -A APIs as a means to introduce UTF-8 support to apps. If the ANSI code page is configured for UTF-8, then -A APIs typically operate in UTF-8. This model has the benefit of supporting existing code built with -A APIs without any code changes. TODO: - [x] Handle application manifests properly when building with MSVC. - [x] Bump the minimum supported Windows version to 1903 (May 2019 Update). - [x] Remove all remaining use cases of the deprecated `std:wstring_convert`. - The instance in `subprocess.h` will be addressed in a follow-up PR, as additional tests are likely needed. - The usage in `common/system.cpp` is handled in https://github.com/bitcoin/bitcoin/pull/32566. Resolves partially https://github.com/bitcoin/bitcoin/issues/32361. ACKs for top commit: laanwj: re-ACK53e4951a5bhodlinator: re-ACK53e4951a5bdavidgumberg: untested crACK https://github.com/bitcoin/bitcoin/commit/53e4951a5b5b9d166d278db4240513d09b447f58 Tree-SHA512: 0dbe9badca8b979ac2b4814fea6e4a7e53c423a1c96cb76ce894253137d3640a87631a5b22b9645e8f0c2a36a107122eb19ed8e92978c17384ffa8b9ab9993b5
This commit is contained in:
16 files changed
+27
-80
No files matched your search
@@ -1,10 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
<assemblyIdentity
|
<assemblyIdentity
|
||||||
type="win32"
|
type="win32"
|
||||||
name="org.bitcoincore.${target}"
|
name="org.bitcoincore.${target}"
|
||||||
version="${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_BUILD}.0"
|
version="${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_BUILD}.0"
|
||||||
/>
|
/>
|
||||||
|
<asmv3:application>
|
||||||
|
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
|
||||||
|
<activeCodePage>UTF-8</activeCodePage>
|
||||||
|
</asmv3:windowsSettings>
|
||||||
|
</asmv3:application>
|
||||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
<security>
|
<security>
|
||||||
<requestedPrivileges>
|
<requestedPrivileges>
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ wallet versions of Bitcoin Core are generally supported.
|
|||||||
Compatibility
|
Compatibility
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Bitcoin Core is supported and tested on operating systems using the
|
Bitcoin Core is supported and tested on the following operating systems or newer:
|
||||||
Linux Kernel 3.17+, macOS 14+, and Windows 10+. Bitcoin
|
Linux Kernel 3.17, macOS 14, and Windows 10 (version 1903). Bitcoin
|
||||||
Core should also work on most other Unix-like systems but is not as
|
Core should also work on most other Unix-like systems but is not as
|
||||||
frequently tested on them. It is not recommended to use Bitcoin Core on
|
frequently tested on them. It is not recommended to use Bitcoin Core on
|
||||||
unsupported systems.
|
unsupported systems.
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ if(BUILD_UTIL_CHAINSTATE)
|
|||||||
add_executable(bitcoin-chainstate
|
add_executable(bitcoin-chainstate
|
||||||
bitcoin-chainstate.cpp
|
bitcoin-chainstate.cpp
|
||||||
)
|
)
|
||||||
|
add_windows_application_manifest(bitcoin-chainstate)
|
||||||
# TODO: The `SKIP_BUILD_RPATH` property setting can be deleted
|
# TODO: The `SKIP_BUILD_RPATH` property setting can be deleted
|
||||||
# in the future after reordering Guix script commands to
|
# in the future after reordering Guix script commands to
|
||||||
# perform binary checks after the installation step.
|
# perform binary checks after the installation step.
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ add_executable(bench_bitcoin
|
|||||||
verify_script.cpp
|
verify_script.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_windows_application_manifest(bench_bitcoin)
|
||||||
|
|
||||||
include(TargetDataSources)
|
include(TargetDataSources)
|
||||||
target_raw_data_sources(bench_bitcoin NAMESPACE benchmark::data
|
target_raw_data_sources(bench_bitcoin NAMESPACE benchmark::data
|
||||||
data/block413567.raw
|
data/block413567.raw
|
||||||
|
|||||||
@@ -1328,10 +1328,6 @@ static int CommandLineRPC(int argc, char *argv[])
|
|||||||
|
|
||||||
MAIN_FUNCTION
|
MAIN_FUNCTION
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
common::WinCmdLineArgs winArgs;
|
|
||||||
std::tie(argc, argv) = winArgs.get();
|
|
||||||
#endif
|
|
||||||
SetupEnvironment();
|
SetupEnvironment();
|
||||||
if (!SetupNetworking()) {
|
if (!SetupNetworking()) {
|
||||||
tfm::format(std::cerr, "Error: Initializing networking failed\n");
|
tfm::format(std::cerr, "Error: Initializing networking failed\n");
|
||||||
|
|||||||
@@ -94,10 +94,6 @@ static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[
|
|||||||
MAIN_FUNCTION
|
MAIN_FUNCTION
|
||||||
{
|
{
|
||||||
ArgsManager& args = gArgs;
|
ArgsManager& args = gArgs;
|
||||||
#ifdef WIN32
|
|
||||||
common::WinCmdLineArgs winArgs;
|
|
||||||
std::tie(argc, argv) = winArgs.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int exit_status;
|
int exit_status;
|
||||||
std::unique_ptr<interfaces::Init> init = interfaces::MakeWalletInit(argc, argv, exit_status);
|
std::unique_ptr<interfaces::Init> init = interfaces::MakeWalletInit(argc, argv, exit_status);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <common/args.h>
|
#include <common/args.h>
|
||||||
|
#include <common/system.h>
|
||||||
#include <util/fs.h>
|
#include <util/fs.h>
|
||||||
#include <util/exec.h>
|
#include <util/exec.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
@@ -61,6 +62,8 @@ static void ExecCommand(const std::vector<const char*>& args, std::string_view a
|
|||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
SetupEnvironment();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandLine cmd{ParseCommandLine(argc, argv)};
|
CommandLine cmd{ParseCommandLine(argc, argv)};
|
||||||
if (cmd.show_version) {
|
if (cmd.show_version) {
|
||||||
|
|||||||
@@ -259,11 +259,6 @@ static bool AppInit(NodeContext& node)
|
|||||||
|
|
||||||
MAIN_FUNCTION
|
MAIN_FUNCTION
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
common::WinCmdLineArgs winArgs;
|
|
||||||
std::tie(argc, argv) = winArgs.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NodeContext node;
|
NodeContext node;
|
||||||
int exit_status;
|
int exit_status;
|
||||||
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);
|
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
#include <util/string.h>
|
#include <util/string.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <codecvt>
|
|
||||||
#include <shellapi.h>
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -879,30 +877,3 @@ void ArgsManager::LogArgs() const
|
|||||||
}
|
}
|
||||||
logArgsPrefix("Command-line arg:", "", m_settings.command_line_options);
|
logArgsPrefix("Command-line arg:", "", m_settings.command_line_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace common {
|
|
||||||
#ifdef WIN32
|
|
||||||
WinCmdLineArgs::WinCmdLineArgs()
|
|
||||||
{
|
|
||||||
wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
|
|
||||||
argv = new char*[argc];
|
|
||||||
args.resize(argc);
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
args[i] = utf8_cvt.to_bytes(wargv[i]);
|
|
||||||
argv[i] = &*args[i].begin();
|
|
||||||
}
|
|
||||||
LocalFree(wargv);
|
|
||||||
}
|
|
||||||
|
|
||||||
WinCmdLineArgs::~WinCmdLineArgs()
|
|
||||||
{
|
|
||||||
delete[] argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, char**> WinCmdLineArgs::get()
|
|
||||||
{
|
|
||||||
return std::make_pair(argc, argv);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} // namespace common
|
|
||||||
@@ -480,21 +480,4 @@ std::string HelpMessageGroup(const std::string& message);
|
|||||||
*/
|
*/
|
||||||
std::string HelpMessageOpt(const std::string& option, const std::string& message);
|
std::string HelpMessageOpt(const std::string& option, const std::string& message);
|
||||||
|
|
||||||
namespace common {
|
|
||||||
#ifdef WIN32
|
|
||||||
class WinCmdLineArgs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WinCmdLineArgs();
|
|
||||||
~WinCmdLineArgs();
|
|
||||||
std::pair<int, char**> get();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int argc;
|
|
||||||
char** argv;
|
|
||||||
std::vector<std::string> args;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
} // namespace common
|
|
||||||
|
|
||||||
#endif // BITCOIN_COMMON_ARGS_H
|
#endif // BITCOIN_COMMON_ARGS_H
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
#include <cassert>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <compat/compat.h>
|
#include <compat/compat.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -83,6 +84,7 @@ void SetupEnvironment()
|
|||||||
setenv("LC_ALL", "C.UTF-8", 1);
|
setenv("LC_ALL", "C.UTF-8", 1);
|
||||||
}
|
}
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
|
assert(GetACP() == CP_UTF8);
|
||||||
// Set the default input/output charset is utf-8
|
// Set the default input/output charset is utf-8
|
||||||
SetConsoleCP(CP_UTF8);
|
SetConsoleCP(CP_UTF8);
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
|||||||
@@ -478,11 +478,6 @@ static void SetupUIArgs(ArgsManager& argsman)
|
|||||||
|
|
||||||
int GuiMain(int argc, char* argv[])
|
int GuiMain(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
common::WinCmdLineArgs winArgs;
|
|
||||||
std::tie(argc, argv) = winArgs.get();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
|
std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
|
||||||
|
|
||||||
SetupEnvironment();
|
SetupEnvironment();
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ add_executable(test_bitcoin-qt
|
|||||||
../../init/bitcoin-qt.cpp
|
../../init/bitcoin-qt.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_windows_application_manifest(test_bitcoin-qt)
|
||||||
|
|
||||||
target_link_libraries(test_bitcoin-qt
|
target_link_libraries(test_bitcoin-qt
|
||||||
core_interface
|
core_interface
|
||||||
bitcoinqt
|
bitcoinqt
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ add_executable(fuzz
|
|||||||
vecdeque.cpp
|
vecdeque.cpp
|
||||||
versionbits.cpp
|
versionbits.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_windows_application_manifest(fuzz)
|
||||||
|
|
||||||
target_link_libraries(fuzz
|
target_link_libraries(fuzz
|
||||||
core_interface
|
core_interface
|
||||||
fuzzer_interface
|
fuzzer_interface
|
||||||
|
|||||||
+1
-3
@@ -12,7 +12,6 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#else
|
#else
|
||||||
#include <codecvt>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -28,8 +27,7 @@ FILE *fopen(const fs::path& p, const char *mode)
|
|||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
return ::fopen(p.c_str(), mode);
|
return ::fopen(p.c_str(), mode);
|
||||||
#else
|
#else
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
|
return ::fopen(p.utf8string().c_str(), mode);
|
||||||
return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-10
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <locale>
|
|
||||||
#include <codecvt>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string SysErrorString(int err)
|
std::string SysErrorString(int err)
|
||||||
@@ -41,16 +39,13 @@ std::string SysErrorString(int err)
|
|||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
std::string Win32ErrorString(int err)
|
std::string Win32ErrorString(int err)
|
||||||
{
|
{
|
||||||
wchar_t buf[256];
|
char buf[256];
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
buf, ARRAYSIZE(buf), nullptr))
|
buf, ARRAYSIZE(buf), nullptr)) {
|
||||||
{
|
return strprintf("%s (%d)", buf, err);
|
||||||
return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return strprintf("Unknown error (%d)", err);
|
return strprintf("Unknown error (%d)", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user