ruby/tool/update-deps

140 строки
3.7 KiB
Ruby
Executable File

#!/usr/bin/ruby
# tool/update-deps assists you to update dependencies in common.mk.
# This script uses preprocessed source files (*.i) to extract
# dependencies.
# It is possible to generate *.i using gcc with -save-temps option as:
#
# ./configure CFLAGS='-save-temps'
# make all golf
#
# After that, tool/update-deps generate common.mk with up-to-date dependencies.
# Currently, the result is not perfect around version.o, compile.o, etc.
# So you must see each changes and incorporate right changes.
#
# ./tool/update-deps > z
# wdiff =(sed -e 's/\\$//' common.mk ) =(sed -e 's/\\$//' z) |less -j 5 -p '\{\+|\+\}|\[-|-\]'
# vi common.mk
src = File.read("common.mk")
includes_macro = {}
src.scan(/^([A-Z_]+_H_INCLUDES)[ \t]*=(([^\\\n]|\\(.|\n))*)\n/) {
name = $1
vals = $2
#STDERR.puts vals.inspect
vals.gsub!(/\\\n/, ' ')
vals.gsub!(/\{\$\(VPATH\)\}/, '')
vals.gsub!(/thread_\$\(THREAD_MODEL\)/, 'thread_pthread')
vals = vals.strip.split(/\s+/)
includes_macro[name] = vals
#STDERR.puts [name, vals].inspect
}
begin
again = false
includes_macro.each {|name, vals|
vals.map! {|val|
if /\A\$\((.*_H_INCLUDES)\)\z/ =~ val
again = true
includes_macro.fetch($1)
else
val
end
}
vals.flatten!
}
end while again
src.gsub!(/^([0-9a-z._]+)\.\$\(OBJEXT\):(.*\n(?:[ ].*\n)*)/) {
#STDERR.puts $&.inspect
matched = $&
basename = $1
deps = $2
dd = deps.dup
dd.gsub!(/\{\$\(VPATH\)\}/, '')
dd.gsub!(/\\\n/, ' ')
dd.gsub!(/thread_\$\(THREAD_MODEL\)/, 'thread_pthread')
used_imacro = {}
includes_macro.each {|k, v|
if dd.sub!(/\$\(#{Regexp.escape k}\)/) { v.join(' ') }
used_imacro[k] = true
end
}
dd = dd.strip.split(/\s+/)
if !File.file?("#{basename}.o")
warn "#{basename}.o not found."
else
unless File.file? "#{basename}.i"
puts "#{basename}.i not found."
next
end
incs = []
File.foreach("#{basename}.i") {|line|
next unless /^# \d+ "([^"]*)"/ =~ line
inc = $1
next if %r{\A[/<]} =~ inc
inc.sub!(%r{\A\./}, '')
inc.sub!(%r{\Ainclude/ruby/}, '') or
inc.sub!(%r{\Ainclude/}, '') or
inc.sub!(%r{\A\.ext/include/[^/]+/ruby/}, '') or
inc.sub!(%r{\Aenc/}, '') or
inc.sub!(%r{\Amissing/}, '')
#p inc
incs << inc
}
incs.uniq!
incs = incs.sort_by {|inc| [(dd.index(inc) || dd.length), incs.index(inc)] }
add = incs - dd
if !add.empty? || true
if incs[0] != dd[0]
raise "first file not matched: #{incs[0].inspect} v.s. #{dd[0].inspect}"
end
depline = "#{basename}.$(OBJEXT):"
used_imacro.each_key {|k|
if includes_macro[k].all? {|v| incs.include? v }
im = "$(#{k})"
incs.map! {|inc|
if includes_macro[k].include? inc
im0 = im
im = nil
im0
else
inc
end
}
incs.compact!
else
needless = includes_macro[k].reject {|v| incs.include? v }
STDERR.puts "#{basename}.$(OBJEXT) can't use #{k}. #{needless.join(' ')} is not used."
end
}
incs.each {|inc|
inc = inc.sub(/\Athread_pthread/, 'thread_$(THREAD_MODEL)')
if /_INCLUDES\)\z/ =~ inc
# use $(RUBY_H_INCLUDES) as is.
elsif inc == 'revision.h'
inc = '$(srcdir)/revision.h'
else
inc = "{$(VPATH)}#{inc}"
end
depline << " #{inc}"
}
lines = []
while 72 < depline.length && depline.sub!(/\A(.{0,72}|.{72}.*?) /, '')
lines << $&
end
lines << depline
matched = lines.join("\\\n ")
matched << "\n"
end
end
#STDERR.puts matched.inspect
matched
}
puts src