配方是用 Ruby 编写的软件包定义。可以使用 brew create <URL>
创建配方,其中 <URL>
是 zip 或 tarball,可以使用 brew install <formula>
安装配方,可以使用 brew install --debug --verbose <formula>
调试配方。配方使用 配方 API,该 API 提供各种 Homebrew 特定的帮助程序。
术语 | 描述 | 示例 |
---|---|---|
公式 | 从上游源构建的 Homebrew 包定义 | /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/f/foo.rb |
cask | 安装 macOS 原生应用程序的 Homebrew 包定义 | /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask/Casks/b/bar.rb |
前缀 | 安装 Homebrew 的路径 | /usr/local |
keg | 给定公式版本的目标安装目录 | /usr/local/Cellar/foo/0.1 |
rack | 包含一个或多个版本化keg 的目录 | /usr/local/Cellar/foo |
keg-only | 如果公式未符号链接到 Homebrew 的前缀,则该公式为keg-only | openjdk 公式 |
opt 前缀 | 指向keg 活动版本的符号链接 | /usr/local/opt/foo |
Cellar | 包含一个或多个命名rack 的目录 | /usr/local/Cellar |
Caskroom | 包含一个或多个命名cask 的目录 | /usr/local/Caskroom |
外部命令 | 在 Homebrew/brew GitHub 存储库外部定义的 brew 子命令 |
brew 别名 |
tap | 公式、cask 和/或外部命令 的目录(通常为 Git 存储库) | /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core |
bottle | 预构建的keg,倒入Cellar 的rack 中,而不是从上游源构建 | qt--6.5.1.ventura.bottle.tar.gz |
tab | 有关keg 的信息,例如它是从bottle 中倒入还是从源代码构建 | /usr/local/Cellar/foo/0.1/INSTALL_RECEIPT.json |
Brew Bundle | Homebrew 的扩展,用于描述依赖项 | brew 'myservice', restart_service: true |
Brew Services | Homebrew 的扩展,用于管理服务 | brew services start myservice |
Homebrew 使用 Git 来存储公式并为项目做出贡献。
从 Homebrew 4.0.0 开始,配方以 JSON 格式从 https://formulae.brew.sh.cn 下载,后者由 Homebrew/formulae.brew.sh 的计划任务从 Homebrew/homebrew-core 存储库的 master
分支自动重新生成。
Homebrew 将配方安装到 $(brew --cellar)
中的酒窖,然后将部分安装符号链接到 $(brew --prefix)
(例如 /opt/homebrew
)中的前缀,以便其他程序可以看到正在发生的事情。我们建议对酒窖中的几个木桶运行 brew ls
,以了解其如何排列。
软件包根据其配方进行安装。阅读一个简单的配方,例如 brew edit etl
(或 etl.rb)或更高级的配方,例如 brew edit git
(或 git.rb)。
在开始之前,请确保运行 brew update
。这可确保你的 Homebrew 安装是一个 Git 存储库。
要在本地创建或编辑配方,你需要先 轻触 homebrew/core
(如果你之前没有轻触过)。这会将 Homebrew/homebrew-core Git 存储库克隆到 $(brew --repository homebrew/core)
。在开发过程中,你还需要在 shell 环境中或在任何 install
、reinstall
或 upgrade
命令之前设置 HOMEBREW_NO_INSTALL_FROM_API=1
,以强制 brew
使用本地存储库,而不是 API。
在提交新配方之前,请确保你的软件包
brew search <formula>
)brew audit --new --formula <formula>
测试在提交新配方之前,请务必阅读我们的 贡献指南。
使用指向源 tarball 的 URL 运行 brew create
brew create https://example.com/foo-0.1.tar.gz
这将创建 $(brew --repository)/Library/Taps/homebrew/homebrew-core/Formula/f/foo.rb
并使用 EDITOR
在其中打开它。
传入 --ruby
或 --python
将填充各种默认值,这些默认值通常对用这些语言编写的项目有用。
如果 brew
在执行 create
步骤时显示 警告:无法从 URL 确定版本
,则需要将正确的 version
显式添加到配方中,然后保存配方。
Homebrew 将尝试从其 URL 中猜测配方的名称。如果它未能这样做,则可以使用 brew create <URL> --set-name <name>
覆盖它。
homepage
我们不接受没有 homepage
的配方!
如果可用,则首选 SSL/TLS (https) homepage
。
尝试从 homepage
中总结配方在 desc
ription 中的作用。请注意,打印时 desc
ription 会自动添加配方名称作为前缀。
license
我们不接受没有 license
的新配方进入 Homebrew/homebrew-core!
我们只接受使用 Debian 自由软件指南许可证 的配方,或根据 公共领域软件的 DFSG 指南 发布到公共领域的配方。
使用 SPDX 许可证列表 中的许可证标识符,例如 license "BSD-2-Clause"
,或对公共领域软件使用 license :public_domain
。
使用 :any_of
、:all_of
或 :with
来描述复杂的许可证表达式。当用户可以选择使用哪个许可证时,应使用 :any_of
。当用户必须使用所有许可证时,应使用 :all_of
。应使用 :with
来指定有效的 SPDX 例外。在标识符中添加 +
以指示该配方可以在同一许可证的更高版本下获得许可。
查看 许可证指南,了解 Homebrew 配方中复杂许可证表达式的示例。
HOMEBREW_NO_INSTALL_FROM_API=1 brew install --interactive foo
您现在处于一个新提示符,其中 tarball 已解压到一个临时沙盒中。
检查软件包的 README
。软件包是否使用 ./configure
、cmake
或其他方式进行安装?如果软件包使用 ./configure
,请删除已注释掉的 cmake
行。
该 README
可能告诉您有关依赖项的信息,而 Homebrew 或 macOS 可能已经拥有这些依赖项。您可以使用 brew search
检查 Homebrew 依赖项。macOS 附带的一些常见依赖项
libexpat
libGL
libiconv
libpcap
libxml2
python
ruby
还有很多其他依赖项;请检查 /usr/lib
以查找它们。
我们通常尝试不在核心 Homebrew 中复制系统库和复杂的工具,但我们确实会复制一些常用的工具。
OpenSSL 和 LibreSSL 是特殊例外。使用其中任何一项的项目应该使用 Homebrew 附带的等效项进行构建,并且我们的 BrewTestBot 的安装后 audit
将在检测到您尚未执行此操作时发出警告。
重要提示:在公式安装期间,$(brew --prefix)/bin
不在 PATH
中。如果您在构建时有依赖项,则必须指定它们,brew
将它们添加到 PATH
中或创建一个 Requirement
。
class Foo < Formula
# ...
depends_on "httpd" => [:build, :test]
depends_on xcode: ["9.3", :build]
depends_on arch: :x86_64
depends_on "jpeg"
depends_on macos: :high_sierra
depends_on "pkg-config"
depends_on "readline" => :recommended
depends_on "gtk+" => :optional
# ...
end
一个 String
(例如 "jpeg"
)指定一个公式依赖项。
一个 Symbol
(例如 :xcode
)指定一个 Requirement
,以将安装限制在满足特定条件的系统中,这些条件可以通过一个或多个公式、cask 或其他系统范围安装的软件(例如 Xcode)来满足。一些 Requirement
还可以采用一个字符串或符号,指定公式所依赖的最低版本。
一个 Hash
(例如 =>
)向依赖项添加信息。给定一个字符串或符号,该值可以是以下一个或多个值
:build
表示这是一个仅在构建时的依赖项,因此在从 bottle 安装或使用 brew missing
列出缺失的依赖项时可以跳过它。:test
表示仅在运行 brew test
时需要此依赖项。:optional
(在 Homebrew/homebrew-core
中不允许)为公式生成一个隐式的 with-foo
选项。这意味着,给定 depends_on "foo" => :optional
,用户必须传递 --with-foo
才能使用该依赖项。:recommended
(在 Homebrew/homebrew-core
中不允许)生成一个隐式 without-foo
选项,这意味着该依赖项默认启用,用户必须传递 --without-foo
来禁用该依赖项。可以使用 option
语法覆盖默认描述(在这种情况下,option
声明 必须在依赖项之前)
option "with-foo", "Compile with foo bindings" # This overrides the generated description if you want to
depends_on "foo" => :optional # Generated description would otherwise be "Build with foo support"
"<option-name>"
(在 Homebrew/homebrew-core
中不允许)要求使用指定选项构建依赖项。有时,公式之间存在无法避免或通过 keg_only
规避的严重冲突。
次要冲突的一个好例子是 mbedtls
公式,它会发布并编译一个“Hello World”可执行文件。这显然对 mbedtls
的功能来说不是必需的,并且由于与流行的 GNU hello
公式发生冲突会造成过度,我们只是在安装过程中将其删除。
pdftohtml
提供了一个严重冲突的示例,其中每个列出的公式都发布了一个同名二进制文件,该二进制文件对于功能至关重要,因此最好使用 conflicts_with
。
作为一般规则,conflicts_with
应该是最后的手段。它是一个相当直接的工具。
无法解决的冲突的语法是
conflicts_with "blueduck", because: "yellowduck also ships a duck binary"
在 Homebrew 中,我们有时会接受不包含版本升级的公式更新。其中包括资源更新、新补丁或修复公式中的安全问题。
有时,这些更新需要对公式本身或其依赖项强制重新编译,以确保公式继续按预期运行或关闭安全问题。这种强制重新编译称为 revision
,并插入在 homepage
/url
/sha256
块的下方。
当公式的依赖项无法针对该依赖项的新版本进行构建时,它必须收到 revision
。此类故障的一个示例见于 此问题报告 及 其修复。
revision
也用于从系统 OpenSSL 转移到 Homebrew 附带的 OpenSSL 的公式,而无需对该公式进行任何其他更改。这确保用户不会暴露于过时 OpenSSL 的潜在安全问题。有关此内容的示例,请参阅 此提交。
有时,公式具有版本方案,该方案会发生更改,从而导致两个版本之间的直接比较不再产生正确的结果。例如,某个项目可能为版本 13
,然后决定变为 1.0.0
。由于我们的版本控制系统默认将 13
转换为 13.0.0
,因此需要进行干预。
当公式的版本方案无法识别新版本为较新版本时,它必须收到 version_scheme
。有关此内容的示例,请参阅 此请求。
当您已经安装了许多公式时,很容易错过一个常见依赖项。您可以使用 otool
命令仔细检查二进制链接到的库(您可能需要使用 xcrun otool
)
$ otool -L /usr/local/bin/ldapvi
/usr/local/bin/ldapvi:
/usr/local/opt/openssl/lib/libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/lib/libglib-2.0.0.dylib (compatibility version 4201.0.0, current version 4201.0.0)
/usr/local/opt/gettext/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.2.0)
/usr/local/opt/readline/lib/libreadline.6.dylib (compatibility version 6.0.0, current version 6.3.0)
/usr/local/lib/libpopt.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
/System/Library/Frameworks/LDAP.framework/Versions/A/LDAP (compatibility version 1.0.0, current version 2.4.0)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
如果所有平台都需要公式依赖项,但可以由 macOS 附带的组件处理,请使用 uses_from_macos
指定它。在 Linux 上,它就像 depends_on
,而在 macOS 上,除非主机系统早于可选的 since:
参数,否则会忽略它。
例如,要在 Linux 上需要 bzip2
公式,同时依赖 macOS 上内置的 bzip2
uses_from_macos "bzip2"
仅在 Linux 上构建或测试时才需要 perl
公式
uses_from_macos "perl" => [:build, :test]
在 Linux 和 pre-macOS 12 上需要 curl
公式
uses_from_macos "curl", since: :monterey
Homebrew 不打包已经打包的特定于语言的库。这些库应直接从 gem
/cpan
/pip
等安装。
安装 gem 依赖项的首选机制是将 bundler
与上游的 Gemfile.lock
结合使用。这需要上游在他们的 Gemfile.lock
中进行检查,因此如果他们没有这样做,最好提交一个问题并要求他们这样做。假设他们有一个,这就像
ENV["GEM_HOME"] = libexec
system "bundle", "install", "--without", "development"
从那里,您可以构建并安装项目本身
system "gem", "build", "<project>.gemspec"
system "gem", "install", "--ignore-dependencies", "<project>-#{version}.gem"
并安装任何 bin,并使用以下命令修改它们的 shebang 行:
bin.install libexec/"bin/<bin>"
bin.env_script_all_files(libexec/"bin", GEM_HOME: ENV.fetch("GEM_HOME", nil))
对于 python,我们使用 resource
作为依赖项,并且有自动化功能为您生成这些依赖项。运行 brew update-python-resources <formula>
将自动为您的 Python 应用程序的依赖项添加必要的 resource
节。请注意,如果您传递 --python
开关,brew update-python-resources
将自动由 brew create
运行。如果 brew update-python-resources
无法确定正确的 resource
节,homebrew-pypi-poet 是一个很好的第三方替代方案,可能会有所帮助。
如果其他方法都失败了,您将需要对所有其他特定于语言的依赖项使用 resource
。这要求您同时指定一个版本的特定 URL 和一个 sha256 校验和以确保安全。这是一个示例
class Foo < Formula
# ...
url "https://example.com/foo-1.0.tar.gz"
resource "pycrypto" do
url "https://files.pythonhosted.org/packages/60/db/645aa9af249f059cc3a368b118de33889219e0362141e75d4eaf6f80f163/pycrypto-2.6.1.tar.gz"
sha256 "f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c"
end
def install
resource("pycrypto").stage { system "python", *Language::Python.setup_install_args(libexec/"vendor") }
end
end
jrnl
是一个很好地完成此操作的公式示例。最终结果意味着用户不必使用 pip
或 Python,只需运行 jrnl
即可。
HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source --verbose --debug foo
--debug
如果构建失败,会要求你打开一个交互式 shell,以便你可以尝试找出出错的原因。
检查 ./configure
输出的顶部。一些配置脚本无法识别 --disable-debug
。如果你看到有关它的警告,请从公式中删除该选项。
向公式的 test do
块添加一个有效的测试。这将由 brew test foo
和 BrewTestBot 运行。
test do
块会自动创建并更改到一个临时目录,该目录会在运行后删除。你可以使用 testpath
函数访问此 Pathname
。环境变量 HOME
在 test do
块中被设置为 testpath
。
我们想要不需要任何用户输入且测试应用程序基本功能的测试。例如,foo build-foo input.foo
是一个好的测试,而(尽管它们被广泛使用)foo --version
和 foo --help
是不好的测试。但是,一个不好的测试总比没有测试好。
请参阅 cmake
公式,了解一个好的测试示例。它将一个基本的 CMakeLists.txt
文件写入测试目录,然后调用 CMake 来生成 Makefile。此测试检查 CMake 是否在基本操作期间不会出现段错误。
你可以使用 公式断言 中的 assert_equal
或 assert_match
检查输出是否符合预期,例如 envv
公式中的此示例
assert_equal "mylist=A:C; export mylist", shell_output("#{bin}/envv del mylist B").strip
您还可以检查是否已创建输出文件
assert_predicate testpath/"output.txt", :exist?
针对具体情况的一些建议
tinyxml2
测试,该测试将一个小的 C++ 源文件写入测试目录,编译并将其链接到 tinyxml2 库,最后检查生成程序是否成功运行。test_fixtures("test.svg")
。test
阶段使用 resource
块从源代码存储库中安装它,如下所示test do
resource "testdata" do
url "https://example.com/input.foo"
sha256 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
end
resource("testdata").stage do
assert_match "OK", shell_output("#{bin}/foo build-foo input.foo")
end
end
Homebrew 预期在 #{prefix}/share/man/...
中找到手册页,而不是在 #{prefix}/man/...
中找到。
有些软件安装到 man
而不是 share/man
,因此请检查输出,并在需要时将 "--mandir=#{man}"
添加到 ./configure
行。
如果 Homebrew 打包存在具体问题(与从其他来源安装软件的方式相比),则可以将 caveats
块添加到公式中以警告用户。这可以指示非标准安装路径,例如 ruby
公式中的此示例
==> Caveats
By default, binaries installed by gem will be placed into:
/usr/local/lib/ruby/gems/bin
You may want to add this to your PATH.
使用项目宣传产品的方式来命名公式。因此,它是 pkg-config
,而不是 pkgconfig
;sdl_mixer
,而不是 sdl-mixer
或 sdlmixer
。
唯一的例外是诸如“Apache Ant”之类的内容。Apache 在所有内容前面都加上了“Apache”,但我们使用公式名称 ant
。我们仅在诸如 gnuplot
(因为它是名称的一部分)和 gnu-go
(因为每个人都称其为“GNU Go”——没有人称其为“Go”)的情况下才包含前缀。单词“Go”太常见,并且有太多实现。
如果您不确定名称,请查看其主页、维基百科页面和 Debian 如何称呼它。
当 Homebrew 已有一个名为 foo
的配方时,我们通常不会接受用其他也名为 foo
的配方替换该配方的请求。这是为了避免混淆和出乎用户意料。
当两个配方共享一个上游名称时,例如 AESCrypt 和 AES Crypt,较新的配方通常必须调整其名称以避免与当前配方冲突。
如果你仍然不确定,那就提交吧。我们会应用一些任意规则并做出决定 😉。
导入类时,Homebrew 将需要该配方,然后创建该类的实例。它通过假设配方名称可以使用 regexp
直接转换为类名称来执行此操作。规则很简单
foo-bar.rb
=> FooBar
foobar.rb
=> Foobar
因此,如果你更改了类的名称,还必须重命名文件。文件名应全部小写,类名应为严格的驼峰式等效形式,例如配方 gnu-go
和 sdl_mixer
变为类 GnuGo
和 SdlMixer
,即使其名称的一部分是首字母缩写。
通过在 tap 根目录中的 Aliases
目录中创建符号链接来添加别名。
你可以运行 brew audit --strict --online
来测试配方是否符合 Homebrew 的内部风格,该风格大致基于 Ruby 风格指南。 audit
命令包括对尾随空格、某些源主机的首选 URL 以及许多其他风格问题的警告。在提交之前修复这些警告将使每个人处理起来更快。
提交给 Homebrew 的新配方应运行 brew audit --new --formula foo
。此命令由 BrewTestBot 在新提交中执行,作为自动化构建和测试过程的一部分,并突出了比标准审核更多潜在问题。
使用 brew info
并检查 Homebrew 从 URL 猜测的版本是否正确。如果不是,请添加一个明确的 version
。
所有内容都建立在 Git 上,因此贡献很容易
brew update # required in more ways than you think (initialises the Homebrew/brew Git repository if you don't already have it)
cd "$(brew --repository homebrew/core)"
# Create a new git branch for your formula so your pull request is easy to
# modify if any changes come up during review.
git checkout -b <some-descriptive-name> origin/master
git add Formula/f/foo.rb
git commit
Git 提交消息的既定标准是
在 Homebrew 中,我们要求预先提供配方名称,如下所示:foobar 7.3 (new formula)
。
这看起来可能非常简短,但你会发现,强迫自己总结提交会鼓励你保持原子性和简洁性。如果你无法用 50 到 80 个字符总结,你可能试图将两次提交作为一次提交。有关更全面的解释,请阅读 Tim Pope 出色的博客文章,关于 Git 提交消息的说明。
简单版本更新所需的提交消息格式为 foobar 7.3
,修复所需的格式为 foobar: fix flibble matrix.
。请将你的提交压缩成一条,并采用此消息格式,否则你的 PR 将被我们的自动压缩工作流替换。
确保引用任何相关的 GitHub 问题,例如在提交消息中 Closes #12345
。当试图了解他们感兴趣的公式的当前状态时,Homebrew 的历史是未来贡献者首先会查看的内容。
现在你只需要将你的提交推送到 GitHub。
如果你尚未 fork Homebrew,请转到 Homebrew/homebrew-core 存储库并点击 Fork 按钮。
如果你已在 GitHub 上 fork Homebrew,则可以手动推送(只需确保你已从 Homebrew/homebrew-core
master 中拉取)
git push https://github.com/myname/homebrew-core/ <what-you-named-your-branch>
现在,打开一个拉取请求以进行更改。
提供了三个命令来向用户显示信息性消息
ohai
用于一般信息opoo
用于警告消息odie
用于错误消息并立即退出当你需要出于任何原因优雅地退出公式时,请使用 odie
。例如
if build.head?
lib_jar = Dir["cfr-*-SNAPSHOT.jar"]
doc_jar = Dir["cfr-*-SNAPSHOT-javadoc.jar"]
odie "Unexpected number of artifacts!" if (lib_jar.length != 1) || (doc_jar.length != 1)
end
对于使用众所周知的构建系统的任何公式,在编译期间都应传递一些参数,以使其构建符合 Homebrew 标准。这些参数已收集到一组 std_*_args
方法中(如 std_configure_args
和 std_cmake_args
,如 brew create
的输出中所示),这些方法设置了构建类型和安装路径,以及任何其他适用的选项。
其中大多数方法接受参数以自定义其输出。例如,要将安装前缀设置为 libexec
以用于 configure
或 cmake
system "./configure", *std_configure_args(prefix: libexec)
system "cmake", "-S", ".", "-B", "build", *std_cmake_args(install_prefix: libexec)
bin.install "foo"
您会在一些公式中看到类似这样的内容。这会将文件 foo
移到公式的 bin
目录(/usr/local/Cellar/pkg/0.1/bin
)并使其可执行(chmod 0555 foo
)。
您还可以在安装过程中重命名文件。这对于向二进制文件添加前缀(否则会与其他公式发生冲突)或删除文件扩展名非常有用。例如,要将 foo.py
安装到公式的 bin
目录(/usr/local/Cellar/pkg/0.1/bin
)中,只需将其作为 foo
而不是 foo.py
bin.install "foo.py" => "foo"
inreplace
inreplace
是一种便捷函数,可以就地编辑文件。例如
inreplace "path", before, after
before
和 after
可以是字符串或正则表达式。如果您需要在文件中进行多次替换,则应使用块形式
inreplace "path" do |s|
s.gsub!(/foo/, "bar")
s.gsub! "123", "456"
end
确保修改 s
!此块忽略返回值。
当修补永远不会在源头上被接受的内容时,应使用 inreplace
而不是补丁,例如使软件的构建系统遵循 Homebrew 的安装层次结构。如果它同时影响 Homebrew 和 MacPorts(即 macOS 特定的内容),则应将其转换为源头上提交的补丁。
如果您需要修改 Makefile
中的变量,而不是在 inreplace
中使用 change_make_var!
,请尝试将它们作为参数传递给 make
system "make", "target", "VAR2=value1", "VAR2=value2", "VAR3=values can have spaces"
system "make", "CC=#{ENV.cc}", "PREFIX=#{prefix}"
请注意,如果你使用 system
的多参数形式,则值可以包含未转义的空格。
虽然通常应该避免使用 patch
,但有时它们是暂时必需的。
当 patch
(即修复头文件包含、修复编译器警告等)时,首先要做的是检查上游项目是否已意识到该问题。如果没有,请提交错误报告和/或提交补丁以供纳入。我们有时仍可能在补丁提交到上游之前接受你的补丁,但通过启动修复上游问题的流程,你可以减少我们必须携带补丁的时间。
始终使用代码注释来证明 patch
的合理性!否则,没有人会知道何时可以安全地移除补丁,或在更新配方时何时可以安全地保留补丁。注释应包括指向相关上游问题的链接。
可以使用资源样式块声明外部 patch
patch do
url "https://example.com/example_patch.diff"
sha256 "85cc828a96735bdafcf29eb6291ca91bac846579bcef7308536e0c875d6c81d7"
end
假定剥离级别为 -p1
。可以使用符号参数覆盖它
patch :p0 do
url "https://example.com/example_patch.diff"
sha256 "85cc828a96735bdafcf29eb6291ca91bac846579bcef7308536e0c875d6c81d7"
end
patch
可以声明在 stable
和 head
块中。始终使用块而不是条件,即 stable do ... end
而不是 if build.stable? then ... end
。
stable do
# ...
patch do
url "https://example.com/example_patch.diff"
sha256 "85cc828a96735bdafcf29eb6291ca91bac846579bcef7308536e0c875d6c81d7"
end
end
嵌入式(END)补丁可以这样声明
patch :DATA
patch :p0, :DATA
补丁数据包含在文件末尾
__END__
diff --git a/foo/showfigfonts b/foo/showfigfonts
index 643c60b..543379c 100644
--- a/foo/showfigfonts
+++ b/foo/showfigfonts
@@ -14,6 +14,7 @@
…
还可以通过传递字符串来嵌入补丁。这使得可以提供多个嵌入式补丁,同时仅使其中一些补丁成为条件。
patch :p0, "..."
在嵌入式补丁中,字符串“HOMEBREW_PREFIX”在应用补丁之前替换为常量 HOMEBREW_PREFIX
的值。
HOMEBREW_NO_INSTALL_FROM_API=1 brew install --interactive --git foo
# (make some edits)
git diff | pbcopy
brew edit foo
现在只需粘贴到 __END__
之后的配方中即可。
对于某些编辑器,可以使用 git diff >> path/to/your/formula/foo.rb
替换 git diff | pbcopy
,以确保补丁不会被更改,例如空格移除、缩进更改等。
请参阅 配方 API 以获取配方中可用的方法的完整列表。如果有什么不清楚的地方,你通常可以通过 grep
ping $(brew --repository homebrew/core)
目录来找出示例。如果你认为这有帮助,请提交一个拉取请求来修改此文档!
通常,公式需要不同的依赖关系、资源、补丁、冲突、弃用或在不同的操作系统和架构上的 keg_only
状态。在这些情况下,组件可以嵌套在 on_macos
、on_linux
、on_arm
或 on_intel
块中。例如,以下是将 gcc
添加为仅限 Linux 的依赖关系的方法
on_linux do
depends_on "gcc"
end
还可以为特定的 macOS 版本或版本范围声明组件。例如,要仅在 High Sierra 上声明依赖关系,请将 depends_on
调用嵌套在 on_high_sierra
块中。向 on_high_sierra
方法添加 :or_older
或 :or_newer
参数,以将依赖关系添加到满足条件的所有 macOS 版本。例如,要将 gettext
添加为 Mojave 及更高版本 macOS 的构建依赖关系,请使用
on_mojave :or_newer do
depends_on "gettext" => :build
end
有时,需要在某些 macOS 版本和 Linux 上使用依赖关系。在这些情况下,可以使用特殊的 on_system
方法
on_system :linux, macos: :sierra_or_older do
depends_on "gettext" => :build
end
要检查多个条件,请嵌套相应的块。例如,以下代码在 ARM 和 macOS 上添加 gettext
构建依赖关系
on_macos do
on_arm do
depends_on "gettext" => :build
end
end
def install
和 test do
中在 def install
和 test do
中,不要使用这些 on_*
方法。相反,请使用 if
语句和以下条件
OS.mac?
和 OS.linux?
根据操作系统返回 true
或 false
Hardware::CPU.intel?
和 Hardware::CPU.arm?
根据架构返回 true
或 false
MacOS.version
返回当前 macOS 版本。使用 ==
、<=
或 >=
与对应于 macOS 版本的符号进行比较(例如 if MacOS.version >= :mojave
)请参阅 icoutils
公式以获取示例。
livecheck
块当 brew livecheck
无法识别公式的版本时,我们可以使用 livecheck
块来控制其行为。以下是一个简单的示例,用于检查页面中包含类似 example-1.2.tar.gz
文件名的链接
livecheck do
url "https://www.example.com/downloads/"
regex(/href=.*?example[._-]v?(\d+(?:\.\d+)+)\.t/i)
end
有关 url
/regex
指南和附加 livecheck
块示例,请参阅 brew livecheck
文档。有关 livecheck
块中使用的方法的更多技术信息,请参阅 Livecheck
类文档。
head
)公式可以使用 head
为上游项目的开发前沿源(例如 master
/main
/trunk
)指定备用下载,该下载可以通过在安装时传递 --HEAD
来激活。指定它的方式与 url
相同
class Foo < Formula
# ...
head "https://github.com/some/package.git", branch: "main" # the default is "master"
end
您还可以在 head do
块中捆绑 URL 和任何 head
特定的依赖项和资源。
class Foo < Formula
# ...
head do
url "https://svn.code.sf.net/p/project/code/trunk"
depends_on "pkg-config" => :build
end
end
您可以在 install
方法中使用 build.head?
测试是否正在构建 head
。
在解析下载 URL 时,Homebrew 会自动检测它指向的资源类型,无论是存档(例如 tarball、zip)还是版本控制存储库(例如 Git、SVN、Mercurial),并选择合适的下载策略。某些策略可以传递其他选项来更改下载内容。例如,要使用存储库中的特定提交、标记或分支,请使用 url
或 head
指定 :tag
和 :revision
、:revision
或 :branch
选项,如下所示
class Foo < Formula
# ...
url "https://github.com/some/package.git",
tag: "v1.6.2",
revision: "344cd2ee3463abab4c16ac0f9529a846314932a2"
end
如果无法推断,请使用 using:
选项指定要使用 Homebrew 的哪种内置下载策略。例如
class Nginx < Formula
desc "HTTP(S) server and reverse proxy, and IMAP/POP3 proxy server"
homepage "https://nginxserver.cn/"
url "https://nginxserver.cn/download/nginx-1.23.2.tar.gz", using: :homebrew_curl
sha256 "a80cc272d3d72aaee70aa8b517b4862a635c0256790434dbfc4d618a999b0b46"
head "https://hg.nginx.org/nginx/", using: :hg
end
Homebrew 提供这些匿名下载策略。
:using 值 |
下载策略 |
---|---|
:bzr |
BazaarDownloadStrategy |
:curl |
CurlDownloadStrategy |
:cvs |
CVSDownloadStrategy |
:fossil |
FossilDownloadStrategy |
:git |
GitDownloadStrategy |
:hg |
MercurialDownloadStrategy |
:homebrew_curl |
HomebrewCurlDownloadStrategy |
:nounzip |
NoUnzipCurlDownloadStrategy |
:post |
CurlPostDownloadStrategy |
:svn |
SubversionDownloadStrategy |
如果您需要更多地控制文件下载和暂存的方式,您可以创建一个自定义下载策略,并使用 :using
选项指定它
class MyDownloadStrategy < SomeHomebrewDownloadStrategy
def fetch(timeout: nil, **options)
opoo "Unhandled options in #{self.class}#fetch: #{options.keys.join(", ")}" unless options.empty?
# downloads output to `temporary_path`
end
end
class Foo < Formula
url "something", using: MyDownloadStrategy
end
有时,在使用特定编译器时,软件包会构建失败。由于最近的 Xcode 版本 不再包含 GCC 编译器,因此我们无法简单地强制使用 GCC。相反,声明此问题的正确方法是使用 fails_with
DSL 方法。正确构建的 fails_with
块记录了已知会导致编译失败的最新编译器构建版本以及失败原因。例如
fails_with :clang do
build 211
cause "Miscompilation resulting in segfault on queries"
end
fails_with :gcc do
version "5" # fails with GCC 5.x and earlier
cause "Requires C++17 support"
end
fails_with gcc: "7" do
version "7.1" # fails with GCC 7.0 and 7.1 but not 7.2, or any other major GCC version
cause <<-EOS
warning: dereferencing type-punned pointer will break strict-aliasing rules
Fixed in GCC 7.2, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42136
EOS
end
对于 :clang
,build
采用一个整数(您可以在 brew --config
输出中找到此数字),而 :gcc
只使用 version
,它采用一个字符串来指示有问题的最后一个 GCC 版本,或一个主版本参数与 version
结合使用,以找出特定 GCC 版本的范围。 cause
采用一个字符串,建议使用 here 文档来提高可读性并允许更全面的文档编制。
fails_with
声明可与 :gcc
、:llvm
和 :clang
中的任何一个一起使用。Homebrew 将使用此信息选择一个可用的编译器(如果可用)。
当安装函数中的代码运行时,当前工作目录将设置为提取的 tar 包。这使得移动一些文件变得很容易
prefix.install "file1", "file2"
或全部
prefix.install Dir["output/*"]
或仅 tar 包的顶级文件,如 README、LICENSE 等。
prefix.install_metafiles
通常,我们希望你明确指出需要安装哪些文件或目录,而不是安装所有内容。
名称 | 默认路径 | 示例 |
---|---|---|
HOMEBREW_PREFIX |
$(brew --prefix) 的输出 |
/usr/local |
前缀 |
#{HOMEBREW_PREFIX}/Cellar/#{name}/#{version} |
/usr/local/Cellar/foo/0.1 |
opt_prefix |
#{HOMEBREW_PREFIX}/opt/#{name} |
/usr/local/opt/foo |
bin |
#{prefix}/bin |
/usr/local/Cellar/foo/0.1/bin |
doc |
#{prefix}/share/doc/#{name} |
/usr/local/Cellar/foo/0.1/share/doc/foo |
include |
#{prefix}/include |
/usr/local/Cellar/foo/0.1/include |
info |
#{prefix}/share/info |
/usr/local/Cellar/foo/0.1/share/info |
lib |
#{prefix}/lib |
/usr/local/Cellar/foo/0.1/lib |
libexec |
#{prefix}/libexec |
/usr/local/Cellar/foo/0.1/libexec |
man |
#{prefix}/share/man |
/usr/local/Cellar/foo/0.1/share/man |
man[1-8] |
#{prefix}/share/man/man[1-8] |
/usr/local/Cellar/foo/0.1/share/man/man[1-8] |
sbin |
#{prefix}/sbin |
/usr/local/Cellar/foo/0.1/sbin |
share |
#{prefix}/share |
/usr/local/Cellar/foo/0.1/share |
pkgshare |
#{prefix}/share/#{name} |
/usr/local/Cellar/foo/0.1/share/foo |
elisp |
#{prefix}/share/emacs/site-lisp/#{name} |
/usr/local/Cellar/foo/0.1/share/emacs/site-lisp/foo |
frameworks |
#{prefix}/Frameworks |
/usr/local/Cellar/foo/0.1/Frameworks |
kext_prefix |
#{prefix}/Library/Extensions |
/usr/local/Cellar/foo/0.1/Library/Extensions |
zsh_function |
#{prefix}/share/zsh/site-functions |
/usr/local/Cellar/foo/0.1/share/zsh/site-functions |
fish_function |
#{prefix}/share/fish/vendor_functions |
/usr/local/Cellar/foo/0.1/share/fish/vendor_functions |
bash_completion |
#{prefix}/etc/bash_completion.d |
/usr/local/Cellar/foo/0.1/etc/bash_completion.d |
zsh_completion |
#{prefix}/share/zsh/site-functions |
/usr/local/Cellar/foo/0.1/share/zsh/site-functions |
fish_completion |
#{prefix}/share/fish/vendor_completions.d |
/usr/local/Cellar/foo/0.1/share/fish/vendor_completions.d |
etc |
#{HOMEBREW_PREFIX}/etc |
/usr/local/etc |
pkgetc |
#{HOMEBREW_PREFIX}/etc/#{name} |
/usr/local/etc/foo |
var |
#{HOMEBREW_PREFIX}/var |
/usr/local/var |
buildpath |
系统中某个位置的临时目录 | /private/tmp/[formula-name]-0q2b/[formula-name] |
这些可用于代码中,例如
bin.install Dir["output/*"]
将二进制文件移动到酒窖中的正确位置,以及
man.mkpath
为手册页位置创建目录结构。
要将手册页安装到特定位置,请使用 man1.install "foo.1", "bar.1"
、man2.install "foo.2"
等。
请注意,在 Homebrew 的上下文中,libexec
由配方保留供私下使用,因此不会符号链接到 HOMEBREW_PREFIX
中。
您可以使用 Ruby 的 FileUtils
提供的文件实用程序。这些实用程序包含在 Formula
类中,因此您无需 FileUtils.
前缀即可使用它们。
创建符号链接时,请特别注意确保它们是相对符号链接。这使得创建可重定位的瓶子变得更加容易。例如,要在 bin
中为 libexec
中的可执行文件创建一个符号链接,请使用
bin.install_symlink libexec/"name"
而不是
ln_s libexec/"name", bin
由 install_symlink
创建的符号链接保证是相对的。仅当提供相对路径时,ln_s
才生成相对符号链接。
Ruby 的 Pathname
的其他几个实用程序可以简化一些常见操作。
要在目录中执行多个操作,请将它们包含在 cd <path> do
块中
cd "src" do
system "./configure", "--disable-debug", "--prefix=#{prefix}"
system "make", "install"
end
要显示埋藏在 libexec
或 macOS .app
包中的一个或多个二进制文件,请使用 write_exec_script
或 write_jar_script
bin.write_exec_script (libexec/"bin").children
bin.write_exec_script prefix/"Package.app/Contents/MacOS/package"
bin.write_jar_script libexec/jar_file, "jarfile", java_version: "11"
对于需要设置一个或多个环境变量才能正常运行的二进制文件,请使用 write_env_script
或 env_script_all_files
(bin/"package").write_env_script libexec/"package", PACKAGE_ROOT: libexec
bin.env_script_all_files(libexec/"bin", PERL5LIB: ENV.fetch("PERL5LIB", nil))
某些公式安装用解释型语言(例如 Python 或 Perl)编写的可执行脚本。Homebrew 提供了一个 rewrite_shebang
方法来重写脚本的 shebang。这将用公式所依赖的路径替换脚本的原始解释器路径。这可确保在执行时使用正确的解释器。如果构建系统已经处理了这一点(例如通常使用 pip
或 Perl ExtUtils::MakeMaker
),则不需要这样做。
例如,icdiff
公式使用了此实用程序。请注意,必须在公式中包含实用程序;例如,对于 Python,必须使用 include Language::Python::Shebang
。
注意: option
在 Homebrew/homebrew-core 中不被允许,因为 CI 不会对其进行测试。
如果您想添加 option
class Yourformula < Formula
# ...
url "https://example.com/yourformula-1.0.tar.gz"
sha256 "abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1"
# ...
option "with-ham", "Description of the option"
option "without-spam", "Another description"
depends_on "bar" => :recommended
depends_on "foo" => :optional # automatically adds a with-foo option # automatically adds a without-bar option
# ...
end
然后定义 option
的效果
if build.with? "ham"
# note, no "with" in the option name (it is added by the build.with? method)
end
if build.without? "ham"
# works as you'd expect. True if `--without-ham` was given.
end
option
名称应以单词 with
或 without
为前缀。例如,运行测试套件的选项应命名为 --with-test
或 --with-check
,而不是 --test
,启用共享库的选项应命名为 --with-shared
,而不是 --shared
或 --enable-shared
。请参阅 备用 ffmpeg
公式以获取示例。
不是 build.with?
或 build.without?
的 option
应使用 deprecated_option
弃用。请参阅 wget
公式以获取历史示例。
任何不一定是安装过程一部分的初始化步骤都可以放在 post_install
块中,例如设置命令或数据目录创建。可以使用 brew postinstall <formula>
单独重新运行此块。
class Foo < Formula
# ...
url "https://example.com/foo-1.0.tar.gz"
def post_install
rm_f pkgetc/"cert.pem"
pkgetc.install_symlink Formula["ca-certificates"].pkgetc/"cert.pem"
end
# ...
end
在上述示例中,libressl
公式用指向 ca-certificates
公式的符号链接替换了其证书的库存列表。
例如,Ruby 1.9 的 gem 应安装到 var/lib/ruby/
,这样在升级 Ruby 时无需重新安装 gem。通常,你可以使用符号链接技巧或(理想情况下)配置选项来实现此目的。
另一个示例是不应在软件包升级时覆盖的配置文件。如果在安装后你发现要保留的配置文件未被复制,而是从 Cellar 中符号链接到 /usr/local/etc/
,则通常可以通过向软件包的配置脚本传递适当的参数来纠正此问题。该参数会根据给定软件包的配置脚本和/或 Makefile 而有所不同,但一个示例可能是:--sysconfdir=#{etc}
有两种方法可以将 launchd
plist 和 systemd
服务添加到公式,以便 brew services
可以选取它们
如果软件包已提供服务文件,则公式可以通过名称引用它
service do
name macos: "custom.launchd.name",
linux: "custom.systemd.name"
end
为了找到文件,我们在内部将 .plist
附加到 launchd
服务名称,将 .service
附加到 systemd
服务名称。
如果公式未提供服务文件,则可以使用以下节生成一个服务文件
# 1. An individual command
service do
run opt_bin/"script"
end
# 2. A command with arguments
service do
run [opt_bin/"script", "--config", etc/"dir/config.yml"]
end
# 3. OS specific commands (If you omit one, the service file won't get generated for that OS.)
service do
run macos: [opt_bin/"macos_script", "standalone"],
linux: var/"special_linux_script"
end
此表列出了可在 service
块中设置的选项。必须在服务块中定义 run
或 name
字段。如果定义了 name
但未定义 run
,则 Homebrew 不会尝试根据这些字段更改程序包提供的服务文件。 run
字段指示要运行的命令,指示 Homebrew 使用块中设置的选项创建服务描述文件,因此在使用 name
和 require_root
以外的字段之前需要此字段。
方法 | 默认值 | macOS | Linux | 描述 |
---|---|---|---|---|
run |
- | 是 | 是 | 要执行的命令:带参数的数组或路径 |
run_type |
:immediate |
是 | 是 | 服务类型::immediate 、:interval 或 :cron |
interval |
- | 是 | 是 | 控制启动间隔,:interval 类型需要此间隔 |
cron |
- | 是 | 是 | 控制触发时间,:cron 类型需要此时间 |
keep_alive |
否 |
是 | 是 | 设置上下文,服务将在其中保持进程运行 |
launch_only_once |
否 |
是 | 是 | 命令是否只应运行一次 |
require_root |
否 |
是 | 是 | 服务是否需要 root 访问权限。如果为 true,Homebrew 会提示在各种情况下使用 sudo ,但不会强制执行 |
environment_variables |
- | 是 | 是 | 要设置的变量哈希 |
working_dir |
- | 是 | 是 | 要从中进行操作的目录 |
root_dir |
- | 是 | 是 | 要作为进程 chroot 的目录 |
input_path |
- | 是 | 是 | 要作为进程输入的路径 |
log_path |
- | 是 | 是 | 要将 stdout 写入的路径 |
error_log_path |
- | 是 | 是 | 要将 stderr 写入的路径 |
restart_delay |
- | 是 | 是 | 在重新启动进程之前要延迟的秒数 |
process_type |
- | 是 | no-op | 要管理的进程类型::background 、:standard 、:interactive 或 :adaptive |
macos_legacy_timers |
- | 是 | no-op | 除非设置此选项,否则 launchd 作业创建的计时器将合并 |
sockets |
- | 是 | no-op | 作为服务访问点的套接字 |
名称 |
- | 是 | 是 | 哈希,其中包含 macOS 上的 launchd 服务名称和/或 Linux 上的 systemd 服务名称。如果不存在此名称,Homebrew 将为服务文件生成默认名称 |
对于在启动后保持运行的服务,可以使用默认的 run_type
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive true
run_type :immediate # This should be omitted since it's the default
end
如果服务需要按时间间隔运行,请使用 run_type :interval
并指定时间间隔
service do
run [opt_bin/"beanstalkd", "test"]
run_type :interval
interval 500
end
如果服务需要在特定时间运行,请使用 run_type :cron
并使用 crontab 语法指定时间
service do
run [opt_bin/"beanstalkd", "test"]
run_type :cron
cron "5 * * * *"
end
可以使用哈希设置环境变量。对于 PATH
,有辅助方法 std_service_path_env
,它返回 #{HOMEBREW_PREFIX}/bin:#{HOMEBREW_PREFIX}/sbin:/usr/bin:/bin:/usr/sbin:/sbin
,以便服务可以找到其他 brew
安装的命令。
service do
run opt_bin/"beanstalkd"
environment_variables PATH: std_service_path_env
end
keep_alive
选项标准选项使服务保持运行状态,无论任何状态或情况如何
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive true # or false
end
与哈希形式中的上述相同
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive always: true
end
在服务以非零返回码退出之前保持运行
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive successful_exit: true
end
仅在作业崩溃时保持运行
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive crashed: true
end
只要文件存在,就保持运行
service do
run [opt_bin/"beanstalkd", "test"]
keep_alive path: "/some/path"
end
sockets
格式sockets
方法接受格式化的套接字定义,格式为 <type>://<host>:<port>
。
type
: udp
或 tcp
host
: 运行套接字的主机,例如 0.0.0.0
port
: 套接字应监听的端口号请注意,套接字默认情况下可以在 IPv4 和 IPv6 地址上访问。
如果你只需要一个套接字,并且不关心名称(默认值为 listeners
)
service do
run [opt_bin/"beanstalkd", "test"]
sockets "tcp://127.0.0.1:80"
end
如果你需要多个套接字和/或你想指定名称
service do
run [opt_bin/"beanstalkd", "test"]
sockets http: "tcp://0.0.0.0:80", https: "tcp://0.0.0.0:443"
end
Homebrew 具有多级环境变量过滤,它影响哪些变量可用于配方。
首先,对 Homebrew 运行的环境进行整体 过滤,以避免环境污染破坏源代码构建。具体来说,此过程会过滤除选定变量列表之外的所有变量,并允许以 HOMEBREW_
为前缀的任何变量。具体实现可在 bin/brew
中找到。
第二级过滤 删除敏感环境变量(例如密钥、密码或令牌等凭据),以防止恶意子进程获取它们。这会阻止任何此类变量到达配方的 Ruby 代码,因为它们在调用之前已被过滤。具体实现可在 ENV.clear_sensitive_environment!
方法 中找到。
总之,任何打算用于公式的环境变量都需要符合这些过滤规则才能使用。
你可以使用 ENV["VARIABLE_NAME"] = "VALUE"
在公式的 install
或 test
块中设置环境变量。可以在 csound
公式中看到示例。
还可以使用 with_env
方法临时设置环境变量;在对该方法的调用中定义的任何变量都将在块的末尾恢复到其原始值。可以在 gh
公式中看到示例。
还有 ENV
帮助程序方法可用于许多常见环境变量设置和检索操作,例如
ENV.cxx11
- 启用 C++11 功能进行编译ENV.deparallelize
- 仅一次编译一个作业;传递一个块以使其仅影响特定的安装步骤ENV.O0
、ENV.O1
、ENV.O3
- 设置特定的编译器优化级别(默认值:macOS:-Os
,Linux:-O2
)ENV.runtime_cpu_detection
- 考虑在运行时检测 CPU 功能的公式ENV.append_to_cflags
- 一次向 CFLAGS
CXXFLAGS
OBJCFLAGS
OBJCXXFLAGS
添加一个值ENV.prepend_create_path
- 创建一个路径并将其前置到现有路径列表ENV.remove
- 从环境变量值中删除一个字符串ENV.delete
- 取消设置一个环境变量可以在 SharedEnvExtension 和 Superenv 模块文档中找到完整列表。
请参阅我们的 弃用、禁用和删除公式 文档,以了解有关如何以及何时弃用或禁用公式的更多信息。
当软件的新版本发布时,请使用 brew bump-formula-pr
自动更新 url
和 sha256
,删除任何 revision
行,并提交一个拉取请求。请参阅我们的 如何打开 Homebrew 拉取请求 文档以了解详细信息。
Homebrew 尝试从 version
自动确定 url
以避免重复。如果 tarball 有一个不寻常的名称,您可能需要手动分配 version
。
如果项目的 makefile 无法并行运行,请尝试通过将这些行添加到公式的 install
方法中来取消并行化
ENV.deparallelize
system "make" # separate compilation and installation steps
system "make", "install"
如果这样解决了问题,请向上游项目提交一个问题,以便我们可以为每个人解决它。
查看 MacPorts 和 Fink 的操作
brew search --macports foo
brew search --fink foo
superenv
是我们的“超级环境”,它通过移除 /usr/local/bin
和所有对构建不重要的用户 PATH
来隔离构建。它这样做是因为用户 PATH
经常充满了破坏构建的内容。 superenv
还会从传递给 clang
/gcc
的命令中移除错误的标志,并注入其他标志(例如,所有 keg_only
依赖项都被添加到 -I
和 -L
标志中)。
如果在您新公式的本地 Homebrew 构建中,您看到 Operation not permitted
错误,这是因为您的新公式尝试在沙盒区域之外写入磁盘。这在 macOS 上由 sandbox-exec
强制执行。
某些软件需要 Fortran 编译器。这可以通过向公式添加 depends_on "gcc"
来声明。
需要 MPI 的软件包应通过向公式添加 depends_on "open-mpi"
来使用 OpenMPI,而不是 MPICH。这些软件包存在冲突并提供相同的标准化接口。选择默认实现并要求采用它允许软件链接到依赖于 MPI 的多个库,而不会因不同的 MPI 运行时而产生意外的不兼容性。
需要 BLAS/LAPACK 线性代数接口的包应通过添加 depends_on "openblas"
并(如果使用 CMake 构建)将 -DBLA_VENDOR=OpenBLAS
传递给 CMake,而不是 Apple 的 Accelerate 框架或默认引用 lapack
实现,来链接到 OpenBLAS。Apple 的 BLAS/LAPACK 实现已过时,可能会引入难以调试的问题。引用 lapack
公式很好,尽管它并未得到积极维护或调整。
master
)您是否在 Git 中创建了一个真正的混乱,导致您无法创建要提交给我们的提交?您可能需要考虑从头开始。可以通过运行以下命令重置您对 Homebrew master
分支的更改
git checkout -f master
git reset --hard origin/master