この記事は Crystal Advent Calendar 2018 の21日目を埋める記事です。
Crystalのビルドツールは何をつかっていますか?
自分は、以下のような編纂をたおどり、今はlucky_cliをビルドツールとして使用しています。
Shell -> Makefile(Cmake) -> ※cake -> lucky_cli
lucky_cliはWeb frameworkであるluckyのモジュールの1つです。
簡単にluckyの特徴を説明しますと、Railsをほどよくリスペクトして、合理的な独自機能の導入、品質を意識し、Bugを極力コンパイル時に排除することに力をいれているWeb frameworkです。
lucky frameworkの構造
lucky自体は主要な機能がモジュール単位で分割されています。lucky_cliもその1つで単体での利用も可能です。
- lucky: lucky frameworkの本体
- lucky_cli: lucky frameworkのタスクマネージャー
- lucky_record: DB、ORM
- lucky_flow: 自動ブラウザテスト、E2Eテスト
- lucky_router: URLルーティング
使い方
lucky_cliのインストールが完了していること前提で、まずは作成されたばかりのプロジェクトフォルダ内で、タスクファイルを作成します。
lucky_cli init
以下のような選択肢がでますので、 tasks.cr
を選択する
Full web project, or just tasks.cr file? (web or tasks.cr)
これで、タスクファイルのテンプレートができあがります。
require "lucky_cli"
# Uncomment to require your lib or app's source code
# require "./src/my_project_name"
# Uncomment this to include tasks from the tasks directory of your project
# If you have a lot of tasks, this can be cleaner than putting them in this file
# require "./tasks/**"
・
・
・
以下のコメントアウトを外して、カレントディレクトリに tasks/
ディレクトリを作成します。
#require "./tasks/**"
mkdir ./tasks
このtasksディレクトリのなかに、tasks.crのコメントを参考にビルドファイルを作成していきます。
試しに、以下のようなtasks/build.crファイルを作成してみます。
banner macro は lucky --help
した際のタスク説明になるので、適当に説明分を記入しておきます。タスクを定義するクラス(ここではBuild)は必ず、LuckyCli::Taskクラスを継承しないといけません。実際のビルド処理の内容は、callメソッドが実行します。それ以外は
自由に拡張できます。Buildタスクで初期化入れたい場合は、constructorが作成できます。
class Build < LuckyCli::Task
banner "Build Crystal program files"
def call
puts "Build success!"
end
end
lucky --helpでさきほど記述した、タスクの説明(banner)が表示されるので、第3者の人にも何を行うタスクなのか伝わりやすいです。
$ lucky --help
Available tasks:
▸ build Build Crystal program files
そして、後はコンソール上でluckyコマンドを実行するだけで、こんなに簡単にビルドツールがつくれます。
$ lucky build
Build success!
lucky_cliの一番のメリットは自由度の高さと、拡張性だとおもいます。たとえば、
共通の処理もあるが、タスク自体は別々にわけたい、だけどタスクファイル自体を別々にわけるほどでもないケース。
BuildクラスとFullBuildクラスを用意し継承させることで、共通機能をもたせ再利用度を高めます。
class Build < LuckyCli::Task
banner "Build Crystal program files"
@app_name = "DemoApp"
def call
puts "Build success! #{@app_name}"
end
end
class FullBuild < Build
banner "Build C++/Crystal program files"
def call
puts "Full build success! #{@app_name}"
end
end
自分の構成
普段自分のタスク構成はこんな感じで使っています。ビルドだけでなく他のコマンド処理も全てlucky_cliによせることで、脳内コンテキストSwitchを最小限にしています。
tasks/
├── build.cr・・・crystal build以外にも、外部ライブラリ(C/C++)とかのビルド
├── clean.cr・・・Executable binaryのclean up ./bin/*、/tmp/*の中をclean
├── run.cr・・・crytal run、 ./bin/* の実行
├── spec.cr・・・crytal spec spec、 crystal spec spec/*のspecを実行
└── tool.cr・・・crytal tool format、 ameba(code analyze)などの便利ツールの実行
まとめ
- crytalで処理をかけるので自由度が高く、拡張しやすい
- Colorize moduleをつかえば、正常終了、異常終了でターミナルにカラー表示も簡単
- 責務毎にタスクファイルをわけれるので保守性、可読性が良い
- 巨大なMakefileのような秘伝のタレになることを防げるきがする
※cakeを辞めた理由・・・Cakefileという専用のテキストファイルを用意しないといけないのと、タスクを1ファイルに書かないといけず保守性も微妙に感じました。自分の書いたビルドコードとcakeのmacroでエラーになったり、、があり1ヶ月くらいで使用をやめました。