From a316c4f922c60c5fc2df137274d40ea0ab44bd43 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 13 Jan 2022 12:56:23 -0500 Subject: [PATCH] Support naming environments - close #140 --- build_tests/typical/Rsconscript | 6 ++++++ build_tests/typical/clone_and_name.rb | 9 +++++++++ doc/user_guide.md | 18 +++++++++++++++++- lib/rscons/configure_op.rb | 2 +- lib/rscons/environment.rb | 16 ++++++++++++---- spec/build_tests_spec.rb | 23 ++++++++++++++++++++--- 6 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 build_tests/typical/Rsconscript create mode 100644 build_tests/typical/clone_and_name.rb diff --git a/build_tests/typical/Rsconscript b/build_tests/typical/Rsconscript new file mode 100644 index 0000000..32ef1d5 --- /dev/null +++ b/build_tests/typical/Rsconscript @@ -0,0 +1,6 @@ +build do + Environment.new(name: "typical") do |env| + env["CPPPATH"] += glob("src/**") + env.Program("^/typical.exe", glob("src/**/*.c")) + end +end diff --git a/build_tests/typical/clone_and_name.rb b/build_tests/typical/clone_and_name.rb new file mode 100644 index 0000000..ab4b28d --- /dev/null +++ b/build_tests/typical/clone_and_name.rb @@ -0,0 +1,9 @@ +build do + base_env = Environment.new do |env| + env["CPPPATH"] += glob("src/**") + end + + base_env.clone(name: "typical") do |env| + env.Program("^/typical.exe", glob("src/**/*.c")) + end +end diff --git a/doc/user_guide.md b/doc/user_guide.md index 8e98b1f..0a4da54 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -82,6 +82,15 @@ files, dependency files, etc...) and build system metadata in a "build directory". This keeps files generated by the build cleanly separated from user-controlled source files. + +In contrast to other build systems or build system generators, rscons executes +from the project base directory (up to the user) rather than executing from +*within* the build directory. +This keeps any file paths printed by compilers (such as in warning or error +messages) accurate relative to the project directory, so that the user does not +need to translate any paths to the correct path within a terminal or editor +application, for example. + By default a build directory named "build" is used, but this can be overridden by the user by using the `-b`/`--build` command-line option. @@ -495,21 +504,26 @@ source files found recursively under the `src` directory. An Environment includes: + - a name - a collection of construction variables - a collection of build hooks - a collection of user-registered build targets - a build root All build targets must be registered within an `Environment`. +If the user does not specify a name for the environment, a name will be +automatically generated based on the Environment's internal ID, for example +"e.1". The Environment's build root is a directory created within the top-level Rscons build directory. +It is based on the Environment name. By default it holds all intermediate files generated by Rscons that are needed to produce a user-specified build target. For example, for the `Rsconscript`: ```ruby build do - Environment.new do |env| + Environment.new(name: "myproj") do |env| env.Program("myprog.exe", glob("src/**/*.c")) end end @@ -517,6 +531,8 @@ end Rscons will place an object file and dependency file corresponding to each C source file under the Environment's build root. +Assuming a top-level build directory of "build", the Environment's build root +would be "build/myproj". This keeps the intermediate generated build artifacts separate from the source files. diff --git a/lib/rscons/configure_op.rb b/lib/rscons/configure_op.rb index a664e80..5a3f419 100644 --- a/lib/rscons/configure_op.rb +++ b/lib/rscons/configure_op.rb @@ -16,7 +16,7 @@ module Rscons def initialize(options) # Default options. options[:prefix] ||= "/usr/local" - @work_dir = "#{Rscons.application.build_dir}/configure" + @work_dir = "#{Rscons.application.build_dir}/_configure" FileUtils.mkdir_p(@work_dir) @log_fh = File.open("#{@work_dir}/config.log", "wb") cache = Cache.instance diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index ab728c8..c5c47bb 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -51,6 +51,10 @@ module Rscons # global Rscons.application.n_threads value. attr_accessor :n_threads + # @return [String] + # Environment name. + attr_reader :name + # Create an Environment object. # # @param options [Hash] @@ -58,6 +62,9 @@ module Rscons # :command, :short, or :off (default :short) # @option options [Boolean] :exclude_builders # Whether to omit adding default builders (default false) + # @option options [String, nil] :name + # Environment name. This determines the folder name used to store all + # environment build files under the top-level build directory. # @option options [String, Array] :use # Use flag(s). If specified, any configuration flags which were saved # with a corresponding `:use` value will be applied to this Environment. @@ -97,7 +104,8 @@ module Rscons else :short end - @build_root = "#{Rscons.application.build_dir}/e.#{@id}" + @name = options[:name] || "e.#{@id}" + @build_root = "#{Rscons.application.build_dir}/#{@name}" @n_threads = Rscons.application.n_threads if block_given? @@ -125,14 +133,14 @@ module Rscons # # @return [Environment] The newly created {Environment} object. def clone(options = {}) + options = options.dup clone = options[:clone] || :all clone = Set[:variables, :builders, :build_hooks] if clone == :all clone = Set[] if clone == :none clone = Set.new(clone) if clone.is_a?(Array) clone.delete(:builders) if options[:exclude_builders] - env = self.class.new( - echo: options[:echo] || @echo, - exclude_builders: true) + options[:echo] ||= @echo + env = self.class.new(options.merge(exclude_builders: true)) if clone.include?(:builders) @builders.each do |builder_name, builder| env.add_builder(builder) diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 49c40e2..cf77aa9 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -1085,6 +1085,23 @@ EOF expect(result.status).to eq 0 end + it "stores build artifacts in a directory according to Environment name" do + test_dir "typical" + + result = run_rscons + expect(File.exist?("build/typical/typical.exe")).to be_truthy + expect(File.exist?("build/typical/src/one/one.c.o")).to be_truthy + end + + it "names Environment during clone" do + test_dir "typical" + + result = run_rscons(rsconscript: "clone_and_name.rb") + expect(File.exist?("build/typical/typical.exe")).to be_truthy + expect(File.exist?("build/typical/src/one/one.c.o")).to be_truthy + expect(Dir.exist?("build/e.1")).to be_falsey + end + context "colored output" do it "does not output in color with --color=off" do test_dir("simple") @@ -1765,13 +1782,13 @@ EOF expect(result.stderr).to eq "" expect(result.status).to eq 0 expect(result.stdout).to match /Checking for C compiler\.\.\./ - expect(Dir.exist?("build/configure")).to be_truthy + expect(Dir.exist?("build/_configure")).to be_truthy result = run_rscons(rsconscript: "check_c_compiler.rb", rscons_args: %w[--build=bb]) expect(result.stderr).to eq "" expect(result.status).to eq 0 expect(result.stdout).to match /Checking for C compiler\.\.\./ - expect(Dir.exist?("bb/configure")).to be_truthy + expect(Dir.exist?("bb/_configure")).to be_truthy end context "check_c_compiler" do @@ -2321,7 +2338,7 @@ EOF expect(result.stdout).to match /Checking for library 'm'\.\.\. found/ expect(result.stdout).to match /Checking for program 'ls'\.\.\. .*ls/ expect(Dir.exist?("build")).to be_falsey - expect(Dir.exist?("bb/configure")).to be_truthy + expect(Dir.exist?("bb/_configure")).to be_truthy end it "aggregates multiple set_define's" do