说明
这篇文章是因为我在提交 brew Formula 的时候资料很少,所以干脆自己动手写,以我向 homebrew-core 发 i386-elf 交叉编译环境为例子展开。
需要
- git
- ruby
前期准备
首先 fork homebrew 的 repo
ps.这里的仓库根据你想 PR 到的仓库 fork,这里用 homebrew-core
git clone https://github.com/MRNIU/homebrew-core
使用你需要的资源下载地址创建新 Formula,这里使用的是 binutils-2.31,你也可以使用自己 github 的资源
brew create https://ftp.gnu.org/gnu/binutils/binutils-2.31.tar.gz
brew 会在
/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
新建一个与下载文件同名的 ruby 脚本,大致内容如下
# Documentation: https://docs.brew.sh/Formula-Cookbook
# https://www.rubydoc.info/github/Homebrew/brew/master/Formula
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
class I386ElfBinutils < Formula
desc "FSF Binutils for i386-elf cross development"
homepage "https://www.gnu.org/software/binutils/"
url "https://ftp.gnu.org/gnu/binutils/binutils-2.31.1.tar.xz"
sha256 "5d20086ecf5752cc7d9134246e9588fa201740d540f7eb84d795b1f7a93bca86"
# depends_on "cmake" => :build
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! For Homebrew/homebrew-core
# this will need to be a test that verifies the functionality of the
# software. Run the test with `brew test SimpleKernel`. 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
修改 .rb 文件
在 brew 新建的脚本中,注释明确提出了几点要求
- 在提交之前删掉所有注释
- 使用
brew install --build-from-source [Formula name]
进行测试 - 使用
brew test [Formula name]
进行测试 - 使用
brew audit --strict [Formula name]
进行测试
这是修改后的 rb 文件
class I386ElfBinutils < Formula
desc "FSF Binutils for i386-elf cross development"
homepage "https://www.gnu.org/software/binutils/"
url "https://ftp.gnu.org/gnu/binutils/binutils-2.31.1.tar.xz"
sha256 "5d20086ecf5752cc7d9134246e9588fa201740d540f7eb84d795b1f7a93bca86"
def install
system "./configure", "--target=i386-elf",
"--disable-multilib",
"--disable-nls",
"--disable-werror",
"--prefix=#{prefix}"
system "make"
system "make", "install"
end
test do
assert_match "f()", shell_output("#{bin}/i386-elf-c++filt _Z1fv")
end
end
要注意的地方
- 每个函数之间要有一行空行
- 资源链接最好是
.tar.xz
- test 部分必须是实用性的,一般不能使用如
-v
-version
等 - 依赖部分只写必须的,运行时依赖不包括在内
brew audit --strict [Formula name]
无法发现空行brew test [Formula name]
仅仅是执行 rb 文件的test
函数
修改完后就可以发 PR 了
PR
PR 提交到社区后,会有社区负责人进行审查,他们会帮助你完善不合适的地方,一般除了格式问题就是 test
函数不符合规范。每次提交都会在 homebrew 的 CI 上测试,只有当社区负责人和 CI 都通过才会被 merge。
这是 merge 后的 rb 文件
i386-elf-binutils.rb
class I386ElfBinutils < Formula
desc "FSF Binutils for i386-elf cross development"
homepage "https://www.gnu.org/software/binutils/"
url "https://ftp.gnu.org/gnu/binutils/binutils-2.31.1.tar.xz"
sha256 "5d20086ecf5752cc7d9134246e9588fa201740d540f7eb84d795b1f7a93bca86"
bottle do
sha256 "89312270dc465d7d2c622d7253acfecc7e8b0d5a5cc7688822c1dbb10ee7166e" => :mojave
sha256 "1f7b4aa5dd270750954ef0a177223843affc45214cb7f19fc5e85743608fc8a6" => :high_sierra
sha256 "7ca42ad9603b7e336f029ae87407c789f1533af638daa54d3db3f2bde2afbf0c" => :sierra
end
def install
system "./configure", "--target=i386-elf",
"--disable-multilib",
"--disable-nls",
"--disable-werror",
"--prefix=#{prefix}"
system "make"
system "make", "install"
end
test do
assert_match "f()", shell_output("#{bin}/i386-elf-c++filt _Z1fv")
end
end
也附上 i386-elf-gcc 的最后版本
class I386ElfGcc < Formula
desc "The GNU compiler collection for i386-elf"
homepage "https://gcc.gnu.org"
url "https://mirrors.nju.edu.cn/gnu/gcc/gcc-8.2.0/gcc-8.2.0.tar.xz"
sha256 "196c3c04ba2613f893283977e6011b2345d1cd1af9abeac58e916b1aab3e0080"
bottle do
sha256 "a5fc827397725b13fcf0b4c455b68021b2285c80fb0c047030db9602d3e98623" => :mojave
sha256 "913cafca1eb2ec4493d09eda85f16c64561835c35882eb4bad13c81692bcb468" => :high_sierra
sha256 "e63d8a51cce665fbd05aa7cbc75082181caeaf38b8c77210e5c3846cdc49e1e5" => :sierra
end
depends_on "gmp"
depends_on "i386-elf-binutils"
depends_on "libmpc"
depends_on "mpfr"
def install
mkdir "i386-elf-gcc-build" do
system "../configure", "--target=i386-elf",
"--prefix=#{prefix}",
"--without-isl",
"--disable-multilib",
"--disable-nls",
"--disable-werror",
"--without-headers",
"--with-as=#{Formula["i386-elf-binutils"].bin}/i386-elf-as",
"--with-ld=#{Formula["i386-elf-binutils"].bin}/i386-elf-ld",
"--enable-languages=c,c++"
system "make", "all-gcc"
system "make", "install-gcc"
system "make", "all-target-libgcc"
system "make", "install-target-libgcc"
end
end
test do
(testpath/"test-c.c").write <<~EOS
int main(void)
{
int i=0;
while(i<10) i++;
return i;
}
EOS
system "#{bin}/i386-elf-gcc", "-c", "-o", "test-c.o", "test-c.c"
assert_match "file format elf32-i386", shell_output("#{Formula["i386-elf-binutils"].bin}/i386-elf-objdump -a test-c.o")
end
end
参考资料
https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request
https://blog.windrunner.me/tool/homebrew.html