lib/rscons/environment.rb in rscons-1.6.1 vs lib/rscons/environment.rb in rscons-1.7.0
- old
+ new
@@ -5,11 +5,11 @@
module Rscons
# The Environment class is the main programmatic interface to Rscons. It
# contains a collection of construction variables, options, builders, and
# rules for building targets.
class Environment
- # @return [Hash] Set of \{"builder_name" => builder_object} pairs.
+ # @return [Hash] Set of !{"builder_name" => builder_object} pairs.
attr_reader :builders
# :command, :short, or :off
attr_accessor :echo
@@ -40,11 +40,11 @@
@varset = VarSet.new
@targets = {}
@user_deps = {}
@builders = {}
@build_dirs = []
- @build_hooks = []
+ @build_hooks = {pre: [], post: []}
unless options[:exclude_builders]
DEFAULT_BUILDERS.each do |builder_class_name|
builder_class = Builders.const_get(builder_class_name)
builder_class or raise "Could not find builder class #{builder_class_name}"
add_builder(builder_class.new)
@@ -101,13 +101,16 @@
@build_dirs.each do |src_dir, obj_dir|
env.build_dir(src_dir, obj_dir)
end
end
if clone.include?(:build_hooks)
- @build_hooks.each do |build_hook_block|
+ @build_hooks[:pre].each do |build_hook_block|
env.add_build_hook(&build_hook_block)
end
+ @build_hooks[:post].each do |build_hook_block|
+ env.add_post_build_hook(&build_hook_block)
+ end
end
if block_given?
yield env
env.process
@@ -130,10 +133,16 @@
end
end
# Add a build hook to the Environment.
#
+ # Build hooks are Ruby blocks which are invoked immediately before a
+ # build operation takes place. Build hooks have an opportunity to modify
+ # the construction variables in use for the build operation based on the
+ # builder in use, target file name, or sources. Build hooks can also
+ # register new build targets.
+ #
# @yield [build_op]
# Invoke the given block with the current build operation.
# @yieldparam build_op [Hash]
# Hash with keys:
# - :builder - The builder object in use.
@@ -142,23 +151,49 @@
# - :vars - Set of construction variable values in use.
# - :env - The Environment invoking the builder.
#
# @return [void]
def add_build_hook(&block)
- @build_hooks << block
+ @build_hooks[:pre] << block
end
+ # Add a post build hook to the Environment.
+ #
+ # Post-build hooks are Ruby blocks which are invoked immediately after a
+ # build operation takes place. Post-build hooks are only invoked if the
+ # build operation succeeded. Post-build hooks can register new build
+ # targets.
+ #
+ # @since 1.7.0
+ #
+ # @yield [build_op]
+ # Invoke the given block with the current build operation.
+ # @yieldparam build_op [Hash]
+ # Hash with keys:
+ # - :builder - The builder object in use.
+ # - :target - Target file name.
+ # - :sources - List of source file(s).
+ # - :vars - Set of construction variable values in use.
+ # - :env - The Environment invoking the builder.
+ #
+ # @return [void]
+ def add_post_build_hook(&block)
+ @build_hooks[:post] << block
+ end
+
# Specify a build directory for this Environment.
#
# Source files from src_dir will produce object files under obj_dir.
#
- # @param src_dir [String] Path to the source directory.
+ # @param src_dir [String, Regexp] Path to the source directory.
# @param obj_dir [String] Path to the object directory.
#
# @return [void]
def build_dir(src_dir, obj_dir)
- src_dir = src_dir.gsub('\\', '/') if src_dir.is_a?(String)
+ if src_dir.is_a?(String)
+ src_dir = src_dir.gsub("\\", "/").sub(%r{/*$}, "")
+ end
@build_dirs << [src_dir, obj_dir]
end
# Return the file name to be built from +source_fname+ with suffix
# +suffix+.
@@ -214,35 +249,37 @@
# When a block is passed to Environment.new, this method is automatically
# called after the block returns.
#
# @return [void]
def process
- unless @targets.empty?
- expand_paths!
+ expand_paths!
+ while @targets.size > 0
+ targets = @targets
+ @targets = {}
cache = Cache.instance
cache.clear_checksum_cache!
targets_processed = {}
process_target = proc do |target|
targets_processed[target] ||= begin
- @targets[target][:sources].each do |src|
- if @targets.include?(src) and not targets_processed.include?(src)
+ targets[target][:sources].each do |src|
+ if targets.include?(src) and not targets_processed.include?(src)
process_target.call(src)
end
end
- result = run_builder(@targets[target][:builder],
+ result = run_builder(targets[target][:builder],
target,
- @targets[target][:sources],
+ targets[target][:sources],
cache,
- @targets[target][:vars] || {})
+ targets[target][:vars] || {})
unless result
raise BuildError.new("Failed to build #{target}")
end
result
end
end
begin
- @targets.each do |target, target_params|
+ targets.each do |target, target_params|
process_target.call(target)
end
ensure
cache.write
end
@@ -408,20 +445,25 @@
# @param vars [Hash] Extra variables to pass to the builder.
#
# @return [String,false] Return value from the {Builder}'s +run+ method.
def run_builder(builder, target, sources, cache, vars)
vars = @varset.merge(vars)
- @build_hooks.each do |build_hook_block|
- build_operation = {
- builder: builder,
- target: target,
- sources: sources,
- vars: vars,
- env: self,
- }
- build_hook_block.call(build_operation)
+ call_build_hooks = lambda do |sec|
+ @build_hooks[sec].each do |build_hook_block|
+ build_operation = {
+ builder: builder,
+ target: target,
+ sources: sources,
+ vars: vars,
+ env: self,
+ }
+ build_hook_block.call(build_operation)
+ end
end
- builder.run(target, sources, cache, self, vars)
+ call_build_hooks[:pre]
+ rv = builder.run(target, sources, cache, self, vars)
+ call_build_hooks[:post] if rv
+ rv
end
# Expand a path to be relative to the Environment's build root.
#
# Paths beginning with "^/" are expanded by replacing "^" with the