From 1b50a9dd3c240665942de9b616166482132ac14c Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 12 Jun 2014 13:31:17 -0400 Subject: [PATCH] add Rscons::BuildTarget Return a BuildTarget object from Environment#method_missing when a build target is registered. --- lib/rscons.rb | 1 + lib/rscons/build_target.rb | 29 ++++++++++++++++++++++++++++ lib/rscons/builder.rb | 13 +++++++++++++ lib/rscons/builders/program.rb | 10 +++++++--- lib/rscons/environment.rb | 14 +++++++++++--- spec/build_tests_spec.rb | 7 +++---- spec/rscons/builders/program_spec.rb | 4 ++-- spec/rscons/environment_spec.rb | 6 +++--- 8 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 lib/rscons/build_target.rb diff --git a/lib/rscons.rb b/lib/rscons.rb index bf54ef1..80a5090 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -1,3 +1,4 @@ +require_relative "rscons/build_target" require_relative "rscons/builder" require_relative "rscons/cache" require_relative "rscons/environment" diff --git a/lib/rscons/build_target.rb b/lib/rscons/build_target.rb new file mode 100644 index 0000000..03795f7 --- /dev/null +++ b/lib/rscons/build_target.rb @@ -0,0 +1,29 @@ +module Rscons + # The BuildTarget class represents a single build target. + class BuildTarget + # Create a BuildTarget object. + # + # @param env [Environment] The Environment. + # @param target [String] Name of the target file. + def initialize(env, target) + @env = env + @target = target + end + + # Manually record a given target as depending on the specified files. + # + # @param user_deps [Array] Dependency files. + def depends(*user_deps) + @env.depends(@target, *user_deps) + end + + # Convert the BuildTarget to a String. + # + # This method always returns the target file name. + # + # @return [String] Target file name. + def to_s + @target + end + end +end diff --git a/lib/rscons/builder.rb b/lib/rscons/builder.rb index b652d65..cc12d2e 100644 --- a/lib/rscons/builder.rb +++ b/lib/rscons/builder.rb @@ -19,6 +19,19 @@ module Rscons {} end + # Create a BuildTarget object for this build target. + # + # Builder sub-classes can override this method to manipulate parameters + # (for example, add a suffix to the user-given target file name). + # + # @param env [Environment] The Environment. + # @param target [String] The user-supplied target name. + # + # @return [BuildTarget] + def create_build_target(env, target) + BuildTarget.new(env, target) + end + # Return whether this builder object is capable of producing a given target # file name from a given source file name. # @param target [String] The target file name. diff --git a/lib/rscons/builders/program.rb b/lib/rscons/builders/program.rb index 429605d..76116b6 100644 --- a/lib/rscons/builders/program.rb +++ b/lib/rscons/builders/program.rb @@ -18,6 +18,13 @@ module Rscons } end + def create_build_target(env, target) + unless target =~ /\./ + target += env.expand_varref("${PROGSUFFIX}") + end + super(env, target) + end + def run(target, sources, cache, env, vars) # build sources to linkable objects objects = env.build_sources(sources, env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], vars).flatten, cache, vars) @@ -32,9 +39,6 @@ module Rscons else "${CC}" end - unless target =~ /\./ - target += env.expand_varref("${PROGSUFFIX}", vars) - end vars = vars.merge({ '_TARGET' => target, '_SOURCES' => objects, diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 2233a4b..45c49de 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -260,7 +260,10 @@ module Rscons raise "Unexpected construction variable set: #{vars.inspect}" end sources = Array(sources) - add_target(target, @builders[method.to_s], sources, vars, rest) + builder = @builders[method.to_s] + build_target = builder.create_build_target(self, target) + add_target(build_target.to_s, builder, sources, vars, rest) + build_target else super end @@ -275,9 +278,14 @@ module Rscons } end - # Manually record a given target as depending on the specified - # dependency files. + # Manually record a given target as depending on the specified files. + # + # @param target [String,BuildTarget] Target file. + # @param user_deps [Array] Dependency files. + # + # @return [void] def depends(target, *user_deps) + target = target.to_s @user_deps[target] ||= [] @user_deps[target] = (@user_deps[target] + user_deps).uniq end diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index f1f46c4..787e7c1 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -432,21 +432,20 @@ EOF it 'rebuilds when user-specified dependencies change' do test_dir('simple') env = Rscons::Environment.new do |env| - env.Program('simple.exe', Dir['*.c']) + env.Program('simple.exe', Dir['*.c']).depends("file.ld") File.open("file.ld", "w") do |fh| fh.puts("foo") end - env.depends('simple.exe', 'file.ld') end lines.should == ["CC simple.o", "LD simple.exe"] File.exists?('simple.o').should be_true `./simple.exe`.should == "This is a simple C program\n" e2 = Rscons::Environment.new do |env| - env.Program('simple.exe', Dir['*.c']) + program = env.Program('simple.exe', Dir['*.c']) + env.depends(program, "file.ld") File.open("file.ld", "w") do |fh| fh.puts("bar") end - env.depends('simple.exe', 'file.ld') end lines.should == ["LD simple.exe"] e3 = Rscons::Environment.new do |env| diff --git a/spec/rscons/builders/program_spec.rb b/spec/rscons/builders/program_spec.rb index db5ee1b..5fd6caa 100644 --- a/spec/rscons/builders/program_spec.rb +++ b/spec/rscons/builders/program_spec.rb @@ -5,13 +5,13 @@ module Rscons subject {Program.new} it "supports overriding CC construction variable" do - subject.should_receive(:standard_build).with("LD prog#{env["PROGSUFFIX"]}", "prog#{env["PROGSUFFIX"]}", ["sp-c++", "-o", "prog#{env["PROGSUFFIX"]}", "prog.o"], ["prog.o"], env, :cache) + subject.should_receive(:standard_build).with("LD prog", "prog", ["sp-c++", "-o", "prog", "prog.o"], ["prog.o"], env, :cache) subject.run("prog", ["prog.o"], :cache, env, "CC" => "sp-c++") end it "supports overriding LDCMD construction variable" do subject.should_receive(:standard_build).with("LD prog.exe", "prog.exe", ["special", "LD!", "prog.o"], ["prog.o"], env, :cache) - subject.run("prog", ["prog.o"], :cache, env, "LDCMD" => ["special", "LD!", "${_SOURCES}"]) + subject.run("prog.exe", ["prog.o"], :cache, env, "LDCMD" => ["special", "LD!", "${_SOURCES}"]) end end end diff --git a/spec/rscons/environment_spec.rb b/spec/rscons/environment_spec.rb index 5a91fa3..4821f6c 100644 --- a/spec/rscons/environment_spec.rb +++ b/spec/rscons/environment_spec.rb @@ -295,11 +295,11 @@ module Rscons it "records the target when the target method is a known builder" do env = Environment.new env.instance_variable_get(:@targets).should == {} - env.Program("target", ["src1", "src2"], var: "val") - target = env.instance_variable_get(:@targets)["target"] + env.Object("target.o", ["src1.c", "src2.c"], var: "val") + target = env.instance_variable_get(:@targets)["target.o"] target.should_not be_nil target[:builder].is_a?(Builder).should be_true - target[:sources].should == ["src1", "src2"] + target[:sources].should == ["src1.c", "src2.c"] target[:vars].should == {var: "val"} target[:args].should == [] end