Homebrew core 公式准入标准:Acceptable Formulae 文档全解与源码级依据
本文以 Homebrew 官方仓库中的 Acceptable-Formulae.md 为核心,系统拆解 homebrew/core 对 Formula 的全部硬性准入要求——从 CI 平台矩阵、keg_only :provided_by_macos、稳定版本来源、SHA-256 校验,到 *-full 变体、编译器支持与 vendored 依赖边界;并结合仓库源码(如 KegOnlyReason、Checksum)逐条印证每条要求的实现机制,帮助贡献者在提交 Formula 前准确预判可接受性与常见拒绝原因。
适用范围:Formula 专属要求与共享政策的分工
Acceptable-Formulae.md 开篇即声明其定位:本页只包含 homebrew/core 的公式专属(formula-specific)要求;而 Formula 与 Cask 共同遵守的准入条件(知名度、维护状态、成人内容、项目风险等)定义在 Package-Acceptance-Policy.md 中,同样适用于本文件。
两者分工清晰:
- Package-Acceptance-Policy.md 覆盖共享政策:软件须有独立于 Homebrew 的公开存在与主页、上游活跃维护且无已知未修复漏洞、满足 GitHub 上的关注度门槛(如至少 30 forks / 30 watchers / 75 stars,仓库所有者自荐则需 90/90/225)、仓库创建需满 30 天等;
- Acceptable-Formulae.md 覆盖core 仓库专属:平台构建、版本来源、许可证、依赖组织等工程化标准。
此外,Package-Acceptance-Policy.md 明确了兜底路径:不满足官方标准的软件通常可以在第三方 tap 中维护,第三方 tap 分发不代表 Homebrew 的背书。
支持平台:必须通过 homebrew/core 的 CI 矩阵
原文要求:Formula 必须在 homebrew/core 当前持续集成矩阵支持的 macOS 与 Linux 配置上成功构建并通过测试。只有当上游本身不支持某平台、且剩余平台上的维护确实有用且可持续时,才可声明显式的平台限制。
这里的"CI 矩阵"直接对应 Homebrew 官方 CI 基础设施。从源码结构看,仓库内 github_runner_matrix.rb 定义了 CI 矩阵的操作系统与 Runner 规格,macos_runner_spec.rb 与 linux_runner_spec.rb 分别描述 macOS 与 Linux 两种 Runner 的具体配置——即"必须构建通过的配置"在工程上就是这些 Runner 规格所覆盖的组合。
实践要点:
- 提交新 Formula 前,应在本地以
brew style、brew audit --new、brew test-bot(实现位于 test_bot.rb)预检; - 若上游明确不支持某平台(如依赖特定硬件或闭源库),应使用
depends_on macos: .../depends_on :linux之类的显式限制,而不是让 CI 构建失败; - "剩余支持有用且可维护"是关键措辞——仅仅"上游还没修"并不构成豁免理由。
macOS 自带软件的准入:keg_only :provided_by_macos
原文规定:与 macOS 自带工具或库重复的软件,在使用 keg_only :provided_by_macos 且满足其他准入条件时可以被接受。
这条要求在源码中有完整的类型化实现。Library/Homebrew/keg_only_reason.rb 中的 KegOnlyReason 类将 keg_only 的原因建模为一组带语义判断的常量:
class KegOnlyReason
# ...
def versioned_formula?
@reason == :versioned_formula
end
def provided_by_macos?
@reason == :provided_by_macos
end
def shadowed_by_macos?
@reason == :shadowed_by_macos
end
def by_macos?
provided_by_macos? || shadowed_by_macos?
end
end
两个关键细节值得注意:
provided_by_macos与shadowed_by_macos的区别:前者表示"macOS 已提供完全相同的软件",后者表示"macOS 提供同类但不同的软件"。二者都被by_macos?归并为 macOS 相关原因;- 跨平台适用性:
applicable?方法(keg_only_reason.rb)返回!by_macos?,即 macOS 相关的 keg_only 原因在其他操作系统上不适用——这与文档"支持平台"一节中允许显式平台限制的逻辑互为呼应。
to_s 方法为 provided_by_macos 给出的默认解释是:"macOS 已提供此软件,并行安装另一个版本可能引发各种麻烦"(keg_only_reason.rb),正是文档要求使用 keg_only 而非 keg-only-unlink 式链接的原因:防止与系统自带版本发生符号链接冲突。
带版本号公式(Versioned Formulae)
文档要求:foo@3 这类带版本号的 Formula 只有在满足 Versions.md 的版本化要求时才被接受。该文档明确了若干可验证的硬性标准:
- 版本化公式应与当前稳定版相差主版本/次版本(而非补丁版本),以确保用户仍能获得安全更新;
- 应共享同一代码库;若上游拆分为独立仓库,应建立独立新公式(
formula2而非formula@2); - 若无法与非版本化版本同时 linkable,须使用
keg_only :versioned_formula(这正是 KegOnlyReason#versioned_formula? 判断的来源); - 版本化公式在其分支生命周期内必须 ABI 稳定,依赖者不应因版本更新而被迫
revision重编。
对应到安装行为:版本化公式默认不会被 link 到 HOMEBREW_PREFIX,用户通过 brew link foo@3 显式启用——这一行为由 formula.rb 中 keg_only?(约 L1730)与 keg_only(reason, explanation = "")(约 L4814)的 DSL 定义支撑。
Fork 的准入
文档区分了两种 fork 情形:
- 替换现有项目的 fork:必须满足 Package-Acceptance-Policy.md 的共享标准——要么原作者公开指定该 fork 为官方后继,要么至少两个其他主流发行版已将该 fork 用作替代品;
- 独立命名的 fork:当其名称能清晰区分于原始项目、且满足全部其他 Formula 要求时,可以被接受。
这与共享政策中"fork 不构成后继时,可以不同名提交、只要用户不会与原项目混淆"的条款(Package-Acceptance-Policy.md)一脉相承。
自更新软件的冲突
文档指出:会自我更新的软件与 Homebrew 的版本管理和升级机制相冲突。处理原则是:
- 若可以不打脆弱或侵入性补丁的方式关闭自更新,必须关闭;
- 若上游的分发模式本身依赖自更新,该软件更适合做成 cask(GUI/桌面软件走 Acceptable-Casks.md 通道),而不是 core formula。
原因很直接:Homebrew 通过 brew upgrade 基于公式声明的版本号管理升级;自更新会在用户不知情的情况下改变二进制内容,使 brew list --versions 与磁盘实际内容脱节,破坏整条依赖链的版本假设。
版本化且可验证的来源:SHA-256 是硬门槛
这是文档中最具工程约束力的一节,包含三条规则:
- 安装步骤不得从移动的默认分支或无版本、无校验和的归档拉取代码;
- 来源必须使用不可变的发布归档、tag 或 revision,且下载归档必须用 SHA-256 校验;
- 依赖解析必须可复现:按生态使用 Language-Specific Formulae 文档记录的依赖机制。部分语言包管理器可以在构建期安装"带版本、已锁定"的依赖集;而 Python 公式应声明带校验和的
resource块并在解析关闭的状态下安装。安装步骤不得解析一个"移动中"或不可复现的依赖集。
第 2 条在仓库中有双重实现证据:
- Library/Homebrew/checksum.rb 定义了
Checksum类,只持有hexdigest(十六进制摘要),并统一downcase处理、支持与其他Checksum或字符串比较——即公式 DSL 中sha256 "..."的底层数据结构; - Checksum-Requirements.md 进一步规定:必须使用
url所指向确切文件的 SHA-256 摘要,不得从不信任镜像复制校验和、不得为绕过不匹配而禁用验证;并说明 core 公式的 MD5 校验已于 2012 年移除、2015 年禁止 MD5 校验公式——"SHA-256 唯一合法"已是长期演进的结果。
第 3 条的动机是可复现性:brew install 必须可以在任意时间、任意机器上重建出同一份软件。若安装步骤依赖 master 分支或 pip install 动态解析最新版,构建产物将随时间漂移,这正是 Reproducible-Builds.md 所反对的。
源码可得性与许可证
文档给出四条并列硬要求:
- core 公式必须是开源的,且许可证与 Debian 自由软件指南(DFSG)兼容;
- 必须能从源码构建,或安装"可移植、平台无关"的产物(如 Java 字节码);
- 专有或平台绑定的纯二进制软件属于 cask 的范畴;
- core 公式不得依赖 cask、专有软件,或任何会自动安装上述两者的运行时步骤。
这四条共同划定了 formula 与 cask 的边界:formula 是"可审计、可重建、可链接"的软件包,cask 是"上游如何分发就如何安装"的桌面应用包。依赖方向是单向的——cask 可以依赖 formula,formula 不能反过来依赖 cask,否则会破坏"formula 可复现构建"的根本承诺。
稳定发布(Stable Releases)
文档规定:
- 上游必须将所打包的版本标识为稳定版,并提供不可变的 tag 或 release;
- 优先使用发布归档而非 Git checkout,且当上游提供时归档文件名应包含版本号;
- 新公式必须在支持平台上无需下游补丁即可构建;
- 没有稳定发布的软件"难以复现、难以制作 bottle、难以支持",不符合 homebrew/core 准入。
其中"bottle"是 Homebrew 预构建二进制包机制(参见 Bottles.md)。归档优先于 Git checkout 的原因在于:归档配合 SHA-256 即可唯一钉死构建输入,而 Git checkout 还涉及历史对象完整性、.git 元数据等额外变量;文件名含版本号(如 redis-7.2.4.tar.gz)则便于自动化工具(如 bump.rb 所支持的自动版本更新)解析版本。
原生 macOS 应用与可选图形界面
文档明确:
- 主要产物是原生
.app的公式不被接受;上游发布的应用包应进入 cask 仓库; - 当上游可以同时构建 CLI/库组件和可选 GUI 时,CLI/库组件应保持为公式的主要目的;
- 被广泛使用的原生 GUI 可以包含,前提是不带来不成比例的依赖成本;
- X11/XQuartz 界面不应默认启用,因为它在 macOS 上体验不佳。
这解释了为何 core 中大量带 GUI 的库(如各类 Qt 生态工具)默认只构建库与 CLI 部分,而 GUI 由构建选项或 cask 侧承担。
依赖与 *-full 变体
文档对默认构建的依赖范围给出了三段式裁决:
- 默认公式应携带:构建与测试所需依赖、满足其他 core 公式的依赖、以及用户合理期望的功能;避免"仅为少数用户的可选上游特性"而引入庞大的依赖树;
*-full公式是罕见逃生舱:仅当软件同时需要"实用默认构建"与"最大功能构建"时使用。其他 core 公式必须依赖默认公式而非*-full变体;成对公式在可行时应能共存,必要时用keg_only隔离;- 不适合 core 的其他依赖取舍方案(如极简构建、激进裁剪)应放到第三方 tap。
注意 Versions.md 开篇对两者的区分:"foo-full 不是版本化公式,它是用于……的独立公式"——即 @N 与 -full 是两套独立的准入体系,前者受 ABI 稳定约束,后者受"默认公式优先被依赖"约束。
编译器支持
文档要求:软件必须能在受支持 macOS 版本上使用当前稳定版 Apple Clang 构建,除非公式声明并论证了其他受支持编译器。"需要过时的编译器通常表明上游已未维护 macOS 支持"。
从源码结构看,仓库专门有 compilers.rb 与 download_strategy/ 之外的 compilers/ 目录(含 compiler_selector.rb)负责构建时的编译器选择逻辑;brew test-bot 在 CI 中默认使用系统 Apple Clang 路径验证构建,因此这条要求实际上由 CI 自动执行——用旧版 Clang 才能编译的公式会直接构建失败。
安装行为的可自动化性
文档要求:公式必须充分自动化依赖解析与安装,以使其作为软件包有用;需要大量手动预安装/后安装步骤的软件不适合 core,除非这些步骤能被做成可靠且安全的。
判断基准是 brew install <formula> 一条命令闭环。若软件需要用户在安装前手动编译某个私有依赖、或安装后手动配置环境变量/证书才能运行,它就不符合"软件包"的抽象。
共享库与静态库的取舍
文档给出三条规则:
- 上游可同时提供共享库或静态库时,优先共享库;
- 静态库有明确用途时,公式可以同时安装两者;
- 纯静态库在存在依赖它的公式时不合适,因为每次更新后所有依赖者都必须重新构建。
这条规则直接关联 Homebrew 的 keg 链接机制(参见 keg.rb):动态库通过符号链接在 lib 下解析,更新版本后依赖者无需重编;而静态库在链接期复制进可执行文件,上游库一升级,依赖它的每个公式都必须 revision bump 重编,维护成本随依赖图放大。
Vendored 依赖的边界
文档最后一条要求区分两种情形:
- 默认禁止不必要的 vendoring:当存在受维护的 Homebrew 公式可以提供同一依赖时,不应把另一个项目打包进源码树。"不必要的 vendoring 使安全更新更难,并可能遗留多份过时副本被同时安装";
- 例外可接受:当上游受支持的构建方式无法使用系统依赖,或取消捆绑会使公式不可靠时,vendored 依赖可以被接受——但该例外必须可见(在公式中声明),且 vendored 组件必须随每次上游发布一起更新。
"随发布更新"是关键:vendored 代码若长期不更新,安全补丁(如 OpenSSL 类 CVE)将在该公式的树内持续潜伏,这正是文档强调"安全更新更难"的原因。
总结:一条 Formula 能否进入 homebrew/core 的判定链
综合 Acceptable-Formulae.md 与 Package-Acceptance-Policy.md,一条新 Formula 的准入可以归纳为两级判定链:
| 层级 | 检查项 | 关键证据/机制 |
|---|---|---|
| 共享政策 | 公开存在、活跃度、知名度门槛、30 天仓库年龄 | Package-Acceptance-Policy.md |
| 平台 | 在 macOS/Linux CI 矩阵构建并测试通过 | Linux-CI.md、github_runner_matrix.rb |
| 产物形态 | 非 .app 主体、非专有二进制、非自更新 |
本文"原生 macOS 应用"与"自更新"小节 |
| 来源 | 不可变 tag/归档 + SHA-256、可复现依赖 | checksum.rb、Checksum-Requirements.md |
| 许可 | DFSG 兼容开源、可源码构建、不依赖 cask | 本文"源码可得性与许可证"小节 |
| 版本 | 上游标识的稳定版 + 不可变 release | Versions.md、Bottles.md |
| 依赖组织 | 默认公式优先、*-full 受控、vendoring 需可见且随版更新 |
本文"依赖与 *-full 变体"小节 |
| 构建环境 | 当前稳定 Apple Clang、共享库优先、安装可自动化 | compilers/、keg.rb |
满足全部条件仍不保证被接受(共享政策明确"满足文档标准不保证接受"),但任何一条不满足都是审查中被拒绝或要求修改的高频原因。贡献者在提交前对照本文表格逐条自查,可显著减少 PR 往返次数。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00