//RakefileFormat
//3. Rakefile Format
//3. Rakefile のフォーマット

//!3.1 Introduction
!3.1 はじめに
//First of all, there is no special format for a Rakefile. A Rakefile contains executable Ruby code. Anything legal in a ruby script is allowed in a Rakefile.
まず第一に、Rakefile 専用のフォーマットというのは存在しません。Rakefile は実行可能な Ruby のコードで構成されます。ruby スクリプトとして正当であれば、Rakefile としても正当です。

//Now that we understand there is no special syntax in a Rakefile, there are some conventions that are used in a Rakefile that are a little unusual in a typical Ruby program. Since a Rakefile is tailored to specifying tasks and actions, the idioms used in a Rakefile are designed to support that.
専用のフォーマットはないと説明しましたが、典型的な Ruby プログラムではあまり見かけない、ちょっと変わったイディオムを使用することがあります。Rakefile は、タスクとアクションを合わせて指定するために、その、ちょっと変わったイディオムをサポートしています。

//So, what goes into a Rakefile?
それでは、Rakefile はどのように書くのでしょうか?

//!3.2 Tasks
!3.2 タスク
//Tasks are the main unit of work in a Rakefile. Tasks have a name (usually given as a symbol or a string), a list of prerequisites (more symbols or strings) and a list of actions (given as a block).
タスクは Rakefile の基本となる作業単位です。タスクは、タスク名(通常は、シンボルか文字列)、前提条件リスト(これも、シンボルか文字列)、アクション(ブロックとして与えられる)を持ちます。

//!!Simple Tasks
!!単純なタスク
//A task is declared by using the task method. task takes a single parameter that is the name of the task.
タスクは task メソッドを使って宣言されます。task は引数に、タスク名を一つ取ります。

 task :name

//!!Tasks with Prerequisites
!!前提条件付きのタスク
//Any prerequisites are given as a list (inclosed in square brackets) following the name and an arrow (=>).
タスク名と => の後のリスト([ ]の中)に、どのような前提条件でも、指定することが出来ます。

 task :name => [:prereq1, :prereq2]

//NOTE: Although this syntax looks a little funky, it is legal Ruby. We are constructing a hash where the key is :name and the value for that key is the list of prerequisites. It is equivalent to the following …
'''注意!!''': この構文はちょっと変わって見えますが、正当な Ruby のコードです。キーが :name 、値が前提条件([ ]の部分)の Hash を作っているだけです。要は、以下と同等です。

 hash = Hash.new
 hash[:name] = [:prereq1, :prereq2]
 task(hash)

//!!Tasks with Actions
!!アクション付きのタスク
//Actions are defined by passing a block to the task method. Any Ruby code can be placed in the block. The block may reference the task object via the block paramter..
アクションは task メソッドのブロックの中に定義されます。どのような Ruby コードでもかまいません。ブロックパラメータを使って、task オブジェクトの参照を渡すこともあります。

// task :name => [:prereq1, :prereq2] do |t|
//   # actions (may reference t)
// end
 task :name => [:prereq1, :prereq2] do |t|
   # アクション(t を利用できます。)
 end

//!!Multiple Definitions
!!複数回の定義
//A task may be specified more than once. Each specification adds its prerequisites and actions to the existing definition. This allows one part of a rakefile to specify the actions and a different rakefile (perhaps separately generated) to specify the dependencies.
タスクが2回以上定義されることがあります。その場合、定義が実行されるたびに、前提条件とアクションを、既存の定義に追加します。これは、アクションの指定と、依存関係宣言を、別の場所(おそらく別のファイル)で定義することを許可するためです。

//For example, the following is equivalent to the single task specification given above.
例えば下記は、上の項(アクション付きのタスクの項)で定義されたタスクと同等のものです。

// task :name
// task :name => [:prereq1]
// task :name => [:prereq2]
// task :name do |t|
//   # actions
// end
 task :name
 task :name => [:prereq1]
 task :name => [:prereq2]
 task :name do |t|
   # アクション
 end

//!3.3 File Tasks
!3.3 ファイルタスク
//Some tasks are designed to create a file from one or more other files. Tasks that generate these files may be skipped if the file already exists. File tasks are used to specify file creation tasks.
いくつかのタスクは、あるファイルから別のファイルを生成します。ファイルが既に存在すれば、そのタスクは省略されるかもしれません。ファイルタスクはファイル生成処理に使用されます。

//File tasks are declared using the file method (instead of the task method). In addition, file tasks are usually named with a string rather than a symbol.
ファイルタスクは file メソッド(task メソッドの代わり)を使用してし定義されます。なお、ファイルタスクのタスク名には、シンボルではなく文字列が使用されるのが一般的です。

