课程代码仓库初始化:Part1 (144) + Part3 (29) 全量生成与验证
把川大 wiki「02.Qt方向」课程代码整理为 CMake 管理的可编译运行项目。
Part1 C/C++ 强化 (p01/, 144 目标, host gcc/g++ 构建, 全绿):
- 修复全部编译失败:补 <cstring>/<fstream>/<iomanip>/<vector> 等缺失头
(common_fix + infer_stl_includes 自动检测注入)、修正 pause() 壳注入
(改检测已转换后的 pause 调用)、namespace 提升出函数体、const 成员函数
正确性、dedupe 不再破坏函数重载集、K&R 隐式 int / 动态异常规范等
C++17 移除特性的可编译等价改写。
- 目录采用深缩写 p01/ch04/s03/ (原 part1_cpp/ch04_class_object/03_ctor_dtor)。
Part3 Qt 桌面 (p03/, 29 目标, 隔离 Qt 5.14.2 构建, 全绿):
- gen_part3.py: Qt 外壳模板 (main+QApplication+show, QTimer 自动退出便于
offscreen 验证)、AUTOMOC + .moc include、rewrite_* 处理散文混入/重载/
资源依赖、生成占位 png/gif + .qrc + rundata 样例数据。
- 修正 QLable 笔误、全角分号、.→->、Windows 路径、QApplication 阻塞事件
循环改为 QCoreApplication 等。
任务1 概念/版本验证:
- tools/std_probe.py: 跨 -std= 编译探针 (--pedantic-errors 让已废除特性硬失败)。
- tools/demo_versions/: K&R 隐式 int、三目左值、void* 转换、enum 赋整、
const 经指针、动态异常规范 共 6 个跨版本演示。
- docs/VERSION_NOTES.md: 每条「原文说法→C17/C++17 是否成立→何版本成立→已验证」。
文档: 顶层 README、docs/SOURCE_PAGES.md (页面→目录映射)、
docs/ERRATA.md (Part1 修正)、docs/ERRATA_part3.md (Part3 修正)。
另修复 tools/run.sh / run_qt.sh 的 ${1:?...} 引号语法 bug。
隔离 Qt 验证: ldd 0 系统 Qt 引用; 173/173 目标全绿; p03 offscreen 运行通过。
This commit is contained in:
+211
@@ -0,0 +1,211 @@
|
||||
# HANDOFF — qt-course 课程代码仓库生成/验证 续接手册
|
||||
|
||||
> 本手册供「新开会话」从当前进度继续。读完即可无缝接手。
|
||||
> 仓库路径:`/home/charles/workspaces/qt-course`
|
||||
> 上次工作会话日期:2026-06-30
|
||||
|
||||
---
|
||||
|
||||
## 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 | ✅ 完成 |
|
||||
| Docker 构建/安装/运行脚本(构建容器模型) | ✅ 完成(轻量 builder 镜像已构建) |
|
||||
| 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 状态**:仓库已 `git init`,但**尚未任何提交**(0 个 tracked 文件,所有内容 untracked)。
|
||||
|
||||
---
|
||||
|
||||
## 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 到 .qt514/(venv+apt)
|
||||
│ ├── docker/ # Dockerfile + docker_build_image/install_qt/build.sh
|
||||
│ └── wiki_data/ # 抓取的 wiki 正文+代码块(已拷入,生成器输入)
|
||||
├── docs/
|
||||
│ └── ERRATA.md # 已记录 30 处修正(自动生成)
|
||||
├── part1_cpp/ # 已生成 144 个目标(17 个 dir)
|
||||
└── part3_qt_desktop/ # 空目录,待生成
|
||||
```
|
||||
|
||||
**Part1 当前目录形**(待用户要求改为深缩写,见 §5):
|
||||
`part1_cpp/ch04_class_object/03_ctor_dtor/ctor_and_dtor.cpp` 等。
|
||||
|
||||
---
|
||||
|
||||
## 3. 已验证可用的关键命令
|
||||
|
||||
```bash
|
||||
cd /home/charles/workspaces/qt-course
|
||||
|
||||
# 重新生成 Part1 全部源码 + CMakeLists(幂等;每次改生成器后先 rm -rf part1_cpp)
|
||||
rm -rf part1_cpp build && python3 tools/gen_part1.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(宿主机,一次性)
|
||||
tools/install_qt_host.sh
|
||||
# 或用容器装:tools/docker/docker_install_qt.sh(需先 tools/docker/docker_build_image.sh)
|
||||
```
|
||||
|
||||
**隔离 Qt 核心事实**(已验证):靶机=gcc13+glibc2.39;容器与宿主机同栈;二进制容器编译宿主机运行;`.qt514` 是唯一真相源;`ldd` 0 系统 Qt 引用;`QT_QPA_PLATFORM=offscreen` 可无 X 运行验证。
|
||||
|
||||
---
|
||||
|
||||
## 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 页面 pageId(58954515–58954552),共 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()`
|
||||
- 过时 API(Qt5.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 58954515–58954552 的映射(约 16–25 个 section)。
|
||||
|
||||
**验证**:Docker 容器构建 → 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`;生成 Part3;Docker/host 构建;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 目标名 ASCII(CMake 禁非 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` 数。
|
||||
|
||||
(手册结)
|
||||
Reference in New Issue
Block a user