正文 §1–§10 是完成前的过程记录,未随「全部完成」banner 同步重写。 本次核实发现其会误导新会话,做定向修正: - banner 新增声明:§1–§10 为历史记录,旧目录名/旧状态/旧命令均过时, 以 banner + README + 实际目录(p01/p03)为准;并附本次端到端核实结论 - §1 git 状态行:删除「尚未任何提交」的失实表述,改为以 git log 为准 - §2 仓库布局树:part1_cpp/→p01/、part3_qt_desktop/→p03/,补全 docs/ 与 ERRATA 条数 - §3 重生成命令:rm -rf part1_cpp build && gen_part1 → rm -rf p01 p03 build && gen_part1 && gen_part3 §4/§5 中保留的旧名属该节历史上下文(§5 即改名计划本身),已由 banner 统一标注。
16 KiB
HANDOFF — qt-course 课程代码仓库生成/验证 续接手册
本手册供「新开会话」从当前进度继续。读完即可无缝接手。 仓库路径:
/home/charles/workspaces/qt-course上次工作会话日期:2026-06-30(全部完成,已首次 git 提交)
⚠️ 当前状态:全部完成(2026-06-30 第二次会话)
本会话已把 HANDOFF §1 中所有「未完成」项做完。仓库已首次提交
(commit 13b3ebb,287 文件)。后续会话主要做维护/扩展,不需重做以下工作。
- Part1:144/144 全绿(原剩 13 个 FAILED 已全部修复,见 §4 新增的修正清单)。
- 目录深缩写已应用:
p01/ch04/s03/形式。 - Part3 Qt:29 目标全绿,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 件事:
- 按章节+话题组织课程代码仓库,用 CMake 项目管理,每个可执行文件 = 一个独立
add_executable目标;为 Qt 示例准备一套与主系统隔离的 Qt 5.14.x 开发环境;示例之间相对隔离。 - 验证所有示例代码在原文所述语言(C 或 C++,先按 C17/C++17)下仍能编译通过、概念仍符合当前标准;不符的确认在何版本成立并编译验证;提供「快速演示不同版本对概念支持」的机制。
- 修正示例代码错误并演示。
用户后续追加的关键指令:
- 源文件名用英文,与章节名匹配;同小节多文件用语义后缀区分。
- 目录约定:
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 状态(此表为历史快照,已被后续提交超越):首次提交为 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 到 .qt514/(venv+apt)
│ ├── docker/ # Dockerfile + docker_build_image/install_qt/build.sh
│ └── 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/sNN(17 个 dir)
└── p03/ # Part3:已生成 29 目标,深缩写 chNN/sNN
实际目录形(深缩写已应用,见 §5):p01/ch04/s03/ctor_and_dtor.cpp 等。
3. 已验证可用的关键命令
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(宿主机,一次性)
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) 里):
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 修复)。- namespace-in-function (block 41/42):仿照已写好的 block 3/6/7 的
exact_fix,把namespace定义提到文件作用域。 - 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→p01ch04_class_object→ch0401_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,CMakeqt5_add_resources() - 过时 API(Qt5.14 仍可用,保留并记 VERSION_NOTES):
QMouseEvent::x()/y()、QString::sprintf、Qt4SIGNAL/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. 接手后立即应做的最小步骤
- 读本手册 +
tools/gen_part1.py+tools/gen_sources.py了解生成器。 - 修 Part1 剩余 4 个 FAILED(§4):补
<cstring>、namespace 提升 41/42、dedupe 重载集。重建到 144/144 全绿。 - 应用深缩写目录(§5):改
PAGE_CONFIG的 dir 为 p/ch/s,全量重建确认路径。 - 写
gen_part3.py+ 扩file_name_map.py;生成 Part3;Docker/host 构建;offscreen 运行验证。 - 写
std_probe.py+tools/demo_versions/;填docs/VERSION_NOTES.md。 - 写
docs/SOURCE_PAGES.md(pageId→章节映射表)、各章 README、顶层 README。 - 全量 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数。
(手册结)