2026/10/14 17:43:16

仓颉模块兼容性承诺详解:Library Evolution 规范概述与 cjcompat 兼容检查工具实现

仓颉模块兼容性承诺详解:Library Evolution 规范概述与 cjcompat 兼容检查工具实现 开发工具CLI代码质量【免费下载链接】cangjie_tools仓颉编程语言命令行工具包括仓颉包管理工具、仓颉格式化工具、仓颉多语言桥接工具及仓颉语言服务。项目地址https://gitcode.com/Cangjie/cangjie_tools点击查看免费下载本文基于仓颉模块演进兼容性规范版本号 0.1.4发布时间 2025-03-25见 Chapter_00_Cover.md的概述章节解析仓颉模块仓颉最小发布单元在演进时对下游使用者的 API 兼容与 ABI 兼容承诺边界、两项明确的例外豁免、以宏展开与类型推导完成后的代码为基准的判定原则并结合cjcompatCangjie Compatible工具在开源仓库中的源码实现说明该规范是如何被落地的、如何在本地执行一次真实的兼容性检查。规范背景与文档结构本规范定义的核心问题对一个仓颉模块在符合哪些条件的代码修改情况下能对下游使用者提供兼容性承诺。它同时作为仓颉工具链中配套工具CJCOMPAT的实现规格文档Specification——即仓库中 cjcompat 子项目所依据的设计蓝本。规范采用书册式结构目录见 SUMMARY.mdChapter_02_Overview.md概述即本文核心内容——目标、适用范围、豁免边界与判定基准Chapter_03_Rules.md兼容性规则正文按全局变量 / 全局函数 / struct / enum / class / interface / extend / import / typeAlias / package逐类给出 API 与 ABI 两列的兼容/不兼容判定表Chapter_01_Change_Log.md修订记录当前唯一一条记录为 2025/03/25 的 0.1.4 版增加修订记录区分 struct/class 中不同可见性的成员变量规则。参考本规范前规范要求读者具有相应的仓颉语言基础知识。兼容性承诺的两层定义规范将兼容承诺分为两个递进层级两者都以下游使用者的构建结果为承诺对象| 层级 | 定义 | 承诺强度 | |-|-|-| |API 兼容| 改动后保证下游代码重新编译能正常完成 | 源码级兼容允许重新编译下游 | |ABI 兼容| 在 API 兼容的基础上进一步保证下游代码在不重新编译的情况下可以直接重新链接 | 二进制级兼容下游产物无需重编 |理解这一分层的关键在于API 兼容只承诺源码还能编过去而 ABI 兼容要求下游的二进制产物可以原封不动地与新版模块链接。任何一项兼容性破坏都会同时向上波及ABI 破坏必伴随 API 破坏因此规则表中会出现大量API 不兼容 / ABI 不兼容同时成立的条目以及少量API 兼容但 ABI 不兼容的条目。规范明确豁免的三类场景在参考业界标准及实践的基础上概述章节特别划定了三类不属于兼容性破坏的边界场景。这些豁免条款直接决定了cjcompat检查器哪些变更应该被忽略对库作者规划变更、对工具使用者理解检查结果都有实际意义新增 API 引发的符号冲突 / 重载决议失败不属于 API 兼容破坏。具体包括新增全局变量、新增全局函数、新增自定义类型、新增扩展、已有类型新增父类和父接口、删除和放宽已有扩展中的泛型约束。这些操作虽然是新增但在特定条件下可能与下游代码产生同名符号冲突或导致函数重载决议失败——规范明确将其排除在 API 兼容破坏之外。FFI foreign 函数名称冲突不属于 ABI 兼容破坏。仓颉支持 FFI 操作若新版本新增了对 foreign 函数的依赖而该函数名恰好与其他模块依赖的 foreign 函数重名导致链接失败这不属于 ABI 兼容破坏。判定基准的特殊性第 3、4 条特别说明由于仓颉支持宏和条件编译二者会导致实际参与编译的代码与源码有差别因此文中介绍的兼容性规则均以完成宏展开和条件编译处理后的代码为判定基准由于仓颉支持自动类型推导文中涉及的类型均以自动类型推导完成后的类型结果为判定基准。这两条基准意味着阅读规则表时看到的类型声明指的都是编译前端处理后宏已展开、条件编译已求值、类型已推导完成的形态而非源码书写形态。CJCOMPAT规范的可执行实现规范概述中声明本规范也同时作为 CJCOMPAT仓颉工具链中提供的兼容性检查配套工具的实现规格文档。在开源仓库中这一角色由cjcompat子项目承担其目录与职责见 开发者指南CheckersAndRules检查规则、CjoLoadercjo 文件解析、DiffAST 差异识别、Dsl公共模块、Logger检查结果、Option命令行选项。命令行用法与参数cjcompat通过对比一个仓颉库两个版本的.cjo文件cjc 编译生成的包文件来判定兼容性是否变更。基本调用格式cjcompat -h帮助输出Usage: cjcompat --old /path/to/old.cjo --new /path/to/new.cjo [--api] [--abi] [--import-path /path] Options: -h Show usage eg: cjcompat -h --old value Path to the .cjo file corresponding to the old version of a Cangjie library. --new value Path to the .cjo file corresponding to the new version of a Cangjie library. eg: cjcompat --old filePathOld --new filePathNew --import-path value Add .cjo search path. --api Enforces rules for API compatibility. --abi Enforces rules for ABI compatibility. eg: cjcompat --old filePathOld --new filePathNew --api三种典型用法# 默认API 与 ABI 规则都检查 cjcompat --old old.cjo --new new.cjo # 仅检查 API 兼容规则 cjcompat --old old.cjo --new new.cjo --api # 仅检查 ABI 兼容规则 cjcompat --old old.cjo --new new.cjo --abi使用前提与约束来自 开发者指南 与源码--old和--new必须指定且仅允许出现一次路径必须以.cjo结尾否则报错退出两个.cjo必须是兼容版本内cjc编译生成的否则可能因版本不兼容出现解析错误运行前需设置CANGJIE_HOME指向 SDK 位置源码中CheckCangjieHome会强制校验该环境变量缺失则报Can not find CANGJIE_HOME, please setup CANGJIE_HOME若报Cannot load file old.cjo说明包还依赖其他.cjo文件可通过CANGJIE_PATH环境变量或--import-path指定依赖.cjo的搜索路径-v可打印cjcompat自身版本及其依赖的 Cangjie 编译器版本可执行文件依赖cangjie-lsp动态库Linux 下需将其加入动态库搜索路径如LD_LIBRARY_PATH。从源码看检查流水线cjcompat的执行入口在 main.cpp参数解析完成后调用 Cjcompat.cpp 中的CJcompat()流水线分为五步与规范的两层承诺一一对应解析命令行与环境。Option.cpp 中的HandleOptions()逐一遍历参数--old/--new/--import-path属于带参选项同一选项重复使用会报Argument: xx, used more than once!--api/--abi属于无参开关。CJCOMPATProcessFlag()中可以看到概述所对应的默认行为——未指定任何规则类型时enableAPI与enableABI同时置为 true即 API 和 ABI 规则默认都检查。此外SetCangjieModulesPath()会在CANGJIE_HOME/modules下寻找模块目录并解析CANGJIE_PATH作为额外搜索路径。加载两个版本的包。CjoLoader见 CjoLoader.h对old.cjo与new.cjo分别调用Load()其内部复用了仓颉编译器前端的Cangjie::CompilerInstance、TypeManager与SourceManager将.cjo还原为 AST 的Package节点。加载失败时输出Cannot load file并提示检查CANGJIE_PATH/CANGJIE_HOME或--import-path。计算 AST 差异。Cjcompat.cpp 中Diff diff(*pkg1, *pkg2, ...); diff.CalculateDiff();对两个包做差异识别产出后续检查器消费的变更集。按优先级执行检查器。AllCheckers见 Checker.h在构造时通过CheckersList.inc中的 X-Macro 展开出全部检查器RunAll()先按precedence稳定排序优先级数值小者优先执行且高优先级检查器一旦判定失败后续低优先级检查器直接停止结果交由Logger聚合。输出报告。Logger{enableAPI, enableABI}只记录命中且属于所启用承诺层级--api/--abi的规则条目最后由logger.Print(...)输出。规则与检查器的规模规范概述中的兼容性规则在实现中被形式化为两级结构规则RuleRule.h 中的RuleKind枚举由RulesList.inc展开定义共 310 余条规则每条规则在清单中显式标注它属于 API 层还是 ABI 层IS_API/IS_ABI标志这正是概述中API 兼容 / ABI 兼容两列判定表的代码化体现检查器CheckerCheckersList.inc 中注册了 94 个检查器如PackageDeclChanged、VarDeleted、FuncParametersChanged、ClassInstanceMemberFuncParamsOrRetTypeChanged等每个检查器可覆盖多条规则实现分布在 src/CheckersAndRules 的 10 个编译单元中特例佐证豁免条款PackageDeclChanged检查器优先级 50全局最高的注释明确指出修改包名会导致所有声明的 mangled name 不同破坏新旧版本声明的对应关系——这类跨声明关联的判定正体现了概述中以完成类型推导后的类型为判定基准的原则所要求的深度比对。与规则章节的衔接概述章节给出的是承诺的定义、豁免的边界与判定的基准具体的何种变更属于破坏则全部列在 Chapter_03_Rules.md 的判定表中按声明类别组织全局变量变更、全局函数变更、struct、enum、class、interface、extend、import 语句、typeAlias 语句与 package 声明语句每类再细分新增和删除场景 / 修改场景 / 修改定义位置修改场景进一步下钻到注解、编译标记如Deprecated、修饰符、泛型参数与约束、成员变量、成员函数、构造函数等子节。阅读建议先以本概述建立承诺—豁免—基准三层框架再对照 Chapter 03 的表格理解具体场景最后可用cjcompat对真实库的两个版本.cjo做一次实测观察Logger报告中的规则命中情况。小结兼容性承诺分两层API 兼容保证下游可重新编译ABI 兼容在此之上保证下游产物不重编即可重新链接新增 API 导致的符号冲突/重载失败、FFI foreign 函数名冲突均被规范明确豁免不属于兼容性破坏一切判定以宏展开、条件编译处理和类型推导完成后的代码为基准cjcompat是该规范的可执行实现--old/--new定位两个版本.cjo--api/--abi选择承诺层级默认双检底层由CjoLoader → Diff → Checkers → Logger流水线完成检查规则与检查器的完整清单分别见RulesList.inc与CheckersList.inc。赞分享开发工具CLI代码质量【免费下载链接】cangjie_tools仓颉编程语言命令行工具包括仓颉包管理工具、仓颉格式化工具、仓颉多语言桥接工具及仓颉语言服务。项目地址https://gitcode.com/Cangjie/cangjie_tools点击查看免费下载相关推荐cangjie_tools 中的 cjcompat基于 Library Evolution 规范的仓颉 ABI/API 兼容性检查工具详解cangjie_tools 中的 cjcompat基于 Library Evolution 规范的仓颉 ABI/API 兼容性检查工具详解 cjcompat开发工具CLI代码质量Kronos金融预测模型实战指南双路径部署深度解析与性能调优Kronos金融预测模型实战指南双路径部署深度解析与性能调优 在金融科技快速发展的今天量化交易团队面临着模型部署的多重挑战。Kronos作为专为金融市场设计人工智能大模型基础模型预训练金融科技lx-music-desktop 更新日志解读版本规范、发布流水线与兼容性承诺lx music desktop 更新日志解读版本规范、发布流水线与兼容性承诺 CHANGELOG.md https://link.gitcode.com/i桌面应用音视频前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考