lib/dake/resolver.rb
# resolve the dependency graph and generate step list for sequential execution
resolve the dependency graph and generate step list for sequential execution
resolve the dependency graph and generate step list for sequential execution
def resolve(target_pairs)
    step_list = []
    visited = Set.new
    path_visited = Set.new
    target_steps = Set.new
    succ_step_dict = {}
    dep_step_dict = {}
    dep_step_list = {}
    succ_target_dict = {}
    step_prereq_dict = {}
    target_pairs.each do |target_name, target_opts|
      if target_opts.tag
        dummy_step = Step.new([], [], [], {}, nil, nil, @analyzer.variable_dict, nil, nil)
        scheme = DakeScheme::Tag.new('@', target_name, dummy_step)
      else
        scheme = @analyzer.analyze_scheme(target_name, nil, nil, nil)
      end
      dep_steps = find_steps(scheme, target_opts.tag)
      dep_steps.each do |dep_step|
        target = dep_step.targets.find { |target| target.scheme.path == scheme.path }
        succ_target_dict[dep_step] ||= Set.new
        succ_target_dict[dep_step] << target
        target_steps << dep_step
        succ_step_dict[dep_step] ||= Set.new
      end
    end
    target_steps.each do |target_step|
      stack = []
      stack.push target_step unless visited.include? target_step
      until stack.empty?
        step = stack.last
        visited << step
        path_visited << step
        unless dep_step_dict[step]
          dep_step_dict[step] = Set.new
          step.prerequisites.map! { |file| @analyzer.analyze_file(file, :prerequisites, step) }.flatten!
          step.prerequisites.each do |dep|
            dep_steps = find_steps(dep.scheme, dep.tag)
            if dep_steps.empty?
              step_prereq_dict[step] ||= Set.new
              step_prereq_dict[step] << dep
            end
            dep_steps.each do |dep_step|
              dep_step_dict[step] << dep_step
              succ_step_dict[dep_step] ||= Set.new
              succ_step_dict[dep_step] << step
              succ_target_dict[dep_step] ||= Set.new
              succ_target_dict[dep_step] << dep
              if path_visited.include? dep_step
                ofile = dep_step.targets.find { |prev_target| prev_target.scheme.path == dep.scheme.path }
                ln1, col1 = ofile.tag ? ofile.name.line_and_column : @analyzer.text_line_and_column(ofile.name)
                ln2, col2 = dep.tag ? dep.name.line_and_column : @analyzer.text_line_and_column(dep.name)
                STDERR.puts 'Cyclical dependency detected.'
                raise "Output `#{dep.scheme.path}' defined in #{dep_step.src_file} at #{ln1}:#{col1} " +
                          "is defined as Input in #{step.src_file} at #{ln2}:#{col2}."
              end
            end
          end
          dep_step_list[step] = dep_step_dict[step].to_a
        end
        while next_step = dep_step_list[step].pop
          break unless visited.include? next_step
        end
        if next_step
          stack.push next_step
        else
          stack.pop
          path_visited.delete step
          step_list << step
        end
      end
    end
    root_steps = target_steps.select { |step| succ_step_dict[step].empty? }.to_set
    DepGraph.new(succ_step_dict, dep_step_dict, step_list, root_steps, step_prereq_dict, succ_target_dict)
  end
def resolve ( target_pairs ) step_list = [ ] visited = Set . new path_visited = Set . new target_steps = Set . new succ_step_dict = { } dep_step_dict = { } dep_step_list = { } succ_target_dict = { } step_prereq_dict = { } target_pairs . each do | target_name , target_opts | if target_opts . tag dummy_step = Step . new ( [ ] , [ ] , [ ] , { } , nil , nil , @analyzer . variable_dict , nil , nil ) scheme = DakeScheme :: Tag . new ( '@' , target_name , dummy_step ) else scheme = @analyzer . analyze_scheme ( target_name , nil , nil , nil ) end dep_steps = find_steps ( scheme , target_opts . tag ) dep_steps . each do | dep_step | target = dep_step . targets . find { | target | target . scheme . path == scheme . path } succ_target_dict [ dep_step ] ||= Set . new succ_target_dict [ dep_step ] << target target_steps << dep_step succ_step_dict [ dep_step ] ||= Set . new end end target_steps . each do | target_step | stack = [ ] stack . push target_step unless visited . include? target_step until stack . empty? step = stack . last visited << step path_visited << step unless dep_step_dict [ step ] dep_step_dict [ step ] = Set . new step . prerequisites . map! { | file | @analyzer . analyze_file ( file , :prerequisites , step ) } . flatten! step . prerequisites . each do | dep | dep_steps = find_steps ( dep . scheme , dep . tag ) if dep_steps . empty? step_prereq_dict [ step ] ||= Set . new step_prereq_dict [ step ] << dep end dep_steps . each do | dep_step | dep_step_dict [ step ] << dep_step succ_step_dict [ dep_step ] ||= Set . new succ_step_dict [ dep_step ] << step succ_target_dict [ dep_step ] ||= Set . new succ_target_dict [ dep_step ] << dep if path_visited . include? dep_step ofile = dep_step . targets . find { | prev_target | prev_target . scheme . path == dep . scheme . path } ln1 , col1 = ofile . tag ? ofile . name . line_and_column : @analyzer . text_line_and_column ( ofile . name ) ln2 , col2 = dep . tag ? dep . name . line_and_column : @analyzer . text_line_and_column ( dep . name ) STDERR . puts 'Cyclical dependency detected.' raise "Output `#{dep.scheme.path}' defined in #{dep_step.src_file} at #{ln1}:#{col1} " + "is defined as Input in #{step.src_file} at #{ln2}:#{col2}." end end end dep_step_list [ step ] = dep_step_dict [ step ] . to_a end while next_step = dep_step_list [ step ] . pop break unless visited . include? next_step end if next_step stack . push next_step else stack . pop path_visited . delete step step_list << step end end end root_steps = target_steps . select { | step | succ_step_dict [ step ] . empty? } . to_set DepGraph . new ( succ_step_dict , dep_step_dict , step_list , root_steps , step_prereq_dict , succ_target_dict ) end
resolve the dependency graph and generate step list for sequential execution
resolve the dependency graph and generate step list for sequential execution
target_pairs
<not_specific>