Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3af6b6be1b | ||
|
|
0442b876a5 | ||
|
|
bab4641b6e | ||
|
|
4698fc41b9 | ||
|
|
952f423860 | ||
|
|
d2da5f7b0d | ||
|
|
ab14dc16ed | ||
|
|
aa795eea85 | ||
|
|
7dffef6bd0 | ||
|
|
dce2114733 | ||
|
|
0bbdda2d41 | ||
|
|
3b8910075a | ||
|
|
34beda844e | ||
|
|
7a04bec2ff | ||
|
|
7698fbf618 | ||
|
|
4eedea2563 | ||
|
|
f678803a5d | ||
|
|
9c49a09f69 | ||
|
|
859f87ddee | ||
|
|
73bc71a656 | ||
|
|
29a8684f90 | ||
|
|
02aff35222 | ||
|
|
897d31ebe0 | ||
|
|
76610a07a9 | ||
|
|
cb3cc9a0de | ||
|
|
0ea842fffe | ||
|
|
d28722a4bb | ||
|
|
8142d0bbc8 | ||
|
|
a8023ae03c | ||
|
|
99ba015630 |
No files matched your search
+25
-22
@@ -1,7 +1,7 @@
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
rscons (1.8.0)
|
rscons (1.9.2)
|
||||||
json (~> 1.0)
|
json (~> 1.0)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
@@ -9,30 +9,30 @@ GEM
|
|||||||
specs:
|
specs:
|
||||||
diff-lcs (1.2.5)
|
diff-lcs (1.2.5)
|
||||||
docile (1.1.5)
|
docile (1.1.5)
|
||||||
json (1.8.1)
|
json (1.8.3)
|
||||||
multi_json (1.10.1)
|
rake (10.4.2)
|
||||||
rake (10.3.2)
|
rdoc (4.2.0)
|
||||||
rdoc (4.1.2)
|
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
redcarpet (3.1.2)
|
redcarpet (3.3.3)
|
||||||
rspec (3.0.0)
|
rspec (3.4.0)
|
||||||
rspec-core (~> 3.0.0)
|
rspec-core (~> 3.4.0)
|
||||||
rspec-expectations (~> 3.0.0)
|
rspec-expectations (~> 3.4.0)
|
||||||
rspec-mocks (~> 3.0.0)
|
rspec-mocks (~> 3.4.0)
|
||||||
rspec-core (3.0.1)
|
rspec-core (3.4.1)
|
||||||
rspec-support (~> 3.0.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-expectations (3.0.1)
|
rspec-expectations (3.4.0)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.0.0)
|
rspec-support (~> 3.4.0)
|
||||||
rspec-mocks (3.0.1)
|
rspec-mocks (3.4.0)
|
||||||
rspec-support (~> 3.0.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (3.0.0)
|
rspec-support (~> 3.4.0)
|
||||||
simplecov (0.8.2)
|
rspec-support (3.4.1)
|
||||||
|
simplecov (0.11.1)
|
||||||
docile (~> 1.1.0)
|
docile (~> 1.1.0)
|
||||||
multi_json
|
json (~> 1.8)
|
||||||
simplecov-html (~> 0.8.0)
|
simplecov-html (~> 0.10.0)
|
||||||
simplecov-html (0.8.0)
|
simplecov-html (0.10.0)
|
||||||
yard (0.8.7.4)
|
yard (0.8.7.6)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@@ -46,3 +46,6 @@ DEPENDENCIES
|
|||||||
rspec
|
rspec
|
||||||
simplecov
|
simplecov
|
||||||
yard
|
yard
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
1.10.6
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# Rscons
|
# Rscons
|
||||||
|
|
||||||
Software construction library inspired by SCons and implemented in Ruby
|
Rscons is a software construction framework inspired by SCons and implemented
|
||||||
|
in Ruby.
|
||||||
|
|
||||||
[](http://badge.fury.io/rb/rscons)
|
[](http://badge.fury.io/rb/rscons)
|
||||||
|
|
||||||
@@ -20,9 +21,10 @@ Or install it yourself as:
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Rscons is a Ruby library.
|
Rscons is implemented as a Ruby library and distributed as a gem.
|
||||||
It can be called from a standalone Ruby script or it can be used with rake and
|
It also provides a "rscons" executable which can evaluate a build script (by
|
||||||
called from your Rakefile.
|
default named Rsconsfile or Rsconsfile.rb).
|
||||||
|
It can also be used from rake or from a standalone Ruby script.
|
||||||
|
|
||||||
### Example: Building a C Program
|
### Example: Building a C Program
|
||||||
|
|
||||||
@@ -235,13 +237,15 @@ end
|
|||||||
|
|
||||||
Rscons ships with a number of builders:
|
Rscons ships with a number of builders:
|
||||||
|
|
||||||
* Command, which executes a user-defined command to produce the target
|
* Command, which executes a user-defined command to produce the target.
|
||||||
* CFile, which builds a C or C++ source file from a lex or yacc input file
|
* Copy, which is identical to Install.
|
||||||
* Disassemble, which disassembles an object file to a disassembly listing
|
* CFile, which builds a C or C++ source file from a lex or yacc input file.
|
||||||
* Library, which collects object files into a static library archive file
|
* Disassemble, which disassembles an object file to a disassembly listing.
|
||||||
* Object, which compiles source files to produce an object file
|
* Install, which installs files or directories to a specified destination.
|
||||||
* Preprocess, which invokes the C/C++ preprocessor on a source file
|
* Library, which collects object files into a static library archive file.
|
||||||
* Program, which links object files to produce an executable
|
* Object, which compiles source files to produce an object file.
|
||||||
|
* Preprocess, which invokes the C/C++ preprocessor on a source file.
|
||||||
|
* Program, which links object files to produce an executable.
|
||||||
|
|
||||||
If you want to create an Environment that does not contain any builders,
|
If you want to create an Environment that does not contain any builders,
|
||||||
you can use the `exclude_builders` key to the Environment constructor.
|
you can use the `exclude_builders` key to the Environment constructor.
|
||||||
@@ -249,10 +253,11 @@ you can use the `exclude_builders` key to the Environment constructor.
|
|||||||
#### Command
|
#### Command
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
env.Command(target, sources, 'CMD' => command)
|
env.Command(target, sources, "CMD" => command)
|
||||||
# Example
|
# Example
|
||||||
env.Command("docs.html", "docs.md",
|
env.Command("docs.html", "docs.md",
|
||||||
CMD => ['pandoc', '-fmarkdown', '-thtml', '-o${_TARGET}', '${_SOURCES}'])
|
"CMD" => ["pandoc", "-fmarkdown", "-thtml", "-o${_TARGET}", "${_SOURCES}"],
|
||||||
|
"CMD_DESC" => "PANDOC")
|
||||||
```
|
```
|
||||||
|
|
||||||
The command builder executes a user-defined command in order to produce the
|
The command builder executes a user-defined command in order to produce the
|
||||||
@@ -280,6 +285,15 @@ env.Disassemble("module.dis", "module.o")
|
|||||||
The Disassemble builder generates a disassembly listing using objdump from
|
The Disassemble builder generates a disassembly listing using objdump from
|
||||||
and object file.
|
and object file.
|
||||||
|
|
||||||
|
#### Install
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
env.Install(destination, sources)
|
||||||
|
# Example
|
||||||
|
env.Install("dist/bin", "app.exe")
|
||||||
|
env.Install("dist/share", "share")
|
||||||
|
```
|
||||||
|
|
||||||
#### Library
|
#### Library
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
@@ -371,6 +385,15 @@ Post-build hooks are only invoked if the build operation was a success.
|
|||||||
Post-build hooks can invoke commands using the newly-built files, or register
|
Post-build hooks can invoke commands using the newly-built files, or register
|
||||||
new build targets.
|
new build targets.
|
||||||
|
|
||||||
|
### Phony Targets
|
||||||
|
|
||||||
|
A build target name given as a Symbol instead of a String is interpreted as a
|
||||||
|
"phony" target.
|
||||||
|
Phony targets operate similarly to normal build targets, except that a file is
|
||||||
|
not expected to be produced by the builder.
|
||||||
|
Phony targets will still be "rebuilt" if any source or the command is out of
|
||||||
|
date.
|
||||||
|
|
||||||
### Construction Variable Naming
|
### Construction Variable Naming
|
||||||
|
|
||||||
* uppercase strings - the default construction variables that Rscons uses
|
* uppercase strings - the default construction variables that Rscons uses
|
||||||
@@ -383,6 +406,38 @@ http://rubydoc.info/github/holtrop/rscons/frames.
|
|||||||
|
|
||||||
## Release Notes
|
## Release Notes
|
||||||
|
|
||||||
|
### v1.9.2
|
||||||
|
|
||||||
|
- allow phony targets in conjunction with build roots
|
||||||
|
|
||||||
|
### v1.9.1
|
||||||
|
|
||||||
|
- change *SUFFIX defaults to arrays
|
||||||
|
- add various C++ file suffixes
|
||||||
|
- use ${INCPREFIX} instead of hard-coded "-I" in Preprocess builder
|
||||||
|
|
||||||
|
### v1.9.0
|
||||||
|
|
||||||
|
#### New Features
|
||||||
|
|
||||||
|
- #6 - add Install and Copy builders
|
||||||
|
- #22 - allow overriding Command builder short description with CMD_DESC variable
|
||||||
|
- #24 - add "rscons" executable
|
||||||
|
- #25 - add support for phony targets given as Symbols instead of Strings
|
||||||
|
- #26 - support registering multiple build targets with the same target name
|
||||||
|
- #27 - add Directory builder
|
||||||
|
|
||||||
|
#### Fixes
|
||||||
|
|
||||||
|
- #20 - fix variable references that expand to arrays in build target sources
|
||||||
|
- #21 - rework Preprocess builder to consider deep dependencies
|
||||||
|
- fix Rscons.set_suffix to append the given suffix if the filename has none
|
||||||
|
- remove ${CFLAGS} from default CPP_CMD
|
||||||
|
|
||||||
|
### v1.8.1
|
||||||
|
|
||||||
|
- fix Environment#dump when construction variables are symbols
|
||||||
|
|
||||||
### v1.8.0
|
### v1.8.0
|
||||||
|
|
||||||
- new Command builder to execute arbitrary user commands
|
- new Command builder to execute arbitrary user commands
|
||||||
|
|||||||
+5
-1
@@ -13,7 +13,11 @@ require "rake/clean"
|
|||||||
CLEAN.include %w[build_test_run .yardoc doc coverage]
|
CLEAN.include %w[build_test_run .yardoc doc coverage]
|
||||||
CLOBBER.include %w[pkg]
|
CLOBBER.include %w[pkg]
|
||||||
|
|
||||||
RSpec::Core::RakeTask.new(:spec)
|
RSpec::Core::RakeTask.new(:spec, :example_string) do |task, args|
|
||||||
|
if args.example_string
|
||||||
|
task.rspec_opts = %W[-e "#{args.example_string}" -f documentation]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
YARD::Rake::YardocTask.new do |yard|
|
YARD::Rake::YardocTask.new do |yard|
|
||||||
yard.files = ['lib/**/*.rb']
|
yard.files = ['lib/**/*.rb']
|
||||||
|
|||||||
Executable
+3
@@ -0,0 +1,3 @@
|
|||||||
|
require "rscons/cli"
|
||||||
|
|
||||||
|
Rscons::Cli.run(ARGV)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#define BAR xyz42abc
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include "bar.h"
|
||||||
|
BAR
|
||||||
+107
-88
@@ -6,9 +6,11 @@ require_relative "rscons/varset"
|
|||||||
require_relative "rscons/version"
|
require_relative "rscons/version"
|
||||||
|
|
||||||
# default builders
|
# default builders
|
||||||
require_relative "rscons/builders/command"
|
|
||||||
require_relative "rscons/builders/cfile"
|
require_relative "rscons/builders/cfile"
|
||||||
|
require_relative "rscons/builders/command"
|
||||||
|
require_relative "rscons/builders/directory"
|
||||||
require_relative "rscons/builders/disassemble"
|
require_relative "rscons/builders/disassemble"
|
||||||
|
require_relative "rscons/builders/install"
|
||||||
require_relative "rscons/builders/library"
|
require_relative "rscons/builders/library"
|
||||||
require_relative "rscons/builders/object"
|
require_relative "rscons/builders/object"
|
||||||
require_relative "rscons/builders/preprocess"
|
require_relative "rscons/builders/preprocess"
|
||||||
@@ -17,12 +19,16 @@ require_relative "rscons/builders/simple_builder"
|
|||||||
|
|
||||||
# Namespace module for rscons classes
|
# Namespace module for rscons classes
|
||||||
module Rscons
|
module Rscons
|
||||||
|
|
||||||
# Names of the default builders which will be added to all newly created
|
# Names of the default builders which will be added to all newly created
|
||||||
# {Environment} objects.
|
# {Environment} objects.
|
||||||
DEFAULT_BUILDERS = [
|
DEFAULT_BUILDERS = [
|
||||||
:Command,
|
|
||||||
:CFile,
|
:CFile,
|
||||||
|
:Command,
|
||||||
|
:Copy,
|
||||||
|
:Directory,
|
||||||
:Disassemble,
|
:Disassemble,
|
||||||
|
:Install,
|
||||||
:Library,
|
:Library,
|
||||||
:Object,
|
:Object,
|
||||||
:Preprocess,
|
:Preprocess,
|
||||||
@@ -32,101 +38,114 @@ module Rscons
|
|||||||
# Class to represent a fatal error while building a target.
|
# Class to represent a fatal error while building a target.
|
||||||
class BuildError < RuntimeError; end
|
class BuildError < RuntimeError; end
|
||||||
|
|
||||||
# Remove all generated files.
|
class << self
|
||||||
#
|
|
||||||
# @return [void]
|
# Remove all generated files.
|
||||||
def self.clean
|
#
|
||||||
cache = Cache.instance
|
# @return [void]
|
||||||
# remove all built files
|
def clean
|
||||||
cache.targets.each do |target|
|
cache = Cache.instance
|
||||||
FileUtils.rm_f(target)
|
# remove all built files
|
||||||
end
|
cache.targets.each do |target|
|
||||||
# remove all created directories if they are empty
|
FileUtils.rm_f(target)
|
||||||
cache.directories.sort {|a, b| b.size <=> a.size}.each do |directory|
|
|
||||||
next unless File.directory?(directory)
|
|
||||||
if (Dir.entries(directory) - ['.', '..']).empty?
|
|
||||||
Dir.rmdir(directory) rescue nil
|
|
||||||
end
|
end
|
||||||
end
|
# remove all created directories if they are empty
|
||||||
cache.clear
|
cache.directories.sort {|a, b| b.size <=> a.size}.each do |directory|
|
||||||
end
|
next unless File.directory?(directory)
|
||||||
|
if (Dir.entries(directory) - ['.', '..']).empty?
|
||||||
# Return whether the given path is an absolute filesystem path.
|
Dir.rmdir(directory) rescue nil
|
||||||
#
|
|
||||||
# @param path [String] the path to examine.
|
|
||||||
#
|
|
||||||
# @return [Boolean] Whether the given path is an absolute filesystem path.
|
|
||||||
def self.absolute_path?(path)
|
|
||||||
path =~ %r{^(/|\w:[\\/])}
|
|
||||||
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 self.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.
|
|
||||||
def self.get_system_shell
|
|
||||||
@@shell ||=
|
|
||||||
begin
|
|
||||||
test_shell = lambda do |*args|
|
|
||||||
begin
|
|
||||||
"success" == IO.popen([*args, "echo success"]) do |io|
|
|
||||||
io.read.strip
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if ENV["SHELL"] and ENV["SHELL"] != "" and test_shell[ENV["SHELL"], "-c"]
|
end
|
||||||
[ENV["SHELL"], "-c"]
|
cache.clear
|
||||||
elsif Object.const_get("RUBY_PLATFORM") =~ /mingw/
|
end
|
||||||
if test_shell["sh", "-c"]
|
|
||||||
# Using Rscons from MSYS should use MSYS's shell.
|
# Return whether the given path is an absolute filesystem path.
|
||||||
["sh", "-c"]
|
#
|
||||||
|
# @param path [String] the path to examine.
|
||||||
|
#
|
||||||
|
# @return [Boolean] Whether the given path is an absolute filesystem path.
|
||||||
|
def absolute_path?(path)
|
||||||
|
path =~ %r{^(/|\w:[\\/])}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return whether the given target is a phony target.
|
||||||
|
#
|
||||||
|
# @param target [Symbol, String] Target name.
|
||||||
|
#
|
||||||
|
# @return [Boolean] Whether the given target is a phony target.
|
||||||
|
def phony_target?(target)
|
||||||
|
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.
|
||||||
|
def get_system_shell
|
||||||
|
@shell ||=
|
||||||
|
begin
|
||||||
|
test_shell = lambda do |*args|
|
||||||
|
begin
|
||||||
|
"success" == IO.popen([*args, "echo success"]) do |io|
|
||||||
|
io.read.strip
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ENV["SHELL"] and ENV["SHELL"] != "" and test_shell[ENV["SHELL"], "-c"]
|
||||||
|
[ENV["SHELL"], "-c"]
|
||||||
|
elsif Object.const_get("RUBY_PLATFORM") =~ /mingw/
|
||||||
|
if test_shell["sh", "-c"]
|
||||||
|
# Using Rscons from MSYS should use MSYS's shell.
|
||||||
|
["sh", "-c"]
|
||||||
|
else
|
||||||
|
["cmd", "/c"]
|
||||||
|
end
|
||||||
else
|
else
|
||||||
["cmd", "/c"]
|
["sh", "-c"]
|
||||||
end
|
end
|
||||||
else
|
|
||||||
["sh", "-c"]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Return an Array containing a command used to execute commands.
|
# Return an Array containing a command used to execute commands.
|
||||||
#
|
#
|
||||||
# This will normally be an empty Array, but on Windows if Rscons detects
|
# This will normally be an empty Array, but on Windows if Rscons detects
|
||||||
# that it is running in MSYS then ["env"] will be returned.
|
# that it is running in MSYS then ["env"] will be returned.
|
||||||
#
|
#
|
||||||
# @return [Array<String>] Command used to execute commands.
|
# @return [Array<String>] Command used to execute commands.
|
||||||
def self.command_executer
|
def command_executer
|
||||||
@@command_executer ||=
|
@command_executer ||=
|
||||||
if Object.const_get("RUBY_PLATFORM") =~ /mingw/
|
if Object.const_get("RUBY_PLATFORM") =~ /mingw/
|
||||||
if ENV.keys.find {|key| key =~ /MSYS/}
|
if ENV.keys.find {|key| key =~ /MSYS/}
|
||||||
begin
|
begin
|
||||||
if IO.popen(["env", "echo", "success"]) {|io| io.read.strip} == "success"
|
if IO.popen(["env", "echo", "success"]) {|io| io.read.strip} == "success"
|
||||||
["env"]
|
["env"]
|
||||||
|
end
|
||||||
|
rescue
|
||||||
end
|
end
|
||||||
rescue
|
|
||||||
end
|
end
|
||||||
end
|
end || []
|
||||||
end || []
|
end
|
||||||
end
|
|
||||||
|
# Set the command executer array.
|
||||||
|
#
|
||||||
|
# @param val [Array<String>] Command used to execute commands.
|
||||||
|
#
|
||||||
|
# @return [Array<String>] Command used to execute commands.
|
||||||
|
def command_executer=(val)
|
||||||
|
@command_executer = val
|
||||||
|
end
|
||||||
|
|
||||||
# Set the command executer array.
|
|
||||||
#
|
|
||||||
# @param val [Array<String>] Command used to execute commands.
|
|
||||||
#
|
|
||||||
# @return [Array<String>] Command used to execute commands.
|
|
||||||
def self.command_executer=(val)
|
|
||||||
@@command_executer = val
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,10 @@ module Rscons
|
|||||||
# The name of the target on success or false on failure.
|
# The name of the target on success or false on failure.
|
||||||
def standard_build(short_cmd_string, target, command, sources, env, cache)
|
def standard_build(short_cmd_string, target, command, sources, env, cache)
|
||||||
unless cache.up_to_date?(target, command, sources, env)
|
unless cache.up_to_date?(target, command, sources, env)
|
||||||
cache.mkdir_p(File.dirname(target))
|
unless Rscons.phony_target?(target)
|
||||||
FileUtils.rm_f(target)
|
cache.mkdir_p(File.dirname(target))
|
||||||
|
FileUtils.rm_f(target)
|
||||||
|
end
|
||||||
return false unless env.execute(short_cmd_string, command)
|
return false unless env.execute(short_cmd_string, command)
|
||||||
cache.register_build(target, command, sources, env)
|
cache.register_build(target, command, sources, env)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ module Rscons
|
|||||||
"_SOURCES" => sources,
|
"_SOURCES" => sources,
|
||||||
})
|
})
|
||||||
command = env.build_command("${CMD}", vars)
|
command = env.build_command("${CMD}", vars)
|
||||||
standard_build("CMD #{target}", target, command, sources, env, cache)
|
cmd_desc = vars["CMD_DESC"] || "Command"
|
||||||
|
standard_build("#{cmd_desc} #{target}", target, command, sources, env, cache)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
module Rscons
|
||||||
|
module Builders
|
||||||
|
# The Directory builder creates a directory.
|
||||||
|
class Directory < Builder
|
||||||
|
|
||||||
|
# Run the builder to produce a build target.
|
||||||
|
#
|
||||||
|
# @param target [String] Target file name.
|
||||||
|
# @param sources [Array<String>] Source file name(s).
|
||||||
|
# @param cache [Cache] The Cache object.
|
||||||
|
# @param env [Environment] The Environment executing the builder.
|
||||||
|
# @param vars [Hash,VarSet] Extra construction variables.
|
||||||
|
#
|
||||||
|
# @return [String,false]
|
||||||
|
# Name of the target file on success or false on failure.
|
||||||
|
def run(target, sources, cache, env, vars)
|
||||||
|
if File.directory?(target)
|
||||||
|
target
|
||||||
|
elsif File.exists?(target)
|
||||||
|
$stderr.puts "Error: `#{target}' already exists and is not a directory"
|
||||||
|
false
|
||||||
|
else
|
||||||
|
puts "Directory #{target}"
|
||||||
|
cache.mkdir_p(target)
|
||||||
|
target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
require "pathname"
|
||||||
|
|
||||||
|
module Rscons
|
||||||
|
module Builders
|
||||||
|
# The Install builder copies files/directories to new locations.
|
||||||
|
class Install < Builder
|
||||||
|
|
||||||
|
# Run the builder to produce a build target.
|
||||||
|
#
|
||||||
|
# @param target [String] Target file name.
|
||||||
|
# @param sources [Array<String>] Source file name(s).
|
||||||
|
# @param cache [Cache] The Cache object.
|
||||||
|
# @param env [Environment] The Environment executing the builder.
|
||||||
|
# @param vars [Hash,VarSet] Extra construction variables.
|
||||||
|
#
|
||||||
|
# @return [String,false]
|
||||||
|
# Name of the target file on success or false on failure.
|
||||||
|
def run(target, sources, cache, env, vars)
|
||||||
|
target_is_dir = (sources.length > 1) ||
|
||||||
|
Dir.exists?(sources.first) ||
|
||||||
|
Dir.exists?(target)
|
||||||
|
outdir = target_is_dir ? target : File.dirname(target)
|
||||||
|
# Collect the list of files to copy over.
|
||||||
|
file_map = {}
|
||||||
|
if target_is_dir
|
||||||
|
sources.each do |src|
|
||||||
|
if Dir.exists? src
|
||||||
|
Dir.glob("#{src}/**/*", File::FNM_DOTMATCH).select do |f|
|
||||||
|
File.file?(f)
|
||||||
|
end.each do |subfile|
|
||||||
|
subpath = Pathname.new(subfile).relative_path_from(Pathname.new(src)).to_s
|
||||||
|
file_map[subfile] = "#{outdir}/#{subpath}"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
file_map[src] = "#{outdir}/#{File.basename(src)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
file_map[sources.first] = target
|
||||||
|
end
|
||||||
|
printed_message = false
|
||||||
|
file_map.each do |src, dest|
|
||||||
|
# Check the cache and copy if necessary
|
||||||
|
unless cache.up_to_date?(dest, :Copy, [src], env)
|
||||||
|
unless printed_message
|
||||||
|
puts "#{name} #{target}"
|
||||||
|
printed_message = true
|
||||||
|
end
|
||||||
|
cache.mkdir_p(File.dirname(dest))
|
||||||
|
FileUtils.cp(src, dest, :preserve => true)
|
||||||
|
end
|
||||||
|
cache.register_build(dest, :Copy, [src], env)
|
||||||
|
end
|
||||||
|
target if (target_is_dir ? Dir.exists?(target) : File.exists?(target))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# The Copy builder is identical to the Install builder.
|
||||||
|
class Copy < Install; end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -18,7 +18,7 @@ module Rscons
|
|||||||
# @return [Hash] Default construction variables for the builder.
|
# @return [Hash] Default construction variables for the builder.
|
||||||
def default_variables(env)
|
def default_variables(env)
|
||||||
{
|
{
|
||||||
'OBJSUFFIX' => '.o',
|
'OBJSUFFIX' => ['.o'],
|
||||||
'DEPFILESUFFIX' => '.mf',
|
'DEPFILESUFFIX' => '.mf',
|
||||||
|
|
||||||
'CPPDEFPREFIX' => '-D',
|
'CPPDEFPREFIX' => '-D',
|
||||||
@@ -26,7 +26,7 @@ module Rscons
|
|||||||
|
|
||||||
'AS' => '${CC}',
|
'AS' => '${CC}',
|
||||||
'ASFLAGS' => [],
|
'ASFLAGS' => [],
|
||||||
'ASSUFFIX' => '.S',
|
'ASSUFFIX' => ['.S'],
|
||||||
'ASPPPATH' => '${CPPPATH}',
|
'ASPPPATH' => '${CPPPATH}',
|
||||||
'ASPPFLAGS' => '${CPPFLAGS}',
|
'ASPPFLAGS' => '${CPPFLAGS}',
|
||||||
'ASDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
'ASDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
||||||
@@ -40,19 +40,19 @@ module Rscons
|
|||||||
|
|
||||||
'CC' => 'gcc',
|
'CC' => 'gcc',
|
||||||
'CFLAGS' => [],
|
'CFLAGS' => [],
|
||||||
'CSUFFIX' => '.c',
|
'CSUFFIX' => ['.c'],
|
||||||
'CCDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
'CCDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
||||||
'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',
|
'CXXSUFFIX' => ['.cc', '.cpp', '.cxx', '.C'],
|
||||||
'CXXDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
'CXXDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
||||||
'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'],
|
||||||
'D_IMPORT_PATH' => [],
|
'D_IMPORT_PATH' => [],
|
||||||
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
|
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
require "fileutils"
|
||||||
|
|
||||||
module Rscons
|
module Rscons
|
||||||
module Builders
|
module Builders
|
||||||
# The Preprocess builder invokes the C preprocessor
|
# The Preprocess builder invokes the C preprocessor
|
||||||
class Preprocess < Builder
|
class Preprocess < Builder
|
||||||
|
|
||||||
# Return default construction variables for the builder.
|
# Return default construction variables for the builder.
|
||||||
#
|
#
|
||||||
# @param env [Environment] The Environment using the builder.
|
# @param env [Environment] The Environment using the builder.
|
||||||
@@ -9,7 +12,9 @@ module Rscons
|
|||||||
# @return [Hash] Default construction variables for the builder.
|
# @return [Hash] Default construction variables for the builder.
|
||||||
def default_variables(env)
|
def default_variables(env)
|
||||||
{
|
{
|
||||||
"CPP_CMD" => ["${_PREPROCESS_CC}", "-E", "-o", "${_TARGET}", "-I${CPPPATH}", "${CPPFLAGS}", "${CFLAGS}", "${_SOURCES}"],
|
"CPP_CMD" => %w[
|
||||||
|
${_PREPROCESS_CC} -E ${_PREPROCESS_DEPGEN}
|
||||||
|
-o ${_TARGET} ${INCPREFIX}${CPPPATH} ${CPPFLAGS} ${_SOURCES}],
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -24,17 +29,32 @@ module Rscons
|
|||||||
# @return [String,false]
|
# @return [String,false]
|
||||||
# Name of the target file on success or false on failure.
|
# Name of the target file on success or false on failure.
|
||||||
def run(target, sources, cache, env, vars)
|
def run(target, sources, cache, env, vars)
|
||||||
pp_cc = if sources.find {|s| s.end_with?(*env.expand_varref("${CXXSUFFIX}", vars))}
|
if sources.find {|s| s.end_with?(*env.expand_varref("${CXXSUFFIX}", vars))}
|
||||||
"${CXX}"
|
pp_cc = "${CXX}"
|
||||||
else
|
depgen = "${CXXDEPGEN}"
|
||||||
"${CC}"
|
else
|
||||||
end
|
pp_cc = "${CC}"
|
||||||
|
depgen = "${CCDEPGEN}"
|
||||||
|
end
|
||||||
vars = vars.merge("_PREPROCESS_CC" => pp_cc,
|
vars = vars.merge("_PREPROCESS_CC" => pp_cc,
|
||||||
|
"_PREPROCESS_DEPGEN" => depgen,
|
||||||
"_TARGET" => target,
|
"_TARGET" => target,
|
||||||
"_SOURCES" => sources)
|
"_SOURCES" => sources,
|
||||||
|
"_DEPFILE" => Rscons.set_suffix(target, env.expand_varref("${DEPFILESUFFIX}", vars)))
|
||||||
command = env.build_command("${CPP_CMD}", vars)
|
command = env.build_command("${CPP_CMD}", vars)
|
||||||
standard_build("Preprocess #{target}", target, command, sources, env, cache)
|
unless cache.up_to_date?(target, command, sources, env)
|
||||||
|
cache.mkdir_p(File.dirname(target))
|
||||||
|
return false unless env.execute("Preprocess #{target}", command)
|
||||||
|
deps = sources
|
||||||
|
if File.exists?(vars["_DEPFILE"])
|
||||||
|
deps += Environment.parse_makefile_deps(vars["_DEPFILE"], nil)
|
||||||
|
FileUtils.rm_f(vars["_DEPFILE"])
|
||||||
|
end
|
||||||
|
cache.register_build(target, command, deps.uniq, env)
|
||||||
|
end
|
||||||
|
target
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
+39
-12
@@ -56,6 +56,9 @@ module Rscons
|
|||||||
# Name of the file to store cache information in
|
# Name of the file to store cache information in
|
||||||
CACHE_FILE = ".rsconscache"
|
CACHE_FILE = ".rsconscache"
|
||||||
|
|
||||||
|
# Prefix for phony cache entries.
|
||||||
|
PHONY_PREFIX = ":PHONY:"
|
||||||
|
|
||||||
# Create a Cache object and load in the previous contents from the cache
|
# Create a Cache object and load in the previous contents from the cache
|
||||||
# file.
|
# file.
|
||||||
def initialize
|
def initialize
|
||||||
@@ -92,7 +95,8 @@ module Rscons
|
|||||||
|
|
||||||
# Check if target(s) are up to date.
|
# Check if target(s) are up to date.
|
||||||
#
|
#
|
||||||
# @param targets [String, Array<String>] The name(s) of the target file(s).
|
# @param targets [Symbol, String, Array<String>]
|
||||||
|
# The name(s) of the target file(s).
|
||||||
# @param command [String, Array, Hash]
|
# @param command [String, Array, Hash]
|
||||||
# The command used to build the target. The command parameter can
|
# The command used to build the target. The command parameter can
|
||||||
# actually be a String, Array, or Hash and could contain information
|
# actually be a String, Array, or Hash and could contain information
|
||||||
@@ -120,19 +124,25 @@ module Rscons
|
|||||||
# stored in the cache file
|
# stored in the cache file
|
||||||
def up_to_date?(targets, command, deps, env, options = {})
|
def up_to_date?(targets, command, deps, env, options = {})
|
||||||
Array(targets).each do |target|
|
Array(targets).each do |target|
|
||||||
# target file must exist on disk
|
cache_key = get_cache_key(target)
|
||||||
return false unless File.exists?(target)
|
|
||||||
|
unless Rscons.phony_target?(target)
|
||||||
|
# target file must exist on disk
|
||||||
|
return false unless File.exists?(target)
|
||||||
|
end
|
||||||
|
|
||||||
# target must be registered in the cache
|
# target must be registered in the cache
|
||||||
return false unless @cache["targets"].has_key?(target)
|
return false unless @cache["targets"].has_key?(cache_key)
|
||||||
|
|
||||||
# target must have the same checksum as when it was built last
|
unless Rscons.phony_target?(target)
|
||||||
return false unless @cache["targets"][target]["checksum"] == lookup_checksum(target)
|
# target must have the same checksum as when it was built last
|
||||||
|
return false unless @cache["targets"][cache_key]["checksum"] == lookup_checksum(target)
|
||||||
|
end
|
||||||
|
|
||||||
# command used to build target must be identical
|
# command used to build target must be identical
|
||||||
return false unless @cache["targets"][target]["command"] == Digest::MD5.hexdigest(command.inspect)
|
return false unless @cache["targets"][cache_key]["command"] == Digest::MD5.hexdigest(command.inspect)
|
||||||
|
|
||||||
cached_deps = @cache["targets"][target]["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
|
||||||
@@ -144,7 +154,7 @@ module Rscons
|
|||||||
|
|
||||||
# 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"][target]["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
|
return false unless user_deps == cached_user_deps_fnames
|
||||||
|
|
||||||
@@ -159,7 +169,8 @@ module Rscons
|
|||||||
|
|
||||||
# Store cache information about target(s) built by a builder.
|
# Store cache information about target(s) built by a builder.
|
||||||
#
|
#
|
||||||
# @param targets [String, Array<String>] The name of the target(s) built.
|
# @param targets [Symbol, String, Array<String>]
|
||||||
|
# The name of the target(s) built.
|
||||||
# @param command [String, Array, Hash]
|
# @param command [String, Array, Hash]
|
||||||
# The command used to build the target. The command parameter can
|
# The command used to build the target. The command parameter can
|
||||||
# actually be a String, Array, or Hash and could contain information
|
# actually be a String, Array, or Hash and could contain information
|
||||||
@@ -172,9 +183,10 @@ module Rscons
|
|||||||
# @return [void]
|
# @return [void]
|
||||||
def register_build(targets, command, deps, env)
|
def register_build(targets, command, deps, env)
|
||||||
Array(targets).each do |target|
|
Array(targets).each do |target|
|
||||||
@cache["targets"][target] = {
|
target_checksum = Rscons.phony_target?(target) ? "" : calculate_checksum(target)
|
||||||
|
@cache["targets"][get_cache_key(target)] = {
|
||||||
"command" => Digest::MD5.hexdigest(command.inspect),
|
"command" => Digest::MD5.hexdigest(command.inspect),
|
||||||
"checksum" => calculate_checksum(target),
|
"checksum" => target_checksum,
|
||||||
"deps" => deps.map do |dep|
|
"deps" => deps.map do |dep|
|
||||||
{
|
{
|
||||||
"fname" => dep,
|
"fname" => dep,
|
||||||
@@ -228,6 +240,21 @@ module Rscons
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Return a String key based on the target name to use in the on-disk cache.
|
||||||
|
#
|
||||||
|
# @param target_name [Symbol, String]
|
||||||
|
# Target name.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
# Key name.
|
||||||
|
def get_cache_key(target_name)
|
||||||
|
if Rscons.phony_target?(target_name)
|
||||||
|
PHONY_PREFIX + target_name.to_s
|
||||||
|
else
|
||||||
|
target_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Create a Cache object and load in the previous contents from the cache
|
# Create a Cache object and load in the previous contents from the cache
|
||||||
# file.
|
# file.
|
||||||
def initialize!
|
def initialize!
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
require "rscons"
|
||||||
|
require "optparse"
|
||||||
|
|
||||||
|
module Rscons
|
||||||
|
# Command-Line Interface functionality.
|
||||||
|
module Cli
|
||||||
|
|
||||||
|
# Default files to look for to execute if none specified.
|
||||||
|
DEFAULT_RSCONSFILES = %w[Rsconsfile Rsconsfile.rb]
|
||||||
|
|
||||||
|
class << self
|
||||||
|
|
||||||
|
# Run the Rscons CLI.
|
||||||
|
#
|
||||||
|
# @param argv [Array]
|
||||||
|
# Command-line parameters.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def run(argv)
|
||||||
|
argv = argv.dup
|
||||||
|
rsconsfile = nil
|
||||||
|
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
opts.banner = "Usage: #{$0} [options]"
|
||||||
|
|
||||||
|
opts.separator ""
|
||||||
|
opts.separator "Options:"
|
||||||
|
|
||||||
|
opts.on("-c", "--clean", "Perform clean operation") do
|
||||||
|
Rscons.clean
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on("-f FILE", "Execute FILE (default Rsconsfile)") do |f|
|
||||||
|
rsconsfile = f
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on_tail("--version", "Show version") do
|
||||||
|
puts "Rscons version #{Rscons::VERSION}"
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.on_tail("-h", "--help", "Show this help.") do
|
||||||
|
puts opts
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end.parse!(argv)
|
||||||
|
|
||||||
|
if rsconsfile
|
||||||
|
unless File.exists?(rsconsfile)
|
||||||
|
$stderr.puts "Cannot read #{rsconsfile}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rsconsfile = DEFAULT_RSCONSFILES.find do |f|
|
||||||
|
File.exists?(f)
|
||||||
|
end
|
||||||
|
unless rsconsfile
|
||||||
|
$stderr.puts "Could not find the Rsconsfile to execute."
|
||||||
|
$stderr.puts "Looked in: [#{DEFAULT_RSCONSFILES.join(", ")}]"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
load rsconsfile
|
||||||
|
rescue Rscons::BuildError => e
|
||||||
|
$stderr.puts e.message
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+40
-28
@@ -280,33 +280,35 @@ module Rscons
|
|||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def process
|
def process
|
||||||
expand_paths!
|
|
||||||
while @targets.size > 0
|
while @targets.size > 0
|
||||||
|
expand_paths!
|
||||||
targets = @targets
|
targets = @targets
|
||||||
@targets = {}
|
@targets = {}
|
||||||
cache = Cache.instance
|
cache = Cache.instance
|
||||||
cache.clear_checksum_cache!
|
cache.clear_checksum_cache!
|
||||||
targets_processed = {}
|
targets_processed = Set.new
|
||||||
process_target = proc do |target|
|
process_target = proc do |target|
|
||||||
targets_processed[target] ||= begin
|
unless targets_processed.include?(target)
|
||||||
targets[target][:sources].each do |src|
|
targets_processed << target
|
||||||
if targets.include?(src) and not targets_processed.include?(src)
|
targets[target].each do |target_params|
|
||||||
process_target.call(src)
|
target_params[:sources].each do |src|
|
||||||
|
if targets.include?(src) and not targets_processed.include?(src)
|
||||||
|
process_target.call(src)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result = run_builder(target_params[:builder],
|
||||||
|
target,
|
||||||
|
target_params[:sources],
|
||||||
|
cache,
|
||||||
|
target_params[:vars] || {})
|
||||||
|
unless result
|
||||||
|
raise BuildError.new("Failed to build #{target}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
result = run_builder(targets[target][:builder],
|
|
||||||
target,
|
|
||||||
targets[target][:sources],
|
|
||||||
cache,
|
|
||||||
targets[target][:vars] || {})
|
|
||||||
unless result
|
|
||||||
raise BuildError.new("Failed to build #{target}")
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
begin
|
begin
|
||||||
targets.each do |target, target_params|
|
targets.each_key do |target|
|
||||||
process_target.call(target)
|
process_target.call(target)
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
@@ -404,7 +406,8 @@ module Rscons
|
|||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def add_target(target, builder, sources, vars, args)
|
def add_target(target, builder, sources, vars, args)
|
||||||
@targets[target] = {
|
@targets[target] ||= []
|
||||||
|
@targets[target] << {
|
||||||
builder: builder,
|
builder: builder,
|
||||||
sources: sources,
|
sources: sources,
|
||||||
vars: vars,
|
vars: vars,
|
||||||
@@ -506,7 +509,11 @@ module Rscons
|
|||||||
#
|
#
|
||||||
# @return [String] The expanded path.
|
# @return [String] The expanded path.
|
||||||
def expand_path(path)
|
def expand_path(path)
|
||||||
path.sub(%r{^\^(?=[\\/])}, @build_root)
|
if Rscons.phony_target?(path)
|
||||||
|
path
|
||||||
|
else
|
||||||
|
path.sub(%r{^\^(?=[\\/])}, @build_root)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Execute a command using the system shell.
|
# Execute a command using the system shell.
|
||||||
@@ -662,8 +669,10 @@ module Rscons
|
|||||||
|
|
||||||
# Print the Environment's construction variables for debugging.
|
# Print the Environment's construction variables for debugging.
|
||||||
def dump
|
def dump
|
||||||
@varset.to_h.sort.each do |var, val|
|
varset_hash = @varset.to_h
|
||||||
puts "#{var} => #{val.inspect}"
|
varset_hash.keys.sort_by(&:to_s).each do |var|
|
||||||
|
var_str = var.is_a?(Symbol) ? var.inspect : var
|
||||||
|
puts "#{var_str} => #{varset_hash[var].inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -677,14 +686,16 @@ module Rscons
|
|||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def expand_paths!
|
def expand_paths!
|
||||||
@targets = @targets.reduce({}) do |result, (target, target_params)|
|
@targets = @targets.reduce({}) do |result, (target, target_params_list)|
|
||||||
sources = target_params[:sources].map do |source|
|
|
||||||
source = expand_path(source) if @build_root
|
|
||||||
expand_varref(source)
|
|
||||||
end
|
|
||||||
target = expand_path(target) if @build_root
|
target = expand_path(target) if @build_root
|
||||||
target = expand_varref(target)
|
target = expand_varref(target)
|
||||||
result[target] = target_params.merge(sources: sources)
|
result[target] = target_params_list.map do |target_params|
|
||||||
|
sources = target_params[:sources].map do |source|
|
||||||
|
source = expand_path(source) if @build_root
|
||||||
|
expand_varref(source)
|
||||||
|
end.flatten
|
||||||
|
target_params.merge(sources: sources)
|
||||||
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -694,7 +705,8 @@ module Rscons
|
|||||||
# This method is used internally by Rscons builders.
|
# This method is used internally by Rscons builders.
|
||||||
#
|
#
|
||||||
# @param mf_fname [String] File name of the Makefile to read.
|
# @param mf_fname [String] File name of the Makefile to read.
|
||||||
# @param target [String] Name of the target to gather dependencies for.
|
# @param target [String, nil]
|
||||||
|
# Name of the target to gather dependencies for, nil for any/all.
|
||||||
#
|
#
|
||||||
# @return [Array<String>] Paths of dependency files.
|
# @return [Array<String>] Paths of dependency files.
|
||||||
def self.parse_makefile_deps(mf_fname, target)
|
def self.parse_makefile_deps(mf_fname, target)
|
||||||
@@ -707,7 +719,7 @@ module Rscons
|
|||||||
buildup += ' ' + line
|
buildup += ' ' + line
|
||||||
if buildup =~ /^(.*): (.*)$/
|
if buildup =~ /^(.*): (.*)$/
|
||||||
mf_target, mf_deps = $1.strip, $2
|
mf_target, mf_deps = $1.strip, $2
|
||||||
if mf_target == target
|
if target.nil? or mf_target == target
|
||||||
deps += mf_deps.split(' ').map(&:strip)
|
deps += mf_deps.split(' ').map(&:strip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ module Rscons
|
|||||||
expand_varref(varref[*lambda_args], lambda_args)
|
expand_varref(varref[*lambda_args], lambda_args)
|
||||||
elsif varref.nil?
|
elsif varref.nil?
|
||||||
nil
|
nil
|
||||||
|
elsif varref.is_a?(Symbol)
|
||||||
|
varref
|
||||||
else
|
else
|
||||||
raise "Unknown varref type: #{varref.class} (#{varref.inspect})"
|
raise "Unknown varref type: #{varref.class} (#{varref.inspect})"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Rscons
|
module Rscons
|
||||||
# gem version
|
# gem version
|
||||||
VERSION = "1.8.0"
|
VERSION = "1.9.2"
|
||||||
end
|
end
|
||||||
@@ -725,11 +725,245 @@ EOF
|
|||||||
test_dir("simple")
|
test_dir("simple")
|
||||||
env = Rscons::Environment.new do |env|
|
env = Rscons::Environment.new do |env|
|
||||||
env["CFLAGS"] += %w[-O2 -fomit-frame-pointer]
|
env["CFLAGS"] += %w[-O2 -fomit-frame-pointer]
|
||||||
|
env[:foo] = :bar
|
||||||
end
|
end
|
||||||
env.dump
|
env.dump
|
||||||
result = lines
|
result = lines
|
||||||
|
expect(result.include?(%{:foo => :bar})).to be_truthy
|
||||||
expect(result.include?(%{CFLAGS => ["-O2", "-fomit-frame-pointer"]})).to be_truthy
|
expect(result.include?(%{CFLAGS => ["-O2", "-fomit-frame-pointer"]})).to be_truthy
|
||||||
expect(result.include?(%{CPPPATH => []})).to be_truthy
|
expect(result.include?(%{CPPPATH => []})).to be_truthy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "considers deep dependencies when deciding whether to rerun Preprocess builder" do
|
||||||
|
test_dir("preprocess")
|
||||||
|
env = Rscons::Environment.new do |env|
|
||||||
|
env.Preprocess("pp", "foo.h")
|
||||||
|
end
|
||||||
|
expect(File.read("pp")).to match(%r{xyz42abc}m)
|
||||||
|
expect(lines).to eq(["Preprocess pp"])
|
||||||
|
env.Preprocess("pp", "foo.h")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
File.open("bar.h", "w") do |fh|
|
||||||
|
fh.puts "#define BAR abc88xyz"
|
||||||
|
end
|
||||||
|
$ttt = true
|
||||||
|
env.Preprocess("pp", "foo.h")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq(["Preprocess pp"])
|
||||||
|
expect(File.read("pp")).to match(%r{abc88xyz}m)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows construction variable references which expand to arrays in sources of a build target" do
|
||||||
|
test_dir("simple")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env["sources"] = Dir["*.c"]
|
||||||
|
env.Program("simple", "${sources}")
|
||||||
|
end
|
||||||
|
expect(File.exists?("simple.o")).to be_truthy
|
||||||
|
expect(`./simple`).to eq "This is a simple C program\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "supports registering multiple build targets with the same target path" do
|
||||||
|
test_dir("build_dir")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env["CPPPATH"] << "src/two"
|
||||||
|
env.Object("one.o", "src/one/one.c")
|
||||||
|
env.Object("one.o", "src/two/two.c")
|
||||||
|
end
|
||||||
|
expect(File.exists?("one.o")).to be_truthy
|
||||||
|
expect(lines).to eq([
|
||||||
|
"CC one.o",
|
||||||
|
"CC one.o",
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "expands target and source paths when builders are registered in build hooks" do
|
||||||
|
test_dir("build_dir")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env["CPPPATH"] << "src/two"
|
||||||
|
env.Object("one.o", "src/one/one.c")
|
||||||
|
env.add_post_build_hook do |build_op|
|
||||||
|
if build_op[:target] == "one.o"
|
||||||
|
env["MODULE"] = "two"
|
||||||
|
env.Object("${MODULE}.o", "src/${MODULE}/${MODULE}.c")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
expect(File.exists?("one.o")).to be_truthy
|
||||||
|
expect(File.exists?("two.o")).to be_truthy
|
||||||
|
expect(lines).to eq([
|
||||||
|
"CC one.o",
|
||||||
|
"CC two.o",
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Directory builder" do
|
||||||
|
it "creates the requested directory" do
|
||||||
|
test_dir("simple")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env.Directory("teh_dir")
|
||||||
|
end
|
||||||
|
expect(File.directory?("teh_dir")).to be_truthy
|
||||||
|
expect(lines).to eq(["Directory teh_dir"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "succeeds when the requested directory already exists" do
|
||||||
|
test_dir("simple")
|
||||||
|
FileUtils.mkdir("teh_dir")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env.Directory("teh_dir")
|
||||||
|
end
|
||||||
|
expect(File.directory?("teh_dir")).to be_truthy
|
||||||
|
expect(lines).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails when the target path is a file" do
|
||||||
|
test_dir("simple")
|
||||||
|
FileUtils.touch("teh_dir")
|
||||||
|
expect do
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env.Directory("teh_dir")
|
||||||
|
end
|
||||||
|
end.to raise_error /Failed to build teh_dir/
|
||||||
|
expect(lines).to eq([
|
||||||
|
"Error: `teh_dir' already exists and is not a directory",
|
||||||
|
])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "Install buildler" do
|
||||||
|
let(:base_env) do
|
||||||
|
test_dir("build_dir")
|
||||||
|
Rscons::Environment.new do |env|
|
||||||
|
env["CPPPATH"] = Dir["src/**/"]
|
||||||
|
env["sources"] = Dir["src/**/*.c"]
|
||||||
|
env.Program("simple.exe", "${sources}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "copies a file to the target file name" do
|
||||||
|
env = base_env.clone do |env|
|
||||||
|
lines
|
||||||
|
env.Install("inst.exe", "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["Install inst.exe"])
|
||||||
|
env.Install("inst.exe", "simple.exe")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
expect(File.exists?("inst.exe")).to be_truthy
|
||||||
|
expect(File.read("inst.exe", mode: "rb")).to eq(File.read("simple.exe", mode: "rb"))
|
||||||
|
FileUtils.rm("inst.exe")
|
||||||
|
env.Install("inst.exe", "simple.exe")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq(["Install inst.exe"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "operates the same as a Copy builder" do
|
||||||
|
env = base_env.clone do |env|
|
||||||
|
lines
|
||||||
|
env.Copy("inst.exe", "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["Copy inst.exe"])
|
||||||
|
env.Copy("inst.exe", "simple.exe")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
expect(File.exists?("inst.exe")).to be_truthy
|
||||||
|
expect(File.read("inst.exe", mode: "rb")).to eq(File.read("simple.exe", mode: "rb"))
|
||||||
|
FileUtils.rm("inst.exe")
|
||||||
|
env.Copy("inst.exe", "simple.exe")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq(["Copy inst.exe"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "copies a file to the target directory name" do
|
||||||
|
env = base_env.clone do |env|
|
||||||
|
lines
|
||||||
|
env.Directory("inst")
|
||||||
|
env.Install("inst", "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq([
|
||||||
|
"Directory inst",
|
||||||
|
"Install inst",
|
||||||
|
])
|
||||||
|
env.Install("inst", "simple.exe")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
expect(File.exists?("inst/simple.exe")).to be_truthy
|
||||||
|
expect(File.read("inst/simple.exe", mode: "rb")).to eq(File.read("simple.exe", mode: "rb"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "copies a directory to the non-existent target directory name" do
|
||||||
|
env = base_env.clone do |env|
|
||||||
|
lines
|
||||||
|
env.Install("dist/src", "src")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["Install dist/src"])
|
||||||
|
env.Install("dist/src", "src")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
%w[src/one/one.c src/two/two.c src/two/two.h].each do |f|
|
||||||
|
expect(File.exists?("dist/#{f}")).to be_truthy
|
||||||
|
expect(File.read("dist/#{f}", mode: "rb")).to eq(File.read(f, mode: "rb"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "copies a directory to the existent target directory name" do
|
||||||
|
env = base_env.clone do |env|
|
||||||
|
lines
|
||||||
|
env.Directory("dist/src")
|
||||||
|
env.Install("dist/src", "src")
|
||||||
|
end
|
||||||
|
expect(lines).to eq([
|
||||||
|
"Directory dist/src",
|
||||||
|
"Install dist/src",
|
||||||
|
])
|
||||||
|
env.Install("dist/src", "src")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq([])
|
||||||
|
%w[src/one/one.c src/two/two.c src/two/two.h].each do |f|
|
||||||
|
expect(File.exists?("dist/#{f}")).to be_truthy
|
||||||
|
expect(File.read("dist/#{f}", mode: "rb")).to eq(File.read(f, mode: "rb"))
|
||||||
|
end
|
||||||
|
FileUtils.rm("dist/src/two/two.c")
|
||||||
|
env.Install("dist/src", "src")
|
||||||
|
env.process
|
||||||
|
expect(lines).to eq(["Install dist/src"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "phony targets" do
|
||||||
|
[false, true].each do |with_build_root|
|
||||||
|
it "allows specifying a Symbol as a target name and reruns the builder if the sources or command have changed" do
|
||||||
|
test_dir("simple")
|
||||||
|
env = Rscons::Environment.new do |env|
|
||||||
|
env.build_root = "bld" if with_build_root
|
||||||
|
env.add_builder(:Checker) do |target, sources, cache, env, vars|
|
||||||
|
unless cache.up_to_date?(target, :Checker, sources, env)
|
||||||
|
puts "Checker #{sources.first}" if env.echo != :off
|
||||||
|
cache.register_build(target, :Checker, sources, env)
|
||||||
|
end
|
||||||
|
target
|
||||||
|
end
|
||||||
|
env.Program("simple.exe", "simple.c")
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["CC #{with_build_root ? 'bld/' : ''}simple.o", "LD simple.exe", "Checker simple.exe"])
|
||||||
|
|
||||||
|
env.clone do |env|
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq([])
|
||||||
|
|
||||||
|
File.open("simple.exe", "w") do |fh|
|
||||||
|
fh.puts "Changed simple.exe"
|
||||||
|
end
|
||||||
|
env.clone do |env|
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["Checker simple.exe"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
module Rscons
|
module Rscons
|
||||||
module Builders
|
module Builders
|
||||||
describe Command do
|
describe Command do
|
||||||
|
|
||||||
let(:command) { ['pandoc', '-fmarkdown', '-thtml', '-o${_TARGET}', '${_SOURCES}'] }
|
let(:command) { ['pandoc', '-fmarkdown', '-thtml', '-o${_TARGET}', '${_SOURCES}'] }
|
||||||
let(:env) {Environment.new}
|
let(:env) {Environment.new}
|
||||||
subject {Command.new}
|
subject {Command.new}
|
||||||
|
|
||||||
|
|
||||||
it "invokes the command to build the target" do
|
it "invokes the command to build the target" do
|
||||||
expected_cmd = ['pandoc', '-fmarkdown', '-thtml', '-ofoo.html', 'foo.md']
|
expected_cmd = ['pandoc', '-fmarkdown', '-thtml', '-ofoo.html', 'foo.md']
|
||||||
expect(subject).to receive(:standard_build).with("CMD foo.html", "foo.html", expected_cmd, ["foo.md"], env, :cache)
|
expect(subject).to receive(:standard_build).with("PANDOC foo.html", "foo.html", expected_cmd, ["foo.md"], env, :cache)
|
||||||
subject.run("foo.html", ["foo.md"], :cache, env, {'CMD' => command})
|
subject.run("foo.html", ["foo.md"], :cache, env,
|
||||||
|
"CMD" => command, "CMD_DESC" => "PANDOC")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1,18 +1,48 @@
|
|||||||
module Rscons
|
module Rscons
|
||||||
module Builders
|
module Builders
|
||||||
describe Preprocess do
|
describe Preprocess do
|
||||||
|
|
||||||
let(:env) {Environment.new}
|
let(:env) {Environment.new}
|
||||||
subject {Preprocess.new}
|
subject {Preprocess.new}
|
||||||
|
|
||||||
it "supports overriding CC construction variable" do
|
it "supports overriding CC construction variable" do
|
||||||
expect(subject).to receive(:standard_build).with("Preprocess module.pp", "module.pp", ["my_cpp", "-E", "-o", "module.pp", "module.c"], ["module.c"], env, :cache)
|
cache = double(Cache)
|
||||||
subject.run("module.pp", ["module.c"], :cache, env, "CC" => "my_cpp")
|
command = %w[my_cpp -E -MMD -MF module.mf -o module.pp module.c]
|
||||||
|
expect(cache).to receive(:up_to_date?).with("module.pp", command, %w[module.c], env).and_return(false)
|
||||||
|
expect(cache).to receive(:mkdir_p).with(".")
|
||||||
|
expect(env).to receive(:execute).with("Preprocess module.pp", command).and_return(true)
|
||||||
|
expect(File).to receive(:exists?).with("module.mf").and_return(true)
|
||||||
|
expect(Environment).to receive(:parse_makefile_deps).with("module.mf", nil).and_return(%w[module.c one.h two.h])
|
||||||
|
expect(FileUtils).to receive(:rm_f).with("module.mf")
|
||||||
|
expect(cache).to receive(:register_build).with("module.pp", command, %w[module.c one.h two.h], env)
|
||||||
|
|
||||||
|
expect(subject.run("module.pp", ["module.c"], cache, env, "CC" => "my_cpp")).to eq("module.pp")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "supports overriding CPP_CMD construction variable" do
|
it "supports overriding CPP_CMD construction variable" do
|
||||||
expect(subject).to receive(:standard_build).with("Preprocess module.pp", "module.pp", ["my_cpp", "module.c"], ["module.c"], env, :cache)
|
cache = double(Cache)
|
||||||
subject.run("module.pp", ["module.c"], :cache, env, "CPP_CMD" => ["my_cpp", "${_SOURCES}"])
|
command = %w[my_cpp module.c]
|
||||||
|
expect(cache).to receive(:up_to_date?).with("module.pp", command, %w[module.c], env).and_return(false)
|
||||||
|
expect(cache).to receive(:mkdir_p).with(".")
|
||||||
|
expect(env).to receive(:execute).with("Preprocess module.pp", command).and_return(true)
|
||||||
|
expect(File).to receive(:exists?).with("module.mf").and_return(true)
|
||||||
|
expect(Environment).to receive(:parse_makefile_deps).with("module.mf", nil).and_return(%w[module.c one.h two.h])
|
||||||
|
expect(FileUtils).to receive(:rm_f).with("module.mf")
|
||||||
|
expect(cache).to receive(:register_build).with("module.pp", command, %w[module.c one.h two.h], env)
|
||||||
|
|
||||||
|
expect(subject.run("module.pp", ["module.c"], cache, env, "CPP_CMD" => ["my_cpp", "${_SOURCES}"])).to eq("module.pp")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns false if executing the preprocessor fails" do
|
||||||
|
cache = double(Cache)
|
||||||
|
command = %w[gcc -E -MMD -MF module.mf -o module.pp module.c]
|
||||||
|
expect(cache).to receive(:up_to_date?).with("module.pp", command, %w[module.c], env).and_return(false)
|
||||||
|
expect(cache).to receive(:mkdir_p).with(".")
|
||||||
|
expect(env).to receive(:execute).with("Preprocess module.pp", command).and_return(false)
|
||||||
|
|
||||||
|
expect(subject.run("module.pp", ["module.c"], cache, env, {})).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -305,10 +305,10 @@ module Rscons
|
|||||||
env.Object("target.o", ["src1.c", "src2.c"], var: "val")
|
env.Object("target.o", ["src1.c", "src2.c"], var: "val")
|
||||||
target = env.instance_variable_get(:@targets)["target.o"]
|
target = env.instance_variable_get(:@targets)["target.o"]
|
||||||
expect(target).to_not be_nil
|
expect(target).to_not be_nil
|
||||||
expect(target[:builder].is_a?(Builder)).to be_truthy
|
expect(target[0][:builder].is_a?(Builder)).to be_truthy
|
||||||
expect(target[:sources]).to eq ["src1.c", "src2.c"]
|
expect(target[0][:sources]).to eq ["src1.c", "src2.c"]
|
||||||
expect(target[:vars]).to eq({var: "val"})
|
expect(target[0][:vars]).to eq({var: "val"})
|
||||||
expect(target[:args]).to eq []
|
expect(target[0][:args]).to eq []
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an error when vars is not a Hash" do
|
it "raises an error when vars is not a Hash" do
|
||||||
|
|||||||
+17
-7
@@ -24,13 +24,23 @@ describe Rscons do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
describe ".get_system_shell" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
Rscons.class_variable_set(:@@shell, nil)
|
Rscons.instance_variable_set(:@shell, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
after(:each) do
|
after(:each) do
|
||||||
Rscons.class_variable_set(:@@shell, nil)
|
Rscons.instance_variable_set(:@shell, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "uses the SHELL environment variable if it tests successfully" do
|
it "uses the SHELL environment variable if it tests successfully" do
|
||||||
@@ -70,11 +80,11 @@ describe Rscons do
|
|||||||
context "command executer" do
|
context "command executer" do
|
||||||
describe ".command_executer" do
|
describe ".command_executer" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
Rscons.class_variable_set(:@@command_executer, nil)
|
Rscons.instance_variable_set(:@command_executer, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
after(:each) do
|
after(:each) do
|
||||||
Rscons.class_variable_set(:@@command_executer, nil)
|
Rscons.instance_variable_set(:@command_executer, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns ['env'] if mingw platform in MSYS and 'env' works" do
|
it "returns ['env'] if mingw platform in MSYS and 'env' works" do
|
||||||
@@ -105,10 +115,10 @@ describe Rscons do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe ".command_executer=" do
|
describe ".command_executer=" do
|
||||||
it "overrides the value of @@command_executer" do
|
it "overrides the value of @command_executer" do
|
||||||
Rscons.class_variable_set(:@@command_executer, ["env"])
|
Rscons.instance_variable_set(:@command_executer, ["env"])
|
||||||
Rscons.command_executer = []
|
Rscons.command_executer = []
|
||||||
expect(Rscons.class_variable_get(:@@command_executer)).to eq([])
|
expect(Rscons.instance_variable_get(:@command_executer)).to eq([])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in new issue
Block a user