Skip to content

fix(subos): prepend 丢掉了调用方的值 - #383

Merged
speak-agent merged 2 commits into
mainfrom
fix/subos-set-is-a-default
Aug 8, 2026
Merged

fix(subos): prepend 丢掉了调用方的值#383
speak-agent merged 2 commits into
mainfrom
fix/subos-set-is-a-default

Conversation

@speak-agent

@speak-agent speak-agent commented Aug 8, 2026

Copy link
Copy Markdown
Member

修订:只保留 prepend 那一半。set 的部分已撤回。

原提案把 set 改成「用户已 export 就让位」。撤回,因为它错在两个层面:

  1. set 与「默认值」是两种真实不同的意图。 有些变量 subos 必须说了算 —— 指向它自己 loader 配置的那类,用户 shell 里一个陈旧值就能把环境弄坏。把两者塌成一个,等于从此无法表达前者。
  2. op 词汇表是 xlings 的契约,mcpp 是消费方。 消费方悄悄给一个 op 加第二种含义,会让同一个 subos 因为「由谁启动」而行为不同 —— 经 mcpp run 和经 xlings 自己应用会不一致。

#382 想要的逃生通道,应当由 xlings 新增一个 op(「声明默认值,用户可覆盖」),mcpp 认它。现在未知 op 会被丢弃,所以那个 op 必须两侧同时到位。本 PR 加了一条断言把「set 就是要赢」钉住,免得日后又被「修」回去。


保留的部分:prepend 丢掉了调用方的值

这一条与 xlings 怎么修无关,是 mcpp 自己的实现缺陷。

解析出的键值对替换子进程里的变量(作为 extraEnv 进去)。prepend 却只发出声明值,把调用方原有内容整个丢掉 —— 对 PATH 形状的变量,丢掉的是用户的整条搜索路径。没人报过。

现在它接在调用方的值前面,且对已存在元素幂等(嵌套运行不会让列表增长)。空值不算「用户设过」。

单测 15 条(prepend 2 条 + set 语义 1 条);全量 67/67;e2e 200 通过。

mcpp#382 的次要观察,而它把配方写明的逃生通道整个作废了。

解析出来的键值对是**替换**子进程里的变量的(它们作为 extraEnv 进去)。于是:

- 一条 `set` 会覆盖用户已经 export 的值。xlings 的 wsl-gl-host-link 白纸黑字写着
  「用户自己 export GALLIUM_DRIVER=llvmpipe 会保留」—— 实际不保留:
  `export GALLIUM_DRIVER=llvmpipe; mcpp run` 仍然带着 subos 的 d3d12 跑,仍然失败。
- 一条 `prepend` 只发出声明值,**丢掉**用户原有的内容。对 PATH 形状的变量,那是
  用户的整条搜索路径。第二个缺陷,没人报过。

现在两者都对着调用方的环境解析:`set` 在变量已有非空值时让位,`prepend` 接在其
前面(且对已存在的元素幂等)。空值不算「用户设过」。

用户刻意设定的环境,是构建环境**唯一**不该悄悄推翻的输入。

  tests/unit/test_subos_info.cpp  +5(17 条);已验证去掉让位逻辑后该断言变红
  e2e 200 通过
上一版把 `set` 改成「用户已 export 就让位」。撤回,因为它错在两个层面:

**`set` 与「默认值」是两种意图。** 有些变量 subos 必须说了算 —— 指向它自己 loader
配置的那类,用户 shell 里一个陈旧值就能把环境弄坏。把两者塌成一个,等于从此无法
表达前者。

**op 词汇表是 xlings 的,不是 mcpp 的。** `envs` 是 xlings 的线格式;消费方悄悄给
一个 op 加第二种含义,会让同一个 subos 因为「由谁启动」而行为不同。

mcpp#382 想要的逃生通道应当是 xlings 新增一个 op(「声明默认值,用户可覆盖」),
mcpp 认它 —— 而不是在这里重解 `set`。现在未知 op 会被丢弃,所以那个 op 必须两侧
同时到位。已加断言把这个决定钉住,免得再被「修」回去。

留下的是 `prepend`:它字面意思就是接在已有值前面,而这里只发声明值、把调用方原有
内容整个丢掉。对 PATH 形状的变量,丢掉的是用户的整条搜索路径。这与 xlings 怎么修
无关,是 mcpp 自己的实现缺陷。

  tests/unit/test_subos_info.cpp  15 条(prepend 2 条 + set 语义 1 条)
@speak-agent speak-agent changed the title fix(subos): set 是默认值,不是命令 fix(subos): prepend 丢掉了调用方的值 Aug 8, 2026
@speak-agent
speak-agent merged commit c1e9360 into main Aug 8, 2026
18 checks passed
speak-agent added a commit that referenced this pull request Aug 8, 2026
main 上唯一未发布的代码改动是 #383(subos 的 `prepend` 把调用方的值整个丢掉)—— 解析结果是**替换**子进程变量的,所以对 PATH 形状的变量,丢掉的是用户的整条搜索路径。

xlings pin 2026.8.7.1 → **2026.8.8.1**(索引已收录)。

本地 67 单测;e2e 200/201/86/29 通过;CI 18/18。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant