久しぶりに、SML#を触ってみようと、macOS Big Sur(バージョン11.6)にインストールしようとしたら上手くいかない。
公式サイトによれば以下のコマンドだけでいけるはずなのだが。。。
brew tap smlsharp/smlsharp
brew install smlsharp
上記のコマンドを実行すると以下のメッセージを吐いて止まる。
SMLSHARP_HEAPSIZE=32M:2G ./minismlsharp -B src -nostdpath -filemap=filemap -O2 -c -o src/basis/main/General.o src/basis/main/General.sml
command failed at status 1: getVersion /usr/local/Cellar/llvm/12.0.1/bin/llc -version
1行目が実行したコマンドで、2行目がエラーメッセージと思われる。
./minismlsharpというおそらくブートストラップ用のコンパイラを実行するとエラーが出るっぽい。
試しに引数なしで ./minismlsharp を実行しても同じエラーがでる。
SML#のソースコードで該当しそうなところを見てみる。
local
val version = ref NONE
val defaultTarget = ref ""
fun get () =
let
val command = [EXPAND (Config.LLC ()), ARG "-version"]
val output = ShellUtils.system command
val v = searchLine
(fn ["LLVM", "version", ""] => NONE
| ["LLVM", "version", version] => SOME version
| _ => NONE)
(#stdout output)
val t = searchLine
(fn ["Default", "target:", ""] => NONE
| ["Default", "target:", target] => SOME target
| _ => NONE)
(#stdout output)
in
case (v, t) of
(SOME ver, SOME target) =>
(version := v;
defaultTarget := target;
{version = ver, target = target})
| _ =>
raise ShellUtils.Fail
{command = "getVersion " ^ ShellUtils.join command,
status = OS.Process.failure,
output = output}
end
in
fun getVersion () =
case !version of
SOME x => x
| NONE => #version (get ())
fun getDefaultTarget () =
case !defaultTarget of
"" => #target (get ())
| s => s
end
たぶん、llcコマンドの実行結果から、LLVMのバージョンとデフォルトのターゲットを取得しようとしているのだろう。
で、うまく取得できないと例外を投げるようだ。
その後、いろいろ試した結果、LLVMのバージョンが二桁になると例外を投げてるんじゃね? と割といい加減な理由が思い浮かんだのだが、まあ、ものは試しとやってみた。
ちなみに、エラーが出ていたときに使っていたLLVMのバージョンは12で、変更後のバージョンは9にした。
実際にやった作業は、まずは
brew install flex
brew install bison
brew install llvm@9
と、LLVMのバージョン9を導入。
その途中でflexとbisonも必要そうだったのでインストールしておいた。
その次に、~/.bash_profileの最後にLLVMのバージョン9を使うように以下を追加。
# ...(略)
#
# LLVM@9
#
export PATH="/usr/local/opt/llvm@9/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/llvm@9/lib"
export CPPFLAGS="-I/usr/local/opt/llvm@9/include"
あとは、変更した.bash_profileを読み込んで、configureしてmake & make installで無事にsmlsharpがインストールできた。
source ~/.bash_profile
./configure
make
make install
蛇足
本当は、minismlsharpをビルドするときに手をいれたかったのだが、驚いたことに、 precompiled/x86_64.ll.xz
というファイルから圧縮されていたLLVM用アセンブリで書かれたソースコードを展開してビルドしてminismlsharpを作成していたので、さすがに無理でした。
ちなみに、エラーメッセージに使われている"getVersion"あたりのコードが以下のような感じ。
@14428=private unnamed_addr constant<{[4x i8],i32,i8*,void(...)*,void(...)*,i32}><{[4x i8]zeroinitializer,i32 -805306344,i8*null,void(...)*bitcast(i8*(i8*)*@_SMLL1t_153 to void(...)*),void(...)*bitcast(i8*(i8*,i8*)*@_SMLL1t_359 to void(...)*),i32 -2147483647}>,align 8
@_SMLDN9LLVMUtils13defaultTargetE_147=private global<{[4x i8],i32,i8*}><{[4x i8]zeroinitializer,i32 -1342177272,i8*getelementptr inbounds(i8,i8*getelementptr inbounds(<{[4x i8],i32,[1x i8]}>,<{[4x i8],i32,[1x i8]}>*@20270,i32 0,i32 0,i32 0),i32 8)}>,align 8
@14429=private unnamed_addr constant<{[4x i8],i32,[12x i8]}><{[4x i8]zeroinitializer,i32 -2147483636,[12x i8]c"getVersion \00"}>,align 8
こんな感じのが25万行…じゃなくて、250万行ある(一瞬、数え間違えた…)。手を入れるとか普通に無理。
(最後の行付近のスクショ)