replace JobSet with BuilderSet
This commit is contained in:
parent
ee1640008c
commit
8426a54a57
@ -3,10 +3,10 @@ require_relative "rscons/application"
|
||||
require_relative "rscons/basic_environment"
|
||||
require_relative "rscons/builder"
|
||||
require_relative "rscons/builder_builder"
|
||||
require_relative "rscons/builder_set"
|
||||
require_relative "rscons/cache"
|
||||
require_relative "rscons/configure_op"
|
||||
require_relative "rscons/environment"
|
||||
require_relative "rscons/job_set"
|
||||
require_relative "rscons/script"
|
||||
require_relative "rscons/threaded_command"
|
||||
require_relative "rscons/util"
|
||||
|
75
lib/rscons/builder_set.rb
Normal file
75
lib/rscons/builder_set.rb
Normal file
@ -0,0 +1,75 @@
|
||||
module Rscons
|
||||
# Class to keep track of a set of builders to be executed.
|
||||
class BuilderSet < Hash
|
||||
|
||||
# Create a BuilderSet.
|
||||
#
|
||||
# @param build_dependencies [Hash]
|
||||
# Hash mapping targets to a set of build dependencies. A builder will not
|
||||
# be returned as ready to run if any of its dependencies are still
|
||||
# building.
|
||||
# @param side_effects [Hash]
|
||||
# Hash mapping targets to a set of side-effect files. A builder will not
|
||||
# be returned as ready to run if any of its dependencies is a side-effect
|
||||
# of another target that has not yet been built.
|
||||
def initialize(build_dependencies, side_effects)
|
||||
super()
|
||||
@build_dependencies = build_dependencies
|
||||
@side_effects = side_effects
|
||||
end
|
||||
|
||||
# Add a builder to the BuilderSet.
|
||||
#
|
||||
# @param builder [Builder]
|
||||
# The {Builder} that will produce the target.
|
||||
def <<(builder)
|
||||
# We allow multiple builders to be registered per target for cases like:
|
||||
# env.Directory("dest")
|
||||
# env.Install("dest", "bin")
|
||||
# env.Install("dest", "share")
|
||||
self[builder.target] ||= []
|
||||
self[builder.target] << builder
|
||||
end
|
||||
|
||||
# Get the next builder that is ready to run from the BuilderSet.
|
||||
#
|
||||
# This method will remove the builder from the BuilderSet.
|
||||
#
|
||||
# @param targets_still_building [Array<String>]
|
||||
# Targets that are not finished building. This is used to avoid returning
|
||||
# a builder as available to run if it depends on one of the targets that
|
||||
# are still building as a source.
|
||||
#
|
||||
# @return [nil, Builder]
|
||||
# The next builder to run.
|
||||
def get_next_builder_to_run(targets_still_building)
|
||||
not_built_yet = targets_still_building + self.keys
|
||||
not_built_yet += not_built_yet.reduce([]) do |result, target|
|
||||
result + (@side_effects[target] || [])
|
||||
end
|
||||
|
||||
target_to_build = self.keys.find do |target|
|
||||
deps = self[target][0].sources + (@build_dependencies[target] || []).to_a
|
||||
!deps.find {|dep| not_built_yet.include?(dep)}
|
||||
end
|
||||
|
||||
if target_to_build
|
||||
builder = self[target_to_build][0]
|
||||
if self[target_to_build].size > 1
|
||||
self[target_to_build].slice!(0)
|
||||
else
|
||||
self.delete(target_to_build)
|
||||
end
|
||||
return builder
|
||||
end
|
||||
|
||||
# If there is a builder to run, and nothing is still building, but we did
|
||||
# not find a builder to run above, then there might be a circular
|
||||
# dependency introduced by the user.
|
||||
if (self.size > 0) and targets_still_building.empty?
|
||||
raise "Could not find a runnable builder. Possible circular dependency for #{self.keys.first}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -70,7 +70,7 @@ module Rscons
|
||||
@threaded_commands = Set.new
|
||||
@registered_build_dependencies = {}
|
||||
@side_effects = {}
|
||||
@job_set = JobSet.new(@registered_build_dependencies, @side_effects)
|
||||
@builder_set = BuilderSet.new(@registered_build_dependencies, @side_effects)
|
||||
@user_deps = {}
|
||||
# Hash of builder name (String) => builder class (Class).
|
||||
@builders = {}
|
||||
@ -260,16 +260,16 @@ module Rscons
|
||||
end
|
||||
failure = nil
|
||||
begin
|
||||
while @job_set.size > 0 or @threaded_commands.size > 0
|
||||
while @builder_set.size > 0 or @threaded_commands.size > 0
|
||||
|
||||
if failure
|
||||
@job_set.clear!
|
||||
@builder_set.clear
|
||||
builder = nil
|
||||
else
|
||||
targets_still_building = @threaded_commands.map do |tc|
|
||||
tc.builder.target
|
||||
end
|
||||
builder = @job_set.get_next_job_to_run(targets_still_building)
|
||||
builder = @builder_set.get_next_builder_to_run(targets_still_building)
|
||||
end
|
||||
|
||||
# TODO: have Cache determine when checksums may be invalid based on
|
||||
@ -328,7 +328,7 @@ module Rscons
|
||||
#
|
||||
# @return [void]
|
||||
def clear_targets
|
||||
@job_set.clear!
|
||||
@builder_set.clear
|
||||
end
|
||||
|
||||
# Define a build target.
|
||||
@ -356,7 +356,7 @@ module Rscons
|
||||
cache: Cache.instance,
|
||||
env: self,
|
||||
vars: vars)
|
||||
@job_set.add_job(builder)
|
||||
@builder_set << builder
|
||||
builder
|
||||
else
|
||||
super
|
||||
|
@ -1,87 +0,0 @@
|
||||
module Rscons
|
||||
# Class to keep track of a set of jobs that need to be performed.
|
||||
class JobSet
|
||||
|
||||
# Create a JobSet
|
||||
#
|
||||
# @param build_dependencies [Hash]
|
||||
# Hash mapping targets to a set of build dependencies. A job will not be
|
||||
# returned as ready to run if any of its dependencies are still building.
|
||||
# @param side_effects [Hash]
|
||||
# Hash mapping targets to a set of side-effect files. A job will not be
|
||||
# returned as ready to run if any of its dependencies is a side-effect
|
||||
# of another target that has not yet been built.
|
||||
def initialize(build_dependencies, side_effects)
|
||||
@jobs = {}
|
||||
@build_dependencies = build_dependencies
|
||||
@side_effects = side_effects
|
||||
end
|
||||
|
||||
# Add a job to the JobSet.
|
||||
#
|
||||
# @param builder [Builder]
|
||||
# The {Builder} that will produce the target.
|
||||
def add_job(builder)
|
||||
# We allow multiple jobs to be registered per target for cases like:
|
||||
# env.Directory("dest")
|
||||
# env.Install("dest", "bin")
|
||||
# env.Install("dest", "share")
|
||||
@jobs[builder.target] ||= []
|
||||
@jobs[builder.target] << builder
|
||||
end
|
||||
|
||||
# Get the next job that is ready to run from the JobSet.
|
||||
#
|
||||
# This method will remove the job from the JobSet.
|
||||
#
|
||||
# @param targets_still_building [Array<String>]
|
||||
# Targets that are not finished building. This is used to avoid returning
|
||||
# a job as available to run if it depends on one of the targets that are
|
||||
# still building as a source.
|
||||
#
|
||||
# @return [nil, Builder]
|
||||
# The next job to run.
|
||||
def get_next_job_to_run(targets_still_building)
|
||||
not_built_yet = targets_still_building + @jobs.keys
|
||||
not_built_yet += not_built_yet.reduce([]) do |result, target|
|
||||
result + (@side_effects[target] || [])
|
||||
end
|
||||
|
||||
target_to_build = @jobs.keys.find do |target|
|
||||
deps = @jobs[target][0].sources + (@build_dependencies[target] || []).to_a
|
||||
!deps.find {|dep| not_built_yet.include?(dep)}
|
||||
end
|
||||
|
||||
if target_to_build
|
||||
builder = @jobs[target_to_build][0]
|
||||
if @jobs[target_to_build].size > 1
|
||||
@jobs[target_to_build].slice!(0)
|
||||
else
|
||||
@jobs.delete(target_to_build)
|
||||
end
|
||||
return builder
|
||||
end
|
||||
|
||||
# If there is a job to run, and nothing is still building, but we did
|
||||
# not find a job to run above, then there might be a circular dependency
|
||||
# introduced by the user.
|
||||
if (@jobs.size > 0) and targets_still_building.empty?
|
||||
raise "Could not find a runnable job. Possible circular dependency for #{@jobs.keys.first}"
|
||||
end
|
||||
end
|
||||
|
||||
# Remove all jobs from the JobSet.
|
||||
def clear!
|
||||
@jobs.clear
|
||||
end
|
||||
|
||||
# Get the JobSet size.
|
||||
#
|
||||
# @return [Integer]
|
||||
# JobSet size.
|
||||
def size
|
||||
@jobs.size
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user