Skip to content

Commit d9fb0dd

Browse files
committed
feat: 本包从哪儿编,与本包发布什么,现在是两件事
`port/include/features.h` 从 2026-08-22 起记着这个缺口和它的第一优解: ⓘ THIS IS THE SECOND-BEST REMEDY. The first would be for a package to distinguish the directories it is built from from the directories it publishes. Measured: mcpp cannot express it — publicUsage takes privateBuild's include directories entire. mcpp 2026.8.27.1 增了 `[build] private_include_dirs`。本包改用它: musl 的三个内部目录(`src/include`、`src/internal`、`musl-generated/internal`) 只到达本包自己的源码,不再进入任何消费者的命令行。 ⇒ openkal-musl#13(把 `hidden` 当普通标识符的消费者编不过)在**目录**这一层 解决,而不是在**宏**这一层再打一个补丁。 ## ⚠️ 为什么 features.h 那段还在 两条轴回答的是不同的问题,只有一条是关于可见性的: private_include_dirs 谁看得见 —— 消费者的命令行上根本没有这些目录 OKM_MUSL_INTERNAL 谁在编译 —— 一个确实带着这些目录、但不是 musl 的 C 单元 (板子在这里构建 compiler-rt 时)仍然需要那些宏是惰性的 第二种情形已被实测过:`int_util.c:49: use of undeclared identifier __weak__`。 去掉任何一条都会让一个已经付过代价的缺陷回来。 ## ⚠️ 为什么是 include_dirs 的子集而不是第二个列表 顺序承重:`port/include` 必须排在架构目录之前,内部覆盖层必须排在 `musl/include` 之前 —— 把这三个挪到末尾,musl 自己的构建会先找到公共 `<features.h>` 并以 `unknown type name hidden` 失败(同一份文件里记着这次实测)。 两个 TOML 数组表达不了一个顺序,所以那一个有序列表仍然是那一个有序列表。 ## 判据 CI 增一步,断言的是**目录**不是症状 —— 断言某个宏不再冲突,会在包侧再打一个 宏补丁时变绿而泄漏还在。并带两个控制项: - 分母:compile_commands.json 至少有一行,否则 grep 恒真 - 反向:`port/include` 必须仍在消费者命令行上,否则「什么都没发布」也会通过 本机实测(mcpp feat/target-side-reaches-every-unit + examples/cross-hello): 消费者单元 公共目录=有、三个内部目录=无。
1 parent f0ce580 commit d9fb0dd

3 files changed

Lines changed: 102 additions & 6 deletions

File tree

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,49 @@ jobs:
190190
grep kal_random syms.txt; exit 1; }
191191
echo " ok kal_random_fill is weak, kal_time_sleep is strong"
192192
193+
# ⭐⭐ THE INTERNAL OVERLAY STOPS AT THIS PACKAGE'S BOUNDARY.
194+
#
195+
# musl reaches its own declarations through `src/include`, whose headers
196+
# define `hidden`, `weak` and `weak_alias` — names that mean something
197+
# only to musl's own sources. This package publishes the path it is built
198+
# from, so every consumer used to see them too, and which consumer broke
199+
# on which name was found one at a time (openkal-musl#13).
200+
#
201+
# `[build] private_include_dirs` (mcpp 2026.8.27.1) says which entries of
202+
# `include_dirs` stop here. This asserts the DIRECTORY is absent from a
203+
# consumer's command line — not that one macro no longer collides, which
204+
# would go green again the moment the package patched that macro while
205+
# the leak stayed.
206+
- name: What this package is built from is not what it publishes
207+
working-directory: examples/cross-hello
208+
run: |
209+
extra=''
210+
[ -n '${{ matrix.target }}' ] && extra='--target ${{ matrix.target }}'
211+
"$MCPP" build --toolchain '${{ matrix.toolchain }}' $extra
212+
test -s compile_commands.json \
213+
|| { echo "::error::no compile_commands.json — nothing to check"; exit 1; }
214+
215+
# ⚠️ A DENOMINATOR. With no consumer row the greps below are
216+
# vacuously true, which is the false green this check must not have.
217+
rows="$(grep -c '"file"' compile_commands.json || true)"
218+
[ "${rows:-0}" -ge 1 ] \
219+
|| { echo "::error::compile_commands.json has no rows"; exit 1; }
220+
221+
bad=0
222+
for d in musl/src/include musl/src/internal musl-generated/internal; do
223+
if grep -q -- "$d" compile_commands.json; then
224+
echo "::error::the internal overlay '$d' reached a consumer"
225+
bad=1
226+
fi
227+
done
228+
# The control: a PUBLIC directory must still be there, or this check
229+
# would pass for a build that published nothing at all.
230+
grep -q -- 'port/include' compile_commands.json \
231+
|| { echo "::error::no public include directory reached the consumer — the check above proves nothing"
232+
exit 1; }
233+
[ "$bad" = 0 ] || exit 1
234+
echo " ok the internal overlay stops here; the public headers do not"
235+
193236
# A program above this package names one package. It does not name
194237
# openkal, it does not name an implementation, and it says nothing about
195238
# the platform.

