Files
张宗平 1a788a8278 移除 Docker 构建路线,改为 host 直装 Qt 5.14.2 + Qt Creator 4.11.0
学生主要用 Windows,Docker 方案不再需要:删掉 tools/docker/ 及 README/HANDOFF/
CMakeLists 里的相关引用(含一处已失效的 docker_run.sh 死链接)。

install_qt_host.sh 现在同时装期号匹配的 Qt Creator 4.11.0:官方 .run 安装器
强制要求 Qt 账号登录且无 Skip 选项,改用 tools/extract_qtcreator_payload.py
直接从 .run 里定位、解出内嵌的 7z payload,绕开账号登录。提取逻辑先解到
staging 目录再原子替换到位,避免中途失败留下部分安装但被判定为"已装";
候选 7z 复用同一临时文件,不会在磁盘上堆多份安装包大小的临时拷贝。
2026-07-02 13:02:37 +08:00

233 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HANDOFF — qt-course 课程代码仓库生成/验证 续接手册
> 本手册供「新开会话」从当前进度继续。读完即可无缝接手。
> 仓库路径:`/home/charles/workspaces/qt-course`
> 上次工作会话日期:2026-06-30(**全部完成**,已首次 git 提交)
---
## ⚠️ 当前状态:全部完成(2026-06-30 第二次会话)
本会话已把 HANDOFF §1 中所有「未完成」项做完。仓库已首次提交
commit `13b3ebb`,287 文件)。**后续会话主要做维护/扩展,不需重做以下工作。**
- Part1144/144 全绿(原剩 13 个 FAILED 已全部修复,见 §4 新增的修正清单)。
- 目录深缩写已应用:`p01/ch04/s03/` 形式。
- Part3 Qt29 目标全绿,offscreen 运行验证通过。
- 任务1 版本机制:`std_probe.py` + `demo_versions/`(6 个) + `VERSION_NOTES.md`
- 文档:顶层 README、SOURCE_PAGES.md、ERRATA.md / ERRATA_part3.md。
- 修复了 `run.sh` / `run_qt.sh``${1:?...}` 引号语法 bug。
> 重新生成命令(幂等):`rm -rf p01 p03 build && python3 tools/gen_part1.py && python3 tools/gen_part3.py`
> ⚠️ **下文 §1–§10 为过程记录,未随本次完成同步重写**:其中出现的旧目录名
> `part1_cpp/`、`part3_qt_desktop/`)、旧状态(Part3「未开始」等)及 §3 的旧重生成
> 命令均已**过时**。一切以本 banner、`README.md`、当前仓库实际目录(`p01/`、`p03/`)为准。
> 2026-06-30 第三次会话已对全仓库脚本指引与 wiki 引用做端到端核实,结论:README 脚本全部
> 有效、173 目标全绿、92 条 ERRATA 引用与实时 wiki 一致(详见本次会话记录)。
---
## 0. 任务总目标(来自用户原始需求)
从川大 wiki「02. Qt 方向」(需登录 scuc/scuc2025) 提取 QT 方向页面,完成 3 件事:
0. **按章节+话题组织课程代码仓库**,用 CMake 项目管理,每个可执行文件 = 一个独立 `add_executable` 目标;为 Qt 示例准备一套**与主系统隔离**的 Qt 5.14.x 开发环境;示例之间相对隔离。
1. **验证所有示例代码**在原文所述语言(C 或 C++,先按 C17/C++17)下仍能编译通过、概念仍符合当前标准;不符的确认在何版本成立并编译验证;提供「快速演示不同版本对概念支持」的机制。
2. **修正示例代码错误**并演示。
用户后续追加的关键指令:
- 源文件名用**英文**,与章节名匹配;同小节多文件用语义后缀区分。
- 目录约定:`02 Qt方向`为顶层(不编号);`01 C++技术强化及提升`等视为「章」;其下编号子项视为「节」。
- 目录用**深缩写**`p01/ch04/s01/` 这种形式。(**尚未应用**,见 §5)
- 容器方案用「构建容器」:容器编译、宿主机运行;或带 GUI 的容器。
---
## 1. 当前完成度(截至上次会话末)
| 项 | 状态 |
|---|---|
| 抓取解析 35 个 wiki 页面、218 个代码块 | ✅ 完成 |
| 仓库骨架(顶层 CMakeLists、.gitignore、tools/、docs/ | ✅ 完成 |
| **隔离 Qt 5.14.2 安装**`.qt514/`aqtinstall 装在仓库内) | ✅ 完成 |
| 验证隔离有效:`ldd` 0 系统 Qt 引用、offscreen 运行打印 5.14.2 | ✅ 完成 |
| Part1 C/C++ 源码 + CMakeLists 生成器 | ✅ 可运行(`tools/gen_part1.py` |
| Part1 英文文件名映射表(`tools/file_name_map.py`) | ✅ 完成,113 节全覆盖 |
| Part1 全部编译通过 | ⚠️ **未完成**144 个目标,剩 4 个 FAILED |
| Part3 Qt 源码/CMakeLists/.qrc 生成 | ❌ **未开始** |
| Qt 示例构建运行验证 | ❌ 未开始 |
| `std_probe.py` + 多版本演示 + VERSION_NOTES.md | ❌ 未开始 |
| 各章 README、SOURCE_PAGES.md、最终 clean build、git 提交 | ❌ 未开始 |
**git 状态**(此表为历史快照,已被后续提交超越):首次提交为 `13b3ebb`287 文件);
截至 2026-06-30 已有多次提交,HEAD 在 main 分支,工作区干净。以 `git log` 为准。
---
## 2. 仓库当前布局
```
qt-course/
├── CMakeLists.txt # 顶层:C17/C++17 严格、option(BUILD_QT_PART)、隔离 Qt 版本断言
├── .gitignore # 排除 build/ .qt514/ .venv-aqt/ 等
├── tools/
│ ├── gen_sources.py # 共享引擎:标题解析 page_outline()、语言判定 classify_lang()、common_fix()
│ ├── gen_part1.py # Part1 生成器(含 exact_fix、block_classify、wrap_statements、emit_console
│ ├── file_name_map.py # (pageId, section_title) → 英文文件名词根(113 条,全覆盖)
│ ├── run.sh / run_qt.sh # 宿主机运行 part1 / Qt 目标(LD_LIBRARY_PATH 隔离)
│ ├── install_qt_host.sh # 宿主机直装 Qt 5.14.2 + Qt Creator 4.11.0 到 .qt514/
│ └── wiki_data/ # 抓取的 wiki 正文+代码块(已拷入,生成器输入)
├── docs/
│ ├── ERRATA.md # Part1 代码修正记录(自动生成,72 条)
│ ├── ERRATA_part3.md # Part3 Qt 代码修正记录(自动生成,20 条)
│ ├── SOURCE_PAGES.md # pageId→章节映射表
│ └── VERSION_NOTES.md # 版本相关概念验证记录
├── p01/ # Part1:已生成 144 目标,深缩写 chNN/sNN17 个 dir
└── p03/ # Part3:已生成 29 目标,深缩写 chNN/sNN
```
**实际目录形**(深缩写已应用,见 §5):`p01/ch04/s03/ctor_and_dtor.cpp` 等。
---
## 3. 已验证可用的关键命令
```bash
cd /home/charles/workspaces/qt-course
# 重新生成全部源码 + CMakeLists(幂等;每次改生成器后先 rm -rf p01 p03
rm -rf p01 p03 build && python3 tools/gen_part1.py && python3 tools/gen_part3.py
# 在宿主机配置+构建 Part1(无需 Qt)
cmake -S . -B build -G Ninja -DBUILD_QT_PART=OFF -DCMAKE_BUILD_TYPE=Debug
cmake --build build
# 构建/运行 Qt 部分(需先装隔离 Qt;见下)
cmake -S . -B build -G Ninja -DBUILD_QT_PART=ON \
-DCMAKE_PREFIX_PATH=$PWD/.qt514/5.14.2/gcc_64 -DCMAKE_BUILD_TYPE=Debug
cmake --build build
LD_LIBRARY_PATH=$PWD/.qt514/5.14.2/gcc_64/lib ./tools/run_qt.sh <target> # 或直接 ./tools/run_qt.sh
# 装/重装隔离 Qt 5.14.2(宿主机,一次性;同时装 Qt Creator 4.11.0
tools/install_qt_host.sh
```
**隔离 Qt 核心事实**(已验证):`.qt514` 是唯一真相源;`ldd` 0 系统 Qt 引用;`QT_QPA_PLATFORM=offscreen` 可无 X 运行验证。学生主要用 Windows,构建/运行方案不引入 Docker。
---
## 4. Part1 剩余 4 个 FAILED 目标(接手第一件事)
最近一次构建:`FAILED: 4 | Linked: 0`,剩余唯一错误类:
| 失败目标 | 文件 | 根因 |
|---|---|---|
| p1c03_42 | part1_cpp/.../function_overload_basics_2.cpp | dedupe 把重载 `MyFunc` 改名 `MyFunc_2` 后,`MyFunc_2("hello")` 调用对 `MyFunc_2(int)` 和另一重载产生歧义(dedupe 重命名破坏了重载集) |
| p1c03_43 | part1_cpp/.../function_overload_basics.cpp | `namespace` 定义在函数体内(同 block 3/6/7 问题,需在 exact_fix 补 58954439:41/42 的 namespace 提升修正) |
| p1c04_03_01 | .../03_ctor_dtor/ctor_and_dtor.cpp | `strcpy` 未声明:C++ 用 iostream 前言但 wiki 块含 `strcpy`,需补 `<cstring>` |
| p1c04_03_04 | .../03_ctor_dtor/deep_vs_shallow_copy.cpp | 同上:`strcpy`/`strlen` 未声明,补 `<cstring>` |
**建议修法**(在 `tools/gen_part1.py``exact_fix(pid,idx)` 里):
1. **`strcpy`/`strlen` 类**:对 ch04 块(pid 58954451 等),若 code 含 `strcpy`/`strlen`/`strcmp` 等而无 `<cstring>`/`<string.h>`,在 `common_fix``exact_fix` 里补 `#include <cstring>`C++)或 `<string.h>`C)。建议加到 `gen_sources.py``common_fix` 通用补头(类似 NBSP 修复)。
2. **namespace-in-function (block 41/42)**:仿照已写好的 block 3/6/7 的 `exact_fix`,把 `namespace` 定义提到文件作用域。
3. **dedupe 破坏重载集 (block overload_basics_2)**:去重逻辑对**同一块内**的重载不应改名;当前 `dedupe_functions` 跨块去重是为了同名不同块变体。需让 dedupe 只对「同名且跨块」改名,块内多个同名重载视为同一组用序号区分——或更稳妥:函数重载演示块整体改名前先识别是重载集(同名不同参数),统一改名 `MyFunc``MyFunc_<n>` 并同步调用点。已属复杂边界,可单独为 58954439:41/42 写 exact_fix 直接给可编译版本。
**每处修正都要 `record_erratum(...)`** 以自动进 `docs/ERRATA.md`(已有 30 条,结构见现有条目)。
修法后:`rm -rf part1_cpp build && python3 tools/gen_part1.py && cmake -S . -B build -G Ninja -DBUILD_QT_PART=OFF && cmake --build build` 应全绿(144 目标全 Linking executable)。然后即可进 Part3。
---
## 5. 待应用:深缩写目录 `p01/ch04/s01/`(用户明确要求,最后统一改)
用户要求目录形如:`p01/ch04/s01/`part 缩写 pNN / 章缩写 chNN / 节缩写 sNN)。
当前是 `part1_cpp/ch04_class_object/03_ctor_dtor/`
**改法**(在 `gen_part1.py``PAGE_CONFIG` 里把 `dir` 值统一改为深缩写;或在 `main()` 拼接 `out_dir` 处做映射):
- `part1_cpp``p01`
- `ch04_class_object``ch04`
- `01_basic_concepts``s01``02_oo_case``s02`,……
- `ch03_cpp_extends_c``ch03`,等等。
- 主顶层 `CMakeLists.txt``add_subdirectory(part1_cpp)``add_subdirectory(p01)`
- 同步更新 `tools/run.sh` / 任何写死 `part1_cpp` 的地方。
- Part3 同理 `part3_qt_desktop``p03`
**映射依据**`PAGE_CONFIG` 里每个 pageId 的 `dir` 和 wiki 树结构 (`tools/wiki_data/qt_full_tree.json`),可脚本一次性生成 `p NN`/`ch NN`/`s NN` 编号。建议在生成目录的最后统一替换,不破坏 `file_name_map.py`(文件名映射与目录无关,仍按 (pageId, section))。
---
## 6. Part3 Qt 续接要点(接手第二件大事)
**输入**`tools/wiki_data/extracted_code.json` 中 9 个 Qt 页面 pageId5895451558954552),共 73 个代码块。
**已勘察分类**codex subagent 已做,结论在上次会话):
- 3 个完整程序(含 main+QApplication,直接成目标)
- 2 个 Q_OBJECT 类定义(需 moc → 开 AUTOMOC
- 28 个可加 harness 块(包 main+QApplication+show,部分需补 Widget 类骨架)
- 40 个纯签名/单语句(折进各章 README 作文档,不单独建目标)
**已知的 Qt 代码修正点**subagent 已列):
- 笔误:`QLable``QLabel``.``->`、全角```;``"D:\ndrawing.pic"``"D:/drawing.pic"`、类后缺 `;`
- `tr()` 在非 QObject 上下文(main) 不可用 → `QObject::tr`/`QStringLiteral`
- 资源依赖:`:/images/*.png``:/Image/boat.jpg``:/Mario.gif``:/Image/butterfly*.png``in.txt`/`file.dat`/`file.txt` → 各自生成占位文件 + `.qrc`CMake `qt5_add_resources()`
- 过时 APIQt5.14 仍可用,保留并记 VERSION_NOTES):`QMouseEvent::x()/y()``QString::sprintf`、Qt4 `SIGNAL/SLOT``static_cast` 重载解析(Qt6 起弃用)
**生成器骨架**:仿 `gen_part1.py``gen_part3.py`,复用 `gen_sources.py``page_outline`/`classify_lang`(已含 Qt 检测)/`common_fix`,但:
- emit 用 Qt 模板:`#include <QApplication>` 等、`QApplication app(...)``w.show()``return app.exec()``QT_QPA_PLATFORM=offscreen` 时设 `QTimer::singleShot` 让程序自动退出。
-`AUTOMOC`(顶层 CMakeLists 已统一开,但建议在 part3 各目标的子 `CMakeLists``set(CMAKE_AUTOMOC ON)`)。
- 资源目标:需 `.qrc` + 占位 png(用工具生成纯色小 png 即可,不依赖原图)。
- 语言全是 C++(`.cpp`)。
- 英文文件名映射表 `file_name_map.py` 里目前**只有 Part1**Part3 需新增 pageId 5895451558954552 的映射(约 1625 个 section)。
**验证**host 构建 → offscreen 运行(`QT_QPA_PLATFORM=offscreen ./tools/run_qt.sh <target>`),用 `QTimer` 自动退出、捕获 stdout/退出码确认。需 X 真窗时给 DISPLAY。
---
## 7. 任务1「概念/版本验证」+ 任务1机制(接手第三件)
用户要「快速演示不同版本支持」。已规划:
- `tools/std_probe.py`:输入片段+标准列表(c89/c99/c11/c17/c23、c++11/14/17/20/23),逐个 `gcc/g++ -std=..` 编译,报 pass/fail+警告。host gcc13 原生支持全部。
- `tools/demo_versions/`:针对 wiki 有版本论断的片段做跨版本对比:K&R 隐式 int、三目返左值(C++独有)、`const int` 改写差异、enum 赋整/`char* p=malloc` 不强转(C vs C++)。
- 结果汇总进 `docs/VERSION_NOTES.md`:每条「文中说法→当前 C17/C++17 是否仍成立→不成立在何版本成立→已编译验证」。
**已知版本相关论断**(来自 Part1 已修的 exact_fix):
- K&R 隐式 int(块 58954439:14)→ C89 成立,C99 起非法
- 三目运算符返左值(块 18)→ C++ 独有
- `const int` 经指针改写 → C/C++ 行为差异
- enum 赋整 / `char* p=malloc` 不强转(块 15)→ C 合法 C++ 报错
- `system("pause")` 平台依赖(已在 common_fix 修为便携 pause()
---
## 8. 接手后立即应做的最小步骤
1. 读本手册 + `tools/gen_part1.py` + `tools/gen_sources.py` 了解生成器。
2. 修 Part1 剩余 4 个 FAILED(§4):补 `<cstring>`、namespace 提升 41/42、dedupe 重载集。重建到 144/144 全绿。
3. 应用深缩写目录(§5):改 `PAGE_CONFIG` 的 dir 为 p/ch/s,全量重建确认路径。
4.`gen_part3.py` + 扩 `file_name_map.py`;生成 Part3host 构建;offscreen 运行验证。
5.`std_probe.py` + `tools/demo_versions/`;填 `docs/VERSION_NOTES.md`
6.`docs/SOURCE_PAGES.md`(pageId→章节映射表)、各章 README、顶层 README。
7. 全量 clean build`git add -A && git commit`(**目前 0 提交,务必最后提交一次**)。
---
## 9. 关键约束/红线
- **不修改** `tools/wiki_data/` 中的原始抓取数据(生成器输入,保持原貌)。
- 每处对 wiki 代码的修正都要 `record_erratum()``docs/ERRATA.md`(透明可审计)。
- 源文件名英文;CMake 目标名 ASCIICMake 禁非 ASCII 目标名——已踩坑并修好)。
- 隔离 Qt:构建/运行一律走 `.qt514/``-DCMAKE_PREFIX_PATH` + `LD_LIBRARY_PATH`),**不碰系统 Qt 5.15**;顶层 `CMakeLists.txt` 有版本断言(迷连系统 5.15 会 FATAL_ERROR)。
- 不要对 wiki 数据做多块「合并」造符号冲突——已踩坑:跨块同名符号会重定义;最终采用「每块一文件」+ 必要时 `exact_fix` 补前向声明(如 `Person`)。
---
## 10. 上次会话犯过、勿重犯的坑
- `ERRATA``gen_sources.py` 模块级可变列表,`record_erratum` 追加到该列表;`gen_part1.py` 必须 `import gen_sources; ERRATA = gen_sources.ERRATA`(早期误用 `from ... import ERRATA` 独立拷贝导致 write_errata 看到空列表)。
- `block_classify``decl_re` 必须**排除**裸调用 `printf(...);`(无返回类型前缀不算声明),否则语句片段被误判 groupdecl;且要**允许**单独 `{`/`}` 行(namespace 块边界),否则纯 namespace 声明块被误判 statements 进而被包进函数体内(namespace 不能在函数内)。
- `dedupe_functions` 跨块改名会**破坏函数重载集**(块内多个同名重载不应逐个改名)。修 §4 时注意。
- `common_fix` 已含:NBSP→空格、全角分号/引号→半角、`system("pause")``pause()`。再加:`strcpy/strlen` 等补 include 即可(勿重复已有逻辑)。
- `ast.parse` 能过不代表运行正确:函数嵌套/作用域错误会跑到运行才炸。改生成器后务必实跑一遍 `python3 tools/gen_part1.py` 看是否抛异常。
- grep `-c``-E` 混用会 `conflicting matchers`;本会话多次踩,请用单一 matcher 或 `python3 -c` 数。
(手册结)