From 1e157c79ecd470f347c1861c054c22eae295ed98 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 19 Aug 2019 22:56:54 -0400 Subject: [PATCH] fix dependency parsing with ldc2 - close #110 --- build_tests/d/Rsconscript | 4 +++ build_tests/d/build-ldc2.rb | 9 +++++++ lib/rscons/builders/mixins/depfile.rb | 2 +- lib/rscons/configure_op.rb | 1 + lib/rscons/util.rb | 10 +++++--- spec/build_tests_spec.rb | 35 ++++++++++++++++++++++++++- spec/rscons/util_spec.rb | 19 ++++++++++++--- 7 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 build_tests/d/build-ldc2.rb diff --git a/build_tests/d/Rsconscript b/build_tests/d/Rsconscript index efdef30..0a9e126 100644 --- a/build_tests/d/Rsconscript +++ b/build_tests/d/Rsconscript @@ -1,3 +1,7 @@ +configure do + check_d_compiler "gdc" +end + build do Environment.new(echo: :command) do |env| env.Program("hello-d.exe", glob("*.d")) diff --git a/build_tests/d/build-ldc2.rb b/build_tests/d/build-ldc2.rb new file mode 100644 index 0000000..0d1c7a5 --- /dev/null +++ b/build_tests/d/build-ldc2.rb @@ -0,0 +1,9 @@ +configure do + check_d_compiler "ldc2" +end + +build do + Environment.new(echo: :command) do |env| + env.Program("hello-d.exe", glob("*.d")) + end +end diff --git a/lib/rscons/builders/mixins/depfile.rb b/lib/rscons/builders/mixins/depfile.rb index 9b5ce49..a32f54e 100644 --- a/lib/rscons/builders/mixins/depfile.rb +++ b/lib/rscons/builders/mixins/depfile.rb @@ -9,7 +9,7 @@ module Rscons def finalize_command_with_depfile deps = @sources if File.exists?(@vars["_DEPFILE"]) - deps += Util.parse_makefile_deps(@vars["_DEPFILE"]) + deps += Util.parse_dependency_file(@vars["_DEPFILE"]) end @cache.register_build(@target, @command, deps.uniq, @env) true diff --git a/lib/rscons/configure_op.rb b/lib/rscons/configure_op.rb index 458ce10..f98036f 100644 --- a/lib/rscons/configure_op.rb +++ b/lib/rscons/configure_op.rb @@ -479,6 +479,7 @@ module Rscons "DC" => dc, "DCCMD" => env["DCCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, "LDCMD" => env["LDCMD"].map {|e| if e == "-o"; "-of"; else; e; end}, + "DDEPGEN" => ["-deps=${_DEPFILE}"], } end _, _, status = log_and_test_command(command) diff --git a/lib/rscons/util.rb b/lib/rscons/util.rb index 0416664..cca75e9 100644 --- a/lib/rscons/util.rb +++ b/lib/rscons/util.rb @@ -160,7 +160,7 @@ module Rscons end end - # Parse dependencies from a Makefile. + # Parse dependencies from a Makefile or ldc2 dependency file. # # This method is used internally by Rscons builders. # @@ -169,7 +169,7 @@ module Rscons # # @return [Array] # Paths of dependency files. - def parse_makefile_deps(mf_fname) + def parse_dependency_file(mf_fname) deps = [] buildup = '' File.read(mf_fname).each_line do |line| @@ -177,7 +177,11 @@ module Rscons buildup += ' ' + $1 else buildup += ' ' + line - if buildup =~ /^.*: (.*)$/ + if buildup =~ /^[^:]+\(\S+\)\s*:.*?:[^:]+\((\S+)\)/ + # ldc2-style dependency line + deps << $1 + elsif buildup =~ /^.*: (.*)$/ + # Makefile-style dependency line mf_deps = $1 deps += mf_deps.split(' ').map(&:strip) end diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index d628f27..cf1e328 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -589,7 +589,7 @@ EOF end unless ENV["omit_gdc_tests"] - it "supports building D sources" do + it "supports building D sources with gdc" do test_dir("d") result = run_rscons expect(result.stderr).to eq "" @@ -600,6 +600,39 @@ EOF expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!" end + it "supports building D sources with ldc2" do + test_dir("d") + result = run_rscons(rsconscript: "build-ldc2.rb") + expect(result.stderr).to eq "" + slines = lines(result.stdout) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/main.o -deps=build/e.1/main.mf main.d}]) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o -deps=build/e.1/mod.mf mod.d}]) + verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o build/e.1/mod.o}]) + expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!" + end + + it "rebuilds D modules with ldc2 when deep dependencies change" do + test_dir("d") + result = run_rscons(rsconscript: "build-ldc2.rb") + expect(result.stderr).to eq "" + slines = lines(result.stdout) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/main.o -deps=build/e.1/main.mf main.d}]) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o -deps=build/e.1/mod.mf mod.d}]) + verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o build/e.1/mod.o}]) + expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!" + contents = File.read("mod.d", mode: "rb").sub("42", "33") + File.open("mod.d", "wb") do |fh| + fh.write(contents) + end + result = run_rscons(rsconscript: "build-ldc2.rb") + expect(result.stderr).to eq "" + slines = lines(result.stdout) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/main.o -deps=build/e.1/main.mf main.d}]) + verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o -deps=build/e.1/mod.mf mod.d}]) + verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o build/e.1/mod.o}]) + expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 33!" + end + it "links with the D linker when object files were built from D sources" do test_dir("d") result = run_rscons(rsconscript: "link_objects.rb") diff --git a/spec/rscons/util_spec.rb b/spec/rscons/util_spec.rb index 99e7d42..6771e79 100644 --- a/spec/rscons/util_spec.rb +++ b/spec/rscons/util_spec.rb @@ -197,12 +197,12 @@ EOF end end - describe ".parse_makefile_deps" do + describe ".parse_dependency_file" do it 'handles dependencies on one line' do expect(File).to receive(:read).with('makefile').and_return(< sock +EOS + expect(Util.parse_dependency_file("deps.out")).to eq [ + "/usr/lib/ldc/x86_64-linux-gnu/include/d/std/meta.d", + "/usr/lib/ldc/x86_64-linux-gnu/include/d/std/array.d", + "/usr/lib/ldc/x86_64-linux-gnu/include/d/core/sys/posix/sys/socket.d", + ] + end end end