相关说明
目前国内已有很多关于如何使用 Homebrew 的文章,但是却很难找到一份关于如何编写 Homebrew 的软件包的介绍,Homebrew 是一个基于 git 的软件包管理器,每个人都可以向 Homebrew 提交新的软件包或是提交已有软件包的更新。本文将用两个例子分别介绍如何提交已有软件包的更新以及如何提交新的软件包。
编写已有软件包的更新
Homebrew 的软件包被称为 formula,对应一个 ruby 脚本。我们以 shadowsock-libev 为例,介绍如何编写已有软件包的更新。首先在 terminal 中执行:
$ brew edit shadowsocks-libev
brew 将使用
$EDITOR
变量中指定的编辑器打开对应的 ruby 脚本,要更新一个软件包,我们只需要更改脚本的前三行:class ShadowsocksLibev < Formula
homepage "https://github.com/shadowsocks/shadowsocks-libev"
url "https://github.com/shadowsocks/shadowsocks-libev/archive/v2.1.4.tar.gz"
sha256 "d4e665e375224ba1d4844b97e7263491ce07a60f08c9cb55c3128a6d3aad13e7"
这是 shadowsocks-libev v2.1.4 版本对应的脚本代码,脚本的第三行对应的就是这个软件包源代码的下载地址,修改第三行的 url 为新版本 v2.2.0 的软件包源代码下载地址,保存并执行如下命令:
$ brew reinstall shadowsocks-libev
此时我们会获得这样的提示:
Error: SHA256 mismatch
Expected: d4e665e375224ba1d4844b97e7263491ce07a60f08c9cb55c3128a6d3aad13e7
Actual: 49688f39649f0f61e323ddba8b02daa5dfe88bf2e051ed91181d266fe824df69
我们再次编辑软件包脚本,将第四行的 SHA256 值修改为新版本的
49688f39649f0f61e323ddba8b02daa5dfe88bf2e051ed91181d266fe824df69
即可。
重新执行命令测试安装 shadowsocks-libev:
$ brew reinstall shadowsocks-libev
现在没有错误出现了,我们的软件包更新的编写就完成了,接下来需要提交这个更新。
提交已有软件包的更新
首先访问Homebrew 的项目主页,随后点击 fork。本文已经假设你拥有一个 Github 帐号,并且拥有一些基本的 git 使用经验,如果你没有,还是多谷歌吧。
执行命令:
$ brew update
$ cd $(brew --repository)
$ git checkout -b shadowsocks
$ git add Library/Formula/shadowsocks-libev.rb
$ git commit
我们首先将 Homebrew 更新到了最新版本,然后切换到了 Homebrew 的本地根目录,随后创建并切换到了一个名叫
shadowsocks
的 branch,添加了新的脚本文件修改记录,最后进行 commit。
Homebrew 推荐的 commit message style 是非常简洁的:只需要软件包名加上版本号即可,比如:
shadowsocks-libev 2.2.0
。注意使用 foobar x.x.x
这样的格式,不要加入字符 v
或者 ver
等来表示版本号,直接使用数字就可。
将这个 branch push 到自己 fork 的 Homebrew 下:
$ git push git@github.com:Github 用户名 /Homebrew.git shadowsocks
最后回到 Homebrew 的项目主页 并提交一个 pull request,title 同样使用
shadowsocks-libev 2.2.0
即可。
我们只需要等待这个更新被接收即可。
最后,我们切换回 master 分支,并且删除掉 shadowsocks 分支。
$ git checkout master
$ git branch -D shadowsocks
创建全新的软件包
首先我们需要获取软件源代码包的地址,以 cidrmerge 为例,直接从 sourceforge 上下载时可以获得这个路径:
http://iweb.dl.sourceforge.net/project/cidrmerge/cidrmerge/cidrmerge-1.5.3/cidrmerge-1.5.3.tar.gz
这个路径仅仅是 sourceforge 使用的镜像站点的地址,实际上我们应该使用这个地址以方便世界各地的用户从不同的镜像站下载源代码:
https://downloads.sourceforge.net/project/cidrmerge/cidrmerge/cidrmerge-1.5.3/cidrmerge-1.5.3.tar.gz
执行命令:
$ brew create https://downloads.sourceforge.net/project/cidrmerge/cidrmerge/cidrmerge-1.5.3/cidrmerge-1.5.3.tar.gz
Homebrew 会按照模板创建一个默认的脚本:
# Documentation: https://github.com/Homebrew/Homebrew/blob/master/share/doc/Homebrew/Formula-Cookbook.md
# /usr/local/Library/Contributions/example-formula.rb
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
class Cidrmerge < Formula
homepage ""
url "http://iweb.dl.sourceforge.net/project/cidrmerge/cidrmerge/cidrmerge-1.5.3/cidrmerge-1.5.3.tar.gz"
version "1.5.3"
sha256 "21b36fc8004d4fc4edae71dfaf1209d3b7c8f8f282d1a582771c43522d84f088"
# depends_on "cmake" => :build
depends_on :x11 # if your formula requires any X11/XQuartz components
def install
# ENV.deparallelize # if your formula fails when building in parallel
# Remove unrecognized options if warned by configure
system "./configure", "--disable-debug",
"--disable-dependency-tracking",
"--disable-silent-rules",
"--prefix=#{prefix}"
# system "cmake", ".", *std_cmake_args
system "make", "install" # if this fails, try separate make/make install steps
end
test do
# `test do` will create, run in and delete a temporary directory.
#
# This test will fail and we won't accept that! It's enough to just replace
# "false" with the main program this formula installs, but it'd be nice if you
# were more thorough. Run the test with `brew test cidrmerge`. Options passed
# to `brew install` such as `--HEAD` also need to be provided to `brew test`.
#
# The installed folder is not in the path, so use the entire path to any
# executables being tested: `system "#{bin}/program", "do", "something"`.
system "false"
end
end
这个小程序没有任何依赖项,只需要执行
make
就能完成编译,只需要保留编译完成得到的 cidrmerge 程序即可,所以只需要添加上项目主页的网址,并编写简单的安装脚本:class Cidrmerge < Formula
homepage "http://cidrmerge.sourceforge.net"
url "https://downloads.sourceforge.net/project/cidrmerge/cidrmerge/cidrmerge-1.5.3/cidrmerge-1.5.3.tar.gz"
sha256 "21b36fc8004d4fc4edae71dfaf1209d3b7c8f8f282d1a582771c43522d84f088"
def install
system "make"
bin.install "cidrmerge"
end
end
使用
system
表示执行后续的命令:system "make"
使用
bin.install
表示在 bin 目录下安装 cidrmerge 文件:bin.install "cidrmerge"
最后加上测试脚本:
test do
input = <<-EOS.undent
10.1.1.0/24
10.1.1.1/32
192.1.4.5/32
192.1.4.4/32
EOS
assert_equal "10.1.1.0/24\n192.1.4.4/31\n", pipe_output("#{bin}/cidrmerge", input)
end
这样,一个完整的安装包脚本就编写完成了。
提交全新的软件包
提交全新的软件包和提交软件包更新的方法类似,也是单独开一个 branch、commit、push to remote,不过 commit message 需要使用
foobar 7.3 (new formula)
这样的形式。pull request 的 title 也需要使用相同的形式。
通常你的软件包并不会一次过关,常常需要按照要求更改几次,在本地进行修改之后重新 commit,然后 push 到你的 Homebrew 的 fork 的相同的分支下。此时可以随意填写 commit message。比如 cidrmerge 就被提了 许多建议。
当你的软件包通过审核之后,你的所有 commits 会被 squash 到第一个
foobar 7.3 (new formula)
的 commit 下,然后被 merge 到 Homebrew 项目,随后 pull request 被关闭.