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