Mac OSX 10.8.5 で Julia HEAD が brew (re)install できない件

## 前置き

OSX 10.8.5 の入っている Mac で、「そういえば Julia HEAD 最新にしてなかった」と `brew reinstall --HEAD julia` しようとしたら、`make` フェーズでエラーとなりビルド出来ませんでした。
@chezou さんの記事「[homebrewでjuliaのHEADのインストールに失敗した時にするといいこと](http://qiita.com/chezou/items/136959635463a918b8be "homebrewでjuliaのHEADのインストールに失敗した時にするといいこと - Qiita")」を実施してもうまくいかず。

「何コレ？」と色々調べてなんとか自己解決したので、記録として残しておきます[^1]。
手っ取り早く解決方法だけ知りたい方は [解決](#%E8%A7%A3%E6%B1%BA) までジャンプしてください。

## 環境

+ Mac OSX 10.8.5
+ Homebrew
+ [homebrew-julia](https://github.com/staticfloat/homebrew-julia/ "staticfloat/homebrew-julia")

### 環境補足

過去に homebrew-julia で Julia HEAD をインストールしてある前提です（[過去記事](http://qiita.com/antimon2/items/a8cd98257219773b9ef3#julia-040-dev)参照）。
次章以降は少なくとも `brew tap staticfloat/julia` を実施済である前提で進めます。

## 起きていた現象

うっかりログを消してしまったのですが、起きていた現象としては、以下のサイトと全く同じ。

[Problem building 0.4 on OSX 10.8.5 - error in signal-handling.c](http://julia-programming-language.2336112.n4.nabble.com/Problem-building-0-4-on-OSX-10-8-5-error-in-signal-handling-c-td24990.html "Julia Users - Problem building 0.4 on OSX 10.8.5 - error in signal-handling.c")

そこのログを引用させていただきます：

```
     CC src/signal-handling.o
In file included from signal-handling.c:62:
./signals-unix.c:40:72: error: use of undeclared identifier 'ucontext64_t'; did you mean 'ucontext_t'?
    bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, (bt_context_t)&((ucontext64_t*)context)->uc_mcontext64->__ss);
                                                                       ^
/usr/include/sys/_structs.h:227:26: note: 'ucontext_t' declared here
typedef _STRUCT_UCONTEXT        ucontext_t;     /* [???] user context */
                                ^
In file included from signal-handling.c:62:
./signals-unix.c:40:85: error: expected expression
    bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, (bt_context_t)&((ucontext64_t*)context)->uc_mcontext64->__ss);
                                                                                    ^
2 errors generated.
make[1]: *** [signal-handling.o] Error 1
make: *** [julia-src-release] Error 2
```

で、原因も含めてそこでのやりとりを要約すると、

+ 出ているエラーは「`ucontext64_t` っていう型を要求されているけれど、定義されていないよ、`ucontext_t` の間違いじゃない？」というもの。
+ 調べたら、signals-apple.c の中で OSX 10.9 未満の時に別のヘッダファイルを `#include` しているみたいだけれど、これを正しくすれば良いんじゃない？
+ 結局 **Yosemite にアップグレード** して解決しちゃいました（てへぺろ）。

ということで。
現象と原因は分かったのですが、根本的な解決策は書かれていないという(^-^;

## 調査

ということで、色々調べてみました。
で、おそらくこうすれば解決だろうという道筋はあっという間に判明。

エラーログに、「`ucontext_t` だったら /usr/include/sys/\_structs.h で定義されているよ」と書かれているのですが、そのファイルの中身を見てみたら、何のことはない、**`ucontext64_t` も定義されていた** のです。
ただし。事前に `__need_ucontext64_t` が（`#define` ディレクティブ等で）定義されていることが必要。
そして先ほどのやりとりで「別のヘッダファイルを `#include` してる」の箇所が、実はこうなっていました。

```
#define __need_ucontext64_t
#include <machine/_structs.h>
```

てことは。ここが↓ならうまく動くのではないか、と。

```
#define __need_ucontext64_t
#include <sys/_structs.h>
```

一応、/usr/innclude/machine/\_structs.h も /usr/include/sys/\_structs.h の中身も詳しく見てみましたが、前者は `ucontect64_t` の定義には無関係そうだし、後者はもし複数回読み込まれたとしてもきちんと未定義のものだけ定義して既定のものを汚さない仕組みになっているっぽかったので。
取り敢えずこれで build 通るか試してみよう、と。

## 解決

で。結果として以下の方法で無事にビルド出来ました。

### 1. パッチファイルの作成

最新のソースを `git clone` してその箇所を修正して、`git diff` を実施。
内容は以下の通り（2015/09/05 10:00 現在）。

```diff:src.signals-apple.c.diff
diff --git a/src/signals-apple.c b/src/signals-apple.c
index ab3709b..5001166 100644
--- a/src/signals-apple.c
+++ b/src/signals-apple.c
@@ -9,7 +9,7 @@
 #include <sys/_types/_ucontext64.h>
 #else
 #define __need_ucontext64_t
-#include <machine/_structs.h>
+#include <sys/_structs.h>
 #endif
 
 static mach_port_t segv_port = 0;
```

ファイルは以下に置いてあります→ https://gist.githubusercontent.com/antimon2/412db3042f91d18d2c8f/raw/dba6b96f5b6fcf8c889503f71d8deef5c0934ad6/src.signals-apple.c.diff

### 2. homebrew-julia の Formula を修正

79行目あたり（`patches` メソッド内）に1行追加：

```bash
$ brew edit julia
 : 
  # Here we build up a list of patches to be applied
  def patches
    patch_list = []

    # First patch fixes hardcoded paths to deps in deps/Makefile
    patch_list << "https://gist.github.com/staticfloat/3806093/raw/cb34c7262b9130f0e9e07641a66fccaa0d08b5d2/deps.Makefile.diff"

    # Second patch fixes suitesparse shenanigans
    if build.head?
      patch_list << "https://gist.github.com/staticfloat/4f8248add3ed27ba250c/raw/0d180c11d4131a53c3361d71ba21aac3f0ef343e/Makefile.diff"
      patch_list << "https://gist.githubusercontent.com/antimon2/412db3042f91d18d2c8f/raw/dba6b96f5b6fcf8c889503f71d8deef5c0934ad6/src.signals-apple.c.diff"
      # ↑ココ
    end
    
    return patch_list
  end
 : 
```

こちらも diff のカタチでも示しておきます：

```diff:julia.rb.diff
diff --git a/julia.rb b/julia.rb
index 0d4c6cc..d74e7c8 100644
--- a/julia.rb
+++ b/julia.rb
@@ -76,6 +76,7 @@ class Julia < Formula
     # Second patch fixes suitesparse shenanigans
     if build.head?
       patch_list << "https://gist.github.com/staticfloat/4f8248add3ed27ba250c/raw/0d180c11d4131a53c3361d71ba21aac3f0ef343e/Makefile.diff"
+      patch_list << "https://gist.githubusercontent.com/antimon2/412db3042f91d18d2c8f/raw/dba6b96f5b6fcf8c889503f71d8deef5c0934ad6/src.signals-apple.c.diff"
     end

     return patch_list
```

### 3. （再）インストール

古いバージョンが削除済み、もしくは新規にインストールする場合は、`reinstall` を `install` と読み替えてください。

```bash
$ brew reinstall --HEAD julia
```

「Formula が変更されているよ」という Warning が出ます。まーそうですね、今回は無視。もしちゃんとやりたかったら、リポジトリを Fork してから修正してそいつを改めて `brew tap` した上で実施すべきなんでしょうね。
とりあえずビルド出来るかが優先だったので。

で。見事ビルド成功！

### 4. 確認

```bash
$ which julia
/usr/local/bin/julia
$ julia --version
julia version 0.4.0-pre
$ julia
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.4.0-pre+7296 (2015-09-05 00:51 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit a246c11* (0 days old master)
|__/                   |  x86_64-apple-darwin12.6.0

julia>
```

うぉ。バージョンが 0.4.0-pre になってる。

## まとめ

C言語ソースレベルの理解が完全ではないのですが、ビルド中に特に警告もエラーも出ず。色々動かしてみて動作的にも問題はない模様。
ですが本家に確認したわけではないので、実施する場合は個人の責任でお願いします。あくまで参考までに。

[^1]: issue もしくは pull request 投げといた方が良いかもだけどまた落ち着いてから。