2009-07-19 Yves BLUSSEAU <yves.grub-devel@zetam.org>
[grub2/phcoder.git] / genmk.rb
blob9574ce98dbf278e55993d054d7cc67bcc088742c
1 #! /usr/bin/ruby -w
3 # Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
5 # This genmk.rb is free software; the author
6 # gives unlimited permission to copy and/or distribute it,
7 # with or without modifications, as long as this notice is preserved.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY, to the extent permitted by law; without
11 # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12 # PARTICULAR PURPOSE.
14 module Enumerable
15   def collect_with_index
16     ret = []
17     self.each_with_index do |item, index|
18       ret.push(yield(item, index))
19     end
20     ret
21   end
22 end
24 class String
25   def to_var
26     self.gsub(/[^a-zA-Z0-9_@]/, '_')
27   end
29   def suffix(str)
30     self.sub(/\.[^\.]*$/, '') + '.' + str
31   end
33   def to_obj
34     self.sub(/\.[^\.]*$/, '').to_var + '.o'
35   end
36 end
38 class Image
39   def initialize(dir, name)
40     @dir = dir
41     @name = name
42   end
43   attr_reader :dir, :name
45   def rule(sources)
46     prefix = @name.to_var
47     exe = @name.suffix('exec')
48     objs = sources.collect do |src|
49       raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
50       prefix + '-' + src.to_obj
51     end
52     objs_str = objs.join(' ')
53     deps = objs.collect {|obj| obj.suffix('d')}
54     deps_str = deps.join(' ')
56     "CLEANFILES += #{@name} #{exe} #{objs_str}
57 MOSTLYCLEANFILES += #{deps_str}
59 ifneq ($(TARGET_APPLE_CC),1)
60 #{@name}: #{exe}
61         $(OBJCOPY) -O $(#{prefix}_FORMAT) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id $< $@
62 else
63 ifneq (#{exe},kernel.exec)
64 #{@name}: #{exe} ./grub-macho2img
65         ./grub-macho2img $< $@
66 else
67 #{@name}: #{exe} ./grub-macho2img
68         ./grub-macho2img --bss $< $@
69 endif
70 endif
72 #{exe}: #{objs_str}
73         $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS)
75 " + objs.collect_with_index do |obj, i|
76       src = sources[i]
77       fake_obj = File.basename(src).suffix('o')
78       dep = deps[i]
79       flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
80       extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
81       dir = File.dirname(src)
83       "#{obj}: #{src} $(#{src}_DEPENDENCIES)
84         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $<
85 -include #{dep}
88     end.join('')
89   end
90 end
92 # Use PModule instead Module, to avoid name conflicting.
93 class PModule
94   def initialize(dir, name)
95     @dir = dir
96     @name = name
97   end
98   attr_reader :dir, :name
100   def rule(sources)
101     prefix = @name.to_var
102     objs = sources.collect do |src|
103       raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
104       prefix + '-' + src.to_obj
105     end
106     objs_str = objs.join(' ')
107     deps = objs.collect {|obj| obj.suffix('d')}
108     deps_str = deps.join(' ')
109     pre_obj = 'pre-' + @name.suffix('o')
110     mod_src = 'mod-' + @name.suffix('c')
111     mod_obj = mod_src.suffix('o')
112     defsym = 'def-' + @name.suffix('lst')
113     undsym = 'und-' + @name.suffix('lst')
114     mod_name = File.basename(@name, '.mod')
115     symbolic_name = mod_name.sub(/\.[^\.]*$/, '')
117     "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{undsym}
118 ifneq ($(#{prefix}_EXPORTS),no)
119 CLEANFILES += #{defsym}
120 DEFSYMFILES += #{defsym}
121 endif
122 MOSTLYCLEANFILES += #{deps_str}
123 UNDSYMFILES += #{undsym}
125 ifneq ($(TARGET_APPLE_CC),1)
126 #{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF)
127         -rm -f $@
128         $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{pre_obj} #{mod_obj}
129         if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
130         $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
131 else
132 #{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF)
133         -rm -f $@
134         -rm -f $@.bin
135         $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin #{pre_obj} #{mod_obj}
136         $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
137         -rm -f $@.bin
138 endif
140 #{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str}
141         -rm -f $@
142         $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{objs_str}
144 #{mod_obj}: #{mod_src}
145         $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -c -o $@ $<
147 #{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
148         sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1)
150 ifneq ($(#{prefix}_EXPORTS),no)
151 ifneq ($(TARGET_APPLE_CC),1)
152 #{defsym}: #{pre_obj}
153         $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@
154 else
155 #{defsym}: #{pre_obj}
156         $(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@
157 endif
158 endif
160 #{undsym}: #{pre_obj}
161         echo '#{mod_name}' > $@
162         $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
164 " + objs.collect_with_index do |obj, i|
165       src = sources[i]
166       fake_obj = File.basename(src).suffix('o')
167       command = 'cmd-' + obj.suffix('lst')
168       fs = 'fs-' + obj.suffix('lst')
169       partmap = 'partmap-' + obj.suffix('lst')
170       handler = 'handler-' + obj.suffix('lst')
171       parttool = 'parttool-' + obj.suffix('lst')
172       dep = deps[i]
173       flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
174       extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
175       dir = File.dirname(src)
177       "#{obj}: #{src} $(#{src}_DEPENDENCIES)
178         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $<
179 -include #{dep}
181 CLEANFILES += #{command} #{fs} #{partmap} #{handler} #{parttool}
182 COMMANDFILES += #{command}
183 FSFILES += #{fs}
184 PARTTOOLFILES += #{parttool}
185 PARTMAPFILES += #{partmap}
186 HANDLERFILES += #{handler}
188 #{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh
189         set -e; \
190           $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
191           | sh $(srcdir)/gencmdlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
193 #{fs}: #{src} $(#{src}_DEPENDENCIES) genfslist.sh
194         set -e; \
195           $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
196           | sh $(srcdir)/genfslist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
198 #{parttool}: #{src} $(#{src}_DEPENDENCIES) genparttoollist.sh
199         set -e; \
200           $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
201           | sh $(srcdir)/genparttoollist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
203 #{partmap}: #{src} $(#{src}_DEPENDENCIES) genpartmaplist.sh
204         set -e; \
205           $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
206           | sh $(srcdir)/genpartmaplist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
208 #{handler}: #{src} $(#{src}_DEPENDENCIES) genhandlerlist.sh
209         set -e; \
210           $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
211           | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
214     end.join('')
215   end
218 class Utility
219   def initialize(dir, name)
220     @dir = dir
221     @name = name
222   end
223   def print_tail()
224     prefix = @name.to_var
225     print "#{@name}: $(#{prefix}_DEPENDENCIES) $(#{prefix}_OBJECTS)
226         $(CC) -o $@ $(#{prefix}_OBJECTS) $(LDFLAGS) $(#{prefix}_LDFLAGS)
229   end
230   attr_reader :dir, :name
232   def rule(sources)
233     prefix = @name.to_var
234     objs = sources.collect do |src|
235       raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
236       prefix + '-' + src.to_obj
237     end
238     objs_str = objs.join(' ');
239     deps = objs.collect {|obj| obj.suffix('d')}
240     deps_str = deps.join(' ');
242     "CLEANFILES += #{@name}$(EXEEXT) #{objs_str}
243 MOSTLYCLEANFILES += #{deps_str}
244 #{prefix}_OBJECTS += #{objs_str}
246 " + objs.collect_with_index do |obj, i|
247       src = sources[i]
248       fake_obj = File.basename(src).suffix('o')
249       dep = deps[i]
250       dir = File.dirname(src)
252       "#{obj}: #{src} $(#{src}_DEPENDENCIES)
253         $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(#{prefix}_CFLAGS) -MD -c -o $@ $<
254 -include #{dep}
257     end.join('')
258   end
261 class Program
262   def initialize(dir, name)
263     @dir = dir
264     @name = name
265   end
266   attr_reader :dir, :name
268   def rule(sources)
269     prefix = @name.to_var
270     objs = sources.collect do |src|
271       raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
272       prefix + '-' + src.to_obj
273     end
274     objs_str = objs.join(' ');
275     deps = objs.collect {|obj| obj.suffix('d')}
276     deps_str = deps.join(' ');
278     "CLEANFILES += #{@name} #{objs_str}
279 MOSTLYCLEANFILES += #{deps_str}
281 #{@name}: $(#{prefix}_DEPENDENCIES) #{objs_str}
282         $(TARGET_CC) -o $@ #{objs_str} $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS)
284 " + objs.collect_with_index do |obj, i|
285       src = sources[i]
286       fake_obj = File.basename(src).suffix('o')
287       dep = deps[i]
288       flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
289       extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
290       dir = File.dirname(src)
292       "#{obj}: #{src} $(#{src}_DEPENDENCIES)
293         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $<
294 -include #{dep}
297     end.join('')
298   end
301 class Script
302   def initialize(dir, name)
303     @dir = dir
304     @name = name
305   end
306   attr_reader :dir, :name
308   def rule(sources)
309     if sources.length != 1
310       raise "only a single source file must be specified for a script"
311     end
312     src = sources[0]
313     if /\.in$/ !~ src
314       raise "unknown source file `#{src}'"
315     end
317     "CLEANFILES += #{@name}
319 #{@name}: #{src} $(#{src}_DEPENDENCIES) config.status
320         ./config.status --file=#{name}:#{src}
321         chmod +x $@
324   end
327 images = []
328 utils = []
329 pmodules = []
330 programs = []
331 scripts = []
333 l = gets
334 print l
335 print "# Generated by genmk.rb, please don't edit!\n"
337 cont = false
338 str = nil
339 while l = gets
340   if cont
341     str += l
342   else
343     str = l
344   end
346   print l
347   cont = (/\\$/ =~ l)
348   unless cont
349     str.gsub!(/\\\n/, ' ')
351     if /^([a-zA-Z0-9_]+)\s*\+?=\s*(.*?)\s*$/ =~ str
352       var, args = $1, $2
354       if var =~ /^([a-zA-Z0-9_]+)_([A-Z]+)$/
355         prefix, type = $1, $2
357         case type
358         when 'IMAGES'
359           images += args.split(/\s+/).collect do |img|
360             Image.new(prefix, img)
361           end
363         when 'MODULES'
364           pmodules += args.split(/\s+/).collect do |pmod|
365             PModule.new(prefix, pmod)
366           end
368         when 'UTILITIES'
369           utils += args.split(/\s+/).collect do |util|
370             Utility.new(prefix, util)
371           end
373         when 'PROGRAMS'
374           programs += args.split(/\s+/).collect do |prog|
375             Program.new(prefix, prog)
376           end
378         when 'SCRIPTS'
379           scripts += args.split(/\s+/).collect do |script|
380             Script.new(prefix, script)
381           end
383         when 'SOURCES'
384           if img = images.detect() {|i| i.name.to_var == prefix}
385             print img.rule(args.split(/\s+/))
386           elsif pmod = pmodules.detect() {|m| m.name.to_var == prefix}
387             print pmod.rule(args.split(/\s+/))
388           elsif util = utils.detect() {|u| u.name.to_var == prefix}
389             print util.rule(args.split(/\s+/))
390           elsif program = programs.detect() {|u| u.name.to_var == prefix}
391             print program.rule(args.split(/\s+/))
392           elsif script = scripts.detect() {|s| s.name.to_var == prefix}
393             print script.rule(args.split(/\s+/))
394           end
395         end
396       end
398     end
400   end
403 utils.each {|util| util.print_tail()}