summaryrefslogtreecommitdiff
path: root/tool/update-deps
blob: edb36b6d6ba4ca24db09d247c9427deb1ed98e32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/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