rscons 1.15.0 → 1.19.1
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.
- 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
|