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/basic_environment"
|
||||||
require_relative "rscons/builder"
|
require_relative "rscons/builder"
|
||||||
require_relative "rscons/builder_builder"
|
require_relative "rscons/builder_builder"
|
||||||
|
require_relative "rscons/builder_set"
|
||||||
require_relative "rscons/cache"
|
require_relative "rscons/cache"
|
||||||
require_relative "rscons/configure_op"
|
require_relative "rscons/configure_op"
|
||||||
require_relative "rscons/environment"
|
require_relative "rscons/environment"
|
||||||
require_relative "rscons/job_set"
|
|
||||||
require_relative "rscons/script"
|
require_relative "rscons/script"
|
||||||
require_relative "rscons/threaded_command"
|
require_relative "rscons/threaded_command"
|
||||||
require_relative "rscons/util"
|
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
|
@threaded_commands = Set.new
|
||||||
@registered_build_dependencies = {}
|
@registered_build_dependencies = {}
|
||||||
@side_effects = {}
|
@side_effects = {}
|
||||||
@job_set = JobSet.new(@registered_build_dependencies, @side_effects)
|
@builder_set = BuilderSet.new(@registered_build_dependencies, @side_effects)
|
||||||
@user_deps = {}
|
@user_deps = {}
|
||||||
# Hash of builder name (String) => builder class (Class).
|
# Hash of builder name (String) => builder class (Class).
|
||||||
@builders = {}
|
@builders = {}
|
||||||
@ -260,16 +260,16 @@ module Rscons
|
|||||||
end
|
end
|
||||||
failure = nil
|
failure = nil
|
||||||
begin
|
begin
|
||||||
while @job_set.size > 0 or @threaded_commands.size > 0
|
while @builder_set.size > 0 or @threaded_commands.size > 0
|
||||||
|
|
||||||
if failure
|
if failure
|
||||||
@job_set.clear!
|
@builder_set.clear
|
||||||
builder = nil
|
builder = nil
|
||||||
else
|
else
|
||||||
targets_still_building = @threaded_commands.map do |tc|
|
targets_still_building = @threaded_commands.map do |tc|
|
||||||
tc.builder.target
|
tc.builder.target
|
||||||
end
|
end
|
||||||
builder = @job_set.get_next_job_to_run(targets_still_building)
|
builder = @builder_set.get_next_builder_to_run(targets_still_building)
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: have Cache determine when checksums may be invalid based on
|
# TODO: have Cache determine when checksums may be invalid based on
|
||||||
@ -328,7 +328,7 @@ module Rscons
|
|||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def clear_targets
|
def clear_targets
|
||||||
@job_set.clear!
|
@builder_set.clear
|
||||||
end
|
end
|
||||||
|
|
||||||
# Define a build target.
|
# Define a build target.
|
||||||
@ -356,7 +356,7 @@ module Rscons
|
|||||||
cache: Cache.instance,
|
cache: Cache.instance,
|
||||||
env: self,
|
env: self,
|
||||||
vars: vars)
|
vars: vars)
|
||||||
@job_set.add_job(builder)
|
@builder_set << builder
|
||||||
builder
|
builder
|
||||||
else
|
else
|
||||||
super
|
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