From 5534878f683b2c18dc0cf58d504825ab9e3deeae Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 9 Apr 2019 18:28:42 -0400 Subject: [PATCH] Object builder cleanup - #94 --- .../shared_library/shared_library_as.rb | 7 ++ lib/rscons.rb | 7 ++ lib/rscons/builders/lang/asm.rb | 2 + lib/rscons/builders/lang/c.rb | 2 + lib/rscons/builders/lang/cxx.rb | 2 + lib/rscons/builders/lang/d.rb | 2 + lib/rscons/builders/mixins/object.rb | 73 +++++++++++++++++++ lib/rscons/builders/mixins/object_deps.rb | 2 +- lib/rscons/builders/object.rb | 36 +-------- lib/rscons/builders/shared_object.rb | 36 +-------- spec/build_tests_spec.rb | 12 ++- 11 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 build_tests/shared_library/shared_library_as.rb create mode 100644 lib/rscons/builders/lang/asm.rb create mode 100644 lib/rscons/builders/lang/c.rb create mode 100644 lib/rscons/builders/lang/cxx.rb create mode 100644 lib/rscons/builders/lang/d.rb create mode 100644 lib/rscons/builders/mixins/object.rb diff --git a/build_tests/shared_library/shared_library_as.rb b/build_tests/shared_library/shared_library_as.rb new file mode 100644 index 0000000..c24f4a5 --- /dev/null +++ b/build_tests/shared_library/shared_library_as.rb @@ -0,0 +1,7 @@ +build do + Environment.new do |env| + env["CPPPATH"] << "src/lib" + env.Object("file.S", "src/lib/one.c", "CFLAGS" => env["CFLAGS"] + ["-S"]) + libmine = env.SharedLibrary("mine", "file.S") + end +end diff --git a/lib/rscons.rb b/lib/rscons.rb index 3a38904..d8927bb 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -166,6 +166,7 @@ module Rscons end # builder mixins +require_relative "rscons/builders/mixins/object" require_relative "rscons/builders/mixins/object_deps" # default builders @@ -182,5 +183,11 @@ require_relative "rscons/builders/shared_library" require_relative "rscons/builders/shared_object" require_relative "rscons/builders/simple_builder" +# language support +require_relative "rscons/builders/lang/asm" +require_relative "rscons/builders/lang/c" +require_relative "rscons/builders/lang/cxx" +require_relative "rscons/builders/lang/d" + # Unbuffer $stdout $stdout.sync = true diff --git a/lib/rscons/builders/lang/asm.rb b/lib/rscons/builders/lang/asm.rb new file mode 100644 index 0000000..98fc071 --- /dev/null +++ b/lib/rscons/builders/lang/asm.rb @@ -0,0 +1,2 @@ +Rscons::Builders::Object.register(command: "${ASCMD}", suffix: "${ASSUFFIX}", short_description: "Assembling") +Rscons::Builders::SharedObject.register(command: "${ASCMD}", suffix: "${ASSUFFIX}", short_description: "Assembling") diff --git a/lib/rscons/builders/lang/c.rb b/lib/rscons/builders/lang/c.rb new file mode 100644 index 0000000..de74149 --- /dev/null +++ b/lib/rscons/builders/lang/c.rb @@ -0,0 +1,2 @@ +Rscons::Builders::Object.register(command: "${CCCMD}", suffix: "${CSUFFIX}") +Rscons::Builders::SharedObject.register(command: "${SHCCCMD}", suffix: "${CSUFFIX}") diff --git a/lib/rscons/builders/lang/cxx.rb b/lib/rscons/builders/lang/cxx.rb new file mode 100644 index 0000000..a3f83a9 --- /dev/null +++ b/lib/rscons/builders/lang/cxx.rb @@ -0,0 +1,2 @@ +Rscons::Builders::Object.register(command: "${CXXCMD}", suffix: "${CXXSUFFIX}") +Rscons::Builders::SharedObject.register(command: "${SHCXXCMD}", suffix: "${CXXSUFFIX}") diff --git a/lib/rscons/builders/lang/d.rb b/lib/rscons/builders/lang/d.rb new file mode 100644 index 0000000..29e5120 --- /dev/null +++ b/lib/rscons/builders/lang/d.rb @@ -0,0 +1,2 @@ +Rscons::Builders::Object.register(command: "${DCCMD}", suffix: "${DSUFFIX}") +Rscons::Builders::SharedObject.register(command: "${SHDCCMD}", suffix: "${DSUFFIX}") diff --git a/lib/rscons/builders/mixins/object.rb b/lib/rscons/builders/mixins/object.rb new file mode 100644 index 0000000..b5b3ed4 --- /dev/null +++ b/lib/rscons/builders/mixins/object.rb @@ -0,0 +1,73 @@ +module Rscons + module Builders + module Mixins + module Object + + class << self + # Hook called by Ruby when this module is included by a class (klass). + def included(klass) + klass.__send__(:extend, ClassMethods) + end + end + + # Object mixin class methods. + module ClassMethods + # @return [Array] + # Parameters used to build. + def providers + @providers ||= [] + end + + # Register a set of parameters that can be used to build an Object. + # + # @param params [Hash] + # Build parameters. + # @option params [Array, String] :command + # Command or construction variable reference thereto. + # @option params [Array, String] :suffix + # Suffix(es) or construction variable reference thereto. + # @option params [String] :short_description + # Short description to be printed when the builder runs (default: + # "Compiling") + def register(params) + providers << params + end + end + + # Construct a builder conforming to the Object interface. + def initialize(params) + super + build_params = self.class.providers.find do |build_params| + @sources.first.end_with?(*@env.expand_varref(build_params[:suffix], @vars)) + end + unless build_params + raise "Unknown input file type: #{@sources.first.inspect}" + end + @command_template = build_params[:command] + @short_description = build_params[:short_description] || "Compiling" + end + + # Run the builder to produce a build target. + def run(params) + if @command + deps = @sources + if File.exists?(@vars["_DEPFILE"]) + deps += Util.parse_makefile_deps(@vars["_DEPFILE"]) + end + @cache.register_build(@target, @command, deps.uniq, @env) + true + else + @vars["_TARGET"] = @target + @vars["_SOURCES"] = @sources + @vars["_DEPFILE"] = Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars)) + command = @env.build_command(@command_template, @vars) + @env.produces(@target, @vars["_DEPFILE"]) + message = "#{@short_description} #{Util.short_format_paths(@sources)}" + standard_command(message, command) + end + end + + end + end + end +end diff --git a/lib/rscons/builders/mixins/object_deps.rb b/lib/rscons/builders/mixins/object_deps.rb index e5dbae1..d83a5cc 100644 --- a/lib/rscons/builders/mixins/object_deps.rb +++ b/lib/rscons/builders/mixins/object_deps.rb @@ -1,6 +1,6 @@ module Rscons module Builders - # Rscons::Buidlers::Mixins namespacing module. + # Rscons::Builders::Mixins namespacing module. module Mixins # Functionality for builders which desire object or static library files # as inputs. diff --git a/lib/rscons/builders/object.rb b/lib/rscons/builders/object.rb index 4a41b69..f5eaecf 100644 --- a/lib/rscons/builders/object.rb +++ b/lib/rscons/builders/object.rb @@ -3,41 +3,7 @@ module Rscons # A default Rscons builder which knows how to produce an object file from # various types of source files. class Object < Builder - - # Mapping of known sources from which to build object files. - KNOWN_SUFFIXES = { - "AS" => "ASSUFFIX", - "CC" => "CSUFFIX", - "CXX" => "CXXSUFFIX", - "DC" => "DSUFFIX", - } - - # Run the builder to produce a build target. - def run(options) - if @command - deps = @sources - if File.exists?(@vars["_DEPFILE"]) - deps += Util.parse_makefile_deps(@vars["_DEPFILE"]) - end - @cache.register_build(@target, @command, deps.uniq, @env) - true - else - @vars["_TARGET"] = @target - @vars["_SOURCES"] = @sources - @vars["_DEPFILE"] = Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars)) - com_prefix = KNOWN_SUFFIXES.find do |compiler, suffix_var| - @sources.first.end_with?(*@env.expand_varref("${#{suffix_var}}", @vars)) - end.tap do |v| - v.nil? and raise "Error: unknown input file type: #{@sources.first.inspect}" - end.first - command = @env.build_command("${#{com_prefix}CMD}", @vars) - @env.produces(@target, @vars["_DEPFILE"]) - verb = com_prefix == "AS" ? "Assembling" : "Compiling" - message = "#{verb} #{Util.short_format_paths(@sources)}" - standard_command(message, command) - end - end - + include Mixins::Object end end end diff --git a/lib/rscons/builders/shared_object.rb b/lib/rscons/builders/shared_object.rb index 656efab..64942ce 100644 --- a/lib/rscons/builders/shared_object.rb +++ b/lib/rscons/builders/shared_object.rb @@ -4,41 +4,7 @@ module Rscons # is capable of being linked into a shared library from various types of # source files. class SharedObject < Builder - - # Mapping of known sources from which to build object files. - KNOWN_SUFFIXES = { - "AS" => "ASSUFFIX", - "SHCC" => "CSUFFIX", - "SHCXX" => "CXXSUFFIX", - "SHDC" => "DSUFFIX", - } - - # Run the builder to produce a build target. - def run(options) - if @command - deps = @sources - if File.exists?(@vars["_DEPFILE"]) - deps += Util.parse_makefile_deps(@vars["_DEPFILE"]) - end - @cache.register_build(@target, @command, deps.uniq, @env) - true - else - @vars["_TARGET"] = @target - @vars["_SOURCES"] = @sources - @vars["_DEPFILE"] = Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars)) - com_prefix = KNOWN_SUFFIXES.find do |compiler, suffix_var| - @sources.first.end_with?(*@env.expand_varref("${#{suffix_var}}", @vars)) - end.tap do |v| - v.nil? and raise "Error: unknown input file type: #{@sources.first.inspect}" - end.first - command = @env.build_command("${#{com_prefix}CMD}", @vars) - @env.produces(@target, @vars["_DEPFILE"]) - verb = com_prefix == "AS" ? "Assembling" : "Compiling" - message = "#{verb} #{Util.short_format_paths(@sources)}" - standard_command(message, command) - end - end - + include Mixins::Object end end end diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index fc492c9..1cca24c 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -779,6 +779,14 @@ EOF expect(`./test-static.exe`).to match /Hi from one/ end + it "creates shared libraries using assembly" do + test_dir("shared_library") + + result = run_rscons(rsconscript: "shared_library_as.rb") + expect(result.stderr).to eq "" + expect(File.exists?("file.S")).to be_truthy + end + it "creates shared libraries using C++" do test_dir("shared_library") @@ -1391,7 +1399,7 @@ EOF it "raises an error when given a source file with an unknown suffix" do test_dir("simple") result = run_rscons(rsconscript: "error_unknown_suffix.rb") - expect(result.stderr).to match /unknown input file type: "foo.xyz"/ + expect(result.stderr).to match /Unknown input file type: "foo.xyz"/ end end @@ -1399,7 +1407,7 @@ EOF it "raises an error when given a source file with an unknown suffix" do test_dir("shared_library") result = run_rscons(rsconscript: "error_unknown_suffix.rb") - expect(result.stderr).to match /unknown input file type: "foo.xyz"/ + expect(result.stderr).to match /Unknown input file type: "foo.xyz"/ end end