ruby-changes:36433
From: akr <ko1@a...>
Date: Thu, 20 Nov 2014 23:18:45 +0900 (JST)
Subject: [ruby-changes:36433] akr:r48514 (trunk): * tool/update-deps: Insert all dependencies found by compiler.
akr 2014-11-20 23:18:37 +0900 (Thu, 20 Nov 2014) New Revision: 48514 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48514 Log: * tool/update-deps: Insert all dependencies found by compiler. Modified files: trunk/ChangeLog trunk/tool/update-deps Index: ChangeLog =================================================================== --- ChangeLog (revision 48513) +++ ChangeLog (revision 48514) @@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Nov 20 23:17:11 2014 Tanaka Akira <akr@f...> + + * tool/update-deps: Insert all dependencies found by compiler. + Thu Nov 20 15:51:01 2014 NARUSE, Yui <naruse@r...> * ext/nkf/depend (nkf.o): add nkf.c as dependency. Index: tool/update-deps =================================================================== --- tool/update-deps (revision 48513) +++ tool/update-deps (revision 48514) @@ -25,6 +25,7 @@ https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L25 require 'optparse' require 'stringio' require 'pathname' +require 'open3' require 'pp' ENV['LC_ALL'] = 'C' @@ -34,6 +35,9 @@ $opt_a = false https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L35 $opt_actual_fix = false $i_not_found = false +DEPENDENCIES_SECTION_START_MARK = "\# AUTOGENERATED DEPENDENCIES START\n" +DEPENDENCIES_SECTION_END_MARK = "\# AUTOGENERATED DEPENDENCIES END\n" + def optionparser op = OptionParser.new op.banner = 'Usage: ruby tool/update-deps' @@ -45,7 +49,11 @@ end https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L49 def read_make_deps(cwd) dependencies = {} - make_p = `make -p all miniruby ruby golf 2> /dev/null` + make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby ruby golf") + if !make_p_status.success? + puts make_p_stderr + raise "make failed" + end dirstack = [cwd] curdir = nil make_p.scan(%r{Entering\ directory\ ['`](.*)'| @@ -108,7 +116,7 @@ end https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L116 # raise ArgumentError, "can not find #{filename} (hint: #{hint0})" #end -def read_single_actual_deps(path_i, cwd) +def read_single_cc_deps(path_i, cwd) files = {} path_i.each_line.with_index {|line, lineindex| next if /\A\# \d+ "(.*)"/ !~ line @@ -130,7 +138,7 @@ def read_single_actual_deps(path_i, cwd) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L138 dep = compiler_wd + dep end if !dep.file? - warn "file not found: #{dep}" + warn "warning: file not found: #{dep}" next end next if !dep.to_s.start_with?(cwd.to_s) # omit system headers. @@ -139,18 +147,18 @@ def read_single_actual_deps(path_i, cwd) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L147 deps end -def read_actual_deps(cwd) +def read_cc_deps(cwd) deps = {} Pathname.glob('**/*.o').sort.each {|fn_o| fn_i = fn_o.sub_ext('.i') if !fn_i.exist? - warn "not found: #{fn_i}" + warn "warning: not found: #{fn_i}" $i_not_found = true next end path_o = cwd + fn_o path_i = cwd + fn_i - deps[path_o] = read_single_actual_deps(path_i, cwd) + deps[path_o] = read_single_cc_deps(path_i, cwd) } deps end @@ -165,12 +173,12 @@ def concentrate(dependencies, cwd) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L173 rel } if %r{\A\.\.(/|\z)} =~ target.to_s - warn "out of tree target: #{target}" + warn "warning: out of tree target: #{target}" next end sources = sources.reject {|s| if %r{\A\.\.(/|\z)} =~ s.to_s - warn "out of tree source: #{s}" + warn "warning: out of tree source: #{s}" true else false @@ -226,7 +234,7 @@ def in_makefile(target, source) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L234 ["enc/depend", target2, source2] when %r{\Aext/} unless File.exist?("#{File.dirname(target)}/extconf.rb") - warn "not found: #{File.dirname(target)}/extconf.rb" + warn "warning: not found: #{File.dirname(target)}/extconf.rb" end target2 = File.basename(target) case source @@ -235,10 +243,10 @@ def in_makefile(target, source) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L243 when %r{\A\.ext/include/[^/]+/ruby/} then source2 = "$(arch_hdrdir)/ruby/#{$'}" when %r{\A#{Regexp.escape File.dirname(target)}/extconf\.h\z} then source2 = "$(RUBY_EXTCONF_H)" when %r{\A#{Regexp.escape File.dirname(target)}/} then source2 = $' - when 'id.h' then source2 = '{$(VPATH)}id.h' - when 'parse.h' then source2 = '{$(VPATH)}parse.h' - when 'lex.c' then source2 = '{$(VPATH)}lex.c' - when 'probes.h' then source2 = '{$(VPATH)}probes.h' + when 'id.h' then source2 = '$(topdir)/id.h' + when 'parse.h' then source2 = '$(topdir)/parse.h' + when 'lex.c' then source2 = '$(topdir)/lex.c' + when 'probes.h' then source2 = '$(topdir)/probes.h' else source2 = "$(top_srcdir)/#{source}" end ["#{File.dirname(target)}/depend", target2, source2] @@ -247,39 +255,101 @@ def in_makefile(target, source) https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L255 end end -def compare_deps(make_deps, actual_deps, out=$stdout) - targets = sort_paths(actual_deps.keys) - targets.each {|target| - actual_sources = actual_deps[target] - if !make_deps.has_key?(target) - warn "no makefile dependency for #{target}" - else - make_sources = make_deps[target] - sort_paths(actual_sources | make_sources).each {|source| - makefile, target2, source2 = in_makefile(target, source) - lines = begin - File.readlines(makefile) - rescue Errno::ENOENT - [] +def show_deps(tag, deps) + targets = sort_paths(deps.keys) + targets.each {|t| + sources = sort_paths(deps[t]) + sources.each {|s| + puts "#{tag} #{t}: #{s}" + } + } +end + +def detect_dependencies(out=$stdout) + cwd = Pathname.pwd + make_deps = read_make_deps(cwd) + #pp make_deps + make_deps = concentrate(make_deps, cwd) + #pp make_deps + cc_deps = read_cc_deps(cwd) + #pp cc_deps + cc_deps = concentrate(cc_deps, cwd) + #pp cc_deps + return make_deps, cc_deps +end + +def compare_deps(make_deps, cc_deps, out=$stdout) + targets = make_deps.keys | cc_deps.keys + + makefiles = {} + + make_lines_hash = {} + make_deps.each {|t, sources| + sources.each {|s| + makefile, t2, s2 = in_makefile(t, s) + makefiles[makefile] = true + make_lines_hash[makefile] ||= Hash.new(false) + make_lines_hash[makefile]["#{t2}: #{s2}"] = true + } + } + + cc_lines_hash = {} + cc_deps.each {|t, sources| + sources.each {|s| + makefile, t2, s2 = in_makefile(t, s) + makefiles[makefile] = true + cc_lines_hash[makefile] ||= Hash.new(false) + cc_lines_hash[makefile]["#{t2}: #{s2}"] = true + } + } + + makefiles.keys.sort.each {|makefile| + cc_lines = cc_lines_hash[makefile] || Hash.new(false) + make_lines = make_lines_hash[makefile] || Hash.new(false) + content = begin + File.read(makefile) + rescue Errno::ENOENT + '' + end + if /^#{Regexp.escape DEPENDENCIES_SECTION_START_MARK} + ((?:.*\n)*) + #{Regexp.escape DEPENDENCIES_SECTION_END_MARK}/x =~ content + pre_post_part = [$`, $'] + current_lines = Hash.new(false) + $1.each_line {|line| current_lines[line.chomp] = true } + (cc_lines.keys | current_lines.keys | make_lines.keys).sort.each {|line| + status = [cc_lines[line], current_lines[line], make_lines[line]] + case status + when [true, true, true] + # no problem + when [true, true, false] + out.puts "warning #{makefile} : #{line} (make doesn't detect written dependency)" + when [true, false, true] + out.puts "add_auto #{makefile} : #{line} (harmless)" # This is automatically updatable. + when [true, false, false] + out.puts "add_auto #{makefile} : #{line} (harmful)" # This is automatically updatable. + when [false, true, true] + out.puts "del_cc #{makefile} : #{line}" # Not automatically updatable because build on other OS may need the dependency. + when [false, true, false] + out.puts "del_cc #{makefile} : #{line} (Curious. make doesn't detect this dependency.)" # Not automatically updatable because build on other OS may need the dependency. + when [false, false, true] + out.puts "del_make #{makefile} : #{line}" # Not automatically updatable because the dependency is written manually. + else + raise "unexpected status: #{status.inspect}" end - #depline = "#{target2}: #{source2} \# #{target}: #{source}\n" - depline = "#{target2}: #{source2}\n" - if !make_sources.include?(source) - out.puts "add #{makefile} : #{depline}" - elsif !actual_sources.include?(source) - if lines.include? depline - out.puts "delL #{makefile} : #{depline}" # delL stands for del line - else - out.puts "delP #{makefile} : #{depline}" # delP stands for del prerequisite - end + } + else + (cc_lines.keys | make_lines.keys).sort.each {|line| + status = [cc_lines[line], make_lines[line]] + case status + when [true, true] + # no problem + when [true, false] + out.puts "add_manual #{makefile} : #{line}" # Not automatically updatable because makefile has no section to update automatically. + when [false, true] + out.puts "del_manual #{makefile} : #{line}" # Not automatically updatable because makefile has no section to update automatically. else - if $opt_a - if lines.include? depline - out.puts "okL #{makefile} : #{depline}" # okL stands for ok line - else - out.puts "okP #{makefile} : #{depline}" # okP stands for ok prerequisite - end - end + raise "unexpected status: #{status.inspect}" end } end @@ -287,104 +357,84 @@ def compare_deps(make_deps, actual_deps, https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L357 end def main_show(out=$stdout) - cwd = Pathname.pwd - make_deps = read_make_deps(cwd) - #pp make_deps - make_deps = concentrate(make_deps, cwd) - #pp make_deps - actual_deps = read_actual_deps(cwd) - #pp actual_deps - actual_deps = concentrate(actual_deps, cwd) - #pp actual_deps - compare_deps(make_deps, actual_deps, out) + make_deps, cc_deps = detect_dependencies(out) + compare_deps(make_deps, cc_deps, out) end def extract_deplines(problems) adds = {} - dels = {} + others = {} problems.each_line {|line| case line - when /\Aadd (\S+) : (\S.*\n)\z/ - (adds[$1] ||= []) << $2 - when /\AdelL (\S+) : (\S.*\n)\z/ - (dels[$1] ||= []) << $2 - when /\AdelP (\S+) : (\S.*\n)\z/ - (dels[$1] ||= []) << $2 - when /\AokL (\S+) : (\S.*\n)\z/ - when /\AokP (\S+) : (\S.*\n)\z/ - (adds[$1] ||= []) << $2 + when /\Aadd_auto (\S+) : ((\S+): (\S+))/ + (adds[$1] ||= []) << [line, "#{$2}\n"] + when /\A(?:del_cc|del_make|add_manual|del_manual|warning) (\S+) : / + (others[$1] ||= []) << line + else + raise "unexpected line: #{line.inspect}" end } - return adds, dels + return adds, others end -DEPENDENCIES_SECTION_START_MARK = "\# AUTOGENERATED DEPENDENCIES START\n" -DEPENDENCIES_SECTION_END_MARK = "\# AUTOGENERATED DEPENDENCIES END\n" - def main_actual_fix(problems) - adds, dels = extract_deplines(problems) - (adds.keys | dels.keys).sort.each {|makefile| + adds, others = extract_deplines(problems) + (adds.keys | others.keys).sort.each {|makefile| content = begin File.read(makefile) rescue Errno::ENOENT - '' + nil end - if /^#{Regexp.escape DEPENDENCIES_SECTION_START_MARK}((?:.*\n)*)#{Regexp.escape DEPENDENCIES_SECTION_END_MARK}/ =~ content - pre_post_part = [$`, $'] - lines = $1.lines.to_a - else - pre_post_part = nil - lines = [] - end - - lines_original = lines.dup - if dels[makefile] - lines -= dels[makefile] - end - if adds[makefile] - lines.concat(adds[makefile] - lines) - end - - if lines == lines_original - next + if content && + /^#{Regexp.escape DEPENDENCIES_SECTION_START_MARK} + ((?:.*\n)*) + #{Regexp.escape DEPENDENCIES_SECTION_END_MARK}/x =~ content + pre_dep_post = [$`, $1, $'] + else + pre_dep_post = nil end - lines.sort! - - if pre_post_part - new_content = [ - pre_post_part.first, - DEPENDENCIES_SECTION_START_MARK, - *lines, - DEPENDENCIES_SECTION_END_MARK, - pre_post_part.last - ].join - tmp_makefile = "#{makefile}.new#{$$}" - File.write(tmp_makefile, new_content) - File.rename tmp_makefile, makefile - puts "modified: #{makefile}" - else + if pre_dep_post && adds[makefile] + pre_lines, dep_lines, post_lines = pre_dep_post + dep_lines = dep_lines.lines.to_a + add_lines = adds[makefile].map(&:last) + new_lines = (dep_lines | add_lines).sort.uniq new_content = [ + pre_lines, DEPENDENCIES_SECTION_START_MARK, - *lines, + *new_lines, DEPENDENCIES_SECTION_END_MARK, + post_lines ].join - if !File.exist?(makefile) - if !lines.empty? - File.open(makefile, 'w') {|f| - f.print new_content - } - puts "created: #{makefile}" - end + if content != new_content + puts "modified: #{makefile}" + tmp_makefile = "#{makefile}.new.#{$$}" + File.write(tmp_makefile, new_content) + File.rename tmp_makefile, makefile + (add_lines - lines).each {|line| puts " added #{line}" } else + puts "not modified: #{makefile}" + end + if others[makefile] + others[makefile].each {|line| puts " #{line}" } + end + else + if pre_dep_post + puts "no addtional lines: #{makefile}" + elsif content puts "no dependencies section: #{makefile}" - (lines_original - lines).each {|line| - puts " del: #{line}" - } - (lines - lines_original).each {|line| - puts " add: #{line}" - } + else + puts "no makefile: #{makefile}" + end + if adds[makefile] + puts " warning: dependencies section was exist at previous phase." + end + if adds[makefile] + adds[makefile].map(&:first).each {|line| puts " #{line}" } + end + if others[makefile] + others[makefile].each {|line| puts " #{line}" } end end } @@ -410,5 +460,5 @@ end https://github.com/ruby/ruby/blob/trunk/tool/update-deps#L460 run if $i_not_found - warn "missing *.i files, see help in #$0 and ensure ccache is disabled" + warn "warning: missing *.i files, see help in #$0 and ensure ccache is disabled" end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/