diff --git a/build_tests/simple/absolute_source_path.rb b/build_tests/simple/absolute_source_path.rb new file mode 100644 index 0000000..2b1f812 --- /dev/null +++ b/build_tests/simple/absolute_source_path.rb @@ -0,0 +1,14 @@ +Rscons::Environment.new do |env| + env.build_root = "build" + tempdir = ENV["TEMP"] || ENV["TMP"] || "/tmp" + source_file = File.join(tempdir, "abs.c") + File.open(source_file, "w") do |fh| + fh.puts(<<-EOF) + int main() + { + return 29; + } + EOF + end + env.Program("abs.exe", source_file) +end diff --git a/lib/rscons.rb b/lib/rscons.rb index 02f6e0e..7af226f 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -71,7 +71,11 @@ module Rscons # # @return [Boolean] Whether the given path is an absolute filesystem path. def absolute_path?(path) - path =~ %r{^(/|\w:[\\/])} + if RUBY_PLATFORM =~ /mingw/ + path =~ %r{^(?:\w:)?[\\/]} + else + path.start_with?("/") + end end # Return whether the given target is a phony target. diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index f120e02..4f0bd74 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -245,12 +245,17 @@ module Rscons end end if @build_root and not found_match - unless Rscons.absolute_path?(source_fname) or build_fname.start_with?("#{@build_root}/") + if Rscons.absolute_path?(build_fname) + if build_fname =~ %r{^(\w):(.*)$} + build_fname = "#{@build_root}/_#{$1}#{$2}" + else + build_fname = "#{@build_root}/_#{build_fname}" + end + elsif !build_fname.start_with?("#{@build_root}/") build_fname = "#{@build_root}/#{build_fname}" end end - build_fname.gsub!('\\', '/') - build_fname + build_fname.gsub('\\', '/') end # Get a construction variable's value. diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 3b61882..d4f7149 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -662,6 +662,15 @@ EOF ] end + it "creates object files under the build root for absolute source paths" do + test_dir("simple") + result = run_test(rsconsfile: "absolute_source_path.rb") + expect(result.stderr).to eq "" + slines = lines(result.stdout) + expect(slines[0]).to match(%r{^CC build/.*/abs\.o$}) + expect(slines[1]).to eq "LD abs.exe" + end + context "backward compatibility" do it "allows a builder to call Environment#run_builder in a non-threaded manner" do test_dir("simple") diff --git a/spec/rscons/environment_spec.rb b/spec/rscons/environment_spec.rb index a11dde1..0d31220 100644 --- a/spec/rscons/environment_spec.rb +++ b/spec/rscons/environment_spec.rb @@ -91,12 +91,13 @@ module Rscons end context "with a build_root" do - it "uses the build_root unless the path is absolute" do + it "uses the build_root" do + stub_const("RUBY_PLATFORM", "mingw") env = Environment.new env.build_root = "build/proj" expect(env.get_build_fname("src/dir/file.c", ".o")).to eq "build/proj/src/dir/file.o" - expect(env.get_build_fname("/some/lib.c", ".a")).to eq "/some/lib.a" - expect(env.get_build_fname("C:\\abspath\\mod.cc", ".o")).to eq "C:/abspath/mod.o" + expect(env.get_build_fname("/some/lib.c", ".a")).to eq "build/proj/_/some/lib.a" + expect(env.get_build_fname("C:\\abspath\\mod.cc", ".o")).to eq "build/proj/_C/abspath/mod.o" expect(env.get_build_fname("build\\proj\\generated.c", ".o")).to eq "build/proj/generated.o" expect(env.get_build_fname("build/proj.XX", ".yy")).to eq "build/proj/build/proj.yy" end diff --git a/spec/rscons_spec.rb b/spec/rscons_spec.rb index 6468f9e..7170e8d 100644 --- a/spec/rscons_spec.rb +++ b/spec/rscons_spec.rb @@ -24,6 +24,34 @@ describe Rscons do end end + describe ".absolute_path?" do + context "on Windows" do + it "returns whether a path is absolute" do + stub_const("RUBY_PLATFORM", "mingw") + expect(Rscons.absolute_path?("/foo")).to be_truthy + expect(Rscons.absolute_path?("\\Windows")).to be_truthy + expect(Rscons.absolute_path?("C:\\Windows")).to be_truthy + expect(Rscons.absolute_path?("f:\\stuff")).to be_truthy + expect(Rscons.absolute_path?("g:/projects")).to be_truthy + expect(Rscons.absolute_path?("x:foo")).to be_falsey + expect(Rscons.absolute_path?("file.txt")).to be_falsey + end + end + + context "not on Windows" do + it "returns whether a path is absolute" do + stub_const("RUBY_PLATFORM", "linux") + expect(Rscons.absolute_path?("/foo")).to be_truthy + expect(Rscons.absolute_path?("\\Windows")).to be_falsey + expect(Rscons.absolute_path?("C:\\Windows")).to be_falsey + expect(Rscons.absolute_path?("f:\\stuff")).to be_falsey + expect(Rscons.absolute_path?("g:/projects")).to be_falsey + expect(Rscons.absolute_path?("x:foo")).to be_falsey + expect(Rscons.absolute_path?("file.txt")).to be_falsey + end + end + end + describe ".set_suffix" do it "changes the suffix to the new one" do expect(Rscons.set_suffix("foo.c", ".h")).to eq("foo.h")