前置き
OSX 10.8.5 の入っている Mac で、「そういえば Julia HEAD 最新にしてなかった」と brew reinstall --HEAD julia
しようとしたら、make
フェーズでエラーとなりビルド出来ませんでした。
@chezou さんの記事「homebrewでjuliaのHEADのインストールに失敗した時にするといいこと」を実施してもうまくいかず。
「何コレ?」と色々調べてなんとか自己解決したので、記録として残しておきます1。
手っ取り早く解決方法だけ知りたい方は 解決 までジャンプしてください。
環境
- Mac OSX 10.8.5
- Homebrew
- homebrew-julia
環境補足
過去に homebrew-julia で Julia HEAD をインストールしてある前提です(過去記事参照)。
次章以降は少なくとも brew tap staticfloat/julia
を実施済である前提で進めます。
起きていた現象
うっかりログを消してしまったのですが、起きていた現象としては、以下のサイトと全く同じ。
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 --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行追加:
$ 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 --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
と読み替えてください。
$ brew reinstall --HEAD julia
「Formula が変更されているよ」という Warning が出ます。まーそうですね、今回は無視。もしちゃんとやりたかったら、リポジトリを Fork してから修正してそいつを改めて brew tap
した上で実施すべきなんでしょうね。
とりあえずビルド出来るかが優先だったので。
で。見事ビルド成功!
4. 確認
$ 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言語ソースレベルの理解が完全ではないのですが、ビルド中に特に警告もエラーも出ず。色々動かしてみて動作的にも問題はない模様。
ですが本家に確認したわけではないので、実施する場合は個人の責任でお願いします。あくまで参考までに。
-
issue もしくは pull request 投げといた方が良いかもだけどまた落ち着いてから。 ↩