Merge pull request #13910 from DonRyuzaki/fix/configure-seed-unicode-separators

fix(tools): preserve Unicode cache separators
This commit is contained in:
Adrià authored and GitHub committed 2026-11-01 09:40:34 +01:00
commit 8decbb2ee2
3 files changed
+67 -1

No files matched your search

+1 -1
View File
@@ -15,7 +15,7 @@ QUOTED_DELIMITER = re.compile(r'":[A-Z]+=')
def checks(cache):
found, doc = {}, []
for line in Path(cache).read_text(encoding="utf-8-sig").splitlines():
for line in Path(cache).read_text(encoding="utf-8-sig").split("\n"):
if line.startswith("//"):
doc.append(line)
continue
@@ -47,6 +47,22 @@ class Tests(unittest.TestCase):
self.assertEqual(r.returncode,2)
self.assertEqual(r.stdout,"")
def test_value_changes_after_unicode_separators_are_reported(self):
baseline, candidate = self.root / "baseline", self.root / "candidate"
for separator in ("\u0085", "\u2028", "\u2029"):
with self.subTest(separator=separator):
before, after = f"prefix{separator}before", f"prefix{separator}after"
baseline.write_text(f"//Test FEATURE\nFEATURE:INTERNAL={before}\n", encoding="utf-8")
candidate.write_text(f"//Test FEATURE\nFEATURE:INTERNAL={after}\n", encoding="utf-8")
result = self.run_tool(baseline, candidate)
self.assertEqual(result.returncode, 1, result.stderr)
self.assertEqual(json.loads(result.stdout), {
"added": [], "removed": [], "changed": [{
"name": "FEATURE", "before": {"value": before, "help": "Test FEATURE"},
"after": {"value": after, "help": "Test FEATURE"},
}],
})
if __name__ == "__main__":
unittest.main()
+50
View File
@@ -327,6 +327,56 @@ class ConfigureSeedRoundTripTests(ConfigureSeedProject):
class ChecksParsingTests(unittest.TestCase):
def test_unicode_line_separators_are_preserved_in_cache_fields(self):
entries = {
f"FEATURE_{index}_{separator}_TAIL": (f"before{separator}after", f"Test help{separator}tail")
for index, separator in enumerate(("\u0085", "\u2028", "\u2029"))
}
with tempfile.TemporaryDirectory() as directory:
cache = Path(directory) / "CMakeCache.txt"
for newline in ("\n", "\r\n"):
for encoding in ("utf-8", "utf-8-sig"):
with self.subTest(newline=newline, encoding=encoding):
text = newline.join(f"//{doc}{newline}{name}:INTERNAL={value}"
for name, (value, doc) in entries.items())
cache.write_bytes(text.encode(encoding))
self.assertEqual(configure_seed.checks(cache), entries)
@unittest.skipUnless(shutil.which("cmake") and shutil.which("ninja"), "CMake and Ninja are required for cache round trips")
def test_unicode_cache_fields_survive_real_cmake_seed_round_trip(self):
entries = {
f"FEATURE_{index}_{separator}_TAIL": (f"before{separator}after", f"Test help{separator}tail")
for index, separator in enumerate(("\u0085", "\u2028", "\u2029"))
}
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
source = root / "source"
source.mkdir()
lines = ["cmake_minimum_required(VERSION 3.20)", "project(unicode_cache NONE)"]
for index, (name, (value, doc)) in enumerate(entries.items()):
lines.extend(("if(NOT REQUIRE_SEED)",
f"set({configure_seed.quote(name)} {configure_seed.quote(value)} CACHE INTERNAL {configure_seed.quote(doc)})",
"endif()",
f"get_property(help CACHE {configure_seed.quote(name)} PROPERTY HELPSTRING)",
f"get_property(value CACHE {configure_seed.quote(name)} PROPERTY VALUE)",
f'file(WRITE "${{CMAKE_BINARY_DIR}}/{index}.help" "${{help}}")',
f'file(WRITE "${{CMAKE_BINARY_DIR}}/{index}.value" "${{value}}")'))
(source / "CMakeLists.txt").write_text("\n".join(lines) + "\n", encoding="utf-8")
first, second = root / "first", root / "second"
configured = subprocess.run(["cmake", "-S", str(source), "-B", str(first), "-G", "Ninja"], capture_output=True)
self.assertEqual(configured.returncode, 0, configured.stderr.decode("utf-8", errors="replace"))
cache = first / "CMakeCache.txt"
self.assertEqual(configure_seed.checks(cache), entries)
seed = root / "seed.cmake"
subprocess.run([sys.executable, str(TOOL), str(cache), str(seed)], check=True, capture_output=True)
subprocess.run(["cmake", "-C", str(seed), "-DREQUIRE_SEED=ON", "-S", str(source), "-B", str(second), "-G", "Ninja"],
check=True, capture_output=True)
self.assertEqual(configure_seed.checks(second / "CMakeCache.txt"), entries)
for index, (value, doc) in enumerate(entries.values()):
for build in (first, second):
self.assertEqual((build / f"{index}.value").read_text(encoding="utf-8"), value)
self.assertEqual((build / f"{index}.help").read_text(encoding="utf-8"), doc)
def test_architecture_dependent_sizes_leave_compile_guards_to_cmake(self):
entries = {
"ARCH_SIZE": ("0", "CHECK_TYPE_SIZE: sizeof(architecture_type)"),