From 3b00016278198daee05d218b609be381a7b93fce Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 9 Apr 2019 19:41:13 -0400 Subject: [PATCH] Program builder cleanup, track object file source language - #94, #87 --- lib/rscons.rb | 1 + lib/rscons/builders/lang/cxx.rb | 4 +-- lib/rscons/builders/lang/d.rb | 4 +-- lib/rscons/builders/mixins/object.rb | 11 +++++++ lib/rscons/builders/mixins/program.rb | 37 +++++++++++++++++++++++ lib/rscons/builders/program.rb | 42 ++++++--------------------- lib/rscons/builders/shared_library.rb | 31 ++++++-------------- lib/rscons/environment.rb | 10 +++++++ 8 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 lib/rscons/builders/mixins/program.rb diff --git a/lib/rscons.rb b/lib/rscons.rb index 46132d2..4aed2d7 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -169,6 +169,7 @@ end require_relative "rscons/builders/mixins/depfile" require_relative "rscons/builders/mixins/object" require_relative "rscons/builders/mixins/object_deps" +require_relative "rscons/builders/mixins/program" # default builders require_relative "rscons/builders/cfile" diff --git a/lib/rscons/builders/lang/cxx.rb b/lib/rscons/builders/lang/cxx.rb index a3f83a9..aec5cd7 100644 --- a/lib/rscons/builders/lang/cxx.rb +++ b/lib/rscons/builders/lang/cxx.rb @@ -1,2 +1,2 @@ -Rscons::Builders::Object.register(command: "${CXXCMD}", suffix: "${CXXSUFFIX}") -Rscons::Builders::SharedObject.register(command: "${SHCXXCMD}", suffix: "${CXXSUFFIX}") +Rscons::Builders::Object.register(command: "${CXXCMD}", suffix: "${CXXSUFFIX}", preferred_ld: "${CXX}") +Rscons::Builders::SharedObject.register(command: "${SHCXXCMD}", suffix: "${CXXSUFFIX}", preferred_ld: "${SHCXX}") diff --git a/lib/rscons/builders/lang/d.rb b/lib/rscons/builders/lang/d.rb index 29e5120..a74c400 100644 --- a/lib/rscons/builders/lang/d.rb +++ b/lib/rscons/builders/lang/d.rb @@ -1,2 +1,2 @@ -Rscons::Builders::Object.register(command: "${DCCMD}", suffix: "${DSUFFIX}") -Rscons::Builders::SharedObject.register(command: "${SHDCCMD}", suffix: "${DSUFFIX}") +Rscons::Builders::Object.register(command: "${DCCMD}", suffix: "${DSUFFIX}", preferred_ld: "${DC}") +Rscons::Builders::SharedObject.register(command: "${SHDCCMD}", suffix: "${DSUFFIX}", preferred_ld: "${SHDC}") diff --git a/lib/rscons/builders/mixins/object.rb b/lib/rscons/builders/mixins/object.rb index 5ed553b..f425187 100644 --- a/lib/rscons/builders/mixins/object.rb +++ b/lib/rscons/builders/mixins/object.rb @@ -1,4 +1,11 @@ module Rscons + class Builder + # @return [String, nil] + # Preferred linker for this object file, or a construction variable + # reference thereto. + attr_reader :preferred_ld + end + module Builders module Mixins module Object @@ -31,6 +38,9 @@ module Rscons # @option params [String] :short_description # Short description to be printed when the builder runs (default: # "Compiling") + # @option params [String] :preferred_ld + # Preferred linker for this object file, or a construction variable + # reference thereto. def register(params) providers << params end @@ -47,6 +57,7 @@ module Rscons end @command_template = build_params[:command] @short_description = build_params[:short_description] || "Compiling" + @preferred_ld = build_params[:preferred_ld] end # Run the builder to produce a build target. diff --git a/lib/rscons/builders/mixins/program.rb b/lib/rscons/builders/mixins/program.rb new file mode 100644 index 0000000..0453c52 --- /dev/null +++ b/lib/rscons/builders/mixins/program.rb @@ -0,0 +1,37 @@ +module Rscons + module Builders + module Mixins + # Mixin providing functionality for a builder that links object files + # together into a program. + module Program + + # Run the builder to produce a build target. + def run(options) + if @command + finalize_command(sources: @objects) + else + ld = @env.expand_varref("${#{ld_var}}", @vars) + if ld == "" + @objects.find do |object| + if builder = @env.builder_for(object) + if ld = builder.preferred_ld + true + end + end + end + end + if ld.nil? || ld == "" + ld = default_ld + end + @vars["_TARGET"] = @target + @vars["_SOURCES"] = @objects + @vars["#{ld_var}"] = ld + command = @env.build_command("${#{ld_var}CMD}", @vars) + standard_command("Linking => #{@target}", command, sources: @objects) + end + end + + end + end + end +end diff --git a/lib/rscons/builders/program.rb b/lib/rscons/builders/program.rb index 3342f69..cba1ffc 100644 --- a/lib/rscons/builders/program.rb +++ b/lib/rscons/builders/program.rb @@ -5,19 +5,9 @@ module Rscons class Program < Builder include Mixins::ObjectDeps + include Mixins::Program # 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. def initialize(options) super(options) unless File.basename(@target)["."] @@ -26,28 +16,14 @@ module Rscons @objects = register_object_deps(Object) end - # Run the builder to produce a build target. - def run(options) - if @command - finalize_command(sources: @objects) - true - else - ld = @env.expand_varref("${LD}", @vars) - ld = if ld != "" - ld - elsif @sources.find {|s| s.end_with?(*@env.expand_varref("${DSUFFIX}", @vars))} - "${DC}" - elsif @sources.find {|s| s.end_with?(*@env.expand_varref("${CXXSUFFIX}", @vars))} - "${CXX}" - else - "${CC}" - end - @vars["_TARGET"] = @target - @vars["_SOURCES"] = @objects - @vars["LD"] = ld - command = @env.build_command("${LDCMD}", @vars) - standard_command("Linking => #{@target}", command, sources: @objects) - end + private + + def default_ld + "${CC}" + end + + def ld_var + "LD" end end diff --git a/lib/rscons/builders/shared_library.rb b/lib/rscons/builders/shared_library.rb index cfb9ac8..0106eeb 100644 --- a/lib/rscons/builders/shared_library.rb +++ b/lib/rscons/builders/shared_library.rb @@ -5,6 +5,7 @@ module Rscons class SharedLibrary < Builder include Mixins::ObjectDeps + include Mixins::Program # Create an instance of the Builder to build a target. def initialize(options) @@ -19,28 +20,14 @@ module Rscons @objects = register_object_deps(SharedObject) end - # Run the builder to produce a build target. - def run(options) - if @command - finalize_command(sources: @objects) - true - else - ld = @env.expand_varref("${SHLD}", @vars) - ld = if ld != "" - ld - elsif @sources.find {|s| s.end_with?(*@env.expand_varref("${DSUFFIX}", @vars))} - "${SHDC}" - elsif @sources.find {|s| s.end_with?(*@env.expand_varref("${CXXSUFFIX}", @vars))} - "${SHCXX}" - else - "${SHCC}" - end - @vars["_TARGET"] = @target - @vars["_SOURCES"] = @objects - @vars["SHLD"] = ld - command = @env.build_command("${SHLDCMD}", @vars) - standard_command("Linking => #{@target}", command, sources: @objects) - end + private + + def default_ld + "${SHCC}" + end + + def ld_var + "SHLD" end end diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 006852d..f69af9e 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -71,6 +71,7 @@ module Rscons @registered_build_dependencies = {} @side_effects = {} @builder_set = BuilderSet.new(@registered_build_dependencies, @side_effects) + @build_targets = {} @user_deps = {} # Hash of builder name (String) => builder class (Class). @builders = {} @@ -318,6 +319,7 @@ module Rscons env: self, vars: vars) @builder_set << builder + @build_targets[target] = builder builder else super @@ -517,6 +519,14 @@ module Rscons Ansi.write($stdout, :cyan, message, :reset, "\n") if message end + # Get the Builder for a target. + # + # @return [Builder, nil] + # The {Builder} for target, or +nil+ if none found. + def builder_for(target) + @build_targets[target] + end + private # Run a builder and process its return value.