//The following file task creates a executable program (named prog) given two object files name a.o and b.o. The tasks for creating a.o and b.o are not shown.
以下のファイルタスクは、実行形式ファイル(prog)を生成するために、2つのオブジェクトファイル、 a.o と b.o が存在することを想定しています。このタスクでは a.o と b.o の生成については触れません。

 file "prog" => ["a.o", "b.o"] do |t|
   sh "cc -o #{t.name} #{t.prerequisites.join(' ')}" 
 end

//!3.4 Directory Tasks
!3.4 ディレクトリタスク
//It is common to need to create directories upon demand. The directory convenience method is a short-hand for creating a FileTask that creates the directory. For example, the following declaration …
ディレクトリの作成が必要となるケースはよくあることです。directory メソッドは、ファイルタスクに足りない、ディレクトリ作成処理を実施します。例えば、

 directory "testdata/examples/doc"

//is equivalent to …
と、以下は同等です。

 file "testdata"              do |t| mkdir t.name end
 file "testdata/examples"     do |t| mkdir t.name end
 file "testdata/examples/doc" do |t| mkdir t.name end

//The directory method does not accept prerequisites or actions, but both prerequisites and actions can be added later. For example …
directory メソッドには、前提条件やアクションは指定できませんが、後から追加することなら可能です。例えば以下のようにします。

 directory "testdata" 
 file "testdata" => ["otherdata"]
 file "testdata" do
   cp Dir["standard_data/*.data"], "testdata" 
 end

//!3.5 Rules
!3.5 ルール
//When a file is named as a prerequisite, but does not have a file task defined for it, Rake will attempt to synthesize a task by looking at a list of rules supplied in the Rakefile.
前提条件にファイル名が未指定の場合、Rake はルールリストから対応するタスクを探し出そうとします。

//Suppose we were trying to invoke task “mycode.o”, but no task is defined for it. But the rakefile has a rule that look like this …
mycode.o が未定義の状態で、mycode.o タスクが実施されるとします。その場合でも rakefile には、以下のようなルールが存在します。

 rule '.o' => ['.c'] do |t|
   sh "cc #{t.source} -c -o #{t.name}" 
 end

//This rule will synthesize any task that ends in “.o”. It has a prerequisite a source file with an extension of “.c” must exist. If Rake is able to find a file named “mycode.c”, it will automatically create a task that builds “mycode.o” from “mycode.c”.
上記のルールは、.o で終わるすべてのタスクに対応します。それは、前提条件に、拡張子 .c のソースファイルが存在することを指定します。mycode.c というファイルを発見すれば、mycode.c から mycode.o を生成するタスクを自動的に作り出します。

//If the file “mycode.c” does not exist, rake will attempt to recursively synthesize a rule for it.
mycode.c が見つからない場合は、再帰的に、ルールに対応するタスクがないかを探そうとします。

//When a task is synthesized from a rule, the source attribute of the task is set to the matching source file. This allows us to write rules with actions that reference the source file.
ルールに対応するタスクが見つかった時、参照(ブロックパラメータ)に、source 属性がセットされます。これは、アクション内でで、ソースファイルを扱えるようにするためです。

//!3.6 Advanced Rules
!3.6 高度なルール
//Any regular expression may be used as the rule pattern. Additionally, a proc may be used to calculate the name of the source file. This allows for complex patterns and sources.
ルールパターンには正規表現が使用できます。ソースファイル名を求めるのに proc 利用されることもあります。これは、複雑なルールパターンや、複雑な手順でソースファイル名を求めるのに対応するためです。

//The following rule is equivalent to the example above.
以下のルールは、上の項(ルールの項)と同等です。

 rule( /\.o$/ => [
   proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
 ]) do |t|
   sh "cc #{t.source} -c -o #{t.name}" 
 end   

//NOTE: Because of a quirk in Ruby syntax, parenthesis are required on rule when the first argument is a regular expression.
'''注意!! : '''Ruby の都合で、ルールに対する最初の引数が正規表現の場合、括弧を省略することは出来ません。

//The following rule might be used for Java files …
以下のルールを、Java ファイルのために利用することがあるかもしれません。

 rule '.java' => [
   proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
 ] do |t|
   java_compile(t.source, t.name)  
 end

//NOTE: java_compile is a hypothetical method that invokes the java compiler.
'''注意!! : '''java_compile は、Java コンパイラを呼び出す命令の例えです。

//!3.7 Importing Dependencies
!3.7 ファイル読み込みの依存関係
//Any ruby file (including other rakefiles) can be included with a standard Ruby require command. The rules and declarations in the required file are just added to the definitions already accumulated.
ruby ファイル(別の rakefile も含む)でありさえすれば、require でそのファイルを読み込むことが出来ます。取り込まれたルールと宣言は、既存の定義に追加されます。

//Because the files are loaded before the rake targets are evaluated, the loaded files must be “ready to go” when the rake command is invoked. This make generated dependency files difficult to use. By the time rake gets around to updating the dependencies file, it is too late to load it.
ファイルの読み込みは、タスクが評価される前に実施されるので、読み込まれるファイルは、あらかじめ準備されている必要があります。このことは、取り扱いの難しい依存ファイルを作る原因になりました。ファイルの読み込みに、準備が間に合わない状態です。

