Skip to content

Commit 10224fb

Browse files
committed
macOS 27: the std module builds; the -D compatibility rule; host-shaped test fixes
macOS 27 (measured on the xcode-27 image, #659): the 27.0 SDK's math.h leaves INFINITY and NAN to <float.h> once modules are on, and clang 22's header does not supply them under -std=c++23, so libc++'s std module stopped building. apple_float_macro_words (hostflags.cppm) states both with the SDK's own GNU-mode spellings for clang on an Apple target; its readers quote the words their own way (ninja text, the std module command, graph std flags, build program argv). gnu++23, -U__STRICT_ANSI__ and -D__need_infinity_nan were rejected for their effect beyond the defect. The raw clang steps of ci-macos state the same words. Compatibility: an element beginning with -D or /D that contains a space is one word, verbatim, as every release since #234 passed it (SPEC-004 §8 rule 8). Windows: flag_element no longer quotes a backslash the syntax does not read as an escape, normalize_include_flags keeps the spelling of an unchanged element, and the split_flags quoting tests follow the host's reader.
1 parent 9460bac commit 10224fb

17 files changed

Lines changed: 246 additions & 56 deletions

‎.agents/docs/2026-09-17-655-implementation-plan.md‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,57 @@ limit, and the second names `xcode-27` and reads
243243
version 21.0.0` with `ImageOS=macos27` (run on 2026-09-16T19:16Z). Because the label names an Xcode and its
244244
base OS has changed once, every macOS 27 leg asserts that `sw_vers` reports 27.
245245

246+
## 5.2 The first macOS 27 run: the std module does not build
247+
248+
Both macOS 27 legs failed on their first run (runs 35139712291 and
249+
35139712295): the std module precompile with llvm 22.1.8 stops at
250+
`<complex>:1012: use of undeclared identifier 'INFINITY'` (14 errors), in the
251+
raw clang step and in mcpp's own std module build. The maintainer asked for the
252+
fix in the same pull request, with the host kept to the minimum. Three probe
253+
rounds on the `xcode-27` image (#659) read:
254+
255+
- The 27.0 SDK's `<math.h>` defines `INFINITY` and `NAN` itself only when
256+
`__has_feature(modules)` is false; with modules on it includes `<float.h>`
257+
with `__need_infinity_nan` and expects the compiler's header to supply them.
258+
- A module interface unit has `__has_feature(modules)` true; a plain unit does
259+
not.
260+
- `-std=c++23` and `-std=c++26` fail; `-std=gnu++23`, `-U__STRICT_ANSI__`, the
261+
26.5 SDK, `-D__need_infinity_nan`, and `-DINFINITY=HUGE_VALF
262+
-DNAN=__builtin_nanf("0x7fc00000")` build. `-fbuiltin-headers-in-system-modules`
263+
and `-fno-implicit-module-maps` do not.
264+
- The CLT SDK and the Xcode SDK on the image are the same 27.0 SDK, so the
265+
sysroot choice is not the cause.
266+
267+
Adopted: `apple_float_macro_words` (hostflags.cppm) states the two macros with
268+
the SDK's own GNU-mode spellings for clang on an Apple target. The alternatives
269+
were rejected on their effect beyond the defect: `gnu++23` changes the language
270+
dialect of every unit, `-U__STRICT_ANSI__` exposes non-standard declarations of
271+
the C library, and `-D__need_infinity_nan` makes the first inclusion of
272+
`<float.h>` supply only the two macros, so a unit that includes it once loses
273+
`FLT_MAX` (clang's `float.h` lines 15-46). The identical spellings make the
274+
redefinition in the SDK's non-module path silent; plain C and C++ units
275+
including `<math.h>`, `<cmath>`, `<float.h>` and `<cfloat>` build with
276+
`-Wall -Werror` on the 27.0 SDK. The value holds quotes and parentheses, so the
277+
decision is a list of words and each reader quotes it: the ninja compile flags
278+
(`ninja_command_word`), the std module command (single quotes), the
279+
graph-supplied std module flags (`shq`) and a build program's argv (none). The
280+
decision reads the target triple only; it reads nothing from the host.
281+
282+
The same round found two host-shaped test defects on the Windows runner of the
283+
first push, both in this pull request's own code: `normalize_include_flags`
284+
wrote every word back through `flag_element`, which quoted any backslash, so
285+
Windows paths came back single-quoted; and two `split_flags` tests assumed
286+
POSIX quoting on every host. `flag_element` now quotes a backslash only where
287+
the syntax would read it as an escape, an element whose words did not change
288+
keeps its spelling, and the POSIX-quoting tests are POSIX-only with a Windows
289+
counterpart.
290+
291+
It also found a compatibility defect of the syntax itself: `NinjaBackend.
292+
QuotesFlagValueWithSpace` (mcpp#234) failed, because `-DT=long long` read as
293+
two words. Every release since #234 passed such an element as one argument, so
294+
the syntax gained one exception (SPEC-004 §8 rule 8): an element that begins
295+
with `-D` or `/D` and contains a space is one word, verbatim.
296+
246297
## 8. Residuals
247298

248299
- `ldflags`, `dialect_cxxflags` and `std-module-flags` keep their current

‎.github/workflows/ci-macos.yml‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ jobs:
7272
echo "=== Module manifest ==="
7373
"$CXX" -print-library-module-manifest-path 2>/dev/null || echo "(not available)"
7474
75+
# THE TWO FLOATING MACROS mcpp STATES FOR AN APPLE TARGET
76+
# (src/toolchain/hostflags.cppm, apple_float_macro_words). The macOS 27
77+
# SDK leaves INFINITY and NAN to <float.h> once modules are on, and clang
78+
# 22's header does not supply them in a -std=c++23 compile, so these raw
79+
# compiles state them the way mcpp does. Unquoted words with no spaces, so
80+
# plain word splitting of the variable is exact.
81+
- name: The floating macros mcpp states for an Apple target
82+
run: echo 'APPLE_FLOAT_MACROS=-DINFINITY=HUGE_VALF -DNAN=__builtin_nanf("0x7fc00000")' >> "$GITHUB_ENV"
83+
7584
- name: Test — non-module C++23 compilation
7685
run: |
7786
WORK=$(mktemp -d)
@@ -84,7 +93,7 @@ jobs:
8493
return 0;
8594
}
8695
EOF
87-
"$CXX" -std=c++23 -o hello main.cpp
96+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -o hello main.cpp
8897
./hello
8998
9099
- name: Test — import std (two-stage module compilation)
@@ -103,11 +112,11 @@ jobs:
103112
104113
echo "=== Step 1: Precompile std module ==="
105114
mkdir -p pcm.cache
106-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
115+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
107116
--precompile "$STD_CPPM" -o pcm.cache/std.pcm
108117
109118
echo "=== Step 2: Compile std.pcm → std.o ==="
110-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
119+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
111120
pcm.cache/std.pcm -c -o std.o
112121
113122
echo "=== Step 3: Compile main.cpp with import std ==="
@@ -118,7 +127,7 @@ jobs:
118127
return 0;
119128
}
120129
EOF
121-
"$CXX" -std=c++23 -fmodule-file=std=pcm.cache/std.pcm -c main.cpp -o main.o
130+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -fmodule-file=std=pcm.cache/std.pcm -c main.cpp -o main.o
122131
123132
echo "=== Step 4: Link ==="
124133
"$CXX" main.o std.o -o hello_modules
@@ -141,16 +150,16 @@ jobs:
141150
142151
mkdir -p pcm.cache
143152
# Build std first
144-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
153+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
145154
--precompile "$STD_CPPM" -o pcm.cache/std.pcm
146-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
155+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
147156
pcm.cache/std.pcm -c -o std.o
148157
149158
# Build std.compat (depends on std)
150-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
159+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
151160
-fmodule-file=std=pcm.cache/std.pcm \
152161
--precompile "$STD_COMPAT_CPPM" -o pcm.cache/std.compat.pcm
153-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
162+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
154163
-fmodule-file=std=pcm.cache/std.pcm \
155164
pcm.cache/std.compat.pcm -c -o std.compat.o
156165
@@ -162,7 +171,7 @@ jobs:
162171
return 0;
163172
}
164173
EOF
165-
"$CXX" -std=c++23 \
174+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS \
166175
-fmodule-file=std=pcm.cache/std.pcm \
167176
-fmodule-file=std.compat=pcm.cache/std.compat.pcm \
168177
-c main.cpp -o main.o
@@ -178,9 +187,9 @@ jobs:
178187
mkdir -p pcm.cache
179188
180189
# Build std
181-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
190+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
182191
--precompile "$STD_CPPM" -o pcm.cache/std.pcm
183-
"$CXX" -std=c++23 -Wno-reserved-module-identifier \
192+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -Wno-reserved-module-identifier \
184193
pcm.cache/std.pcm -c -o std.o
185194
186195
# User module: greeter
@@ -193,9 +202,9 @@ jobs:
193202
}
194203
}
195204
EOF
196-
"$CXX" -std=c++23 -fmodule-file=std=pcm.cache/std.pcm \
205+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -fmodule-file=std=pcm.cache/std.pcm \
197206
--precompile greeter.cppm -o pcm.cache/greeter.pcm
198-
"$CXX" -std=c++23 -fmodule-file=std=pcm.cache/std.pcm \
207+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS -fmodule-file=std=pcm.cache/std.pcm \
199208
pcm.cache/greeter.pcm -c -o greeter.o
200209
201210
# Main
@@ -207,7 +216,7 @@ jobs:
207216
return 0;
208217
}
209218
EOF
210-
"$CXX" -std=c++23 \
219+
"$CXX" -std=c++23 $APPLE_FLOAT_MACROS \
211220
-fmodule-file=std=pcm.cache/std.pcm \
212221
-fmodule-file=greeter=pcm.cache/greeter.pcm \
213222
-c main.cpp -o main.o

‎CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ libarchive、bzip2、lz4、xz、zlib 与 zstd 的每个 C 文件都无法解析
2929
这样的元素。
3030
- Windows 上 `shell_quote_arg` 按 MSVCRT 规则加倍引号前与结尾处的反斜杠,以 `\` 结尾的
3131
词不再吞掉闭合引号。
32+
- **macOS 27 上 `import std` 可以构建。** 27.0 SDK 的 `<math.h>` 在模块开启时把 `INFINITY` 与
33+
`NAN` 交给 `<float.h>`,而 clang 22 的头在 `-std=c++23` 下不提供它们,std 模块预编译因此失败
34+
(`<complex>:1012: use of undeclared identifier 'INFINITY'`)。对 Apple 目标上的 clang,mcpp 以
35+
SDK 自身的拼写陈述这两个宏(`-DINFINITY=HUGE_VALF -DNAN=__builtin_nanf("0x7fc00000")`),
36+
普通单元中的重定义逐词相同,不产生警告。判据只读目标三元组。
37+
- **以 `-D` 或 `/D` 开头且含空格的元素仍是一个参数**,按原样传入,与 mcpp#234 以来各版本相同。
3238
- **CI 覆盖 macOS 27。** `ci-macos` 与 `ci-macos-e2e` 在 `macos-15` 与 macOS 27 上各跑一遍,
3339
`ci-fresh-install` 的 xlings 与 Homebrew 两条安装渠道在 `macos-14` 与 macOS 27 上各跑一遍。
3440
GitHub 以预览标签 `xcode-27` 提供 macOS 27(无 `macos-27` 标签),每条 macOS 27 的腿断言

‎docs/04-mcpp-toml.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ written: `[build]`, `[targets.<name>]`, a `flags` glob entry, a feature, a
430430
|---|---|
431431
| `"-O2 -g"` | `-O2`, `-g` |
432432
| `"-include config.h"` | `-include`, `config.h` |
433-
| `"'-DNAME=a b'"` or `"-DNAME=\"a b\""` | `-DNAME=a b` |
433+
| `"'-DNAME=a b'"` or `"-I\"my dir\""` | `-DNAME=a b`, `-Imy dir` |
434+
| `"-DNAME=long long"` | `-DNAME=long long` (see below) |
434435
| `"-DNAME=\\\"text\\\""` | `-DNAME="text"` (a string literal) |
435436
| `"-I/opt/my\\ dir/include"` | `-I/opt/my dir/include` |
436437
| `"-IC:\\sdk\\include"` | `-IC:\sdk\include` |
@@ -445,7 +446,9 @@ escapes):
445446
- outside quotes, a backslash before a space, a tab, `"`, `'` or `\` stands for
446447
that character; any other backslash is literal;
447448
- quoted and unquoted pieces that touch form one word;
448-
- `$`, `*`, `;`, `|` and the other shell operators have no meaning.
449+
- `$`, `*`, `;`, `|` and the other shell operators have no meaning;
450+
- an element that begins with `-D` or `/D` and contains a space is one word,
451+
taken verbatim, as in every earlier release.
449452

450453
A `defines` entry is one value and is not read by this syntax: `defines =
451454
["NAME=\"text\""]` passes the single word `-DNAME="text"`. `ldflags`,

‎docs/specs/manifest-semantics.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ feature、`[profile.<n>]`、`[target.<selector>.build]`、xpkg 描述符,以及
352352
6. 未闭合的引号区域延伸到元素末尾。
353353
7. 除上述字符外,任何字符没有特殊含义;实现**禁止**对 `$`、`*`、`?`、`;`、`|`、`&`、`<`、
354354
`>`、`` ` ``、`~` 做展开或解释。
355+
8. 例外:以 `-D` 或 `/D` 开头且含空格(U+0020)的元素代表一个词,即元素文本本身,规则 1 至 7
356+
不适用。自 mcpp#234 起,每个版本在宿主读取之前都把这样的元素整体加引号,该例外保持其含义不变。
355357

356358
`defines` 的一个条目 `X` 是一个值:它代表一个词 `-D` 与 `X` 的拼接,**禁止**按上述规则
357359
读取。实现向这三个列表插入一个词 `w` 时,**必须**使用一个按上述规则读回恰为 `w` 的拼写。

‎docs/zh/04-mcpp-toml.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ glob 条目、feature、`[target.<selector>.build]`、xpkg 描述符,以及构
382382
|---|---|
383383
| `"-O2 -g"` | `-O2`、`-g` |
384384
| `"-include config.h"` | `-include`、`config.h` |
385-
| `"'-DNAME=a b'"` 或 `"-DNAME=\"a b\""` | `-DNAME=a b` |
385+
| `"'-DNAME=a b'"` 或 `"-I\"my dir\""` | `-DNAME=a b`、`-Imy dir` |
386+
| `"-DNAME=long long"` | `-DNAME=long long`(见下) |
386387
| `"-DNAME=\\\"text\\\""` | `-DNAME="text"`(字符串字面量) |
387388
| `"-I/opt/my\\ dir/include"` | `-I/opt/my dir/include` |
388389
| `"-IC:\\sdk\\include"` | `-IC:\sdk\include` |
@@ -395,7 +396,8 @@ glob 条目、feature、`[target.<selector>.build]`、xpkg 描述符,以及构
395396
- `"..."` 按字面取,只有 `\"` 与 `\\` 分别代表 `"` 与 `\`;
396397
- 引号之外,反斜杠后跟空格、制表符、`"`、`'` 或 `\` 时代表该字符,其余反斜杠按字面;
397398
- 相邻的带引号与不带引号的片段组成一个词;
398-
- `$`、`*`、`;`、`|` 等 shell 运算符没有特殊含义。
399+
- `$`、`*`、`;`、`|` 等 shell 运算符没有特殊含义;
400+
- 以 `-D` 或 `/D` 开头且含空格的元素是一个词,按原样取,与此前各版本相同。
399401

400402
`defines` 的一个条目是一个值,不按此写法读取:`defines = ["NAME=\"text\""]` 传入的是
401403
一个词 `-DNAME="text"`。`ldflags`、`dialect_cxxflags` 与 `std-module-flags` 不在本节范围内。

‎modules/manifest/src/flag_words.cppm‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,17 @@
2727
// - outside quotes, a backslash before a space, a tab, `"`, `'` or `\`
2828
// stands for that character, and any other backslash is literal;
2929
// - quoted and unquoted pieces that touch form one word, so `""` is an
30-
// empty word and `-DV="a b"` is the single word `-DV=a b`.
30+
// empty word and `-I"my dir"` is the single word `-Imy dir`.
3131
//
32-
// `$`, `*`, `;` and the other shell operators have no meaning. The one
33-
// spelling the published index relies on, libarchive's
32+
// `$`, `*`, `;` and the other shell operators have no meaning.
33+
//
34+
// ONE EXCEPTION, KEPT FOR COMPATIBILITY. An element that begins with `-D` or
35+
// `/D` and contains a space is one word, taken verbatim. Every release since
36+
// mcpp#234 quoted such an element whole before the host read it, so
37+
// `-DT=long long` has always been the single argument `-DT=long long` on every
38+
// host; reading it as two words would change working manifests.
39+
//
40+
// The one spelling the published index relies on, libarchive's
3441
// `-DPLATFORM_CONFIG_H=\"mcpp_libarchive_config.h\"`, reads as the word
3542
// `-DPLATFORM_CONFIG_H="mcpp_libarchive_config.h"`, which is what both hosts
3643
// passed before. pkg-config's `\ ` for a space in a path reads as a space.
@@ -81,6 +88,8 @@ bool escapable_outside_quotes(char c) {
8188
} // namespace
8289

8390
std::vector<std::string> flag_words(std::string_view s) {
91+
if ((s.starts_with("-D") || s.starts_with("/D")) && s.find(' ') != std::string_view::npos)
92+
return {std::string(s)};
8493
std::vector<std::string> out;
8594
std::string word;
8695
bool started = false;
@@ -125,8 +134,17 @@ std::vector<std::string> flag_words(const std::vector<std::string>& elements) {
125134
}
126135

127136
std::string flag_element(std::string_view word) {
128-
const bool plain = !word.empty()
129-
&& word.find_first_of(" \t\"'\\") == std::string_view::npos;
137+
// A word with a space that begins with -D or /D is its own element (the
138+
// exception above); quoting it as well would be equally correct, and
139+
// leaving it keeps the spelling every release wrote.
140+
if ((word.starts_with("-D") || word.starts_with("/D")) && word.find(' ') != std::string_view::npos)
141+
return std::string(word);
142+
// Plain means the syntax reads the word back unchanged: no blank, no
143+
// quote, and no backslash in front of a character it would escape. A
144+
// Windows path (`C:\sdk\include`) is plain and keeps its spelling.
145+
bool plain = !word.empty() && word.find_first_of(" \t\"'") == std::string_view::npos;
146+
for (std::size_t i = 0; plain && i + 1 < word.size(); ++i)
147+
if (word[i] == '\\' && escapable_outside_quotes(word[i + 1])) plain = false;
130148
if (plain) return std::string(word);
131149
// Single quotes hold everything except `'`, which closes the region, is
132150
// written as an escaped quote outside it, and reopens it.

‎modules/manifest/tests/test_flag_words.cpp‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,22 @@ TEST(FlagWords, TheSyntaxTable) {
2323
// Quotes inside a word are quoting, as in `sh`.
2424
{R"(-DMID="mid")", {"-DMID=mid"}},
2525
{"-DSQ='sq'", {"-DSQ=sq"}},
26-
{R"(-DV="a b")", {"-DV=a b"}},
2726
{"'-DV=a b'", {"-DV=a b"}},
27+
// The compatibility exception: a -D or /D element with a space is one
28+
// word, verbatim (mcpp#234), quotes and backslashes included.
29+
{"-DT=long long", {"-DT=long long"}},
30+
{R"(-DV="a b")", {R"(-DV="a b")"}},
31+
{"/DV=a b", {"/DV=a b"}},
32+
{"-DA=1 -DB=2", {"-DA=1 -DB=2"}},
2833
// compat.lua's descriptor: one element, two words.
2934
{"-include mcpp_lua_platform_config.h", {"-include", "mcpp_lua_platform_config.h"}},
3035
// pkg-config writes a space in a path as `\ `.
3136
{R"(-I/opt/my\ dir/include)", {"-I/opt/my dir/include"}},
3237
// A backslash before an ordinary character is literal: Windows paths.
3338
{R"(-IC:\Users\x\include)", {R"(-IC:\Users\x\include)"}},
3439
{R"("-IC:\Program Files\x")", {R"(-IC:\Program Files\x)"}},
40+
// Without a space the syntax applies to a -D element as to any other.
41+
{R"(-DV="mid")", {"-DV=mid"}},
3542
// Escapes a backslash can make outside and inside double quotes.
3643
{R"(-DV=a\\b)", {R"(-DV=a\b)"}},
3744
{R"("a\"b\\c\d")", {R"(a"b\c\d)"}},
@@ -49,7 +56,7 @@ TEST(FlagWords, TheSyntaxTable) {
4956
{"''", {""}},
5057
{R"(-DV="")", {"-DV="}},
5158
// An unterminated quote extends to the end of the element.
52-
{R"(-DV="a b)", {"-DV=a b"}},
59+
{R"(-I"a b)", {"-Ia b"}},
5360
// A trailing backslash has nothing to escape.
5461
{R"(-DV=a\)", {R"(-DV=a\)"}},
5562
};
@@ -58,22 +65,24 @@ TEST(FlagWords, TheSyntaxTable) {
5865
}
5966

6067
TEST(FlagWords, AListIsTheConcatenationOfItsElements) {
61-
const std::vector<std::string> list{"-include x.h", R"(-DV="a b")", "", "-O2"};
62-
EXPECT_EQ(flag_words(list), (Words{"-include", "x.h", "-DV=a b", "-O2"}));
68+
const std::vector<std::string> list{"-include x.h", R"(-I"my dir")", "", "-O2"};
69+
EXPECT_EQ(flag_words(list), (Words{"-include", "x.h", "-Imy dir", "-O2"}));
6370
}
6471

6572
TEST(FlagWords, APlainWordIsItsOwnElement) {
66-
for (std::string_view w : {"-O2", "-DV=1", "-IC:/x", "/std:c++latest", "-Wl,-z,defs", "$x"})
73+
for (std::string_view w : {"-O2", "-DV=1", "-IC:/x", "/std:c++latest", "-Wl,-z,defs", "$x",
74+
R"(-IC:\sdk\include)", R"(C:\dir\)"})
6775
EXPECT_EQ(flag_element(w), w);
6876
}
6977

7078
// The property the engine relies on when it inserts a value into a flag list:
7179
// the element it writes reads back as exactly that one word.
7280
TEST(FlagWords, AnElementReadsBackAsItsWord) {
7381
Words words{"", " ", "a b", "'", "\"", "\\", "a\\", "\\\\srv\\share", "it's",
74-
"-DV=\"def\"", "-DV='c'", "x\ty", "a\"b'c\\d e"};
82+
"-DV=\"def\"", "-DV='c'", "x\ty", "a\"b'c\\d e", "-DT=long long",
83+
"-DV=\"a b\"", "/DV=x y"};
7584
// A deterministic walk over the characters the syntax gives meaning to.
76-
const std::string alphabet = "ab \t\"'\\$";
85+
const std::string alphabet = "ab \t\"'\\$-D";
7786
std::uint32_t state = 655;
7887
for (int n = 0; n < 2000; ++n) {
7988
std::string w;

‎src/build/build_program.cppm‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ std::vector<std::string> host_base_flags(const mcpp::toolchain::Toolchain& tc,
509509

510510
const mcpp::toolchain::PathEscape plain = mcpp::toolchain::no_escape;
511511
auto f = mcpp::toolchain::host_compile_tokens(tc, opt, plain);
512+
for (auto& w : mcpp::toolchain::apple_float_macro_words(tc)) f.push_back(std::move(w));
512513
for (auto& t : mcpp::toolchain::host_link_tokens(tc, opt, plain))
513514
f.push_back(t);
514515
return f;

‎src/build/flags.cppm‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,8 @@ CompileFlags compute_flags(const BuildPlan& plan) {
741741
hopt.appleSdkCxxHeaders = plan.toolchain.appleSdkCxxHeaders;
742742
compile_toolchain_flags = mcpp::toolchain::render_tokens(
743743
mcpp::toolchain::host_compile_tokens(plan.toolchain, hopt, ninjaEsc));
744+
for (auto const& w : mcpp::toolchain::apple_float_macro_words(plan.toolchain))
745+
compile_toolchain_flags += " " + ninja_command_word(w);
744746
} else {
745747
// Skipped entirely, not filtered. What this block emits is the
746748
// HOST's world reconstructed by hand — libc++'s headers, glibc's

0 commit comments

Comments
 (0)