首页
/ Homebrew core 公式准入标准:Acceptable Formulae 文档全解与源码级依据

Homebrew core 公式准入标准:Acceptable Formulae 文档全解与源码级依据

2026-09-05 09:43:21作者:虞亚竹Luna

本文以 Homebrew 官方仓库中的 Acceptable-Formulae.md 为核心,系统拆解 homebrew/core 对 Formula 的全部硬性准入要求——从 CI 平台矩阵、keg_only :provided_by_macos、稳定版本来源、SHA-256 校验,到 *-full 变体、编译器支持与 vendored 依赖边界;并结合仓库源码(如 KegOnlyReasonChecksum)逐条印证每条要求的实现机制,帮助贡献者在提交 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 当前持续集成矩阵支持的 macOSLinux 配置上成功构建并通过测试。只有当上游本身不支持某平台、且剩余平台上的维护确实有用且可持续时,才可声明显式的平台限制。

这里的"CI 矩阵"直接对应 Homebrew 官方 CI 基础设施。从源码结构看,仓库内 github_runner_matrix.rb 定义了 CI 矩阵的操作系统与 Runner 规格,macos_runner_spec.rblinux_runner_spec.rb 分别描述 macOS 与 Linux 两种 Runner 的具体配置——即"必须构建通过的配置"在工程上就是这些 Runner 规格所覆盖的组合。

实践要点:

  • 提交新 Formula 前,应在本地以 brew stylebrew audit --newbrew 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

两个关键细节值得注意:

  1. provided_by_macosshadowed_by_macos 的区别:前者表示"macOS 已提供完全相同的软件",后者表示"macOS 提供同类但不同的软件"。二者都被 by_macos? 归并为 macOS 相关原因;
  2. 跨平台适用性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.rbkeg_only?(约 L1730)与 keg_only(reason, explanation = "")(约 L4814)的 DSL 定义支撑。

Fork 的准入

文档区分了两种 fork 情形:

  1. 替换现有项目的 fork:必须满足 Package-Acceptance-Policy.md 的共享标准——要么原作者公开指定该 fork 为官方后继,要么至少两个其他主流发行版已将该 fork 用作替代品;
  2. 独立命名的 fork:当其名称能清晰区分于原始项目、且满足全部其他 Formula 要求时,可以被接受。

这与共享政策中"fork 不构成后继时,可以不同名提交、只要用户不会与原项目混淆"的条款(Package-Acceptance-Policy.md)一脉相承。

自更新软件的冲突

文档指出:会自我更新的软件与 Homebrew 的版本管理和升级机制相冲突。处理原则是:

  • 若可以不打脆弱或侵入性补丁的方式关闭自更新,必须关闭
  • 若上游的分发模式本身依赖自更新,该软件更适合做成 cask(GUI/桌面软件走 Acceptable-Casks.md 通道),而不是 core formula。

原因很直接:Homebrew 通过 brew upgrade 基于公式声明的版本号管理升级;自更新会在用户不知情的情况下改变二进制内容,使 brew list --versions 与磁盘实际内容脱节,破坏整条依赖链的版本假设。

版本化且可验证的来源:SHA-256 是硬门槛

这是文档中最具工程约束力的一节,包含三条规则:

  1. 安装步骤不得从移动的默认分支或无版本、无校验和的归档拉取代码
  2. 来源必须使用不可变的发布归档、tag 或 revision,且下载归档必须用 SHA-256 校验
  3. 依赖解析必须可复现:按生态使用 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 变体

文档对默认构建的依赖范围给出了三段式裁决:

  1. 默认公式应携带:构建与测试所需依赖、满足其他 core 公式的依赖、以及用户合理期望的功能;避免"仅为少数用户的可选上游特性"而引入庞大的依赖树;
  2. *-full 公式是罕见逃生舱:仅当软件同时需要"实用默认构建"与"最大功能构建"时使用。其他 core 公式必须依赖默认公式而非 *-full 变体;成对公式在可行时应能共存,必要时用 keg_only 隔离;
  3. 不适合 core 的其他依赖取舍方案(如极简构建、激进裁剪)应放到第三方 tap

注意 Versions.md 开篇对两者的区分:"foo-full 不是版本化公式,它是用于……的独立公式"——即 @N-full 是两套独立的准入体系,前者受 ABI 稳定约束,后者受"默认公式优先被依赖"约束。

编译器支持

文档要求:软件必须能在受支持 macOS 版本上使用当前稳定版 Apple Clang 构建,除非公式声明并论证了其他受支持编译器。"需要过时的编译器通常表明上游已未维护 macOS 支持"。

从源码结构看,仓库专门有 compilers.rbdownload_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.mdPackage-Acceptance-Policy.md,一条新 Formula 的准入可以归纳为两级判定链:

层级 检查项 关键证据/机制
共享政策 公开存在、活跃度、知名度门槛、30 天仓库年龄 Package-Acceptance-Policy.md
平台 在 macOS/Linux CI 矩阵构建并测试通过 Linux-CI.mdgithub_runner_matrix.rb
产物形态 .app 主体、非专有二进制、非自更新 本文"原生 macOS 应用"与"自更新"小节
来源 不可变 tag/归档 + SHA-256、可复现依赖 checksum.rbChecksum-Requirements.md
许可 DFSG 兼容开源、可源码构建、不依赖 cask 本文"源码可得性与许可证"小节
版本 上游标识的稳定版 + 不可变 release Versions.mdBottles.md
依赖组织 默认公式优先、*-full 受控、vendoring 需可见且随版更新 本文"依赖与 *-full 变体"小节
构建环境 当前稳定 Apple Clang、共享库优先、安装可自动化 compilers/keg.rb

满足全部条件仍不保证被接受(共享政策明确"满足文档标准不保证接受"),但任何一条不满足都是审查中被拒绝或要求修改的高频原因。贡献者在提交前对照本文表格逐条自查,可显著减少 PR 往返次数。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395