Class: Rake::Pipeline::DynamicFileTask
- Defined in:
- lib/rake-pipeline/dynamic_file_task.rb
Overview
This class extends Rake’s FileTask class to add support for dynamic dependencies. Typically, Rake handles static dependencies, where a file’s dependencies are known before the task is invoked. A DynamicFileTask also supports dynamic dependencies, meaning the file’s dependencies can be determined just before invoking the task. Because calculating a file’s dependencies at runtime may be an expensive operation (it could involve reading the file from disk and parsing it to extract dependency information, for example), the results of this calculation are stored on disk in a manifest file, and reused on subsequent runs if possible.
For example, consider this file app.c:
#include "app.h"
some_stuff();
If we have a task that compiles app.c into app.o, it needs to process app.c to look for additional dependencies specified by the file itself.
Defined Under Namespace
Classes: ManifestRequired
Instance Attribute Summary collapse
-
#last_manifest ⇒ Object
Returns the value of attribute last_manifest.
-
#manifest ⇒ Object
Returns the value of attribute manifest.
Instance Method Summary collapse
-
#dynamic(&block) ⇒ DynamicFileTask
Add a block that will return dynamic dependencies.
-
#dynamic_prerequisites ⇒ Array[String]
At runtime, we will call this to get dynamic prerequisites.
-
#has_dynamic_block? ⇒ Boolean
True if the task has a block to invoke for dynamic dependencies, false otherwise.
-
#invoke(*args) ⇒ Object
Invoke this task.
-
#invoke_dynamic_block ⇒ Object
Invoke the task’s dynamic block.
-
#invoke_prerequisites(task_args, invocation_chain) ⇒ Object
Override rake’s invoke_prerequisites method to invoke static prerequisites and then any dynamic prerequisites.
-
#invoke_with_call_chain ⇒ Object
After invoking a task, add the mtime of the task’s output to its current manifest entry.
- #last_manifest_entry ⇒ Object
-
#manifest_entry ⇒ ManifestEntry
The manifest entry from the current manifest.
-
#manifest_entry=(new_entry) ⇒ ManifestEntry
Set the current manifest entry,.
-
#needed? ⇒ Boolean
In addition to the regular FileTask check, a DynamicFileTask should be invoked when any of it’s prerequisites are required, there is no manifest or it’s dependencies are out of date.
Methods inherited from FileTask
Instance Attribute Details
#last_manifest ⇒ Object
Returns the value of attribute last_manifest.
29 30 31 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 29 def last_manifest @last_manifest end |
#manifest ⇒ Object
Returns the value of attribute manifest.
29 30 31 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 29 def manifest @manifest end |
Instance Method Details
#dynamic(&block) ⇒ DynamicFileTask
Add a block that will return dynamic dependencies. This block can assume that all static dependencies are up to date.
91 92 93 94 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 91 def dynamic(&block) @dynamic = block self end |
#dynamic_prerequisites ⇒ Array[String]
At runtime, we will call this to get dynamic prerequisites.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 105 def dynamic_prerequisites @dynamic_prerequisites ||= begin dynamics = if has_dynamic_block? dynamic_prerequisites_from_manifest || invoke_dynamic_block else [] end # Make sure we don't dynamically depend on ourselves, as # that will create a circular reference, and that makes # everybody sad. dynamics.reject { |x| x == name } end end |
#has_dynamic_block? ⇒ Boolean
Returns true if the task has a block to invoke for dynamic dependencies, false otherwise.
33 34 35 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 33 def has_dynamic_block? !!@dynamic end |
#invoke(*args) ⇒ Object
Invoke this task. This method only checks to see if there is a manifest then delegates to super
58 59 60 61 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 58 def invoke(*args) raise ManifestRequired if has_dynamic_block? && !manifest super end |
#invoke_dynamic_block ⇒ Object
Invoke the task’s dynamic block.
97 98 99 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 97 def invoke_dynamic_block @dynamic.call(self) end |
#invoke_prerequisites(task_args, invocation_chain) ⇒ Object
Override rake’s invoke_prerequisites method to invoke static prerequisites and then any dynamic prerequisites.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 122 def invoke_prerequisites(task_args, invocation_chain) super raise ManifestRequired if has_dynamic_block? && !manifest # Retrieve the dynamic prerequisites. If all goes well, # we will not have to invoke the dynamic block to do this. dynamics = dynamic_prerequisites # invoke dynamic prerequisites just as we would invoke # static prerequisites. dynamics.each do |prereq| task = lookup_prerequisite(prereq) prereq_args = task_args.new_scope(task.arg_names) task.invoke_with_call_chain(prereq_args, invocation_chain) end # Create a new manifest entry for each dynamic dependency. # When the pipeline finishes, these manifest entries will be written # to the file system. entry = Rake::Pipeline::ManifestEntry.new dynamics.each do |dynamic| entry.deps.merge!(dynamic => mtime_or_now(dynamic).to_i) end self.manifest_entry = entry end |
#invoke_with_call_chain ⇒ Object
After invoking a task, add the mtime of the task’s output to its current manifest entry.
153 154 155 156 157 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 153 def invoke_with_call_chain(*) super manifest_entry.mtime = mtime_or_now(name).to_i end |
#last_manifest_entry ⇒ Object
52 53 54 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 52 def last_manifest_entry last_manifest[name] end |
#manifest_entry ⇒ ManifestEntry
Returns the manifest entry from the current manifest. This is the entry that will be written to disk after the task runs.
40 41 42 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 40 def manifest_entry manifest[name] end |
#manifest_entry=(new_entry) ⇒ ManifestEntry
Set the current manifest entry,
48 49 50 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 48 def manifest_entry=(new_entry) manifest[name] = new_entry end |
#needed? ⇒ Boolean
In addition to the regular FileTask check, a DynamicFileTask should be invoked when any of it’s prerequisites are required, there is no manifest or it’s dependencies are out of date.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 68 def needed? return true if super return true if prerequisites_needed? # if we have no manifest, this file task is needed return true unless last_manifest_entry # If any of this task's dynamic dependencies have changed, # this file task is needed last_manifest_entry.deps.each do |dep, time| return true if File.mtime(dep).to_i > time end # Otherwise, it's not needed false end |