//The import command addresses this by specifying a file to be loaded after the main rakefile is loaded, but before any targets on the command line are specified. In addition, if the file name matches an explicit task, that task is invoked before loading the file. This allows dependency files to be generated and used in a single rake command invocation.
import メソッドは、すべての rakefile が読み込まれた後、rake コマンドで指定されたターゲットより先に実施されます。しかも、import メソッドに指定したファイル名にマッチするタスクがある場合は、ファイルを読み込む前に、そのタスクを実施します。このことにより、依存ファイルの生成と読み込みを、一回の rake コマンドで行うことが可能になります。

//Example:
*''例''

 require 'rake/loaders/makefile'
 
 file ".depends.mf" => [SRC_LIST] do |t|
   sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" 
 end
 
 import ".depends.mf" 

//If “.depends” does not exist, or is out of date w.r.t. the source files, a new “.depends” file is generated using makedepend before loading.
.depends.mf が存在しない場合や、ソースファイルに対して古い状態である場合は、ファイルが取り込まれる前に、新しい .depends.mf を生成します。

//!3.8 Comments
!3.8 コメント
//Standard Ruby comments (beginning with ”#”) can be used anywhere it is legal in Ruby source code, including comments for tasks and rules. However, if you wish a task to be described using the ”-T” switch, then you need to use the desc command to describe the task.
Ruby のコメント(# から始まる)は、どこでも使用することができます。タスクやルールにコメントを使用しても問題はありません。しかし、タスクが -T オプション(後述します)に対応することを望む場合は、desc メソッドを使用する必要があります。

//Example:
*''例''

// desc "Create a distribution package" 
// task :package => [ ... ] do ... end
 desc "配布パッケージの作成" 
 task :package => [ ... ] do ... end

//The ”-T” switch (or ”―tasks” if you like to spell things out) will display a list of tasks that have a defined comment. If you use desc to describe your major tasks, you have a semi-automatic way of generating a summary of your Rake file.
-T(こだわり派は --task)オプションは、タスクに定義されたコメントを画面にリストアップします。desc メソッドでコメントを定義してあれば、半自動的に要約が生成されます。

 traken$ rake -T
 (in /home/.../rake)
 rake clean            # Remove any temporary products.
 rake clobber          # Remove any generated file.
 rake clobber_rdoc     # Remove rdoc products
 rake contrib_test     # Run tests for contrib_test
 rake default          # Default Task
 rake install          # Install the application
 rake lines            # Count lines in the main rake file
 rake rdoc             # Build the rdoc HTML Files
 rake rerdoc           # Force a rebuild of the RDOC files
 rake test             # Run tests
 rake testall          # Run all test targets

//Only tasks with descriptions will be displayed with the ”-T” switch. Use ”-P” (or ”―prereqs”) to get a list of all tasks and their prerequisites.
-T オプションでは、タスクのコメントのみがリストアップされます。前提条件も合わせてリストアップしたい場合は -P(もしくは --prereqs)オプションを使用してください。

//!3.9 Odds and Ends
!3.9 その他
//!!do/end verses { }
!!do/end か { } か

//Blocks may be specified with either a do/end pair, or with curly braces in Ruby. We strongly recommend using do/end to specify the actions for tasks and rules. Because the rakefile idiom tends to leave off parenthesis on the task/file/rule methods, unusual ambiguities can arise when using curly braces.
Ruby のブロックは、do/end か { } のどちらかで指定されますが、rakefile でタスクやルールを指定する場合は、do/end を使用することを、強くおすすめします。rakefile で、task/file/rule メソッドを使用する場合には、括弧を省略することが多いため、{ } を使用してしまうと、期待した動作にならないことがあるからです。

//For example, suppose that the method object_files returns a list of object files in a project. Now we use object_files as the prerequistes in a rule specified with actions in curly braces.
例えば、プロジェクトのオブジェクトファイルのリストを返す、object_files メソッドがあるとします。そして、ルールの前提条件にその object_files メソッドが使用され、アクションの指定には { } を使用するとします。

// # DON'T DO THIS!
// file "prog" => object_files {
//   # Actions are expected here (but it doesn't work)!
// }
 # このようにしてはいけません!!
 file "prog" => object_files {
   # ここにアクションが定義されると思いますが、うまく動いてくれません。
 }

//Because curly braces have a higher precedence than do/end, the block is associated with the object_files method rather than the file method.
{ } は do/end より優先順位が高いため、{ } のブロックを、file メソッドのブロックではなく、object_files メソッドのブロックとして扱われてしまいます。

//This is the proper way to specify the task …
以下が、タスクを指定する適切な方法です。

// # THIS IS FINE
// file "prog" => object_files do
//   # Actions go here
// end
 # このようにしてください!!
 file "prog" => object_files do
   # ここにアクションで、うまくいきます。。
 end