Class: Rscons::Environment
- Inherits:
-
Object
- Object
- Rscons::Environment
- Defined in:
- lib/rscons/environment.rb
Overview
The Environment class is the main programmatic interface to Rscons. It contains a collection of construction variables, options, builders, and rules for building targets.
Instance Attribute Summary collapse
-
#build_root ⇒ String
The build root.
-
#builders ⇒ Hash
readonly
Set of {“builder_name” => builder_object} pairs.
-
#echo ⇒ Symbol
:command, :short, or :off.
-
#n_threads ⇒ Integer
Get the number of threads to use for parallelized builds in this Environment.
Instance Method Summary collapse
-
#[](*args) ⇒ Object
Get a construction variable’s value.
-
#[]=(*args) ⇒ Object
Set a construction variable’s value.
-
#add_build_hook {|build_op| ... } ⇒ void
Add a build hook to the Environment.
-
#add_builder(builder, &action) ⇒ void
Add a Builder object to the Environment.
-
#add_post_build_hook {|build_op| ... } ⇒ void
Add a post build hook to the Environment.
-
#append(values) ⇒ void
Add a set of construction variables to the Environment.
-
#build_after(targets, prerequisites) ⇒ void
Manually record the given target(s) as needing to be built after the given prerequisite(s).
-
#build_dir(src_dir, obj_dir) ⇒ void
Specify a build directory for this Environment.
-
#build_sources(sources, suffixes, cache, vars) ⇒ Array<String>
deprecated
Deprecated.
Use #register_builds instead.
-
#clear_targets ⇒ void
Clear all targets registered for the Environment.
-
#clone(options = {}) ⇒ Environment
Make a copy of the Environment object.
-
#depends(target, *user_deps) ⇒ void
Manually record a given target as depending on the specified files.
-
#dump ⇒ Object
Print the Environment’s construction variables for debugging.
-
#execute(short_desc, command, options = {}) ⇒ true, ...
Execute a builder command.
-
#expand_path(path) ⇒ String+
Expand a path to be relative to the Environment’s build root.
-
#expand_varref(varref, extra_vars = nil) ⇒ nil, ...
(also: #build_command)
Expand a construction variable reference.
-
#get_build_fname(source_fname, suffix, options = {}) ⇒ String
Return the file name to be built from
source_fname
with suffixsuffix
. -
#get_user_deps(target) ⇒ Array<String>?
Return the list of user dependencies for a given target.
-
#get_var(key) ⇒ Object
Access the value of a construction variable.
-
#initialize(options = {}) ⇒ Environment
constructor
Create an Environment object.
-
#merge_flags(flags) ⇒ void
Merge construction variable flags into this Environment’s construction variables.
-
#method_missing(method, *args) ⇒ BuildTarget
Define a build target.
-
#parse_flags(flags) ⇒ Hash
Parse command-line flags for compilation/linking options into separate construction variables.
-
#parse_flags!(flags) ⇒ Hash
Parse command-line flags for compilation/linking options into separate construction variables.
-
#print_builder_run_message(short_description, command) ⇒ void
Print the builder run message, depending on the Environment’s echo mode.
-
#print_failed_command(command) ⇒ void
Print a failed command.
-
#process ⇒ void
Build all build targets specified in the Environment.
-
#produces(target, *side_effects) ⇒ void
Manually record the given side effect file(s) as being produced when the named target is produced.
-
#register_builds(target, sources, suffixes, vars, options = {}) ⇒ Array<String>
Find and register builders to build source files into files containing one of the suffixes given by suffixes.
-
#run_builder(builder, target, sources, cache, vars, options = {}) ⇒ String, false
Invoke a builder to build the given target based on the given sources.
-
#shell(command) ⇒ String
Execute a command using the system shell.
Constructor Details
#initialize(options = {}) ⇒ Environment
Create an Environment object.
If a block is given, the Environment object is yielded to the block and when the block returns, the #process method is automatically called.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/rscons/environment.rb', line 45 def initialize( = {}) @threaded_commands = Set.new @registered_build_dependencies = {} @side_effects = {} @varset = VarSet.new @job_set = JobSet.new(@registered_build_dependencies, @side_effects) @user_deps = {} @builders = {} @build_dirs = [] @build_hooks = {pre: [], post: []} unless [:exclude_builders] DEFAULT_BUILDERS.each do |builder_class_name| builder_class = Builders.const_get(builder_class_name) builder_class or raise "Could not find builder class #{builder_class_name}" add_builder(builder_class.new) end end @echo = [:echo] || :short @build_root = [:build_root] || "build" if block_given? yield self self.process end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ BuildTarget
Define a build target.
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
# File 'lib/rscons/environment.rb', line 452 def method_missing(method, *args) if @builders.has_key?(method.to_s) target, sources, vars, *rest = args vars ||= {} unless vars.is_a?(Hash) or vars.is_a?(VarSet) raise "Unexpected construction variable set: #{vars.inspect}" end builder = @builders[method.to_s] target = ((target)) sources = Array(sources).map do |source| ((source)) end.flatten build_target = builder.create_build_target(env: self, target: target, sources: sources, vars: vars) add_target(build_target.to_s, builder, sources, vars, rest) build_target else super end end |
Instance Attribute Details
#build_root ⇒ String
Returns The build root.
18 19 20 |
# File 'lib/rscons/environment.rb', line 18 def build_root @build_root end |
#builders ⇒ Hash (readonly)
Returns Set of {“builder_name” => builder_object} pairs.
12 13 14 |
# File 'lib/rscons/environment.rb', line 12 def builders @builders end |
#echo ⇒ Symbol
Returns :command, :short, or :off.
15 16 17 |
# File 'lib/rscons/environment.rb', line 15 def echo @echo end |
Instance Method Details
#[](*args) ⇒ Object
Get a construction variable’s value.
279 280 281 |
# File 'lib/rscons/environment.rb', line 279 def [](*args) @varset.send(:[], *args) end |
#[]=(*args) ⇒ Object
Set a construction variable’s value.
304 305 306 |
# File 'lib/rscons/environment.rb', line 304 def []=(*args) @varset.send(:[]=, *args) end |
#add_build_hook {|build_op| ... } ⇒ void
This method returns an undefined value.
Add a build hook to the Environment.
Build hooks are Ruby blocks which are invoked immediately before a build operation takes place. Build hooks have an opportunity to modify the construction variables in use for the build operation based on the builder in use, target file name, or sources. Build hooks can also register new build targets.
187 188 189 |
# File 'lib/rscons/environment.rb', line 187 def add_build_hook(&block) @build_hooks[:pre] << block end |
#add_builder(builder) ⇒ void #add_builder(builder, &action) ⇒ void
This method returns an undefined value.
Add a Builder object to the Environment.
155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/rscons/environment.rb', line 155 def add_builder(builder, &action) if not builder.is_a? Rscons::Builder builder = Rscons::Builders::SimpleBuilder.new(builder, &action) end @builders[builder.name] = builder var_defs = builder.default_variables(self) if var_defs var_defs.each_pair do |var, val| @varset[var] ||= val end end end |
#add_post_build_hook {|build_op| ... } ⇒ void
This method returns an undefined value.
Add a post build hook to the Environment.
Post-build hooks are Ruby blocks which are invoked immediately after a build operation takes place. Post-build hooks are only invoked if the build operation succeeded. Post-build hooks can register new build targets.
211 212 213 |
# File 'lib/rscons/environment.rb', line 211 def add_post_build_hook(&block) @build_hooks[:post] << block end |
#append(values) ⇒ void
This method returns an undefined value.
Add a set of construction variables to the Environment.
313 314 315 |
# File 'lib/rscons/environment.rb', line 313 def append(values) @varset.append(values) end |
#build_after(targets, prerequisites) ⇒ void
This method returns an undefined value.
Manually record the given target(s) as needing to be built after the given prerequisite(s).
For example, consider a builder registered to generate gen.c which also generates gen.h as a side-effect. If program.c includes gen.h, then it should not be compiled before gen.h has been generated. When using multiple threads to build, Rscons may attempt to compile program.c before gen.h has been generated because it does not know that gen.h will be generated along with gen.c. One way to prevent that situation would be to first process the Environment with just the code-generation builders in place and then register the compilation builders. Another way is to use this method to record that a certain target should not be built until another has completed. For example, for the situation previously described:
env.build_after("program.o", "gen.c")
511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/rscons/environment.rb', line 511 def build_after(targets, prerequisites) targets = Array(targets) prerequisites = Array(prerequisites) targets.each do |target| target = ((target)) @registered_build_dependencies[target] ||= Set.new prerequisites.each do |prerequisite| prerequisite = ((prerequisite)) @registered_build_dependencies[target] << prerequisite end end end |
#build_dir(src_dir, obj_dir) ⇒ void
This method returns an undefined value.
Specify a build directory for this Environment.
Source files from src_dir will produce object files under obj_dir.
228 229 230 231 232 233 |
# File 'lib/rscons/environment.rb', line 228 def build_dir(src_dir, obj_dir) if src_dir.is_a?(String) src_dir = src_dir.gsub("\\", "/").sub(%r{/*$}, "") end @build_dirs.unshift([src_dir, obj_dir]) end |
#build_sources(sources, suffixes, cache, vars) ⇒ Array<String>
Use #register_builds instead.
Build a list of source files into files containing one of the suffixes given by suffixes.
This method is used internally by Rscons builders.
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
# File 'lib/rscons/environment.rb', line 569 def build_sources(sources, suffixes, cache, vars) sources.map do |source| if source.end_with?(*suffixes) source else converted = nil suffixes.each do |suffix| converted_fname = get_build_fname(source, suffix) if builder = find_builder_for(converted_fname, source, []) converted = run_builder(builder, converted_fname, [source], cache, vars) return nil unless converted break end end converted or raise "Could not find a builder to handle #{source.inspect}." end end end |
#clear_targets ⇒ void
This method returns an undefined value.
Clear all targets registered for the Environment.
400 401 402 |
# File 'lib/rscons/environment.rb', line 400 def clear_targets @job_set.clear! end |
#clone(options = {}) ⇒ Environment
Make a copy of the Environment object.
By default, a cloned environment will contain a copy of all environment options, construction variables, and builders, but not a copy of the targets, build hooks, build directories, or the build root.
Exactly which items are cloned are controllable via the optional :clone parameter, which can be :none, :all, or a set or array of any of the following:
-
:variables to clone construction variables (on by default)
-
:builders to clone the builders (on by default)
-
:build_root to clone the build root (on by default)
-
:build_dirs to clone the build directories (on by default)
-
:build_hooks to clone the build hooks (on by default)
If a block is given, the Environment object is yielded to the block and when the block returns, the #process method is automatically called.
Any options that #initialize receives can also be specified here.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rscons/environment.rb', line 92 def clone( = {}) clone = [:clone] || :all clone = Set[:variables, :builders, :build_root, :build_dirs, :build_hooks] if clone == :all clone = Set[] if clone == :none clone = Set.new(clone) if clone.is_a?(Array) clone.delete(:builders) if [:exclude_builders] env = self.class.new( echo: [:echo] || @echo, build_root: [:build_root], exclude_builders: true) if clone.include?(:builders) @builders.each do |builder_name, builder| env.add_builder(builder) end end env.append(@varset) if clone.include?(:variables) env.build_root = @build_root if clone.include?(:build_root) if clone.include?(:build_dirs) @build_dirs.reverse.each do |src_dir, obj_dir| env.build_dir(src_dir, obj_dir) end end if clone.include?(:build_hooks) @build_hooks[:pre].each do |build_hook_block| env.add_build_hook(&build_hook_block) end @build_hooks[:post].each do |build_hook_block| env.add_post_build_hook(&build_hook_block) end end env.instance_variable_set(:@n_threads, @n_threads) if block_given? yield env env.process end env end |
#depends(target, *user_deps) ⇒ void
This method returns an undefined value.
Manually record a given target as depending on the specified files.
478 479 480 481 482 483 484 |
# File 'lib/rscons/environment.rb', line 478 def depends(target, *user_deps) target = (target.to_s) user_deps = user_deps.map {|ud| (ud)} @user_deps[target] ||= [] @user_deps[target] = (@user_deps[target] + user_deps).uniq build_after(target, user_deps) end |
#dump ⇒ Object
Print the Environment’s construction variables for debugging.
878 879 880 881 882 883 884 |
# File 'lib/rscons/environment.rb', line 878 def dump varset_hash = @varset.to_h varset_hash.keys.sort_by(&:to_s).each do |var| var_str = var.is_a?(Symbol) ? var.inspect : var Ansi.write($stdout, :cyan, var_str, :reset, " => #{varset_hash[var].inspect}\n") end end |
#execute(short_desc, command, options = {}) ⇒ true, ...
Execute a builder command.
433 434 435 436 437 438 439 440 441 442 |
# File 'lib/rscons/environment.rb', line 433 def execute(short_desc, command, = {}) (short_desc, command) env_args = [:env] ? [[:env]] : [] = [:options] ? [[:options]] : [] system(*env_args, *Rscons.command_executer, *command, *).tap do |result| unless result or @echo == :command print_failed_command(command) end end end |
#expand_path(path) ⇒ String+
Expand a path to be relative to the Environment’s build root.
Paths beginning with “^/” are expanded by replacing “^” with the Environment’s build root.
716 717 718 719 720 721 722 723 724 725 726 |
# File 'lib/rscons/environment.rb', line 716 def (path) if Rscons.phony_target?(path) path elsif path.is_a?(Array) path.map do |path| (path) end else path.sub(%r{^\^(?=[\\/])}, @build_root).gsub("\\", "/") end end |
#expand_varref(varref, extra_vars = nil) ⇒ nil, ... Also known as: build_command
Expand a construction variable reference.
412 413 414 415 416 417 418 419 420 |
# File 'lib/rscons/environment.rb', line 412 def (varref, extra_vars = nil) vars = if extra_vars.nil? @varset else @varset.merge(extra_vars) end lambda_args = [env: self, vars: vars] vars.(varref, lambda_args) end |
#get_build_fname(source_fname, suffix, options = {}) ⇒ String
Return the file name to be built from source_fname
with suffix suffix
.
This method takes into account the Environment’s build directories.
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/rscons/environment.rb', line 251 def get_build_fname(source_fname, suffix, = {}) build_fname = Rscons.set_suffix(source_fname, suffix).gsub('\\', '/') [:features] ||= [] extra_path = [:features].include?("shared") ? "/_shared" : "" found_match = @build_dirs.find do |src_dir, obj_dir| if src_dir.is_a?(Regexp) build_fname.sub!(src_dir, "#{obj_dir}#{extra_path}") else build_fname.sub!(%r{^#{src_dir}/}, "#{obj_dir}#{extra_path}/") end end unless found_match if Rscons.absolute_path?(build_fname) if build_fname =~ %r{^(\w):(.*)$} build_fname = "#{@build_root}#{extra_path}/_#{$1}#{$2}" else build_fname = "#{@build_root}#{extra_path}/_#{build_fname}" end elsif !build_fname.start_with?("#{@build_root}/") build_fname = "#{@build_root}#{extra_path}/#{build_fname}" end end build_fname.gsub('\\', '/') end |
#get_user_deps(target) ⇒ Array<String>?
Return the list of user dependencies for a given target.
551 552 553 |
# File 'lib/rscons/environment.rb', line 551 def get_user_deps(target) @user_deps[target] end |
#get_var(key) ⇒ Object
Access the value of a construction variable.
This method is similar to #[] but does not make a copy-on-access copy of the variable accessed. This means that the returned value is NOT safe to be modified by the caller. Thus the caller must guarantee that it does not modify the returned value.
297 298 299 |
# File 'lib/rscons/environment.rb', line 297 def get_var(key) @varset.get_var(key) end |
#merge_flags(flags) ⇒ void
This method returns an undefined value.
Merge construction variable flags into this Environment’s construction variables.
This method does the same thing as #append, except that Array values in flags
are appended to the end of Array construction variables instead of replacing their contents.
867 868 869 870 871 872 873 874 875 |
# File 'lib/rscons/environment.rb', line 867 def merge_flags(flags) flags.each_pair do |key, val| if self.get_var(key).is_a?(Array) and val.is_a?(Array) self[key] += val else self[key] = val end end end |
#parse_flags(flags) ⇒ Hash
Parse command-line flags for compilation/linking options into separate construction variables.
For #parse_flags, the parsed construction variables are returned in a Hash instead of merging them directly to the Environment. They can be merged with #merge_flags. The #parse_flags! version immediately merges the parsed flags as well.
Example:
# Import FreeType build options
env.parse_flags!("!freetype-config --cflags --libs")
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 |
# File 'lib/rscons/environment.rb', line 772 def parse_flags(flags) if flags =~ /^!(.*)$/ flags = shell($1) end rv = {} words = Shellwords.split(flags) skip = false words.each_with_index do |word, i| if skip skip = false next end append = lambda do |var, val| rv[var] ||= [] rv[var] += val end handle = lambda do |var, val| if val.nil? or val.empty? val = words[i + 1] skip = true end if val and not val.empty? append[var, [val]] end end if word == "-arch" if val = words[i + 1] append["CCFLAGS", ["-arch", val]] append["LDFLAGS", ["-arch", val]] end skip = true elsif word =~ /^#{get_var("CPPDEFPREFIX")}(.*)$/ handle["CPPDEFINES", $1] elsif word == "-include" if val = words[i + 1] append["CCFLAGS", ["-include", val]] end skip = true elsif word == "-isysroot" if val = words[i + 1] append["CCFLAGS", ["-isysroot", val]] append["LDFLAGS", ["-isysroot", val]] end skip = true elsif word =~ /^#{get_var("INCPREFIX")}(.*)$/ handle["CPPPATH", $1] elsif word =~ /^#{get_var("LIBLINKPREFIX")}(.*)$/ handle["LIBS", $1] elsif word =~ /^#{get_var("LIBDIRPREFIX")}(.*)$/ handle["LIBPATH", $1] elsif word == "-mno-cygwin" append["CCFLAGS", [word]] append["LDFLAGS", [word]] elsif word == "-mwindows" append["LDFLAGS", [word]] elsif word == "-pthread" append["CCFLAGS", [word]] append["LDFLAGS", [word]] elsif word =~ /^-Wa,(.*)$/ append["ASFLAGS", $1.split(",")] elsif word =~ /^-Wl,(.*)$/ append["LDFLAGS", $1.split(",")] elsif word =~ /^-Wp,(.*)$/ append["CPPFLAGS", $1.split(",")] elsif word.start_with?("-") append["CCFLAGS", [word]] elsif word.start_with?("+") append["CCFLAGS", [word]] append["LDFLAGS", [word]] else append["LIBS", [word]] end end rv end |
#parse_flags!(flags) ⇒ Hash
Parse command-line flags for compilation/linking options into separate construction variables.
For #parse_flags, the parsed construction variables are returned in a Hash instead of merging them directly to the Environment. They can be merged with #merge_flags. The #parse_flags! version immediately merges the parsed flags as well.
Example:
# Import FreeType build options
env.parse_flags!("!freetype-config --cflags --libs")
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 |
# File 'lib/rscons/environment.rb', line 772 def parse_flags(flags) if flags =~ /^!(.*)$/ flags = shell($1) end rv = {} words = Shellwords.split(flags) skip = false words.each_with_index do |word, i| if skip skip = false next end append = lambda do |var, val| rv[var] ||= [] rv[var] += val end handle = lambda do |var, val| if val.nil? or val.empty? val = words[i + 1] skip = true end if val and not val.empty? append[var, [val]] end end if word == "-arch" if val = words[i + 1] append["CCFLAGS", ["-arch", val]] append["LDFLAGS", ["-arch", val]] end skip = true elsif word =~ /^#{get_var("CPPDEFPREFIX")}(.*)$/ handle["CPPDEFINES", $1] elsif word == "-include" if val = words[i + 1] append["CCFLAGS", ["-include", val]] end skip = true elsif word == "-isysroot" if val = words[i + 1] append["CCFLAGS", ["-isysroot", val]] append["LDFLAGS", ["-isysroot", val]] end skip = true elsif word =~ /^#{get_var("INCPREFIX")}(.*)$/ handle["CPPPATH", $1] elsif word =~ /^#{get_var("LIBLINKPREFIX")}(.*)$/ handle["LIBS", $1] elsif word =~ /^#{get_var("LIBDIRPREFIX")}(.*)$/ handle["LIBPATH", $1] elsif word == "-mno-cygwin" append["CCFLAGS", [word]] append["LDFLAGS", [word]] elsif word == "-mwindows" append["LDFLAGS", [word]] elsif word == "-pthread" append["CCFLAGS", [word]] append["LDFLAGS", [word]] elsif word =~ /^-Wa,(.*)$/ append["ASFLAGS", $1.split(",")] elsif word =~ /^-Wl,(.*)$/ append["LDFLAGS", $1.split(",")] elsif word =~ /^-Wp,(.*)$/ append["CPPFLAGS", $1.split(",")] elsif word.start_with?("-") append["CCFLAGS", [word]] elsif word.start_with?("+") append["CCFLAGS", [word]] append["LDFLAGS", [word]] else append["LIBS", [word]] end end rv end |
#print_builder_run_message(short_description, command) ⇒ void
This method returns an undefined value.
Print the builder run message, depending on the Environment’s echo mode.
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 |
# File 'lib/rscons/environment.rb', line 903 def (short_description, command) case @echo when :command if command.is_a?(Array) = command_to_s(command) elsif command.is_a?(String) = command elsif short_description.is_a?(String) = short_description end when :short = short_description if short_description end Ansi.write($stdout, :cyan, , :reset, "\n") if end |
#print_failed_command(command) ⇒ void
This method returns an undefined value.
Print a failed command.
925 926 927 |
# File 'lib/rscons/environment.rb', line 925 def print_failed_command(command) Ansi.write($stdout, :red, "Failed command was: #{command_to_s(command)}", :reset, "\n") end |
#process ⇒ void
This method returns an undefined value.
Build all build targets specified in the Environment.
When a block is passed to Environment.new, this method is automatically called after the block returns.
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/rscons/environment.rb', line 323 def process cache = Cache.instance failure = nil begin while @job_set.size > 0 or @threaded_commands.size > 0 if failure @job_set.clear! job = nil else targets_still_building = @threaded_commands.map do |tc| tc.build_operation[:target] end job = @job_set.get_next_job_to_run(targets_still_building) end # TODO: have Cache determine when checksums may be invalid based on # file size and/or timestamp. cache.clear_checksum_cache! if job result = run_builder(job[:builder], job[:target], job[:sources], cache, job[:vars], allow_delayed_execution: true, setup_info: job[:setup_info]) unless result failure = "Failed to build #{job[:target]}" Ansi.write($stderr, :red, failure, :reset, "\n") next end end completed_tcs = Set.new # First do a non-blocking wait to pick up any threads that have # completed since last time. while tc = wait_for_threaded_commands(nonblock: true) completed_tcs << tc end # If needed, do a blocking wait. if (@threaded_commands.size > 0) and ((completed_tcs.empty? and job.nil?) or (@threaded_commands.size >= n_threads)) completed_tcs << wait_for_threaded_commands end # Process all completed {ThreadedCommand} objects. completed_tcs.each do |tc| result = finalize_builder(tc) if result @build_hooks[:post].each do |build_hook_block| build_hook_block.call(tc.build_operation) end else unless @echo == :command print_failed_command(tc.command) end failure = "Failed to build #{tc.build_operation[:target]}" Ansi.write($stderr, :red, failure, :reset, "\n") break end end end ensure cache.write end if failure raise BuildError.new(failure) end end |
#produces(target, *side_effects) ⇒ void
This method returns an undefined value.
Manually record the given side effect file(s) as being produced when the named target is produced.
535 536 537 538 539 540 541 542 |
# File 'lib/rscons/environment.rb', line 535 def produces(target, *side_effects) target = ((target)) side_effects = Array(side_effects).map do |side_effect| ((side_effect)) end.flatten @side_effects[target] ||= [] @side_effects[target] += side_effects end |
#register_builds(target, sources, suffixes, vars, options = {}) ⇒ Array<String>
Find and register builders to build source files into files containing one of the suffixes given by suffixes.
This method is used internally by Rscons builders. It should be called from the builder’s #setup method.
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/rscons/environment.rb', line 614 def register_builds(target, sources, suffixes, vars, = {}) [:features] ||= [] @registered_build_dependencies[target] ||= Set.new sources.map do |source| if source.end_with?(*suffixes) source else output_fname = nil suffixes.each do |suffix| attempt_output_fname = get_build_fname(source, suffix, features: [:features]) if builder = find_builder_for(attempt_output_fname, source, [:features]) output_fname = attempt_output_fname self.__send__(builder.name, output_fname, source, vars) @registered_build_dependencies[target] << output_fname break end end output_fname or raise "Could not find a builder for #{source.inspect}." end end end |
#run_builder(builder, target, sources, cache, vars, options = {}) ⇒ String, false
Invoke a builder to build the given target based on the given sources.
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
# File 'lib/rscons/environment.rb', line 654 def run_builder(builder, target, sources, cache, vars, = {}) vars = @varset.merge(vars) build_operation = { builder: builder, target: target, sources: sources, cache: cache, env: self, vars: vars, setup_info: [:setup_info] } call_build_hooks = lambda do |sec| @build_hooks[sec].each do |build_hook_block| build_hook_block.call(build_operation) end end # Invoke pre-build hooks. call_build_hooks[:pre] # Call the builder's #run method. if builder.method(:run).arity == 5 rv = builder.run(*build_operation.values_at(:target, :sources, :cache, :env, :vars)) else rv = builder.run(build_operation) end if rv.is_a?(ThreadedCommand) # Store the build operation so the post-build hooks can be called # with it when the threaded command completes. rv.build_operation = build_operation start_threaded_command(rv) unless [:allow_delayed_execution] # Delayed command execution is not allowed, so we need to execute # the command and finalize the builder now. tc = wait_for_threaded_commands(which: [rv]) rv = finalize_builder(tc) if rv call_build_hooks[:post] else unless @echo == :command print_failed_command(tc.command) end end end else call_build_hooks[:post] if rv end rv end |
#shell(command) ⇒ String
Execute a command using the system shell.
The shell is automatically determined but can be overridden by the SHELL construction variable. If the SHELL construction variable is specified, the flag to pass to the shell is automatically dtermined but can be overridden by the SHELLFLAG construction variable.
738 739 740 741 742 743 744 745 746 747 748 749 |
# File 'lib/rscons/environment.rb', line 738 def shell(command) shell_cmd = if self["SHELL"] flag = self["SHELLFLAG"] || (self["SHELL"] == "cmd" ? "/c" : "-c") [self["SHELL"], flag] else Rscons.get_system_shell end IO.popen([*shell_cmd, command]) do |io| io.read end end |