From 3f8b4d616f70afad4c495534b33cb9b21a92cd33 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 10 Feb 2019 18:24:49 -0500 Subject: [PATCH] Remove BuildTarget, Builder#create_build_target, and Builder#setup - close #90 --- build_tests/shared_library/Rsconscript | 2 +- .../shared_library/shared_library_cxx.rb | 2 +- .../shared_library/shared_library_d.rb | 2 +- .../shared_library/shared_library_set_shld.rb | 2 +- build_tests/simple/run_builder.rb | 2 +- build_tests/simple/user_dep_build_order.rb | 6 +- .../backward_compatible_build_hooks.rb | 2 +- lib/rscons.rb | 1 - lib/rscons/build_target.rb | 36 --------- lib/rscons/builder.rb | 80 +++++++------------ lib/rscons/builders/library.rb | 33 ++++---- lib/rscons/builders/program.rb | 53 +++++------- lib/rscons/builders/shared_library.rb | 60 +++++--------- lib/rscons/builders/simple_builder.rb | 15 +++- lib/rscons/environment.rb | 50 ++++++------ spec/rscons/builder_spec.rb | 2 +- spec/rscons/builders/simple_builder_spec.rb | 2 +- 17 files changed, 138 insertions(+), 212 deletions(-) delete mode 100644 lib/rscons/build_target.rb diff --git a/build_tests/shared_library/Rsconscript b/build_tests/shared_library/Rsconscript index f6ef61f..882bd08 100644 --- a/build_tests/shared_library/Rsconscript +++ b/build_tests/shared_library/Rsconscript @@ -6,7 +6,7 @@ build do Rscons.glob("src/*.c"), "LIBPATH" => %w[.], "LIBS" => %w[mine]) - env.build_after("test-shared.exe", libmine.to_s) + env.build_after("test-shared.exe", libmine) env.Program("test-static.exe", Rscons.glob("src/**/*.c")) end diff --git a/build_tests/shared_library/shared_library_cxx.rb b/build_tests/shared_library/shared_library_cxx.rb index f617419..1fce3c3 100644 --- a/build_tests/shared_library/shared_library_cxx.rb +++ b/build_tests/shared_library/shared_library_cxx.rb @@ -6,7 +6,7 @@ build do Rscons.glob("src/*.cc"), "LIBPATH" => %w[.], "LIBS" => %w[mine]) - env.build_after("test-shared.exe", libmine.to_s) + env.build_after("test-shared.exe", libmine) env.Program("test-static.exe", Rscons.glob("src/**/*.cc")) end diff --git a/build_tests/shared_library/shared_library_d.rb b/build_tests/shared_library/shared_library_d.rb index 745c72c..06d5a57 100644 --- a/build_tests/shared_library/shared_library_d.rb +++ b/build_tests/shared_library/shared_library_d.rb @@ -6,6 +6,6 @@ build do Rscons.glob("src/*.c"), "LIBPATH" => %w[.], "LIBS" => %w[mine]) - env.build_after("test-shared.exe", libmine.to_s) + env.build_after("test-shared.exe", libmine) end end diff --git a/build_tests/shared_library/shared_library_set_shld.rb b/build_tests/shared_library/shared_library_set_shld.rb index b399cc4..07c54d6 100644 --- a/build_tests/shared_library/shared_library_set_shld.rb +++ b/build_tests/shared_library/shared_library_set_shld.rb @@ -7,7 +7,7 @@ build do Rscons.glob("src/*.c"), "LIBPATH" => %w[.], "LIBS" => %w[mine]) - env.build_after("test-shared.exe", libmine.to_s) + env.build_after("test-shared.exe", libmine) env.Program("test-static.exe", Rscons.glob("src/**/*.c")) end diff --git a/build_tests/simple/run_builder.rb b/build_tests/simple/run_builder.rb index 18e4b77..2a37de6 100644 --- a/build_tests/simple/run_builder.rb +++ b/build_tests/simple/run_builder.rb @@ -1,7 +1,7 @@ class MyObject < Rscons::Builder def run(options) target, sources, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) - env.run_builder(env.builders["Object"].new, target, sources, cache, vars) + env.run_builder(env.builders["Object"].new(env: env, target: target, sources: sources, cache: cache, vars: vars), target, sources, cache, vars) end end diff --git a/build_tests/simple/user_dep_build_order.rb b/build_tests/simple/user_dep_build_order.rb index 2243f8f..e52eaf2 100644 --- a/build_tests/simple/user_dep_build_order.rb +++ b/build_tests/simple/user_dep_build_order.rb @@ -17,8 +17,8 @@ end build do Environment.new do |env| env.add_builder(TestBuilder) - env.TestBuilder("one", [], "wait_time" => "3") - env.TestBuilder("two", [], "wait_time" => "0") - env.depends("two", "one") + one = env.TestBuilder("one", [], "wait_time" => "3") + two = env.TestBuilder("two", [], "wait_time" => "0") + env.depends(two, one) end end diff --git a/build_tests/typical/backward_compatible_build_hooks.rb b/build_tests/typical/backward_compatible_build_hooks.rb index 9e63d37..68dc11b 100644 --- a/build_tests/typical/backward_compatible_build_hooks.rb +++ b/build_tests/typical/backward_compatible_build_hooks.rb @@ -1,6 +1,6 @@ class MyObject < Rscons::Builder def run(target, sources, cache, env, vars) - env.run_builder(env.builders["Object"].new, target, sources, cache, vars) + env.run_builder(env.builders["Object"].new(target: target, sources: sources, cache: cache, env: env, vars: vars), target, sources, cache, vars) end end diff --git a/lib/rscons.rb b/lib/rscons.rb index 48d38d2..dddf970 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -1,7 +1,6 @@ require_relative "rscons/ansi" require_relative "rscons/application" require_relative "rscons/basic_environment" -require_relative "rscons/build_target" require_relative "rscons/builder" require_relative "rscons/builder_builder" require_relative "rscons/cache" diff --git a/lib/rscons/build_target.rb b/lib/rscons/build_target.rb deleted file mode 100644 index 23ddcee..0000000 --- a/lib/rscons/build_target.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Rscons - # The BuildTarget class represents a single build target. - class BuildTarget - # Create a BuildTarget object. - # - # @param options [Hash] Options to create the BuildTarget with. - # @option options [Environment] :env - # The Environment. - # @option options [String] :target - # The user-supplied target name. - # @option options [Array] :sources - # The user-supplied source file name(s). - def initialize(options) - @env = options[:env] - @target = options[:target] - end - - # Manually record a given target as depending on the specified files. - # - # @param user_deps [Array] Dependency files. - # - # @return [void] - 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 ebb0465..ddcd812 100644 --- a/lib/rscons/builder.rb +++ b/lib/rscons/builder.rb @@ -42,6 +42,29 @@ module Rscons end end + # @return [String, Symbol] + # Target file name. + attr_reader :target + + # Create an instance of the Builder to build a target. + # + # @param options [Hash] + # Options. + # @option options [String, Symbol] :target + # Target file name. + # @option options [Array] :sources + # Source file name(s). + # @option options [Environment] :env + # The Environment executing the builder. + # @option options [Hash,VarSet] :vars + # Extra construction variables. + def initialize(options) + @target = options[:target] + @sources = options[:sources] + @env = options[:env] + @vars = options[:vars] + end + # Return the name of the builder. # # If not overridden this defaults to the last component of the class name. @@ -51,55 +74,14 @@ module Rscons self.class.name end - # Create a BuildTarget object for this build target. + # Manually record a given build target as depending on the specified files. # - # Builder sub-classes can override this method to manipulate parameters - # (for example, add a suffix to the user-given target file name). + # @param user_deps [Array] + # Dependency files. # - # @param options [Hash] Options to create the BuildTarget with. - # @option options [Environment] :env - # The Environment. - # @option options [String] :target - # The user-supplied target name. - # @option options [Array] :sources - # The user-supplied source file name(s). - # @option options [Hash,VarSet] :vars - # Extra construction variables. - # - # @return [BuildTarget] - def create_build_target(options) - BuildTarget.new(options) - end - - # Set up a build operation using this builder. - # - # This method is called when a build target is registered using this - # builder. This method should not do any building, but should perform any - # setup needed and register any prerequisite build targets that need to be - # built before the target being requested here. - # - # If the builder needs no special setup, it does not need to override this - # method. If there is any information produced in this method that will be - # needed later in the build, it can be stored in the return value from this - # method, which will be passed to the {#run} method. - # - # @since 1.10.0 - # - # @param options [Hash] - # Options. - # @option options [String] :target - # Target file name. - # @option options [Array] :sources - # Source file name(s). - # @option options [Environment] :env - # The Environment executing the builder. - # @option options [Hash,VarSet] :vars - # Extra construction variables. - # - # @return [Object] - # Any object that the builder author wishes to be saved and passed back - # in to the {#run} method. - def setup(options) + # @return [void] + def depends(*user_deps) + @env.depends(@target, *user_deps) end # Run the builder to produce a build target. @@ -139,8 +121,6 @@ module Rscons # The Environment executing the builder. # @option options [Hash,VarSet] :vars # Extra construction variables. - # @option options [Object] :setup_info - # Whatever value was returned from this builder's {#setup} method call. # # @return [ThreadedCommand,String,false] # Name of the target file on success or false on failure. @@ -177,8 +157,6 @@ module Rscons # The Environment executing the builder. # @option options [Hash,VarSet] :vars # Extra construction variables. - # @option options [Object] :setup_info - # Whatever value was returned from this builder's {#setup} method call. # @option options [true,false,nil] :command_status # If the {#run} method returns a {ThreadedCommand}, this field will # contain the return value from executing the command with diff --git a/lib/rscons/builders/library.rb b/lib/rscons/builders/library.rb index 99880c5..67751fe 100644 --- a/lib/rscons/builders/library.rb +++ b/lib/rscons/builders/library.rb @@ -10,18 +10,23 @@ module Rscons 'ARCMD' => ['${AR}', '${ARFLAGS}', '${_TARGET}', '${_SOURCES}'] ) - # Set up a build operation using this builder. + # Create an instance of the Builder to build a target. # - # @param options [Hash] Builder setup options. - # - # @return [Object] - # Any object that the builder author wishes to be saved and passed back - # in to the {#run} method. - def setup(options) - target, sources, env, vars = options.values_at(:target, :sources, :env, :vars) - suffixes = env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], vars) + # @param options [Hash] + # Options. + # @option options [String] :target + # Target file name. + # @option options [Array] :sources + # Source file name(s). + # @option options [Environment] :env + # The Environment executing the builder. + # @option options [Hash,VarSet] :vars + # Extra construction variables. + def initialize(options) + super(options) + suffixes = @env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], @vars) # Register builders to build each source to an object file or library. - env.register_builds(target, sources, suffixes, vars) + @objects = @env.register_builds(@target, @sources, suffixes, @vars) end # Run the builder to produce a build target. @@ -31,14 +36,14 @@ module Rscons # @return [String,false] # Name of the target file on success or false on failure. def run(options) - target, sources, cache, env, vars, objects = options.values_at(:target, :sources, :cache, :env, :vars, :setup_info) + target, sources, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) vars = vars.merge({ '_TARGET' => target, - '_SOURCES' => objects, + '_SOURCES' => @objects, }) - options[:sources] = objects + options[:sources] = @objects command = env.build_command("${ARCMD}", vars) - standard_threaded_build("AR #{target}", target, command, objects, env, cache) + standard_threaded_build("AR #{target}", target, command, @objects, env, cache) end # Finalize a build. diff --git a/lib/rscons/builders/program.rb b/lib/rscons/builders/program.rb index ea541d9..487f850 100644 --- a/lib/rscons/builders/program.rb +++ b/lib/rscons/builders/program.rb @@ -17,41 +17,26 @@ module Rscons 'LDCMD' => ['${LD}', '-o', '${_TARGET}', '${LDFLAGS}', '${_SOURCES}', '${LIBDIRPREFIX}${LIBPATH}', '${LIBLINKPREFIX}${LIBS}'] ) - # Create a BuildTarget object for this build target. + # Create an instance of the Builder to build a target. # - # The build target filename is given a ".exe" suffix if Rscons is - # executing on a Windows platform and no other suffix is given. - # - # @param options [Hash] Options to create the BuildTarget with. - # @option options [Environment] :env - # The Environment. + # @param options [Hash] + # Options. # @option options [String] :target - # The user-supplied target name. + # Target file name. # @option options [Array] :sources - # The user-supplied source file name(s). - # - # @return [BuildTarget] - def create_build_target(options) - env, target, vars = options.values_at(:env, :target, :vars) - my_options = options.dup - unless File.basename(target)["."] - my_options[:target] += env.expand_varref("${PROGSUFFIX}", vars) + # Source file name(s). + # @option options [Environment] :env + # The Environment executing the builder. + # @option options [Hash,VarSet] :vars + # Extra construction variables. + def initialize(options) + super(options) + unless File.basename(@target)["."] + @target += @env.expand_varref("${PROGSUFFIX}", @vars) end - super(my_options) - end - - # Set up a build operation using this builder. - # - # @param options [Hash] Builder setup options. - # - # @return [Object] - # Any object that the builder author wishes to be saved and passed back - # in to the {#run} method. - def setup(options) - target, sources, env, vars = options.values_at(:target, :sources, :env, :vars) - suffixes = env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], vars) + suffixes = @env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], @vars) # Register builders to build each source to an object file or library. - env.register_builds(target, sources, suffixes, vars) + @objects = @env.register_builds(@target, @sources, suffixes, @vars) end # Run the builder to produce a build target. @@ -61,7 +46,7 @@ module Rscons # @return [String,false] # Name of the target file on success or false on failure. def run(options) - target, sources, cache, env, vars, objects = options.values_at(:target, :sources, :cache, :env, :vars, :setup_info) + target, sources, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) ld = env.expand_varref("${LD}", vars) ld = if ld != "" ld @@ -74,12 +59,12 @@ module Rscons end vars = vars.merge({ '_TARGET' => target, - '_SOURCES' => objects, + '_SOURCES' => @objects, 'LD' => ld, }) - options[:sources] = objects + options[:sources] = @objects command = env.build_command("${LDCMD}", vars) - standard_threaded_build("LD #{target}", target, command, objects, env, cache) + standard_threaded_build("LD #{target}", target, command, @objects, env, cache) end # Finalize a build. diff --git a/lib/rscons/builders/shared_library.rb b/lib/rscons/builders/shared_library.rb index 5020647..15a4105 100644 --- a/lib/rscons/builders/shared_library.rb +++ b/lib/rscons/builders/shared_library.rb @@ -24,47 +24,31 @@ module Rscons end end - # Create a BuildTarget object for this build target. - # - # The build target filename is given a platform-dependent suffix if no - # other suffix is given. + # Create an instance of the Builder to build a target. # # @param options [Hash] - # Options to create the BuildTarget with. - # @option options [Environment] :env - # The Environment. + # Options. # @option options [String] :target - # The user-supplied target name. + # Target file name. # @option options [Array] :sources - # The user-supplied source file name(s). - # - # @return [BuildTarget] - def create_build_target(options) - env, target, vars = options.values_at(:env, :target, :vars) - my_options = options.dup - libprefix = env.expand_varref("${SHLIBPREFIX}", vars) - unless File.basename(target).start_with?(libprefix) - my_options[:target].sub!(%r{^(.*/)?([^/]+)$}, "\\1#{libprefix}\\2") + # Source file name(s). + # @option options [Environment] :env + # The Environment executing the builder. + # @option options [Hash,VarSet] :vars + # Extra construction variables. + def initialize(options) + super(options) + libprefix = @env.expand_varref("${SHLIBPREFIX}", @vars) + unless File.basename(@target).start_with?(libprefix) + @target = @target.sub!(%r{^(.*/)?([^/]+)$}, "\\1#{libprefix}\\2") end - unless File.basename(target)["."] - my_options[:target] += env.expand_varref("${SHLIBSUFFIX}", vars) + unless File.basename(@target)["."] + @target += @env.expand_varref("${SHLIBSUFFIX}", @vars) end - super(my_options) - end - - # Set up a build operation using this builder. - # - # @param options [Hash] Builder setup options. - # - # @return [Object] - # Any object that the builder author wishes to be saved and passed back - # in to the {#run} method. - def setup(options) - target, sources, env, vars = options.values_at(:target, :sources, :env, :vars) - suffixes = env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], vars) + suffixes = @env.expand_varref(["${OBJSUFFIX}", "${LIBSUFFIX}"], @vars) # Register builders to build each source to an object file or library. - env.register_builds(target, sources, suffixes, vars, - features: %w[shared]) + @objects = @env.register_builds(@target, @sources, suffixes, @vars, + features: %w[shared]) end # Run the builder to produce a build target. @@ -74,7 +58,7 @@ module Rscons # @return [String,false] # Name of the target file on success or false on failure. def run(options) - target, sources, cache, env, vars, objects = options.values_at(:target, :sources, :cache, :env, :vars, :setup_info) + target, sources, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) ld = env.expand_varref("${SHLD}", vars) ld = if ld != "" ld @@ -87,12 +71,12 @@ module Rscons end vars = vars.merge({ '_TARGET' => target, - '_SOURCES' => objects, + '_SOURCES' => @objects, 'SHLD' => ld, }) - options[:sources] = objects + options[:sources] = @objects command = env.build_command("${SHLDCMD}", vars) - standard_threaded_build("SHLD #{target}", target, command, objects, env, cache) + standard_threaded_build("SHLD #{target}", target, command, @objects, env, cache) end # Finalize a build. diff --git a/lib/rscons/builders/simple_builder.rb b/lib/rscons/builders/simple_builder.rb index 512d151..68e2d82 100644 --- a/lib/rscons/builders/simple_builder.rb +++ b/lib/rscons/builders/simple_builder.rb @@ -5,12 +5,23 @@ module Rscons # @since 1.8.0 class SimpleBuilder < Builder - # Create a new builder with the given action. + # Create an instance of the Builder to build a target. # + # @param options [Hash] + # Options. + # @option options [String] :target + # Target file name. + # @option options [Array] :sources + # Source file name(s). + # @option options [Environment] :env + # The Environment executing the builder. + # @option options [Hash,VarSet] :vars + # Extra construction variables. # @param run_proc [Proc] # A Proc to execute when the builder runs. The provided block must # provide the have the same signature as {Builder#run}. - def initialize(&run_proc) + def initialize(options, &run_proc) + super(options) @run_proc = run_proc end diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 12a822a..8ef8070 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -282,8 +282,7 @@ module Rscons job[:sources], cache, job[:vars], - allow_delayed_execution: true, - setup_info: job[:setup_info]) + allow_delayed_execution: true) unless result failure = "Failed to build #{job[:target]}" Ansi.write($stderr, :red, failure, :reset, "\n") @@ -342,9 +341,9 @@ module Rscons # @param method [Symbol] Method name. # @param args [Array] Method arguments. # - # @return [BuildTarget] - # The {BuildTarget} object registered, if the method called is a - # {Builder}. + # @return [Builder] + # The {Builder} object registered, if the method called is the name of a + # registered {Builder}. def method_missing(method, *args) if @builders.has_key?(method.to_s) target, sources, vars, *rest = args @@ -352,14 +351,13 @@ module Rscons unless vars.is_a?(Hash) or vars.is_a?(VarSet) raise "Unexpected construction variable set: #{vars.inspect}" end - builder = @builders[method.to_s].new target = expand_path(expand_varref(target)) sources = Array(sources).map do |source| expand_path(expand_varref(source)) end.flatten - build_target = builder.create_build_target(env: self, target: target, sources: sources, vars: vars) - add_target(build_target.to_s, builder, sources, vars, rest) - build_target + builder = @builders[method.to_s].new(env: self, target: target, sources: sources, vars: vars) + add_target(builder.target, builder, sources, vars, rest) + builder else super end @@ -367,13 +365,21 @@ module Rscons # Manually record a given target as depending on the specified files. # - # @param target [String,BuildTarget] Target file. - # @param user_deps [Array] Dependency files. + # @param target [String, Builder] Target file. + # @param user_deps [Array] Dependency files. # # @return [void] def depends(target, *user_deps) + if target.is_a?(Builder) + target = target.target + end target = expand_varref(target.to_s) - user_deps = user_deps.map {|ud| expand_varref(ud)} + user_deps = user_deps.map do |ud| + if ud.is_a?(Builder) + ud = ud.target + end + expand_varref(ud) + end @user_deps[target] ||= [] @user_deps[target] = (@user_deps[target] + user_deps).uniq build_after(target, user_deps) @@ -400,7 +406,7 @@ module Rscons # @param targets [String, Array] # Target files to wait to build until the prerequisites are finished # building. - # @param prerequisites [String, Array] + # @param prerequisites [String, Builder, Array] # Files that must be built before building the specified targets. # # @return [void] @@ -411,6 +417,9 @@ module Rscons target = expand_path(expand_varref(target)) @registered_build_dependencies[target] ||= Set.new prerequisites.each do |prerequisite| + if prerequisite.is_a?(Builder) + prerequisite = prerequisite.target + end prerequisite = expand_path(expand_varref(prerequisite)) @registered_build_dependencies[target] << prerequisite end @@ -451,8 +460,8 @@ module Rscons # Find and register builders to build source files into files containing # one of the suffixes given by suffixes. # - # This method is used internally by Rscons builders. It should be called - # from the builder's #setup method. + # This method is used internally by Rscons builders. It can be called + # from the builder's #initialize method. # # @since 1.10.0 # @@ -510,8 +519,6 @@ module Rscons # @since 1.10.0 # Allow a threaded command to be scheduled but not yet completed before # this method returns. - # @option options [Object] :setup_info - # Arbitrary builder info returned by Builder#setup. # # @return [String,false] Return value from the {Builder}'s +run+ method. def run_builder(builder, target, sources, cache, vars, options = {}) @@ -523,7 +530,6 @@ module Rscons cache: cache, env: self, vars: vars, - setup_info: options[:setup_info] } call_build_hooks = lambda do |sec| @build_hooks[sec].each do |build_hook_block| @@ -672,17 +678,11 @@ module Rscons # # @return [void] def add_target(target, builder, sources, vars, args) - setup_info = builder.setup( - target: target, - sources: sources, - env: self, - vars: vars) @job_set.add_job( builder: builder, target: target, sources: sources, - vars: vars, - setup_info: setup_info) + vars: vars) end # Start a threaded command in a new thread. diff --git a/spec/rscons/builder_spec.rb b/spec/rscons/builder_spec.rb index 8e4ebc2..afbdb15 100644 --- a/spec/rscons/builder_spec.rb +++ b/spec/rscons/builder_spec.rb @@ -2,7 +2,7 @@ module Rscons describe Builder do describe "#run" do it "raises an error if called directly and not through a subclass" do - expect{subject.run({})}.to raise_error /This method must be overridden in a subclass/ + expect{Builder.new({}).run({})}.to raise_error /This method must be overridden in a subclass/ end end end diff --git a/spec/rscons/builders/simple_builder_spec.rb b/spec/rscons/builders/simple_builder_spec.rb index 569a2fe..fefff78 100644 --- a/spec/rscons/builders/simple_builder_spec.rb +++ b/spec/rscons/builders/simple_builder_spec.rb @@ -4,7 +4,7 @@ module Rscons let(:env) {Environment.new} it "should create a new builder with the given action" do - builder = Rscons::Builders::SimpleBuilder.new { 0x1234 } + builder = Rscons::Builders::SimpleBuilder.new({}) { 0x1234 } expect(builder.run(1,2,3,4,5)).to eq(0x1234) end end