しょぼいマシンで自作プログラミング言語を作ってみる (2)
続きに手を付ける前に……
LLVMをhomebrew版からmacports版に
思うところあって、自分のパッケージ構成管理をhomebrewからMacPortsに変えてみました。
MacPortsのLLVM、LLVMのコア部分とClang部分は別パッケージ扱いのようです。
$ sudo port install llvm-19 mlir-19 clang-19
$ sudo port select --set llvm mp-llvm-19
$ sudo port select --set clang mp-clang-19
これでhomebrew版と同様に使えるはずです。
$ clang --version
clang version 19.1.2
Target: x86_64-apple-darwin20.6.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-19/bin
うん。とりあえず、バージョンも同じですね。よしよし。
そうそう。MLIRなるLLVMのサブパッケージがあるので入れてみました。
ええっと、今更ながらLLVMとかMLIRの詳しい話は……どうしたって?
うん。たぶん、他の人が詳しく説明してくれるでしょうからしません。
開発用パッケージも念の為
開発用パッケージも念の為、落としましょうか。
CMake用のファイルが入っているっぽいですよ。
$ sudo port install llvm-devel mlir-devel
チュートリアルが当てにならない
ちょっとした愚痴
いや、チュートリアルが全然当てにならないのが困りました。
あれはgitからプロジェクトディレクトリを一式落として、プロジェクトディレクトリ内で完結することを前提として書かれているんです。
CMakeの内容もそれを前提としているし、ソースコードも同様だったりするんですよね。
LLVM用ライブラリのヘッダインクルードもこんな感じ。
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
brewなりMacPortsなりapt-getなりyumなりでインストールすることを前提とするなら、"(ダブルクォート)ではなく<>(山カッコ)でincludeすべきなのに……。
CMakeLists.txtも同様。あれではtutorialのビルドもままならないです。
ということでソースは参考にするにとどめて、一から作ることとしましょう。
CMakeLists.txtをカスタマイズしよう。
# cmake option from execute command output
if(WIN32)
set(EXEC_TERMINAL_CMD "cmd")
set(EXEC_TERMINAL_CMD_OPT "/c")
set(EXEC_CMD_EXT ".exe")
else()
set(EXEC_TERMINAL_CMD "bash")
set(EXEC_TERMINAL_CMD_OPT "-c")
set(EXEC_CMD_EXT "")
endif()
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "which${EXEC_CMD_EXT} clang"
OUTPUT_VARIABLE CMAKE_C_COMPILER
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "which${EXEC_CMD_EXT} clang++"
OUTPUT_VARIABLE CMAKE_CXX_COMPILER
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "which${EXEC_CMD_EXT} llvm-ar"
OUTPUT_VARIABLE CMAKE_CXX_COMPILER_AR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "which${EXEC_CMD_EXT} llvm-ranlib"
OUTPUT_VARIABLE CMAKE_CXX_COMPILER_RANLIB
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "llvm-config${EXEC_CMD_EXT} --includedir"
OUTPUT_VARIABLE LLVM_INCLUDEDIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${EXEC_TERMINAL_CMD} ${EXEC_TERMINAL_CMD_OPT} "llvm-config${EXEC_CMD_EXT} --libfiles"
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
これをCMakeLists.txtに組み込んで、あとはよしなにやったらビルドできましたぞ!!
コンパイラのパスやインクルードパスなどをコマンドラインから取得するのが上記の内容ですね。
あとはCMakeLists.txtのお作法に合わせて、makeの設定をゴニョゴニョすればビルドされます。
llvmの関数もこんな感じで使えました。
#include <llvm/Support/raw_ostream.h>
int main(int argc, char **argv) {
llvm::outs() << "hoge\n";
return 0;
}
ということで、実装を始めましょうか。