From ef58b42da02ce760e73b61d102797d2351f9124a Mon Sep 17 00:00:00 2001 From: "../" Date: Fri, 11 Sep 2026 04:47:55 +0800 Subject: [PATCH] Pass /utf-8 to MSVC so the build survives non-CP1252 host codepages. Several BOM-less UTF-8 sources make cl.exe fall back to the system ANSI codepage; library/src/api/dds_constants.hpp line 47 holds an em dash that CP936 cannot decode, so the compile fails with C4819 escalated by /WX into C2220. English CP1252 CI runners decode those bytes without complaint, which is why the breakage only surfaces on localized Windows. The flag belongs in the //:build_windows and //:debug_build_windows select arms of DDS_CPPOPTS, not in a build:windows --cxxopt: that flag keys off the host OS and therefore also reaches wasm transitions, where clang rejects an MSVC-only flag with "no such file or directory: '/utf-8'". ci_windows_cppopts_test now guards both halves, and fails without the flag. --- CPPVARIABLES.bzl | 7 ++++++ python/tests/ci_windows_cppopts_test.py | 30 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/CPPVARIABLES.bzl b/CPPVARIABLES.bzl index b63ed4bfa..70c033d26 100644 --- a/CPPVARIABLES.bzl +++ b/CPPVARIABLES.bzl @@ -40,13 +40,20 @@ DDS_CPPOPTS = select({ # Optimisation (/O2, /Od) and language standard (/std) come from Bazel's # compilation_mode and the patched MSVC default_cpp_std (/std:c++20). # Restating them here overrides the toolchain and triggers MSVC D9025. + # /utf-8 must stay in these arms, not a global --cxxopt: wasm-transition + # targets match //:build_wasm and would reject an MSVC-only flag. "//:build_windows": [ + # Without /utf-8, MSVC decodes BOM-less UTF-8 sources in the system ANSI + # codepage; on hosts below CP1252 that raises C4819, which /WX turns into + # error C2220. + "/utf-8", "/W4", "/WX", "/permissive-", ], "//:debug_build_windows": [ "/Zi", + "/utf-8", "/W4", "/WX", "/permissive-", diff --git a/python/tests/ci_windows_cppopts_test.py b/python/tests/ci_windows_cppopts_test.py index 85c922018..5e33da681 100644 --- a/python/tests/ci_windows_cppopts_test.py +++ b/python/tests/ci_windows_cppopts_test.py @@ -113,6 +113,36 @@ def test_windows_cppopts_do_not_override_toolchain_cxx_standard(self) -> None: f"{label} must not set /std:; MSVC default_cpp_std is C++20", ) + def test_windows_cppopts_set_source_charset_utf8(self) -> None: + """BOM-less UTF-8 sources make MSVC fall back to the system ANSI + codepage; below CP1252 that raises C4819, which /WX turns into C2220. + """ + text = (_repo_root() / "CPPVARIABLES.bzl").read_text(encoding="utf-8") + for label, block in ( + ("build_windows", _windows_cppopts_block(text)), + ("debug_build_windows", _debug_windows_cppopts_block(text)), + ): + self.assertIn( + '"/utf-8"', + block, + f"{label} must pass /utf-8 so MSVC reads UTF-8 sources on any host codepage", + ) + + def test_windows_bazelrc_does_not_set_utf8_cxxopt(self) -> None: + """/utf-8 is MSVC-only. A build:windows --cxxopt keys off the host OS, + so it also reaches wasm transitions, where clang fails with + "no such file or directory: '/utf-8'". + """ + bazelrc = (_repo_root() / ".bazelrc").read_text(encoding="utf-8") + for flag in ("--cxxopt", "--host_cxxopt"): + self.assertIsNone( + re.search( + rf"(?m)^build:windows\s+{re.escape(flag)}=/utf-8\b", + bazelrc, + ), + f"build:windows must not set {flag}=/utf-8 (leaks into wasm)", + ) + def test_windows_bazelrc_keeps_default_cpp_std_without_host_cxxopt(self) -> None: """default_cpp_std (patched to /std:c++20) covers googletest and every MSVC cc_* compile. Do not disable it, and do not add build:windows