rscons 1.15.0 → 1.19.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/rscons +2 -0
- data/lib/rscons.rb +36 -0
- data/lib/rscons/builders/install.rb +1 -0
- data/lib/rscons/builders/object.rb +3 -2
- data/lib/rscons/builders/preprocess.rb +1 -1
- data/lib/rscons/builders/shared_object.rb +1 -1
- data/lib/rscons/cache.rb +67 -29
- data/lib/rscons/cli.rb +6 -0
- data/lib/rscons/environment.rb +52 -21
- data/lib/rscons/util.rb +34 -0
- data/lib/rscons/varset.rb +73 -27
- data/lib/rscons/version.rb +1 -1
- data/rscons.gemspec +1 -2
- metadata +8 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dda25ef5e4dd644cd868bb86d6fc3ba9230f694ea7bf0c31577f5ab687c8409f
|
4
|
+
data.tar.gz: e8993bd5dc123252060eef9ba22da1750d1ae0162ce20ad17a6d6b52096cd959
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a19b6cde13d0b98aaeee43e55ef525da74bd2f0376788ac871d69186d4e511d606193a7c5f81255547273e05b1d2e7334f4a5f4639ff461f9ce3e89eb1f08fe6
|
7
|
+
data.tar.gz: 91f7d0caebfeb99ec2245b00c76ce4693312fce401987995b13200c28ebb08de2c7c7310a76ad9a9397090cb80c4db361d021edac571d8d931b06c56e02765b2
|
data/bin/rscons
CHANGED
data/lib/rscons.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative "rscons/cache"
|
|
5
5
|
require_relative "rscons/environment"
|
6
6
|
require_relative "rscons/job_set"
|
7
7
|
require_relative "rscons/threaded_command"
|
8
|
+
require_relative "rscons/util"
|
8
9
|
require_relative "rscons/varset"
|
9
10
|
require_relative "rscons/version"
|
10
11
|
|
@@ -55,6 +56,11 @@ module Rscons
|
|
55
56
|
# Whether to output ANSI color escape sequences.
|
56
57
|
attr_accessor :do_ansi_color
|
57
58
|
|
59
|
+
# @since 1.16.0
|
60
|
+
# @return [VarSet]
|
61
|
+
# Access any variables set on the rscons command-line.
|
62
|
+
attr_reader :vars
|
63
|
+
|
58
64
|
# Remove all generated files.
|
59
65
|
#
|
60
66
|
# @return [void]
|
@@ -165,6 +171,35 @@ module Rscons
|
|
165
171
|
@command_executer = val
|
166
172
|
end
|
167
173
|
|
174
|
+
# Return a list of paths matching the specified pattern(s).
|
175
|
+
#
|
176
|
+
# @since 1.16.0
|
177
|
+
#
|
178
|
+
# A pattern can contain a "/**" component to recurse through directories.
|
179
|
+
# If the pattern ends with "/**" then only the recursive list of
|
180
|
+
# directories will be returned.
|
181
|
+
#
|
182
|
+
# Examples:
|
183
|
+
# - "src/**": return all directories under "src", recursively (including
|
184
|
+
# "src" itself).
|
185
|
+
# - "src/**/*": return all files and directories recursively under the src
|
186
|
+
# directory.
|
187
|
+
# - "src/**/*.c": return all .c files recursively under the src directory.
|
188
|
+
# - "dir/*/": return all directories in dir, but no files.
|
189
|
+
#
|
190
|
+
# @return [Array<String>] Paths matching the specified pattern(s).
|
191
|
+
def glob(*patterns)
|
192
|
+
require "pathname"
|
193
|
+
patterns.reduce([]) do |result, pattern|
|
194
|
+
if pattern.end_with?("/**")
|
195
|
+
pattern += "/"
|
196
|
+
end
|
197
|
+
result += Dir.glob(pattern).map do |path|
|
198
|
+
Pathname.new(path.gsub("\\", "/")).cleanpath.to_s
|
199
|
+
end
|
200
|
+
end.sort
|
201
|
+
end
|
202
|
+
|
168
203
|
private
|
169
204
|
|
170
205
|
# Determine the number of threads to use by default.
|
@@ -203,6 +238,7 @@ module Rscons
|
|
203
238
|
end
|
204
239
|
|
205
240
|
@n_threads = determine_n_threads
|
241
|
+
@vars = VarSet.new
|
206
242
|
|
207
243
|
end
|
208
244
|
|
@@ -54,8 +54,9 @@ module Rscons
|
|
54
54
|
'DC' => 'gdc',
|
55
55
|
'DFLAGS' => [],
|
56
56
|
'DSUFFIX' => ['.d'],
|
57
|
+
'DDEPGEN' => ['-MMD', '-MF', '${_DEPFILE}'],
|
57
58
|
'D_IMPORT_PATH' => [],
|
58
|
-
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
|
59
|
+
'DCCMD' => ['${DC}', '-c', '-o', '${_TARGET}', '${DDEPGEN}', '${INCPREFIX}${D_IMPORT_PATH}', '${DFLAGS}', '${_SOURCES}'],
|
59
60
|
}
|
60
61
|
end
|
61
62
|
|
@@ -114,7 +115,7 @@ module Rscons
|
|
114
115
|
if options[:command_status]
|
115
116
|
target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
|
116
117
|
if File.exists?(vars['_DEPFILE'])
|
117
|
-
deps += Environment.parse_makefile_deps(vars['_DEPFILE']
|
118
|
+
deps += Environment.parse_makefile_deps(vars['_DEPFILE'])
|
118
119
|
FileUtils.rm_f(vars['_DEPFILE'])
|
119
120
|
end
|
120
121
|
cache.register_build(target, options[:tc].command, deps.uniq, env)
|
@@ -55,7 +55,7 @@ module Rscons
|
|
55
55
|
if options[:command_status]
|
56
56
|
target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
|
57
57
|
if File.exists?(vars['_DEPFILE'])
|
58
|
-
deps += Environment.parse_makefile_deps(vars['_DEPFILE']
|
58
|
+
deps += Environment.parse_makefile_deps(vars['_DEPFILE'])
|
59
59
|
FileUtils.rm_f(vars['_DEPFILE'])
|
60
60
|
end
|
61
61
|
cache.register_build(target, options[:tc].command, deps.uniq, env)
|
@@ -100,7 +100,7 @@ module Rscons
|
|
100
100
|
if options[:command_status]
|
101
101
|
target, deps, cache, env, vars = options.values_at(:target, :sources, :cache, :env, :vars)
|
102
102
|
if File.exists?(vars['_DEPFILE'])
|
103
|
-
deps += Environment.parse_makefile_deps(vars['_DEPFILE']
|
103
|
+
deps += Environment.parse_makefile_deps(vars['_DEPFILE'])
|
104
104
|
FileUtils.rm_f(vars['_DEPFILE'])
|
105
105
|
end
|
106
106
|
cache.register_build(target, options[:tc].command, deps.uniq, env)
|
data/lib/rscons/cache.rb
CHANGED
@@ -85,17 +85,14 @@ module Rscons
|
|
85
85
|
@lookup_checksums = {}
|
86
86
|
end
|
87
87
|
|
88
|
-
# Write the cache to disk
|
88
|
+
# Write the cache to disk.
|
89
89
|
#
|
90
90
|
# @return [void]
|
91
91
|
def write
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
fh.puts(JSON.dump(@cache))
|
96
|
-
end
|
92
|
+
@cache["version"] = VERSION
|
93
|
+
File.open(CACHE_FILE, "w") do |fh|
|
94
|
+
fh.puts(JSON.dump(@cache))
|
97
95
|
end
|
98
|
-
@dirty = false
|
99
96
|
end
|
100
97
|
|
101
98
|
# Check if target(s) are up to date.
|
@@ -111,6 +108,10 @@ module Rscons
|
|
111
108
|
# @param deps [Array<String>] List of the target's dependency files.
|
112
109
|
# @param env [Environment] The Rscons::Environment.
|
113
110
|
# @param options [Hash] Optional options.
|
111
|
+
# @option options [Boolean] :debug
|
112
|
+
# If turned on, this causes the Cache to print messages explaining why
|
113
|
+
# a build target is out of date. This could aid a builder author in
|
114
|
+
# debugging the operation of their builder.
|
114
115
|
# @option options [Boolean] :strict_deps
|
115
116
|
# Only consider a target up to date if its list of dependencies is
|
116
117
|
# exactly equal (including order) to the cached list of dependencies
|
@@ -133,39 +134,79 @@ module Rscons
|
|
133
134
|
|
134
135
|
unless Rscons.phony_target?(target)
|
135
136
|
# target file must exist on disk
|
136
|
-
|
137
|
+
unless File.exists?(target)
|
138
|
+
if options[:debug]
|
139
|
+
puts "Target #{target} needs rebuilding because it does not exist on disk"
|
140
|
+
end
|
141
|
+
return false
|
142
|
+
end
|
137
143
|
end
|
138
144
|
|
139
145
|
# target must be registered in the cache
|
140
|
-
|
146
|
+
unless @cache["targets"].has_key?(cache_key)
|
147
|
+
if options[:debug]
|
148
|
+
puts "Target #{target} needs rebuilding because there is no cached build information for it"
|
149
|
+
end
|
150
|
+
return false
|
151
|
+
end
|
141
152
|
|
142
153
|
unless Rscons.phony_target?(target)
|
143
154
|
# target must have the same checksum as when it was built last
|
144
|
-
|
155
|
+
unless @cache["targets"][cache_key]["checksum"] == lookup_checksum(target)
|
156
|
+
if options[:debug]
|
157
|
+
puts "Target #{target} needs rebuilding because it has been changed on disk since being built last"
|
158
|
+
end
|
159
|
+
return false
|
160
|
+
end
|
145
161
|
end
|
146
162
|
|
147
163
|
# command used to build target must be identical
|
148
|
-
|
164
|
+
unless @cache["targets"][cache_key]["command"] == Digest::MD5.hexdigest(command.inspect)
|
165
|
+
if options[:debug]
|
166
|
+
puts "Target #{target} needs rebuilding because the command used to build it has changed"
|
167
|
+
end
|
168
|
+
return false
|
169
|
+
end
|
149
170
|
|
150
171
|
cached_deps = @cache["targets"][cache_key]["deps"] || []
|
151
172
|
cached_deps_fnames = cached_deps.map { |dc| dc["fname"] }
|
152
173
|
if options[:strict_deps]
|
153
174
|
# depedencies passed in must exactly equal those in the cache
|
154
|
-
|
175
|
+
unless deps == cached_deps_fnames
|
176
|
+
if options[:debug]
|
177
|
+
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"
|
178
|
+
end
|
179
|
+
return false
|
180
|
+
end
|
155
181
|
else
|
156
182
|
# all dependencies passed in must exist in cache (but cache may have more)
|
157
|
-
|
183
|
+
unless (Set.new(deps) - Set.new(cached_deps_fnames)).empty?
|
184
|
+
if options[:debug]
|
185
|
+
puts "Target #{target} needs rebuilding because there are new dependencies"
|
186
|
+
end
|
187
|
+
return false
|
188
|
+
end
|
158
189
|
end
|
159
190
|
|
160
191
|
# set of user dependencies must match
|
161
192
|
user_deps = env.get_user_deps(target) || []
|
162
193
|
cached_user_deps = @cache["targets"][cache_key]["user_deps"] || []
|
163
194
|
cached_user_deps_fnames = cached_user_deps.map { |dc| dc["fname"] }
|
164
|
-
|
195
|
+
unless user_deps == cached_user_deps_fnames
|
196
|
+
if options[:debug]
|
197
|
+
puts "Target #{target} needs rebuilding because the set of user-specified dependency files has changed"
|
198
|
+
end
|
199
|
+
return false
|
200
|
+
end
|
165
201
|
|
166
202
|
# all cached dependencies must have their checksums match
|
167
203
|
(cached_deps + cached_user_deps).each do |dep_cache|
|
168
|
-
|
204
|
+
unless dep_cache["checksum"] == lookup_checksum(dep_cache["fname"])
|
205
|
+
if options[:debug]
|
206
|
+
puts "Target #{target} needs rebuilding because dependency file #{dep_cache["fname"]} has changed"
|
207
|
+
end
|
208
|
+
return false
|
209
|
+
end
|
169
210
|
end
|
170
211
|
end
|
171
212
|
|
@@ -205,7 +246,6 @@ module Rscons
|
|
205
246
|
}
|
206
247
|
end,
|
207
248
|
}
|
208
|
-
@dirty = true
|
209
249
|
end
|
210
250
|
end
|
211
251
|
|
@@ -228,9 +268,8 @@ module Rscons
|
|
228
268
|
next if parts[i] == ""
|
229
269
|
subpath = File.join(*parts[0, i + 1])
|
230
270
|
unless File.exists?(subpath)
|
231
|
-
FileUtils.
|
271
|
+
FileUtils.mkdir_p(subpath)
|
232
272
|
@cache["directories"][subpath] = true
|
233
|
-
@dirty = true
|
234
273
|
end
|
235
274
|
end
|
236
275
|
end
|
@@ -243,6 +282,16 @@ module Rscons
|
|
243
282
|
@cache["directories"].keys
|
244
283
|
end
|
245
284
|
|
285
|
+
# Return a file's checksum, or the previously calculated checksum for
|
286
|
+
# the same file.
|
287
|
+
#
|
288
|
+
# @param file [String] The file name.
|
289
|
+
#
|
290
|
+
# @return [String] The file's checksum.
|
291
|
+
def lookup_checksum(file)
|
292
|
+
@lookup_checksums[file] || calculate_checksum(file)
|
293
|
+
end
|
294
|
+
|
246
295
|
private
|
247
296
|
|
248
297
|
# Return a String key based on the target name to use in the on-disk cache.
|
@@ -271,17 +320,6 @@ module Rscons
|
|
271
320
|
@cache["targets"] ||= {}
|
272
321
|
@cache["directories"] ||= {}
|
273
322
|
@lookup_checksums = {}
|
274
|
-
@dirty = false
|
275
|
-
end
|
276
|
-
|
277
|
-
# Return a file's checksum, or the previously calculated checksum for
|
278
|
-
# the same file.
|
279
|
-
#
|
280
|
-
# @param file [String] The file name.
|
281
|
-
#
|
282
|
-
# @return [String] The file's checksum.
|
283
|
-
def lookup_checksum(file)
|
284
|
-
@lookup_checksums[file] || calculate_checksum(file)
|
285
323
|
end
|
286
324
|
|
287
325
|
# Calculate and return a file's checksum.
|
data/lib/rscons/cli.rb
CHANGED
data/lib/rscons/environment.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require "set"
|
3
3
|
require "shellwords"
|
4
|
-
require "thwait"
|
5
4
|
|
6
5
|
module Rscons
|
7
6
|
# The Environment class is the main programmatic interface to Rscons. It
|
@@ -280,6 +279,24 @@ module Rscons
|
|
280
279
|
@varset.send(:[], *args)
|
281
280
|
end
|
282
281
|
|
282
|
+
# Access the value of a construction variable.
|
283
|
+
#
|
284
|
+
# @since 1.18.0
|
285
|
+
#
|
286
|
+
# This method is similar to #[] but does not make a copy-on-access copy of
|
287
|
+
# the variable accessed. This means that the returned value is NOT safe to
|
288
|
+
# be modified by the caller. Thus the caller must guarantee that it does
|
289
|
+
# not modify the returned value.
|
290
|
+
#
|
291
|
+
# @param key [String, Symbol]
|
292
|
+
# The construction variable name.
|
293
|
+
#
|
294
|
+
# @return [Object]
|
295
|
+
# The construction variable's value.
|
296
|
+
def get_var(key)
|
297
|
+
@varset.get_var(key)
|
298
|
+
end
|
299
|
+
|
283
300
|
# Set a construction variable's value.
|
284
301
|
#
|
285
302
|
# @see VarSet#[]=
|
@@ -323,6 +340,7 @@ module Rscons
|
|
323
340
|
cache.clear_checksum_cache!
|
324
341
|
|
325
342
|
if job
|
343
|
+
validate_user_deps(job[:target], @user_deps[job[:target]], cache)
|
326
344
|
result = run_builder(job[:builder],
|
327
345
|
job[:target],
|
328
346
|
job[:sources],
|
@@ -385,12 +403,12 @@ module Rscons
|
|
385
403
|
|
386
404
|
# Expand a construction variable reference.
|
387
405
|
#
|
388
|
-
# @param varref [Array,
|
406
|
+
# @param varref [nil, String, Array, Proc, Symbol, TrueClass, FalseClass] Variable reference to expand.
|
389
407
|
# @param extra_vars [Hash, VarSet]
|
390
408
|
# Extra variables to use in addition to (or replace) the Environment's
|
391
409
|
# construction variables when expanding the variable reference.
|
392
410
|
#
|
393
|
-
# @return [Array,
|
411
|
+
# @return [nil, String, Array, Symbol, TrueClass, FalseClass] Expansion of the variable reference.
|
394
412
|
def expand_varref(varref, extra_vars = nil)
|
395
413
|
vars = if extra_vars.nil?
|
396
414
|
@varset
|
@@ -782,7 +800,7 @@ module Rscons
|
|
782
800
|
append["LDFLAGS", ["-arch", val]]
|
783
801
|
end
|
784
802
|
skip = true
|
785
|
-
elsif word =~ /^#{
|
803
|
+
elsif word =~ /^#{get_var("CPPDEFPREFIX")}(.*)$/
|
786
804
|
handle["CPPDEFINES", $1]
|
787
805
|
elsif word == "-include"
|
788
806
|
if val = words[i + 1]
|
@@ -795,11 +813,11 @@ module Rscons
|
|
795
813
|
append["LDFLAGS", ["-isysroot", val]]
|
796
814
|
end
|
797
815
|
skip = true
|
798
|
-
elsif word =~ /^#{
|
816
|
+
elsif word =~ /^#{get_var("INCPREFIX")}(.*)$/
|
799
817
|
handle["CPPPATH", $1]
|
800
|
-
elsif word =~ /^#{
|
818
|
+
elsif word =~ /^#{get_var("LIBLINKPREFIX")}(.*)$/
|
801
819
|
handle["LIBS", $1]
|
802
|
-
elsif word =~ /^#{
|
820
|
+
elsif word =~ /^#{get_var("LIBDIRPREFIX")}(.*)$/
|
803
821
|
handle["LIBPATH", $1]
|
804
822
|
elsif word == "-mno-cygwin"
|
805
823
|
append["CCFLAGS", [word]]
|
@@ -848,7 +866,7 @@ module Rscons
|
|
848
866
|
# @return [void]
|
849
867
|
def merge_flags(flags)
|
850
868
|
flags.each_pair do |key, val|
|
851
|
-
if self
|
869
|
+
if self.get_var(key).is_a?(Array) and val.is_a?(Array)
|
852
870
|
self[key] += val
|
853
871
|
else
|
854
872
|
self[key] = val
|
@@ -993,10 +1011,7 @@ module Rscons
|
|
993
1011
|
!thread.alive?
|
994
1012
|
end
|
995
1013
|
else
|
996
|
-
|
997
|
-
raise "No threads to wait for"
|
998
|
-
end
|
999
|
-
ThreadsWait.new(*threads).next_wait
|
1014
|
+
Util.wait_for_thread(*threads)
|
1000
1015
|
end
|
1001
1016
|
end
|
1002
1017
|
|
@@ -1065,16 +1080,14 @@ module Rscons
|
|
1065
1080
|
end
|
1066
1081
|
end
|
1067
1082
|
|
1068
|
-
# Parse dependencies
|
1083
|
+
# Parse dependencies from a Makefile.
|
1069
1084
|
#
|
1070
1085
|
# This method is used internally by Rscons builders.
|
1071
1086
|
#
|
1072
1087
|
# @param mf_fname [String] File name of the Makefile to read.
|
1073
|
-
# @param target [String, nil]
|
1074
|
-
# Name of the target to gather dependencies for, nil for any/all.
|
1075
1088
|
#
|
1076
1089
|
# @return [Array<String>] Paths of dependency files.
|
1077
|
-
def self.parse_makefile_deps(mf_fname
|
1090
|
+
def self.parse_makefile_deps(mf_fname)
|
1078
1091
|
deps = []
|
1079
1092
|
buildup = ''
|
1080
1093
|
File.read(mf_fname).each_line do |line|
|
@@ -1082,16 +1095,34 @@ module Rscons
|
|
1082
1095
|
buildup += ' ' + $1
|
1083
1096
|
else
|
1084
1097
|
buildup += ' ' + line
|
1085
|
-
if buildup =~
|
1086
|
-
|
1087
|
-
|
1088
|
-
deps += mf_deps.split(' ').map(&:strip)
|
1089
|
-
end
|
1098
|
+
if buildup =~ /^.*: (.*)$/
|
1099
|
+
mf_deps = $1
|
1100
|
+
deps += mf_deps.split(' ').map(&:strip)
|
1090
1101
|
end
|
1091
1102
|
buildup = ''
|
1092
1103
|
end
|
1093
1104
|
end
|
1094
1105
|
deps
|
1095
1106
|
end
|
1107
|
+
|
1108
|
+
# Ensures that user dependencies exist with valid checksums in the
|
1109
|
+
# cache. Raises an exception if any dependency is invalid.
|
1110
|
+
#
|
1111
|
+
# @param target [String]
|
1112
|
+
# Target to be built
|
1113
|
+
# @param user_deps [Array<String>, nil]
|
1114
|
+
# User dependencies of the target
|
1115
|
+
# @param cache [Cache]
|
1116
|
+
# Rscons cache instance
|
1117
|
+
#
|
1118
|
+
# @return [void]
|
1119
|
+
def validate_user_deps(target, user_deps, cache)
|
1120
|
+
return if user_deps.nil?
|
1121
|
+
user_deps.each do |dep|
|
1122
|
+
if cache.lookup_checksum(dep) == ""
|
1123
|
+
raise "User dependency #{dep} of target #{target} is invalid"
|
1124
|
+
end
|
1125
|
+
end
|
1126
|
+
end
|
1096
1127
|
end
|
1097
1128
|
end
|
data/lib/rscons/util.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rscons
|
2
|
+
# A collection of stand-alone utility methods.
|
3
|
+
module Util
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Wait for any of a number of threads to complete.
|
7
|
+
#
|
8
|
+
# @param threads [Array<Thread>]
|
9
|
+
# Threads to wait for.
|
10
|
+
#
|
11
|
+
# @return [Thread]
|
12
|
+
# The Thread that completed.
|
13
|
+
def wait_for_thread(*threads)
|
14
|
+
if threads.empty?
|
15
|
+
raise "No threads to wait for"
|
16
|
+
end
|
17
|
+
queue = Queue.new
|
18
|
+
threads.each do |thread|
|
19
|
+
# Create a wait thread for each thread we're waiting for.
|
20
|
+
Thread.new do
|
21
|
+
begin
|
22
|
+
thread.join
|
23
|
+
ensure
|
24
|
+
queue.push(thread)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# Wait for any thread to complete.
|
29
|
+
queue.pop
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rscons/varset.rb
CHANGED
@@ -11,11 +11,13 @@ module Rscons
|
|
11
11
|
append(vars)
|
12
12
|
end
|
13
13
|
|
14
|
-
# Access the value of variable.
|
14
|
+
# Access the value of a variable.
|
15
15
|
#
|
16
|
-
# @param key [String, Symbol]
|
16
|
+
# @param key [String, Symbol]
|
17
|
+
# The variable name.
|
17
18
|
#
|
18
|
-
# @return [Object]
|
19
|
+
# @return [Object]
|
20
|
+
# The variable's value.
|
19
21
|
def [](key)
|
20
22
|
if @my_vars.include?(key)
|
21
23
|
@my_vars[key]
|
@@ -30,11 +32,38 @@ module Rscons
|
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
35
|
+
# Access the value of a variable.
|
36
|
+
#
|
37
|
+
# This method is similar to #[] but does not make a copy-on-access copy of
|
38
|
+
# the variable accessed. This means that the returned value is NOT safe to
|
39
|
+
# be modified by the caller. Thus the caller must guarantee that it does
|
40
|
+
# not modify the returned value.
|
41
|
+
#
|
42
|
+
# @param key [String, Symbol]
|
43
|
+
# The variable name.
|
44
|
+
#
|
45
|
+
# @return [Object]
|
46
|
+
# The variable's value.
|
47
|
+
def get_var(key)
|
48
|
+
if @my_vars.include?(key)
|
49
|
+
@my_vars[key]
|
50
|
+
else
|
51
|
+
@coa_vars.each do |coa_vars|
|
52
|
+
if coa_vars.include?(key)
|
53
|
+
return coa_vars[key]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
33
60
|
# Assign a value to a variable.
|
34
61
|
#
|
35
|
-
# @param key [String, Symbol]
|
62
|
+
# @param key [String, Symbol]
|
63
|
+
# The variable name.
|
36
64
|
#
|
37
|
-
# @param val [Object]
|
65
|
+
# @param val [Object]
|
66
|
+
# The value to set.
|
38
67
|
def []=(key, val)
|
39
68
|
@my_vars[key] = val
|
40
69
|
end
|
@@ -86,40 +115,50 @@ module Rscons
|
|
86
115
|
# Replace "$!{var}" variable references in varref with the expanded
|
87
116
|
# variables' values, recursively.
|
88
117
|
#
|
89
|
-
# @param varref [nil, String, Array, Proc]
|
118
|
+
# @param varref [nil, String, Array, Proc, Symbol, TrueClass, FalseClass]
|
90
119
|
# Value containing references to variables.
|
91
120
|
# @param lambda_args [Array]
|
92
121
|
# Arguments to pass to any lambda variable values to be expanded.
|
93
122
|
#
|
94
|
-
# @return [nil, String, Array]
|
123
|
+
# @return [nil, String, Array, Symbol, TrueClass, FalseClass]
|
95
124
|
# Expanded value with "$!{var}" variable references replaced.
|
96
125
|
def expand_varref(varref, lambda_args)
|
97
|
-
|
126
|
+
case varref
|
127
|
+
when String
|
98
128
|
if varref =~ /^(.*)\$\{([^}]+)\}(.*)$/
|
99
129
|
prefix, varname, suffix = $1, $2, $3
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
130
|
+
prefix = expand_varref(prefix, lambda_args) unless prefix.empty?
|
131
|
+
varval = expand_varref(get_var(varname), lambda_args)
|
132
|
+
# suffix needs no expansion since the regex matches the last occurence
|
133
|
+
case varval
|
134
|
+
when Array
|
135
|
+
if prefix.is_a?(Array)
|
136
|
+
varval.map {|vv| prefix.map {|p| "#{p}#{vv}#{suffix}"}}.flatten
|
137
|
+
else
|
138
|
+
varval.map {|vv| "#{prefix}#{vv}#{suffix}"}
|
139
|
+
end
|
140
|
+
when String, Symbol, true, false, nil
|
141
|
+
if prefix.is_a?(Array)
|
142
|
+
prefix.map {|p| "#{p}#{varval}#{suffix}"}
|
143
|
+
else
|
144
|
+
"#{prefix}#{varval}#{suffix}"
|
145
|
+
end
|
105
146
|
else
|
106
|
-
raise "
|
147
|
+
raise "Unknown construction variable type: #{varval.class} (from #{varname.inspect} => #{get_var(varname).inspect})"
|
107
148
|
end
|
108
149
|
else
|
109
150
|
varref
|
110
151
|
end
|
111
|
-
|
152
|
+
when Array
|
112
153
|
varref.map do |ent|
|
113
154
|
expand_varref(ent, lambda_args)
|
114
155
|
end.flatten
|
115
|
-
|
116
|
-
expand_varref(varref[*lambda_args], lambda_args)
|
117
|
-
elsif varref.nil?
|
118
|
-
nil
|
119
|
-
elsif varref.is_a?(Symbol)
|
156
|
+
when Symbol, true, false, nil
|
120
157
|
varref
|
158
|
+
when Proc
|
159
|
+
expand_varref(varref[*lambda_args], lambda_args)
|
121
160
|
else
|
122
|
-
raise "Unknown
|
161
|
+
raise "Unknown construction variable type: #{varref.class} (#{varref.inspect})"
|
123
162
|
end
|
124
163
|
end
|
125
164
|
|
@@ -143,6 +182,13 @@ module Rscons
|
|
143
182
|
end
|
144
183
|
end
|
145
184
|
|
185
|
+
# Return a String representing the VarSet.
|
186
|
+
#
|
187
|
+
# @return [String] Representation of the VarSet.
|
188
|
+
def inspect
|
189
|
+
to_h.inspect
|
190
|
+
end
|
191
|
+
|
146
192
|
# Return an array containing the values associated with the given keys.
|
147
193
|
#
|
148
194
|
# @param keys [Array<String, Symbol>]
|
@@ -177,16 +223,16 @@ module Rscons
|
|
177
223
|
#
|
178
224
|
# @return [Object] Deep copied value.
|
179
225
|
def deep_dup(obj)
|
180
|
-
|
181
|
-
|
226
|
+
case obj
|
227
|
+
when String
|
228
|
+
obj.dup
|
229
|
+
when Array
|
230
|
+
obj.map { |v| deep_dup(v) }
|
231
|
+
when Hash
|
182
232
|
obj.reduce({}) do |result, (k, v)|
|
183
233
|
result[k] = deep_dup(v)
|
184
234
|
result
|
185
235
|
end
|
186
|
-
elsif obj_class == Array
|
187
|
-
obj.map { |v| deep_dup(v) }
|
188
|
-
elsif obj_class == String
|
189
|
-
obj.dup
|
190
236
|
else
|
191
237
|
obj
|
192
238
|
end
|
data/lib/rscons/version.rb
CHANGED
data/rscons.gemspec
CHANGED
@@ -22,8 +22,7 @@ Gem::Specification.new do |gem|
|
|
22
22
|
|
23
23
|
gem.add_development_dependency "rspec"
|
24
24
|
gem.add_development_dependency "rake"
|
25
|
-
gem.add_development_dependency "simplecov"
|
25
|
+
gem.add_development_dependency "simplecov", "~> 0.15.0"
|
26
26
|
gem.add_development_dependency "yard"
|
27
27
|
gem.add_development_dependency "rdoc"
|
28
|
-
gem.add_development_dependency "redcarpet"
|
29
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rscons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.19.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Holtrop
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -62,16 +62,16 @@ dependencies:
|
|
62
62
|
name: simplecov
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- - "
|
65
|
+
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 0.15.0
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 0.15.0
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: yard
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,20 +100,6 @@ dependencies:
|
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
|
-
- !ruby/object:Gem::Dependency
|
104
|
-
name: redcarpet
|
105
|
-
requirement: !ruby/object:Gem::Requirement
|
106
|
-
requirements:
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
requirements:
|
114
|
-
- - ">="
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '0'
|
117
103
|
description: Software construction library inspired by SCons and implemented in Ruby.
|
118
104
|
email:
|
119
105
|
- jholtrop@gmail.com
|
@@ -145,6 +131,7 @@ files:
|
|
145
131
|
- lib/rscons/environment.rb
|
146
132
|
- lib/rscons/job_set.rb
|
147
133
|
- lib/rscons/threaded_command.rb
|
134
|
+
- lib/rscons/util.rb
|
148
135
|
- lib/rscons/varset.rb
|
149
136
|
- lib/rscons/version.rb
|
150
137
|
- rscons.gemspec
|
@@ -167,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
154
|
- !ruby/object:Gem::Version
|
168
155
|
version: '0'
|
169
156
|
requirements: []
|
170
|
-
|
171
|
-
rubygems_version: 2.6.13
|
157
|
+
rubygems_version: 3.1.4
|
172
158
|
signing_key:
|
173
159
|
specification_version: 4
|
174
160
|
summary: Software construction library inspired by SCons and implemented in Ruby
|