资讯详情

资讯详情

Emscripten 开发流程指南:PR 合入规范、测试编写、版本发布与特性弃用机制

Emscripten 开发流程指南PR 合入规范、测试编写、版本发布与特性弃用机制【免费下载链接】emscriptenEmscripten: An LLVM-to-WebAssembly Compiler项目地址: https://gitcode.com/gh_mirrors/em/emscripten本文基于 Emscripten 仓库中的官方流程文档 docs/process.md系统梳理该 LLVM-to-WebAssembly 编译器的完整开发工程体系PR 合入Landing规则、测试编写约定、C/C/JavaScript/Python 三种代码风格、Minor/Major 版本发布流程、官网与emcc --help文档同步机制、LLVM 系统与 musl 系统库更新流程以及设置项/特性的弃用Deprecation流程。读完后你将掌握作为 Emscripten 贡献者或深度用户时如何合规地提交、测试、发布和维护这个工具链。一、文档定位与核心脉络docs/process.md 是 Emscripten 维护者约定的开发流程 发布流程双合一文档全文分为两大部分Development Processes开发流程Landing PRs、Writing Tests、Coding StyleRelease Processes发布流程Minor/Major 版本更新、emscripten.org官网更新、emcc.py帮助文本更新、LLVM 库与 musl 更新、设置项弃用。这些规则并非停留在纸面——仓库中的脚本、配置与测试目录正是其落地载体。下文按原文脉络逐节展开并给出对应的源码与配置文件佐证。二、Landing PRsPR 合入规则文档规定即使 PR 的代码已获批准approved合入仍受以下约束2.1 CI 先行合入的前提是 GitHub 上的 CI 保持绿色若 CI 失败仅当失败属于已知偶发性问题known intermittent failures且有很强的理由认为其与当前 PR 无关时才允许合入。如果看到某位没有 commit 权限的用户的 PR 已经获批无论批准人是你还是别人应在确认 CI 之后代为合入land it for them。如果你批准了某位有commit 权限的人的 PR且没有紧急性则留给作者本人合入——他们可能还有其他 PR 需要一起落地。2.2 Squash 优先Rebase 例外文档强烈推荐使用 GitHub 的squash选项合入 PR将其压缩为单个 commit——这也要求 PR 本身保持小粒度强烈建议小 PR。只有在同时满足以下三个条件时才允许保留多个 commitPR 不容易拆分为一系列小 PR例如评审必须整体考虑所有 commit因为单个 commit 难以独立理解或对后续 PR 的评审会反过来影响先前 PR 的讨论各个 commit 本身具有独立价值例如逐个阅读更容易理解各个 commit 与二分定位bisection兼容——即每个 commit 之后所有测试都应当通过。满足上述条件时合入多个 commit应使用rebase选项以避免产生 merge commit。2.3 PR 标题约定对非功能性变更NFCNon-Functional Change即不新增/修改功能的重构类改动在 PR 标题末尾追加NFC在 PR 标题开头添加[prefix]以标识所针对的子系统或领域例如[test] Update foo test或[ports] Fix zlib port。三、Writing Tests测试编写约定文档指出几乎所有 PR 都应附带某种测试并给出如下具体约定Bug 修复优先更新现有测试而非新增测试test_core.py与test_other.py的取舍大多数测试位于 test/test_core.py 和 test/test_other.py。二者的区别在于test_core.py中的测试会在多种不同的配置组合下运行因此在其中新增一个测试相当于在test_other.py中新增约 10 个测试——即test_core是覆盖面更广、成本更高的回归层优先黑盒测试尽可能通过编译器的公开命令行接口即emcc等命令来测试而不是直接调用内部 Python API独立源文件优先超过几行的 C/C 测试优先写成独立的.c/.cpp源文件而不是内嵌在 Python 测试代码中test/目录下大量独立的hello_world.c、test_mem_growth.c等文件正是这一惯例的体现;断言与返回码C/C 测试内部应使用assert检查预期并且main函数返回 0最小化回归复现对回归测试应尽量精简并理解复现代码从而写出最小测试用例C 优先于 C对简单测试总是优先使用 C 而不是 C——C 携带的系统包袱更小缩小被测系统的范围且编译速度极快系统库改动必须重建缓存测试对 system libraries 的改动时记得先重建所触碰的库例如运行./embuilder再执行测试或者用emcc --clear-cache这种简单粗暴的方式强制重建所有库。四、Coding Style三种语言族的代码风格4.1 C/C 代码在 Emscripten 中编写新的 C/C 代码时遵循LLVM 风格binaryen 亦同。可以使用clang-format自动格式化新代码也可以用git clang-format origin/main只格式化自己改动的行。仓库根目录的 .clang-format 给出了具体细节——从文件内容可以确认其基于 LLVM 风格BasedOnStyle: LLVM指针左对齐并为EM_ASM、EM_JS、MAIN_THREAD_EM_ASM等自定义宏设置了WhitespaceSensitiveMacros保证这些宏内的空白不被格式化破坏。编辑 musl、libc 等第三方代码时则应遵循上游upstream自身的约定不要套用 LLVM 风格。4.2 JavaScript 代码JavaScript 使用与 C/C 相同的 LLVM 系风格。文档同时提醒clang-format对 Emscripten 的 JS 库代码并不总是好用因为这些代码会用到自定义宏与预处理器机制对应 .clang-format 中 JavaScript 语言块BasedOnStyle: LLVM、ColumnLimit: 100。4.3 Python 代码Python 总体遵循 pep8唯一的大例外是缩进使用 2 空格。CI 会对所有 PR 运行ruff以强制该风格。具体的 lint 配置见 pyproject.tomlindent-width 2、line-length 100启用了Dpydocstyle、PL、UP、PERF等规则组并对test/、system/lib/update_*.py等路径做了按文件忽略。静态类型检查Emscripten 开始逐步引入 Python 3 类型标注语法并用mypy做静态检查。mypy 的配置位于 pyproject.toml 的[tool.mypy]段mypy_path指向third_party/含 ply 等 vendored 依赖并对tools.webidl_binder、tools.toolchain_profiler等存量模块设置ignore_errors true过渡。文档说明最终目标是能带着--disallow-untyped-defs运行 mypy 检查所有类型目前正增量推进。五、Release Processes版本发布流程5.1 Minor 版本更新1.X.Y → 1.X.Y1何时更新When此类更新会确保清空构建缓存因此应在需要时进行例如 libc 或 libc 发生了变更emsdk 的预编译版本以版本号区分因此也可以周期性地打一个版本让新的预编译 emsdk 版本可用。前置要求Requirementsemscripten-releases 的构建 CIwaterfall在目标 hash 上于所有操作系统均为绿色该 hash 是 emscripten-releases 仓库中的 git hash其中 [DEPS] 文件精确指定了所有其他仓库应使用的 revision——DEPS 为 emscripten-releases 仓库中的文件此处按原文描述不在本仓库内GitHub CI 在 emscripten 仓库main分支、且对应 DEPS 中所引用的那个 emscripten commit 上为绿色。操作步骤How选定一个满足上述要求的版本作为发布版本记其 SHA 为non-LTO-sha若同时要做 LTO 发布在 emscripten-releases 仓库创建一个 CL将non-LTO-sha处的 DEPS 拷贝为DEPS.tagged-release该 CL 合入后的 SHA 记为LTO-sha。合入后需等待数小时构建与归档耗时并确认该 commit 已在全部三个平台通过 Archive Binaries 阶段、macOS 额外通过 Archive Binaries (arm64) 阶段在 emsdk 仓库运行scripts/create_release.py该脚本位于 emsdk 仓库非本仓库LTO non-LTO 双发布时./scripts/create_release.py LTO-sha non-LTO-sha使LTO-sha指向正式版本名如3.1.7non-LTO-sha指向 asserts 构建发布如3.1.7-asserts仅 non-LTO 发布时./scripts/create_release.py non-LTO-sha直接指向版本名发布无 asserts 版本不带参数运行则自动从 emscripten-releases 挑选一个 tot 版本。 该脚本会更新 emsdk 的emscripten-releases-tags.json添加新版本并创建新本地 git 分支推送到originemsdk 仓库的该次更新合入 main 后用新版本号为其打 tagemscripten 仓库同样打 tag位置是 DEPS或 DEPS.tagged-release文件所引用的那个 commit在 emscripten 仓库运行tools/maint/create_release.py更新 emscripten-version.txt 与 ChangeLog.md。从源码看tools/maint/create_release.py 精确实现了文档描述update_version_txt()在emscripten-version.txt中替换版本号update_changelog()定位{release_version} (in development)标记插入带日期的新条目并把开发中标记滚动到新版本create_release_pr()创建version_X.Y.Z分支、提交 Mark X.Y.Z as released非 dry-run 时推送并用gh pr create指定 release-reviewers 评审组。脚本还要求工作区干净git status -uno --porcelain非空即报错退出支持-n/--dry-run与--release-commit参数并可调用 tools/maint/gen_release_notes.py 生成草稿 Release 的说明文件。5.2 Major 版本更新1.X.Y → 1.(X1).0何时有合理把握系统已趋稳定时。前置要求包含全部 Minor 更新的要求另加近期没有重大变更合入近期没有重大回归regression被报告发布人本地所有测试通过包括主测试套件不给runner.py传任何参数、other、browser、sockets、sanity、binaryen*并非所有 bot 都会跑全部这些近期刚打过 Minor 版本 tag该版本上没有重大 bug 报告且此后没有重大变更合入。因为 bug 常常只在 tag 版本上被发现所以一个大特性必须先经历 Minor 版本才能进入 Major 版本。操作与 Minor 更新流程完全相同按上述 6 步执行。六、更新 emscripten.org 官网官网源码维护在 site/source 目录用 reStructuredText 编写用 Sphinx 构建构建入口为 site/Makefile 与 site/conf.py站点托管在独立的 emscripten-site 仓库的gh-pages分支main分支上有一个 CI 作业只要生成的站点内容有变化就会自动更新gh-pages分支因此一般无需手动 checkout emscripten-site 仓库确需手动更新时运行 tools/maint/update_website.py若 emscripten-site 与 emscripten 检出在相邻位置则不带参数运行否则传入检出位置。该脚本内部会检查两个仓库均干净、拉取 site 仓库的gh-pages、执行make install EMSCRIPTEN_SITEsite_out若有变更则创建update分支并提交提交信息中附上 emscripten 仓库的 git revision需要安装特定版本的 Sphinx可运行pip3 install -r requirements-dev.txt见 requirements-dev.txt视系统情况可能还需将~/.local/bin加入 PATH。本地构建与预览网站按上文安装 Python 依赖pip3 install -r requirements-dev.txt运行make -C site html在输出目录启动本地 web 服务器例如python3 -m http.server 8000 -d site/build/html浏览器访问http://localhost:8000/假设使用 8000 端口。七、更新 emcc.py 的帮助文本emcc --help的输出不是手写的而是从 site/ 下的主文档emcc.rst渲染而来——与网站上展示的内容相同只是渲染为纯文本。在 PR 中更新emcc.rst之后进入 emscripten 检出中的site目录运行make clean不执行的话可能得不到正确的输出运行make text将产物build/text/docs/tools_reference/emcc.txt拷贝为../docs/emcc.txt两条路径均相对于第 1 步进入的site/目录并把该变更加入 PR。该产物即仓库根部的 docs/emcc.txt与 emcc.py 入口配套。Sphinx 安装方式同第六节所述。八、更新 LLVM 系统库Emscripten 在 system/lib 下维护 compiler-rt、libcxx、libcxxabi、libunwind 四个库的移植版对应 system/lib/compiler-rt、system/lib/libcxx、system/lib/libcxxabi、system/lib/libunwind并周期性跟随 LLVM 新发布版更新。维护方在 llvm-project 上保持一个 fork为每个 LLVM 大版本建立一条分支例如 LLVM 16 对应emscripten-libs-16分支大版本更新建新分支小版本更新复用已有分支。更新到更新的 LLVM 版本的完整步骤同步现有分支在 LLVM fork 目录中检出目标库分支运行./system/lib/push_llvm_changes.py Emscriptens LLVM fork directory即执行 system/lib/push_llvm_changes.py确保该分支与当前 emscripten 代码库保持同步避免更新过程中丢失 emscripten 专属改动。若是创建新分支则先确保旧分支已用该脚本更新到位再创建新分支并把旧分支上所有 emscripten 专属改动 cherry-pick 过来解决可能的冲突。合入上游 tag在 fork 的库分支上创建 PR把上游 LLVM 的发布 tag 合并进来。例如把llvmorg-16.0.6合入emscripten-libs-16git co emscripten-libs-16 git remote add upstream gitgithub.com:llvm/llvm-project.git git fetch --tags upstream git merge llvmorg-16.0.6拉回 Emscripten 仓库使用下列更新脚本均位于 system/lib把 fork 分支的内容拷入 emscripten 树system/lib/update_compiler_rt.pysystem/lib/update_libcxx.pysystem/lib/update_libcxxabi.pysystem/lib/update_libunwind.py用法示例fork 目录中须已检出目标库分支./system/lib/update_compiler_rt.py Emscriptens LLVM fork directory文档特别提醒两种场景下都必须先运行push_llvm_changes.py确保 emscripten 的改动不会在拷贝过程中丢失。九、更新 muslEmscripten 在 system/lib/libc 下维护自己的 musl 移植目录内含 musl 源码树并维护一个 musl 的 fork 用于更新。流程与 LLVM 库更新同构更新已有分支时先运行 system/lib/push_musl_changes.py 使分支与当前 emscripten 代码库同步创建新分支时同样先确保旧分支同步再新建分支并 cherry-pick 旧分支上所有 emscripten 专属改动在 musl fork 分支上创建 PR 合入上游发布 tag。例如把v1.2.4合入merge-v1.2.4分支git co merge-v1.2.4 git remote add upstream git://git.musl-libc.org/musl git fetch --tags upstream git merge v1.2.4用 system/lib/update_musl.py 把 fork 分支的变更连同新版本拉回 Emscripten 仓库。十、弃用设置项与特性Deprecating settings and featuresEmscripten 拥有大量设置项与特性使组合式测试在实践中不可行。为管理复杂度、削减技术债项目持续弃用并移除不再被使用的设置与特性并设计了如下流程——其核心目的之一是与用户社区互动、评估移除某特性的影响面流程中任何阶段都可以集体决定放弃或推迟弃用为该设置或特性创建一个Intent to deprecate类型的 bug向 emscripten-discuss 邮件列表发送题为[PSA] Intent to deprecate XXX的消息XXX即被弃用的设置/特性名并附上第 1 步的 bug 链接若可行修改 emscripten 使该特性被使用时产生deprecated警告。对设置项而言通常只需把它加入 tools/settings.py 中的DEPRECATED_SETTINGS对公共 GitHub 仓库做全局代码搜索调查该特性的实际使用情况在大公司内部代码库工作的人员也应在内部做同样的全局搜索汇总第 2、3、4 步的反馈到该 bug 中围绕弃用影响展开讨论**至少经过 4 个 emscripten 发布或 2 个月取较短者**后方可做出最终弃用决定决定权在 Emscripten 维护者若决定推进则可以移除该特性若决定不推进则移除弃用警告。特性移除后应尽可能让代码仍能检测到旧特性并给用户一条可操作actionable的提示信息同时在 ChangeLog.md 中记录一条变更。从源码看该流程的第 3 步正是当前实现tools/settings.py 定义了DEPRECATED_SETTINGS字典如USE_PTHREADS→ prefer the standard -pthread flag、MEMORY64→ prefer the standard -m64 or --targetwasm64 flags 等每个条目附带迁移原因/建议并注释说明deprecated 设置仍可在命令行与代码库中使用待用户停止使用后可移入LEGACY_SETTINGS。而警告的触发点在 tools/link.py 的check_settings()当某个废弃设置出现在user_settings中时通过diagnostics.warning(deprecated, ...)输出X is deprecated (reason). Please open a bug if you have a continuing need for this setting对WASM0/WASM2这类带值的设置还单独做了等值匹配。十一、关键文件速查环节仓库内关键文件流程总纲docs/process.md测试层test/test_core.py、test/test_other.py、test/runner.py代码风格.clang-format、pyproject.toml版本发布tools/maint/create_release.py、tools/maint/gen_release_notes.py、emscripten-version.txt、ChangeLog.md官网构建site/Makefile、site/conf.py、tools/maint/update_website.py、requirements-dev.txtemcc 帮助文本docs/emcc.txt、emcc.pyLLVM 库同步system/lib/push_llvm_changes.py、system/lib/update_compiler_rt.py、system/lib/update_libcxx.py、system/lib/update_libcxxabi.py、system/lib/update_libunwind.pymusl 同步system/lib/push_musl_changes.py、system/lib/update_musl.py弃用机制tools/settings.py、tools/link.py需要说明的适用前提本文所述发布流程依赖 emscripten-releases、emsdk、llvm-project fork、musl fork 等仓库之外的配套仓库DEPS 文件、DEPS.tagged-release、waterfall CI 等均位于那些仓库中本仓库仅包含与之对接的脚本官网自动同步依赖main分支的 CI 作业。文中所有脚本路径、命令与文件位置均以当前仓库快照为准。【免费下载链接】emscriptenEmscripten: An LLVM-to-WebAssembly Compiler项目地址: https://gitcode.com/gh_mirrors/em/emscripten创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →