Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [2026.8.1.2] — 2026-08-01

### 新增

- **`mcpp.lock` 成为 git 依赖的解析输入,而且是权威的那一份。** 在此之前 lock 只写不读:`branch = "develop"` 这类依赖每次进 `prepare_build` 都要打一次 `git ls-remote`,而写进 lock 的那个 commit 从来没有人看过。现在**先读 lock**——分支已经解析过就直接用记录的 commit,不再有网络往返。

「权威」是这里的关键词,不是「缓存的提示」。一个只在本地克隆恰好还在时才生效的 lock,等于把「构建哪个 commit」这个决定交给了缓存目录的存活状况:清一次 `~/.mcpp/git`、或者换一台机器 clone 同一个工程,构建就会静默滑到分支的新头上,并把 lock 改写成新值——**而 `mcpp new` 生成的 `.gitignore` 并不忽略 `mcpp.lock`,它本来就是要提交的**。实测(见 e2e 24 新增断言):分支移到 v2、缓存删除后,旧行为构建出 v2,新行为构建出 lock 里记的 v1。要新的分支头依然只有一条路——`mcpp update <dep>`,它丢掉 lock 条目,下次构建重新解析。

连带把这块的结构收敛成两个各自独立的问题,各带**恰好一个** `--offline` 闸:**(1) 是哪个 commit** —— `tag`/`rev` 自带答案,`branch` 由 lock 回答、否则 `ls-remote`;**(2) 它在不在盘上** —— commit 选定缓存目录,miss 就 clone。原来 tag/rev 有一条自己的分支腿、打一行每次构建都出现的 `from cache` 噪声,并且在 dep 根本没进 lock 时报「is locked but its local cache is missing」;这条腿现在整个不需要了。

### 修复

- **`--offline` 不再拒绝本地 git 远端。** `docs/05-mcpp-toml.md` 写明 `--offline` 的语义是「完全不碰网络……已安装的东西照常构建」,`prepare.cppm` 里依赖下载闸的注释也把线画在同一处:「这条线以上全是本地操作,一个依赖齐备的离线构建必须成功」。但 `git = "../sibling-repo"` 这种指向本地目录的远端,`ls-remote`/`clone` 都只是文件系统读取,拒绝它买不到任何隔离性。现在按远端形态判定——`file://`、以及不带 scheme 也不是 `git@host:path` 的存在路径,算本地(Windows 盘符 `C:\repo` 含冒号但不含 `@`,因此仍归本地)。

- **克隆被中途杀掉后不再永久提供错误的 commit。** 缓存目录以 commit 命名,但内容是 `git clone` 之后再 `git checkout` 两步做出来的;进程死在两步之间,目录名和 HEAD 就对不上了,而后续构建只检查目录存不存在。现在分支依赖会比对 `git rev-parse HEAD`,不符即删除重克隆(tag/rev 以 ref 名为身份,无可比之物)。

- **git 克隆在 Windows 上不再依赖 `cd` 跨盘。** 克隆命令用的是 `git clone … && cd <dir> && git checkout`,而 cmd.exe 的 `cd` 不带 `/d` 是不换盘的——缓存根(`MCPP_HOME`)与工程不同盘是常态。仓库里其它跨盘位置(`process.cppm`、`msvc.cppm`)都写了 `cd /d`,这里漏了。改用 `git -C <dir>`,连 shell 都不需要。

- **`mcpp.lock` 读取失败改用 degraded 通道。** 按 `src/diag.cppm` 的划分,「引擎做得比要求的少」属于 Degraded 且必须给出 impact——lock 读不出来,每个 git 分支依赖都会退回网络解析、并可能越过记录的 commit。原来记的是普通 warning,`--strict` 提升不到它。

- **`parse_git_source` 不再切开名字里带 `@` 的 tag/rev。** 写侧只对 `branch` 追加 `@<commit>`,解析侧却无条件按最后一个 `@` 切分,于是一个叫 `v1.0@rc1` 的 tag 会被读成 ref `v1.0` + commit `rc1`。现在只有 branch 走这条切分(且仍按最后一个 `@`,以容纳 `feat@v2` 这类分支名)。

## [2026.8.1.1] — 2026-08-01

### 修复
Expand Down
24 changes: 22 additions & 2 deletions docs/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,10 @@ glfw = "3.4" # Explicit namespace, skips the mcpplibs-first c
[dependencies]
mylib = { path = "../mylib" }

# Git dependency
# Git dependency — pick exactly one of tag / branch / rev
[dependencies]
mylib = { git = "https://github.com/user/mylib.git", tag = "v1.0.0" }
applib = { git = "https://github.com/user/applib.git", branch = "develop" }

