この記事は「Qiita Advent Calendar 2019 DSLで自作ビルドツールを作ろう」の17日目の記事です。
17日目 ビルドルールをYAMLに書きたい 2. YAMLルールをもう少し便利に
前回、ビルドルールにYAMLルールを導入してみたのですが、いろいろと実装が途中までになっており、しかもRubyの便利な機能を使えないので結局表現が煩雑になってしまいました。
これはYAMLの制約なのでもうどうしようもないのですが、せっかく作ったので、もう少し強化してまともにビルド処理ができるようにしたいです。今回は、YAMLルールにカスタム命令を実装します。
YAMLにカスタムルールを追加してファイルの自動生成などの処理に対応する
Rumy-MakeのRubyで記述していたルールでは、ルール記法は一般化されていたので、例えばスクリプトを使用してファイルを自動生成する場合には以下のように記述していました。
make_target :gen_riscv_csr_info do depends ["../script/gen_sysreg_table.rb", "./riscv_spr_table.rb"] executes ["cd ../src && ruby -I../script/ ../script/gen_sysreg_table.rb riscv"] end
しかし、YAMLではここまで自由な書き方はできません。いろいろ考えたのですが、YAMLのライブラリビルド、実行ファイルビルドと一緒で、カスタムビルド用のルールを定義して同じように記述できるようにしました。つまり、YAMLの記法で、
- "libswimmer.a" : # ライブラリのビルドルール - type : - "lib" # ビルドタイプを"lib"に設定 - "swimmer_riscv" : # 実行ファイルのビルドルール - type : - "bin" # ビルドタイプをバイナリに設定 - "config.hpp" : # ファイル生成などの、カスタムルール - type : - "custom" # ビルドタイプをカスタムに設定
このように先頭に記述すれば、カスタムルールを定義できるようにしました。これに基づいて、rumy-yaml.rb
の実装を追加します。
src/rumy-yaml.rb
def obtain_rule (rule_array) # assert(rule_array.kind_of?(Array)) rule_array.each {|rule| ... elsif value[0].key?("type") then if value[0]["type"][0] == "lib" then make_library_rule(key, value) elsif value[0]["type"][0] == "bin" then make_execute_rule(key, value) elsif value[0]["type"][0] == "custom" then make_custom_rule(key, value) # customでmake_custom_ruleに飛ぶ ...
make_custom_rule()
は以下のような実装になっています。
def make_custom_rule(rule_name, option_hash) rule_option_hash = Hash.new rule_option_hash['executes'] = [] rule_option_hash['depends' ] = [] option_hash.each {|elem| elem.each{|key, value| rule_option_hash[key] = value } } make_target rule_name do depends rule_option_hash['depends'] executes rule_option_hash['executes'] end end
とても単純です。make_target
でルールを定義するようにしました。
これを使って、YAMLにルールを追加します。スクリプトを使って、C++のヘッダファイルを生成するルールなどです。
# RISC-Vのアーキテクチャテーブルを生成するスクリプトを実行するためのカスタムルール。 - gen_riscv_arch_info : - type : - "custom" - depends : - "../script/gen_arch_table.rb" - "../script/gen_decode_table.rb" - "../script/gen_operand_table.rb" - "../script/gen_inst_mnemonic.rb" - "riscv_arch_table.rb" - executes : - "cd ../src && ruby -I../script/ ../script/gen_arch_table.rb riscv" # シミュレータのコンフィグファイルを生成するためのカスタムルール。 - config_hpp : - type : - "custom" - executes : - "sed 's/@VERSION@/#{build_date}/g' config.h.in | sed 's/@REVISION@/#{build_version}/g' > config.hpp" # CSRテーブルを生成するためのカスタムルール。 - gen_riscv_csr_info : - type : - "custom" - depends : - "../script/gen_sysreg_table.rb" - "./riscv_spr_table.rb" - executes : - "cd ../src && ruby -I../script/ ../script/gen_sysreg_table.rb riscv"
このような実装により、YAMLによりビルドルールを記法することができました。
ただし、作っておいて何ですが結局Rumyルールよりも複雑で表現能力も低いので、あまり使わないと思います。YAMLの呼び出しと構文解析の勉強だけで、この機能はお蔵入りかな...