diff --git a/lib/rscons/environment.rb b/lib/rscons/environment.rb index 0018eb9..ef46d51 100644 --- a/lib/rscons/environment.rb +++ b/lib/rscons/environment.rb @@ -286,9 +286,10 @@ module Rscons begin while @job_set.size > 0 - # TODO: get_next_job_to_run needs to take into account targets still - # being processed. - job = @job_set.get_next_job_to_run + targets_still_building = @threaded_commands.map do |tc| + tc.build_operation[:target] + end + job = @job_set.get_next_job_to_run(targets_still_building) # TODO: have Cache determine when checksums may be invalid based on # file size and/or timestamp. diff --git a/lib/rscons/job_set.rb b/lib/rscons/job_set.rb index 911fc84..beab72a 100644 --- a/lib/rscons/job_set.rb +++ b/lib/rscons/job_set.rb @@ -34,28 +34,44 @@ module Rscons # # This method will remove the job from the JobSet. # + # @param targets_still_building [Array] + # 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, Hash] # The next job to run. - def get_next_job_to_run - if @jobs.size > 0 - evaluated_targets = Set.new - attempt = lambda do |target| - evaluated_targets << target - @jobs[target][0][:sources].each do |src| - if @jobs.include?(src) and not evaluated_targets.include?(src) - return attempt[src] - end + def get_next_job_to_run(targets_still_building) + attempted_targets = Set.new + + @jobs.keys.each do |target| + attempted_targets << target + skip = false + @jobs[target][0][:sources].each do |src| + if @jobs.include?(src) and not attempted_targets.include?(src) + # Skip this target because it depends on another target later in + # the job set. + skip = true + break end - job = @jobs[target][0] - if @jobs[target].size > 1 - @jobs[target].slice!(0) - else - @jobs.delete(target) + if targets_still_building.include?(src) + # Skip this target because it depends on another target that is + # still being built. + skip = true + break end - return job end - attempt[@jobs.first.first] + next if skip + job = @jobs[target][0] + if @jobs[target].size > 1 + @jobs[target].slice!(0) + else + @jobs.delete(target) + end + return job end + + nil end # Remove all jobs from the JobSet.