Files
scuc-qt-course/HANDOFF.md
T
张宗平 8e44203929 更新 HANDOFF:标注正文为历史记录,修正 §1/§2/§3 过时项
正文 §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 统一标注。
2026-06-30 16:31:32 +08:00

16 KiB
Raw Blame History

HANDOFF — qt-course 课程代码仓库生成/验证 续接手册

本手册供「新开会话」从当前进度继续。读完即可无缝接手。 仓库路径:/home/charles/workspaces/qt-course 上次工作会话日期:2026-06-30全部完成,已首次 git 提交)


⚠️ 当前状态:全部完成(2026-06-30 第二次会话)

本会话已把 HANDOFF §1 中所有「未完成」项做完。仓库已首次提交 (commit 13b3ebb287 文件)。后续会话主要做维护/扩展,不需重做以下工作。

  • 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 件事:

  1. 按章节+话题组织课程代码仓库,用 CMake 项目管理,每个可执行文件 = 一个独立 add_executable 目标;为 Qt 示例准备一套与主系统隔离的 Qt 5.14.x 开发环境;示例之间相对隔离。
  2. 验证所有示例代码在原文所述语言(C 或 C++,先按 C17/C++17)下仍能编译通过、概念仍符合当前标准;不符的确认在何版本成立并编译验证;提供「快速演示不同版本对概念支持」的机制。
  3. 修正示例代码错误并演示。

用户后续追加的关键指令:

  • 源文件名用英文,与章节名匹配;同小节多文件用语义后缀区分。
  • 目录约定: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 状态(此表为历史快照,已被后续提交超越):首次提交为 13b3ebb287 文件); 截至 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/sNN17 个 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.pyexact_fix(pid,idx) 里):

  1. strcpy/strlen:对 ch04 块(pid 58954451 等),若 code 含 strcpy/strlen/strcmp 等而无 <cstring>/<string.h>,在 common_fixexact_fix 里补 #include <cstring>C++)或 <string.h>C)。建议加到 gen_sources.pycommon_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 只对「同名且跨块」改名,块内多个同名重载视为同一组用序号区分——或更稳妥:函数重载演示块整体改名前先识别是重载集(同名不同参数),统一改名 MyFuncMyFunc_<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.pyPAGE_CONFIG 里把 dir 值统一改为深缩写;或在 main() 拼接 out_dir 处做映射):

  • part1_cppp01
  • ch04_class_objectch04
  • 01_basic_conceptss0102_oo_cases02,……
  • ch03_cpp_extends_cch03,等等。
  • 主顶层 CMakeLists.txtadd_subdirectory(part1_cpp)add_subdirectory(p01)
  • 同步更新 tools/run.sh / 任何写死 part1_cpp 的地方。
  • Part3 同理 part3_qt_desktopp03

映射依据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 已列):

  • 笔误:QLableQLabel.->、全角;"D:\ndrawing.pic""D:/drawing.pic"、类后缺 ;
  • tr() 在非 QObject 上下文(main) 不可用 → QObject::tr/QStringLiteral
  • 资源依赖::/images/*.png:/Image/boat.jpg:/Mario.gif:/Image/butterfly*.pngin.txt/file.dat/file.txt → 各自生成占位文件 + .qrcCMake qt5_add_resources()
  • 过时 APIQt5.14 仍可用,保留并记 VERSION_NOTES):QMouseEvent::x()/y()QString::sprintf、Qt4 SIGNAL/SLOTstatic_cast 重载解析(Qt6 起弃用)

生成器骨架:仿 gen_part1.pygen_part3.py,复用 gen_sources.pypage_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 各目标的子 CMakeListsset(CMAKE_AUTOMOC ON))。
  • 资源目标:需 .qrc + 占位 png(用工具生成纯色小 png 即可,不依赖原图)。
  • 语言全是 C++(.cpp)。
  • 英文文件名映射表 file_name_map.py 里目前只有 Part1Part3 需新增 pageId 5895451558954552 的映射(约 1625 个 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;生成 Part3Docker/host 构建;offscreen 运行验证。
  5. std_probe.py + tools/demo_versions/;填 docs/VERSION_NOTES.md
  6. docs/SOURCE_PAGES.md(pageId→章节映射表)、各章 README、顶层 README。
  7. 全量 clean buildgit 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. 上次会话犯过、勿重犯的坑

  • ERRATAgen_sources.py 模块级可变列表,record_erratum 追加到该列表;gen_part1.py 必须 import gen_sources; ERRATA = gen_sources.ERRATA(早期误用 from ... import ERRATA 独立拷贝导致 write_errata 看到空列表)。
  • block_classifydecl_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 数。

(手册结)