mcpp.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,37 @@ include_dirs = [
196196
"musl/include",
197197
]
198198

199+
# ⭐⭐ THE FIRST-BEST REMEDY, WHICH port/include/features.h SAID WAS NOT
200+
# AVAILABLE AND NOW IS.
201+
#
202+
# That file records the measurement of 2026-08-22: "The first would be for a
203+
# package to distinguish the directories it is BUILT FROM from the directories
204+
# it PUBLISHES. Measured: mcpp cannot express it — publicUsage takes
205+
# privateBuild's include directories entire."
206+
#
207+
# It can now. `private_include_dirs` names the entries OF `include_dirs` that
208+
# stop at this package's boundary, so musl's internal overlay reaches musl's
209+
# own sources and reaches no consumer.
210+
#
211+
# ⚠️ A SUBSET OF THE LIST ABOVE RATHER THAN A LIST OF ITS OWN, and that is the
212+
# point: the ORDER is load-bearing. `port/include` must precede the
213+
# architecture's directory, and the internal overlay must precede
214+
# `musl/include` — moving these three to the end makes musl's own build find
215+
# the public <features.h> first and fail with `unknown type name hidden`.
216+
# The one ordered list stays the one ordered list.
217+
#
218+
# ⚠️ THIS DOES NOT REPLACE `OKM_MUSL_INTERNAL`. That answers a different
219+
# question — "is this package the one compiling this unit" — and it is what
220+
# keeps the macros inert for a C consumer that IS built with these directories
221+
# on its line (compiler-rt, when a board builds it here). The two are the
222+
# authorship axis and the visibility axis; removing either brings back a defect
223+
# that has already been measured.
224+
private_include_dirs = [
225+
"musl/src/include",
226+
"musl/src/internal",
227+
"musl-generated/internal",
228+
]
229+
199230
cflags = [
200231
# musl is written to C99 and to nothing else. -nostdinc is not an
201232
# optimisation: a C library that included the headers of another C library

port/include/features.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,36 @@
7171
* and finds <features.h> defining `weak', `hidden' and `weak_alias' as macros
7272
* that mean something only to musl's own sources.
7373
*
74-
* ⓘ THIS IS THE SECOND-BEST REMEDY. The first would be for a package to
75-
* distinguish the directories it is built from from the directories it
76-
* publishes. Measured 2026-08-22: mcpp cannot express it --- publicUsage takes
77-
* privateBuild's include directories entire. Moving the two directories into
74+
* ⓘ THIS WAS THE SECOND-BEST REMEDY, AND THE FIRST ONE HAS ARRIVED.
75+
*
76+
* The note used to read: "The first would be for a package to distinguish the
77+
* directories it is built from from the directories it publishes. Measured
78+
* 2026-08-22: mcpp cannot express it --- publicUsage takes privateBuild's
79+
* include directories entire." It was left here so that the better fix would
80+
* not be lost, and it was not: mcpp 2026.8.27.1 added
81+
* `[build] private_include_dirs`, and this package's manifest now uses it.
82+
*
83+
* ⚠️ SO WHY IS THE BLOCK BELOW STILL HERE? Because the two answer different
84+
* questions and only one of them is about visibility.
85+
*
86+
* private_include_dirs --- WHO SEES the internal overlay. A consumer no
87+
* longer has these directories on its command line
88+
* at all, so the macros cannot reach it.
89+
* OKM_MUSL_INTERNAL --- WHO IS COMPILING. A C source that IS built with
90+
* these directories on its line and is NOT musl's
91+
* --- compiler-rt, when a board builds it here ---
92+
* still needs the macros inert.
93+
*
94+
* The second case is measured and is recorded further down: `int_util.c:49:
95+
* use of undeclared identifier __weak__'. Removing either axis brings back a
96+
* defect that has already been paid for once.
97+
*
98+
* ⚠️ The rejected alternative is also kept: moving the two directories into
7899
* per-glob flags places them AFTER include_dirs on the command line, and musl's
79100
* own build then finds the public <features.h> before the internal one and
80-
* fails with `unknown type name hidden'. The note is here so that the better
81-
* fix is not lost.
101+
* fails with `unknown type name hidden'. That is why `private_include_dirs` is
102+
* a SUBSET of `include_dirs` rather than a second list --- the order is the
103+
* thing that cannot be given up.
82104
*
83105
* ⭐⭐ THE DISCRIMINATOR WAS WRONG ONCE, AND THE WRONG ONE HELD FOR A DAY.
84106
*

0 commit comments

Comments
 (0)