On program startup in C locale, switch to UTF-8 charset if possible

The UTF-8 charset is a superset of the C locale's 7-bit ASCII charset.

Since commit d284ce2fd6 (Initialize character set encoding on program
startup, 2026-02-02, v4.3.0-rc1~40^2) we set a single locale globally.
We can handle archives with UTF-8 paths by running in a locale with a
UTF-8 charset.

Fixes: #25226
Issue: #26903
Issue: #27562
This commit is contained in:
Brad King
2026-03-13 09:28:12 -04:00
parent 5ede3fb6c5
commit 40bcc1e9d5
8 changed files with 30 additions and 0 deletions
@@ -109,6 +109,7 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "ISO-8859-1" CACHE STRING "")
set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_Qt5 "ON" CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
@@ -5,6 +5,7 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database,import_std23" CACHE STRING "")
set(CMake_TEST_Rust "ON" CACHE STRING "")
@@ -7,6 +7,7 @@ set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "")
set(CMake_TEST_GUI "ON" CACHE BOOL "")
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
@@ -10,6 +10,7 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "")
set(CMake_TEST_ISPC "ON" CACHE STRING "")
endif()
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(CMake_TEST_MATH_OVERFLOW ON CACHE BOOL "")
set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "")
set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "")
@@ -3,6 +3,7 @@ set(BUILD_CursesDialog ON CACHE BOOL "")
set(CMAKE_PREFIX_PATH "$ENV{CI_PROJECT_DIR}/.gitlab/qt" CACHE STRING "")
set(CMake_TEST_Java OFF CACHE BOOL "")
set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "")
set(CMake_TEST_LOCALE_C_UTF8 ON CACHE BOOL "")
set(Python_FIND_REGISTRY NEVER CACHE STRING "")
include("${CMAKE_CURRENT_LIST_DIR}/configure_common.cmake")
+14
View File
@@ -17,6 +17,9 @@
# include "cm_fileno.hxx"
#else
# include <cm/string_view>
# include <cmext/string_view>
# include <unistd.h>
#endif
@@ -118,6 +121,17 @@ Globals::Globals()
#else
// On non-Windows platforms, we select the user's locale.
std::setlocale(LC_CTYPE, "");
// In the "C" locale try switching to a UTF-8 character set.
if (char const* locale = std::setlocale(LC_CTYPE, nullptr)) {
if (locale == "C"_s || locale == "POSIX"_s) {
std::setlocale(LC_CTYPE, "C.UTF-8")
# ifdef __APPLE__
|| std::setlocale(LC_CTYPE, "UTF-8")
# endif
|| std::setlocale(LC_CTYPE, "en_US.UTF-8");
}
}
#endif
}
+3
View File
@@ -694,6 +694,9 @@ add_RunCMake_test(export)
if(DEFINED CMake_TEST_LOCALE_CHARSET)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_LOCALE_CHARSET=${CMake_TEST_LOCALE_CHARSET})
endif()
if(DEFINED CMake_TEST_LOCALE_C_UTF8)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_LOCALE_C_UTF8=${CMake_TEST_LOCALE_C_UTF8})
endif()
if(CMake_TEST_MSYSTEM_PREFIX)
list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_MSYSTEM_PREFIX=${CMake_TEST_MSYSTEM_PREFIX})
endif()
@@ -15,6 +15,14 @@ endif()
run_cmake_script(Locale)
unset(RunCMake-stdout-file)
if(CMake_TEST_LOCALE_C_UTF8 OR CMAKE_HOST_WIN32)
set(RunCMake-stdout-file Locale-stdout-utf-8.txt)
run_cmake_command(LocaleC-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=C ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
run_cmake_command(LocaleBad-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=Bad ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
run_cmake_command(LocalePOSIX-UTF8 ${CMAKE_COMMAND} -E env LC_CTYPE=POSIX ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/Locale.cmake)
unset(RunCMake-stdout-file)
endif()
run_cmake(UnitTest)
run_cmake(Exherbo)
run_cmake(Ubuntu)