build2-package 是做什么的?
解析 ROOT
设 HERE 为包含此 SKILL.md 的目录(系统上下文中的绝对路径)。
ROOT 是 build2 技能树。使用第一个其 guides/packaging-guide-summary.md 存在的候选路径:
HERE/../build2(同级布局:此目录与build2技能相邻,包括复制到用户级技能目录中的副本)HERE/../..(嵌套布局:此目录位于build2技能的skills/子目录下)
如果两者都不存在,则停止。
之后的所有 read_file 路径均为 ${ROOT}/...。
此文件即流程。${ROOT}/guides/ 和 ${ROOT}/HOWTO/ 下的打包指南是每个步骤正确做法的权威来源。请勿自行创造布局、bdep new 调用、分支名称或发布序列。
外部操作需要明确批准
此技能会创建真实、公开可见的包并最终发布。任何可能在你本地工作树之外可见的操作都不会自动发生。这包括:在 GitHub 上创建仓库、任何 git push(分支或标签)、在 GitHub 上转移或重命名仓库、打开或合并拉取请求、运行 bdep ci 以及运行 bdep publish。
运行 /build2-package(或 /build2 package)并不表示对这些操作的批准,到达需要执行这些操作的关卡也不表示自动批准。在本轮运行中首次执行其中一项操作之前,请停止,准确说明即将发生的事情(命令及其对外界可见的内容),并等待用户对该特定操作的明确指示。对一次此类操作的批准不会延续到后续操作,每次都需要重新请求。默认假设:除非用户明确要求该步骤,否则这些操作都不会发生。
其他一切操作,包括本地提交、分支创建、编辑文件、本地构建和测试、只读克隆或拉取,均可直接进行无需询问。
硬性规则
这些规则不可选择。违反任何一条都意味着本轮运行失败。
- 禁止从头编写
buildfile。始终从bdep new开始。对于此工作流,请勿使用${ROOT}/scripts/new-package.sh。 - 在首次
bdep new --type empty,third-party提交之后、发布时的review分支快进合并到main之前,禁止触碰main分支。 - 禁止捆绑(vendoring)依赖项。将其解绑为
depends。 - 禁止将主
lib{}/exe{}目标放在根目录的buildfile中。 - 如果上游提供了编译模式,则禁止将库设为仅头文件。
- 禁止跳过源码分发配方(
b dist,然后在解压的归档中执行configure、update、test、clean)。仅通过bdep ci的绿色测试是不够的。 - 禁止降低自动生成的
depends: * build2/depends: * bpkg行。 - 禁止猜测上游标签、许可证或公共头文件包含方案。如果树中或获取的页面中没有,请停止并询问。
- 每个逻辑打包步骤(或紧密相关的组)只做一个 git 提交。其树恰好由一次
bdep new调用生成的提交,使用该命令行作为提交消息,不加其他内容。为单个上游文件创建.orig/.patch覆盖对的提交,使用Patch <filename>: <reason>(非平凡补丁可附带可选的<details>正文)作为消息,参见 packaging-guide-antipatterns.md。 - 在本地测试、已安装用例测试、分发测试和 CI 均通过之前,不要将
review合并到main,不要运行bdep release,也不要运行bdep publish。 - 每个目录级符号链接(而非普通文件符号链接)都需要在该包自己的
<pkg>/.gitattributes中添加匹配的symlink=dir条目(这是一个新文件,bdep new --package不会生成它),该条目与添加符号链接的提交在同一提交中。使用find <pkg>/ -type l -exec test -d {} \; -print验证,并对照<pkg>/.gitattributes交叉检查每个匹配项。git不记录符号链接类型,并且在检出时总是重新创建文件符号链接,因此跳过此步骤会导致包在 Windows 检出时损坏。 - 禁止留下叙述打包过程本身、早期未成功的方法或沿途错误的注释或 README 说明。注释和 README 仅反映最终状态(参见 packaging-guide-antipatterns.md,“Don't leave diary-style comments or notes”)。
- 未经用户明确批准,禁止创建仓库、推送、在 GitHub 上转移或重命名仓库、打开或合并拉取请求、运行
bdep ci或运行bdep publish。默认情况下这些操作都不会发生(参见上文“外部操作需要明确批准”)。
必须阅读的内容(本轮,任何写操作之前)
在创建仓库、编辑 buildfile 或发布之前,使用 read_file 完整阅读以下文件。请勿略读。
${ROOT}/guides/packaging-guide-summary.md${ROOT}/guides/packaging-guide-testing.md${ROOT}/guides/packaging-guide-antipatterns.md${ROOT}/HOWTO/package-naming.md
然后按需从此文件末尾的映射中加载。永远不要用记忆替代此文件命名的指南。
在操作过程中对照检查清单文档重新验证
一次完整的打包过程(关卡 A-K,或一次 new-version/revision 执行)可能跨越的轮次远多于单个上下文窗口所能容纳的。当你到达后续关卡时,早期轮次(包括上述必须阅读的内容)可能已被摘要取代。仅仅在开始时阅读过某指南,不意味着其规则仍然在上下文范围内,不要依赖对话记忆。
在到达每个关卡时至少重新打开并对照这些检查清单风格的文档检查树的当前状态一次,并在关卡 K(发布时)之前再检查一次:
${ROOT}/guides/packaging-guide-antipatterns.md:禁止的事项(手写 buildfile、在包中修复上游、更改上游布局、虽有编译模式却设为仅头文件、捆绑依赖、根 buildfile 中的主目标、过宽的修订版本、错误的头文件包含、临时修补、日记式注释或说明)。${ROOT}/guides/packaging-guide-review.md:cppget.org 审查者应用的相同检查清单。在发布前自行对照检查树,而不是在实际审查过程中才发现问题。${ROOT}/HOWTO/third-party-private-headers.md:私有头文件不得进入安装树。${ROOT}/HOWTO/buildfile-compile-options.md:哪些编译/链接选项是局部的,哪些是被导出的。${ROOT}/HOWTO/package-naming.md:在关卡 E 做出的命名决策,后期发现的改名代价高昂。${ROOT}/guides/packaging-guide-summary.md步骤 5:每个包中的每个目录符号链接都需要在该包自己的<pkg>/.gitattributes中有对应的symlink=dir条目(硬性规则 11)。
如果树不再符合上述任何一条,在进入下一关卡前修复它,而不是带着偏离继续前进。
参数
$ARGUMENTS 是 /build2-package(或 /build2 package)之后的调用文本。按顺序解析。第一个匹配的规则胜出。
| 第一个词元 | 模式 |
|---|---|
| 空 / 省略 | 如果 cwd 尚未是打包仓库则为 new,否则为 continue |
new | 初始打包过程 |
new-version | 首次发布后的新上游版本 |
revision | 打包修订(X.Y.Z+R) |
continue | 在 cwd 中恢复进行中的过程 |
| 其他任何内容 | 如果看起来像 git URL 或 owner/repo,则视作带有该上游的 new。否则询问。 |
剩余词元:可选的 <upstream-url> 和可选的 <tag-or-version>。如果任何一项缺失且模式需要,请询问。不要自行创造。
在首次写操作之前向用户报告选择的模式。
模式:continue
检查 cwd(及其 git 历史)并从下方匹配模式中第一个未完成的关卡恢复。证据优于对话摘要。
| 证据 | 从何处恢复 |
|---|---|
没有 .git,或没有 bdep new --type empty,third-party 首次提交 | 从头开始 new |
首次提交存在,没有 review 分支 | 创建 review 并继续 new |
在 review 上,没有 upstream/ 子模块 | 添加上游 |
upstream/ 存在,没有包目录 / 没有 bdep new --package | 包结构 |
| 包脚手架存在,测试或 CI 未通过 | 测试 |
测试通过,review 未合并到 main | 发布时合并 |
合并后在 main 上,没有 vX.Y.Z 标签 | 发布然后发布 |
| 已发布,用户要求新的上游 | new-version |
| 已发布,用户要求打包修复 | revision |
如果仓库在 main 上,但打包提交本应在 review 上,则停止。这是流程错误。不要重写已发布的历史。询问用户如何恢复。
模式:new(初始过程)
遵循 ${ROOT}/guides/packaging-guide-summary.md 中的检查清单以及 ${ROOT}/guides/packaging-guide-testing.md 中的步骤 8-10。以下编号的关卡不可跳过或重新排序。
关卡 A:现有工作
按此顺序搜索全部四个来源,并报告匹配项:
https://cppget.org/?advanced-searchhttps://queue.cppget.orghttps://github.com/build2-packaginghttps://github.com/build2-packaging/WISHLIST
如果仓库或已发布的包已存在,请停止并询问是否加入该工作(continue / new-version / revision),而不是开始重复的工作。
关卡 B:空仓库和首次提交
在此关卡的外部操作之前停止并获取明确批准: 创建 GitHub 仓库并推送初始提交。如果有助于展示即将推送的内容,可以先进行本地脚手架搭建(bdep new、git add、git commit),但在用户同意之前不要创建远程仓库或运行 git push。
在用户的个人工作空间中创建一个空的公共 git 仓库。描述:build2 package for <name>。使用 SSH 克隆。没有 README、许可证或 GitHub 生成的文件。
bdep new --type empty,third-party
git add .
git commit -m "bdep new --type empty,third-party"
git push -u origin main
在继续之前验证:
git rev-list --max-parents=0 HEAD为此提交。git show --stat --format=%s HEAD的消息完全为bdep new --type empty,third-party。- 树只包含该命令生成的文件。
如果该提交中有任何额外文件或手动编辑,请重置并重做。审查过程依赖于此。
关卡 C:review 分支
git checkout -b review
在此过程中的所有后续提交都保持在 review 上。不要 git checkout main。不要合并。不要发布。不要发布。
关卡 D:上游子模块
git submodule add https://github.com/<upstream>/<repo>.git upstream
仅使用 https://。检出发布提交(标签)。提交:Add upstream submodule, <tag>。
关卡 E:名称和布局
如有需要,重新阅读 ${ROOT}/HOWTO/package-naming.md。做出决定,并在生成包之前记录决定:
- Git 仓库名称:保留上游大小写,无
build2-前缀,无-package后缀。 project:和project =:小写,除非混合大小写是上游标识符(Qt 是文档化的例外)。- 包
name::库使用lib前缀,除非 Debian 和上游都使可执行文件冲突不可能发生。 - 将库与可执行文件拆分为单独的包。
- 公共头文件包含方案(子目录前缀 vs 文件名前缀)。
- 合并 vs 拆分
include//src/。
尽可能保持接近上游布局。
关卡 F:预填充然后 bdep new --package
创建包目录。仅符号链接存在的上游元文件(README.md、LICENSE / 等效文件、NEWS / CHANGES / ChangeLog)。单独提交该操作。然后:
bdep new --package --lang ... --type lib,...,third-party <name>
通过删除并重新运行来迭代,而不是手动编辑脚手架,直到布局匹配。需要 third-party 子选项。使用确切的命令行作为消息提交。
如果变更日志的基本名称不是已识别的名称,稍后手动设置 changes-file:。参见 ${ROOT}/HOWTO/package-changes-file.md。
关卡 G:版本、清单、依赖
- 版本保持
X.Y.Z-a.0.z直到bdep release --no-open。 summary:少于 70 个字符,无模糊措辞,无末尾句号。- 配套的
-tests/-examples/-benchmarks:复制主 summary 并追加(tests)(或对应类型)。不要重写。参见${ROOT}/HOWTO/tests-extra-dependencies.md。 license:为 SPDX(或other:)。参见${ROOT}/guides/packaging-license.md。- 取消注释
pkg.cppget.org前提条件。使用仍包含所有依赖项的最不稳定部分。不要在长期存在的repositories.manifest中保留queue.cppget.org。 depends编辑后执行bdep sync -a。- 此库公共头文件中的接口头文件放入
intf_libs。其他所有内容放入impl_libs。
关卡 H:填充源码和 buildfile
在接触 buildfile 之前填充包树:首先符号链接单个头文件/源文件,并且仅当这样做可以节省大量单个符号链接时才符号链接整个子目录(需要 buildfile-in-prefix 布局,参见 packaging-guide-antipatterns.md)。遵循 ${ROOT}/guides/packaging-guide-summary.md 步骤 5 中的实例。
必须: 对于刚添加的每个目录符号链接,在同一提交中向该包自己的 <pkg>/.gitattributes 中添加匹配的 symlink=dir 条目(如果文件不存在则创建)。使用 find <pkg>/ -type l -exec test -d {} \; -print 验证,并交叉检查每个匹配项。这是硬性规则 11,跳过它会导致包在 Windows 检出时损坏。在调整 buildfile 之前提交符号链接(和 .gitattributes),以便于回滚。
然后仅调整生成的文件。保留生成的结构和注释。
按需加载:
- 头文件 / 私有头文件:
${ROOT}/HOWTO/third-party-private-headers.md - SONAME / 输出名称:
${ROOT}/...
关卡 I:本地测试
遵循 ${ROOT}/guides/packaging-guide-testing.md 中的步骤 8-10。
关卡 J:PR 和 CI
创建拉取请求。确保 CI 通过。
关卡 K:发布
在获得用户批准后,合并 review 到 main,创建标签,运行 bdep release 和 bdep publish。
模式:new-version
遵循相同的流程,但跳过关卡 A-E,从关卡 F 开始,使用上游的新标签。
模式:revision
遵循相同的流程,但跳过关卡 A-H,从关卡 I 开始。
文件引用映射
以下是按需加载的文件映射:
${ROOT}/guides/packaging-guide-summary.md${ROOT}/guides/packaging-guide-testing.md${ROOT}/guides/packaging-guide-antipatterns.md${ROOT}/guides/packaging-guide-review.md${ROOT}/guides/packaging-license.md${ROOT}/HOWTO/package-naming.md${ROOT}/HOWTO/package-changes-file.md${ROOT}/HOWTO/tests-extra-dependencies.md${ROOT}/HOWTO/third-party-private-headers.md${ROOT}/HOWTO/buildfile-compile-options.md