もしあなたがRubyプログラマーなら、Rake(故Jim Weirichによって作られたビルドユーティリティー)をほぼ確実に使ったことがあるだろう。しかし、Rakeがいかにパワフルでフレキシブルなツールになりうるかということは理解していないかもしれない。実際、私は、Quarto(自作のe-book製作ツールチェーン)の土台としてRakeを使うと決めるまで理解していなかった。
この投稿はRakeについてのシリーズの一部で、基本から始めて高度な使用法に進む。2013年の8月から9月に購読者に向け公開されたRubyTapasビデオのシリーズのひとつをもとにしている。各投稿はビデオから始まり、ビデオより文字を好む人のためにスクリプトが続く。
これらのエピソードを無料で公開するにあたり、より多くの人々が、この広く行き渡っているが過小評価されているツールのすべての能力を知り愛するようになることを願う。もしあなたがRakeに感謝するのであれば、Jimへの追悼としてthe Weirich Fundへの寄付を検討して欲しい。
前回のエピソードでは、ビルドスクリプトの成果物をクリーンアップするRakeタスクを定義しました。再帰的に“outputs”ディレクトリを削除する単純な方法でこれを実現しました。
task :clean do
rm_rf "outputs"
end
時にはクリーンアップはこれほど単純ではありません。今日は、これまで開発してきた
Rakefile
をいくらか修正したバージョンから始めましょう。以前と同じように、MarkdownファイルをHTMLに変換しています。直前のエピソードと異なるのは、HTMLファイルがソースファイルと同じディレクトリに生成されることです。つまり、ソースディレクトリと出力ディレクトリは分かれていません。
MarkdownファイルをHTMLにビルドするルールに加え、いくつかの新しいルールも追加しました。すべてのHTMLフラグメントファイルを単一の
book.html
に結合するルールがあります。そして、Calibre
電子書籍パッケージのebook-convert
コマンドを使ってbook.html
をEPUBフォーマットの電子書籍に変換するルールがあります。最後に、Amazonのkindlegen
を使って、受け取ったEPUBファイルをKindle互換の.mobi
ファイルに変換するルールがあります。最後の調整として、
:default
ルールを.epub
ターゲットと.mobi
ターゲットに依存するよう更新しています。
SOURCE_FILES = Rake::FileList.new("**/*.md", "**/*.markdown") do |fl|
fl.exclude("~*")
fl.exclude(/^scratch\//)
fl.exclude do |f|
`git ls-files #{f}`.empty?
end
end
task :default => ["book.epub", "book.mobi"]
task :html => SOURCE_FILES.ext(".html")
rule ".html" => ->(f){source_for_html(f)} do |t|
sh "pandoc -o #{t.name} #{t.source}"
end
file "book.html" => SOURCE_FILES.ext(".html") do |t|
chapters = FileList["**/ch*.html"]
backmatter = FileList["backmatter/*.html"]
sh "cat #{chapters} #{backmatter} > #{t.name}"
end
file "book.epub" => "book.html" do |t|
sh "ebook-convert book.html #{t.name}"
end
file "book.mobi" => "book.epub" do |t|
sh "kindlegen book.epub -o #{t.name}"
end
def source_for_html(html_file)
SOURCE_FILES.detect{|f| f.ext('') == html_file.ext('')}
end
このビルドスクリプトは、2つの異なるカテゴリのファイルを生成します。
- 中間ファイル。すべてのHTMLファイルはこのカテゴリに含まれます。これらのファイルは、全ビルドプロセスが終了すると必要がなくなるので、一時ファイルとも呼ばれます。
- 成果物である電子書籍ファイル。これらのファイルは、全プロセスの最終目的です。
プロジェクトの自動クリーンアップについて言うなら、これらの2つの異なるカテゴリのファイルを別々に取り扱いたいでしょう。電子書籍の成果物はそのまま残し、中間ファイルだけをクリーンアップしたいこともあれば、すべての生成されたファイルを一掃し、白紙の状態から始めたいこともあります。
これらの2つのタイプのクリーンアップを扱うタスクを書くこともできます。あるいは、Rakeのオプションライブラリ
rake/clean
を使うこともできます。rake/clean
を使うには、まずrequireします。そうすると、新たなグローバル定数CLEAN
を使用できるようになります。この定数はFileList
であり、最初は空です。
require 'rake/clean'
CLEAN # => []
CLEAN.class # => Rake::FileList
どのファイルが中間ファイルであるかをRakeに告げるために
CLEAN
リストを使用できます。まず、Markdownファイルから生成されたHTMLファイルのリストを追加しましょう。CLEAN.include(SOURCE_FILES.ext(".html"))
そして結合されたbook.html
をリストに追加します。
file "book.html" => SOURCE_FILES.ext(".html") do |t|
chapters = FileList["**/ch*.html"]
backmatter = FileList["backmatter/*.html"]
sh "cat #{chapters} #{backmatter} > #{t.name}"
end
CLEAN.include("book.html")
次に、ファイルを
CLOBBER
と呼ばれる他のリストに追加します。このリストはどのファイルが最終成果物であるかをRakeに告げます。CLOBBER
リストに.epub
および.mobi
の電子書籍ファイルを追加します。
file "book.epub" => "book.html" do |t|
sh "ebook-convert book.html #{t.name}"
end
CLOBBER << "book.epub"
file "book.mobi" => "book.epub" do |t|
sh "kindlegen book.epub -o #{t.name}"
end
CLOBBER << "book.mobi"
Rakefile
の1か所で、これらのファイルをCLEAN
とCLOBBER
のリストに追加することもできたかもしれません。しかし、ファイルを生成する各ルールのすぐ隣にそれぞれを追加することにより、これらのルールを完全に削除したり修正したりする時に、CLEAN
リストまたはCLOBBER
リストの関連するエントリーを変更することを覚えている可能性が高くなります。コマンドラインで、
rake -T
コマンド使って使用可能なタスクの一覧を表示するようRakeに告げると、定義していないclean
とclobber
という2つのタスクが使用できることが確認できます。電子書籍ファイルを生成するために、まず
rake
を引数なしで実行します。プロジェクト内のファイルを一覧表示すると、様々な.html
中間ファイルと最終成果物である.epub
や.mobi
ファイルが確認できます。
$ rake
$ tree
.
├── backmatter
│ ├── appendix.html
│ └── appendix.md
├── book.epub
├── book.html
├── book.mobi
├── ch1.html
├── ~ch1.md
├── ch1.md
├── ch2.html
├── ch2.md
├── ch3.html
├── ch3.md
├── ch4.html
├── ch4.markdown
├── Rakefile
├── scratch
│ └── test.md
└── temp.md
rake clean
を実行しても、何も出力されません。しかし、プロジェクトの中身を再び一覧表示すると、すべての.html
ファイルが消去されていることが確認できます。
$ rake clean
avdi@hazel:~/Dropbox/rubytapas/134-rake-clean/project$ tree
.
├── backmatter
│ └── appendix.md
├── book.epub
├── book.mobi
├── ~ch1.md
├── ch1.md
├── ch2.md
├── ch3.md
├── ch4.markdown
├── Rakefile
├── scratch
│ └── test.md
└── temp.md
そして
rake clobber
を実行すると、見つからなかったファイルについて、たくさんの警告が表示されます。これは、clobber
はまずclean
タスクを実行しますが、そのタスクはすでに実行されているからです。このタスクはすでに存在しないたくさんのファイルを削除しようとしますが、心配ありません。これらの警告は無害であり、安心して無視できます。clobber
の実行後にプロジェクトの中身を見てみると、中間ファイルと共に電子書籍ファイルがなくなっていることが確認できます。rake/clean
については以上ですが、ビルドされたファイルを削除するためにproject独自のクリーンアップタスクを書く必要はありませんでした。適切なファイルあるいはファイルパターンをCLEAN
とCLOBBER
のリストに追加しただけで、あとはRakeにしてもらいました。ハッピーハッキング!Rakeについてのエピソード・文章を楽しんでいただけたことを願っている。もし今日、何かしら学んだのであれば、Jimの遺産である教育プログラムの継続を支援するため、the Weirich Fundに寄付することにより「恩送りすること(訳注:原文は"paying it forward")」を検討して欲しい。もし、今回のようなビデオをもっと見たければ、RubyTapasをじっくり見てほしい。シリーズが完結するまで、ほぼ毎日公開していくつもりなので、ほどなくご確認を!
P.S. 特に興味深い方法でRakeを使っているなら、連絡して欲しい。
関連する投稿:
0 件のコメント:
コメントを投稿