rscons 0.0.14 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -1
- data/README.md +128 -11
- data/{Rakefile → Rakefile.rb} +8 -3
- data/build_tests/d/main.d +6 -0
- data/lib/rscons/builders/library.rb +2 -2
- data/lib/rscons/builders/object.rb +27 -28
- data/lib/rscons/builders/program.rb +17 -19
- data/lib/rscons/cache.rb +9 -9
- data/lib/rscons/environment.rb +52 -65
- data/lib/rscons/varset.rb +7 -11
- data/lib/rscons/version.rb +1 -1
- data/spec/build_tests_spec.rb +153 -52
- data/spec/rscons/cache_spec.rb +204 -0
- data/spec/rscons/environment_spec.rb +257 -6
- data/spec/rscons/varset_spec.rb +16 -11
- data/spec/rscons_spec.rb +26 -0
- data/spec/spec_helper.rb +3 -1
- metadata +10 -14
- data/build_tests/build_dir/build.rb +0 -5
- data/build_tests/build_dir/tweaker_build.rb +0 -12
- data/build_tests/clone_env/build.rb +0 -11
- data/build_tests/custom_builder/build.rb +0 -15
- data/build_tests/header/build.rb +0 -3
- data/build_tests/library/build.rb +0 -4
- data/build_tests/simple/build.rb +0 -4
- data/build_tests/simple_cc/build.rb +0 -4
- data/build_tests/two_sources/build.rb +0 -4
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
Software construction library inspired by SCons and implemented in Ruby
|
4
4
|
|
5
|
+
[](http://badge.fury.io/rb/rscons)
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
8
10
|
|
9
|
-
gem
|
11
|
+
gem "rscons"
|
10
12
|
|
11
13
|
And then execute:
|
12
14
|
|
@@ -18,20 +20,135 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
Rscons is a Ruby library.
|
24
|
+
It can be called from a standalone Ruby script or it can be used with rake and
|
25
|
+
called from your Rakefile.
|
26
|
+
|
27
|
+
### Example: Building a C Program
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
RScons::Environment.new do |env|
|
31
|
+
env["CFLAGS"] << "-Wall"
|
32
|
+
env.Program("program", Dir["**/*.c"])
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
### Example: Building a D Program
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
RScons::Environment.new do |env|
|
40
|
+
env["DFLAGS"] << "-Wall"
|
41
|
+
env.Program("program", Dir["**/*.d"])
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
### Example: Cloning an Environment
|
24
46
|
|
25
|
-
|
26
|
-
|
27
|
-
|
47
|
+
```ruby
|
48
|
+
main_env = RScons::Environment.new do |env|
|
49
|
+
# Store object files from sources under "src" in "build/main"
|
50
|
+
env.build_dir("src", "build/main")
|
51
|
+
env["CFLAGS"] = ["-DSOME_DEFINE", "-O3"]
|
52
|
+
env["LIBS"] = ["SDL"]
|
53
|
+
env.Program("program", Dir["src/**/*.cc"])
|
54
|
+
end
|
55
|
+
|
56
|
+
debug_env = main_env.clone do |env|
|
57
|
+
# Store object files from sources under "src" in "build/debug"
|
58
|
+
env.build_dir("src", "build/debug")
|
59
|
+
env["CFLAGS"] -= ["-O3"]
|
60
|
+
env["CFLAGS"] += ["-g", "-O0"]
|
61
|
+
env.Program("program-debug", Dir["src/**/*.cc"])
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
### Example: Custom Builder
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class GenerateFoo < Rscons::Builder
|
69
|
+
def run(target, sources, cache, env, vars)
|
70
|
+
File.open(target, "w") do |fh|
|
71
|
+
fh.puts <<EOF
|
72
|
+
#define GENERATED 42
|
73
|
+
EOF
|
28
74
|
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Rscons::Environment.new do |env|
|
79
|
+
env.GenerateFoo("foo.h", [])
|
80
|
+
env.Program("a.out", Dir["*.c"])
|
81
|
+
end
|
82
|
+
```
|
29
83
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
84
|
+
### Example: Using different compilation flags for some sources
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
Rscons::Environment.new do |env|
|
88
|
+
env["CFLAGS"] = ["-O3", "-Wall", "-DDEFINE"]
|
89
|
+
env.add_build_hook do |build_op|
|
90
|
+
if build_op[:target] =~ %r{build/third-party}
|
91
|
+
build_op[:vars]["CFLAGS"] -= ["-Wall"]
|
34
92
|
end
|
93
|
+
end
|
94
|
+
env.build_dir("src", "build")
|
95
|
+
env.Program("program", Dir["**/*.cc"])
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
### Example: Creating a static library
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
Rscons::Environment.new do |env|
|
103
|
+
env.Library("mylib.a", Dir["src/**/*.c"])
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
## Details
|
108
|
+
|
109
|
+
### Default Builders
|
110
|
+
|
111
|
+
Rscons ships with a number of default builders:
|
112
|
+
|
113
|
+
* Library, which collects object files into a static library archive file
|
114
|
+
* Object, which compiles source files to produce an object file
|
115
|
+
* Program, which links object files to produce an executable
|
116
|
+
|
117
|
+
If you want to create an Environment that does not contain any (or select)
|
118
|
+
builders, you can use the `exclude_builders` key to the Environment constructor.
|
119
|
+
|
120
|
+
### Managing Environments
|
121
|
+
|
122
|
+
An Rscons::Environment consists of:
|
123
|
+
|
124
|
+
* a collection of construction variables
|
125
|
+
* a collection of builders
|
126
|
+
* a mapping of build directories
|
127
|
+
* a collection of targets to build
|
128
|
+
* a collection of build hooks
|
129
|
+
|
130
|
+
When cloning an environment, the construction variables, builders, and build
|
131
|
+
directories are cloned, but the new environment does not inherit any of the
|
132
|
+
targets or build hooks from the source environment.
|
133
|
+
|
134
|
+
Cloned environments contain "deep copies" of construction variables.
|
135
|
+
For example, in:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
base_env = Rscons::Environment.new
|
139
|
+
base_env["CPPPATH"] = ["one", "two"]
|
140
|
+
cloned_env = base_env.clone
|
141
|
+
cloned_env["CPPPATH"] << "three"
|
142
|
+
```
|
143
|
+
|
144
|
+
`base_env["CPPPATH"]` will not include "three".
|
145
|
+
|
146
|
+
### Construction Variables
|
147
|
+
|
148
|
+
The default construction variables that Rscons uses are named using uppercase
|
149
|
+
strings.
|
150
|
+
Rscons options are lowercase symbols.
|
151
|
+
Lowercase strings are reserved as user-defined construction variables.
|
35
152
|
|
36
153
|
## Contributing
|
37
154
|
|
data/{Rakefile → Rakefile.rb}
RENAMED
@@ -7,11 +7,8 @@ end
|
|
7
7
|
|
8
8
|
require "bundler/gem_tasks"
|
9
9
|
require "rspec/core/rake_task"
|
10
|
-
require "rake/clean"
|
11
10
|
require "yard"
|
12
11
|
|
13
|
-
CLEAN.include 'build_tests_run'
|
14
|
-
|
15
12
|
RSpec::Core::RakeTask.new(:spec)
|
16
13
|
|
17
14
|
YARD::Rake::YardocTask.new do |yard|
|
@@ -19,3 +16,11 @@ YARD::Rake::YardocTask.new do |yard|
|
|
19
16
|
end
|
20
17
|
|
21
18
|
task :default => :spec
|
19
|
+
|
20
|
+
task :clean do
|
21
|
+
FileUtils.rm_rf(["build_test_run", "doc", "coverage"])
|
22
|
+
end
|
23
|
+
|
24
|
+
task :clobber => :clean do
|
25
|
+
FileUtils.rm_rf(["pkg"])
|
26
|
+
end
|
@@ -8,7 +8,7 @@ module Rscons
|
|
8
8
|
'AR' => 'ar',
|
9
9
|
'LIBSUFFIX' => '.a',
|
10
10
|
'ARFLAGS' => [],
|
11
|
-
'
|
11
|
+
'ARCMD' => ['${AR}', 'rcs', '${ARFLAGS}', '${_TARGET}', '${_SOURCES}']
|
12
12
|
}
|
13
13
|
end
|
14
14
|
|
@@ -20,7 +20,7 @@ module Rscons
|
|
20
20
|
'_TARGET' => target,
|
21
21
|
'_SOURCES' => objects,
|
22
22
|
})
|
23
|
-
command = env.build_command(env['
|
23
|
+
command = env.build_command(env['ARCMD'], vars)
|
24
24
|
standard_build("AR #{target}", target, command, objects, env, cache)
|
25
25
|
end
|
26
26
|
end
|
@@ -2,17 +2,24 @@ module Rscons
|
|
2
2
|
# A default RScons builder which knows how to produce an object file from
|
3
3
|
# various types of source files.
|
4
4
|
class Object < Builder
|
5
|
+
KNOWN_SUFFIXES = {
|
6
|
+
"AS" => "ASSUFFIX",
|
7
|
+
"CC" => "CSUFFIX",
|
8
|
+
"CXX" => "CXXSUFFIX",
|
9
|
+
"DC" => "DSUFFIX",
|
10
|
+
}
|
11
|
+
|
5
12
|
def default_variables(env)
|
6
13
|
{
|
7
14
|
'OBJSUFFIX' => '.o',
|
8
15
|
|
9
|
-
'AS' => '$CC',
|
16
|
+
'AS' => '${CC}',
|
10
17
|
'ASFLAGS' => [],
|
11
18
|
'ASSUFFIX' => '.S',
|
12
|
-
'ASPPPATH' => '$CPPPATH',
|
13
|
-
'ASPPFLAGS' => '$CPPFLAGS',
|
14
|
-
'ASDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
|
15
|
-
'
|
19
|
+
'ASPPPATH' => '${CPPPATH}',
|
20
|
+
'ASPPFLAGS' => '${CPPFLAGS}',
|
21
|
+
'ASDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
22
|
+
'ASCMD' => ['${AS}', '-c', '-o', '${_TARGET}', '${ASDEPGEN}', '-I${ASPPPATH}', '${ASPPFLAGS}', '${ASFLAGS}', '${_SOURCES}'],
|
16
23
|
|
17
24
|
'CPPFLAGS' => [],
|
18
25
|
'CPPPATH' => [],
|
@@ -20,29 +27,27 @@ module Rscons
|
|
20
27
|
'CC' => 'gcc',
|
21
28
|
'CFLAGS' => [],
|
22
29
|
'CSUFFIX' => '.c',
|
23
|
-
'CCDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
|
24
|
-
'
|
30
|
+
'CCDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
31
|
+
'CCCMD' => ['${CC}', '-c', '-o', '${_TARGET}', '${CCDEPGEN}', '-I${CPPPATH}', '${CPPFLAGS}', '${CFLAGS}', '${_SOURCES}'],
|
25
32
|
|
26
33
|
'CXX' => 'g++',
|
27
34
|
'CXXFLAGS' => [],
|
28
35
|
'CXXSUFFIX' => '.cc',
|
29
|
-
'CXXDEPGEN' => ['-MMD', '-MF', '$_DEPFILE'],
|
30
|
-
'
|
36
|
+
'CXXDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
37
|
+
'CXXCMD' =>['${CXX}', '-c', '-o', '${_TARGET}', '${CXXDEPGEN}', '-I${CPPPATH}', '${CPPFLAGS}', '${CXXFLAGS}', '${_SOURCES}'],
|
31
38
|
|
32
39
|
'DC' => 'gdc',
|
33
40
|
'DFLAGS' => [],
|
34
41
|
'DSUFFIX' => '.d',
|
35
42
|
'D_IMPORT_PATH' => [],
|
36
|
-
'
|
43
|
+
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '-I${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
|
37
44
|
}
|
38
45
|
end
|
39
46
|
|
40
47
|
def produces?(target, source, env)
|
41
|
-
target.has_suffix?(env['OBJSUFFIX']) and
|
42
|
-
source.has_suffix?(env[
|
43
|
-
|
44
|
-
source.has_suffix?(env['CXXSUFFIX']) or
|
45
|
-
source.has_suffix?(env['DSUFFIX']))
|
48
|
+
target.has_suffix?(env['OBJSUFFIX']) and KNOWN_SUFFIXES.find do |compiler, suffix_var|
|
49
|
+
source.has_suffix?(env[suffix_var])
|
50
|
+
end
|
46
51
|
end
|
47
52
|
|
48
53
|
def run(target, sources, cache, env, vars = {})
|
@@ -51,25 +56,19 @@ module Rscons
|
|
51
56
|
'_SOURCES' => sources,
|
52
57
|
'_DEPFILE' => target.set_suffix('.mf'),
|
53
58
|
})
|
54
|
-
com_prefix =
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
elsif sources.first.has_suffix?(env['DSUFFIX'])
|
61
|
-
'DC'
|
62
|
-
else
|
63
|
-
raise "Error: unknown input file type: #{sources.first.inspect}"
|
64
|
-
end
|
65
|
-
command = env.build_command(env["#{com_prefix}COM"], vars)
|
59
|
+
com_prefix = KNOWN_SUFFIXES.find do |compiler, suffix_var|
|
60
|
+
sources.first.has_suffix?(env[suffix_var])
|
61
|
+
end.tap do |v|
|
62
|
+
v.nil? and raise "Error: unknown input file type: #{sources.first.inspect}"
|
63
|
+
end.first
|
64
|
+
command = env.build_command(env["#{com_prefix}CMD"], vars)
|
66
65
|
unless cache.up_to_date?(target, command, sources)
|
67
66
|
cache.mkdir_p(File.dirname(target))
|
68
67
|
FileUtils.rm_f(target)
|
69
68
|
return false unless env.execute("#{com_prefix} #{target}", command)
|
70
69
|
deps = sources
|
71
70
|
if File.exists?(vars['_DEPFILE'])
|
72
|
-
deps +=
|
71
|
+
deps += Environment.parse_makefile_deps(vars['_DEPFILE'], target)
|
73
72
|
FileUtils.rm_f(vars['_DEPFILE'])
|
74
73
|
end
|
75
74
|
cache.register_build(target, command, deps.uniq)
|
@@ -10,31 +10,29 @@ module Rscons
|
|
10
10
|
'LDFLAGS' => [],
|
11
11
|
'LIBPATH' => [],
|
12
12
|
'LIBS' => [],
|
13
|
-
'
|
13
|
+
'LDCMD' => ['${LD}', '-o', '${_TARGET}', '${LDFLAGS}', '${_SOURCES}', '-L${LIBPATH}', '-l${LIBS}']
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
17
17
|
def run(target, sources, cache, env, vars = {})
|
18
18
|
# build sources to linkable objects
|
19
19
|
objects = env.build_sources(sources, [env['OBJSUFFIX'], env['LIBSUFFIX']].flatten, cache, vars)
|
20
|
-
if
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
standard_build("LD #{target}", target, command, objects, env, cache)
|
37
|
-
end
|
20
|
+
ld = if env["LD"]
|
21
|
+
env["LD"]
|
22
|
+
elsif sources.find {|s| s.has_suffix?(env["DSUFFIX"])}
|
23
|
+
env["DC"]
|
24
|
+
elsif sources.find {|s| s.has_suffix?(env["CXXSUFFIX"])}
|
25
|
+
env["CXX"]
|
26
|
+
else
|
27
|
+
env["CC"]
|
28
|
+
end
|
29
|
+
vars = vars.merge({
|
30
|
+
'_TARGET' => target,
|
31
|
+
'_SOURCES' => objects,
|
32
|
+
'LD' => ld,
|
33
|
+
})
|
34
|
+
command = env.build_command(env['LDCMD'], vars)
|
35
|
+
standard_build("LD #{target}", target, command, objects, env, cache)
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
data/lib/rscons/cache.rb
CHANGED
@@ -67,12 +67,12 @@ module Rscons
|
|
67
67
|
end
|
68
68
|
@cache[:targets] ||= {}
|
69
69
|
@cache[:directories] ||= {}
|
70
|
-
@cache[:version] ||= VERSION
|
71
70
|
@lookup_checksums = {}
|
72
71
|
end
|
73
72
|
|
74
73
|
# Write the cache to disk to be loaded next time.
|
75
74
|
def write
|
75
|
+
@cache[:version] = VERSION
|
76
76
|
File.open(CACHE_FILE, 'w') do |fh|
|
77
77
|
fh.puts(YAML.dump(@cache))
|
78
78
|
end
|
@@ -119,9 +119,11 @@ module Rscons
|
|
119
119
|
end
|
120
120
|
|
121
121
|
# all cached dependencies must have their checksums match
|
122
|
-
@cache[:targets][target][:deps].
|
123
|
-
dep_cache[:checksum] == lookup_checksum(dep_cache[:fname])
|
124
|
-
end
|
122
|
+
@cache[:targets][target][:deps].each do |dep_cache|
|
123
|
+
return false unless dep_cache[:checksum] == lookup_checksum(dep_cache[:fname])
|
124
|
+
end
|
125
|
+
|
126
|
+
true
|
125
127
|
end
|
126
128
|
|
127
129
|
# Store cache information about a target built by a builder
|
@@ -150,13 +152,11 @@ module Rscons
|
|
150
152
|
# removal upon a "clean" operation.
|
151
153
|
def mkdir_p(path)
|
152
154
|
parts = path.split(/[\\\/]/)
|
153
|
-
(0..parts.size).each do |i|
|
155
|
+
(0..parts.size-1).each do |i|
|
154
156
|
subpath = File.join(*parts[0, i + 1]).encode(__ENCODING__)
|
155
157
|
unless File.exists?(subpath)
|
156
158
|
FileUtils.mkdir(subpath)
|
157
|
-
|
158
|
-
@cache[:directories][subpath] = true
|
159
|
-
end
|
159
|
+
@cache[:directories][subpath] = true
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
@@ -179,7 +179,7 @@ module Rscons
|
|
179
179
|
# Calculate and return a file's checksum
|
180
180
|
# @param file [String] The file name.
|
181
181
|
def calculate_checksum(file)
|
182
|
-
@lookup_checksums[file] = Digest::MD5.hexdigest(File.read(file,
|
182
|
+
@lookup_checksums[file] = Digest::MD5.hexdigest(File.read(file, mode: 'rb')).encode(__ENCODING__) rescue ''
|
183
183
|
end
|
184
184
|
end
|
185
185
|
end
|
data/lib/rscons/environment.rb
CHANGED
@@ -6,7 +6,7 @@ module Rscons
|
|
6
6
|
# contains a collection of construction variables, options, builders, and
|
7
7
|
# rules for building targets.
|
8
8
|
class Environment
|
9
|
-
#
|
9
|
+
# Hash of +{"builder_name" => builder_object}+ pairs.
|
10
10
|
attr_reader :builders
|
11
11
|
|
12
12
|
# Create an Environment object.
|
@@ -22,7 +22,7 @@ module Rscons
|
|
22
22
|
@targets = {}
|
23
23
|
@builders = {}
|
24
24
|
@build_dirs = []
|
25
|
-
@
|
25
|
+
@build_hooks = []
|
26
26
|
@varset[:exclude_builders] ||= []
|
27
27
|
unless @varset[:exclude_builders] == :all
|
28
28
|
exclude_builders = Set.new(@varset[:exclude_builders] || [])
|
@@ -32,10 +32,7 @@ module Rscons
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
add_builder(builder)
|
37
|
-
end
|
38
|
-
@varset[:echo] ||= :command
|
35
|
+
@varset[:echo] ||= :short
|
39
36
|
|
40
37
|
if block_given?
|
41
38
|
yield self
|
@@ -46,7 +43,7 @@ module Rscons
|
|
46
43
|
# Make a copy of the Environment object.
|
47
44
|
# The cloned environment will contain a copy of all environment options,
|
48
45
|
# construction variables, builders, and build directories. It will not
|
49
|
-
# contain a copy of the targets or
|
46
|
+
# contain a copy of the targets or build hooks.
|
50
47
|
# If a block is given, the Environment object is yielded to the block and
|
51
48
|
# when the block returns, the {#process} method is automatically called.
|
52
49
|
def clone(variables = {})
|
@@ -75,9 +72,9 @@ module Rscons
|
|
75
72
|
end
|
76
73
|
end
|
77
74
|
|
78
|
-
# Add a
|
79
|
-
def
|
80
|
-
@
|
75
|
+
# Add a build hook to the Environment.
|
76
|
+
def add_build_hook(&block)
|
77
|
+
@build_hooks << block
|
81
78
|
end
|
82
79
|
|
83
80
|
# Specify a build directory for this Environment.
|
@@ -89,8 +86,6 @@ module Rscons
|
|
89
86
|
|
90
87
|
# Return the file name to be built from source_fname with suffix suffix.
|
91
88
|
# This method takes into account the Environment's build directories.
|
92
|
-
# It also creates any parent directories needed to be able to open and
|
93
|
-
# write to the output file.
|
94
89
|
def get_build_fname(source_fname, suffix)
|
95
90
|
build_fname = source_fname.set_suffix(suffix).gsub('\\', '/')
|
96
91
|
@build_dirs.each do |src_dir, obj_dir|
|
@@ -122,41 +117,33 @@ module Rscons
|
|
122
117
|
@varset.send(:append, *args)
|
123
118
|
end
|
124
119
|
|
125
|
-
# Return a list of target file names
|
126
|
-
def targets
|
127
|
-
@targets.keys
|
128
|
-
end
|
129
|
-
|
130
|
-
# Return a list of sources needed to build target target.
|
131
|
-
def target_sources(target)
|
132
|
-
@targets[target][:source] rescue nil
|
133
|
-
end
|
134
|
-
|
135
120
|
# Build all target specified in the Environment.
|
136
121
|
# When a block is passed to Environment.new, this method is automatically
|
137
122
|
# called after the block returns.
|
138
123
|
def process
|
139
124
|
cache = Cache.new
|
140
|
-
targets_processed =
|
125
|
+
targets_processed = {}
|
141
126
|
process_target = proc do |target|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
127
|
+
targets_processed[target] ||= begin
|
128
|
+
@targets[target][:source].each do |src|
|
129
|
+
if @targets.include?(src) and not targets_processed.include?(src)
|
130
|
+
process_target.call(src)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
result = run_builder(@targets[target][:builder],
|
134
|
+
target,
|
135
|
+
@targets[target][:source],
|
136
|
+
cache,
|
137
|
+
@targets[target][:vars] || {})
|
138
|
+
unless result
|
139
|
+
cache.write
|
140
|
+
raise BuildError.new("Failed to build #{target}")
|
141
|
+
end
|
142
|
+
result
|
152
143
|
end
|
153
144
|
end
|
154
145
|
@targets.each do |target, info|
|
155
|
-
|
156
|
-
unless process_target.call(target)
|
157
|
-
cache.write
|
158
|
-
raise BuildError.new("Failed to build #{target}")
|
159
|
-
end
|
146
|
+
process_target.call(target)
|
160
147
|
end
|
161
148
|
cache.write
|
162
149
|
end
|
@@ -177,7 +164,7 @@ module Rscons
|
|
177
164
|
# @param short_desc [String] Message to print if the Environment's :echo
|
178
165
|
# mode is set to :short
|
179
166
|
# @param command [Array] The command to execute.
|
180
|
-
# @param options [Hash] Optional options to pass to
|
167
|
+
# @param options [Hash] Optional options to pass to Kernel#system.
|
181
168
|
def execute(short_desc, command, options = {})
|
182
169
|
print_command = proc do
|
183
170
|
puts command.map { |c| c =~ /\s/ ? "'#{c}'" : c }.join(' ')
|
@@ -214,30 +201,6 @@ module Rscons
|
|
214
201
|
end
|
215
202
|
end
|
216
203
|
|
217
|
-
# Parse dependencies for a given target from a Makefile.
|
218
|
-
# This method is used internally by RScons builders.
|
219
|
-
# @param mf_fname [String] File name of the Makefile to read.
|
220
|
-
# @param target [String] Name of the target to gather dependencies for.
|
221
|
-
def parse_makefile_deps(mf_fname, target)
|
222
|
-
deps = []
|
223
|
-
buildup = ''
|
224
|
-
File.read(mf_fname).each_line do |line|
|
225
|
-
if line =~ /^(.*)\\\s*$/
|
226
|
-
buildup += ' ' + $1
|
227
|
-
else
|
228
|
-
buildup += ' ' + line
|
229
|
-
if buildup =~ /^(.*): (.*)$/
|
230
|
-
mf_target, mf_deps = $1.strip, $2
|
231
|
-
if mf_target == target
|
232
|
-
deps += mf_deps.split(' ').map(&:strip)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
buildup = ''
|
236
|
-
end
|
237
|
-
end
|
238
|
-
deps
|
239
|
-
end
|
240
|
-
|
241
204
|
# Build a list of source files into files containing one of the suffixes
|
242
205
|
# given by suffixes.
|
243
206
|
# This method is used internally by RScons builders.
|
@@ -275,16 +238,40 @@ module Rscons
|
|
275
238
|
# Return the result of the builder's run() method.
|
276
239
|
def run_builder(builder, target, sources, cache, vars)
|
277
240
|
vars = @varset.merge(vars)
|
278
|
-
@
|
241
|
+
@build_hooks.each do |build_hook_block|
|
279
242
|
build_operation = {
|
280
243
|
builder: builder,
|
281
244
|
target: target,
|
282
245
|
sources: sources,
|
283
246
|
vars: vars,
|
284
247
|
}
|
285
|
-
|
248
|
+
build_hook_block.call(build_operation)
|
286
249
|
end
|
287
250
|
builder.run(target, sources, cache, self, vars)
|
288
251
|
end
|
252
|
+
|
253
|
+
# Parse dependencies for a given target from a Makefile.
|
254
|
+
# This method is used internally by RScons builders.
|
255
|
+
# @param mf_fname [String] File name of the Makefile to read.
|
256
|
+
# @param target [String] Name of the target to gather dependencies for.
|
257
|
+
def self.parse_makefile_deps(mf_fname, target)
|
258
|
+
deps = []
|
259
|
+
buildup = ''
|
260
|
+
File.read(mf_fname).each_line do |line|
|
261
|
+
if line =~ /^(.*)\\\s*$/
|
262
|
+
buildup += ' ' + $1
|
263
|
+
else
|
264
|
+
buildup += ' ' + line
|
265
|
+
if buildup =~ /^(.*): (.*)$/
|
266
|
+
mf_target, mf_deps = $1.strip, $2
|
267
|
+
if mf_target == target
|
268
|
+
deps += mf_deps.split(' ').map(&:strip)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
buildup = ''
|
272
|
+
end
|
273
|
+
end
|
274
|
+
deps
|
275
|
+
end
|
289
276
|
end
|
290
277
|
end
|