]> git.proxmox.com Git - grub2.git/blame - gentpl.py
cleanup: grub_cpu_to_XXX_compile_time for constants
[grub2.git] / gentpl.py
CommitLineData
8c411768 1#! /usr/bin/python
e3ec28ab 2# GRUB -- GRand Unified Bootloader
ab4f1501 3# Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc.
e3ec28ab
VS
4#
5# GRUB is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# GRUB is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
8c411768 17
aa437b58
MG
18from __future__ import print_function
19
ab4f1501
CW
20__metaclass__ = type
21
22from optparse import OptionParser
23import re
24
8c411768 25#
ab4f1501 26# This is the python script used to generate Makefile.*.am
8c411768
BC
27#
28
29GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
062cdbc1 30 "i386_multiboot", "i386_ieee1275", "x86_64_efi",
9612ebc0 31 "i386_xen", "x86_64_xen",
54da1feb 32 "mips_loongson", "sparc64_ieee1275",
3666d5f6 33 "powerpc_ieee1275", "mips_arc", "ia64_efi",
15a463d7 34 "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ]
8c411768
BC
35
36GROUPS = {}
eefe8abd
VS
37
38GROUPS["common"] = GRUB_PLATFORMS[:]
39
40# Groups based on CPU
8427685f
BC
41GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ]
42GROUPS["x86_64"] = [ "x86_64_efi" ]
43GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
3666d5f6 44GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
8427685f
BC
45GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
46GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
389b31cd 47GROUPS["arm"] = [ "arm_uboot", "arm_efi" ]
15a463d7 48GROUPS["arm64"] = [ "arm64_efi" ]
8427685f 49
eefe8abd 50# Groups based on firmware
15a463d7 51GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ]
8427685f 52GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
389b31cd 53GROUPS["uboot"] = [ "arm_uboot" ]
9612ebc0 54GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ]
8427685f 55
eefe8abd
VS
56# emu is a special case so many core functionality isn't needed on this platform
57GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
58
59# Groups based on hardware features
a07a81b3
VS
60GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
61 "sparc64_ieee1275", "powerpc_ieee1275"]
9612ebc0 62GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
bee1aeb9 63GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"]
eefe8abd 64GROUPS["usb"] = GROUPS["pci"]
8427685f 65
eefe8abd 66# If gfxterm is main output console integrate it into kernel
72c9a507 67GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ]
eefe8abd
VS
68GROUPS["videomodules"] = GRUB_PLATFORMS[:];
69for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
8427685f 70
ee74fa48 71# Similar for terminfo
9612ebc0 72GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["xen"] + GROUPS["ieee1275"] + GROUPS["uboot"];
ee74fa48
VS
73GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
74for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
75
389b31cd 76# Flattened Device Trees (FDT)
15a463d7 77GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ]
389b31cd 78
eefe8abd 79# Miscelaneous groups schedulded to disappear in future
eefe8abd
VS
80GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
81GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
8c411768
BC
82
83#
84# Create platform => groups reverse map, where groups covering that
85# platform are ordered by their sizes
86#
87RMAP = {}
88for platform in GRUB_PLATFORMS:
89 # initialize with platform itself as a group
90 RMAP[platform] = [ platform ]
91
92 for k in GROUPS.keys():
93 v = GROUPS[k]
94 # skip groups that don't cover this platform
95 if platform not in v: continue
96
97 bigger = []
98 smaller = []
99 # partition currently known groups based on their size
100 for group in RMAP[platform]:
101 if group in GRUB_PLATFORMS: smaller.append(group)
102 elif len(GROUPS[group]) < len(v): smaller.append(group)
103 else: bigger.append(group)
104 # insert in the middle
105 RMAP[platform] = smaller + [ k ] + bigger
106
ab4f1501
CW
107#
108# Input
109#
110
111# We support a subset of the AutoGen definitions file syntax. Specifically,
34b2003d
CW
112# compound names are disallowed; some preprocessing directives are
113# disallowed (though #if/#endif are allowed; note that, like AutoGen, #if
114# skips everything to the next #endif regardless of the value of the
115# conditional); and shell-generated strings, Scheme-generated strings, and
116# here strings are disallowed.
ab4f1501
CW
117
118class AutogenToken:
119 (autogen, definitions, eof, var_name, other_name, string, number,
120 semicolon, equals, comma, lbrace, rbrace, lbracket, rbracket) = range(14)
121
122class AutogenState:
123 (init, need_def, need_tpl, need_semi, need_name, have_name, need_value,
124 need_idx, need_rbracket, indx_name, have_value, done) = range(12)
125
126class AutogenParseError(Exception):
7e90f5ad 127 def __init__(self, message, path, line):
ab4f1501 128 super(AutogenParseError, self).__init__(message)
7e90f5ad 129 self.path = path
ab4f1501
CW
130 self.line = line
131
132 def __str__(self):
133 return (
134 super(AutogenParseError, self).__str__() +
7e90f5ad 135 " at file %s line %d" % (self.path, self.line))
ab4f1501
CW
136
137class AutogenDefinition(list):
138 def __getitem__(self, key):
139 try:
140 return super(AutogenDefinition, self).__getitem__(key)
141 except TypeError:
142 for name, value in self:
143 if name == key:
144 return value
145
146 def __contains__(self, key):
147 for name, value in self:
148 if name == key:
149 return True
150 return False
151
152 def get(self, key, default):
153 for name, value in self:
154 if name == key:
155 return value
156 else:
157 return default
158
159 def find_all(self, key):
160 for name, value in self:
161 if name == key:
162 yield value
163
164class AutogenParser:
165 def __init__(self):
166 self.definitions = AutogenDefinition()
167 self.def_stack = [("", self.definitions)]
168 self.curdef = None
169 self.new_name = None
7e90f5ad 170 self.cur_path = None
ab4f1501
CW
171 self.cur_line = 0
172
173 @staticmethod
174 def is_unquotable_char(c):
175 return (ord(c) in range(ord("!"), ord("~") + 1) and
176 c not in "#,;<=>[\\]`{}?*'\"()")
177
178 @staticmethod
179 def is_value_name_char(c):
180 return c in ":^-_" or c.isalnum()
181
7e90f5ad
CW
182 def error(self, message):
183 raise AutogenParseError(message, self.cur_file, self.cur_line)
184
ab4f1501
CW
185 def read_tokens(self, f):
186 data = f.read()
187 end = len(data)
188 offset = 0
189 while offset < end:
190 while offset < end and data[offset].isspace():
191 if data[offset] == "\n":
192 self.cur_line += 1
193 offset += 1
194 if offset >= end:
195 break
196 c = data[offset]
34b2003d
CW
197 if c == "#":
198 offset += 1
199 try:
200 end_directive = data.index("\n", offset)
201 directive = data[offset:end_directive]
202 offset = end_directive
203 except ValueError:
204 directive = data[offset:]
205 offset = end
206 name, value = directive.split(None, 1)
207 if name == "if":
208 try:
209 end_if = data.index("\n#endif", offset)
210 new_offset = end_if + len("\n#endif")
211 self.cur_line += data[offset:new_offset].count("\n")
212 offset = new_offset
213 except ValueError:
214 self.error("#if without matching #endif")
215 else:
216 self.error("Unhandled directive '#%s'" % name)
217 elif c == "{":
ab4f1501
CW
218 yield AutogenToken.lbrace, c
219 offset += 1
220 elif c == "=":
221 yield AutogenToken.equals, c
222 offset += 1
223 elif c == "}":
224 yield AutogenToken.rbrace, c
225 offset += 1
226 elif c == "[":
227 yield AutogenToken.lbracket, c
228 offset += 1
229 elif c == "]":
230 yield AutogenToken.rbracket, c
231 offset += 1
232 elif c == ";":
233 yield AutogenToken.semicolon, c
234 offset += 1
235 elif c == ",":
236 yield AutogenToken.comma, c
237 offset += 1
238 elif c in ("'", '"'):
239 s = []
240 while True:
241 offset += 1
242 if offset >= end:
7e90f5ad 243 self.error("EOF in quoted string")
ab4f1501
CW
244 if data[offset] == "\n":
245 self.cur_line += 1
246 if data[offset] == "\\":
247 offset += 1
248 if offset >= end:
7e90f5ad 249 self.error("EOF in quoted string")
ab4f1501
CW
250 if data[offset] == "\n":
251 self.cur_line += 1
252 # Proper escaping unimplemented; this can be filled
253 # out if needed.
254 s.append("\\")
255 s.append(data[offset])
256 elif data[offset] == c:
257 offset += 1
258 break
259 else:
260 s.append(data[offset])
261 yield AutogenToken.string, "".join(s)
34b2003d
CW
262 elif c == "/":
263 offset += 1
264 if data[offset] == "*":
265 offset += 1
266 try:
267 end_comment = data.index("*/", offset)
268 new_offset = end_comment + len("*/")
269 self.cur_line += data[offset:new_offset].count("\n")
270 offset = new_offset
271 except ValueError:
272 self.error("/* without matching */")
273 elif data[offset] == "/":
274 try:
275 offset = data.index("\n", offset)
276 except ValueError:
277 pass
ab4f1501
CW
278 elif (c.isdigit() or
279 (c == "-" and offset < end - 1 and
280 data[offset + 1].isdigit())):
281 end_number = offset + 1
282 while end_number < end and data[end_number].isdigit():
283 end_number += 1
284 yield AutogenToken.number, data[offset:end_number]
285 offset = end_number
286 elif self.is_unquotable_char(c):
287 end_name = offset
288 while (end_name < end and
289 self.is_value_name_char(data[end_name])):
290 end_name += 1
291 if end_name < end and self.is_unquotable_char(data[end_name]):
292 while (end_name < end and
293 self.is_unquotable_char(data[end_name])):
294 end_name += 1
295 yield AutogenToken.other_name, data[offset:end_name]
296 offset = end_name
297 else:
298 s = data[offset:end_name]
299 if s.lower() == "autogen":
300 yield AutogenToken.autogen, s
301 elif s.lower() == "definitions":
302 yield AutogenToken.definitions, s
303 else:
304 yield AutogenToken.var_name, s
305 offset = end_name
306 else:
7e90f5ad 307 self.error("Invalid input character '%s'" % c)
ab4f1501
CW
308 yield AutogenToken.eof, None
309
310 def do_need_name_end(self, token):
311 if len(self.def_stack) > 1:
7e90f5ad 312 self.error("Definition blocks were left open")
ab4f1501
CW
313
314 def do_need_name_var_name(self, token):
315 self.new_name = token
316
317 def do_end_block(self, token):
318 if len(self.def_stack) <= 1:
7e90f5ad 319 self.error("Too many close braces")
ab4f1501
CW
320 new_name, parent_def = self.def_stack.pop()
321 parent_def.append((new_name, self.curdef))
322 self.curdef = parent_def
323
324 def do_empty_val(self, token):
325 self.curdef.append((self.new_name, ""))
326
327 def do_str_value(self, token):
328 self.curdef.append((self.new_name, token))
329
330 def do_start_block(self, token):
331 self.def_stack.append((self.new_name, self.curdef))
332 self.curdef = AutogenDefinition()
333
334 def do_indexed_name(self, token):
335 self.new_name = token
336
7e90f5ad 337 def read_definitions_file(self, f):
ab4f1501
CW
338 self.curdef = self.definitions
339 self.cur_line = 0
340 state = AutogenState.init
341
342 # The following transition table was reduced from the Autogen
343 # documentation:
344 # info -f autogen -n 'Full Syntax'
345 transitions = {
346 AutogenState.init: {
347 AutogenToken.autogen: (AutogenState.need_def, None),
348 },
349 AutogenState.need_def: {
350 AutogenToken.definitions: (AutogenState.need_tpl, None),
351 },
352 AutogenState.need_tpl: {
353 AutogenToken.var_name: (AutogenState.need_semi, None),
354 AutogenToken.other_name: (AutogenState.need_semi, None),
355 AutogenToken.string: (AutogenState.need_semi, None),
356 },
357 AutogenState.need_semi: {
358 AutogenToken.semicolon: (AutogenState.need_name, None),
359 },
360 AutogenState.need_name: {
361 AutogenToken.autogen: (AutogenState.need_def, None),
362 AutogenToken.eof: (AutogenState.done, self.do_need_name_end),
363 AutogenToken.var_name: (
364 AutogenState.have_name, self.do_need_name_var_name),
365 AutogenToken.rbrace: (
366 AutogenState.have_value, self.do_end_block),
367 },
368 AutogenState.have_name: {
369 AutogenToken.semicolon: (
370 AutogenState.need_name, self.do_empty_val),
371 AutogenToken.equals: (AutogenState.need_value, None),
372 AutogenToken.lbracket: (AutogenState.need_idx, None),
373 },
374 AutogenState.need_value: {
375 AutogenToken.var_name: (
376 AutogenState.have_value, self.do_str_value),
377 AutogenToken.other_name: (
378 AutogenState.have_value, self.do_str_value),
379 AutogenToken.string: (
380 AutogenState.have_value, self.do_str_value),
381 AutogenToken.number: (
382 AutogenState.have_value, self.do_str_value),
383 AutogenToken.lbrace: (
384 AutogenState.need_name, self.do_start_block),
385 },
386 AutogenState.need_idx: {
387 AutogenToken.var_name: (
388 AutogenState.need_rbracket, self.do_indexed_name),
389 AutogenToken.number: (
390 AutogenState.need_rbracket, self.do_indexed_name),
391 },
392 AutogenState.need_rbracket: {
393 AutogenToken.rbracket: (AutogenState.indx_name, None),
394 },
395 AutogenState.indx_name: {
396 AutogenToken.semicolon: (
397 AutogenState.need_name, self.do_empty_val),
398 AutogenToken.equals: (AutogenState.need_value, None),
399 },
400 AutogenState.have_value: {
401 AutogenToken.semicolon: (AutogenState.need_name, None),
402 AutogenToken.comma: (AutogenState.need_value, None),
403 },
404 }
405
406 for code, token in self.read_tokens(f):
407 if code in transitions[state]:
408 state, handler = transitions[state][code]
409 if handler is not None:
410 handler(token)
411 else:
7e90f5ad 412 self.error(
ab4f1501 413 "Parse error in state %s: unexpected token '%s'" % (
7e90f5ad 414 state, token))
ab4f1501
CW
415 if state == AutogenState.done:
416 break
417
7e90f5ad
CW
418 def read_definitions(self, path):
419 self.cur_file = path
420 with open(path) as f:
421 self.read_definitions_file(f)
422
ab4f1501
CW
423defparser = AutogenParser()
424
425#
426# Output
427#
428
429outputs = {}
430
431def output(s, section=''):
432 if s == "":
433 return
434 outputs.setdefault(section, [])
435 outputs[section].append(s)
436
437def write_output(section=''):
438 for s in outputs.get(section, []):
aa437b58 439 print(s, end='')
ab4f1501 440
8c411768
BC
441#
442# Global variables
443#
8c411768
BC
444
445def gvar_add(var, value):
ab4f1501 446 output(var + " += " + value + "\n")
8c411768
BC
447
448#
449# Per PROGRAM/SCRIPT variables
450#
451
ab4f1501
CW
452seen_vars = set()
453
454def vars_init(defn, *var_list):
455 name = defn['name']
456
457 if name not in seen_target and name not in seen_vars:
458 for var in var_list:
459 output(var + " = \n", section='decl')
460 seen_vars.add(name)
e1fd1939 461
8c411768 462def var_set(var, value):
ab4f1501 463 output(var + " = " + value + "\n")
8c411768
BC
464
465def var_add(var, value):
ab4f1501 466 output(var + " += " + value + "\n")
8c411768
BC
467
468#
ab4f1501 469# Variable names and rules
8c411768
BC
470#
471
ab4f1501
CW
472canonical_name_re = re.compile(r'[^0-9A-Za-z@_]')
473canonical_name_suffix = ""
474
475def set_canonical_name_suffix(suffix):
476 global canonical_name_suffix
477 canonical_name_suffix = suffix
478
479def cname(defn):
480 return canonical_name_re.sub('_', defn['name'] + canonical_name_suffix)
8c411768 481
911bd640
BC
482def rule(target, source, cmd):
483 if cmd[0] == "\n":
ab4f1501 484 output("\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n")
911bd640 485 else:
ab4f1501 486 output("\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n")
8c411768 487
d9b78bce 488#
ab4f1501 489# Handle keys with platform names as values, for example:
d9b78bce
BC
490#
491# kernel = {
492# nostrip = emu;
f6023b61 493# ...
d9b78bce
BC
494# }
495#
ab4f1501
CW
496def platform_tagged(defn, platform, tag):
497 for value in defn.find_all(tag):
498 for group in RMAP[platform]:
499 if value == group:
500 return True
501 return False
8c411768 502
ab4f1501
CW
503def if_platform_tagged(defn, platform, tag, snippet_if, snippet_else=None):
504 if platform_tagged(defn, platform, tag):
505 return snippet_if
506 elif snippet_else is not None:
507 return snippet_else
8c411768 508
d9b78bce 509#
ab4f1501 510# Handle tagged values
8427685f
BC
511#
512# module = {
513# extra_dist = ...
514# extra_dist = ...
515# ...
516# };
517#
ab4f1501
CW
518def foreach_value(defn, tag, closure):
519 r = []
520 for value in defn.find_all(tag):
521 r.append(closure(value))
522 return ''.join(r)
8427685f
BC
523
524#
ab4f1501 525# Handle best matched values for a platform, for example:
d9b78bce
BC
526#
527# module = {
528# cflags = '-Wall';
529# emu_cflags = '-Wall -DGRUB_EMU=1';
f6023b61 530# ...
d9b78bce
BC
531# }
532#
ab4f1501
CW
533def foreach_platform_specific_value(defn, platform, suffix, nonetag, closure):
534 r = []
911bd640 535 for group in RMAP[platform]:
ab4f1501
CW
536 values = list(defn.find_all(group + suffix))
537 if values:
538 for value in values:
539 r.append(closure(value))
540 break
541 else:
542 for value in defn.find_all(nonetag):
543 r.append(closure(value))
544 return ''.join(r)
8667a314 545
8427685f 546#
ab4f1501 547# Handle values from sum of all groups for a platform, for example:
8427685f
BC
548#
549# module = {
550# common = kern/misc.c;
551# emu = kern/emu/misc.c;
552# ...
553# }
554#
ab4f1501
CW
555def foreach_platform_value(defn, platform, suffix, closure):
556 r = []
8427685f 557 for group in RMAP[platform]:
ab4f1501
CW
558 for value in defn.find_all(group + suffix):
559 r.append(closure(value))
560 return ''.join(r)
8427685f 561
ab4f1501
CW
562def platform_conditional(platform, closure):
563 output("\nif COND_" + platform + "\n")
564 closure(platform)
565 output("endif\n")
8c411768 566
8427685f 567#
ab4f1501 568# Handle guarding with platform-specific "enable" keys, for example:
8427685f
BC
569#
570# module = {
571# name = pci;
572# noemu = bus/pci.c;
573# emu = bus/emu/pci.c;
574# emu = commands/lspci.c;
575#
576# enable = emu;
577# enable = i386_pc;
578# enable = x86_efi;
579# enable = i386_ieee1275;
580# enable = i386_coreboot;
581# };
582#
ab4f1501
CW
583def foreach_enabled_platform(defn, closure):
584 if 'enable' in defn:
585 for platform in GRUB_PLATFORMS:
586 if platform_tagged(defn, platform, "enable"):
587 platform_conditional(platform, closure)
588 else:
589 for platform in GRUB_PLATFORMS:
590 platform_conditional(platform, closure)
d9b78bce 591
8427685f 592#
ab4f1501 593# Handle guarding with platform-specific automake conditionals, for example:
8427685f
BC
594#
595# module = {
596# name = usb;
597# common = bus/usb/usb.c;
598# noemu = bus/usb/usbtrans.c;
599# noemu = bus/usb/usbhub.c;
600# enable = emu;
601# enable = i386;
54da1feb 602# enable = mips_loongson;
8427685f
BC
603# emu_condition = COND_GRUB_EMU_USB;
604# };
605#
ab4f1501
CW
606def under_platform_specific_conditionals(defn, platform, closure):
607 output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "if " + cond + "\n"))
608 closure(defn, platform)
609 output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "endif " + cond + "\n"))
610
611def platform_specific_values(defn, platform, suffix, nonetag):
612 return foreach_platform_specific_value(defn, platform, suffix, nonetag,
8427685f 613 lambda value: value + " ")
911bd640 614
ab4f1501
CW
615def platform_values(defn, platform, suffix):
616 return foreach_platform_value(defn, platform, suffix, lambda value: value + " ")
617
618def extra_dist(defn):
619 return foreach_value(defn, "extra_dist", lambda value: value + " ")
620
621def platform_sources(defn, p): return platform_values(defn, p, "")
622def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist")
623
624def platform_startup(defn, p): return platform_specific_values(defn, p, "_startup", "startup")
625def platform_ldadd(defn, p): return platform_specific_values(defn, p, "_ldadd", "ldadd")
626def platform_dependencies(defn, p): return platform_specific_values(defn, p, "_dependencies", "dependencies")
627def platform_cflags(defn, p): return platform_specific_values(defn, p, "_cflags", "cflags")
628def platform_ldflags(defn, p): return platform_specific_values(defn, p, "_ldflags", "ldflags")
629def platform_cppflags(defn, p): return platform_specific_values(defn, p, "_cppflags", "cppflags")
630def platform_ccasflags(defn, p): return platform_specific_values(defn, p, "_ccasflags", "ccasflags")
631def platform_stripflags(defn, p): return platform_specific_values(defn, p, "_stripflags", "stripflags")
632def platform_objcopyflags(defn, p): return platform_specific_values(defn, p, "_objcopyflags", "objcopyflags")
8c411768 633
e1fd1939
CW
634#
635# Emit snippet only the first time through for the current name.
636#
ab4f1501
CW
637seen_target = set()
638
639def first_time(defn, snippet):
640 if defn['name'] not in seen_target:
641 return snippet
642 return ''
643
b1f742c1
VS
644def is_platform_independent(defn):
645 if 'enable' in defn:
646 return False
647 for suffix in [ "", "_nodist" ]:
648 template = platform_values(defn, GRUB_PLATFORMS[0], suffix)
649 for platform in GRUB_PLATFORMS[1:]:
650 if template != platform_values(defn, platform, suffix):
651 return False
652
653 for suffix in [ "startup", "ldadd", "dependencies", "cflags", "ldflags", "cppflags", "ccasflags", "stripflags", "objcopyflags", "condition" ]:
654 template = platform_specific_values(defn, GRUB_PLATFORMS[0], "_" + suffix, suffix)
655 for platform in GRUB_PLATFORMS[1:]:
656 if template != platform_specific_values(defn, platform, "_" + suffix, suffix):
657 return False
658 for tag in [ "nostrip" ]:
659 template = platform_tagged(defn, GRUB_PLATFORMS[0], tag)
660 for platform in GRUB_PLATFORMS[1:]:
661 if template != platform_tagged(defn, platform, tag):
662 return False
663
664 return True
665
ab4f1501
CW
666def module(defn, platform):
667 name = defn['name']
668 set_canonical_name_suffix(".module")
669
670 gvar_add("platform_PROGRAMS", name + ".module")
671 gvar_add("MODULE_FILES", name + ".module$(EXEEXT)")
672
673 var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources")
674 var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources")
675 var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
676 var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform))
677 var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform))
678 var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform))
679 var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform))
680 var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform))
681
682 gvar_add("dist_noinst_DATA", extra_dist(defn))
683 gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
684 gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
685
686 gvar_add("MOD_FILES", name + ".mod")
687 gvar_add("MARKER_FILES", name + ".marker")
688 gvar_add("CLEANFILES", name + ".marker")
689 output("""
690""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES)
691 $(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1)
6568636e 692 grep 'MARKER' $@.new > $@; rm -f $@.new
ab4f1501
CW
693""")
694
695def kernel(defn, platform):
696 name = defn['name']
697 set_canonical_name_suffix(".exec")
698 gvar_add("platform_PROGRAMS", name + ".exec")
699 var_set(cname(defn) + "_SOURCES", platform_startup(defn, platform))
700 var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform))
701 var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources")
702 var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
703 var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_KERNEL) " + platform_cflags(defn, platform))
704 var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_KERNEL) " + platform_ldflags(defn, platform))
705 var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) " + platform_cppflags(defn, platform))
706 var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_KERNEL) " + platform_ccasflags(defn, platform))
707 var_set(cname(defn) + "_STRIPFLAGS", "$(AM_STRIPFLAGS) $(STRIPFLAGS_KERNEL) " + platform_stripflags(defn, platform))
708 var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF)")
709
710 gvar_add("dist_noinst_DATA", extra_dist(defn))
711 gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
712 gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
713
714 gvar_add("platform_DATA", name + ".img")
715 gvar_add("CLEANFILES", name + ".img")
716 rule(name + ".img", name + ".exec$(EXEEXT)",
717 if_platform_tagged(defn, platform, "nostrip",
a9f25a08 718"""if test x$(TARGET_APPLE_LINKER) = x1; then \
fc97214f 719 $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \
22899b9c 720 elif test ! -z '$(TARGET_OBJ2ELF)'; then \
60b967be 721 $(TARGET_OBJ2ELF) $< $@ || (rm -f $@; exit 1); \
22899b9c 722 else cp $< $@; fi""",
a9f25a08 723"""if test x$(TARGET_APPLE_LINKER) = x1; then \
ab4f1501 724 $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \
c8f7614b 725 $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \
60b967be
VS
726 elif test ! -z '$(TARGET_OBJ2ELF)'; then \
727 """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \
728 $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \
ab4f1501 729else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \
22899b9c 730fi"""))
ab4f1501
CW
731
732def image(defn, platform):
733 name = defn['name']
734 set_canonical_name_suffix(".image")
735 gvar_add("platform_PROGRAMS", name + ".image")
736 var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform))
737 var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + "## platform nodist sources")
738 var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
739 var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_IMAGE) " + platform_cflags(defn, platform))
740 var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_IMAGE) " + platform_ldflags(defn, platform))
741 var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_IMAGE) " + platform_cppflags(defn, platform))
742 var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_IMAGE) " + platform_ccasflags(defn, platform))
743 var_set(cname(defn) + "_OBJCOPYFLAGS", "$(OBJCOPYFLAGS_IMAGE) " + platform_objcopyflags(defn, platform))
744 # var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
745
746 gvar_add("dist_noinst_DATA", extra_dist(defn))
747 gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
748 gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
749
750 gvar_add("platform_DATA", name + ".img")
751 gvar_add("CLEANFILES", name + ".img")
752 rule(name + ".img", name + ".image$(EXEEXT)", """
a9f25a08 753if test x$(TARGET_APPLE_LINKER) = x1; then \
8c411768
BC
754 $(MACHO2IMG) $< $@; \
755else \
ab4f1501 756 $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \
8c411768
BC
757fi
758""")
ab4f1501
CW
759
760def library(defn, platform):
761 name = defn['name']
762 set_canonical_name_suffix("")
763
764 vars_init(defn,
765 cname(defn) + "_SOURCES",
766 "nodist_" + cname(defn) + "_SOURCES",
767 cname(defn) + "_CFLAGS",
768 cname(defn) + "_CPPFLAGS",
769 cname(defn) + "_CCASFLAGS")
770 # cname(defn) + "_DEPENDENCIES")
771
772 if name not in seen_target:
773 gvar_add("noinst_LIBRARIES", name)
774 var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform))
775 var_add("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform))
776 var_add(cname(defn) + "_CFLAGS", first_time(defn, "$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(defn, platform))
777 var_add(cname(defn) + "_CPPFLAGS", first_time(defn, "$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(defn, platform))
778 var_add(cname(defn) + "_CCASFLAGS", first_time(defn, "$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(defn, platform))
779 # var_add(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
780
781 gvar_add("dist_noinst_DATA", extra_dist(defn))
782 if name not in seen_target:
783 gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
784 gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
785
786def installdir(defn, default="bin"):
787 return defn.get('installdir', default)
788
789def manpage(defn, adddeps):
790 name = defn['name']
791 mansection = defn['mansection']
792
793 output("if COND_MAN_PAGES\n")
794 gvar_add("man_MANS", name + "." + mansection)
795 rule(name + "." + mansection, name + " " + adddeps, """
796chmod a+x """ + name + """
797PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """
8c411768 798""")
ab4f1501
CW
799 gvar_add("CLEANFILES", name + "." + mansection)
800 output("endif\n")
801
802def program(defn, platform, test=False):
803 name = defn['name']
804 set_canonical_name_suffix("")
805
806 if 'testcase' in defn:
807 gvar_add("check_PROGRAMS", name)
808 gvar_add("TESTS", name)
809 else:
810 var_add(installdir(defn) + "_PROGRAMS", name)
811 if 'mansection' in defn:
812 manpage(defn, "")
813
814 var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform))
815 var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform))
816 var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
817 var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_PROGRAM) " + platform_cflags(defn, platform))
818 var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_PROGRAM) " + platform_ldflags(defn, platform))
819 var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_PROGRAM) " + platform_cppflags(defn, platform))
820 var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_PROGRAM) " + platform_ccasflags(defn, platform))
821 # var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform))
822
823 gvar_add("dist_noinst_DATA", extra_dist(defn))
824 gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
825 gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
826
827def data(defn, platform):
828 var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform))
829 gvar_add("dist_noinst_DATA", extra_dist(defn))
830
831def script(defn, platform):
832 name = defn['name']
833
834 if 'testcase' in defn:
835 gvar_add("check_SCRIPTS", name)
836 gvar_add ("TESTS", name)
837 else:
838 var_add(installdir(defn) + "_SCRIPTS", name)
839 if 'mansection' in defn:
840 manpage(defn, "grub-mkconfig_lib")
841
842 rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """
843(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
844chmod a+x """ + name + """
8c411768
BC
845""")
846
ab4f1501
CW
847 gvar_add("CLEANFILES", name)
848 gvar_add("EXTRA_DIST", extra_dist(defn))
849 gvar_add("dist_noinst_DATA", platform_sources(defn, platform))
8c411768 850
e1fd1939 851def rules(target, closure):
ab4f1501
CW
852 seen_target.clear()
853 seen_vars.clear()
854
855 for defn in defparser.definitions.find_all(target):
b1f742c1
VS
856 if is_platform_independent(defn):
857 under_platform_specific_conditionals(defn, GRUB_PLATFORMS[0], closure)
858 else:
859 foreach_enabled_platform(
860 defn,
861 lambda p: under_platform_specific_conditionals(defn, p, closure))
ab4f1501
CW
862 # Remember that we've seen this target.
863 seen_target.add(defn['name'])
864
865parser = OptionParser(usage="%prog DEFINITION-FILES")
866_, args = parser.parse_args()
867
868for arg in args:
7e90f5ad 869 defparser.read_definitions(arg)
ab4f1501
CW
870
871rules("module", module)
872rules("kernel", kernel)
873rules("image", image)
874rules("library", library)
875rules("program", program)
876rules("script", script)
877rules("data", data)
878
879write_output(section='decl')
880write_output()