Carbon 语言工具链与语言版本管理方案:SemVer 驱动的 `MAJOR.MINOR.PATCH` 版本化设计全解析
Carbon 语言工具链与语言版本管理方案SemVer 驱动的MAJOR.MINOR.PATCH版本化设计全解析【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang导读本文以 Carbon Language 项目提案 Establish toolchain and language versioning 及其落地的 版本管理文档 为核心系统讲解 Carbon 如何为语言、标准库、编译器、链接器等全套工具链设计一套**单一、统一、基于 Semantic VersioningSemVer**的版本号方案MAJOR.MINOR.PATCH各段位的递增语义、破坏性变更的判定与豁免规则、rc.N/nightly/dev三类预发布版本的含义与排序机制以及面向 1.0 之后的语言演化类 Rust Edition 机制、LTS 版本与标准化的前瞻规划。读者读完后既能完整理解 Carbon 版本号每一段的何时变、为何变、怎么读也能在仓库源码bazel/version/与.bazelrc中看到这套方案的真实工程落地方式。为什么 Carbon 需要版本化方案提案在 Problem 一节指出Carbon 无论对语言本身还是实现该语言的参考工具链都需要一套版本化方案。这套方案在尚未达到任何具体里程碑之前就应定义并落地——因为版本号既要服务于里程碑标记也要在它开始对用户有意义之前把规则先定清楚避免临场拍脑袋。更深层的原因是编程语言与其标准库对用户暴露的API面极其广阔且耦合紧密——几乎所有用该语言写出的源码都依赖这个API。因此 SemVer 通用标准必须被翻译成语言语境下的具体规则明确什么是 Carbon 的公共 API、什么算变更否则版本号将缺乏可判定的语义。从项目目标看docs/project/goals.md这份版本化方案直接服务于两大目标语言工具与生态系统Carbon 需要一个贯穿语言本身及生态的一致版本方案尤其在语言高速演进期让工具链与生态就语言特性对表软件与语言演化用户需要一个清晰的模型来理解、跟踪语言演化并在大量不同形态的版本中不产生混乱。提案核心单一版本 SemVer 明确的预发布语义提案的 Proposal 一节给出四点主张随后在 Summary 中浓缩为可操作的版本格式主张要点单一版本语言、标准库、编译器、链接器及主项目发布的全部开发工具共享同一版本号基于 SemVer版本格式MAJOR.MINOR.PATCH并明确 SemVer 标准在语言语境下的映射明确的预发布语义定义一套数量少、语义清晰的预发布版本避免歧义面向未来的方向性指引为 1.0 之后的语言演化、LTS、标准化预留方向汇总后的版本格式为MAJOR.MINOR.PATCH正式版本号MAJOR.MINOR.PATCH-rc.N第 N 个可能成为正式发布的候选版本MAJOR.MINOR.PATCH-0.nightly.YYYY.MM.DD某天自动构建的夜间增量开发版MAJOR.MINOR.PATCH-0.dev开发者交互式增量构建的开发版。下面结合 版本管理文档 的细化内容逐段拆解。MAJOR主版本递增与破坏性变更与 SemVer 对齐任何对语言或工具链任意部分的破坏性变更breaking change都必须递增主版本。文档 docs/project/versioning.md 对此有更细化的约定从0到1的首次递增基于达成某个功能完整性与质量里程碑即声明语言进入稳定版对应 docs/project/milestones.md 中的 1.0 里程碑1.0 之后的递增采用基于时间的发布策略已就绪的特性/破坏性变更随当前主版本发布其余等待下一个主版本具体节奏属于未来工作需在临近 1.0 时与用户讨论确定递增主版本只是可以做破坏性变更不代表应该做。破坏性语言变更因用户迁移成本churn极高而代价巨大但参考 C 语言、编译器与标准库更新的经验真正做到零破坏极其困难且过度约束。预期多数版本尤其早期会包含一定程度的破坏性变更项目的工作方向是让升级尽可能廉价、变更尽可能小未来若 Carbon 稳定到一定程度可能重新评估用次版本号承载某些发布届时会再修订版本与发布策略。什么算破坏性变更在 docs/project/versioning.md 中破坏性变更不仅限于传统意义上的 API 破坏标准库 API 或工具 API 变化还包括语言与工具链层面任何导致正确、可用、非反射non-reflective的代码变得无效、被拒绝、结果不正确或行为被静默改变的变化都算破坏性变更。豁免项什么不算破坏性变更文档明确了两类豁免反射式代码reflective code以某种方式探测 Carbon 版本、或检测某特性存在与否的代码。它们可能因为检测到了本该是非破坏性的新增而被破坏。Carbon 不希望新增特性被算作破坏性变更因此将这类专门检测新增内容的代码排除在外错误代码的破坏除非某段错误代码尽管有 bug但已被接受且在某种有用且通常广泛的方式下正常运行否则对错误代码的破坏性修改不算破坏性变更。MINOR次版本递增的定位当前阶段 Carbon 计划主要依靠主版本为0时的次版本递增来追踪通向 1.0 的进度。具体而言已定义0.1与0.2两个里程碑详见 docs/project/milestones.md必要时可再增加细分步骤提案 p004105 明确MINOR递增只在早期开发阶段、主版本为0时预期发生若未来 Carbon 足够稳定可能重新启用次版本号来标记向后兼容的发布在 1.0 之后的世界里项目预期多数重要特性会伴随少量可管理的、由废弃deprecation引起的破坏性变更因此当前计划是 1.0 之后不做纯次版本发布而是聚焦于让更新对语言用户既容易又规模化。PATCH补丁版本只修 bug补丁版本仅在对先前发布版本进行根本性 bug 修复时递增绝大多数应为严格向后兼容的修复。关键约定补丁发布由需求驱动不必然存在具体排程与流程将在准备 1.0 里程碑时确定1.0 之前不承诺任何补丁发布流程或节奏因为此前的任何发布都不应被视为稳定恢复某个版本的预期公共 API也被视为 bug 修复即使这类修复理论上可能破坏按新写法编写的代码、通常需要递增主版本只要它确实是在恢复该版本的预期行为就可以仅用补丁版本承载。由于这类修复仍可能造成破坏SemVer 承诺被严肃对待补丁修复需满足很高的门槛docs/project/versioning.md 给出三项叠加判据必须是回归regression修复而非特性补齐修复的是用户从先前版本遇到的回归包括语言或工具整体凝聚力/可靠性的回归任何补丁修复都应从回归修复与稳定化而非向前修复的视角论证破坏范围可证明很小结合含回归的发布持续时长很短与可能受影响的代码构造范围很窄来判定回归影响大且难以绕过例如动摇了相当规模用户群的核心优先目标或使任何重要用户群采用该发布版本的工程成本不经济。PATCH 判例文档中的四个示例场景是否值得补丁发布原因与替代处理新特性含 bug 导致 unsoundness可编译出运行时崩溃或 UB 的错误代码值得即使属新特性也是语言整体可靠性的严重回归除非发布数月后才被发现且修复代价同样巨大安全性漏洞除外小众新特性含 bug使本应可用的代码模式被编译期拒绝或稳定崩溃不值得使用面窄入侵式修改不划算更适合对可能触发崩溃的用法甚至使用该特性发出警告或错误通过 flag 开启的编译器可选特性不可靠不适合向前修复更宜禁用该 flag 或触发警告编译器默认开启opt-out的特性不可靠视影响面而定影响极小则文档化退出方式影响足够大、构成体验回归则值得窄范围补丁修复或缓解预发布版本rc、nightly 与 dev 的语义与排序SemVer 为预发布版本提供了非常开放的框架但没有规定语义模型。Carbon 选择定义一套小而清晰的预发布版本让它们用 SemVer 规则比较时能有序排列。文档规定的预发布版本降序MAJOR.MINOR.PATCH-rc.N MAJOR.MINOR.PATCH-0.nightly.YYYY.MM.DD MAJOR.MINOR.PATCH-0.dev发布候选-rc.N当某个版本被认为完整、可发布并希望收集反馈时创建release candidaterc预发布。判定标准与预期正式版之间不应存在有意义或显著的差距哪怕是已知差距除非收到反对反馈发布候选应能直接转正为正式版本。每个预发布类别都使用该版本的顺序计数N且必须以.0起始才能保证同一版本、同一类别后续迭代版本在 SemVer 排序中排在第一个之后。夜间构建-0.nightly.YYYY.MM.DD夜间版本是每晚自动化测试通过后自动构建的增量开发版不提供任何高于当时代码库 通过自动化测试的质量门槛其首要用途不是评估潜在发布而是供 Carbon 开发者与贡献者跟踪增量开发进度机制上在nightly之前插入0组件确保其排序在所有发布资格预发布版本之前追加日期派生后缀YYYY.MM.DD为版本号相同的夜间构建提供粗略的时间顺序。开发构建-0.dev开发期间的交互式构建需要无歧义的版本标记即dev预发布版本与夜间版本类似只是开发活动的产物从不参与任何发布流程它们不要求自动化、不要求可复现可能包含未完成的在途编辑及各种变体机制上同样以0前缀保证有效排序不附加额外信息例如无法轻易提取构建日期以保持开发构建机制简单并最小化缓存影响。源码落地版本字符串在仓库中的真实生成链路提案与文档并非纸上谈兵——仓库中已有一套完整的 Bazel 版本生成实现可以直接观察到这套方案如何被工程化。版本基线与预发布后缀的拼装仓库根目录的 version_base.bzl 定义了当前活跃开发版本的基线version_base 0.0.0该文件注释明确说明当前开发版本为0.0.0因为尚未对 0.1 里程碑取得足够进展且永远不会发布 0.0.0 的非开发预发布版本只会出现 0.0.0 的夜间开发预发布。真正的拼装逻辑在 bazel/version/compute_version.bzl 的compute_version函数中对应提案中三类预发布后缀的编码若_release_flag为假则依据pre_release值追加后缀rc读取rc_number要求非负拼为-rc.Nnightly读取nightly_date并调用_validate_nightly_date严格校验YYYY.MM.DD三段格式年 4 位、月/日各 2 位且均为数字拼为-0.nightly.YYYY.MM.DDdev直接拼为-0.dev其他取值直接fail。这与提案中rc、nightly、dev的形态一一对应包括nightly与dev必须带0前缀的排序设计。Bazel 构建标志与命令行别名bazel/version/BUILD 定义了四个版本相关构建标志均为默认值供 Bazel 调用时覆盖标志类型默认值说明--releaseboolfalse启用正式发布版本启用时必须是唯一使用的版本标志--pre_releaseKINDstringdev取值仅限rc、nightly、dev三者之一--rc_numberNint-1设置发布候选编号要求--pre_releaserc--nightly_dateYYYY.MM.DDstring设置夜间预发布日期要求--pre_releasenightly为方便命令行使用.bazelrc 提供了等价的短别名因此实际构建时可写为bazel build //... --release bazel build //... --pre_releaserc --rc_number2 bazel build //... --pre_releasenightly --nightly_date2024.06.17 bazel build //... --pre_releasedev源码注释中以2024.06.17作为 nightly 日期示例实际日期按需替换即可。从模板到最终版本字符串bazel/version/rules.bzl 的expand_version_build_info规则负责把模板文件扩展为携带版本与构建信息的源码文件支持的替换键包括VERSION、GIT_COMMIT_SHA、GIT_DIRTY_SUFFIX、BUILD_TIMESTAMP等。最终成品可在 common/version_stamp.tmpl.cpp 中看到版本字符串的实际形态constexpr llvm::StringLiteral Version::String $VERSION$GIT_COMMIT_SHA$GIT_DIRTY_SUFFIX; constexpr llvm::StringLiteral Version::ToolchainInfo R( Carbon Language toolchain version: $VERSION$GIT_COMMIT_SHA$GIT_DIRTY_SUFFIX );也就是说Carbon 工具链实际展示的版本形如0.0.0-0.devgit短哈希[.dirty]将提案中的版本方案与 git 提交信息组合为可追溯的构建标识供carbon驱动等工具读取版本头文件见 common/version.h。版本号与里程碑的联动提案与里程碑文档 docs/project/milestones.md 明确挂钩Carbon 为初始里程碑分配版本号便于引用与纳入版本化方案——0.1MVP供 C 用户与开发者开始认真评估的最小可用产品覆盖核心语言特性包、导入、命名空间、用户定义类型、泛型、控制流等与最小标准库组件0.2功能完整达到足以让用户完成评估的功能完备度内存安全、协程/async、Carbon 原生线程等显式推迟至此里程碑之后1.0不再是实验标志 Carbon 不再是实验、可用于生产。版本化文档将0 → 1的首次递增定义为基于功能完整性与质量里程碑的判定。这正是MINOR递增在0.x阶段扮演进度刻度、MAJOR递增承担稳定性声明的设计意图。面向未来的方向性草图提案的 Directional sketch for the future 明确指出上述机制对 1.0 之前的版本足够但 1.0 之后语言与项目的需求将扩大需要更多细化的版本与演化工具。这些只是方向性指引届时需要各自的独立提案。语言演化与破坏性变更的解耦长期来看单一版本号不足以支撑语言的演化需求。提案建议至少把主版本映射为类似 Rust Edition 的源码内控制机制允许代码库在同一工具链版本下增量采纳破坏性变更的修复或新语言特性——即部分代码即使使用新编译器仍可按先前主版本的语义编译Rust 已在实践中验证、C 亦被提议采用editions源码显式选择版本语义使编译器在增量迁移期间支持混用代码Carbon 至少需要等价机制并可能探索更细粒度的功能集 opt-in系统类似 pragma 式扩展用法或 Circle 编译器无论具体形态如何关键在于破坏性变更的铺开不得被强制绑定到 Carbon 工具链升级每一步都应增量推进。LTS 版本与标准化SemVer 足够检测问题但不足以解决某些用户对语言稳定性的需求方向是LTS 版本基于特定完整度、质量水平与用户需求指定 LTS支持窗口可能比 Linux 发行版 LTS 更长甚至需要数十年级别的支持窗口窗口拉长后 LTS 频率应降低避免维护过多版本造成不可持续LTS 的指定方式留给未来工作但预期不改变版本号模式与结构只改变针对该发布版本的支持策略标准化部分环境要求语言标准化才可使用。提案将标准化类比为把普通发布提升为 LTS——选定某个有效的 LTS 走标准化流程形成标准标准更新则跟踪为更新版本的 LTS。具体做法留给未来工作核心意图不是约束达成 LTS 或标准的路径而是明确 Carbon应当开放并规划这些能力以满足潜在用户的需求。备选方案对比为什么这样设计提案的 Alternatives considered 记录了被否决的备选路径可帮助理解最终取舍备选方案否决原因什么都不做 / 只谈最小 nightly 版本项目各处milestones、roadmap已在讨论版本号提前建立沟通机制更有效也能更早向社区传递发布意图与节奏1.0 之后不做任何破坏性变更与软件与语言演化目标直接冲突Carbon 为兼顾 C 互操作与增量内存安全注定较复杂必须保留改进与修复问题的能力各组件独立版本化需仔细维护组件间兼容矩阵而现代语言中编译器、语言、标准库、工具链深度耦合Clang/GCC 大版本升级的经验表明工具链变更与语言变更同样具破坏性使用自定义版本方案而非 SemVerSemVer 本就是宽松框架、可容纳自定方案套用 SemVer 只需极小的装饰性调整还能直接复用脚本与大众心智模型避免外部人员误读增加更多预发布变体如 alpha/beta无证据表明需要nightly rc 的组合大概率已覆盖全部实际用例维护少见用例的基础设施与文档是净负担其中什么都不做一节还强调这套详细方案不是锁死——Carbon 可以在任何时刻按需修改任何部分会倾听潜在用户反馈并调整。结语Carbon 的版本化方案以单一版本 SemVer 明确预发布语义为骨架MAJOR承载破坏性变更与里程碑声明、MINOR服务 0.x 阶段的进度追踪、PATCH只修 bugrc.N、0.nightly.YYYY.MM.DD、0.dev三类预发布则把发布候选、自动夜间构建与交互开发构建各归其位。这一设计不仅写进了 docs/project/versioning.md也已通过 version_base.bzl、bazel/version/compute_version.bzl 与 .bazelrc 等真实工程化实现落地并经由 common/version_stamp.tmpl.cpp 进入每个工具链二进制。对关注 Carbon 演进的开发者而言理解这套规则就等于拿到了解读 Carbon 每一个发布、每一次升级意图的版本号字典。【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →