Posted at

Xcode でコマンドラインアプリを作って Homebrew でインストールできる様にする

More than 3 years have passed since last update.


対象

Xcode でコマンドラインアプリを作成し、オレオレ HomeBrew リポジトリを作って GitHub で公開するケースを想定しています。

利用している Homebrew のバージョンは 0.9.5 です。


まずはアプリ作成

Xcode で Mac 用コマンドラインアプリを作成します。

Archive して export したアプリを、zip で固めて GitHub の Releases に登録します。


リポジトリ作成

Prefix に homebrew- と付けたリポジトリがオレオレ Homebrew リポジトリとして利用できます。例えば GitHub に homebrew-repo といったリポジトリを作成します。


Formula 作成

Homebrew でアプリをインストールさせる為のレシピである Formula を作成します。


インストールさせるアプリの URL を取得

まずは先ほど GitHub の Releases に登録したアプリの URL をコピーします。

https://github.com/yourname/yourtool/releases/download/0.1.0/yourtool-v-0.1.0.zip

の様な URL になっていると思います。


Formula をテンプレートから生成

$ brew create {url}

を実行すると、テンプレートから Formula を生成してくれます。

{url} には先ほどコピーしておいた URL を入力します。

# 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 yourtool < Formula
desc ""
homepage ""
url "https://github.com/yourname/yourtool/releases/download/0.1.0/yourtool-v-0.1.0.zip"
version "0.1.0"
sha256 "e8fd4a24bc0cf69aead75c844ad080e5e26efc6db76357b226e182cbc27ae22a"

# 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 yourtool`. 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

こんな感じの Formula が生成されます。


Formula を編集

編集して、以下の様な感じにします。

class yourtool < Formula

desc "your tool description"
homepage "your tool homepage url"
url "https://github.com/yourname/yourtool/releases/download/0.1.0/yourtool-v-0.1.0.zip"
version "0.1.0"
sha256 "e8fd4a24bc0cf69aead75c844ad080e5e26efc6db76357b226e182cbc27ae22a"

def install
bin.install Dir["Contents/*"]
bin.install_symlink "MacOS/yourtool"
end
end

テンプレートから生成された状態から、変更するのはコメントの削除と、def install メソッド内の変更です。

bin.install メソッドは、zip の状態で Download されたアプリから、必要なファイルを /usr/local/Cellar/yourtool/0.1.0/bin/ 以下に展開します。

export されたアプリのディレクトリ構成は以下の様になっていますので、

yourtool.app

└── Contents
├── Frameworks
├── Info.plist
├── MacOS
│   └── yourtool
├── PkgInfo
└── _CodeSignature

bin.install Dir["Contents/*"] と記述する事で、Contents 以下の動作に必要なファイルを全て /usr/local/Cellar/yourtool/0.1.0/bin/ 配下に展開するという動作になります。

続く bin.install_symlink "MacOS/yourtool" では、/usr/local/Cellar/yourtool/0.1.0/bin/ 配下に展開されたファイルのうち、指定したファイルの symlink を/usr/local/bin 配下に貼るという動作をします。

今回のケースではバイナリである yourtool をパスが通った場所に symlink します。


Formula を push する

上記保存されますと、/usr/local/Library/Formula/ 配下に yourtool.rb といった名前で配置されます。これを先ほど作成した homebrew-repo に commit して push します。


brew install する

$ brew install yourname/repo/yourtool

を実行すると、オレオレリポジトリを brew tap した後、続けて Install してくれます。

which yourname してパスが通っている事を確認、実行して問題無ければ成功です。


本家に登録してもらう

ある程度本気のアプリであれば、本家の Homebrew リポジトリを Fork して Formula を PullRequest して登録してもらうと良いと思います。


参考

Swiftで書いたコマンドラインツールをHomebrewでインストールできるようにする

HomeBrewで自作ツールを配布する

Formula Cookbook