# Long-form dep spec: features and backend knobs
[dependencies]
Expand All @@ -356,6 +357,25 @@ package declares `[features]` but does not include the requested feature (includ
the result of backend desugaring), a warning is issued by default, and an error
under `mcpp build --strict`.

**Git dependencies and `mcpp.lock`**: a `tag` or `rev` already names a fixed point
in history, but a `branch` moves. The first build resolves the branch to a commit
and records it in `mcpp.lock`, and every later build rebuilds **that** commit — the
lock is authoritative, not a cache hint, so deleting `~/.mcpp/git` or moving to
another machine cannot quietly put you on a newer tip. Ask for the newer tip
explicitly:

```bash
mcpp update mylib # drop the recorded commit; the next build re-resolves it
mcpp update # same, for every dependency
```

Because the recorded commit is enough to decide what to build, a rebuild with the
clone already in `~/.mcpp/git` makes no network request at all and works under
`--offline`. Only two things need the network: resolving a branch that has no
commit in the lock, and cloning a commit that is not cached yet. A `git =` value
that names a local directory (or a `file://` URL) needs neither, so it is never
refused offline.

**SemVer constraints**:

```toml
Expand Down Expand Up @@ -454,7 +474,7 @@ Controls, in order of precedence:

| Control | Effect |
|---|---|
| `--offline` (any command) | Never touch the network — no index refresh, no downloads, no toolchain auto-install. Anything already installed still builds |
| `--offline` (any command) | Never touch the network — no index refresh, no downloads, no toolchain auto-install, no `git ls-remote`/`clone`. Anything already installed still builds, including git deps whose commit is in `mcpp.lock` and whose clone is cached |
| `MCPP_OFFLINE=1` | Same, for a whole shell session or CI job |
| `[index] auto_refresh = false` in `~/.mcpp/config.toml` | Never refresh the index automatically; downloads still work |

Expand Down
20 changes: 18 additions & 2 deletions docs/zh/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,10 @@ glfw = "3.4" # 显式 namespace, 不走 mcpplibs 优先候选
[dependencies]
mylib = { path = "../mylib" }

# Git 依赖
# Git 依赖 —— tag / branch / rev 三选一
[dependencies]
mylib = { git = "https://github.com/user/mylib.git", tag = "v1.0.0" }
applib = { git = "https://github.com/user/applib.git", branch = "develop" }

# 长式 dep spec:features 与 backend 旋钮
[dependencies]
Expand All @@ -325,6 +326,21 @@ feature(库若支持该旋钮,应在自己的 `[features]` 中声明 `backend-*`
若目标包声明了 `[features]` 但不含所请求的 feature(含 backend 脱糖结果),
默认给出 warning,`mcpp build --strict` 下报错。

**Git 依赖与 `mcpp.lock`**:`tag` 和 `rev` 本身就指向历史中的固定点,而 `branch`
是会动的。首次构建把分支解析成一个 commit 并写进 `mcpp.lock`,此后每次构建都重建
**那个** commit —— lock 是权威而不是缓存提示,所以删掉 `~/.mcpp/git` 或换一台机器
都不会悄悄把你挪到更新的分支头上。要新的分支头,得显式要:

```bash
mcpp update mylib # 丢掉记录的 commit,下次构建重新解析
mcpp update # 同上,对所有依赖
```

既然记录的 commit 已经足以决定构建什么,那么在 `~/.mcpp/git` 里已有克隆的情况下,
重新构建完全不发网络请求,`--offline` 下照常工作。只有两件事需要网络:解析一个在
lock 里没有 commit 的分支,以及克隆一个尚未缓存的 commit。`git =` 若指向本地目录
(或 `file://` URL),这两件事都不需要网络,因此离线下也绝不会被拒绝。

**SemVer 约束**:

```toml
Expand Down Expand Up @@ -443,7 +459,7 @@ mcpp index status # 看本地现状:状态、年龄、修订号

| 开关 | 作用 |
|---|---|
| `--offline`(任意命令) | 完全不碰网络——不刷索引、不下载、不自动装工具链。已安装的东西照常构建 |
| `--offline`(任意命令) | 完全不碰网络——不刷索引、不下载、不自动装工具链,也不发 `git ls-remote`/`clone`。已安装的东西照常构建,包括 commit 已在 `mcpp.lock`、克隆已在缓存里的 git 依赖 |
| `MCPP_OFFLINE=1` | 同上,作用于整个 shell 会话或 CI job |
| `~/.mcpp/config.toml` 里 `[index] auto_refresh = false` | 永不自动刷新索引,但下载仍然可用 |

Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mcpp"
version = "2026.8.1.1"
version = "2026.8.1.2"
description = "Modern C++ build & package management tool"
license = "Apache-2.0"
authors = ["mcpp-community"]
Expand Down
Loading
Loading