diff --git a/lib/rscons/application.rb b/lib/rscons/application.rb index cdbfb84..9a1e39d 100644 --- a/lib/rscons/application.rb +++ b/lib/rscons/application.rb @@ -28,7 +28,6 @@ module Rscons @vars = VarSet.new @build_dir = "build" @prefix = "/usr/local" - @default_environment = Environment.new end # Run the specified operation. @@ -91,7 +90,7 @@ module Rscons end Ansi.write($stdout, "Setting build directory... ", :green, @build_dir, :reset, "\n") rv = 0 - co = ConfigureOp.new("#{@build_dir}/configure", @default_environment) + co = ConfigureOp.new("#{@build_dir}/configure") begin @script.configure(co) rescue ConfigureOp::ConfigureFailure diff --git a/lib/rscons/cache.rb b/lib/rscons/cache.rb index 0ad1949..014f6b0 100644 --- a/lib/rscons/cache.rb +++ b/lib/rscons/cache.rb @@ -124,6 +124,7 @@ module Rscons def write if @dirty || (@cache["version"] != VERSION) @cache["version"] = VERSION + validate_json_object(@cache) File.open(CACHE_FILE, "w") do |fh| fh.puts(JSON.dump(@cache)) end diff --git a/lib/rscons/configure_op.rb b/lib/rscons/configure_op.rb index 615b0b4..d9b3917 100644 --- a/lib/rscons/configure_op.rb +++ b/lib/rscons/configure_op.rb @@ -12,11 +12,8 @@ module Rscons # # @param work_dir [String] # Work directory for configure operation. - # @param env [Environment] - # Environment aggregating the configuration options. - def initialize(work_dir, env) + def initialize(work_dir) @work_dir = work_dir - @env = env FileUtils.mkdir_p(@work_dir) @log_fh = File.open("#{@work_dir}/config.log", "wb") end @@ -95,7 +92,7 @@ module Rscons command = [program, *args, package].compact stdout, _, status = log_and_test_command(command) if status == 0 - parse_flags(stdout) + store_parse(stdout, options) end common_config_checks(status, options) end @@ -116,7 +113,7 @@ module Rscons "_SOURCES" => "#{@work_dir}/cfgtest.c", "_TARGET" => "#{@work_dir}/cfgtest.exe", } - command = @env.build_command("${LDCMD}", vars) + command = Environment.new.build_command("${LDCMD}", vars) _, _, status = log_and_test_command(command) common_config_checks(status, options) end @@ -137,7 +134,7 @@ module Rscons "_SOURCES" => "#{@work_dir}/cfgtest.cxx", "_TARGET" => "#{@work_dir}/cfgtest.exe", } - command = @env.build_command("${LDCMD}", vars) + command = Environment.new.build_command("${LDCMD}", vars) _, _, status = log_and_test_command(command) common_config_checks(status, options) end @@ -158,7 +155,7 @@ module Rscons "_SOURCES" => "#{@work_dir}/cfgtest.d", "_TARGET" => "#{@work_dir}/cfgtest.exe", } - command = @env.build_command("${LDCMD}", vars) + command = Environment.new.build_command("${LDCMD}", vars) _, _, status = log_and_test_command(command) common_config_checks(status, options) end @@ -179,7 +176,7 @@ module Rscons "_SOURCES" => "#{@work_dir}/cfgtest.c", "_TARGET" => "#{@work_dir}/cfgtest.exe", } - command = @env.build_command("${LDCMD}", vars) + command = Environment.new.build_command("${LDCMD}", vars) _, _, status = log_and_test_command(command) common_config_checks(status, options) end @@ -237,7 +234,7 @@ module Rscons end _, _, status = log_and_test_command(command) if status == 0 - merge_vars(merge) + store_merge(merge) true end end @@ -273,7 +270,7 @@ module Rscons end _, _, status = log_and_test_command(command) if status == 0 - merge_vars(merge) + store_merge(merge) true end end @@ -301,10 +298,11 @@ module Rscons merge = {"DC" => "gdc"} when "ldc2" command = %W[ldc2 -of #{@work_dir}/cfgtest.exe #{@work_dir}/cfgtest.d] + env = Environment.new merge = { "DC" => "ldc2", - "DCCMD" => @env["DCCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, - "LDCMD" => @env["LDCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, + "DCCMD" => env["DCCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, + "LDCMD" => env["LDCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, } else $stderr.puts "Unknown D compiler (#{dc})" @@ -312,7 +310,7 @@ module Rscons end _, _, status = log_and_test_command(command) if status == 0 - merge_vars(merge) + store_merge(merge) true end end @@ -331,34 +329,59 @@ module Rscons end end - # Merge construction variables into the configured Environment. + # Store construction variables for merging into the Cache. # # @param vars [Hash] # Hash containing the variables to merge. - def merge_vars(vars) + # @param options [Hash] + # Options. + def store_merge(vars, options = {}) + usename = options[:use] || "_default_" + cache = Cache.instance + cache.configuration_data["vars"] ||= {} + cache.configuration_data["vars"][usename] ||= {} + cache.configuration_data["vars"][usename]["merge"] ||= {} vars.each_pair do |key, value| - @env[key] = value + cache.configuration_data["vars"][usename]["merge"][key] = value end end - # Merge construction variables into the configured Environment. - # - # This method does the same thing as {#merge_vars}, except that Array - # values in +vars+ are appended to the end of Array construction variables - # instead of replacing their contents. + # Store construction variables for appending into the Cache. # # @param vars [Hash] - # Hash containing the variables to merge. - def append_vars(vars) - vars.each_pair do |key, val| - if @env[key].is_a?(Array) and val.is_a?(Array) - @env[key] += val + # Hash containing the variables to append. + # @param options [Hash] + # Options. + def store_append(vars, options = {}) + usename = options[:use] || "_default_" + cache = Cache.instance + cache.configuration_data["vars"] ||= {} + cache.configuration_data["vars"][usename] ||= {} + cache.configuration_data["vars"][usename]["append"] ||= {} + vars.each_pair do |key, value| + if cache.configuration_data["vars"][usename]["append"][key].is_a?(Array) and value.is_a?(Array) + cache.configuration_data["vars"][usename]["append"][key] += value else - @env[key] = val + cache.configuration_data["vars"][usename]["append"][key] = value end end end + # Store flags to be parsed into the Cache. + # + # @param flags [String] + # String containing the flags to parse. + # @param options [Hash] + # Options. + def store_parse(flags, options = {}) + usename = options[:use] || "_default_" + cache = Cache.instance + cache.configuration_data["vars"] ||= {} + cache.configuration_data["vars"][usename] ||= {} + cache.configuration_data["vars"][usename]["parse"] ||= [] + cache.configuration_data["vars"][usename]["parse"] << flags + end + # Perform processing common to several configure checks. # # @param status [Process::Status, Integer] @@ -384,7 +407,7 @@ module Rscons end end if options[:set_define] - @env["CPPDEFINES"] << options[:set_define] + store_append("CPPDEFINES" => options[:set_define]) end end @@ -417,82 +440,5 @@ module Rscons end end - # Parse compilation flags (from a program like pkg-config for example). - # - # @param flags [String] - # Compilation flags. - def parse_flags(flags) - vars = {} - words = Shellwords.split(flags) - skip = false - words.each_with_index do |word, i| - if skip - skip = false - next - end - append = lambda do |var, val| - vars[var] ||= [] - vars[var] += val - end - handle = lambda do |var, val| - if val.nil? or val.empty? - val = words[i + 1] - skip = true - end - if val and not val.empty? - append[var, [val]] - end - end - if word == "-arch" - if val = words[i + 1] - append["CCFLAGS", ["-arch", val]] - append["LDFLAGS", ["-arch", val]] - end - skip = true - elsif word =~ /^#{@env["CPPDEFPREFIX"]}(.*)$/ - handle["CPPDEFINES", $1] - elsif word == "-include" - if val = words[i + 1] - append["CCFLAGS", ["-include", val]] - end - skip = true - elsif word == "-isysroot" - if val = words[i + 1] - append["CCFLAGS", ["-isysroot", val]] - append["LDFLAGS", ["-isysroot", val]] - end - skip = true - elsif word =~ /^#{@env["INCPREFIX"]}(.*)$/ - handle["CPPPATH", $1] - elsif word =~ /^#{@env["LIBLINKPREFIX"]}(.*)$/ - handle["LIBS", $1] - elsif word =~ /^#{@env["LIBDIRPREFIX"]}(.*)$/ - handle["LIBPATH", $1] - elsif word == "-mno-cygwin" - append["CCFLAGS", [word]] - append["LDFLAGS", [word]] - elsif word == "-mwindows" - append["LDFLAGS", [word]] - elsif word == "-pthread" - append["CCFLAGS", [word]] - append["LDFLAGS", [word]] - elsif word =~ /^-Wa,(.*)$/ - append["ASFLAGS", $1.split(",")] - elsif word =~ /^-Wl,(.*)$/ - append["LDFLAGS", $1.split(",")] - elsif word =~ /^-Wp,(.*)$/ - append["CPPFLAGS", $1.split(",")] - elsif word.start_with?("-") - append["CCFLAGS", [word]] - elsif word.start_with?("+") - append["CCFLAGS", [word]] - append["LDFLAGS", [word]] - else - append["LIBS", [word]] - end - end - append_vars(vars) - end - end end diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index ccd905b..88dc3e3 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -62,6 +62,7 @@ module Rscons end @echo = options[:echo] || :short @build_root = options[:build_root] || "build" + load_configuration_data! if block_given? yield self @@ -1102,5 +1103,28 @@ module Rscons end deps end + + # Load construction variables saved from the configure operation. + def load_configuration_data! + if vars = Cache.instance.configuration_data["vars"] + if default_vars = vars["_default_"] + apply_configuration_data!(default_vars) + end + end + end + + def apply_configuration_data!(vars) + if merge_vars = vars["merge"] + append(merge_vars) + end + if append_vars = vars["append"] + merge_flags(append_vars) + end + if parse_vars = vars["parse"] + parse_vars.each do |parse_string| + parse_flags!(parse_string) + end + end + end end end diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index dc5d06f..52f4b1a 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -134,6 +134,12 @@ EOF env = ENV.to_h env["PATH"] = "#{@build_test_run_dir}/_bin#{File::PATH_SEPARATOR}#{env["PATH"]}" stdout, stderr, status = Open3.capture3(env, *command) + File.open("#{@build_test_run_dir}/.stdout", "wb") do |fh| + fh.write(stdout) + end + File.open("#{@build_test_run_dir}/.stderr", "wb") do |fh| + fh.write(stderr) + end end # Remove output lines generated as a result of the test environment stderr = stderr.lines.find_all do |line|