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