class SC::Project
A project describes a collection of targets that you can build. Normally you instantiate a project by calling Project.load()
method. You should pass in the path of the project and the project type. The project type will determine the namespace used in the buildfile to detect and load tasks.
Examples¶ ↑
Load a SproutCore-style project:
Project.load('myproject', :sproutcore)
Load a standard gcc-build project:
Project.load('myproject', :cc)
How a Project
is Loaded¶ ↑
When you load a project, here is what happens:
-
Locate and load Buildfiles, if any are found
-
Run project_type:target:find for all targets defined for the project. this will locate and define the targets for the project
-
If you request a build of a particular resource, a manifest will be built for the target. This manifest contains a series of rules that can be invoked in order to build the named resource.
Attributes
Parent project this project shoud inherit build rules and targets from
the path of this project
Public Class Methods
Returns a new project loaded from the specified path
# File lib/sproutcore/models/project.rb, line 82 def self.load(project_root, opts={}) new project_root, opts end
Attempts to find the nearest project root
# File lib/sproutcore/models/project.rb, line 64 def self.load_nearest_project(path, opts={}) candidate = nil while path if Buildfile.has_buildfile?(path) candidate = path # If we find a buildfile and the buildfile explicitly states # that it is a project, then just stop here.. break if Buildfile.load(path).project? end new_path = File.dirname(path) path = (new_path == path) ? nil : new_path end (candidate) ? self.new(candidate, opts) : nil end
When a new project is created, you may optionally pass either a :parent option or a :paths options. If you pass the paths option, then this class will search the paths for projects and initialize them as parent projects to this one.
If you pass a parent project, then this project will start out with a clone of the parent project's buildfile and targets.
# File lib/sproutcore/models/project.rb, line 57 def initialize(project_root, opts ={}) @project_root = project_root @parent_project = opts[:parent] @buildfile = @targets = nil end
Public Instance Methods
Adds a new target to the project with the passed target name. Include the source_root for the target as well as any additional options you want copied onto the target. If a previous target was defined by the same name it will be replaced by this one.
Params¶ ↑
target_name:: the name of the target. target_type:: the type of target
Options (any others allowed also)¶ ↑
source_root:: the absolute path to the target source
Returns¶ ↑
new target
# File lib/sproutcore/models/project.rb, line 183 def add_target(target_name, target_type, options={}) targets[target_name.to_sym] = Target.new(target_name.to_sym, target_type.to_sym, options.merge(:project => self)) end
The current buildfile for the project. The buildfile is calculated by merging any parent project buildfile with the contents of any buildfiles found in the current project. Buildfiles include any file named “Buildfile”, “sc-config”, or “sc-config.rb”. You can also specify your own buildfile names with the “buildfile_names” config in the SC.env.
Returns¶ ↑
Buildfile instance
# File lib/sproutcore/models/project.rb, line 100 def buildfile @buildfile ||= (parent_project.nil? ? Buildfile.new : parent_project.buildfile.dup).load!(project_root) end
The config for the current project. The config is computed by merging the config settings from the current buildfile and then the current environment in the following order:
config for all modes, all targets + config for current mode, all targets + Current environment defined in SC.env
This is the config hash you should access to determine general project wide settings that cannot be overridden by individual targets.
Returns¶ ↑
merged HashStruct
# File lib/sproutcore/models/project.rb, line 118 def config return @config ||= buildfile.config_for(:all, SC.build_mode).merge(SC.env) end
Called by project to discover any targets within the project itself. The default implementation will search the project root directory for any directories matching those named in the “target_types” config. (See Buildfile
for documentation). It will then recursively descend into each target looking for further nested targets unless you've set the “allow_nested_targets” config to false.
If you need to change the way the project autodiscovers its own targets you can either change the “target_types” and “allow_nested_targets” configs or you can override this method in your own ruby code to do whatever kind of changes you want.
Params¶ ↑
root_path:: The path to search for targets. root_name:: The root target name config:: The config hash to use for this. Should come from target
Returns¶ ↑
self
# File lib/sproutcore/models/project.rb, line 208 def find_targets_for(root_path, root_name, config) # look for directories matching the target_types keys and create target # with target_types value as type. -- normalize to lowercase string target_types = {} (config[:target_types] || {}).each do |key, value| target_types[key.to_s.downcase] = value end # look for directories matching a target type Dir.glob(File.join(root_path, '*')).each do |dir_name| target_type = target_types[File.basename(dir_name).to_s.downcase] next if target_type.nil? next unless File.directory?(dir_name) # loop through each item in the directory. Dir.glob(File.join(dir_name,'*')).each do |source_root| next unless File.directory?(source_root) # compute target name and create target target_name = [root_name, File.basename(source_root)] * '/' target = self.add_target target_name, target_type, :source_root => source_root # if target's config allows nested targets, then call recursively # asking the target's config allows the target's Buildfile to # override the default. if target.config[:allow_nested_targets] find_targets_for(source_root, target_name, target.config) end end # Dir.glob end # target_type.each return self end
Attempts to discover and load a generator with the specified name from the current project. If the generator cannot be found, this method will return nil.
# File lib/sproutcore/models/project.rb, line 250 def generator_for(generator_name, opts={}) opts[:target_project] = self return SC::Generator.load(generator_name, opts) end
# File lib/sproutcore/models/project.rb, line 45 def inspect "SC::Project(#{File.basename(project_root || '')})" end
# File lib/sproutcore/models/project.rb, line 86 def reload! @buildfile = @targets = nil end
Returns the target with the specified target name. The target name may be absolute path or not, both will lookup from the top.
Params¶ ↑
target_name:: the target to lookup
Returns¶ ↑
a Target instance or nil if no matching target could be found
# File lib/sproutcore/models/project.rb, line 163 def target_for(target_name) ret = (targets[target_name.to_s.sub(/^([^\/])/,'/\1').to_sym]) ret.nil? ? nil : ret end
A hash of the known targets for this project, including any targets inherited from a parent project. Each target is stored in the hash by target_name.
The first time this method is called, the project will automatically clone any targets from a parent project, and then calls find_targets_for
() on itself to recursively discover any targets in the project.
If you need to change the way the project discovers project, override find_targets_for
() instead of this method.
Returns¶ ↑
Hash of targets keyed by target_name
# File lib/sproutcore/models/project.rb, line 141 def targets return @targets unless @targets.nil? # Create an empty targets hash or clone from parent project @targets = HashStruct.new dup_targets(parent_project.targets) if parent_project # find targets inside project. find_targets_for(project_root, nil, self.config) return @targets end
Private Instance Methods
Loops through the hash of targets and adds them to the receiver. This is how we inherit inherit targets from a parent project.
# File lib/sproutcore/models/project.rb, line 259 def dup_targets(to_dup) to_dup.each do | target_name, target | add_target target_name, target[:target_type], target.to_hash end end