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.
Instance Attribute Summary collapse
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_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 ⇒ ManifestEntry
The manifest entry from the last time this task was run, usually read off the filesystem.
-
#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 is needed if it has no manifest entry from a previous run, or if one of its dynamic dependencies has been modified.
Methods inherited from FileTask
Instance Attribute Details
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.
87 88 89 90 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 87 def dynamic(&block) @dynamic = block self end |
#dynamic_prerequisites ⇒ Array[String]
At runtime, we will call this to get dynamic prerequisites.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 101 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.
28 29 30 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 28 def has_dynamic_block? !!@dynamic end |
#invoke_dynamic_block ⇒ Object
Invoke the task’s dynamic block.
93 94 95 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 93 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.
118 119 120 121 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 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 118 def invoke_prerequisites(task_args, invocation_chain) super # If we don't have a dynamic block, just act like a regular FileTask. return unless has_dynamic_block? # 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)) 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.
150 151 152 153 154 155 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 150 def invoke_with_call_chain(*) super return unless has_dynamic_block? manifest_entry.mtime = mtime_or_now(name) end |
#last_manifest_entry ⇒ ManifestEntry
Returns the manifest entry from the last time this task was run, usually read off the filesystem.
42 43 44 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 42 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.
49 50 51 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 49 def manifest_entry manifest[name] end |
#manifest_entry=(new_entry) ⇒ ManifestEntry
Set the current manifest entry,
57 58 59 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 57 def manifest_entry=(new_entry) manifest[name] = new_entry end |
#needed? ⇒ Boolean
In addition to the regular FileTask check, A DynamicFileTask is needed if it has no manifest entry from a previous run, or if one of its dynamic dependencies has been modified.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/rake-pipeline/dynamic_file_task.rb', line 66 def needed? return true if super # 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) > time end # Otherwise, it's not needed false end |