Compare commits

...
10 Commits
Author SHA1 Message Date
josh 5cf77f1f58 v1.16.0 2018-08-24 09:24:03 -04:00
josh b4cc45c381 update documentation 2018-08-24 09:17:23 -04:00
josh 750506201f add github URL to README.md 2018-08-23 15:37:18 -04:00
josh 284312a21c support command-line variables - close #51 2018-08-23 14:58:08 -04:00
josh d081a4695f add shebang line to bin/rscons 2018-08-23 11:30:18 -04:00
josh c7f66694ab add Rscons.glob - close #50 2018-08-23 11:26:20 -04:00
josh 57de94a3fb improve debuggability of cache.up_to_date? - close #46 2018-08-23 10:10:05 -04:00
josh 53ba7dad41 allow passing a VarSet into cache methods - close #47 2018-08-22 16:32:05 -04:00
josh 8cb02a7e34 generate dependencies for D builds - close #49 2018-08-22 15:23:48 -04:00
josh dbbce9e476 update a few dependencies 2018-05-24 15:32:39 -04:00
32 changed files with 371 additions and 91 deletions

No files matched your search

+13
View File
@@ -1,5 +1,18 @@
## ChangeLog ## ChangeLog
### v1.16.0
#### New Features
- Add `Rscons.glob`
- Support command-line variables
- improve debuggability of cache.up_to_date?
- allow passing a VarSet into cache methods
#### Fixes
- generate dependencies for D builds
### v1.15.0 ### v1.15.0
- allow json 1.x or 2.x - allow json 1.x or 2.x
+4 -6
View File
@@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
rscons (1.15.0) rscons (1.16.0)
json (>= 1.8, < 3.0) json (>= 1.8, < 3.0)
GEM GEM
@@ -10,9 +10,8 @@ GEM
diff-lcs (1.3) diff-lcs (1.3)
docile (1.1.5) docile (1.1.5)
json (2.1.0) json (2.1.0)
rake (12.0.0) rake (12.3.1)
rdoc (5.1.0) rdoc (5.1.0)
redcarpet (3.4.0)
rspec (3.6.0) rspec (3.6.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.6.0)
@@ -31,7 +30,7 @@ GEM
json (>= 1.8, < 3) json (>= 1.8, < 3)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.2) simplecov-html (0.10.2)
yard (0.9.9) yard (0.9.12)
PLATFORMS PLATFORMS
ruby ruby
@@ -40,11 +39,10 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
rake rake
rdoc rdoc
redcarpet
rscons! rscons!
rspec rspec
simplecov simplecov
yard yard
BUNDLED WITH BUNDLED WITH
1.15.4 1.16.2
+37 -17
View File
@@ -1,7 +1,7 @@
# Rscons # Rscons
Rscons is a software construction framework inspired by SCons and implemented Rscons (https://github.com/holtrop/rscons) is a software construction framework
in Ruby. inspired by SCons and implemented in Ruby.
[![Gem Version](https://badge.fury.io/rb/rscons.png)](http://badge.fury.io/rb/rscons) [![Gem Version](https://badge.fury.io/rb/rscons.png)](http://badge.fury.io/rb/rscons)
@@ -30,7 +30,7 @@ task block or split among multiple tasks.
```ruby ```ruby
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CFLAGS"] << "-Wall" env["CFLAGS"] << "-Wall"
env.Program("program", Dir["src/**/*.c"]) env.Program("program", Rscons.glob("src/**/*.c"))
end end
``` ```
@@ -39,7 +39,7 @@ end
```ruby ```ruby
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["DFLAGS"] << "-Wall" env["DFLAGS"] << "-Wall"
env.Program("program", Dir["src/**/*.d"]) env.Program("program", Rscons.glob("src/**/*.d"))
end end
``` ```
@@ -51,7 +51,7 @@ main_env = Rscons::Environment.new do |env|
env.build_dir("src", "build/main") env.build_dir("src", "build/main")
env["CFLAGS"] = ["-DSOME_DEFINE", "-O3"] env["CFLAGS"] = ["-DSOME_DEFINE", "-O3"]
env["LIBS"] = ["SDL"] env["LIBS"] = ["SDL"]
env.Program("program", Dir["src/**/*.cc"]) env.Program("program", Rscons.glob("src/**/*.cc"))
end end
debug_env = main_env.clone do |env| debug_env = main_env.clone do |env|
@@ -59,7 +59,7 @@ debug_env = main_env.clone do |env|
env.build_dir("src", "build/debug") env.build_dir("src", "build/debug")
env["CFLAGS"] -= ["-O3"] env["CFLAGS"] -= ["-O3"]
env["CFLAGS"] += ["-g", "-O0"] env["CFLAGS"] += ["-g", "-O0"]
env.Program("program-debug", Dir["src/**/*.cc"]) env.Program("program-debug", Rscons.glob("src/**/*.cc"))
end end
``` ```
@@ -86,7 +86,7 @@ end
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.add_builder(GenerateFoo.new) env.add_builder(GenerateFoo.new)
env.GenerateFoo("foo.h", []) env.GenerateFoo("foo.h", [])
env.Program("a.out", Dir["*.c"]) env.Program("a.out", Rscons.glob("*.c"))
end end
``` ```
@@ -111,6 +111,15 @@ Rscons::Environment.new do |env|
end end
``` ```
The `Cache#up_to_date?` method accepts an optional 5th parameter which is an
options Hash. The `:debug` option can be specified in this Hash with a value
of `true` to aid in debugging builders while developing them. For example:
```ruby
unless cache.up_to_date?(target, cmd, sources, env, debug: true)
end
```
### Example: Custom Builder That Generates Multiple Output Files ### Example: Custom Builder That Generates Multiple Output Files
```ruby ```ruby
@@ -191,7 +200,7 @@ Rscons::Environment.new do |env|
end end
end end
env.build_dir("src", "build") env.build_dir("src", "build")
env.Program("program", Dir["**/*.cc"]) env.Program("program", Rscons.glob("**/*.cc"))
end end
``` ```
@@ -199,7 +208,7 @@ end
```ruby ```ruby
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.Library("mylib.a", Dir["src/**/*.c"]) env.Library("mylib.a", Rscons.glob("src/**/*.c"))
end end
``` ```
@@ -327,7 +336,7 @@ env.Install("dist/share", "share")
```ruby ```ruby
env.Library(target, sources) env.Library(target, sources)
# Example # Example
env.Library("lib.a", Dir["src/**/*.c"]) env.Library("lib.a", Rscons.glob("src/**/*.c"))
``` ```
The Library builder creates a static library archive from the given source The Library builder creates a static library archive from the given source
@@ -362,7 +371,7 @@ preprocessed output to the target file.
```ruby ```ruby
env.Program(target, sources) env.Program(target, sources)
# Example # Example
env.Program("myprog", Dir["src/**/*.cc"]) env.Program("myprog", Rscons.glob("src/**/*.cc"))
``` ```
The Program builder compiles and links the given sources to an executable file. The Program builder compiles and links the given sources to an executable file.
@@ -375,7 +384,7 @@ This can be controlled with the `PROGSUFFIX` construction variable.
```ruby ```ruby
env.SharedLibrary(target, sources) env.SharedLibrary(target, sources)
# Example # Example
env.SharedLibrary("mydll", Dir["src/**/*.cc"]) env.SharedLibrary("mydll", Rscons.glob("src/**/*.cc"))
``` ```
The SharedLibrary builder compiles and links the given sources to a dynamically The SharedLibrary builder compiles and links the given sources to a dynamically
@@ -411,14 +420,14 @@ construction variables can be overridden by the user.
| ARFLAGS | Array | Static library archiver flags | ["rcs"] | | ARFLAGS | Array | Static library archiver flags | ["rcs"] |
| AS | String | Assembler executable | "${CC}" | | AS | String | Assembler executable | "${CC}" |
| ASCMD | Array | Assembler command line | ["${AS}", "-c", "-o", "${_TARGET}", "${ASDEPGEN}", "${INCPREFIX}${ASPPPATH}", "${ASPPFLAGS}", "${ASFLAGS}", "${_SOURCES}"] | | ASCMD | Array | Assembler command line | ["${AS}", "-c", "-o", "${_TARGET}", "${ASDEPGEN}", "${INCPREFIX}${ASPPPATH}", "${ASPPFLAGS}", "${ASFLAGS}", "${_SOURCES}"] |
| ASDEPGEN | Array | Assembly dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}"] | | ASDEPGEN | Array | Assembly dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}", "-MT", "TARGET"] |
| ASFLAGS | Array | Assembler flags | [] | | ASFLAGS | Array | Assembler flags | [] |
| ASPPFLAGS | Array | Assembler preprocessor flags | ["${CPPFLAGS}"] | | ASPPFLAGS | Array | Assembler preprocessor flags | ["${CPPFLAGS}"] |
| ASPPPATH | Array | Assembler preprocessor path | ["${CPPPATH}"] | | ASPPPATH | Array | Assembler preprocessor path | ["${CPPPATH}"] |
| ASSUFFIX | Array | Assembly file suffixes | [".S"] | | ASSUFFIX | Array | Assembly file suffixes | [".S"] |
| CC | String | C compiler executable | "gcc" | | CC | String | C compiler executable | "gcc" |
| CCCMD | Array | C compiler command line | ["${CC}", "-c", "-o", "${_TARGET}", "${CCDEPGEN}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${CFLAGS}", "${CCFLAGS}", "${_SOURCES}"] | | CCCMD | Array | C compiler command line | ["${CC}", "-c", "-o", "${_TARGET}", "${CCDEPGEN}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${CFLAGS}", "${CCFLAGS}", "${_SOURCES}"] |
| CCDEPGEN | Array | C compiler dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}"] | | CCDEPGEN | Array | C compiler dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}", "-MT", "TARGET"] |
| CCFLAGS | Array | Common flags for both C and C++ compiler | [] | | CCFLAGS | Array | Common flags for both C and C++ compiler | [] |
| CFLAGS | Array | C compiler flags | [] | | CFLAGS | Array | C compiler flags | [] |
| CPP_CMD | Array | Preprocess command line | ["${_PREPROCESS_CC}", "-E", "${_PREPROCESS_DEPGEN}", "-o", "${_TARGET}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${_SOURCES}"] | | CPP_CMD | Array | Preprocess command line | ["${_PREPROCESS_CC}", "-E", "${_PREPROCESS_DEPGEN}", "-o", "${_TARGET}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${_SOURCES}"] |
@@ -430,12 +439,13 @@ construction variables can be overridden by the user.
| CSUFFIX | Array | C source file suffixes | [".c"] | | CSUFFIX | Array | C source file suffixes | [".c"] |
| CXX | String | C++ compiler executable | "g++" | | CXX | String | C++ compiler executable | "g++" |
| CXXCMD | Array | C++ compiler command line | ["${CXX}", "-c", "-o", "${_TARGET}", "${CXXDEPGEN}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${CXXFLAGS}", "${CCFLAGS}", "${_SOURCES}"] | | CXXCMD | Array | C++ compiler command line | ["${CXX}", "-c", "-o", "${_TARGET}", "${CXXDEPGEN}", "${INCPREFIX}${CPPPATH}", "${CPPFLAGS}", "${CXXFLAGS}", "${CCFLAGS}", "${_SOURCES}"] |
| CXXDEPGEN | Array | C++ compiler dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}"] | | CXXDEPGEN | Array | C++ compiler dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}", "-MT", "TARGET"] |
| CXXFLAGS | Array | C++ compiler flags | [] | | CXXFLAGS | Array | C++ compiler flags | [] |
| CXXSUFFIX | Array | C++ source file suffixes | [".cc", ".cpp", ".cxx", ".C"] | | CXXSUFFIX | Array | C++ source file suffixes | [".cc", ".cpp", ".cxx", ".C"] |
| D_IMPORT_PATH | Array | D compiler import path | [] | | D_IMPORT_PATH | Array | D compiler import path | [] |
| DC | String | D compiler executable | "gdc" | | DC | String | D compiler executable | "gdc" |
| DCCMD | Array | D compiler command line | ["${DC}", "-c", "-o", "${_TARGET}", "${INCPREFIX}${D_IMPORT_PATH}", "${DFLAGS}", "${_SOURCES}"] | | DCCMD | Array | D compiler command line | ["${DC}", "-c", "-o", "${_TARGET}", "${DDEPGEN}", "${INCPREFIX}${D_IMPORT_PATH}", "${DFLAGS}", "${_SOURCES}"] |
| DDEPGEN | Array | D compiler dependency generation flags | ["-MMD", "-MF", "${_DEPFILE}", "-MT", "TARGET"] |
| DEPFILESUFFIX | String | Dependency file suffix for Makefile-style dependency rules emitted by the compiler (used internally for temporary dependency files used to determine a source file's dependencies) | ".mf" | | DEPFILESUFFIX | String | Dependency file suffix for Makefile-style dependency rules emitted by the compiler (used internally for temporary dependency files used to determine a source file's dependencies) | ".mf" |
| DFLAGS | Array | D compiler flags | [] | | DFLAGS | Array | D compiler flags | [] |
| DISASM_CMD | Array | Disassemble command line | ["${OBJDUMP}", "${DISASM_FLAGS}", "${_SOURCES}"] | | DISASM_CMD | Array | Disassemble command line | ["${OBJDUMP}", "${DISASM_FLAGS}", "${_SOURCES}"] |
@@ -548,9 +558,19 @@ end
You can pass multiple dependency files to `Environment#depends`: You can pass multiple dependency files to `Environment#depends`:
```ruby ```ruby
env.depends("my_app", "config/link.ld", "README.txt", *Dir.glob("assets/**/*")) env.depends("my_app", "config/link.ld", "README.txt", *Rscons.glob("assets/**/*"))
``` ```
### Command-Line Variables
Variables can be specified on the rscons command line. For example:
```
rscons VAR=val
```
These variables are accessible in a global VarSet called `Rscons.vars`.
### Construction Variable Naming ### Construction Variable Naming
* uppercase strings - the default construction variables that Rscons uses * uppercase strings - the default construction variables that Rscons uses
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env ruby
require "rscons/cli" require "rscons/cli"
Rscons::Cli.run(ARGV) Rscons::Cli.run(ARGV)
+2 -2
View File
@@ -1,5 +1,5 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**'))
env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
env.Program('build_dir.exe', Dir['src/**/*.c']) env.Program('build_dir.exe', Rscons.glob('src/**/*.c'))
end end
@@ -6,7 +6,7 @@ end
Rscons::Environment.new(echo: :command) do |env| Rscons::Environment.new(echo: :command) do |env|
env.add_builder(MyObject.new) env.add_builder(MyObject.new)
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**'))
env.add_build_hook do |build_op| env.add_build_hook do |build_op|
if build_op[:builder].name == "MyObject" && build_op[:sources].first =~ %r{one\.c} if build_op[:builder].name == "MyObject" && build_op[:sources].first =~ %r{one\.c}
build_op[:vars]["CFLAGS"] << "-O1" build_op[:vars]["CFLAGS"] << "-O1"
+2 -2
View File
@@ -1,6 +1,6 @@
env = Rscons::Environment.new do |env| env = Rscons::Environment.new do |env|
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**/*/'))
env.build_dir("src", "build") env.build_dir("src", "build")
env.build_root = "build_root" env.build_root = "build_root"
env.Program('build_dir.exe', Dir['src/**/*.c']) env.Program('build_dir.exe', Rscons.glob('src/**/*.c'))
end end
+2 -2
View File
@@ -1,5 +1,5 @@
Rscons::Environment.new(echo: :command) do |env| Rscons::Environment.new(echo: :command) do |env|
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**/*/'))
env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/') env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
env.add_build_hook do |build_op| env.add_build_hook do |build_op|
if build_op[:target] =~ %r{build_one/.*\.o} if build_op[:target] =~ %r{build_one/.*\.o}
@@ -8,5 +8,5 @@ Rscons::Environment.new(echo: :command) do |env|
build_op[:vars]["CFLAGS"] << "-O2" build_op[:vars]["CFLAGS"] << "-O2"
end end
end end
env.Program('build_hook.exe', Dir['src/**/*.c'].sort) env.Program('build_hook.exe', Rscons.glob('src/**/*.c'))
end end
+2 -2
View File
@@ -1,8 +1,8 @@
Rscons::Environment.new(echo: :command) do |env| Rscons::Environment.new(echo: :command) do |env|
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**').sort)
env.build_root = "build_root" env.build_root = "build_root"
FileUtils.mkdir_p(env.build_root) FileUtils.mkdir_p(env.build_root)
FileUtils.mv("src/one/one.c", "build_root") FileUtils.mv("src/one/one.c", "build_root")
env.Object("^/one.o", "^/one.c") env.Object("^/one.o", "^/one.c")
env.Program("build_dir.exe", Dir['src/**/*.c'] + ["^/one.o"]) env.Program("build_dir.exe", Rscons.glob('src/**/*.c') + ["^/one.o"])
end end
+2 -2
View File
@@ -1,6 +1,6 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CSUFFIX"] = %w[.yargh .c] env["CSUFFIX"] = %w[.yargh .c]
env["CFLAGS"] += %w[-x c] env["CFLAGS"] += %w[-x c]
env["CPPPATH"] += Dir["src/**/"] env["CPPPATH"] += Rscons.glob("src/**")
env.Program("build_dir.exe", Dir["src/**/*.{c,yargh}"]) env.Program("build_dir.exe", Rscons.glob("src/**/*.{c,yargh}"))
end end
+2 -2
View File
@@ -1,6 +1,6 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.append('CPPPATH' => Dir['src/**/*/'].sort) env.append('CPPPATH' => Rscons.glob('src/**'))
env.build_dir("src2", "build") env.build_dir("src2", "build")
env.build_root = "build_root" env.build_root = "build_root"
env.Program('build_dir.exe', Dir['src/**/*.c']) env.Program('build_dir.exe', Rscons.glob('src/**/*.c'))
end end
+2 -2
View File
@@ -1,6 +1,6 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env.append("CPPPATH" => Dir["src/**/*/"].sort) env.append("CPPPATH" => Rscons.glob("src/**"))
env.build_dir("src/one/", "build_one/") env.build_dir("src/one/", "build_one/")
env.build_dir("src/two", "build_two") env.build_dir("src/two", "build_two")
env.Program("build_dir.exe", Dir["src/**/*.c"]) env.Program("build_dir.exe", Rscons.glob("src/**/*.c"))
end end
+1 -1
View File
@@ -1,3 +1,3 @@
Rscons::Environment.new(echo: :command) do |env| Rscons::Environment.new(echo: :command) do |env|
env.Program("hello-d.exe", Dir["*.d"]) env.Program("hello-d.exe", Rscons.glob("*.d"))
end end
+2 -1
View File
@@ -1,6 +1,7 @@
import std.stdio; import std.stdio;
import mod;
void main() void main()
{ {
writeln("Hello from D!"); writeln("Hello from D, value is ", Klass.VAL, "!");
} }
+4
View File
@@ -0,0 +1,4 @@
class Klass
{
enum VAL = 42;
};
+1 -1
View File
@@ -1,4 +1,4 @@
Rscons::Environment.new(echo: :command) do |env| Rscons::Environment.new(echo: :command) do |env|
env["ARCMD"] = %w[ar rcf ${_TARGET} ${_SOURCES}] env["ARCMD"] = %w[ar rcf ${_TARGET} ${_SOURCES}]
env.Library("lib.a", Dir["*.c"].sort) env.Library("lib.a", Rscons.glob("*.c"))
end end
+3 -3
View File
@@ -1,11 +1,11 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CPPPATH"] << "src/lib" env["CPPPATH"] << "src/lib"
libmine = env.SharedLibrary("mine", Dir["src/lib/*.c"]) libmine = env.SharedLibrary("mine", Rscons.glob("src/lib/*.c"))
env.Program("test-shared.exe", env.Program("test-shared.exe",
Dir["src/*.c"], Rscons.glob("src/*.c"),
"LIBPATH" => %w[.], "LIBPATH" => %w[.],
"LIBS" => %w[mine]) "LIBS" => %w[mine])
env.build_after("test-shared.exe", libmine.to_s) env.build_after("test-shared.exe", libmine.to_s)
env.Program("test-static.exe", env.Program("test-static.exe",
Dir["src/**/*.c"]) Rscons.glob("src/**/*.c"))
end end
@@ -1,11 +1,11 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CPPPATH"] << "src/lib" env["CPPPATH"] << "src/lib"
libmine = env.SharedLibrary("mine", Dir["src/lib/*.cc"]) libmine = env.SharedLibrary("mine", Rscons.glob("src/lib/*.cc"))
env.Program("test-shared.exe", env.Program("test-shared.exe",
Dir["src/*.cc"], Rscons.glob("src/*.cc"),
"LIBPATH" => %w[.], "LIBPATH" => %w[.],
"LIBS" => %w[mine]) "LIBS" => %w[mine])
env.build_after("test-shared.exe", libmine.to_s) env.build_after("test-shared.exe", libmine.to_s)
env.Program("test-static.exe", env.Program("test-static.exe",
Dir["src/**/*.cc"]) Rscons.glob("src/**/*.cc"))
end end
@@ -1,8 +1,8 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CPPPATH"] << "src/lib" env["CPPPATH"] << "src/lib"
libmine = env.SharedLibrary("mine", Dir["src/lib/*.d"]) libmine = env.SharedLibrary("mine", Rscons.glob("src/lib/*.d"))
env.Program("test-shared.exe", env.Program("test-shared.exe",
Dir["src/*.c"], Rscons.glob("src/*.c"),
"LIBPATH" => %w[.], "LIBPATH" => %w[.],
"LIBS" => %w[mine]) "LIBS" => %w[mine])
env.build_after("test-shared.exe", libmine.to_s) env.build_after("test-shared.exe", libmine.to_s)
@@ -1,12 +1,12 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["CPPPATH"] << "src/lib" env["CPPPATH"] << "src/lib"
env["SHLD"] = "gcc" env["SHLD"] = "gcc"
libmine = env.SharedLibrary("mine", Dir["src/lib/*.c"]) libmine = env.SharedLibrary("mine", Rscons.glob("src/lib/*.c"))
env.Program("test-shared.exe", env.Program("test-shared.exe",
Dir["src/*.c"], Rscons.glob("src/*.c"),
"LIBPATH" => %w[.], "LIBPATH" => %w[.],
"LIBS" => %w[mine]) "LIBS" => %w[mine])
env.build_after("test-shared.exe", libmine.to_s) env.build_after("test-shared.exe", libmine.to_s)
env.Program("test-static.exe", env.Program("test-static.exe",
Dir["src/**/*.c"]) Rscons.glob("src/**/*.c"))
end end
+34
View File
@@ -0,0 +1,34 @@
class DebugBuilder < Rscons::Builder
def run(options)
target, sources, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
command = %W[gcc -c -o #{target} #{sources.first}]
if Rscons.vars["command_change"]
command += %w[-Wall]
end
if Rscons.vars["new_dep"]
sources += ["extra"]
end
if Rscons.vars["strict_deps1"]
sources += ["extra"]
strict_deps = true
end
if Rscons.vars["strict_deps2"]
sources = ["extra"] + sources
strict_deps = true
end
unless cache.up_to_date?(target, command, sources, env, debug: true, strict_deps: strict_deps)
desc = "#{self.class.name} #{target}"
return false unless env.execute(desc, command)
cache.register_build(target, command, sources, env)
end
target
end
end
Rscons::Environment.new do |env|
env.add_builder(DebugBuilder.new)
if Rscons.vars["new_user_dep"]
env.depends("foo.o", "new_dep")
end
env.DebugBuilder("foo.o", "simple.c")
end
+20
View File
@@ -0,0 +1,20 @@
class TestBuilder < Rscons::Builder
def run(options)
target, sources, cache, env = options.values_at(:target, :sources, :cache, :env)
command = Rscons::VarSet.new("A" => "a", "B" => "b")
unless cache.up_to_date?(target, command, sources, env)
File.open(target, "w") do |fh|
fh.puts("hi")
end
msg = "#{self.class.name} #{target}"
env.print_builder_run_message(msg, msg)
cache.register_build(target, command, sources, env)
end
target
end
end
Rscons::Environment.new do |env|
env.add_builder(TestBuilder.new)
env.TestBuilder("foo")
end
+1 -1
View File
@@ -1,4 +1,4 @@
Rscons::Environment.new do |env| Rscons::Environment.new do |env|
env["sources"] = Dir["*.c"].sort env["sources"] = Rscons.glob("*.c")
env.Program("simple.exe", "${sources}") env.Program("simple.exe", "${sources}")
end end
+35
View File
@@ -55,6 +55,11 @@ module Rscons
# Whether to output ANSI color escape sequences. # Whether to output ANSI color escape sequences.
attr_accessor :do_ansi_color attr_accessor :do_ansi_color
# @since 1.16.0
# @return [VarSet]
# Access any variables set on the rscons command-line.
attr_reader :vars
# Remove all generated files. # Remove all generated files.
# #
# @return [void] # @return [void]
@@ -165,6 +170,35 @@ module Rscons
@command_executer = val @command_executer = val
end end
# Return a list of paths matching the specified pattern(s).
#
# @since 1.16.0
#
# A pattern can contain a "/**" component to recurse through directories.
# If the pattern ends with "/**" then only the recursive list of
# directories will be returned.
#
# Examples:
# - "src/**": return all directories under "src", recursively (including
# "src" itself).
# - "src/**/*": return all files and directories recursively under the src
# directory.
# - "src/**/*.c": return all .c files recursively under the src directory.
# - "dir/*/": return all directories in dir, but no files.
#
# @return [Array<String>] Paths matching the specified pattern(s).
def glob(*patterns)
require "pathname"
patterns.reduce([]) do |result, pattern|
if pattern.end_with?("/**")
pattern += "/"
end
result += Dir.glob(pattern).map do |path|
Pathname.new(path.gsub("\\", "/")).cleanpath.to_s
end
end.sort
end
private private
# Determine the number of threads to use by default. # Determine the number of threads to use by default.
@@ -203,6 +237,7 @@ module Rscons
end end
@n_threads = determine_n_threads @n_threads = determine_n_threads
@vars = VarSet.new
end end
+6 -5
View File
@@ -30,7 +30,7 @@ module Rscons
'ASSUFFIX' => ['.S'], 'ASSUFFIX' => ['.S'],
'ASPPPATH' => '${CPPPATH}', 'ASPPPATH' => '${CPPPATH}',
'ASPPFLAGS' => '${CPPFLAGS}', 'ASPPFLAGS' => '${CPPFLAGS}',
'ASDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'], 'ASDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}', '-MT', 'TARGET'],
'ASCMD' => ['${AS}', '-c', '-o', '${_TARGET}', '${ASDEPGEN}', '${INCPREFIX}${ASPPPATH}', '${ASPPFLAGS}', '${ASFLAGS}', '${_SOURCES}'], 'ASCMD' => ['${AS}', '-c', '-o', '${_TARGET}', '${ASDEPGEN}', '${INCPREFIX}${ASPPPATH}', '${ASPPFLAGS}', '${ASFLAGS}', '${_SOURCES}'],
'CPPFLAGS' => ['${CPPDEFPREFIX}${CPPDEFINES}'], 'CPPFLAGS' => ['${CPPDEFPREFIX}${CPPDEFINES}'],
@@ -42,20 +42,21 @@ module Rscons
'CC' => 'gcc', 'CC' => 'gcc',
'CFLAGS' => [], 'CFLAGS' => [],
'CSUFFIX' => ['.c'], 'CSUFFIX' => ['.c'],
'CCDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'], 'CCDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}', '-MT', 'TARGET'],
'CCCMD' => ['${CC}', '-c', '-o', '${_TARGET}', '${CCDEPGEN}', '${INCPREFIX}${CPPPATH}', '${CPPFLAGS}', '${CFLAGS}', '${CCFLAGS}', '${_SOURCES}'], 'CCCMD' => ['${CC}', '-c', '-o', '${_TARGET}', '${CCDEPGEN}', '${INCPREFIX}${CPPPATH}', '${CPPFLAGS}', '${CFLAGS}', '${CCFLAGS}', '${_SOURCES}'],
'CXX' => 'g++', 'CXX' => 'g++',
'CXXFLAGS' => [], 'CXXFLAGS' => [],
'CXXSUFFIX' => ['.cc', '.cpp', '.cxx', '.C'], 'CXXSUFFIX' => ['.cc', '.cpp', '.cxx', '.C'],
'CXXDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'], 'CXXDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}', '-MT', 'TARGET'],
'CXXCMD' =>['${CXX}', '-c', '-o', '${_TARGET}', '${CXXDEPGEN}', '${INCPREFIX}${CPPPATH}', '${CPPFLAGS}', '${CXXFLAGS}', '${CCFLAGS}', '${_SOURCES}'], 'CXXCMD' =>['${CXX}', '-c', '-o', '${_TARGET}', '${CXXDEPGEN}', '${INCPREFIX}${CPPPATH}', '${CPPFLAGS}', '${CXXFLAGS}', '${CCFLAGS}', '${_SOURCES}'],
'DC' => 'gdc', 'DC' => 'gdc',
'DFLAGS' => [], 'DFLAGS' => [],
'DSUFFIX' => ['.d'], 'DSUFFIX' => ['.d'],
'DDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}', '-MT', 'TARGET'],
'D_IMPORT_PATH' => [], 'D_IMPORT_PATH' => [],
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'], 'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${DDEPGEN}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
} }
end end
@@ -114,7 +115,7 @@ module Rscons
if options[:command_status] if options[:command_status]
target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
if File.exists?(vars['_DEPFILE']) if File.exists?(vars['_DEPFILE'])
deps += Environment.parse_makefile_deps(vars['_DEPFILE'], target) deps += Environment.parse_makefile_deps(vars['_DEPFILE'], 'TARGET')
FileUtils.rm_f(vars['_DEPFILE']) FileUtils.rm_f(vars['_DEPFILE'])
end end
cache.register_build(target, options[:tc].command, deps.uniq, env) cache.register_build(target, options[:tc].command, deps.uniq, env)
+1 -1
View File
@@ -100,7 +100,7 @@ module Rscons
if options[:command_status] if options[:command_status]
target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars) target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
if File.exists?(vars['_DEPFILE']) if File.exists?(vars['_DEPFILE'])
deps += Environment.parse_makefile_deps(vars['_DEPFILE'], target) deps += Environment.parse_makefile_deps(vars['_DEPFILE'], 'TARGET')
FileUtils.rm_f(vars['_DEPFILE']) FileUtils.rm_f(vars['_DEPFILE'])
end end
cache.register_build(target, options[:tc].command, deps.uniq, env) cache.register_build(target, options[:tc].command, deps.uniq, env)
+52 -8
View File
@@ -111,6 +111,10 @@ module Rscons
# @param deps [Array<String>] List of the target's dependency files. # @param deps [Array<String>] List of the target's dependency files.
# @param env [Environment] The Rscons::Environment. # @param env [Environment] The Rscons::Environment.
# @param options [Hash] Optional options. # @param options [Hash] Optional options.
# @option options [Boolean] :debug
# If turned on, this causes the Cache to print messages explaining why
# a build target is out of date. This could aid a builder author in
# debugging the operation of their builder.
# @option options [Boolean] :strict_deps # @option options [Boolean] :strict_deps
# Only consider a target up to date if its list of dependencies is # Only consider a target up to date if its list of dependencies is
# exactly equal (including order) to the cached list of dependencies # exactly equal (including order) to the cached list of dependencies
@@ -133,39 +137,79 @@ module Rscons
unless Rscons.phony_target?(target) unless Rscons.phony_target?(target)
# target file must exist on disk # target file must exist on disk
return false unless File.exists?(target) unless File.exists?(target)
if options[:debug]
puts "Target #{target} needs rebuilding because it does not exist on disk"
end
return false
end
end end
# target must be registered in the cache # target must be registered in the cache
return false unless @cache["targets"].has_key?(cache_key) unless @cache["targets"].has_key?(cache_key)
if options[:debug]
puts "Target #{target} needs rebuilding because there is no cached build information for it"
end
return false
end
unless Rscons.phony_target?(target) unless Rscons.phony_target?(target)
# target must have the same checksum as when it was built last # target must have the same checksum as when it was built last
return false unless @cache["targets"][cache_key]["checksum"] == lookup_checksum(target) unless @cache["targets"][cache_key]["checksum"] == lookup_checksum(target)
if options[:debug]
puts "Target #{target} needs rebuilding because it has been changed on disk since being built last"
end
return false
end
end end
# command used to build target must be identical # command used to build target must be identical
return false unless @cache["targets"][cache_key]["command"] == Digest::MD5.hexdigest(command.inspect) unless @cache["targets"][cache_key]["command"] == Digest::MD5.hexdigest(command.inspect)
if options[:debug]
puts "Target #{target} needs rebuilding because the command used to build it has changed"
end
return false
end
cached_deps = @cache["targets"][cache_key]["deps"] || [] cached_deps = @cache["targets"][cache_key]["deps"] || []
cached_deps_fnames = cached_deps.map { |dc| dc["fname"] } cached_deps_fnames = cached_deps.map { |dc| dc["fname"] }
if options[:strict_deps] if options[:strict_deps]
# depedencies passed in must exactly equal those in the cache # depedencies passed in must exactly equal those in the cache
return false unless deps == cached_deps_fnames unless deps == cached_deps_fnames
if options[:debug]
puts "Target #{target} needs rebuilding because the :strict_deps option is given and the set of dependencies does not match the previous set of dependencies"
end
return false
end
else else
# all dependencies passed in must exist in cache (but cache may have more) # all dependencies passed in must exist in cache (but cache may have more)
return false unless (Set.new(deps) - Set.new(cached_deps_fnames)).empty? unless (Set.new(deps) - Set.new(cached_deps_fnames)).empty?
if options[:debug]
puts "Target #{target} needs rebuilding because there are new dependencies"
end
return false
end
end end
# set of user dependencies must match # set of user dependencies must match
user_deps = env.get_user_deps(target) || [] user_deps = env.get_user_deps(target) || []
cached_user_deps = @cache["targets"][cache_key]["user_deps"] || [] cached_user_deps = @cache["targets"][cache_key]["user_deps"] || []
cached_user_deps_fnames = cached_user_deps.map { |dc| dc["fname"] } cached_user_deps_fnames = cached_user_deps.map { |dc| dc["fname"] }
return false unless user_deps == cached_user_deps_fnames unless user_deps == cached_user_deps_fnames
if options[:debug]
puts "Target #{target} needs rebuilding because the set of user-specified dependency files has changed"
end
return false
end
# all cached dependencies must have their checksums match # all cached dependencies must have their checksums match
(cached_deps + cached_user_deps).each do |dep_cache| (cached_deps + cached_user_deps).each do |dep_cache|
return false unless dep_cache["checksum"] == lookup_checksum(dep_cache["fname"]) unless dep_cache["checksum"] == lookup_checksum(dep_cache["fname"])
if options[:debug]
puts "Target #{target} needs rebuilding because dependency file #{dep_cache["fname"]} has changed"
end
return false
end
end end
end end
+6
View File
@@ -60,6 +60,12 @@ module Rscons
end.parse!(argv) end.parse!(argv)
argv.each do |arg|
if arg =~ /^([^=]+)=(.*)$/
Rscons.vars[$1] = $2
end
end
if rsconsfile if rsconsfile
unless File.exists?(rsconsfile) unless File.exists?(rsconsfile)
$stderr.puts "Cannot read #{rsconsfile}" $stderr.puts "Cannot read #{rsconsfile}"
+7
View File
@@ -143,6 +143,13 @@ module Rscons
end end
end end
# Return a String representing the VarSet.
#
# @return [String] Representation of the VarSet.
def inspect
to_h.inspect
end
# Return an array containing the values associated with the given keys. # Return an array containing the values associated with the given keys.
# #
# @param keys [Array<String, Symbol>] # @param keys [Array<String, Symbol>]
+1 -1
View File
@@ -1,4 +1,4 @@
module Rscons module Rscons
# gem version # gem version
VERSION = "1.15.0" VERSION = "1.16.0"
end end
-1
View File
@@ -25,5 +25,4 @@ Gem::Specification.new do |gem|
gem.add_development_dependency "simplecov" gem.add_development_dependency "simplecov"
gem.add_development_dependency "yard" gem.add_development_dependency "yard"
gem.add_development_dependency "rdoc" gem.add_development_dependency "rdoc"
gem.add_development_dependency "redcarpet"
end end
+118 -22
View File
@@ -91,6 +91,7 @@ end
$LOAD_PATH.unshift(#{@owd.inspect} + "/lib") $LOAD_PATH.unshift(#{@owd.inspect} + "/lib")
# force color off # force color off
ENV["TERM"] = nil ENV["TERM"] = nil
#{options[:ruby_setup_code]}
EOF EOF
end end
stdout, stderr, status = nil, nil, nil stdout, stderr, status = nil, nil, nil
@@ -125,7 +126,7 @@ 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 build/simple.o -MMD -MF build/simple.mf simple.c', 'gcc -c -o build/simple.o -MMD -MF build/simple.mf -MT TARGET simple.c',
"gcc -o simple.exe build/simple.o", "gcc -o simple.exe build/simple.o",
] ]
end end
@@ -194,7 +195,7 @@ 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 build/simple.o -MMD -MF build/simple.mf simple.c', 'gcc -c -o build/simple.o -MMD -MF build/simple.mf -MT TARGET simple.c',
"gcc -o simple.exe build/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")
@@ -249,8 +250,8 @@ EOF
result = run_test(rsconsfile: "carat.rb") result = run_test(rsconsfile: "carat.rb")
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[
%q{gcc -c -o build_root/one.o -MMD -MF build_root/one.mf -Isrc/one/ -Isrc/two/ build_root/one.c}, %q{gcc -c -o build_root/one.o -MMD -MF build_root/one.mf -MT TARGET -Isrc -Isrc/one -Isrc/two build_root/one.c},
%q{gcc -c -o build_root/src/two/two.o -MMD -MF build_root/src/two/two.mf -Isrc/one/ -Isrc/two/ src/two/two.c}, %q{gcc -c -o build_root/src/two/two.o -MMD -MF build_root/src/two/two.mf -MT TARGET -Isrc -Isrc/one -Isrc/two src/two/two.c},
%Q{gcc -o build_dir.exe build_root/src/two/two.o build_root/one.o}, %Q{gcc -o build_dir.exe build_root/src/two/two.o build_root/one.o},
] ]
end end
@@ -329,9 +330,9 @@ 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[
%q{gcc -c -o debug/program.o -MMD -MF debug/program.mf '-DSTRING="Debug Version"' -O2 src/program.c}, %q{gcc -c -o debug/program.o -MMD -MF debug/program.mf -MT TARGET '-DSTRING="Debug Version"' -O2 src/program.c},
%Q{gcc -o program-debug.exe debug/program.o}, %Q{gcc -o program-debug.exe debug/program.o},
%q{gcc -c -o release/program.o -MMD -MF release/program.mf '-DSTRING="Release Version"' -O2 src/program.c}, %q{gcc -c -o release/program.o -MMD -MF release/program.mf -MT TARGET '-DSTRING="Release Version"' -O2 src/program.c},
%Q{gcc -o program-release.exe release/program.o}, %Q{gcc -o program-release.exe release/program.o},
] ]
end end
@@ -341,7 +342,7 @@ EOF
result = run_test(rsconsfile: "clone_all.rb") result = run_test(rsconsfile: "clone_all.rb")
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ expect(lines(result.stdout)).to eq [
%q{gcc -c -o build/program.o -MMD -MF build/program.mf -DSTRING="Hello" -O2 src/program.c}, %q{gcc -c -o build/program.o -MMD -MF build/program.mf -MT TARGET -DSTRING="Hello" -O2 src/program.c},
%q{post build/program.o}, %q{post build/program.o},
%Q{gcc -o program.exe build/program.o}, %Q{gcc -o program.exe build/program.o},
%q{post program.exe}, %q{post program.exe},
@@ -364,8 +365,8 @@ 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 -DONE one.c', 'gcc -c -o one.o -MMD -MF one.mf -MT TARGET -DONE one.c',
'gcc -c -o build/two.o -MMD -MF build/two.mf two.c', 'gcc -c -o build/two.o -MMD -MF build/two.mf -MT TARGET two.c',
"gcc -o two_sources.exe one.o build/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
@@ -377,10 +378,10 @@ 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 build/one.o -MMD -MF build/one.mf -Dmake_lib one.c', 'gcc -c -o build/one.o -MMD -MF build/one.mf -MT TARGET -Dmake_lib one.c',
'gcc -c -o build/two.o -MMD -MF build/two.mf -Dmake_lib two.c', 'gcc -c -o build/two.o -MMD -MF build/two.mf -MT TARGET -Dmake_lib two.c',
'ar rcs lib.a build/one.o build/two.o', 'ar rcs lib.a build/one.o build/two.o',
'gcc -c -o build/three.o -MMD -MF build/three.mf three.c', 'gcc -c -o build/three.o -MMD -MF build/three.mf -MT TARGET three.c',
"gcc -o library.exe lib.a build/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
@@ -392,8 +393,8 @@ EOF
result = run_test(rsconsfile: "build_hooks.rb") result = run_test(rsconsfile: "build_hooks.rb")
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 build_one/one.o -MMD -MF build_one/one.mf -Isrc/one/ -Isrc/two/ -O1 src/one/one.c', 'gcc -c -o build_one/one.o -MMD -MF build_one/one.mf -MT TARGET -Isrc/one -Isrc/two -O1 src/one/one.c',
'gcc -c -o build_two/two.o -MMD -MF build_two/two.mf -Isrc/one/ -Isrc/two/ -O2 src/two/two.c', 'gcc -c -o build_two/two.o -MMD -MF build_two/two.mf -MT TARGET -Isrc/one -Isrc/two -O2 src/two/two.c',
'gcc -o build_hook.exe build_one/one.o build_two/two.o', 'gcc -o build_hook.exe build_one/one.o build_two/two.o',
] ]
expect(`./build_hook.exe`).to eq "Hello from two()\n" expect(`./build_hook.exe`).to eq "Hello from two()\n"
@@ -429,11 +430,31 @@ EOF
test_dir("d") test_dir("d")
result = run_test result = run_test
expect(result.stderr).to eq "" expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [ slines = lines(result.stdout)
"gdc -c -o build/main.o main.d", expect(slines).to include("gdc -c -o build/main.o -MMD -MF build/main.mf -MT TARGET main.d")
"gdc -o hello-d.exe build/main.o", expect(slines).to include("gdc -c -o build/mod.o -MMD -MF build/mod.mf -MT TARGET mod.d")
] expect(slines.last).to eq("gdc -o hello-d.exe build/main.o build/mod.o")
expect(`./hello-d.exe`.rstrip).to eq "Hello from D!" expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 42!"
end
it "does dependency generation for D sources" do
test_dir("d")
result = run_test
expect(result.stderr).to eq ""
slines = lines(result.stdout)
expect(slines).to include("gdc -c -o build/main.o -MMD -MF build/main.mf -MT TARGET main.d")
expect(slines).to include("gdc -c -o build/mod.o -MMD -MF build/mod.mf -MT TARGET mod.d")
expect(slines.last).to eq("gdc -o hello-d.exe build/main.o build/mod.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_test
expect(result.stderr).to eq ""
slines = lines(result.stdout)
expect(slines).to include("gdc -c -o build/main.o -MMD -MF build/main.mf -MT TARGET main.d")
expect(slines).to include("gdc -c -o build/mod.o -MMD -MF build/mod.mf -MT TARGET mod.d")
expect(slines.last).to eq("gdc -o hello-d.exe build/main.o build/mod.o")
expect(`./hello-d.exe`.rstrip).to eq "Hello from D, value is 33!"
end end
it "creates shared libraries using D" do it "creates shared libraries using D" do
@@ -873,8 +894,8 @@ EOF
result = run_test(rsconsfile: "backward_compatible_build_hooks.rb") result = run_test(rsconsfile: "backward_compatible_build_hooks.rb")
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 -Isrc/one/ -Isrc/two/ -O1 src/two/two.c', 'gcc -c -o one.o -MMD -MF one.mf -MT TARGET -Isrc -Isrc/one -Isrc/two -O1 src/two/two.c',
'gcc -c -o two.o -MMD -MF two.mf -Isrc/one/ -Isrc/two/ -O2 src/two/two.c' 'gcc -c -o two.o -MMD -MF two.mf -MT TARGET -Isrc -Isrc/one -Isrc/two -O2 src/two/two.c'
] ]
expect(File.exists?('one.o')).to be_truthy expect(File.exists?('one.o')).to be_truthy
expect(File.exists?('two.o')).to be_truthy expect(File.exists?('two.o')).to be_truthy
@@ -1241,6 +1262,81 @@ EOF
"LD simple.exe", "LD simple.exe",
] ]
end end
it "allows a VarSet to be passed in as the command parameter" do
test_dir("simple")
result = run_test(rsconsfile: "cache_varset.rb")
expect(result.stderr).to eq ""
expect(lines(result.stdout)).to eq [
"TestBuilder foo",
]
result = run_test(rsconsfile: "cache_varset.rb")
expect(result.stderr).to eq ""
expect(result.stdout).to eq ""
end
context "debugging" do
it "prints a message when the target does not exist" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
expect(result.stdout).to match /Target foo\.o needs rebuilding because it does not exist on disk/
end
it "prints a message when there is no cached build information for the target" do
test_dir("simple")
FileUtils.touch("foo.o")
result = run_test(rsconsfile: "cache_debugging.rb")
expect(result.stdout).to match /Target foo\.o needs rebuilding because there is no cached build information for it/
end
it "prints a message when the target file has changed on disk" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
File.open("foo.o", "wb") {|fh| fh.puts "hi"}
result = run_test(rsconsfile: "cache_debugging.rb")
expect(result.stdout).to match /Target foo\.o needs rebuilding because it has been changed on disk since being built last/
end
it "prints a message when the command has changed" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
result = run_test(rsconsfile: "cache_debugging.rb", rscons_args: %w[command_change=yes])
expect(result.stdout).to match /Target foo\.o needs rebuilding because the command used to build it has changed/
end
it "prints a message when strict_deps is in use and the set of dependencies does not match" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb", rscons_args: %w[strict_deps1=yes])
result = run_test(rsconsfile: "cache_debugging.rb", rscons_args: %w[strict_deps2=yes])
expect(result.stdout).to match /Target foo\.o needs rebuilding because the :strict_deps option is given and the set of dependencies does not match the previous set of dependencies/
end
it "prints a message when there is a new dependency" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
result = run_test(rsconsfile: "cache_debugging.rb", rscons_args: %w[new_dep=yes])
expect(result.stdout).to match /Target foo\.o needs rebuilding because there are new dependencies/
end
it "prints a message when there is a new user-specified dependency" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
result = run_test(rsconsfile: "cache_debugging.rb", rscons_args: %w[new_user_dep=yes])
expect(result.stdout).to match /Target foo\.o needs rebuilding because the set of user-specified dependency files has changed/
end
it "prints a message when a dependency file has changed" do
test_dir("simple")
result = run_test(rsconsfile: "cache_debugging.rb")
f = File.read("simple.c", mode: "rb")
f += "\n"
File.open("simple.c", "wb") do |fh|
fh.write(f)
end
result = run_test(rsconsfile: "cache_debugging.rb")
expect(result.stdout).to match /Target foo\.o needs rebuilding because dependency file simple\.c has changed/
end
end
end end
context "Object builder" do context "Object builder" do
@@ -1258,7 +1354,7 @@ EOF
result = run_test(rsconsfile: "override_depfilesuffix.rb") result = run_test(rsconsfile: "override_depfilesuffix.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.deppy simple.c", "gcc -c -o simple.o -MMD -MF simple.deppy -MT TARGET simple.c",
] ]
end end