From 0d8f661fd44709c65f15802d5aef9a96481481ca Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 19 Feb 2014 15:02:46 -0500 Subject: [PATCH] add :clone option to Environment#clone to control exactly which Environment attributes are cloned --- lib/rscons/environment.rb | 47 +++++++++++++++++++++++++++++++-------- spec/build_tests_spec.rb | 23 +++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 48027f0..5babd64 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -51,24 +51,53 @@ module Rscons end # Make a copy of the Environment object. - # The cloned environment will contain a copy of all environment options, - # construction variables, and builders (unless :exclude_builders => true is - # passed as an option). It will not contain a copy of the targets, build - # hooks, build directories, or the build root. If a block is given, the - # Environment object is yielded to the block and when the block returns, - # the {#process} method is automatically called. The possible options keys - # match those documented in the #initialize method. + # + # By default, a cloned environment will contain a copy of all environment + # options, construction variables, and builders, but not a copy of the + # targets, build hooks, build directories, or the build root. + # + # Exactly which items are cloned are controllable via the optional :clone + # parameter, which can be :none, :all, or a set or array of any of the + # following: + # - :variables to clone construction variables (on by default) + # - :builders to clone the builders (on by default) + # - :build_root to clone the build root (off by default) + # - :build_dirs to clone the build directories (off by default) + # - :build_hooks to clone the build hooks (off by default) + # + # If a block is given, the Environment object is yielded to the block and + # when the block returns, the {#process} method is automatically called. + # + # Any options that #initialize receives can also be specified here. + # + # @return a new {Environment} object. def clone(options = {}) + clone = options[:clone] || Set[:variables, :builders] + clone = Set[:variables, :builders, :build_root, :build_dirs, :build_hooks] if clone == :all + clone = Set[] if clone == :none + clone = Set.new(clone) if clone.is_a?(Array) + clone.delete(:builders) if options[:exclude_builders] env = self.class.new( echo: options[:echo] || @echo, build_root: options[:build_root], exclude_builders: true) - unless options[:exclude_builders] + if clone.include?(:builders) @builders.each do |builder_name, builder| env.add_builder(builder) end end - env.append(@varset.clone) + env.append(@varset.clone) if clone.include?(:variables) + env.build_root = @build_root if clone.include?(:build_root) + if clone.include?(:build_dirs) + @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| + env.add_build_hook(&build_hook_block) + end + end if block_given? yield env diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 3fbe959..ec61fd7 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -298,6 +298,29 @@ EOF ] end + it 'allows cloning all attributes of an Environment object' do + test_dir('clone_env') + + env1 = Rscons::Environment.new(echo: :command) do |env| + env.build_dir('src', 'build') + env['CFLAGS'] = '-O2' + env.add_build_hook do |build_op| + build_op[:vars]['CPPFLAGS'] = '-DSTRING="Hello"' + end + env.Program('program', Dir['src/*.c']) + end + + env2 = env1.clone(clone: :all) do |env| + env.Program('program2', Dir['src/*.c']) + end + + lines.should == [ + %q{gcc -c -o build/program.o -MMD -MF build/program.mf -DSTRING="Hello" -O2 src/program.c}, + %q{gcc -o program build/program.o}, + %q{gcc -o program2 build/program.o}, + ] + end + it 'builds a C++ program with one source file' do test_dir('simple_cc') Rscons::Environment.new do |env|