Compare commits

..
43 Commits
Author SHA1 Message Date
josh 353f4f45bc v2.2.0 2020-10-13 18:59:18 -04:00
josh 5bac91f92f add failure messages for failed configuration checks - close #119 2020-10-12 21:01:04 -04:00
josh bbe9563ceb compiler checks should support cross-compilers and freestanding compilers - close #118 2020-10-08 19:23:17 -04:00
josh 5ec74604c6 improve support for MSYS2 - close #120 2020-10-08 19:04:50 -04:00
josh 8e06efe61e v2.1.0 2020-04-16 16:52:58 -04:00
josh 0756874ddb update CHANGELOG for v2.1.0 2020-04-16 16:51:16 -04:00
josh dded5e2648 ruby 2.7 compatibility - #117 2020-04-16 15:48:45 -04:00
josh fbe60f6ba2 stick with simplecov 0.15.x for now 2020-04-16 15:02:01 -04:00
josh 8dd9799666 Revert "update simplecov"
This reverts commit 01ca86de8b.
2020-04-16 15:02:01 -04:00
josh f2c755c8bb update bundle 2020-04-16 13:07:20 -04:00
josh 01ca86de8b update simplecov 2020-02-29 14:27:21 -05:00
josh 943fabd0d1 update some gems 2020-02-29 10:47:46 -05:00
josh d08e2f6b5c v2.0.2 2019-12-16 21:36:38 -05:00
josh 90365dd197 update CHANGELOG for v2.0.2 2019-12-16 21:36:22 -05:00
josh 8d05516c40 distinguish object files built from multiple sources with the same base name but different extensions - close #113 2019-12-14 00:10:42 -05:00
josh db49d86866 show a configuration failed message on stderr on configuration failure 2019-10-14 22:57:49 -04:00
josh e667455c32 user guide: fix configure script example 2019-10-14 22:49:34 -04:00
josh e62332aba6 avoid backtrace when configuring fails during autoconf 2019-10-14 22:23:18 -04:00
josh 397639849d call print_run_message() in json_to_yaml build test 2019-10-12 17:59:08 -04:00
josh 96d5caf2e5 user guide: fix print_run_message() examples 2019-10-12 17:57:58 -04:00
josh f4b10a30af update CHANGELOG for v2.0.1 2019-10-02 21:10:29 -04:00
josh cf52c3fc6f v2.0.1 2019-10-02 20:59:58 -04:00
josh 5378afb6f8 Install builder cannot replace a currently executing binary on Linux - close #112 2019-09-28 23:18:31 -04:00
josh 48d9273cc6 v2.0.0 2019-09-11 23:32:27 -04:00
josh efea4f1181 user guide: Installation: mention marking rscons executable 2019-09-11 23:29:25 -04:00
josh b4fa6d965c CHANGELOG - add logo 2019-09-11 23:25:19 -04:00
josh ac56ad34f6 add rscons logo to README 2019-09-11 23:24:20 -04:00
josh 2fd533a32a clobber large_project directory 2019-09-11 23:20:22 -04:00
josh c938ed71d1 add "all" rake task 2019-09-11 23:19:46 -04:00
josh ec60201a62 user guide: add rscons logo 2019-09-11 23:18:38 -04:00
josh 0cafb8c5b3 user guide: stylize as "Rscons" 2019-09-11 23:15:16 -04:00
josh 004810386b clobber should remove "gen" directory 2019-09-11 23:15:02 -04:00
josh a15ee9daaf add logo images 2019-09-11 23:02:17 -04:00
josh cd33405697 user guide: add FreeBSD compatibility 2019-09-01 21:52:32 -04:00
josh efa77066bf allow ConfigureOp#log_and_test_command to be passed standard input data - close #111 2019-09-01 21:50:57 -04:00
josh a1bb9d81fd check_program: do not fail on Windows for non-existent PATH entries 2019-08-27 19:47:21 -04:00
josh 0344f02cb1 build tests: use -m instead of -lc for mingw 2019-08-27 19:32:36 -04:00
josh d52bdaf046 build tests: do ldc2 tests even if omit_gdc_tests set 2019-08-27 18:51:56 -04:00
josh ad7ccb771d update build test for gdc fix 2019-08-27 18:50:01 -04:00
josh 044ee343ca Use OBJSUFFIX of .obj for ldc2 on Windows. 2019-08-26 19:10:19 -04:00
josh eb54a2b64a fix specs create_exe() on Windows 2019-08-26 18:51:03 -04:00
josh 2dd1ce9f1d Use base64 encoding for compressed script to avoid encoding issues. 2019-08-26 18:33:42 -04:00
josh 1e157c79ec fix dependency parsing with ldc2 - close #110 2019-08-19 22:56:54 -04:00
42 changed files with 533 additions and 293 deletions

No files matched your search

