Суть
src/engine/core/conf.h в ветке _WIN32 определяет глобальные макросы до подключения стандартной библиотеки:
#define ssize_t int
#define socklen_t int
#undef min / #define min min
#undef max / #define max max
#define __func__ ""
#define mkdir(str, int) _mkdir(str)
Это глобальное загрязнение препроцессора. Если любой TU включает проектный заголовок (тянущий conf.h) раньше системных заголовков, эти макросы «остывают» в стандартную/интринсик-библиотеку и могут её сломать.
Как проявилось
В #3373 новый тест tests/file_crc.cpp (первая строка — #include "utils/file_crc.h") оказался первым в unity-чанке. Цепочка file_crc.h → conf.h → sysdep.h → structs.h → <vector> → … → clang intrin.h → mmintrin.h собиралась clang-cl'ом, и __v2si (MMX-вектор из двух int) схлопывался в скалярный int:
mmintrin.h: error: cannot initialize a parameter of type
'…__vector_size__(2 * sizeof(int)) int' with an rvalue of type '__v2si' (aka 'int')
Job windows / Clang / Base падал. На master он зелёный — там первым в чанке был другой тест, подключающий <gtest/gtest.h> первой строкой, поэтому системные/интринсик-заголовки включались в чистом состоянии.
Это не баг Meson и не компилятора
Unity-сборка — лишь катализатор (переставила порядок файлов в чанке). Эффект воспроизведётся и без Meson: любой обычный .cpp, который на clang-cl/Windows включает проектный заголовок раньше системного, упрётся в то же. Корень — гигиена заголовков: conf.h гадит в глобальные макросы перед системной библиотекой.
Обход (уже в #3373)
Коммит 2deb69b: в новых тест-файлах <gtest/gtest.h> подключается первым — системные/интринсик-заголовки включаются в чистом виде. Это лечит симптом, не причину.
Что чинить по-настоящему
conf.h не должен определять глобальные макросы: ssize_t/socklen_t → typedef; min/max нейтрализовать через NOMINMAX + <algorithm>, а не #define; __func__ "" — убрать/загардить; mkdir → inline-обёртка.
- Как минимум сам
conf.h должен подтягивать нужные системные заголовки до своих дефайнов, чтобы порядок включения в TU не имел значения.
- Точный макрос-виновник для
__v2si не изолирован (clang-cl локально не воспроизводится) — нужен прогон/бисект на Windows.
Refs #3373
Суть
src/engine/core/conf.hв ветке_WIN32определяет глобальные макросы до подключения стандартной библиотеки:Это глобальное загрязнение препроцессора. Если любой TU включает проектный заголовок (тянущий
conf.h) раньше системных заголовков, эти макросы «остывают» в стандартную/интринсик-библиотеку и могут её сломать.Как проявилось
В #3373 новый тест
tests/file_crc.cpp(первая строка —#include "utils/file_crc.h") оказался первым в unity-чанке. Цепочкаfile_crc.h → conf.h → sysdep.h → structs.h → <vector> → … → clang intrin.h → mmintrin.hсобиралась clang-cl'ом, и__v2si(MMX-вектор из двух int) схлопывался в скалярныйint:Job
windows / Clang / Baseпадал. На master он зелёный — там первым в чанке был другой тест, подключающий<gtest/gtest.h>первой строкой, поэтому системные/интринсик-заголовки включались в чистом состоянии.Это не баг Meson и не компилятора
Unity-сборка — лишь катализатор (переставила порядок файлов в чанке). Эффект воспроизведётся и без Meson: любой обычный
.cpp, который на clang-cl/Windows включает проектный заголовок раньше системного, упрётся в то же. Корень — гигиена заголовков:conf.hгадит в глобальные макросы перед системной библиотекой.Обход (уже в #3373)
Коммит 2deb69b: в новых тест-файлах
<gtest/gtest.h>подключается первым — системные/интринсик-заголовки включаются в чистом виде. Это лечит симптом, не причину.Что чинить по-настоящему
conf.hне должен определять глобальные макросы:ssize_t/socklen_t→typedef;min/maxнейтрализовать черезNOMINMAX+<algorithm>, а не#define;__func__ ""— убрать/загардить;mkdir→inline-обёртка.conf.hдолжен подтягивать нужные системные заголовки до своих дефайнов, чтобы порядок включения в TU не имел значения.__v2siне изолирован (clang-cl локально не воспроизводится) — нужен прогон/бисект на Windows.Refs #3373