Compare commits

...
16 Commits
16 changed files with 124 additions and 72 deletions

No files matched your search

+1
View File
@@ -32,6 +32,7 @@
- various performance improvements - various performance improvements
- wrote a new user guide - wrote a new user guide
- added new website ([https://holtrop.github.io/rscons/](https://holtrop.github.io/rscons/)) - added new website ([https://holtrop.github.io/rscons/](https://holtrop.github.io/rscons/))
- added new logo
## v1.17.0 ## v1.17.0
+2
View File
@@ -1,5 +1,7 @@
# Rscons # Rscons
![rscons logo](img/rscons_logo_1000.png)
Rscons (https://github.com/holtrop/rscons) is an open-source build system Rscons (https://github.com/holtrop/rscons) is an open-source build system
for developers. for developers.
+8 -1
View File
@@ -11,7 +11,7 @@ require "rake/clean"
require "fileutils" require "fileutils"
CLEAN.include %w[build_test_run .yardoc yard coverage test] CLEAN.include %w[build_test_run .yardoc yard coverage test]
CLOBBER.include %w[dist pkg] CLOBBER.include %w[dist gen large_project pkg]
task :build_dist do task :build_dist do
sh "ruby rb/build_dist.rb" sh "ruby rb/build_dist.rb"
@@ -93,3 +93,10 @@ task :user_guide do
end end
task :default => :spec task :default => :spec
task :all => [
:build_dist,
:spec,
:yard,
:user_guide,
]
@@ -17,6 +17,10 @@ configure do
end end
op.complete(status, success_message: "good!", fail_message: fail_message, fail: should_fail) op.complete(status, success_message: "good!", fail_message: fail_message, fail: should_fail)
end end
custom_check("Checking sed -E flag") do |op|
stdout, stderr, status = op.log_and_test_command(%w[sed -E -e s/ab+/rep/], stdin: "abbbc")
op.complete(stdout =~ /repc/ ? 0 : 1, success_message: "good", fail_message: "fail")
end
end end
build do build do
+1 -1
View File
@@ -1,6 +1,6 @@
build do build do
Environment.new do |env| Environment.new do |env|
env["LIBS"] += ["c"] env["LIBS"] += ["m"]
env.Program('simple.exe', Dir['*.c']) env.Program('simple.exe', Dir['*.c'])
end end
end end
+3 -2
View File
@@ -8,7 +8,7 @@ It supports the following features:
* built-in builders for several common operations * built-in builders for several common operations
* out-of-the-box support for C, C++, and D languages * out-of-the-box support for C, C++, and D languages
* extensibility for other languages or custom builders * extensibility for other languages or custom builders
* compatible with Windows, Linux, and OS X * compatible with Windows, Linux, OS X, and FreeBSD
* colorized output with build progress * colorized output with build progress
* build hooks * build hooks
@@ -98,7 +98,8 @@ The only dependency required to run Rscons is to have a Ruby interpreter
installed. installed.
The latest release can be downloaded from [https://github.com/holtrop/rscons/releases](https://github.com/holtrop/rscons/releases). The latest release can be downloaded from [https://github.com/holtrop/rscons/releases](https://github.com/holtrop/rscons/releases).
Simply copy the `rscons` executable script into the desired location within Simply copy the `rscons` executable script into the desired location within
the project to be built (typically the root of the repository). the project to be built (typically the root of the repository) and mark it
executable.
## Version Control Setup ## Version Control Setup
Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+9 -2
View File
@@ -280,12 +280,19 @@ module Rscons
# Execute a test command and log the result. # Execute a test command and log the result.
# #
# @param command [Array<String>]
# Command to execute.
# @param options [Hash]
# Optional arguments.
# @option options [String] :stdin
# Data to send to standard input stream of the executed command.
#
# @return [String, String, Process::Status] # @return [String, String, Process::Status]
# stdout, stderr, status # stdout, stderr, status
def log_and_test_command(command) def log_and_test_command(command, options = {})
begin begin
@log_fh.puts("Command: #{command.join(" ")}") @log_fh.puts("Command: #{command.join(" ")}")
stdout, stderr, status = Open3.capture3(*command) stdout, stderr, status = Open3.capture3(*command, stdin_data: options[:stdin])
@log_fh.puts("Exit status: #{status.to_i}") @log_fh.puts("Exit status: #{status.to_i}")
@log_fh.write(stdout) @log_fh.write(stdout)
@log_fh.write(stderr) @log_fh.write(stderr)
+12 -10
View File
@@ -204,16 +204,18 @@ module Rscons
File.file?(path) and File.executable?(path) File.file?(path) and File.executable?(path)
end end
if RbConfig::CONFIG["host_os"] =~ /mswin|windows|mingw/i if RbConfig::CONFIG["host_os"] =~ /mswin|windows|mingw/i
executable = executable.downcase if File.directory?(path_entry)
dir_entries = Dir.entries(path_entry) executable = executable.downcase
dir_entries.find do |entry| dir_entries = Dir.entries(path_entry)
path = "#{path_entry}/#{entry}" dir_entries.find do |entry|
entry = entry.downcase path = "#{path_entry}/#{entry}"
if ((entry == executable) or entry = entry.downcase
(entry == "#{executable}.exe") or if ((entry == executable) or
(entry == "#{executable}.com") or (entry == "#{executable}.exe") or
(entry == "#{executable}.bat")) and is_executable[path] (entry == "#{executable}.com") or
return path (entry == "#{executable}.bat")) and is_executable[path]
return path
end
end end
end end
else else
+1 -1
View File
@@ -1,4 +1,4 @@
module Rscons module Rscons
# Project version. # Project version.
VERSION = "2.0.0beta2" VERSION = "2.0.0"
end end
+6 -1
View File
@@ -1,6 +1,6 @@
<html> <html>
<head> <head>
<title>RScons User Guide<%= subpage_title %> - Version <%= Rscons::VERSION %></title> <title>Rscons User Guide<%= subpage_title %> - Version <%= Rscons::VERSION %></title>
<style> <style>
body { body {
background-color: #CCC; background-color: #CCC;
@@ -31,6 +31,11 @@
.separator { .separator {
height: 2em; height: 2em;
} }
.img_block_center {
display: block;
margin-left: auto;
margin-right: auto;
}
.page_nav { .page_nav {
width: 100%; width: 100%;
table-layout: fixed; table-layout: fixed;
+3 -1
View File
@@ -154,7 +154,8 @@ class Generator
end end
def render_toc def render_toc
toc_content = %[<h1>Table of Contents</h1>\n] toc_content = %[<img class="img_block_center" src="rscons_logo_1000.png" />]
toc_content += %[<h1>Table of Contents</h1>\n]
@sections.each do |section| @sections.each do |section|
indent = section.number.split(".").size - 1 indent = section.number.split(".").size - 1
toc_content += %[<span style="padding-left: #{4 * indent}ex;">] toc_content += %[<span style="padding-left: #{4 * indent}ex;">]
@@ -223,5 +224,6 @@ end
input = load_file("doc/user_guide.md") input = load_file("doc/user_guide.md")
FileUtils.rm_rf("gen/user_guide") FileUtils.rm_rf("gen/user_guide")
FileUtils.mkdir_p("gen/user_guide") FileUtils.mkdir_p("gen/user_guide")
FileUtils.cp("img/rscons_logo_1000.png", "gen/user_guide")
Generator.new(input, "gen/user_guide/user_guide.html", false) Generator.new(input, "gen/user_guide/user_guide.html", false)
Generator.new(input, "gen/user_guide", true) Generator.new(input, "gen/user_guide", true)
+70 -52
View File
@@ -145,7 +145,11 @@ EOF
stdout, stderr, status = nil, nil, nil stdout, stderr, status = nil, nil, nil
Bundler.with_clean_env do Bundler.with_clean_env do
env = ENV.to_h env = ENV.to_h
env["PATH"] = "#{@build_test_run_dir}/_bin#{File::PATH_SEPARATOR}#{env["PATH"]}" path = ["#{@build_test_run_dir}/_bin", "#{env["PATH"]}"]
if options[:path]
path = Array(options[:path]) + path
end
env["PATH"] = path.join(File::PATH_SEPARATOR)
stdout, stderr, status = Open3.capture3(env, *command) stdout, stderr, status = Open3.capture3(env, *command)
File.open("#{@build_test_run_dir}/.stdout", "wb") do |fh| File.open("#{@build_test_run_dir}/.stdout", "wb") do |fh|
fh.write(stdout) fh.write(stdout)
@@ -591,51 +595,51 @@ EOF
expect(result.stdout).to eq "" expect(result.stdout).to eq ""
end end
it "supports building D sources with gdc" do
test_dir("d")
result = run_rscons
expect(result.stderr).to eq ""
slines = lines(result.stdout)
verify_lines(slines, [%r{gdc -c -o build/e.1/main.o -MMD -MF build/e.1/main.mf main.d}])
verify_lines(slines, [%r{gdc -c -o build/e.1/mod.o -MMD -MF build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{gdc -o 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 "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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 33!"
end
unless ENV["omit_gdc_tests"] unless ENV["omit_gdc_tests"]
it "supports building D sources with gdc" do
test_dir("d")
result = run_rscons
expect(result.stderr).to eq ""
slines = lines(result.stdout)
verify_lines(slines, [%r{gdc -c -o build/e.1/main.o -MMD -MF build/e.1/main.mf main.d}])
verify_lines(slines, [%r{gdc -c -o build/e.1/mod.o -MMD -MF build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{gdc -o 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 "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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
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(bj)? -deps=build/e.1/main.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.o(bj)? -deps=build/e.1/mod.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.o(bj)? build/e.1/mod.o(bj)?}])
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 it "links with the D linker when object files were built from D sources" do
test_dir("d") test_dir("d")
result = run_rscons(rsconscript: "link_objects.rb") result = run_rscons(rsconscript: "link_objects.rb")
@@ -669,11 +673,7 @@ EOF
test_dir("shared_library") test_dir("shared_library")
result = run_rscons(rsconscript: "shared_library_d.rb") result = run_rscons(rsconscript: "shared_library_d.rb")
# Currently gdc produces an error while trying to build the shared expect(result.stderr).to eq ""
# library. Since this isn't really an rscons problem, I'm commenting out
# this check. I'm not sure what I want to do about D support at this
# point anyway...
#expect(result.stderr).to eq ""
slines = lines(result.stdout) slines = lines(result.stdout)
if RUBY_PLATFORM =~ /mingw/ if RUBY_PLATFORM =~ /mingw/
verify_lines(slines, [%r{Linking mine.dll}]) verify_lines(slines, [%r{Linking mine.dll}])
@@ -2050,6 +2050,16 @@ EOF
expect(result.stdout).to match /Checking for program 'find'... .*find/ expect(result.stdout).to match /Checking for program 'find'... .*find/
end end
context "with non-existent PATH entries" do
it "succeeds when the requested program is found" do
test_dir "configure"
result = run_rscons(rsconscript: "check_program_success.rb", op: "configure", path: "/foo/bar")
expect(result.stderr).to eq ""
expect(result.status).to eq 0
expect(result.stdout).to match /Checking for program 'find'... .*find/
end
end
it "fails when the requested program is not found" do it "fails when the requested program is not found" do
test_dir "configure" test_dir "configure"
result = run_rscons(rsconscript: "check_program_failure.rb", op: "configure") result = run_rscons(rsconscript: "check_program_failure.rb", op: "configure")
@@ -2179,6 +2189,14 @@ EOF
expect(result.status).to eq 0 expect(result.status).to eq 0
end end
end end
it "allows passing standard input data to the executed command" do
test_dir "configure"
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stdout).to match /Checking sed -E flag\.\.\. good/
expect(result.status).to eq 0
end
end end
end end
@@ -2192,8 +2210,8 @@ EOF
expect(result.stdout).to match /Setting build directory\.\.\. bb/ expect(result.stdout).to match /Setting build directory\.\.\. bb/
expect(result.stdout).to match %r{Setting prefix\.\.\. /my/prefix} expect(result.stdout).to match %r{Setting prefix\.\.\. /my/prefix}
expect(result.stdout).to match /Checking for C compiler\.\.\. gcc/ expect(result.stdout).to match /Checking for C compiler\.\.\. gcc/
expect(result.stdout).to match /Checking for C\+\+ compiler\.\.\. g++/ expect(result.stdout).to match /Checking for C\+\+ compiler\.\.\. g\+\+/
expect(result.stdout).to match /Checking for D compiler\.\.\. gdc/ expect(result.stdout).to match /Checking for D compiler\.\.\. (gdc|ldc2)/
expect(result.stdout).to match /Checking for package 'mypackage'\.\.\. found/ expect(result.stdout).to match /Checking for package 'mypackage'\.\.\. found/
expect(result.stdout).to match /Checking for C header 'stdio.h'\.\.\. found/ expect(result.stdout).to match /Checking for C header 'stdio.h'\.\.\. found/
expect(result.stdout).to match /Checking for C\+\+ header 'iostream'\.\.\. found/ expect(result.stdout).to match /Checking for C\+\+ header 'iostream'\.\.\. found/
+4 -1
View File
@@ -121,7 +121,10 @@ EOF
before(:each) do before(:each) do
stub_const("File::PATH_SEPARATOR", ";") stub_const("File::PATH_SEPARATOR", ";")
stub_const("RbConfig::CONFIG", "host_os" => "mingw") stub_const("RbConfig::CONFIG", "host_os" => "mingw")
expect(ENV).to receive(:[]).with("PATH").and_return("C:\\bin;C:\\Windows") expect(ENV).to receive(:[]).with("PATH").and_return("C:\\none;C:\\bin;C:\\Windows")
allow(File).to receive(:directory?).with("C:\\none").and_return(false)
allow(File).to receive(:directory?).with("C:\\bin").and_return(true)
allow(File).to receive(:directory?).with("C:\\Windows").and_return(true)
allow(Dir).to receive(:entries).with("C:\\bin").and_return(%w[one.com]) allow(Dir).to receive(:entries).with("C:\\bin").and_return(%w[one.com])
allow(Dir).to receive(:entries).with("C:\\Windows").and_return(%w[two.exe Three.bat]) allow(Dir).to receive(:entries).with("C:\\Windows").and_return(%w[two.exe Three.bat])
end end