def run_builder(builder, target, sources, cache, vars, options = {})
      vars = @varset.merge(vars)
      build_operation = {
        builder: builder,
        target: target,
        sources: sources,
        cache: cache,
        env: self,
        vars: vars,
        setup_info: options[: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 options[: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
def run_builder(builder, target, sources, cache, vars, options = {})
      vars = @varset.merge(vars)
      build_operation = {
        builder: builder,
        target: target,
        sources: sources,
        cache: cache,
        env: self,
        vars: vars,
        setup_info: options[: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 options[: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
Invoke a builder to build the given target based on the given sources.

 @param builder [Builder] The Builder to use.
 @param target [String] The target output file.
 @param sources [Array<String>] List of source files.
 @param cache [Cache] The Cache.
 @param vars [Hash] Extra variables to pass to the builder.
 @param options [Hash]
   @since 1.10.0
   Options.
 @option options [Boolean] :allow_delayed_execution
   @since 1.10.0
   Allow a threaded command to be scheduled but not yet completed before
   this method returns.
 @option options [Object] :setup_info
   Arbitrary builder info returned by Builder#setup.

 @return [String,false] Return value from the {Builder}'s +run+ method.