+19
View File
@@ -1,3 +1,21 @@
## v2.1.0
### New Features
- #117 - ruby 2.7 compatibility
## v2.0.2
### Fixes
- #113 - distinguish object files built from multiple sources with the same base name but different extensions
## v2.0.1
### Fixes
- #112 - Install builder cannot replace a currently executing binary on Linux
## v2.0.0
- convert rscons from a Ruby gem to a standalone script
@@ -32,6 +50,7 @@
- various performance improvements
- wrote a new user guide
- added new website ([https://holtrop.github.io/rscons/](https://holtrop.github.io/rscons/))
- added new logo
## v1.17.0
+10 -6
View File
@@ -1,10 +1,14 @@
source 'https://rubygems.org'
gem "json"
gem "rspec"
gem "rake"
gem "simplecov"
gem "yard"
gem "rdoc"
gem "redcarpet"
gem "syntax"
gem "simplecov", "~> 0.15.0"
if RbConfig::CONFIG["host"]["msys"]
gem "json", "2.1.0"
else
gem "json"
gem "yard"
gem "rdoc"
gem "redcarpet"
gem "syntax"
end
+20 -20
View File
@@ -2,31 +2,31 @@ GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.3)
docile (1.3.2)
json (2.2.0)
rake (12.3.2)
rdoc (6.1.1)
redcarpet (3.4.0)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.2)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.4)
docile (1.1.5)
json (2.3.0)
rake (13.0.1)
rdoc (6.2.1)
redcarpet (3.5.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.1)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.2)
simplecov (0.15.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.2)
simplecov (0.15.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
syntax (1.2.2)
yard (0.9.20)
yard (0.9.24)
PLATFORMS
ruby
@@ -38,9 +38,9 @@ DEPENDENCIES
rdoc
redcarpet
rspec
simplecov
simplecov (~> 0.15.0)
syntax
yard
BUNDLED WITH
1.17.3
2.1.4
+2
View File
@@ -1,5 +1,7 @@
# Rscons
![rscons logo](img/rscons_logo_1000.png)
Rscons (https://github.com/holtrop/rscons) is an open-source build system
for developers.
+17 -8
View File
@@ -6,12 +6,11 @@ rescue Bundler::BundlerError => e
end
require "rspec/core/rake_task"
require "yard"
require "rake/clean"
require "fileutils"
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
sh "ruby rb/build_dist.rb"
@@ -37,11 +36,6 @@ task :dspec, [:example_string] => :build_dist do |task, args|
FileUtils.rm_f(Dir.glob(".rscons-*"))
end
YARD::Rake::YardocTask.new do |yard|
yard.files = ['lib/**/*.rb']
yard.options = ["-ogen/yard"]
end
task :gen_large_project, [:size] => :build_dist do |task, args|
size = (args.size || 10000).to_i
FileUtils.rm_rf("large_project")
@@ -88,8 +82,23 @@ EOF
FileUtils.cp("dist/rscons", "large_project")
end
task :user_guide do
unless RbConfig::CONFIG["host"]["msys"]
require "yard"
YARD::Rake::YardocTask.new do |yard|
yard.files = ['lib/**/*.rb']
yard.options = ["-ogen/yard"]
end
task :user_guide do
system("ruby", "-Ilib", "rb/gen_user_guide.rb")
end
end
task :default => :spec
task :all => [
:build_dist,
:spec,
:yard,
:user_guide,
]
@@ -1,4 +1,5 @@
configure do
check_d_compiler
check_d_import "std.stdio", check_d_import_path: ["./usr1"]
check_d_import "frobulous", check_d_import_path: ["./usr2"]
end
@@ -1,3 +1,4 @@
configure do
check_d_compiler
check_d_import "std.stdio"
end
@@ -17,6 +17,10 @@ configure do
end
op.complete(status, success_message: "good!", fail_message: fail_message, fail: should_fail)
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
build do
+5
View File
@@ -0,0 +1,5 @@
configure do
check_c_compiler "foo123c", fail: false, on_fail: "Install the foo123 package"
check_d_compiler "foo123d", fail: false
check_cxx_compiler "foo123cxx", on_fail: lambda {puts "Install the foo123cxx package"}
end
+3 -2
View File
@@ -6,7 +6,8 @@ build do
"CMD_DESC" => "Generating")
env["build_root"] = env.build_root
env["inc_c"] = "inc.c"
env.build_after("${build_root}/program.o", "${inc_c}")
env.Program("program.exe", ["program.c", "inc.c"])
env.Object("program.o", "program.c")
env.build_after("program.o", "${inc_c}")
env.Program("program.exe", ["program.o", "inc.c"])
end
end
+3 -2
View File
@@ -4,8 +4,9 @@ build do
env["inc_h"] = "inc.h"
env.Copy("copy_inc.h", "${inc_h}")
env.depends("${build_root}/program.o", "${inc_h}")
env.Program("program.exe", ["program.c", "inc.c"])
env.depends("program.o", "${inc_h}")
env.Object("program.o", "program.c")
env.Program("program.exe", ["program.o", "inc.c"])
inc_c = env.Command("inc.c",
[],
+3 -2
View File
@@ -4,8 +4,9 @@ build do
env["inc_h"] = "inc.h"
env.Copy("copy_inc.h", "${inc_h}")
env.depends("${build_root}/program.o", "${inc_h}")
env.Program("program.exe", ["program.c", "inc.c"])
env.depends("program.o", "${inc_h}")
env.Object("program.o", "program.c")
env.Program("program.exe", ["program.o", "inc.c"])
env.Command("inc.c",
[],
+4
View File
@@ -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"))
+9
View File
@@ -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
+1
View File
@@ -4,6 +4,7 @@ build do
require 'yaml'
env.add_builder(:JsonToYaml) do |params|
unless @cache.up_to_date?(@target, :JsonToYaml, @sources, @env)
print_run_message("JsonToYaml #{@target}", nil)
@cache.mkdir_p(File.dirname(@target))
File.open(@target, 'w') do |f|
f.write(YAML.dump(JSON.load(IO.read(@sources.first))))
@@ -0,0 +1,5 @@
build do
Environment.new do |env|
env.Program("foo.exe", glob("*.cc", "*.c"))
end
end
+6
View File
@@ -0,0 +1,6 @@
#include <stdio.h>
void foo(void)
{
printf("foo\n");
}
+12
View File
@@ -0,0 +1,12 @@
#include <iostream>
extern "C" {
void foo(void);
}
int main(int argc, char * argv[])
{
foo();
std::cout << "main" << std::endl;
return 0;
}
+1 -1
View File
@@ -1,6 +1,6 @@
build do
Environment.new do |env|
env["LIBS"] += ["c"]
env["LIBS"] += ["m"]
env.Program('simple.exe', Dir['*.c'])
end
end
+2 -2
View File
@@ -2,9 +2,9 @@ build do
Environment.new(echo: :command) do |env|
env.append('CPPPATH' => glob('src/**/*/'))
env.add_build_hook do |builder|
if File.basename(builder.target) == "one.o"
if File.basename(builder.sources.first) == "one.c"
builder.vars["CFLAGS"] << "-O1"
elsif File.basename(builder.target) == "two.o"
elsif File.basename(builder.sources.first) == "two.c"
builder.vars["CFLAGS"] << "-O2"
end
end
+55 -41
View File
@@ -8,7 +8,7 @@ It supports the following features:
* built-in builders for several common operations
* out-of-the-box support for C, C++, and D languages
* 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
* build hooks
@@ -98,7 +98,8 @@ The only dependency required to run Rscons is to have a Ruby interpreter
installed.
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
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
@@ -245,6 +246,15 @@ configure do
end
```
Global configuration options may be supplied to the compiler checks as well.
Example:
```ruby
configure do
check_c_compiler "x86_64-elf-gcc", on_fail: "Install x86_64-elf cross toolchain first!"
end
```
###> Checking for a Header File
The following methods can be used to check for the presence of a header file:
@@ -271,18 +281,6 @@ end
Optionally specifies an array of paths to look for the header file in.
##### `:fail`
If the `:fail` option is set to `false`, then the absence of the header file
will not result in the configure option failing.
The `:fail` option defaults to `true` if the `:set_define` option is not
defined, and defaults to `false` if the `:set_define` option is defined.
##### `:set_define`
If set, a build define of the specified String will be added to the
`CPPDEFINES` construction variable array if the requested header is found.
###> Checking for a D Import
The `check_d_import` method can be used to check for the presence of D import.
@@ -326,18 +324,6 @@ end
Optionally specifies an array of paths to look for the library in.
##### `:fail`
If the `:fail` option is set to `false`, then the absence of the library
will not result in the configure option failing.
The `:fail` option defaults to `true` if the `:set_define` option is not
defined, and defaults to `false` if the `:set_define` option is defined.
##### `:set_define`
If set, a build define of the specified String will be added to the
`CPPDEFINES` construction variable array if the requested library is found.
##### `:use`
If not set, the library will be used by default in all `Environment` objects.
@@ -386,18 +372,6 @@ used to look for package configuration flags for the specified package.
If the `:program` option is given, the program specified will be used to look
for configuration flags.
##### `:fail`
If the `:fail` option is set to `false`, then the absence of the package or
program requested will not result in the configure option failing.
The `:fail` option defaults to `true` if the `:set_define` option is not
defined, and defaults to `false` if the `:set_define` option is defined.
##### `:set_define`
If set, a build define of the specified String will be added to the
`CPPDEFINES` construction variable array if the requested package is found.
##### `:use`
If not set, the library will be used by default in all `Environment` objects.
@@ -456,6 +430,46 @@ configure do
end
```
###> Global Configuration Check Options
#### `:fail`
If the `:fail` option is set to `false`, then the absence of the package or
program requested will not result in the configure option failing.
The `:fail` option defaults to `true` if the `:set_define` option is not
defined, and defaults to `false` if the `:set_define` option is defined.
#### `:on_fail`
The `:on_fail` option can be set to a String or a Proc object. If the
configuration operation fails (or would fail), the given message is printed
or the Proc is called.
Examples:
```ruby
configure do
check_c_compiler "special-gcc", on_fail: "First install special gcc!"
end
configure do
package_hint = lambda do
puts "The following packages must be installed to build this project:"
puts "- libsdl2-dev"
puts "- libsdl2-image-dev"
puts "- libsdl2-net-dev"
end
check_lib "SDL2", on_fail: package_hint
check_lib "SDL2_image", on_fail: package_hint
check_lib "SDL2_net", on_fail: package_hint
end
```
#### `:set_define`
If set, a build define of the specified String will be added to the
`CPPDEFINES` construction variable array if the requested package is found.
##> Build Operations
The `build` block is used to create Environments and register build targets.
@@ -1024,7 +1038,7 @@ Here is our Custom builder example extended to print its status:
```ruby
class Rscons::Builders::Custom < Rscons::Builder
def run(options)
print_run_message("Creating <target>#{@target}<reset> from Custom builder")
print_run_message("Creating <target>#{@target}<reset> from Custom builder", nil)
File.open(@target, "w") do |fh|
fh.write("Target file created.")
end
@@ -1049,7 +1063,7 @@ Here is a Custom builder which combines its source files similar to what the
class Rscons::Builders::Custom < Rscons::Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Combining <source>#{Util.short_format_paths(@sources)}<reset> => <target>#{@target}<reset>")
print_run_message("Combining <source>#{Util.short_format_paths(@sources)}<reset> => <target>#{@target}<reset>", nil)
File.open(@target, "wb") do |fh|
@sources.each do |source|
fh.write(File.read(source, mode: "rb"))
@@ -1276,7 +1290,7 @@ To do this, create a `configure` script with contents similar to the following:
```
#!/bin/sh
exec "$(dirname "$0")"/rscons "$@"
exec "$(dirname "$0")"/rscons configure "$@"
```
and make it executable with `chmod +x configure`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+2 -12
View File
@@ -64,16 +64,6 @@ module Rscons
target.is_a?(Symbol)
end
# Return a new path by changing the suffix in path to suffix.
#
# @param path [String] The path to alter.
# @param suffix [String] The new filename suffix, e.g. ".exe".
#
# @return [String] New path.
def set_suffix(path, suffix)
path.sub(/\.[^.]*$/, "") + suffix
end
# Return the system shell and arguments for executing a shell command.
#
# @return [Array<String>] The shell and flag.
@@ -91,7 +81,7 @@ module Rscons
end
if ENV["SHELL"] and ENV["SHELL"] != "" and test_shell[ENV["SHELL"], "-c"]
[ENV["SHELL"], "-c"]
elsif Object.const_get("RUBY_PLATFORM") =~ /mingw/
elsif Object.const_get("RUBY_PLATFORM") =~ /mingw|msys/
if test_shell["sh", "-c"]
# Using Rscons from MSYS should use MSYS's shell.
["sh", "-c"]
@@ -112,7 +102,7 @@ module Rscons
# @return [Array<String>] Command used to execute commands.
def command_executer
@command_executer ||=
if Object.const_get("RUBY_PLATFORM") =~ /mingw/
if Object.const_get("RUBY_PLATFORM") =~ /mingw|msys/
if ENV.keys.find {|key| key =~ /MSYS/}
begin
if IO.popen(["env", "echo", "success"]) {|io| io.read.strip} == "success"
+1 -1
View File
@@ -84,7 +84,7 @@ module Rscons
# @return [Boolean]
# Whether to output ANSI color escape codes.
def do_ansi?(io)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
(ENV["TERM"] == "xterm") && %w[fifo characterSpecial].include?(io.stat.ftype)
else
io.tty?
+3
View File
@@ -75,6 +75,8 @@ module Rscons
end
if rv == 0
build(operation_options)
else
rv
end
when "clean"
clean
@@ -192,6 +194,7 @@ module Rscons
begin
@script.configure(co)
rescue ConfigureOp::ConfigureFailure
Ansi.write($stderr, :red, "Configuration failed", :reset, "\n")
rv = 1
end
co.close(rv == 0)
+1
View File
@@ -57,6 +57,7 @@ module Rscons
printed_message = true
end
@cache.mkdir_p(File.dirname(dest), install: @install_builder)
FileUtils.rm_f(dest)
FileUtils.cp(src, dest, :preserve => true)
end
@cache.register_build(dest, :Copy, [src], @env, install: @install_builder)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -78,7 +78,7 @@ module Rscons
if @vars[:direct]
@env.get_build_fname(target, depfilesuffix, self.class)
else
Rscons.set_suffix(target, depfilesuffix)
"#{target}#{depfilesuffix}"
end
@cache.mkdir_p(File.dirname(@vars["_DEPFILE"]))
command = @env.build_command(@command_template, @vars)
+1 -1
View File
@@ -23,7 +23,7 @@ module Rscons
@vars["_PREPROCESS_DEPGEN"] = depgen
@vars["_TARGET"] = @target
@vars["_SOURCES"] = @sources
@vars["_DEPFILE"] = Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars))
@vars["_DEPFILE"] = "#{target}#{env.expand_varref("${DEPFILESUFFIX}", vars)}"
command = @env.build_command("${CPP_CMD}", @vars)
self.produces(@vars["_DEPFILE"])
standard_command("Preprocessing <source>#{Util.short_format_paths(@sources)}<reset> => <target>#{@target}<reset>", command)
+48 -35
View File
@@ -62,6 +62,10 @@ module Rscons
# @return [void]
def check_c_compiler(*ccc)
$stdout.write("Checking for C compiler... ")
options = {}
if ccc.last.is_a?(Hash)
options = ccc.slice!(-1)
end
if ccc.empty?
# Default C compiler search array.
ccc = %w[gcc clang]
@@ -69,7 +73,7 @@ module Rscons
cc = ccc.find do |cc|
test_c_compiler(cc)
end
complete(cc ? 0 : 1, success_message: cc)
complete(cc ? 0 : 1, options.merge(success_message: cc))
end
# Check for a working C++ compiler.
@@ -80,6 +84,10 @@ module Rscons
# @return [void]
def check_cxx_compiler(*ccc)
$stdout.write("Checking for C++ compiler... ")
options = {}
if ccc.last.is_a?(Hash)
options = ccc.slice!(-1)
end
if ccc.empty?
# Default C++ compiler search array.
ccc = %w[g++ clang++]
@@ -87,7 +95,7 @@ module Rscons
cc = ccc.find do |cc|
test_cxx_compiler(cc)
end
complete(cc ? 0 : 1, success_message: cc)
complete(cc ? 0 : 1, options.merge(success_message: cc))
end
# Check for a working D compiler.
@@ -98,6 +106,10 @@ module Rscons
# @return [void]
def check_d_compiler(*cdc)
$stdout.write("Checking for D compiler... ")
options = {}
if cdc.last.is_a?(Hash)
options = cdc.slice!(-1)
end
if cdc.empty?
# Default D compiler search array.
cdc = %w[gdc ldc2]
@@ -105,7 +117,7 @@ module Rscons
dc = cdc.find do |dc|
test_d_compiler(dc)
end
complete(dc ? 0 : 1, success_message: dc)
complete(dc ? 0 : 1, options.merge(success_message: dc))
end
# Check for a package or configure program output.
@@ -280,12 +292,19 @@ module Rscons
# 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]
# stdout, stderr, status
def log_and_test_command(command)
def log_and_test_command(command, options = {})
begin
@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.write(stdout)
@log_fh.write(stderr)
@@ -380,11 +399,15 @@ module Rscons
else
!options[:set_define]
end
color = should_fail ? :red : :yellow
Ansi.write($stdout, color, "#{fail_message}\n")
if options[:on_fail].is_a?(String)
$stdout.puts(options[:on_fail])
elsif options[:on_fail].is_a?(Proc)
options[:on_fail].call
end
if should_fail
Ansi.write($stdout, :red, "#{fail_message}\n")
raise ConfigureFailure.new
else
Ansi.write($stdout, :yellow, "#{fail_message}\n")
end
end
end
@@ -401,24 +424,19 @@ module Rscons
def test_c_compiler(cc)
File.open("#{@work_dir}/cfgtest.c", "wb") do |fh|
fh.puts <<-EOF
#include <stdio.h>
int main(int argc, char * argv[]) {
printf("Success.\\n");
return 0;
int fun(int val) {
return val * 2;
}
EOF
end
command = %W[#{cc} -o #{@work_dir}/cfgtest.exe #{@work_dir}/cfgtest.c]
command = %W[#{cc} -c -o #{@work_dir}/cfgtest.o #{@work_dir}/cfgtest.c]
merge = {"CC" => cc}
_, _, status = log_and_test_command(command)
if status == 0
stdout, _, status = log_and_test_command(["#{@work_dir}/cfgtest.exe"])
if status == 0 and stdout =~ /Success/
store_merge(merge)
true
end
end
end
# Test a C++ compiler.
#
@@ -430,25 +448,20 @@ module Rscons
def test_cxx_compiler(cc)
File.open("#{@work_dir}/cfgtest.cxx", "wb") do |fh|
fh.puts <<-EOF
#include <iostream>
using namespace std;
int main(int argc, char * argv[]) {
cout << "Success." << endl;
return 0;
template<typename T>
T fun(T val) {
return val * 2;
}
EOF
end
command = %W[#{cc} -o #{@work_dir}/cfgtest.exe #{@work_dir}/cfgtest.cxx]
command = %W[#{cc} -c -o #{@work_dir}/cfgtest.o #{@work_dir}/cfgtest.cxx]
merge = {"CXX" => cc}
_, _, status = log_and_test_command(command)
if status == 0
stdout, _, status = log_and_test_command(["#{@work_dir}/cfgtest.exe"])
if status == 0 and stdout =~ /Success/
store_merge(merge)
true
end
end
end
# Test a D compiler.
#
@@ -460,9 +473,8 @@ module Rscons
def test_d_compiler(dc)
File.open("#{@work_dir}/cfgtest.d", "wb") do |fh|
fh.puts <<-EOF
import std.stdio;
int main() {
writeln("Success.");
import core.math;
int fun() {
return 0;
}
EOF
@@ -470,27 +482,28 @@ module Rscons
[:gdc, :ldc2].find do |dc_test|
case dc_test
when :gdc
command = %W[#{dc} -o #{@work_dir}/cfgtest.exe #{@work_dir}/cfgtest.d]
command = %W[#{dc} -c -o #{@work_dir}/cfgtest.o #{@work_dir}/cfgtest.d]
merge = {"DC" => dc}
when :ldc2
command = %W[#{dc} -of #{@work_dir}/cfgtest.exe #{@work_dir}/cfgtest.d]
# ldc2 on Windows expect an object file suffix of .obj.
ldc_objsuffix = RUBY_PLATFORM =~ /mingw|msys/ ? ".obj" : ".o"
command = %W[#{dc} -c -of #{@work_dir}/cfgtest#{ldc_objsuffix} #{@work_dir}/cfgtest.d]
env = BasicEnvironment.new
merge = {
"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},
"DCCMD" => env["DCCMD"].map {|e| e.sub(/^-o$/, "-of")},
"LDCMD" => env["LDCMD"].map {|e| e.sub(/^-o$/, "-of")},
"DDEPGEN" => ["-deps=${_DEPFILE}"],
}
merge["OBJSUFFIX"] = [ldc_objsuffix]
end
_, _, status = log_and_test_command(command)
if status == 0
stdout, _, status = log_and_test_command(["#{@work_dir}/cfgtest.exe"])
if status == 0 and stdout =~ /Success/
store_merge(merge)
true
end
end
end
end
# Common functionality for all store methods.
#
+1 -1
View File
@@ -1,6 +1,6 @@
module Rscons
on_windows = RUBY_PLATFORM =~ /mingw|cygwin/
on_windows = RUBY_PLATFORM =~ /mingw|msys|cygwin/
pic_flags = on_windows ? [] : %w[-fPIC]
# Default Rscons construction variables.
+2 -6
View File
@@ -1,7 +1,6 @@
require "fileutils"
require "set"
require "shellwords"
require "thwait"
module Rscons
# The Environment class is the main programmatic interface to Rscons. It
@@ -251,7 +250,7 @@ module Rscons
if extra_path = builder_class.extra_path
extra_path = "/#{extra_path}"
end
"#{@build_root}#{extra_path}/#{Util.make_relative_path(Rscons.set_suffix(source_fname, suffix))}".gsub("\\", "/")
"#{@build_root}#{extra_path}/#{Util.make_relative_path("#{source_fname}#{suffix}")}".gsub("\\", "/")
end
# Build all build targets specified in the Environment.
@@ -702,10 +701,7 @@ module Rscons
!thread.alive?
end
else
if @threads.empty?
raise "No threads to wait for"
end
ThreadsWait.new(*@threads.keys).next_wait
Util.wait_for_thread(*@threads.keys)
end
end
+42 -7
View File
@@ -9,7 +9,7 @@ module Rscons
#
# @return [Boolean] Whether the given path is an absolute filesystem path.
def absolute_path?(path)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
path =~ %r{^(?:\w:)?[\\/]}
else
path.start_with?("/")
@@ -68,8 +68,8 @@ module Rscons
case RbConfig::CONFIG["host_os"]
when /linux/
return File.read("/proc/cpuinfo").scan(/^processor\s*:/).size
when /mswin|mingw/
if `wmic cpu get NumberOfLogicalProcessors /value` =~ /NumberOfLogicalProcessors=(\d+)/
when /mswin|mingw|msys/
if `wmic cpu get NumberOfLogicalProcessors -value` =~ /NumberOfLogicalProcessors=(\d+)/
return $1.to_i
end
when /darwin/
@@ -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<String>]
# 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
@@ -187,6 +191,32 @@ module Rscons
deps
end
# Wait for any of a number of threads to complete.
#
# @param threads [Array<Thread>]
# Threads to wait for.
#
# @return [Thread]
# The Thread that completed.
def wait_for_thread(*threads)
if threads.empty?
raise "No threads to wait for"
end
queue = Queue.new
threads.each do |thread|
# Create a wait thread for each thread we're waiting for.
Thread.new do
begin
thread.join
ensure
queue.push(thread)
end
end
end
# Wait for any thread to complete.
queue.pop
end
private
# Check if a directory contains a certain executable.
@@ -195,11 +225,15 @@ module Rscons
# Directory to look in.
# @param executable [String]
# Executable to look for.
#
# @return [String, nil]
# Executable found.
def test_path_for_executable(path_entry, executable)
is_executable = lambda do |path|
File.file?(path) and File.executable?(path)
end
if RbConfig::CONFIG["host_os"] =~ /mswin|windows|mingw/i
if RbConfig::CONFIG["host_os"] =~ /mswin|windows|mingw|msys/i
if File.directory?(path_entry)
executable = executable.downcase
dir_entries = Dir.entries(path_entry)
dir_entries.find do |entry|
@@ -212,6 +246,7 @@ module Rscons
return path
end
end
end
else
path = "#{path_entry}/#{executable}"
return path if is_executable[path]
+1 -1
View File
@@ -1,4 +1,4 @@
module Rscons
# Project version.
VERSION = "2.0.0beta2"
VERSION = "2.2.0"
end
+6 -1
View File
@@ -1,6 +1,6 @@
<html>
<head>
<title>RScons User Guide<%= subpage_title %> - Version <%= Rscons::VERSION %></title>
<title>Rscons User Guide<%= subpage_title %> - Version <%= Rscons::VERSION %></title>
<style>
body {
background-color: #CCC;
@@ -31,6 +31,11 @@
.separator {
height: 2em;
}
.img_block_center {
display: block;
margin-left: auto;
margin-right: auto;
}
.page_nav {
width: 100%;
table-layout: fixed;
+7 -5
View File
@@ -59,9 +59,10 @@ combined_file.each do |line|
end
require "zlib"
require "base64"
compressed_script = Zlib::Deflate.deflate(stripped_comments.join)
escaped_compressed_script = compressed_script.gsub("#", "#1").gsub("\n", "#2").gsub("\r", "#3").gsub("\0", "#4")
hash = Digest::MD5.hexdigest(escaped_compressed_script)
encoded_compressed_script = Base64.encode64(compressed_script).gsub("\n", "")
hash = Digest::MD5.hexdigest(encoded_compressed_script)
FileUtils.mkdir_p(DIST)
File.open("#{DIST}/#{PROG_NAME}", "wb", 0755) do |fh|
@@ -70,9 +71,10 @@ File.open("#{DIST}/#{PROG_NAME}", "wb", 0755) do |fh|
script = File.join(File.dirname(__FILE__), ".rscons-#{VERSION}-#{hash}.rb")
unless File.exists?(script)
if File.read(__FILE__, mode: "rb") =~ /^#==>(.*)/
escaped_compressed = $1
unescaped_compressed = escaped_compressed.gsub("#4", "\\0").gsub("#3", "\\r").gsub("#2", "\\n").gsub("#1", "#")
require "zlib"
require "base64"
encoded_compressed = $1
unescaped_compressed = Base64.decode64(encoded_compressed)
inflated = Zlib::Inflate.inflate(unescaped_compressed)
File.open(script, "wb") do |fh|
fh.write(inflated)
@@ -85,6 +87,6 @@ load script
if __FILE__ == $0
Rscons::Cli.run(ARGV)
end
#==>#{escaped_compressed_script}
#==>#{encoded_compressed_script}
EOF
end
+3 -1
View File
@@ -154,7 +154,8 @@ class Generator
end
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|
indent = section.number.split(".").size - 1
toc_content += %[<span style="padding-left: #{4 * indent}ex;">]
@@ -223,5 +224,6 @@ end
input = load_file("doc/user_guide.md")
FileUtils.rm_rf("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", true)
+209 -121
View File
@@ -65,6 +65,9 @@ describe Rscons do
def create_exe(exe_name, contents)
exe_file = "#{@build_test_run_dir}/_bin/#{exe_name}"
if RUBY_PLATFORM =~ /mingw/
exe_file += ".bat"
end
File.open(exe_file, "wb") do |fh|
fh.puts("#!/bin/sh")
fh.puts(contents)
@@ -140,9 +143,13 @@ EOF
end
end
stdout, stderr, status = nil, nil, nil
Bundler.with_clean_env do
Bundler.with_unbundled_env do
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)
File.open("#{@build_test_run_dir}/.stdout", "wb") do |fh|
fh.write(stdout)
@@ -180,6 +187,10 @@ EOF
end
end
def nr(str)
str.gsub("\r", "")
end
###########################################################################
# Tests
###########################################################################
@@ -188,8 +199,8 @@ EOF
test_dir('simple')
result = run_rscons
expect(result.stderr).to eq ""
expect(File.exists?('build/e.1/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(File.exists?('build/e.1/simple.c.o')).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "allows specifying a Builder object as the source to another build target" do
@@ -197,7 +208,7 @@ EOF
result = run_rscons(rsconscript: "builder_as_source.rb")
expect(result.stderr).to eq ""
expect(File.exists?("simple.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it 'prints commands as they are executed' do
@@ -205,8 +216,8 @@ EOF
result = run_rscons(rsconscript: "command.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/simple.o -MMD -MF build/e.1/simple.mf simple.c},
%r{gcc -o simple.exe build/e.1/simple.o},
%r{gcc -c -o build/e.1/simple.c.o -MMD -MF build/e.1/simple.c.o.mf simple.c},
%r{gcc -o simple.exe build/e.1/simple.c.o},
])
end
@@ -224,19 +235,19 @@ EOF
test_dir('header')
result = run_rscons
expect(result.stderr).to eq ""
expect(File.exists?('build/e.1/header.o')).to be_truthy
expect(`./header.exe`).to eq "The value is 2\n"
expect(File.exists?('build/e.1/header.c.o')).to be_truthy
expect(nr(`./header.exe`)).to eq "The value is 2\n"
end
it 'rebuilds a C module when a header it depends on changes' do
test_dir('header')
result = run_rscons
expect(result.stderr).to eq ""
expect(`./header.exe`).to eq "The value is 2\n"
expect(nr(`./header.exe`)).to eq "The value is 2\n"
file_sub('header.h') {|line| line.sub(/2/, '5')}
result = run_rscons
expect(result.stderr).to eq ""
expect(`./header.exe`).to eq "The value is 5\n"
expect(nr(`./header.exe`)).to eq "The value is 5\n"
end
it 'does not rebuild a C module when its dependencies have not changed' do
@@ -247,7 +258,7 @@ EOF
%r{Compiling header.c},
%r{Linking header.exe},
])
expect(`./header.exe`).to eq "The value is 2\n"
expect(nr(`./header.exe`)).to eq "The value is 2\n"
result = run_rscons
expect(result.stderr).to eq ""
expect(result.stdout).to eq ""
@@ -261,7 +272,7 @@ EOF
%r{Compiling header.c},
%r{Linking header.exe},
])
expect(`./header.exe`).to eq "The value is 2\n"
expect(nr(`./header.exe`)).to eq "The value is 2\n"
sleep 0.05
file_sub('header.c') {|line| line}
result = run_rscons
@@ -274,13 +285,13 @@ EOF
result = run_rscons(rsconscript: "command.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/simple.o -MMD -MF build/e.1/simple.mf simple.c},
%r{gcc -o simple.exe build/e.1/simple.o},
%r{gcc -c -o build/e.1/simple.c.o -MMD -MF build/e.1/simple.c.o.mf simple.c},
%r{gcc -o simple.exe build/e.1/simple.c.o},
])
result = run_rscons(rsconscript: "link_flag_change.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -o simple.exe build/e.1/simple.o -Llibdir},
%r{gcc -o simple.exe build/e.1/simple.c.o -Llibdir},
])
end
@@ -310,9 +321,9 @@ EOF
result = run_rscons(rsconscript: "carat.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/one.o -MMD -MF build/e.1/one.mf -Isrc -Isrc/one -Isrc/two build/e.1/one.c},
%r{gcc -c -o build/e.1/src/two/two.o -MMD -MF build/e.1/src/two/two.mf -Isrc -Isrc/one -Isrc/two src/two/two.c},
%r{gcc -o program.exe build/e.1/src/two/two.o build/e.1/one.o},
%r{gcc -c -o build/e.1/one.o -MMD -MF build/e.1/one.o.mf -Isrc -Isrc/one -Isrc/two build/e.1/one.c},
%r{gcc -c -o build/e.1/src/two/two.c.o -MMD -MF build/e.1/src/two/two.c.o.mf -Isrc -Isrc/one -Isrc/two src/two/two.c},
%r{gcc -o program.exe build/e.1/src/two/two.c.o build/e.1/one.o},
])
end
@@ -321,7 +332,7 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
expect(File.exists?('foo.yml')).to be_truthy
expect(IO.read('foo.yml')).to eq("---\nkey: value\n")
expect(nr(IO.read('foo.yml'))).to eq("---\nkey: value\n")
end
it "raises an error when a side-effect file is registered for a build target that is not registered" do
@@ -336,9 +347,9 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
expect(`./simple.exe`).to match /This is a simple C program/
expect(File.exists?('build/e.1/simple.o')).to be_truthy
expect(File.exists?('build/e.1/simple.c.o')).to be_truthy
result = run_rscons(op: %w[clean])
expect(File.exists?('build/e.1/simple.o')).to be_falsey
expect(File.exists?('build/e.1/simple.c.o')).to be_falsey
expect(File.exists?('build/e.1')).to be_falsey
expect(File.exists?('simple.exe')).to be_falsey
expect(File.exists?('simple.c')).to be_truthy
@@ -349,7 +360,7 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
expect(`./simple.exe`).to match /This is a simple C program/
expect(File.exists?('build/e.1/simple.o')).to be_truthy
expect(File.exists?('build/e.1/simple.c.o')).to be_truthy
File.open('build/e.1/dum', 'w') { |fh| fh.puts "dum" }
result = run_rscons(op: %w[clean])
expect(File.exists?('build/e.1')).to be_truthy
@@ -366,12 +377,12 @@ EOF
result = run_rscons(rsconscript: "install.rb", op: %W[install])
expect(result.stderr).to eq ""
expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.o")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_truthy
result = run_rscons(rsconscript: "install.rb", op: %W[clean])
expect(result.stderr).to eq ""
expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.o")).to be_falsey
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_falsey
end
end
@@ -388,7 +399,7 @@ EOF
result = run_rscons(rsconscript: "install.rb", op: %W[clean])
expect(result.stderr).to eq ""
expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.o")).to be_falsey
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_falsey
result = run_rscons(rsconscript: "install.rb", op: %W[uninstall -v])
expect(result.stderr).to eq ""
@@ -407,7 +418,7 @@ EOF
%r{Linking program.exe},
])
expect(File.exists?('inc.h')).to be_truthy
expect(`./program.exe`).to eq "The value is 5678\n"
expect(nr(`./program.exe`)).to eq "The value is 5678\n"
end
it 'supports custom builders with multiple targets' do
@@ -423,13 +434,13 @@ EOF
])
expect(File.exists?("inc.c")).to be_truthy
expect(File.exists?("inc.h")).to be_truthy
expect(`./program.exe`).to eq "The value is 42\n"
expect(nr(`./program.exe`)).to eq "The value is 42\n"
File.open("inc.c", "w") {|fh| fh.puts "int THE_VALUE = 33;"}
result = run_rscons(rsconscript: "multiple_targets.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [%r{CHGen inc.c}])
expect(`./program.exe`).to eq "The value is 42\n"
expect(nr(`./program.exe`)).to eq "The value is 42\n"
end
it 'raises an error when a custom builder returns an invalid value from #run' do
@@ -470,10 +481,10 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/src/program.o -MMD -MF build/e.1/src/program.mf '-DSTRING="Debug Version"' -O2 src/program.c},
%r{gcc -o program-debug.exe build/e.1/src/program.o},
%r{gcc -c -o build/e.2/src/program.o -MMD -MF build/e.2/src/program.mf '-DSTRING="Release Version"' -O2 src/program.c},
%r{gcc -o program-release.exe build/e.2/src/program.o},
%r{gcc -c -o build/e.1/src/program.c.o -MMD -MF build/e.1/src/program.c.o.mf '-DSTRING="Debug Version"' -O2 src/program.c},
%r{gcc -o program-debug.exe build/e.1/src/program.c.o},
%r{gcc -c -o build/e.2/src/program.c.o -MMD -MF build/e.2/src/program.c.o.mf '-DSTRING="Release Version"' -O2 src/program.c},
%r{gcc -o program-release.exe build/e.2/src/program.c.o},
])
end
@@ -482,12 +493,12 @@ EOF
result = run_rscons(rsconscript: "clone_all.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/src/program.o -MMD -MF build/e.1/src/program.mf -DSTRING="Hello" -O2 src/program.c},
%r{post build/e.1/src/program.o},
%r{gcc -o program.exe build/e.1/src/program.o},
%r{gcc -c -o build/e.1/src/program.c.o -MMD -MF build/e.1/src/program.c.o.mf -DSTRING="Hello" -O2 src/program.c},
%r{post build/e.1/src/program.c.o},
%r{gcc -o program.exe build/e.1/src/program.c.o},
%r{post program.exe},
%r{post build/e.2/src/program.o},
%r{gcc -o program2.exe build/e.2/src/program.o},
%r{post build/e.2/src/program.c.o},
%r{gcc -o program2.exe build/e.2/src/program.c.o},
%r{post program2.exe},
])
end
@@ -496,8 +507,8 @@ EOF
test_dir('simple_cc')
result = run_rscons
expect(result.stderr).to eq ""
expect(File.exists?('build/e.1/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C++ program\n"
expect(File.exists?('build/e.1/simple.cc.o')).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C++ program\n"
end
it "links with the C++ linker when object files were built from C++ sources" do
@@ -505,7 +516,7 @@ EOF
result = run_rscons(rsconscript: "link_objects.rb")
expect(result.stderr).to eq ""
expect(File.exists?("simple.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C++ program\n"
expect(nr(`./simple.exe`)).to eq "This is a simple C++ program\n"
end
it 'allows overriding construction variables for individual builder calls' do
@@ -513,12 +524,12 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o one.o -MMD -MF one.mf -DONE one.c},
%r{gcc -c -o build/e.1/two.o -MMD -MF build/e.1/two.mf two.c},
%r{gcc -o two_sources.exe one.o build/e.1/two.o},
%r{gcc -c -o one.o -MMD -MF one.o.mf -DONE one.c},
%r{gcc -c -o build/e.1/two.c.o -MMD -MF build/e.1/two.c.o.mf two.c},
%r{gcc -o two_sources.exe one.o build/e.1/two.c.o},
])
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(nr(`./two_sources.exe`)).to eq "This is a C program with two sources.\n"
end
it 'builds a static library archive' do
@@ -526,14 +537,14 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/one.o -MMD -MF build/e.1/one.mf -Dmake_lib one.c},
%r{gcc -c -o build/e.1/two.o -MMD -MF build/e.1/two.mf -Dmake_lib two.c},
%r{ar rcs lib.a build/e.1/one.o build/e.1/two.o},
%r{gcc -c -o build/e.1/three.o -MMD -MF build/e.1/three.mf three.c},
%r{gcc -o library.exe lib.a build/e.1/three.o},
%r{gcc -c -o build/e.1/one.c.o -MMD -MF build/e.1/one.c.o.mf -Dmake_lib one.c},
%r{gcc -c -o build/e.1/two.c.o -MMD -MF build/e.1/two.c.o.mf -Dmake_lib two.c},
%r{ar rcs lib.a build/e.1/one.c.o build/e.1/two.c.o},
%r{gcc -c -o build/e.1/three.c.o -MMD -MF build/e.1/three.c.o.mf three.c},
%r{gcc -o library.exe lib.a build/e.1/three.c.o},
])
expect(File.exists?("library.exe")).to be_truthy
expect(`ar t lib.a`).to eq "one.o\ntwo.o\n"
expect(nr(`ar t lib.a`)).to eq "one.c.o\ntwo.c.o\n"
end
it 'supports build hooks to override construction variables' do
@@ -541,11 +552,11 @@ EOF
result = run_rscons(rsconscript: "build_hooks.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o build/e.1/src/one/one.o -MMD -MF build/e.1/src/one/one.mf -Isrc/one -Isrc/two -O1 src/one/one.c},
%r{gcc -c -o build/e.1/src/two/two.o -MMD -MF build/e.1/src/two/two.mf -Isrc/one -Isrc/two -O2 src/two/two.c},
%r{gcc -o build_hook.exe build/e.1/src/one/one.o build/e.1/src/two/two.o},
%r{gcc -c -o build/e.1/src/one/one.c.o -MMD -MF build/e.1/src/one/one.c.o.mf -Isrc/one -Isrc/two -O1 src/one/one.c},
%r{gcc -c -o build/e.1/src/two/two.c.o -MMD -MF build/e.1/src/two/two.c.o.mf -Isrc/one -Isrc/two -O2 src/two/two.c},
%r{gcc -o build_hook.exe build/e.1/src/one/one.c.o build/e.1/src/two/two.c.o},
])
expect(`./build_hook.exe`).to eq "Hello from two()\n"
expect(nr(`./build_hook.exe`)).to eq "Hello from two()\n"
end
it 'supports build hooks to override the entire vars hash' do
@@ -553,8 +564,8 @@ EOF
result = run_rscons(rsconscript: "build_hooks_override_vars.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o one.o -MMD -MF one.mf -Isrc -Isrc/one -Isrc/two -O1 src/two/two.c},
%r{gcc -c -o two.o -MMD -MF two.mf -Isrc -Isrc/one -Isrc/two -O2 src/two/two.c},
%r{gcc -c -o one.o -MMD -MF one.o.mf -Isrc -Isrc/one -Isrc/two -O1 src/two/two.c},
%r{gcc -c -o two.o -MMD -MF two.o.mf -Isrc -Isrc/one -Isrc/two -O2 src/two/two.c},
])
expect(File.exists?('one.o')).to be_truthy
expect(File.exists?('two.o')).to be_truthy
@@ -570,8 +581,8 @@ EOF
%r{Compiling simple.c},
%r{Linking simple.exe},
])
expect(File.exists?('build/e.1/simple.o')).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(File.exists?('build/e.1/simple.c.o')).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
File.open("program.ld", "w") {|fh| fh.puts("2")}
result = run_rscons(rsconscript: "user_dependencies.rb")
@@ -588,18 +599,53 @@ EOF
expect(result.stdout).to eq ""
end
unless ENV["omit_gdc_tests"]
it "supports building D sources" do
unless RUBY_PLATFORM =~ /mingw|msys/
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}])
verify_lines(slines, [%r{gdc -c -o build/e.1/main.d.o -MMD -MF build/e.1/main.d.o.mf main.d}])
verify_lines(slines, [%r{gdc -c -o build/e.1/mod.d.o -MMD -MF build/e.1/mod.d.o.mf mod.d}])
verify_lines(slines, [%r{gdc -o hello-d.exe build/e.1/main.d.o build/e.1/mod.d.o}])
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!"
end
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.d.o(bj)? -deps=build/e.1/main.d.o(bj)?.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.d.o(bj)? -deps=build/e.1/mod.d.o(bj)?.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.d.o(bj)? build/e.1/mod.d.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.d.o(bj)? -deps=build/e.1/main.d.o(bj)?.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.d.o(bj)? -deps=build/e.1/mod.d.o(bj)?.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.d.o(bj)? build/e.1/mod.d.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.d.o(bj)? -deps=build/e.1/main.d.o(bj)?.mf main.d}])
verify_lines(slines, [%r{ldc2 -c -of build/e.1/mod.d.o(bj)? -deps=build/e.1/mod.d.o(bj)?.mf mod.d}])
verify_lines(slines, [%r{ldc2 -of hello-d.exe build/e.1/main.d.o(bj)? build/e.1/mod.d.o(bj)?}])
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 33!"
end
unless RUBY_PLATFORM =~ /mingw|msys/
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")
@@ -614,18 +660,18 @@ EOF
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}])
verify_lines(slines, [%r{gdc -c -o build/e.1/main.d.o -MMD -MF build/e.1/main.d.o.mf main.d}])
verify_lines(slines, [%r{gdc -c -o build/e.1/mod.d.o -MMD -MF build/e.1/mod.d.o.mf mod.d}])
verify_lines(slines, [%r{gdc -o hello-d.exe build/e.1/main.d.o build/e.1/mod.d.o}])
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!"
fcontents = File.read("mod.d", mode: "rb").sub("42", "33")
File.open("mod.d", "wb") {|fh| fh.write(fcontents)}
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}])
verify_lines(slines, [%r{gdc -c -o build/e.1/main.d.o -MMD -MF build/e.1/main.d.o.mf main.d}])
verify_lines(slines, [%r{gdc -c -o build/e.1/mod.d.o -MMD -MF build/e.1/mod.d.o.mf mod.d}])
verify_lines(slines, [%r{gdc -o hello-d.exe build/e.1/main.d.o build/e.1/mod.d.o}])
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 33!"
end
@@ -633,13 +679,9 @@ EOF
test_dir("shared_library")
result = run_rscons(rsconscript: "shared_library_d.rb")
# Currently gdc produces an error while trying to build the shared
# 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 ""
expect(result.stderr).to eq ""
slines = lines(result.stdout)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
verify_lines(slines, [%r{Linking mine.dll}])
else
verify_lines(slines, [%r{Linking libmine.so}])
@@ -665,7 +707,7 @@ EOF
result = run_rscons(rsconscript: "preprocess.rb")
expect(result.stderr).to eq ""
expect(File.read("simplepp.c")).to match /# \d+ "simple.c"/
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "supports preprocessing C++ sources" do
@@ -673,7 +715,7 @@ EOF
result = run_rscons(rsconscript: "preprocess.rb")
expect(result.stderr).to eq ""
expect(File.read("simplepp.cc")).to match /# \d+ "simple.cc"/
expect(`./simple.exe`).to eq "This is a simple C++ program\n"
expect(nr(`./simple.exe`)).to eq "This is a simple C++ program\n"
end
it "supports invoking builders with no sources" do
@@ -691,23 +733,23 @@ EOF
%r{Linking program.exe},
])
expect(File.exists?('inc.h')).to be_truthy
expect(`./program.exe`).to eq "The value is 678\n"
expect(nr(`./program.exe`)).to eq "The value is 678\n"
end
it "supports lambdas as construction variable values" do
test_dir "custom_builder"
result = run_rscons(rsconscript: "cvar_lambda.rb")
expect(result.stderr).to eq ""
expect(`./program.exe`).to eq "The value is 5678\n"
expect(nr(`./program.exe`)).to eq "The value is 5678\n"
end
it "supports registering build targets from within a build hook" do
test_dir("simple")
result = run_rscons(rsconscript: "register_target_in_build_hook.rb")
expect(result.stderr).to eq ""
expect(File.exists?("build/e.1/simple.o")).to be_truthy
expect(File.exists?("build/e.1/simple.o.txt")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(File.exists?("build/e.1/simple.c.o")).to be_truthy
expect(File.exists?("build/e.1/simple.c.o.txt")).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "supports multiple values for CXXSUFFIX" do
@@ -715,9 +757,9 @@ EOF
File.open("other.cccc", "w") {|fh| fh.puts}
result = run_rscons(rsconscript: "cxxsuffix.rb")
expect(result.stderr).to eq ""
expect(File.exists?("build/e.1/simple.o")).to be_truthy
expect(File.exists?("build/e.1/other.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C++ program\n"
expect(File.exists?("build/e.1/simple.cc.o")).to be_truthy
expect(File.exists?("build/e.1/other.cccc.o")).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C++ program\n"
end
it "supports multiple values for CSUFFIX" do
@@ -725,9 +767,9 @@ EOF
FileUtils.mv("src/one/one.c", "src/one/one.yargh")
result = run_rscons(rsconscript: "csuffix.rb")
expect(result.stderr).to eq ""
expect(File.exists?("build/e.1/src/one/one.o")).to be_truthy
expect(File.exists?("build/e.1/src/two/two.o")).to be_truthy
expect(`./program.exe`).to eq "Hello from two()\n"
expect(File.exists?("build/e.1/src/one/one.yargh.o")).to be_truthy
expect(File.exists?("build/e.1/src/two/two.c.o")).to be_truthy
expect(nr(`./program.exe`)).to eq "Hello from two()\n"
end
it "supports multiple values for OBJSUFFIX" do
@@ -737,7 +779,7 @@ EOF
expect(File.exists?("two_sources.exe")).to be_truthy
expect(File.exists?("one.oooo")).to be_truthy
expect(File.exists?("two.ooo")).to be_truthy
expect(`./two_sources.exe`).to eq "This is a C program with two sources.\n"
expect(nr(`./two_sources.exe`)).to eq "This is a C program with two sources.\n"
end
it "supports multiple values for LIBSUFFIX" do
@@ -745,7 +787,7 @@ EOF
result = run_rscons(rsconscript: "libsuffix.rb")
expect(result.stderr).to eq ""
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(nr(`./two_sources.exe`)).to eq "This is a C program with two sources.\n"
end
it "supports multiple values for ASSUFFIX" do
@@ -760,7 +802,7 @@ EOF
%r{Linking two_sources.exe},
])
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(nr(`./two_sources.exe`)).to eq "This is a C program with two sources.\n"
end
it "supports dumping an Environment's construction variables" do
@@ -798,8 +840,8 @@ EOF
test_dir("simple")
result = run_rscons(rsconscript: "cvar_array.rb")
expect(result.stderr).to eq ""
expect(File.exists?("build/e.1/simple.o")).to be_truthy
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(File.exists?("build/e.1/simple.c.o")).to be_truthy
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
end
it "supports registering multiple build targets with the same target path" do
@@ -880,7 +922,7 @@ EOF
result = run_rscons(rsconscript: "absolute_source_path.rb")
expect(result.stderr).to eq ""
slines = lines(result.stdout)
verify_lines(slines, [%r{build/e.1/.*/abs\.o$}])
verify_lines(slines, [%r{build/e.1/.*/abs\.c.o$}])
verify_lines(slines, [%r{\babs.exe\b}])
end
@@ -890,7 +932,7 @@ EOF
result = run_rscons
expect(result.stderr).to eq ""
slines = lines(result.stdout)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
verify_lines(slines, [%r{Linking mine.dll}])
expect(File.exists?("mine.dll")).to be_truthy
else
@@ -902,7 +944,7 @@ EOF
expect(result.stderr).to eq ""
expect(result.stdout).to eq ""
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw/ ? "" : "LD_LIBRARY_PATH=. ")
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw|msys/ ? "" : "LD_LIBRARY_PATH=. ")
expect(`#{ld_library_path_prefix}./test-shared.exe`).to match /Hi from one/
expect(`./test-static.exe`).to match /Hi from one/
end
@@ -921,7 +963,7 @@ EOF
result = run_rscons(rsconscript: "shared_library_cxx.rb")
expect(result.stderr).to eq ""
slines = lines(result.stdout)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
verify_lines(slines, [%r{Linking mine.dll}])
else
verify_lines(slines, [%r{Linking libmine.so}])
@@ -931,7 +973,7 @@ EOF
expect(result.stderr).to eq ""
expect(result.stdout).to eq ""
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw/ ? "" : "LD_LIBRARY_PATH=. ")
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw|msys/ ? "" : "LD_LIBRARY_PATH=. ")
expect(`#{ld_library_path_prefix}./test-shared.exe`).to match /Hi from one/
expect(`./test-static.exe`).to match /Hi from one/
end
@@ -1062,7 +1104,7 @@ EOF
result = run_rscons(rsconscript: "command_builder.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [%r{BuildIt simple.exe}])
expect(`./simple.exe`).to eq "This is a simple C program\n"
expect(nr(`./simple.exe`)).to eq "This is a simple C program\n"
result = run_rscons(rsconscript: "command_builder.rb")
expect(result.stderr).to eq ""
@@ -1395,6 +1437,18 @@ EOF
expect(result.stdout).to eq ""
end
it "supports building multiple object files from sources with the same pathname and basename" do
test_dir "multiple_basename"
result = run_rscons
expect(result.stderr).to eq ""
expect(result.status).to eq 0
expect(File.exist?("foo.exe")).to be_truthy
result = run_rscons
expect(result.stderr).to eq ""
expect(result.stdout).to eq ""
expect(result.status).to eq 0
end
context "debugging" do
it "prints a message when the target does not exist" do
test_dir("simple")
@@ -1488,7 +1542,7 @@ EOF
result = run_rscons(rsconscript: "override_depfilesuffix.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [
%r{gcc -c -o simple.o -MMD -MF simple.deppy simple.c},
%r{gcc -c -o simple.o -MMD -MF simple.o.deppy simple.c},
])
end
@@ -1512,7 +1566,7 @@ EOF
test_dir("library")
result = run_rscons(rsconscript: "override_arcmd.rb")
expect(result.stderr).to eq ""
verify_lines(lines(result.stdout), [%r{ar rcf lib.a build/e.1/one.o build/e.1/three.o build/e.1/two.o}])
verify_lines(lines(result.stdout), [%r{ar rcf lib.a build/e.1/one.c.o build/e.1/three.c.o build/e.1/two.c.o}])
end
it "allows passing object files as sources" do
@@ -1531,7 +1585,7 @@ EOF
result = run_rscons(rsconscript: "shared_library_set_shld.rb")
expect(result.stderr).to eq ""
slines = lines(result.stdout)
if RUBY_PLATFORM =~ /mingw/
if RUBY_PLATFORM =~ /mingw|msys/
verify_lines(slines, [%r{Linking mine.dll}])
else
verify_lines(slines, [%r{Linking libmine.so}])
@@ -1542,7 +1596,7 @@ EOF
test_dir "shared_library"
result = run_rscons(rsconscript: "shared_library_from_object.rb")
expect(result.stderr).to eq ""
expect(File.exists?("one.o"))
expect(File.exists?("one.c.o"))
end
end
@@ -1675,7 +1729,7 @@ EOF
create_exe "gcc", "exit 1"
create_exe "clang", "exit 1"
result = run_rscons(rsconscript: rsconscript, op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for C compiler\.\.\. not found/
end
@@ -1718,7 +1772,7 @@ EOF
create_exe "g++", "exit 1"
create_exe "clang++", "exit 1"
result = run_rscons(rsconscript: rsconscript, op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for C\+\+ compiler\.\.\. not found/
end
@@ -1739,6 +1793,7 @@ EOF
{"check_d_compiler.rb" => "when no arguments are given",
"check_d_compiler_find_first.rb" => "when arguments are given"}.each_pair do |rsconscript, desc|
context desc do
unless RUBY_PLATFORM =~ /mingw|msys/
it "finds the first listed D compiler" do
test_dir "configure"
result = run_rscons(rsconscript: rsconscript, op: "configure")
@@ -1746,6 +1801,7 @@ EOF
expect(result.status).to eq 0
expect(result.stdout).to match /Checking for D compiler\.\.\. gdc/
end
end
it "finds the second listed D compiler" do
test_dir "configure"
@@ -1761,13 +1817,14 @@ EOF
create_exe "gdc", "exit 1"
create_exe "ldc2", "exit 1"
result = run_rscons(rsconscript: rsconscript, op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for D compiler\.\.\. not found/
end
end
end
unless RUBY_PLATFORM =~ /mingw|msys/
it "successfully tests a compiler with an unknown name that uses gdc-compatible options" do
test_dir "configure"
create_exe "mycompiler", %[exec gdc "$@"]
@@ -1776,6 +1833,7 @@ EOF
expect(result.status).to eq 0
expect(result.stdout).to match /Checking for D compiler\.\.\. mycompiler/
end
end
it "successfully tests a compiler with an unknown name that uses ldc2-compatible options" do
test_dir "configure"
@@ -1799,7 +1857,7 @@ EOF
it "fails when the requested header is not found" do
test_dir "configure"
result = run_rscons(rsconscript: "check_c_header_failure.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for C header 'not___found\.h'... not found/
end
@@ -1864,7 +1922,7 @@ EOF
it "fails when the requested header is not found" do
test_dir "configure"
result = run_rscons(rsconscript: "check_cxx_header_failure.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for C\+\+ header 'not___found\.h'... not found/
end
@@ -1905,7 +1963,7 @@ EOF
it "fails when the requested import is not found" do
test_dir "configure"
result = run_rscons(rsconscript: "check_d_import_failure.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for D import 'not\.found'... not found/
end
@@ -1946,7 +2004,7 @@ EOF
it "fails when the requested library is not found" do
test_dir "configure"
result = run_rscons(rsconscript: "check_lib_failure.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for library 'mfoofoo'... not found/
end
@@ -2014,10 +2072,20 @@ EOF
expect(result.stdout).to match /Checking for program 'find'... .*find/
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
test_dir "configure"
result = run_rscons(rsconscript: "check_program_failure.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking for program 'program-that-is-not-found'... not found/
end
@@ -2049,7 +2117,7 @@ EOF
it "fails when the configure program given does not exist" do
test_dir "configure"
result = run_rscons(rsconscript: "check_cfg.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.status).to_not eq 0
expect(result.stdout).to match /Checking 'my-config'\.\.\. not found/
end
@@ -2094,7 +2162,7 @@ EOF
test_dir "configure"
create_exe "grep", "exit 4"
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.stdout).to match /Checking 'grep' version\.\.\. error executing grep/
expect(result.status).to_not eq 0
end
@@ -2105,7 +2173,7 @@ EOF
test_dir "configure"
create_exe "grep", "echo 'grep (GNU grep) 1.1'"
result = run_rscons(rsconscript: "custom_config_check.rb", op: "configure")
expect(result.stderr).to eq ""
expect(result.stderr).to match /Configuration failed/
expect(result.stdout).to match /Checking 'grep' version\.\.\. too old!/
expect(result.status).to_not eq 0
end
@@ -2143,6 +2211,24 @@ EOF
expect(result.status).to eq 0
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
context "on_fail option" do
it "prints on_fail messages and calls on_fail procs on failure" do
test_dir "configure"
result = run_rscons(rsconscript: "on_fail.rb", op: %w[configure])
expect(result.status).to_not eq 0
expect(result.stdout).to match /Install the foo123 package/
expect(result.stdout).to match /Install the foo123cxx package/
end
end
@@ -2156,8 +2242,8 @@ EOF
expect(result.stdout).to match /Setting build directory\.\.\. bb/
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\.\.\. g++/
expect(result.stdout).to match /Checking for D compiler\.\.\. gdc/
expect(result.stdout).to match /Checking for C\+\+ compiler\.\.\. g\+\+/
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 C header 'stdio.h'\.\.\. found/
expect(result.stdout).to match /Checking for C\+\+ header 'iostream'\.\.\. found/
@@ -2184,11 +2270,13 @@ EOF
expect(result.status).to_not eq 0
end
it "exits with an error if configuration fails during autoconf" do
it "exits with an error code and message if configuration fails during autoconf" do
test_dir "configure"
result = run_rscons(rsconscript: "autoconf_fail.rb")
expect(result.stdout).to match /Checking for C compiler\.\.\. not found/
expect(result.status).to_not eq 0
expect(result.stderr).to_not match /from\s/
expect(lines(result.stderr).last).to eq "Configuration failed"
end
it "exits with an error if configuration has not been performed before attempting to create an environment" do
@@ -2297,7 +2385,7 @@ EOF
expect(result.stderr).to eq ""
expect(result.stdout).to match %r{Compiling/Linking}
expect(File.exists?("test.exe")).to be_truthy
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw/ ? "" : "LD_LIBRARY_PATH=. ")
ld_library_path_prefix = (RUBY_PLATFORM =~ /mingw|msys/ ? "" : "LD_LIBRARY_PATH=. ")
expect(`#{ld_library_path_prefix}./test.exe`).to match /three/
result = run_rscons(rsconscript: "c_shared_library.rb")
@@ -2392,13 +2480,13 @@ EOF
result = run_rscons(rsconscript: "install.rb", op: %W[install])
expect(result.stderr).to eq ""
expect(File.exists?("#{prefix}/bin/program.exe")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.o")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_truthy
result = run_rscons(rsconscript: "install.rb", op: %W[uninstall])
expect(result.stderr).to eq ""
expect(result.stdout).to_not match /Removing/
expect(File.exists?("#{prefix}/bin/program.exe")).to be_falsey
expect(File.exists?("build/e.1/src/one/one.o")).to be_truthy
expect(File.exists?("build/e.1/src/one/one.c.o")).to be_truthy
expect(Dir.entries(prefix)).to match_array %w[. ..]
end
end
+21 -5
View File
@@ -68,7 +68,7 @@ EOF
expect(RbConfig::CONFIG).to receive(:[]).with("host_os").and_return("mingw")
end
it "returns the number of logical processors that wmic reports" do
expect(Util).to receive(:`).with("wmic cpu get NumberOfLogicalProcessors /value").and_return("NumberOfLogicalProcessors=7")
expect(Util).to receive(:`).with("wmic cpu get NumberOfLogicalProcessors -value").and_return("NumberOfLogicalProcessors=7")
expect(Util.determine_n_threads).to eq(7)
end
end
@@ -121,7 +121,10 @@ EOF
before(:each) do
stub_const("File::PATH_SEPARATOR", ";")
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:\\Windows").and_return(%w[two.exe Three.bat])
end
@@ -197,12 +200,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(<<EOS)
module.o: source.cc
EOS
expect(Util.parse_makefile_deps('makefile')).to eq ['source.cc']
expect(Util.parse_dependency_file('makefile')).to eq ['source.cc']
end
it 'handles dependencies split across many lines' do
@@ -211,9 +214,22 @@ module.o: module.c \\
module.h \\
other.h
EOS
expect(Util.parse_makefile_deps('makefile')).to eq [
expect(Util.parse_dependency_file('makefile')).to eq [
'module.c', 'module.h', 'other.h']
end
it "parses ldc2-style dependency lines" do
expect(File).to receive(:read).with("deps.out").and_return(<<EOS)
std.traits (/usr/lib/ldc/x86_64-linux-gnu/include/d/std/traits.d) : private : std.meta (/usr/lib/ldc/x86_64-linux-gnu/include/d/std/meta.d):staticIndexOf
std.conv (/usr/lib/ldc/x86_64-linux-gnu/include/d/std/conv.d) : private : std.array (/usr/lib/ldc/x86_64-linux-gnu/include/d/std/array.d):array
std.stdio (/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d) : private static : core.sys.posix.sys.socket (/usr/lib/ldc/x86_64-linux-gnu/include/d/core/sys/posix/sys/socket.d) -> 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
-10
View File
@@ -1,15 +1,5 @@
describe Rscons do
describe ".set_suffix" do
it "changes the suffix to the new one" do
expect(Rscons.set_suffix("foo.c", ".h")).to eq("foo.h")
end
it "appends a suffix if the given file name does not have one" do
expect(Rscons.set_suffix("bazz", ".d")).to eq("bazz.d")
end
end
describe ".get_system_shell" do
before(:each) do
Rscons.instance_variable_set(:@shell, nil)