Always use a build root and default it to "build"

This commit is contained in:
Josh Holtrop 2017-05-30 11:06:32 -04:00
parent 43df46018c
commit c7e4e1ad9b
5 changed files with 76 additions and 85 deletions

View File

@ -3,6 +3,6 @@ Rscons::Environment.new do |env|
[], [],
"CMD" => %w[ruby gen.rb ${_TARGET}], "CMD" => %w[ruby gen.rb ${_TARGET}],
"CMD_DESC" => "Generating") "CMD_DESC" => "Generating")
env.build_after("program.o", "inc.c") env.build_after("#{env.build_root}/program.o", "inc.c")
env.Program("program.exe", ["program.c", "inc.c"]) env.Program("program.exe", ["program.c", "inc.c"])
end end

View File

@ -1,5 +1,4 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.build_root = "build"
env.add_builder(:Checker) do |target, sources, cache, env, vars| env.add_builder(:Checker) do |target, sources, cache, env, vars|
unless cache.up_to_date?(target, :Checker, sources, env) unless cache.up_to_date?(target, :Checker, sources, env)
puts "Checker #{sources.first}" if env.echo != :off puts "Checker #{sources.first}" if env.echo != :off

View File

@ -14,15 +14,15 @@ module Rscons
# @return [Symbol] :command, :short, or :off # @return [Symbol] :command, :short, or :off
attr_accessor :echo attr_accessor :echo
# @return [String, nil] The build root. # @return [String] The build root.
attr_reader :build_root attr_reader :build_root
# Set the build root. # Set the build root.
# #
# @param build_root [String] The build root. # @param build_root [String] The build root.
def build_root=(build_root) def build_root=(build_root)
@build_root = build_root raise "build_root must be non-nil" unless build_root
@build_root.gsub!('\\', '/') if @build_root @build_root = build_root.gsub("\\", "/")
end end
# Create an Environment object. # Create an Environment object.
@ -31,7 +31,7 @@ module Rscons
# @option options [Symbol] :echo # @option options [Symbol] :echo
# :command, :short, or :off (default :short) # :command, :short, or :off (default :short)
# @option options [String] :build_root # @option options [String] :build_root
# Build root directory (default nil) # Build root directory (default "build")
# @option options [Boolean] :exclude_builders # @option options [Boolean] :exclude_builders
# Whether to omit adding default builders (default false) # Whether to omit adding default builders (default false)
# #
@ -54,7 +54,7 @@ module Rscons
end end
end end
@echo = options[:echo] || :short @echo = options[:echo] || :short
@build_root = options[:build_root] @build_root = options[:build_root] || "build"
if block_given? if block_given?
yield self yield self
@ -244,7 +244,7 @@ module Rscons
build_fname.sub!(%r{^#{src_dir}/}, "#{obj_dir}/") build_fname.sub!(%r{^#{src_dir}/}, "#{obj_dir}/")
end end
end end
if @build_root and not found_match unless found_match
if Rscons.absolute_path?(build_fname) if Rscons.absolute_path?(build_fname)
if build_fname =~ %r{^(\w):(.*)$} if build_fname =~ %r{^(\w):(.*)$}
build_fname = "#{@build_root}/_#{$1}#{$2}" build_fname = "#{@build_root}/_#{$1}#{$2}"
@ -432,10 +432,10 @@ module Rscons
# #
# @return [void] # @return [void]
def add_target(target, builder, sources, vars, args) def add_target(target, builder, sources, vars, args)
target = expand_path(target) if @build_root target = expand_path(target)
target = expand_varref(target) target = expand_varref(target)
sources = sources.map do |source| sources = sources.map do |source|
source = expand_path(source) if @build_root source = expand_path(source)
expand_varref(source) expand_varref(source)
end.flatten end.flatten
setup_info = builder.setup( setup_info = builder.setup(

View File

@ -116,7 +116,7 @@ EOF
test_dir('simple') test_dir('simple')
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?('simple.o')).to be_truthy expect(File.exists?('build/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n" expect(`./simple.exe`).to eq "This is a simple C program\n"
end end
@ -125,8 +125,8 @@ EOF
result = run_test(rsconsfile: "command.rb") result = run_test(rsconsfile: "command.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
'gcc -c -o simple.o -MMD -MF simple.mf simple.c', 'gcc -c -o build/simple.o -MMD -MF build/simple.mf simple.c',
"gcc -o simple.exe simple.o", "gcc -o simple.exe build/simple.o",
] ]
end end
@ -135,7 +135,7 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
'CC header.o', 'CC build/header.o',
"LD header.exe", "LD header.exe",
] ]
end end
@ -144,7 +144,7 @@ EOF
test_dir('header') test_dir('header')
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?('header.o')).to be_truthy expect(File.exists?('build/header.o')).to be_truthy
expect(`./header.exe`).to eq "The value is 2\n" expect(`./header.exe`).to eq "The value is 2\n"
end end
@ -164,7 +164,7 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
'CC header.o', 'CC build/header.o',
"LD header.exe", "LD header.exe",
] ]
expect(`./header.exe`).to eq "The value is 2\n" expect(`./header.exe`).to eq "The value is 2\n"
@ -178,7 +178,7 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
'CC header.o', 'CC build/header.o',
"LD header.exe", "LD header.exe",
] ]
expect(`./header.exe`).to eq "The value is 2\n" expect(`./header.exe`).to eq "The value is 2\n"
@ -194,13 +194,13 @@ EOF
result = run_test(rsconsfile: "command.rb") result = run_test(rsconsfile: "command.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
'gcc -c -o simple.o -MMD -MF simple.mf simple.c', 'gcc -c -o build/simple.o -MMD -MF build/simple.mf simple.c',
"gcc -o simple.exe simple.o", "gcc -o simple.exe build/simple.o",
] ]
result = run_test(rsconsfile: "link_flag_change.rb") result = run_test(rsconsfile: "link_flag_change.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"gcc -o simple.exe simple.o -Llibdir", "gcc -o simple.exe build/simple.o -Llibdir",
] ]
end end
@ -300,7 +300,7 @@ EOF
test_dir('custom_builder') test_dir('custom_builder')
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq ["CC program.o", "LD program.exe"] expect(lines(result.stdout)).to eq ["CC build/program.o", "LD program.exe"]
expect(File.exists?('inc.h')).to be_truthy expect(File.exists?('inc.h')).to be_truthy
expect(`./program.exe`).to eq "The value is 5678\n" expect(`./program.exe`).to eq "The value is 5678\n"
end end
@ -311,7 +311,7 @@ EOF
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
slines = lines(result.stdout) slines = lines(result.stdout)
expect(slines[0]).to eq("CHGen inc.c") expect(slines[0]).to eq("CHGen inc.c")
expect(Set[*slines[1..2]]).to eq(Set["CC program.o", "CC inc.o"]) expect(Set[*slines[1..2]]).to eq(Set["CC build/program.o", "CC build/inc.o"])
expect(slines[3]).to eq("LD program.exe") expect(slines[3]).to eq("LD program.exe")
expect(File.exists?("inc.c")).to be_truthy expect(File.exists?("inc.c")).to be_truthy
expect(File.exists?("inc.h")).to be_truthy expect(File.exists?("inc.h")).to be_truthy
@ -355,7 +355,7 @@ EOF
test_dir('simple_cc') test_dir('simple_cc')
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?('simple.o')).to be_truthy expect(File.exists?('build/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C++ program\n" expect(`./simple.exe`).to eq "This is a simple C++ program\n"
end end
@ -365,8 +365,8 @@ EOF
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(Set[*lines(result.stdout)]).to eq Set[ expect(Set[*lines(result.stdout)]).to eq Set[
'gcc -c -o one.o -MMD -MF one.mf -DONE one.c', 'gcc -c -o one.o -MMD -MF one.mf -DONE one.c',
'gcc -c -o two.o -MMD -MF two.mf two.c', 'gcc -c -o build/two.o -MMD -MF build/two.mf two.c',
"gcc -o two_sources.exe one.o two.o", "gcc -o two_sources.exe one.o build/two.o",
] ]
expect(File.exists?("two_sources.exe")).to be_truthy expect(File.exists?("two_sources.exe")).to be_truthy
expect(`./two_sources.exe`).to eq "This is a C program with two sources.\n" expect(`./two_sources.exe`).to eq "This is a C program with two sources.\n"
@ -377,11 +377,11 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(Set[*lines(result.stdout)]).to eq Set[ expect(Set[*lines(result.stdout)]).to eq Set[
'gcc -c -o one.o -MMD -MF one.mf -Dmake_lib one.c', 'gcc -c -o build/one.o -MMD -MF build/one.mf -Dmake_lib one.c',
'gcc -c -o two.o -MMD -MF two.mf -Dmake_lib two.c', 'gcc -c -o build/two.o -MMD -MF build/two.mf -Dmake_lib two.c',
'ar rcs lib.a one.o two.o', 'ar rcs lib.a build/one.o build/two.o',
'gcc -c -o three.o -MMD -MF three.mf three.c', 'gcc -c -o build/three.o -MMD -MF build/three.mf three.c',
"gcc -o library.exe lib.a three.o", "gcc -o library.exe lib.a build/three.o",
] ]
expect(File.exists?("library.exe")).to be_truthy expect(File.exists?("library.exe")).to be_truthy
expect(`ar t lib.a`).to eq "one.o\ntwo.o\n" expect(`ar t lib.a`).to eq "one.o\ntwo.o\n"
@ -405,8 +405,8 @@ EOF
File.open("program.ld", "w") {|fh| fh.puts("1")} File.open("program.ld", "w") {|fh| fh.puts("1")}
result = run_test(rsconsfile: "user_dependencies.rb") result = run_test(rsconsfile: "user_dependencies.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq ["CC simple.o", "LD simple.exe"] expect(lines(result.stdout)).to eq ["CC build/simple.o", "LD simple.exe"]
expect(File.exists?('simple.o')).to be_truthy expect(File.exists?('build/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n" expect(`./simple.exe`).to eq "This is a simple C program\n"
File.open("program.ld", "w") {|fh| fh.puts("2")} File.open("program.ld", "w") {|fh| fh.puts("2")}
@ -430,8 +430,8 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"gdc -c -o main.o main.d", "gdc -c -o build/main.o main.d",
"gdc -o hello-d.exe main.o", "gdc -o hello-d.exe build/main.o",
] ]
expect(`./hello-d.exe`.rstrip).to eq "Hello from D!" expect(`./hello-d.exe`.rstrip).to eq "Hello from D!"
end end
@ -476,7 +476,7 @@ EOF
test_dir('custom_builder') test_dir('custom_builder')
result = run_test(rsconsfile: "cvar_expansion.rb") result = run_test(rsconsfile: "cvar_expansion.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq ["CC program.o", "LD program.exe"] expect(lines(result.stdout)).to eq ["CC build/program.o", "LD program.exe"]
expect(File.exists?('inc.h')).to be_truthy expect(File.exists?('inc.h')).to be_truthy
expect(`./program.exe`).to eq "The value is 678\n" expect(`./program.exe`).to eq "The value is 678\n"
end end
@ -492,8 +492,8 @@ EOF
test_dir("simple") test_dir("simple")
result = run_test(rsconsfile: "register_target_in_build_hook.rb") result = run_test(rsconsfile: "register_target_in_build_hook.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?("simple.o")).to be_truthy expect(File.exists?("build/simple.o")).to be_truthy
expect(File.exists?("simple.o.txt")).to be_truthy expect(File.exists?("build/simple.o.txt")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n" expect(`./simple.exe`).to eq "This is a simple C program\n"
end end
@ -502,8 +502,8 @@ EOF
File.open("other.cccc", "w") {|fh| fh.puts} File.open("other.cccc", "w") {|fh| fh.puts}
result = run_test(rsconsfile: "cxxsuffix.rb") result = run_test(rsconsfile: "cxxsuffix.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?("simple.o")).to be_truthy expect(File.exists?("build/simple.o")).to be_truthy
expect(File.exists?("other.o")).to be_truthy expect(File.exists?("build/other.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C++ program\n" expect(`./simple.exe`).to eq "This is a simple C++ program\n"
end end
@ -512,8 +512,8 @@ EOF
FileUtils.mv("src/one/one.c", "src/one/one.yargh") FileUtils.mv("src/one/one.c", "src/one/one.yargh")
result = run_test(rsconsfile: "csuffix.rb") result = run_test(rsconsfile: "csuffix.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?("src/one/one.o")).to be_truthy expect(File.exists?("build/src/one/one.o")).to be_truthy
expect(File.exists?("src/two/two.o")).to be_truthy expect(File.exists?("build/src/two/two.o")).to be_truthy
expect(`./build_dir.exe`).to eq "Hello from two()\n" expect(`./build_dir.exe`).to eq "Hello from two()\n"
end end
@ -542,8 +542,8 @@ EOF
expect(Set[*lines(result.stdout)]).to eq Set[ expect(Set[*lines(result.stdout)]).to eq Set[
"CC one.ssss", "CC one.ssss",
"CC two.sss", "CC two.sss",
"AS one.o", "AS build/one.o",
"AS two.o", "AS build/two.o",
"LD two_sources.exe", "LD two_sources.exe",
] ]
expect(File.exists?("two_sources.exe")).to be_truthy expect(File.exists?("two_sources.exe")).to be_truthy
@ -585,7 +585,7 @@ EOF
test_dir("simple") test_dir("simple")
result = run_test(rsconsfile: "cvar_array.rb") result = run_test(rsconsfile: "cvar_array.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(File.exists?("simple.o")).to be_truthy expect(File.exists?("build/simple.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n" expect(`./simple.exe`).to eq "This is a simple C program\n"
end end
@ -637,7 +637,7 @@ EOF
result = run_test(rsconsfile: "progsuffix.rb") result = run_test(rsconsfile: "progsuffix.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.out", "LD simple.out",
] ]
end end
@ -647,7 +647,7 @@ EOF
result = run_test(rsconsfile: "progsuffix2.rb") result = run_test(rsconsfile: "progsuffix2.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.out", "LD simple.out",
] ]
end end
@ -657,7 +657,7 @@ EOF
result = run_test(rsconsfile: "progsuffix3.rb") result = run_test(rsconsfile: "progsuffix3.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.xyz", "LD simple.xyz",
] ]
end end
@ -688,7 +688,7 @@ EOF
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC simple.o",
"CC two.o", "CC build/two.o",
"MyProgram simple.exe", "MyProgram simple.exe",
] ]
end end
@ -867,24 +867,18 @@ EOF
end end
context "phony targets" do context "phony targets" do
[false, true].each do |with_build_root|
context "with#{with_build_root ? "" : "out"} build root" do
it "allows specifying a Symbol as a target name and reruns the builder if the sources or command have changed" do it "allows specifying a Symbol as a target name and reruns the builder if the sources or command have changed" do
test_dir("simple") test_dir("simple")
FileUtils.cp("phony_target.rb", "phony_target2.rb") result = run_test(rsconsfile: "phony_target.rb")
unless with_build_root
file_sub("phony_target2.rb") {|line| line.sub(/.*build_root.*/, "")}
end
result = run_test(rsconsfile: "phony_target2.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq([ expect(lines(result.stdout)).to eq([
"CC #{with_build_root ? "build/" : ""}simple.o", "CC build/simple.o",
"LD simple.exe", "LD simple.exe",
"Checker simple.exe", "Checker simple.exe",
]) ])
result = run_test(rsconsfile: "phony_target2.rb") result = run_test(rsconsfile: "phony_target.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(result.stdout).to eq "" expect(result.stdout).to eq ""
@ -900,8 +894,6 @@ EOF
]) ])
end end
end end
end
end
context "Environment#clear_targets" do context "Environment#clear_targets" do
it "clears registered targets" do it "clears registered targets" do
@ -971,7 +963,7 @@ EOF
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.exe", "LD simple.exe",
] ]
@ -1044,7 +1036,7 @@ EOF
result = run_test(rsconsfile: "cache_user_dep.rb") result = run_test(rsconsfile: "cache_user_dep.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.exe", "LD simple.exe",
] ]
@ -1064,7 +1056,7 @@ EOF
result = run_test(rsconsfile: "cache_user_dep.rb") result = run_test(rsconsfile: "cache_user_dep.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
"CC simple.o", "CC build/simple.o",
"LD simple.exe", "LD simple.exe",
] ]
@ -1112,7 +1104,7 @@ EOF
test_dir("library") test_dir("library")
result = run_test(rsconsfile: "override_arcmd.rb") result = run_test(rsconsfile: "override_arcmd.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to include "ar rcf lib.a one.o three.o two.o" expect(lines(result.stdout)).to include "ar rcf lib.a build/one.o build/three.o build/two.o"
end end
end end

View File

@ -85,9 +85,9 @@ module Rscons
context "with no build directories" do context "with no build directories" do
it "returns the name of the source file with suffix changed" do it "returns the name of the source file with suffix changed" do
env = Environment.new env = Environment.new
expect(env.get_build_fname("src/dir/file.c", ".o")).to eq "src/dir/file.o" expect(env.get_build_fname("src/dir/file.c", ".o")).to eq "build/src/dir/file.o"
expect(env.get_build_fname("src\\dir\\other.d", ".a")).to eq "src/dir/other.a" expect(env.get_build_fname("src\\dir\\other.d", ".a")).to eq "build/src/dir/other.a"
expect(env.get_build_fname("source.cc", ".o")).to eq "source.o" expect(env.get_build_fname("source.cc", ".o")).to eq "build/source.o"
end end
context "with a build_root" do context "with a build_root" do
@ -112,7 +112,7 @@ module Rscons
expect(env.get_build_fname("src/input.cc", ".o")).to eq "bld/input.o" expect(env.get_build_fname("src/input.cc", ".o")).to eq "bld/input.o"
expect(env.get_build_fname("libs/lib1/some/file.c", ".o")).to eq "build/libs/lib1/some/file.o" expect(env.get_build_fname("libs/lib1/some/file.c", ".o")).to eq "build/libs/lib1/some/file.o"
expect(env.get_build_fname("libs/otherlib/otherlib.cc", ".o")).to eq "build/libs/otherlib/otherlib.o" expect(env.get_build_fname("libs/otherlib/otherlib.cc", ".o")).to eq "build/libs/otherlib/otherlib.o"
expect(env.get_build_fname("other_directory/o.d", ".a")).to eq "other_directory/o.a" expect(env.get_build_fname("other_directory/o.d", ".a")).to eq "build/other_directory/o.a"
end end
context "with a build_root" do context "with a build_root" do