Class: SC::Buildfile
- Inherits:
-
Object
- Object
- SC::Buildfile
- Includes:
- Commands, Cloneable, TaskManager
- Defined in:
- lib/sproutcore/buildfile.rb,
lib/sproutcore/buildfile/buildfile_dsl.rb
Overview
A Buildfile is a special type of file that contains the configurations and build tasks used for a particular project or project target. Buildfiles are based on Rake but largely use their own syntax and helper methods.
Whenever you create a project, you will often also add a Buildfile, sc-config, or sc-config.rb file. All of these files are laoded into the build system using this class. The other model objects will then reference their buildfile to extract configuration information and to find key tasks required for the build process.
Loading a Buildfile
To load a buildfile, just use the load() method:
buildfile = Buildfile.load('/path/to/buildfile')
You can also load multiple buildfiles by calling the load!() method on an exising Buildfile object or by passing a directory with several buildfiles in it:
buildfile = Buildfile.new
buildfile.load!('buildfile1').load!('buildfile2')
Defining a Buildfile
Finally, you can also define new settings on a buildfile directly. Simply use the define() method:
buildfile = Buildfile.define do
task :demo_task
end
You can also define additional tasks on an existing buildfile object like so:
buildfile = Buildfile.new
buildfile.define! do
task :demo_task
end
When you call define!() on a buildfile, the block is executed in the context of the buildfile object, just like a Buildfile loaded from disk. You will not usually use define!() on a buildfile in normal code, but it is very useful for unit testing.
Executing Tasks
Once a buildfile is loaded, you can execute tasks on the buildfile using the invoke() method. You should pass the name of the task you want to execute along with any constants you want set for the task to access:
buildfile.invoke :demo_task, :context => my_context
With the above example, the demo_task could access the “context” as a global constant like do:
task :demo_task do
CONTEXT.name = "demo!"
end
Accessing Configs
Configs are stored in a “normalized” state in the “configs” property. You can access configs directly this way, but the more useful way to access configs is through the config_for() method. Pass the name of the target that is the current “focus” of the config:
config = buildfile.config_for('/sproutcore') # target always starts w /
Configs can be specified in different “contexts” by the buildfile. When you call this method, the configs will be merged together, layering any configs that are targeted specifically at the /sproutcore target over the top of globally defined configs. The current build mode is also reflected in this call.
Defined Under Namespace
Modules: Commands Classes: BuildTask, Task
Constant Summary collapse
- BUILDFILE_NAMES =
Default buildfile names. Override with SC.env.buildfile_names
%w(Buildfile sc-config sc-config.rb)
Instance Attribute Summary collapse
-
#configs ⇒ Object
readonly
The hash of configs as loaded from the files.
-
#current_path ⇒ Object
readonly
TASK METHODS.
-
#options ⇒ Object
readonly
Application options from the command line.
-
#path ⇒ Object
The location of the buildfile represented by this object.
-
#project_name ⇒ Object
This is set if you use the project helper method in your buildfile.
- #project_type ⇒ Object
-
#proxies ⇒ Object
readonly
The hash of all proxies paths and their options.
-
#target_name ⇒ Object
readonly
The namespace for this buildfile.
Attributes included from TaskManager
#last_description, #last_task_options
Class Method Summary collapse
-
.define(&block) ⇒ Object
Creates a new buildfile and then gives you an opportunity to define its contents by executing the passed block in the context of the buildfile.
-
.has_buildfile?(dir_path, buildfile_names = nil) ⇒ Boolean
Determines if this directory has a buildfile or not…
-
.load(path) ⇒ Object
Loads the buildfile at the specified path.
Instance Method Summary collapse
-
#add_config(config_name, config_mode, opts = nil) ⇒ Object
Merge the passed hash of options into the config hash.
-
#add_import(fn) ⇒ Object
Add a file to the list of files to be imported.
-
#add_proxy(proxy_path, opts = {}) ⇒ Object
Adds a proxy to the list of proxy paths.
-
#config_for(config_name, mode_name = nil) ⇒ Object
Params config_name:: The config name mode_name:: optional mode name === Returns merged config – a HashStruct.
-
#current_mode ⇒ Object
CONFIG METHODS.
- #current_mode=(new_mode) ⇒ Object
-
#define!(string = nil, &block) ⇒ Object
Extend the buildfile dynamically by executing the named task.
-
#dup ⇒ Object
When dup’ing, rewrite the @tasks hash to use clones of the tasks the point to the new application object.
-
#for_target(target) ⇒ Object
Configures the buildfile for use with the specified target.
-
#has_task?(task_name) ⇒ Boolean
Returns true if the buildfile has the named task defined.
-
#initialize ⇒ Buildfile
constructor
INTERNAL SUPPORT.
-
#intern(task_class, task_name) ⇒ Object
Support redefining a task…
-
#invoke(task_name, consts = nil) ⇒ Object
Executes the name task.
-
#load!(filename = nil, buildfile_names = nil) ⇒ Object
Loads the contents of the passed file into the buildfile object.
-
#load_imports ⇒ Object
Load the pending list of imported files.
- #loaded_paths ⇒ Object
- #project! ⇒ Object
-
#project? ⇒ Boolean
Returns YES if this buildfile appears to represent a project.
- #task_defined?(task_name) ⇒ Boolean
Methods included from Commands
#build_task, #config, #desc, #import, #mode, #namespace, #project, #proxy, #replace_task, #task, #task_options
Methods included from TaskManager
#[], #clear, #create_rule, #current_scope, #define_task, #in_namespace, #lookup, #resolve_args, #tasks
Methods included from Cloneable
Constructor Details
#initialize ⇒ Buildfile
INTERNAL SUPPORT
404 405 406 407 408 409 410 411 |
# File 'lib/sproutcore/buildfile.rb', line 404 def initialize super @configs = HashStruct.new @proxies = HashStruct.new @pending_imports = [] @imported = [] @options = HashStruct.new end |
Instance Attribute Details
#configs ⇒ Object (readonly)
The hash of configs as loaded from the files. The configs are stored by mode and then by config name. To get a merged config, use config_for().
289 290 291 |
# File 'lib/sproutcore/buildfile.rb', line 289 def configs @configs end |
#current_path ⇒ Object (readonly)
TASK METHODS
142 143 144 |
# File 'lib/sproutcore/buildfile.rb', line 142 def current_path @current_path end |
#options ⇒ Object (readonly)
Application options from the command line
257 258 259 |
# File 'lib/sproutcore/buildfile.rb', line 257 def @options end |
#path ⇒ Object
The location of the buildfile represented by this object.
98 99 100 |
# File 'lib/sproutcore/buildfile.rb', line 98 def path @path end |
#project_name ⇒ Object
This is set if you use the project helper method in your buildfile.
367 368 369 |
# File 'lib/sproutcore/buildfile.rb', line 367 def project_name @project_name end |
#project_type ⇒ Object
369 |
# File 'lib/sproutcore/buildfile.rb', line 369 def project_type; @project_type || :default; end |
#proxies ⇒ Object (readonly)
The hash of all proxies paths and their options
382 383 384 |
# File 'lib/sproutcore/buildfile.rb', line 382 def proxies @proxies end |
#target_name ⇒ Object (readonly)
The namespace for this buildfile. This should be name equal to the namespace of the target that owns the buildfile, if there is one
284 285 286 |
# File 'lib/sproutcore/buildfile.rb', line 284 def target_name @target_name end |
Class Method Details
.define(&block) ⇒ Object
Creates a new buildfile and then gives you an opportunity to define its contents by executing the passed block in the context of the buildfile.
Returns
A new buildfile instance
134 135 136 |
# File 'lib/sproutcore/buildfile.rb', line 134 def self.define(&block) self.new.define!(&block) end |
.has_buildfile?(dir_path, buildfile_names = nil) ⇒ Boolean
Determines if this directory has a buildfile or not…
105 106 107 108 109 110 111 112 |
# File 'lib/sproutcore/buildfile.rb', line 105 def self.has_buildfile?(dir_path, buildfile_names=nil) buildfile_names ||= (SC.env.buildfile_names || BUILDFILE_NAMES) buildfile_names.each do |path| path = File.join(dir_path, path) return true if File.exist?(path) && !File.directory?(path) end return false end |
.load(path) ⇒ Object
Loads the buildfile at the specified path. This simply creates a new instance and loads it.
Params
path:: the path to laod at
Returns
A new Buildfile instance
123 124 125 |
# File 'lib/sproutcore/buildfile.rb', line 123 def self.load(path) self.new.load!(path) end |
Instance Method Details
#add_config(config_name, config_mode, opts = nil) ⇒ Object
Merge the passed hash of options into the config hash. This method is usually used by the config global helper
Params
config_name:: the name of the config to set
config_mode:: the mode to store the config. If omitted use current
opts: the config options to merge in
Returns
receiver
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/sproutcore/buildfile.rb', line 304 def add_config(config_name, config_mode, opts=nil) # Normalize Params if opts.nil? opts = config_mode; config_mode = nil end config_mode = current_mode if config_mode.nil? # Normalize the config name -- :all or 'all' is OK, absolute OK. config_name = config_name.to_s if config_name != 'all' && (config_name[0..0] != '/') if target_name && (config_name == File.basename(target_name)) config_name = target_name else config_name = [target_name, config_name].join('/') end end # Perform Merge mode_configs = (self.configs[config_mode.to_sym] ||= HashStruct.new) config = (mode_configs[config_name.to_sym] ||= HashStruct.new) config.merge!(opts) end |
#add_import(fn) ⇒ Object
Add a file to the list of files to be imported.
233 234 235 |
# File 'lib/sproutcore/buildfile.rb', line 233 def add_import(fn) @pending_imports << fn end |
#add_proxy(proxy_path, opts = {}) ⇒ Object
Adds a proxy to the list of proxy paths. These are used only in server mode to proxy certain URLs. If you call this method with the same proxy path more than once, the options will be merged.
Params
:proxy_path the URL to proxy
:opts any proxy options
Returns
receiver
395 396 397 398 |
# File 'lib/sproutcore/buildfile.rb', line 395 def add_proxy(proxy_path, opts={}) @proxies[proxy_path] = HashStruct.new(opts) return self end |
#config_for(config_name, mode_name = nil) ⇒ Object
Params
config_name:: The config name
mode_name:: optional mode name
Returns
merged config -- a HashStruct
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'lib/sproutcore/buildfile.rb', line 342 def config_for(config_name, mode_name=nil) mode_name = :all if mode_name.nil? || mode_name.to_s.size == 0 config_name = :all if config_name.nil? || config_name.to_s.size == 0 # collect the hashes all_configs = configs[:all] cur_configs = configs[mode_name] ret = HashStruct.new # now merge em! -- note that this assumes the merge method will handle # self.merge(self) & self.merge(nil) gracefully ret.merge!(all_configs[:all]) if all_configs ret.merge!(cur_configs[:all]) if cur_configs ret.merge!(all_configs[config_name]) if all_configs ret.merge!(cur_configs[config_name]) if cur_configs # Done -- return result return ret end |
#current_mode ⇒ Object
CONFIG METHODS
263 264 265 |
# File 'lib/sproutcore/buildfile.rb', line 263 def current_mode @define_context.current_mode end |
#current_mode=(new_mode) ⇒ Object
267 268 269 |
# File 'lib/sproutcore/buildfile.rb', line 267 def current_mode=(new_mode) @define_context.current_mode = new_mode end |
#define!(string = nil, &block) ⇒ Object
Extend the buildfile dynamically by executing the named task. This will yield the block if given after making the buildfile the current build file.
Params
string:: optional string to eval
&block:: optional block to execute
Returns
self
155 156 157 158 159 160 161 162 |
# File 'lib/sproutcore/buildfile.rb', line 155 def define!(string=nil, &block) context = reset_define_context :current_mode => :all instance_eval(string) if string instance_eval(&block) if block_given? load_imports reset_define_context context return self end |
#dup ⇒ Object
When dup’ing, rewrite the @tasks hash to use clones of the tasks the point to the new application object.
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/sproutcore/buildfile.rb', line 415 def dup ret = super # Make sure the tasks themselves are cloned tasks = ret.instance_variable_get('@tasks') tasks.each do | key, task | tasks[key] = task.dup(ret) end # Deep clone the config and proxy hashes as well... %w(@configs @proxies @options).each do |ivar| cloned_ivar = instance_variable_get(ivar).deep_clone ret.instance_variable_set(ivar, cloned_ivar) end ret.instance_variable_set('@is_project', false) # transient - do not dup return ret end |
#for_target(target) ⇒ Object
Configures the buildfile for use with the specified target. Call this BEFORE you load any actual file contents.
Returns
self
277 278 279 280 |
# File 'lib/sproutcore/buildfile.rb', line 277 def for_target(target) @target_name = target.target_name.to_s return self end |
#has_task?(task_name) ⇒ Boolean
Returns true if the buildfile has the named task defined
Params
task_name:: the full name of the task, including namespaces
224 225 226 |
# File 'lib/sproutcore/buildfile.rb', line 224 def has_task?(task_name) !self[task_name.to_s].nil? end |
#intern(task_class, task_name) ⇒ Object
Support redefining a task…
250 251 252 253 254 |
# File 'lib/sproutcore/buildfile.rb', line 250 def intern(task_class, task_name) ret = super(task_class, task_name) ret.clear if @is_redefining return ret end |
#invoke(task_name, consts = nil) ⇒ Object
Executes the name task. Unlike invoke_task, this method will execute the task even if it has already been executed before. You can also pass a hash of additional constants that will be set on the global namespace before the task is invoked.
Params
task_name:: the full name of the task, including namespaces
consts:: Optional hash of constant values to set on the env
214 215 216 217 218 |
# File 'lib/sproutcore/buildfile.rb', line 214 def invoke(task_name, consts = nil) consts = set_kernel_consts consts # save to restore self[task_name.to_s].invoke set_kernel_consts consts # clear constants end |
#load!(filename = nil, buildfile_names = nil) ⇒ Object
Loads the contents of the passed file into the buildfile object. The contents will be executed in the context of the buildfile object. If the filename passed is nil or the file does not exist, this will simply do nothing.
Params
filename:: the buildfile to load or a directory
buildfile_names:: optional array of names to search in directory
Returns
self
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/sproutcore/buildfile.rb', line 180 def load!(filename=nil, buildfile_names=nil) # If a directory is passed, look for any buildfile and load them... if File.directory?(filename) # search directory for buildfiles and load them. buildfile_names ||= (SC.env.buildfile_names || BUILDFILE_NAMES) buildfile_names.each do |path| path = File.join(filename, path) next unless File.exist?(path) && !File.directory?(path) load!(path) end elsif File.exist?(filename) old_path = @current_path @current_path = filename loaded_paths << filename # save loaded paths SC.logger.debug "Loading buildfile at #{filename}" define!(File.read(filename)) if filename && File.exist?(filename) @current_path = old_path end return self end |
#load_imports ⇒ Object
Load the pending list of imported files.
238 239 240 241 242 243 244 245 246 247 |
# File 'lib/sproutcore/buildfile.rb', line 238 def load_imports while fn = @pending_imports.shift next if @imported.member?(fn) if fn_task = lookup(fn) fn_task.invoke end load!(fn) @imported << fn end end |
#loaded_paths ⇒ Object
204 |
# File 'lib/sproutcore/buildfile.rb', line 204 def loaded_paths; @loaded_paths ||= []; end |
#project! ⇒ Object
375 |
# File 'lib/sproutcore/buildfile.rb', line 375 def project!; @is_project = true; end |
#project? ⇒ Boolean
Returns YES if this buildfile appears to represent a project. If you use the project() helper method, it will set this
374 |
# File 'lib/sproutcore/buildfile.rb', line 374 def project?; @is_project || false; end |
#task_defined?(task_name) ⇒ Boolean
164 165 166 |
# File 'lib/sproutcore/buildfile.rb', line 164 def task_defined?(task_name) !!lookup(task_name) end |