From 05bbea6fa166359b39c84e082a0e84cb42eaaa5f Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 25 May 2017 17:00:21 -0400 Subject: [PATCH] add Environment#build_after --- build_tests/custom_builder/build_after.rb | 8 +++++ build_tests/custom_builder/gen.rb | 9 ++++++ lib/rscons/environment.rb | 36 +++++++++++++++++++++++ spec/build_tests_spec.rb | 6 ++++ 4 files changed, 59 insertions(+) create mode 100644 build_tests/custom_builder/build_after.rb create mode 100644 build_tests/custom_builder/gen.rb diff --git a/build_tests/custom_builder/build_after.rb b/build_tests/custom_builder/build_after.rb new file mode 100644 index 0000000..60259dc --- /dev/null +++ b/build_tests/custom_builder/build_after.rb @@ -0,0 +1,8 @@ +Rscons::Environment.new do |env| + env.Command("inc.c", + [], + "CMD" => %w[ruby gen.rb ${_TARGET}], + "CMD_DESC" => "Generating") + env.build_after("program.o", "inc.c") + env.Program("program.exe", ["program.c", "inc.c"]) +end diff --git a/build_tests/custom_builder/gen.rb b/build_tests/custom_builder/gen.rb new file mode 100644 index 0000000..79310fd --- /dev/null +++ b/build_tests/custom_builder/gen.rb @@ -0,0 +1,9 @@ +sleep 1.0 +c_file = ARGV.first +h_file = File.basename(c_file, ".c") + ".h" +File.open(c_file, "w") do |fh| + fh.puts +end +File.open(h_file, "w") do |fh| + fh.puts("#define THE_VALUE 191") +end diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index cc8cbd2..805ed86 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -459,6 +459,42 @@ module Rscons @user_deps[target] = (@user_deps[target] + user_deps).uniq end + # Manually record the given target(s) as needing to be built after the + # given prerequisite(s). + # + # For example, consider a builder registered to generate gen.c which also + # generates gen.h as a side-effect. If program.c includes gen.h, then it + # should not be compiled before gen.h has been generated. When using + # multiple threads to build, Rscons may attempt to compile program.c before + # gen.h has been generated because it does not know that gen.h will be + # generated along with gen.c. One way to prevent that situation would be + # to first process the Environment with just the code-generation builders + # in place and then register the compilation builders. Another way is to + # use this method to record that a certain target should not be built until + # another has completed. For example, for the situation previously + # described: + # env.build_after("program.o", "gen.c") + # + # @since 1.10.0 + # + # @param targets [String, Array] + # Target files to wait to build until the prerequisites are finished + # building. + # @param prerequisites [String, Array] + # Files that must be built before building the specified targets. + # + # @return [void] + def build_after(targets, prerequisites) + targets = Array(targets) + prerequisites = Array(prerequisites) + targets.each do |target| + @registered_build_dependencies[target] ||= Set.new + prerequisites.each do |prerequisite| + @registered_build_dependencies[target] << prerequisite + end + end + end + # Return the list of user dependencies for a given target. # # @param target [String] Target file name. diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 2e7ff1e..4ff375a 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -1090,6 +1090,12 @@ EOF elapsed = Time.new - start_time expect(elapsed).to be < 4 end + + it "allows the user to specify that a target be built after another" do + test_dir("custom_builder") + result = run_test(rsconsfile: "build_after.rb", rscons_args: %w[-j 4]) + expect(result.stderr).to eq "" + end end context "CLI" do