2014年6月26日木曜日

Rake Part 6: Clean and Clobber 翻訳

Avdi GrimmLearn Advanced Rake in 7 Episodesを、本人の許可を得て翻訳します。以下、Part 6の翻訳です。



もしあなたが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か所で、これらのファイルをCLEANCLOBBERのリストに追加することもできたかもしれません。しかし、ファイルを生成する各ルールのすぐ隣にそれぞれを追加することにより、これらのルールを完全に削除したり修正したりする時に、CLEANリストまたはCLOBBERリストの関連するエントリーを変更することを覚えている可能性が高くなります。


コマンドラインで、rake -Tコマンド使って使用可能なタスクの一覧を表示するようRakeに告げると、定義していないcleanclobberという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独自のクリーンアップタスクを書く必要はありませんでした。適切なファイルあるいはファイルパターンをCLEANCLOBBERのリストに追加しただけで、あとはRakeにしてもらいました。ハッピーハッキング!




Rakeについてのエピソード・文章を楽しんでいただけたことを願っている。もし今日、何かしら学んだのであれば、Jimの遺産である教育プログラムの継続を支援するため、the Weirich Fundに寄付することにより「恩送りすること(訳注:原文は"paying it forward")」を検討して欲しい。もし、今回のようなビデオをもっと見たければ、RubyTapasをじっくり見てほしい。シリーズが完結するまで、ほぼ毎日公開していくつもりなので、ほどなくご確認を!

P.S. 特に興味深い方法でRakeを使っているなら、連絡して欲しい

関連する投稿:
  1. Rake Part 5: File Operations
  2. Rake Part 2: File Lists
  3. Rake Part 4: Pathmap

0 件のコメント:

コメントを投稿