From b02ae60a768007c18254c8a27c17857fa8d564d0 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 2 Feb 2026 15:02:37 -0500 Subject: [PATCH] cmake_host_system_information: Add query for the locale's charset Issue: #27562 --- .gitlab/ci/configure_fedora43_makefiles.cmake | 1 + .gitlab/ci/configure_fedora43_ninja.cmake | 1 + .gitlab/ci/configure_macos_arm64_ninja.cmake | 1 + .gitlab/ci/configure_macos_x86_64_ninja.cmake | 1 + .gitlab/ci/configure_windows_common.cmake | 1 + .gitlab/ci/env_fedora43_makefiles.sh | 3 +++ .gitlab/ci/env_fedora43_ninja.sh | 3 +++ .../command/cmake_host_system_information.rst | 11 ++++++++++ Help/manual/cmake-language.7.rst | 5 +++++ Help/release/dev/cmake-locale.rst | 6 ++++++ .../cmCMakeHostSystemInformationCommand.cxx | 20 +++++++++++++++++++ Tests/RunCMake/CMakeLists.txt | 3 +++ .../Locale-stdout-iso-8859-1.txt | 1 + .../Locale-stdout-utf-8.txt | 1 + .../Locale-stdout.txt | 1 + .../Locale.cmake | 2 ++ .../QueryKeys-stdout.txt | 1 + .../QueryKeys.cmake | 1 + .../RunCMakeTest.cmake | 8 ++++++++ 19 files changed, 71 insertions(+) create mode 100644 Help/release/dev/cmake-locale.rst create mode 100644 Tests/RunCMake/cmake_host_system_information/Locale-stdout-iso-8859-1.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Locale-stdout-utf-8.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Locale-stdout.txt create mode 100644 Tests/RunCMake/cmake_host_system_information/Locale.cmake diff --git a/.gitlab/ci/configure_fedora43_makefiles.cmake b/.gitlab/ci/configure_fedora43_makefiles.cmake index b5a9f30573..3ddf236d2e 100644 --- a/.gitlab/ci/configure_fedora43_makefiles.cmake +++ b/.gitlab/ci/configure_fedora43_makefiles.cmake @@ -108,6 +108,7 @@ set(CMake_TEST_IPO_WORKS_Fortran "ON" CACHE BOOL "") 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_Qt5 "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 "") diff --git a/.gitlab/ci/configure_fedora43_ninja.cmake b/.gitlab/ci/configure_fedora43_ninja.cmake index 5c75c1e120..a67e40a299 100644 --- a/.gitlab/ci/configure_fedora43_ninja.cmake +++ b/.gitlab/ci/configure_fedora43_ninja.cmake @@ -4,6 +4,7 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "") set(CMake_TEST_CPACK_APPIMAGE_RUNTIME_FILE "$ENV{CI_PROJECT_DIR}/.gitlab/appimagetool/lib/appimagetool/runtime" CACHE FILEPATH "") set(CMake_TEST_ISPC "ON" CACHE STRING "") endif() +set(CMake_TEST_LOCALE_CHARSET "UTF-8" CACHE STRING "") set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,export_bmi,install_bmi,shared,bmionly,build_database" CACHE STRING "") set(CMake_TEST_Rust "ON" CACHE STRING "") set(CMake_TEST_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "") diff --git a/.gitlab/ci/configure_macos_arm64_ninja.cmake b/.gitlab/ci/configure_macos_arm64_ninja.cmake index 3bfdcf2d4f..c1924fe94d 100644 --- a/.gitlab/ci/configure_macos_arm64_ninja.cmake +++ b/.gitlab/ci/configure_macos_arm64_ninja.cmake @@ -6,6 +6,7 @@ set(CMake_TEST_FindOpenMP "ON" CACHE BOOL "") 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_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERSION "1.2" CACHE STRING "") diff --git a/.gitlab/ci/configure_macos_x86_64_ninja.cmake b/.gitlab/ci/configure_macos_x86_64_ninja.cmake index 48f9dcbf91..1af144f2c6 100644 --- a/.gitlab/ci/configure_macos_x86_64_ninja.cmake +++ b/.gitlab/ci/configure_macos_x86_64_ninja.cmake @@ -9,6 +9,7 @@ set(CMake_TEST_GUI "ON" CACHE BOOL "") 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_TLS_VERIFY_URL "https://gitlab.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERIFY_URL_BAD "https://badtls-expired.kitware.com" CACHE STRING "") set(CMake_TEST_TLS_VERSION "1.2" CACHE STRING "") diff --git a/.gitlab/ci/configure_windows_common.cmake b/.gitlab/ci/configure_windows_common.cmake index 7467cfdf4c..124688531d 100644 --- a/.gitlab/ci/configure_windows_common.cmake +++ b/.gitlab/ci/configure_windows_common.cmake @@ -2,6 +2,7 @@ set(BUILD_QtDialog ON CACHE BOOL "") 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(Python_FIND_REGISTRY NEVER CACHE STRING "") include("${CMAKE_CURRENT_LIST_DIR}/configure_common.cmake") diff --git a/.gitlab/ci/env_fedora43_makefiles.sh b/.gitlab/ci/env_fedora43_makefiles.sh index 217ff305df..f02e487f1e 100644 --- a/.gitlab/ci/env_fedora43_makefiles.sh +++ b/.gitlab/ci/env_fedora43_makefiles.sh @@ -1,3 +1,6 @@ if test "$CMAKE_CI_NIGHTLY" = "true"; then source .gitlab/ci/ispc-env.sh fi + +# Test in a Latin-1 locale. +export LANG=en_US.ISO-8859-1 diff --git a/.gitlab/ci/env_fedora43_ninja.sh b/.gitlab/ci/env_fedora43_ninja.sh index a2b941b61c..0ef4bcea03 100644 --- a/.gitlab/ci/env_fedora43_ninja.sh +++ b/.gitlab/ci/env_fedora43_ninja.sh @@ -2,3 +2,6 @@ if test "$CMAKE_CI_NIGHTLY" = "true"; then source .gitlab/ci/appimagetool-env.sh source .gitlab/ci/ispc-env.sh fi + +# Test in a UTF-8 locale. +export LANG=en_US.UTF-8 diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 73effab66b..35360c28fe 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -137,6 +137,17 @@ queried. The list of queried values is stored in ````. Human readable full processor description +``LOCALE_CHARSET`` + .. versionadded:: 4.3 + + The locale's character set, if known, otherwise empty. + + This is the :ref:`encoding ` expected + in :manual:`cmake-language(7)` files and scripts: + + * On Windows, this is always ``UTF-8``. + * On UNIX and macOS, this is based on the current locale. + ``OS_NAME`` .. versionadded:: 3.10 diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index 908c46ceff..777ef0b7ba 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -78,6 +78,11 @@ Furthermore, CMake 3.0 and above allow a leading UTF-8 .. _Byte-Order Mark: https://en.wikipedia.org/wiki/Byte_order_mark +.. versionadded:: 4.3 + + The :command:`cmake_host_system_information` command's ``LOCALE_CHARSET`` + query returns the expected character set encoding. + Source Files ------------ diff --git a/Help/release/dev/cmake-locale.rst b/Help/release/dev/cmake-locale.rst new file mode 100644 index 0000000000..ce91492cb9 --- /dev/null +++ b/Help/release/dev/cmake-locale.rst @@ -0,0 +1,6 @@ +cmake-locale +------------ + +* The :command:`cmake_host_system_information` command gained a + ``LOCALE_CHARSET`` query for the expected :manual:`cmake-language(7)` + script encoding. diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 514f00c25c..55e93ee0cc 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -15,6 +15,10 @@ #include #include +#if !defined(_WIN32) +# include +#endif + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/String.h" @@ -74,6 +78,22 @@ cm::optional GetValue(cmsys::SystemInformation& info, if (key == "FQDN"_s) { return ValueToString(info.GetFullyQualifiedDomainName()); } + if (key == "LOCALE_CHARSET"_s) { +#if defined(_WIN32) + // On Windows we always use UTF-8. + return ValueToString("UTF-8"); +#else + // On non-Windows platforms we use the locale's encoding. + if (char const* charset = nl_langinfo(CODESET)) { + if (cmsysString_strcasecmp(charset, "utf-8") == 0 || + cmsysString_strcasecmp(charset, "utf8") == 0) { + charset = "UTF-8"; + } + return ValueToString(charset); + } + return ValueToString(""); +#endif + } if (key == "TOTAL_VIRTUAL_MEMORY"_s) { return ValueToString(info.GetTotalVirtualMemory()); } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 2fc19c7721..6d23fc8a14 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -685,6 +685,9 @@ if(WIN32) endif() add_RunCMake_test(execute_process) 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(CMake_TEST_MSYSTEM_PREFIX) list(APPEND cmake_host_system_information_ARGS -DCMake_TEST_MSYSTEM_PREFIX=${CMake_TEST_MSYSTEM_PREFIX}) endif() diff --git a/Tests/RunCMake/cmake_host_system_information/Locale-stdout-iso-8859-1.txt b/Tests/RunCMake/cmake_host_system_information/Locale-stdout-iso-8859-1.txt new file mode 100644 index 0000000000..2307984bc4 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Locale-stdout-iso-8859-1.txt @@ -0,0 +1 @@ +^-- LOCALE_CHARSET='ISO-8859-1'$ diff --git a/Tests/RunCMake/cmake_host_system_information/Locale-stdout-utf-8.txt b/Tests/RunCMake/cmake_host_system_information/Locale-stdout-utf-8.txt new file mode 100644 index 0000000000..f15d5c9615 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Locale-stdout-utf-8.txt @@ -0,0 +1 @@ +^-- LOCALE_CHARSET='UTF-8'$ diff --git a/Tests/RunCMake/cmake_host_system_information/Locale-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Locale-stdout.txt new file mode 100644 index 0000000000..3cb5e721ca --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Locale-stdout.txt @@ -0,0 +1 @@ +^-- LOCALE_CHARSET='[^']+'$ diff --git a/Tests/RunCMake/cmake_host_system_information/Locale.cmake b/Tests/RunCMake/cmake_host_system_information/Locale.cmake new file mode 100644 index 0000000000..32b31be27a --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Locale.cmake @@ -0,0 +1,2 @@ +cmake_host_system_information(RESULT charset QUERY LOCALE_CHARSET) +message(STATUS "LOCALE_CHARSET='${charset}'") diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt index 1a4322141e..3575c84fed 100644 --- a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt @@ -23,6 +23,7 @@ -- PROCESSOR_SERIAL_NUMBER=`.*` -- PROCESSOR_NAME=`.*` -- PROCESSOR_DESCRIPTION=`.*` +-- LOCALE_CHARSET=`[^`]+` -- OS_NAME=`.*` -- OS_RELEASE=`.*` -- OS_VERSION=`.*` diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake index 2b497fbbc8..408dd0d9d4 100644 --- a/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake @@ -28,6 +28,7 @@ try_and_print(HAS_L1_CACHE) try_and_print(PROCESSOR_SERIAL_NUMBER) try_and_print(PROCESSOR_NAME) try_and_print(PROCESSOR_DESCRIPTION) +try_and_print(LOCALE_CHARSET) try_and_print(OS_NAME) try_and_print(OS_RELEASE) try_and_print(OS_VERSION) diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake index 3917913e37..803518af8a 100644 --- a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -7,6 +7,14 @@ run_cmake(BadArg3) run_cmake(QueryList) run_cmake(QueryKeys) +if(CMake_TEST_LOCALE_CHARSET STREQUAL "UTF-8" OR CMAKE_HOST_WIN32) + set(RunCMake-stdout-file Locale-stdout-utf-8.txt) +elseif(CMake_TEST_LOCALE_CHARSET STREQUAL "ISO-8859-1") + set(RunCMake-stdout-file Locale-stdout-iso-8859-1.txt) +endif() +run_cmake_script(Locale) +unset(RunCMake-stdout-file) + run_cmake(UnitTest) run_cmake(Exherbo) run_cmake(Ubuntu)