mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
filesystems per default. On those systems checking out coreboot v1 would fail because in src/arch/<ARCH> there's a file Config and a directory config. I renamed the directory to init. The name is not good, but it's the same name that is used for those files in v2. Also change __FUNCTION__ to __func__ and print it via %s so that I could test my changes by building the v1 Epia target on an OpenSUSE 11.1 Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Stefan Reinauer <stepan@coresystems.de>
1196 lines
37 KiB
Python
1196 lines
37 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Usage: python NLBConfig.py configfile freebiospath
|
|
|
|
# Based on the commands in the user-supplied configfile, and several other
|
|
# config files known to this program, this program generates a Makefile,
|
|
# Makefile.settings, crt0.S file, etc. in the target directory, which is
|
|
# specified by the 'target' command in the user's configfile. For more
|
|
# info, see .../freebios/Documentation/Config
|
|
|
|
# $Id$
|
|
# Author:
|
|
# Modified by Jan Kok to improve readability of Makefile, etc.
|
|
import sys
|
|
import os
|
|
import re
|
|
import string
|
|
|
|
debug = 0
|
|
|
|
# device variables
|
|
superio_decls = ''
|
|
superio_devices = []
|
|
numsuperio = 0
|
|
|
|
# Architecture variables
|
|
arch = ''
|
|
makebase = ''
|
|
ldscriptbase = ''
|
|
|
|
makeoptions = {}
|
|
makeexpressions = []
|
|
|
|
# Key is the rule name. Value is a mkrule object.
|
|
makebaserules = {}
|
|
|
|
# List of targets in the order defined by makerule commands.
|
|
makerule_targets = []
|
|
|
|
treetop = ''
|
|
target_dir = ''
|
|
|
|
sources = []
|
|
objectrules = []
|
|
userdefines = []
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Error Handling
|
|
# -----------------------------------------------------------------------------
|
|
|
|
class location:
|
|
class place:
|
|
def __init__(self, file, line, command):
|
|
self.file = file
|
|
self.line = line
|
|
self.command = command
|
|
def next_line(self, command):
|
|
self.line = self.line + 1
|
|
self.command = command
|
|
def at(self):
|
|
return "%s:%d" % (self.file, self.line)
|
|
|
|
def __init__ (self):
|
|
self.stack = []
|
|
|
|
def file(self):
|
|
return self.stack[-1].file
|
|
def line(self):
|
|
return self.stack[-1].line
|
|
def command(self):
|
|
return self.stack[-1].command
|
|
|
|
def push_file(self, file):
|
|
self.stack.append(self.place(file, 0, ""))
|
|
def pop_file(self):
|
|
self.stack.pop()
|
|
def next_line(self, command):
|
|
self.stack[-1].next_line(command)
|
|
def at(self):
|
|
return self.stack[-1].at()
|
|
loc = location()
|
|
|
|
def fatal(string):
|
|
global loc
|
|
size = len(loc.stack)
|
|
i = 0
|
|
while(i < size -1):
|
|
print loc.stack[i].at()
|
|
i = i + 1
|
|
print "%s: %s"% (loc.at(), string)
|
|
sys.exit(1)
|
|
|
|
def warning(string):
|
|
global loc
|
|
print "===> Warning:"
|
|
size = len(loc.stack)
|
|
i = 0
|
|
while(i < size -1):
|
|
print loc.stack[i].at()
|
|
i = i + 1
|
|
print "%s: %s"% (loc.at(), string)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Rules
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# this is the absolute base rule, and so is very special.
|
|
mainrulelist = "all"
|
|
|
|
def add_main_rule_dependency(new_dependency):
|
|
global mainrulelist
|
|
mainrulelist = mainrulelist + ' ' + new_dependency
|
|
|
|
# function to add an object to the set of objects to be made.
|
|
# this is a tuple, object name, source it depends on,
|
|
# and an optional rule (can be empty) for actually building
|
|
# the object
|
|
def addobject(object, sourcepath, rule, condition, variable):
|
|
sourcepath = topify(sourcepath)
|
|
objectrules.append([object, sourcepath, rule, condition, variable])
|
|
|
|
# OK, let's face it, make sucks.
|
|
# if you have a rule like this:
|
|
# a.o: /some/long/path/a.c
|
|
# make won't apply the .c.o rule. Toy!
|
|
|
|
def addobject_defaultrule(object, sourcepath, condition, variable):
|
|
# c_defaultrule = "$(CC) -c $(CFLAGS) -o $@ $<"
|
|
c_defaultrule = "@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CFLAGS) -o $@ $<"
|
|
s_defaultrule = "@echo $(CC) ... -o $@ $<\n\t@$(CC) -c $(CPU_OPT) -o $@ $<"
|
|
S_defaultrule = "@echo $(CPP) ... $< > $@\n\t@$(CPP) $(CPPFLAGS) $< >$@.new && mv $@.new $@"
|
|
# Compute the source file name
|
|
if (sourcepath[-2:] != '.c') and (sourcepath[-2:] != '.S'):
|
|
base = object[:-2]
|
|
sourcepath = os.path.join(sourcepath, base) + '.c'
|
|
|
|
sources.append(sourcepath)
|
|
if (sourcepath[-2:] == '.c'):
|
|
defaultrule = "\t" + c_defaultrule
|
|
elif (sourcepath[-2:] == '.S'):
|
|
base = os.path.basename(sourcepath)
|
|
s_name = base[:-2] + '.s'
|
|
mkrule(s_name, sourcepath, [ S_defaultrule ] )
|
|
sourcepath = s_name
|
|
defaultrule = "\t" + s_defaultrule
|
|
else:
|
|
fatal("Invalid object suffix")
|
|
addobject(object, sourcepath, defaultrule, condition, variable)
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Class for storing and printing make rules
|
|
# -----------------------------------------------------------------------------
|
|
|
|
class mkrule:
|
|
|
|
# This defines the function mkrule(target, depends, action).
|
|
# It creates a makerule object and records it for later recall.
|
|
def __init__(self, target, depends, actions):
|
|
self.whence = loc.file()
|
|
self.comments = [] # list of strings
|
|
self.target = target # string
|
|
self.depends = depends # string of dependency names
|
|
self.actions = actions # list of strings
|
|
if makebaserules.has_key(target):
|
|
warning("makerule for target '%s' is replacing previous defintion in file %s" %
|
|
(target, makebaserules[target].whence))
|
|
else:
|
|
# Keep a list of targets so we can output the rules
|
|
# in the order that they are defined.
|
|
makerule_targets.append(target)
|
|
# I remember myself, therefore I am.
|
|
makebaserules[target] = self
|
|
|
|
def adddepend(self, depend):
|
|
self.depends = self.depends + ' ' + depend
|
|
|
|
def addaction(self, action):
|
|
self.actions.append(action)
|
|
|
|
def write(self, file):
|
|
file.write("\n")
|
|
|
|
if 1: # Put comments before target : dependencies line.
|
|
file.write("# from: %s\n" % self.whence)
|
|
for comment in self.comments:
|
|
file.write("# %s\n" % comment)
|
|
|
|
# Write the target : dependencies line.
|
|
file.write("%s: %s\n" % (self.target, self.depends))
|
|
|
|
if 0: # Put comments after target : dependencies line,
|
|
# which causes them to be printed during make.
|
|
file.write("\t# from: %s\n" % self.whence)
|
|
for comment in self.comments:
|
|
file.write("\t# %s\n" % comment)
|
|
|
|
# Write out the actions.
|
|
for action in self.actions:
|
|
file.write("\t%s\n" % action)
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Command parsing functions
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Match a compiled pattern with a string, die if fails, return list of groups.
|
|
def match(pattern, string):
|
|
m = pattern.match(string)
|
|
if not m:
|
|
fatal("Bad command sytax")
|
|
return m.groups()
|
|
|
|
# A common pattern: <nonwhitespace><whitespace><rest of line>
|
|
splitargs_re = re.compile(r'(\S*)\s*(.*)')
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Command execution functions
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# For all these functions,
|
|
# dir is the directory that the current Config file is in
|
|
# the second arg is the remainder of the command line (for most commands
|
|
# any comments are stripped off)
|
|
|
|
# COMMAND: target <target-name>
|
|
# target must be the first command in the file. This command may only be
|
|
# used once. target names the target directory for building this
|
|
# instance of the BIOS. The target directory will be $(TOP)/<target-name>.
|
|
def target(dir, targ_name):
|
|
global target_dir
|
|
target_dir = os.path.join(os.path.dirname(loc.file()), targ_name)
|
|
if not os.path.isdir(target_dir):
|
|
print 'Creating directory', target_dir
|
|
os.makedirs(target_dir)
|
|
print 'Will place Makefile, crt0.S, etc. in ', target_dir
|
|
|
|
# dir should be the path to a directory containing a Config file.
|
|
# If so, process the commands in that config file right now.
|
|
def handleconfig(dir):
|
|
file = os.path.join(dir, 'Config')
|
|
print "Process config file: ", file
|
|
if os.path.isfile(file):
|
|
doconfigfile(dir, file)
|
|
else:
|
|
warning("%s not found" % file)
|
|
|
|
# type is the command name, e.g. 'northbridge'
|
|
# name is the path arg that followed the command
|
|
# <treetop>/src/<command>/<name>/Config is executed.
|
|
def common_command_action(dir, type, name):
|
|
realpath = os.path.join(treetop, 'src', type, name)
|
|
handleconfig(realpath)
|
|
return realpath
|
|
|
|
# COMMAND: arch <my_arch>
|
|
# <my_arch> is typically i386 or alpha.
|
|
# Set various variables and execute a make.base file.
|
|
def set_arch(dir, my_arch):
|
|
global arch, makebase
|
|
arch = my_arch
|
|
configpath = os.path.join(treetop, "src/arch/", my_arch, "init")
|
|
makebase = os.path.join(configpath, "make.base")
|
|
print "Now Process the ", my_arch, " base files"
|
|
if (debug):
|
|
print "Makebase is :", makebase, ":"
|
|
doconfigfile(treetop, makebase)
|
|
|
|
# COMMAND: dir <name>
|
|
# Execute the config file at <name>/Config
|
|
# If <name> begins with "/", it is interpreted as relative to $TOP,
|
|
# otherwise it is interpreted as relative to the directory of the config
|
|
# file that invoked this dir command.
|
|
def dir(base_dir, name):
|
|
regexp = re.compile(r"^/(.*)")
|
|
m = regexp.match(name)
|
|
if m and m.group(1):
|
|
# /dir
|
|
fullpath = os.path.join(treetop, m.group(1))
|
|
else:
|
|
# dir
|
|
fullpath = os.path.join(base_dir, name)
|
|
handleconfig(fullpath)
|
|
|
|
# The mainboard directory, as an absolute path. We need to remember this
|
|
# because the docipl command generates Makefile code that includes files
|
|
# from this directory.
|
|
mainboard_dir = None
|
|
|
|
# COMMAND: mainboard <mainboard name>
|
|
# The second command in a top-level config file is the mainboard command.
|
|
# This command may only be used once. The mainboard command names a mainboard
|
|
# source directory to use. The file $(TOP)/src/<mainboard name>/Config
|
|
# is executed.
|
|
def mainboard(dir, mainboard_name):
|
|
global mainboard_dir
|
|
set_option('MAINBOARD_PART_NUMBER', os.path.basename(mainboard_name))
|
|
set_option('MAINBOARD_VENDOR', os.path.dirname(mainboard_name))
|
|
mainboard_dir = common_command_action(dir, 'mainboard', mainboard_name)
|
|
|
|
# COMMAND: etherboot <network_device_name>
|
|
# Execute the file $(TOP)/src/etherboot/Config and set some Makefile variables.
|
|
def etherboot(dir, net_name):
|
|
common_command_action(dir, 'etherboot', '')
|
|
option(dir,'OLD_KERNEL_HACK')
|
|
option(dir,'USE_TFTP')
|
|
option(dir,'TFTP_INITRD')
|
|
option(dir,'PYRO_SERIAL')
|
|
|
|
# COMMAND: keyboard ...
|
|
# old legacy PC junk, which will be dying soon.
|
|
def keyboard(dir, keyboard_name):
|
|
if (debug):
|
|
print "KEYBOARD"
|
|
keyboard_dir = os.path.join(treetop, 'src', keyboard_name)
|
|
addobject_defaultrule('keyboard.o', keyboard_dir, '', 'OBJECTS')
|
|
|
|
# COMMAND: cpu <cpu name>
|
|
#
|
|
# This command may only be used once for a given CPU name. Executes the
|
|
# config file $(TOP)/src/cpu/<cpu name>/Config
|
|
#
|
|
def cpu(dir, cpu_name):
|
|
common_command_action(dir, 'cpu', cpu_name)
|
|
|
|
# COMMAND: pmc <vendor>/<pmc card name>
|
|
#
|
|
# This command may only be used once. Executes the
|
|
# config file $(TOP)/src/pmc/<vendor>/<pmc card name>/Config
|
|
#
|
|
def pmc(dir, pmc_name):
|
|
common_command_action(dir, 'pmc', pmc_name)
|
|
|
|
# COMMAND: northsouthbridge <vendor>/<northsouthbridge name>
|
|
#
|
|
# This command may only be used once. Executes the config file
|
|
# $(TOP)/src/northsouthbridge/<vendor>/<northsouthbridge name>/Config
|
|
#
|
|
def northsouthbridge(dir, northsouthbridge_name):
|
|
common_command_action(dir, 'northsouthbridge', northsouthbridge_name)
|
|
|
|
# COMMAND: northbridge <vendor>/<northbridge name>
|
|
#
|
|
# This command may only be used once. Executes the config file
|
|
# $(TOP)/src/northbridge/<vendor>/<northbridge name>/Config
|
|
#
|
|
def northbridge(dir, northbridge_name):
|
|
common_command_action(dir, 'northbridge', northbridge_name)
|
|
|
|
# COMMAND: southbridge <vendor>/<southbridge name>
|
|
#
|
|
# This command may only be used once. Executes the config file
|
|
# $(TOP)/src/southbridge/<vendor>/<southbridge name>/Config
|
|
#
|
|
def southbridge(dir, southbridge_name):
|
|
common_command_action(dir, 'southbridge', southbridge_name)
|
|
|
|
# COMMAND: superio <vendor> <superio name>
|
|
#
|
|
# This command may be used as many times as needed.
|
|
# I don't see a need yet to read in a config file for
|
|
# superio. Don't bother.
|
|
#
|
|
def superio(dir, superio_name):
|
|
# note that superio is w.r.t. treetop
|
|
dir = os.path.join(treetop, 'src', 'superio', superio_name)
|
|
addobject_defaultrule('superio.o', dir, '', 'OBJECTS')
|
|
|
|
# COMMAND: nsuperio ...
|
|
# commands are of the form:
|
|
# superio_name [name=val]*
|
|
def nsuperio(dir, superio_commands):
|
|
global superio_decls, superio_devices, numsuperio, target_dir
|
|
# note that superio is w.r.t. treetop
|
|
(superio_name, rest) = match(splitargs_re, superio_commands)
|
|
superio_decl_name = re.sub("/", "_", superio_name)
|
|
dir = os.path.join(treetop, 'src', 'superio', superio_name)
|
|
object="superio_%s.o" % superio_decl_name
|
|
superio_source = dir + "/superio.c"
|
|
addobject_defaultrule(object, superio_source, '', 'OBJECTS')
|
|
addobject_defaultrule('nsuperio.o', "", '', 'OBJECTS')
|
|
|
|
superio_cmds = '';
|
|
m = splitargs_re.match(rest)
|
|
(cmd, rest) = m.groups()
|
|
while (cmd):
|
|
superio_cmds = superio_cmds + ", ." + cmd
|
|
m = splitargs_re.match(rest)
|
|
(cmd, rest) = m.groups()
|
|
# now build the declaration
|
|
decl = '';
|
|
decl = "extern struct superio_control superio_"
|
|
decl = decl + superio_decl_name + "_control; \n"
|
|
decl = decl + "struct superio superio_" + "%s_%d" %(superio_decl_name,
|
|
numsuperio)
|
|
decl = decl + "= { "
|
|
decl = decl + "&superio_" + superio_decl_name+ "_control"
|
|
decl = decl + superio_cmds + "};\n"
|
|
superio_decls = superio_decls + decl;
|
|
superio_devices.append("&superio_" + "%s_%d" % (superio_decl_name,
|
|
numsuperio));
|
|
# note that we're using the new interface
|
|
option(dir, "USE_NEW_SUPERIO_INTERFACE=1")
|
|
numsuperio = numsuperio + 1
|
|
|
|
|
|
# A list of files for initializing a motherboard.
|
|
mainboardinit_files = []
|
|
|
|
# COMMAND: mainboardinit <path_to_inc_file> [<condition>]
|
|
# Include the assembly language .inc file at $(TOP)/src/<path_to_inc_file>
|
|
# in the crt0.s file.
|
|
def mainboardinit(dir, command):
|
|
(file, condition) = match(splitargs_re, command)
|
|
mainboardinit_files.append( (file, condition) )
|
|
print "Added mainboard init file: ", file
|
|
|
|
# COMMAND: raminit <path_to_inc_file>
|
|
# Include the assembly language .inc file at $(TOP)/src/<path_to_inc_file>
|
|
# in the crt0.s file. This command is essentially a duplicate of mainboardinit.
|
|
def raminit(dir, file):
|
|
mainboardinit_files.append( (file, '') )
|
|
print "Added ram init file: ", file
|
|
|
|
# Set of files we build the linker script from.
|
|
ldscripts = []
|
|
|
|
# COMMAND: ldscript <path_to_lds_file> <condition>
|
|
# $(TOP)/src/<path_to_lds_file> will be added to the Makefile variable
|
|
# LDSCRIPTS-1 if the <condition> is true or omitted.
|
|
def ldscript(dir, command):
|
|
(file, condition) = match(splitargs_re, command)
|
|
filepath = os.path.join(treetop, 'src', file);
|
|
ldscripts.append( (filepath, condition) )
|
|
print "Added ldscript init file: ", filepath
|
|
|
|
# COMMAND: object <path-to-source> [<condition>]
|
|
#
|
|
# <path-to-source> is a pathname to a .c or .S file rooted at
|
|
# $(TOP)/<path-to-source>.
|
|
# <condition> is a condition such as HAVE_PIRQ_TABLE.
|
|
# This command adds a rule to the Makefile for
|
|
# the target such that:
|
|
# 1) Basename of <path-to-source>.o depends on $(TOP)/<path-to-source>
|
|
# 2) romimage has a dependency on the .o
|
|
# 3) includepath for compiling the .o includes the directory containing the
|
|
# source
|
|
# An alternative explanation: The basename of path-to-source, minus the
|
|
# .c or .S suffix, plus a .o suffix, is added to the OBJECTS-1 Makefile
|
|
# variable if the <condition> is true or omitted. The OBJECTS-1 list is
|
|
# used (by a makrule in $(TOP)/src/config/Config) to make linuxbios.a,
|
|
# thus these objects are linked in only if needed to satisfy some reference.
|
|
#
|
|
def object(dir, command):
|
|
(obj_name, condition) = match(splitargs_re, command)
|
|
if (obj_name[-2:] == '.c') or (obj_name[-2:] == '.S'):
|
|
source_name = os.path.join(dir, obj_name)
|
|
obj_name = obj_name[:-2] + '.o'
|
|
elif (obj_name[-2:] == '.o'):
|
|
source_name = os.path.join(dir, obj_name[:-2] + '.c')
|
|
else:
|
|
fatal("Invalid object name")
|
|
addobject_defaultrule(obj_name, source_name, condition, 'OBJECTS')
|
|
|
|
# COMMAND: driver <path-to-source> [<condition>]
|
|
#
|
|
# Similar to object command, but these objects go into the Makefile variable
|
|
# DRIVERS-1 if the <condition> is true or omitted, and the objects listed
|
|
# in DRIVERS-1 are always linked in (via $(TOP)/src/config/Config) to
|
|
# linuxbios.o
|
|
#
|
|
def driver(dir, command):
|
|
(obj_name, condition) = match(splitargs_re, command)
|
|
addobject_defaultrule(obj_name, dir, condition, 'DRIVERS')
|
|
|
|
# COMMAND: makerule <target> : [<dependencies>] ; [<action>]
|
|
#
|
|
# Lets you add make rules to the Makefile.
|
|
#
|
|
makerule_re = re.compile(r'([^:\s]+)\s*:\s*([^;]*?)\s*;\s*(.*)')
|
|
def makerule(dir, rule):
|
|
if (debug):
|
|
print "makerule " , rule
|
|
(target, dependencies, action) = match(makerule_re, rule)
|
|
# Each rule created by makerule will be printed to the Makefile
|
|
# with a comment which shows the config file from whence it came.
|
|
mkrule(target, dependencies, [action])
|
|
|
|
# COMMAND: addaction <target> <action>
|
|
#
|
|
# Add an action to an existing rule designated by <target>.
|
|
#
|
|
def addaction(dir, rule):
|
|
if (debug):
|
|
print "addaction " , rule
|
|
(target, action) = match(splitargs_re, rule)
|
|
if not makebaserules.has_key(target):
|
|
warning("Need 'makerule %s ...' before addaction" % (target))
|
|
makebaserules[target].addaction(action)
|
|
|
|
# COMMAND: adddepend <target> <dependency>
|
|
#
|
|
# Add a dependency to an existing rule designated by <target>.
|
|
#
|
|
def adddepend(dir, rule):
|
|
(target, depend) = match(splitargs_re, rule)
|
|
if not makebaserules.has_key(target):
|
|
warning("Need 'makerule %s ...' before adddepend" % (target))
|
|
makebaserules[target].adddepend(depend)
|
|
|
|
# COMMAND: makedefine <stuff>
|
|
# <stuff> is printed out to the Makefile. <stuff> is usually of the form
|
|
# <VAR>=<value>
|
|
def makedefine(dir, rule):
|
|
userdefines.append(rule)
|
|
|
|
|
|
class mkexpr:
|
|
class identifier:
|
|
def __init__ (self, name):
|
|
self.name = name
|
|
def bc(self):
|
|
return "($(" + self.name + "))"
|
|
def perl(self):
|
|
return "($(" + self.name + "))"
|
|
|
|
class constant:
|
|
def __init__ (self, value):
|
|
self.value = value
|
|
def bc(self):
|
|
return "(" + self.value + ")"
|
|
def perl(self):
|
|
return "(" + self.value + ")"
|
|
|
|
class unary:
|
|
def __init__ (self, op, right):
|
|
self.op = op
|
|
self.right = right
|
|
|
|
def bc(self):
|
|
rstring = self.right.bc()
|
|
if (self.op == "!"):
|
|
result = "!" + rstring
|
|
elif (self.op == "-"):
|
|
result = "-" + rstring
|
|
return "(" + result + ")"
|
|
|
|
def perl(self):
|
|
rstring = self.right.perl()
|
|
if (self.op == "!"):
|
|
result = "!" + rstring
|
|
elif (self.op == "-"):
|
|
result = "-" + rstring
|
|
return "(" + result + ")"
|
|
|
|
class binary:
|
|
def __init__(self, op, left, right):
|
|
self.op = op
|
|
self.left = left
|
|
self.right = right
|
|
|
|
def bc(self):
|
|
lstring = self.left.bc()
|
|
rstring = self.right.bc()
|
|
if (self.op == "&"):
|
|
result = lstring + "&&" + rstring
|
|
elif (self.op == "|"):
|
|
result = lstring + "||" + rstring
|
|
elif (self.op == "+"):
|
|
result = lstring + "+" + rstring
|
|
elif (self.op == "-"):
|
|
result = lstring + "-" + rstring
|
|
elif (self.op == "*"):
|
|
result = lstring + "*" + rstring
|
|
elif (self.op == "/"):
|
|
result = lstring + "/" + rstring
|
|
elif (self.op == "<<"):
|
|
result = lstring + "*(2^" + rstring + ") "
|
|
elif (self.op == ">>"):
|
|
result = lstring + "/(2^" + rstring + ") "
|
|
return "(" + result + ")"
|
|
|
|
|
|
def perl(self):
|
|
lstring = self.left.perl()
|
|
rstring = self.right.perl()
|
|
if (self.op == "&"):
|
|
result = lstring + "&&" + rstring
|
|
elif (self.op == "|"):
|
|
result = lstring + "||" + rstring
|
|
elif (self.op == "+"):
|
|
result = lstring + "+" + rstring
|
|
elif (self.op == "-"):
|
|
result = lstring + "-" + rstring
|
|
elif (self.op == "*"):
|
|
result = lstring + "*" + rstring
|
|
elif (self.op == "/"):
|
|
result = lstring + "/" + rstring
|
|
elif (self.op == "<<"):
|
|
result = lstring + "<<" + rstring
|
|
elif (self.op == ">>"):
|
|
result = lstring + ">>" + rstring
|
|
elif (self.op == ">"):
|
|
result = lstring + ">" + rstring
|
|
elif (self.op == ">="):
|
|
result = lstring + ">=" + rstring
|
|
elif (self.op == "<"):
|
|
result = lstring + "<" + rstring
|
|
elif (self.op == "<="):
|
|
result = lstring + "<=" + rstring
|
|
elif (self.op == "=="):
|
|
result = lstring + "==" + rstring
|
|
elif (self.op == "=="):
|
|
result = lstring + "!=" + rstring
|
|
return "(" + result + ")"
|
|
|
|
class expression:
|
|
def __init__(self, expr):
|
|
self.expr = expr
|
|
|
|
def bc(self):
|
|
string = self.expr.bc()
|
|
return "${shell echo '" + string + "' | bc}"
|
|
|
|
def perl(self):
|
|
string = self.expr.perl()
|
|
return "${shell perl -e 'printf(\"%u\\n\", " + string + ");' }"
|
|
|
|
# Tokens: ( ) ! | & + - * / << >> == <= >= < > != option )
|
|
start_re = re.compile(r"^\s*(([A-Za-z_][A-Za-z_0-9]*)|((0x[0-9A-Za-z]+)|([0-9]+))|(\()|(!))(.*)$")
|
|
close_re = re.compile(r"^\s*\)(.*)$")
|
|
# middle_re = re.compile(r"^\s*((\|)|(&)|(\+)|(-)|(\*)|(/)|(<<)|(>>)|(==)|(<=)|(>=)|(<)|(>))(.*)$")
|
|
middle_re = re.compile(r"^\s*((\|)|(&)|(\+)|(-)|(\*)|(/)|(<<)|(>>)|>=|<=|>|<|==|!=)(.*)$")
|
|
|
|
def __init__(self, expr):
|
|
self.orig_expr = expr
|
|
self.expr = ""
|
|
|
|
def prec(self, op):
|
|
if (op == "|"):
|
|
result = 1
|
|
elif (op == "&"):
|
|
result = 2
|
|
elif (op == "<") or (op == ">") or \
|
|
(op == ">=") or (op == "<=") or \
|
|
(op == "==") or (op == "!="):
|
|
result = 3
|
|
elif (op == "+") or (op == "-"):
|
|
result = 4
|
|
elif (op == "*") or (op == "/"):
|
|
result = 5
|
|
elif (op == "<<") or (op == ">>"):
|
|
result = 6
|
|
else:
|
|
fatal("Unknown operator: %s" % op)
|
|
|
|
|
|
def _parse_start(self):
|
|
#print("start expr: %s"%(self.expr))
|
|
m = self.start_re.match(self.expr)
|
|
if m:
|
|
(token, self.expr) = (m.group(1), m.group(8))
|
|
if token == "(":
|
|
left = self._parse()
|
|
#print("close expr: %s"%(self.expr))
|
|
m = self.close_re.match(self.expr)
|
|
if m:
|
|
self.expr = m.group(1)
|
|
else:
|
|
fatal("No Matching )");
|
|
elif (token == "!"):
|
|
right = self._parse()
|
|
left = self.unary(token, right)
|
|
elif m.group(2):
|
|
if not makeoptions.has_key(token):
|
|
fatal("Option %s not defined" % token)
|
|
left = self.identifier(token)
|
|
elif m.group(3):
|
|
left = self.constant(token)
|
|
else:
|
|
fatal("Invalid expression: %s" % self.expr)
|
|
return left
|
|
|
|
def _parse_middle(self, left):
|
|
#print("middle expr: %s"%(self.expr))
|
|
m = self.middle_re.match(self.expr)
|
|
while(m):
|
|
(op, self.expr) = (m.group(1),m.group(10))
|
|
right = self._parse_start()
|
|
m = self.middle_re.match(self.expr)
|
|
if m and (self.prec(op) < self.prec(m.group(1))):
|
|
right = self._parse_middle()
|
|
left = self.binary(op, left, right)
|
|
return left
|
|
|
|
def _parse(self):
|
|
left = self._parse_start()
|
|
return self._parse_middle(left)
|
|
|
|
def parse(self):
|
|
self.expr = self.orig_expr
|
|
result = self._parse()
|
|
if self.expr != "":
|
|
fatal("Extra tokens: %s"% self.expr)
|
|
return self.expression(result)
|
|
|
|
# Put "<option>:=<value>" and add <option> to VARIABLES in Makefile.settings
|
|
def set_option(option, value):
|
|
if makeoptions.has_key(option) and (makeoptions[option][0] == "expr"):
|
|
fatal("Cannot replace expression %s" % option)
|
|
makeoptions[option] = ("option", value)
|
|
|
|
# Add <option> to VARIABLES in Makefile.settings
|
|
# And remove any value <option> may already have.
|
|
def clear_option(option):
|
|
if makeoptions.has_key(option) and (makeoptions[option][0] == "expr"):
|
|
fatal("Cannot clear expression %s" % option)
|
|
makeoptions[option] = ("nooption", "")
|
|
|
|
# Put "<option>:=<value>" and add <option> to VARIABLES in Makefile.settings
|
|
def set_expr(option, value):
|
|
if makeoptions.has_key(option) and (makeoptions[option][0] == "expr"):
|
|
fatal("Cannot replace expression %s" % option)
|
|
makeexpressions.append(option);
|
|
makeoptions[option] = ("expr", mkexpr(value).parse().perl())
|
|
|
|
|
|
# COMMAND: option <option-name> [=<optional value>]
|
|
#
|
|
# This command affects the CFLAGS for the generated Makefile. If there is
|
|
# no optional value, then the option should appear in CFLAGS as:
|
|
# CFLAGS += -D<option-name>
|
|
# If there is a value, then the option should appear as:
|
|
# CFLAGS += -D<option-name>=<optional value>
|
|
# Also, put "<option>:=<value>" and add <option> to VARIABLES in
|
|
# Makefile.settings
|
|
#
|
|
option_re = re.compile(r"^([A-Za-z_][A-Za-z_0-9]+)\s*$")
|
|
option_arg_re = re.compile(r"^([A-Za-z_][A-Za-z_0-9]+)\s*=(.*)$")
|
|
def option(dir, option):
|
|
m = option_arg_re.match(option)
|
|
key = option
|
|
value = ""
|
|
if m and m.group(1):
|
|
(key, value) = m.groups()
|
|
else:
|
|
warning("Invalid option specifcation: %s assuming you meant %s=1" %
|
|
(option, option) )
|
|
value = "1"
|
|
m = option_re.match(key)
|
|
if not m:
|
|
fatal("Invalid option name: %s" % (key))
|
|
set_option(key, value)
|
|
|
|
# COMMAND: nooption <option-name>
|
|
# Add <option-name> to VARIABLES and "-U<option-name>" to CFLAGS.
|
|
def nooption(dir, option):
|
|
clear_option(option)
|
|
|
|
# COMMAND: expr
|
|
def expr(dir, option):
|
|
m = option_arg_re.match(option)
|
|
value= ""
|
|
if m and m.group(1):
|
|
(key, value) = m.groups()
|
|
else:
|
|
fatal("Invalid expression: %s" % (option))
|
|
set_expr(key, value)
|
|
|
|
# COMMAND: commandline <stuff>
|
|
# Equivalent to "option CMD_LINE="<stuff>".
|
|
def commandline(dir, command):
|
|
set_option("CMD_LINE", "\"" + command + "\"")
|
|
|
|
# COMMAND: docipl <ipl_name>
|
|
# We do all these rules by hand because docipl will always be special.
|
|
# It's more or less a stand-alone bootstrap.
|
|
|
|
def docipl(dir, ipl_name):
|
|
|
|
# add the docipl rule
|
|
add_main_rule_dependency('docipl')
|
|
mkrule('docipl', 'ipl.o',
|
|
['objcopy -O binary -R .note -R .comment -S ipl.o docipl'])
|
|
|
|
# now, add the ipl.o rule
|
|
iplpath = os.path.join(treetop, 'src', ipl_name)
|
|
# Now we need a mainboard-specific include path
|
|
mkrule('ipl.o', iplpath,
|
|
['$(CC) $(CFLAGS) -I%s -c $<' % mainboard_dir])
|
|
|
|
# now set new values for the ldscript.ld. Should be a script?
|
|
set_option("_RAMBASE", "0x4000")
|
|
set_option("_ROMBASE", "0x80000")
|
|
|
|
# COMMAND: payload <payload_name>
|
|
def payload(dir, payload_name):
|
|
payloadrule = 'PAYLOAD=' + payload_name
|
|
makedefine(dir, payloadrule)
|
|
|
|
# COMMAND: linux <linux_dir>
|
|
def linux(dir, linux_name):
|
|
linuxrule = 'LINUX=' + linux_name + '/vmlinux'
|
|
makedefine(dir, linuxrule)
|
|
|
|
# COMMAND: rambase <address>
|
|
def rambase(dir, address):
|
|
set_option("_RAMBASE", address)
|
|
|
|
# COMMAND: biosbase <address>
|
|
#
|
|
# Set the LinuxBIOS code base. Default is 0xf0000.
|
|
#
|
|
def biosbase(dir, address):
|
|
set_option("_ROMBASE", address)
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Config file processing
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# This table translates command name strings into execution functions.
|
|
|
|
# NOTE: rather than creating new high-level commands like northbridge,
|
|
# etherboot, docipl, nsuperio, commandline, etc., consider using the
|
|
# lower-level commands such as dir, option, object, mainboardinit, etc.
|
|
# That would move the LinuxBIOS specialized knowledge out of this utility
|
|
# and into Config scripts, which would be more modular.
|
|
|
|
command_actions = {
|
|
'arch' : set_arch,
|
|
'target' : target,
|
|
'mainboard' : mainboard,
|
|
'cpu' : cpu,
|
|
'pmc' : pmc,
|
|
'northbridge' : northbridge,
|
|
'southbridge' : southbridge,
|
|
'northsouthbridge' : northsouthbridge,
|
|
'superio' : superio,
|
|
'nsuperio' : nsuperio,
|
|
'object' : object,
|
|
'driver' : driver,
|
|
'linux' : linux,
|
|
'payload' : payload,
|
|
'raminit' : raminit,
|
|
'mainboardinit' : mainboardinit,
|
|
'ldscript' : ldscript,
|
|
'dir' : dir,
|
|
'keyboard' : keyboard,
|
|
'docipl' : docipl,
|
|
'etherboot' : etherboot,
|
|
'makedefine' : makedefine,
|
|
'makerule' : makerule,
|
|
'addaction' : addaction,
|
|
'option' : option,
|
|
'nooption' : nooption,
|
|
'rambase' : rambase,
|
|
'biosbase' : biosbase,
|
|
'commandline' : commandline,
|
|
'expr' : expr,
|
|
}
|
|
|
|
# Open file, extract lines, and close. For reading config and "base" files.
|
|
def readfile(filename):
|
|
if not os.path.isfile(filename):
|
|
print filename, "is not a file \n"
|
|
sys.exit(1)
|
|
fileobject = open(filename, "r")
|
|
filelines = fileobject.readlines()
|
|
fileobject.close()
|
|
return filelines
|
|
|
|
# Pattern for getting command and rest of line (if any). Note that blank
|
|
# lines and pure comment lines cause the "verb" group to be ''.
|
|
# Trailing comments are matched and passed through to the "args" group.
|
|
# The pattern should always match, so we don't need to check that.
|
|
command_re = re.compile(r'\s*([^#\s]*)\s*(.*\S)?\s*')
|
|
|
|
# Strip whitespace and comment if any from end of line.
|
|
stripcomment_re = re.compile(r'([^#]*[^#\s])?.*')
|
|
|
|
# List of all config files processed. This is used for making a list
|
|
# of dependencies for Makefile itself.
|
|
config_file_list = []
|
|
|
|
# Process config files.
|
|
def doconfigfile(dir, filename):
|
|
if (debug):
|
|
print "doconfigfile" , filename
|
|
|
|
config_file_list.append(filename)
|
|
|
|
# Keep track of current config file, for error reporting.
|
|
loc.push_file(filename)
|
|
|
|
if (debug):
|
|
print "doconfigfile: config_file_list ", config_file_list
|
|
filelines = readfile(filename)
|
|
if (debug > 1):
|
|
print "doconfigfile: filelines", filelines
|
|
|
|
for line in filelines:
|
|
loc.next_line(line)
|
|
|
|
(verb, args) = command_re.match(line).groups()
|
|
if not verb:
|
|
# Line was blank or pure comment
|
|
continue
|
|
|
|
if not verb in ('makerule', 'addaction'):
|
|
# The commands above can accept comments as regular
|
|
# arguments. For all other commands, strip
|
|
# final whitespace and comments.
|
|
if args:
|
|
args = stripcomment_re.match(args).group(1)
|
|
|
|
if ((arch == '') and not verb in
|
|
('arch', 'mainboard', 'target')):
|
|
fatal("arch, target, or mainboard must be\n"
|
|
"the first commands, not %s"%(verb))
|
|
|
|
if command_actions.has_key(verb):
|
|
# Call the command execution function.
|
|
command_actions[verb](dir, args)
|
|
else:
|
|
fatal("%s is not a valid command!"% (verb))
|
|
|
|
loc.pop_file()
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Functions for writing output files
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Write out crt0_includes.h (top-level assembly language) include file.
|
|
def writecrt0_includes(path):
|
|
crt0filepath = os.path.join(path, "crt0_includes.h")
|
|
print "Creating", crt0filepath
|
|
file = open(crt0filepath, 'w+')
|
|
|
|
for mbifile in mainboardinit_files:
|
|
if mbifile[1]:
|
|
file.write("#if %s == 1\n" %mbifile[1])
|
|
file.write("#include <%s>\n" % mbifile[0])
|
|
if mbifile[1]:
|
|
file.write("#endif\n")
|
|
|
|
file.close();
|
|
|
|
|
|
# Write doxygen file.
|
|
def writedoxygenfile(path):
|
|
global objectrules, doxyscriptbase
|
|
|
|
doxyfilepath = os.path.join(path, "LinuxBIOSDoc.config")
|
|
print "Creating", doxyfilepath
|
|
file = open(doxyfilepath, 'w+')
|
|
|
|
# FIXME. Should be computing .c once. Fix this in objectrules.append
|
|
file.write("INPUT= \\\n")
|
|
for objrule in objectrules:
|
|
source = objrule[1]
|
|
if (source[-2:] != '.c'): # no suffix. Build name.
|
|
base = objrule[0][:-2]
|
|
source = os.path.join(source, base) + ".c"
|
|
file.write("%s \\\n" % source)
|
|
|
|
doxylines = readfile(doxyscriptbase)
|
|
if (debug):
|
|
print "DOXYLINES ",doxylines
|
|
for line in doxylines:
|
|
file.write(line)
|
|
file.close();
|
|
|
|
# If the first part of <path> matches treetop, replace that part with "$(TOP)"
|
|
def topify(path):
|
|
global treetop
|
|
if path[0:len(treetop)] == treetop:
|
|
path = path[len(treetop):len(path)]
|
|
if (path[0:1] == "/"):
|
|
path = path[1:len(path)]
|
|
path = "$(TOP)/" + path
|
|
return path
|
|
|
|
def writemakefileheader(file, fname):
|
|
file.write("# File: %s\n" % fname)
|
|
file.write("# This file was generated by '%s %s %s'\n\n"
|
|
% (sys.argv[0], sys.argv[1], sys.argv[2]))
|
|
|
|
def writemakefilesettings(path):
|
|
# Write Makefile.settings to seperate the settings
|
|
# from the actual makefile creation
|
|
# In practice you need to rerun NLBConfig.py to change
|
|
# these but in theory you shouldn't need to.
|
|
|
|
filename = os.path.join(path, "Makefile.settings")
|
|
print "Creating", filename
|
|
file = open(filename, 'w+')
|
|
writemakefileheader(file, filename)
|
|
|
|
file.write("TOP:=%s\n" % (treetop))
|
|
file.write("ARCH:=%s\n" % (arch))
|
|
file.write("MAINBOARD:=%s\n" % (mainboard_dir))
|
|
file.write("TARGET_DIR:=%s\n" % (target_dir))
|
|
|
|
keys = makeoptions.keys()
|
|
keys.sort()
|
|
for key in keys:
|
|
(type, value) = makeoptions[key]
|
|
if type == "option":
|
|
file.write("export %s:=%s\n" % (key, value))
|
|
|
|
# Write out the expressions in the order they were defined
|
|
# This ensures expressions that depend on other expressions
|
|
# will execute correctly
|
|
i = 0
|
|
while(i < len(makeexpressions)):
|
|
key = makeexpressions[i]
|
|
(type, value) = makeoptions[key]
|
|
file.write("export %s:=%s\n" % (key, value))
|
|
i = i + 1
|
|
|
|
file.write("export VARIABLES := ");
|
|
for key in keys:
|
|
file.write("%s " % key)
|
|
file.write("\n");
|
|
|
|
file.close();
|
|
|
|
|
|
# write the makefile
|
|
# let's try the Makefile
|
|
# first, dump all the -D stuff
|
|
|
|
def writemakefile(path):
|
|
makefilepath = os.path.join(path, "Makefile")
|
|
print "Creating", makefilepath
|
|
file = open(makefilepath, 'w+')
|
|
writemakefileheader(file, makefilepath)
|
|
|
|
# file.write("include Makefile.settings\n")
|
|
# file.write("include cpuflags\n")
|
|
# Putting "include cpuflags" in the Makefile has the problem that the
|
|
# cpuflags file would be generated _after_ we want to include it.
|
|
# Instead, let make do the work of computing CPUFLAGS:
|
|
file.write("""\
|
|
# Get the value of TOP, VARIABLES, and several other variables.
|
|
include Makefile.settings
|
|
|
|
# Function to create an item like -Di586 or -DMAX_CPUS='1' or -Ui686
|
|
D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)
|
|
|
|
# Compute the value of CPUFLAGS here during make's first pass.
|
|
CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))
|
|
""")
|
|
|
|
# print out all the object dependencies
|
|
file.write("\n# object dependencies (objectrules:)\n")
|
|
file.write("OBJECTS-1 :=\n")
|
|
file.write("DRIVERS-1 :=\n")
|
|
for objrule in objectrules:
|
|
obj_name = objrule[0]
|
|
obj_cond = objrule[3]
|
|
obj_var = objrule[4] # 'OBJECTS' or 'DRIVERS'
|
|
if not obj_cond:
|
|
file.write("%s-1 += %s\n" % (obj_var, obj_name))
|
|
else:
|
|
file.write("%s-$(%s) += %s\n"
|
|
% (obj_var, obj_cond, obj_name))
|
|
|
|
# Print out all ldscript.ld dependencies.
|
|
file.write("\n# ldscript.ld dependencies:\n")
|
|
file.write("LDSUBSCRIPTS-1 := \n" )
|
|
for (script, condition) in ldscripts:
|
|
script = topify(script);
|
|
if condition:
|
|
file.write("LDSUBSCRIPTS-$(%s) += %s\n" % (condition, script))
|
|
else:
|
|
file.write("LDSUBSCRIPTS-1 += %s\n" % (script))
|
|
|
|
|
|
# Print out the dependencies for crt0_includes.h
|
|
file.write("\n# Dependencies for crt0_includes.h\n")
|
|
file.write("CRT0_INCLUDES:=\n")
|
|
for mbifile in mainboardinit_files:
|
|
file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % mbifile[0])
|
|
|
|
|
|
file.write("\nSOURCES=\n")
|
|
for source in sources:
|
|
file.write("SOURCES += %s\n" % source)
|
|
|
|
# Print out the user defines.
|
|
file.write("\n# userdefines:\n")
|
|
for udef in userdefines:
|
|
file.write("%s\n" % udef)
|
|
|
|
# Print out the base rules.
|
|
# Need to have a rule that counts on 'all'.
|
|
file.write("\n# mainrulelist:")
|
|
file.write("\nmainrule: %s\n" % mainrulelist)
|
|
|
|
# Print out any user rules.
|
|
file.write("\n# From makerule or docipl commands:\n")
|
|
# Old way (hash order): for target in makebaserules.keys():
|
|
# New way (config file order):
|
|
for target in makerule_targets:
|
|
makebaserules[target].write(file)
|
|
|
|
file.write("\n# objectrules:\n")
|
|
for objrule in objectrules:
|
|
source = objrule[1]
|
|
file.write("%s: %s\n" % (objrule[0], source))
|
|
file.write("%s\n" % objrule[2])
|
|
|
|
# Print out the rules that will make cause the files
|
|
# generated by NLBConfig.py to be remade if any dependencies change.
|
|
|
|
file.write("\n# Remember the automatically generated files\n")
|
|
file.write("GENERATED:=\n")
|
|
for genfile in [ 'Makefile',
|
|
'Makefile.settings',
|
|
'crt0_includes.h',
|
|
'nsuperio.c',
|
|
'LinuxBIOSDoc.config' ]:
|
|
file.write("GENERATED += %s\n" % genfile)
|
|
|
|
file.write("\n# Remake Makefile (and the other files generated by\n")
|
|
file.write("# NLBConfig.py) if any config dependencies change.\n")
|
|
|
|
for cfile in config_file_list:
|
|
file.write("$(GENERATED): %s\n" % topify(cfile))
|
|
|
|
for depfile in [ '%s' % top_config_file, # This a duplicate, remove?
|
|
'$(TOP)/util/config/NLBConfig.py',
|
|
'$(TOP)/src/arch/$(ARCH)/init/make.base' ]:
|
|
file.write("$(GENERATED): %s\n" % depfile)
|
|
|
|
file.write("$(GENERATED):\n")
|
|
file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n"
|
|
% top_config_file)
|
|
|
|
keys = makeoptions.keys()
|
|
keys.sort()
|
|
file.write("\necho:\n")
|
|
for key in keys:
|
|
file.write("\t@echo %s='$(%s)'\n"% (key,key))
|
|
|
|
|
|
file.close();
|
|
|
|
def writesuperiofile(path):
|
|
superiofile = os.path.join(path, "nsuperio.c")
|
|
print "Creating", superiofile
|
|
file = open(superiofile, 'w+')
|
|
|
|
file.write("#include <pci.h>\n")
|
|
file.write(superio_decls)
|
|
file.write("struct superio *all_superio[] = {");
|
|
for sio_dev in superio_devices:
|
|
file.write("%s,\n" % sio_dev)
|
|
file.write("};\n")
|
|
file.write("unsigned long nsuperio = %d;\n" % numsuperio)
|
|
|
|
# ---------------------------------------------------------------------
|
|
# MAIN
|
|
# ---------------------------------------------------------------------
|
|
|
|
if len(sys.argv) != 3:
|
|
print "python NLBConfig.py <Config Filename> <src-path>\n"
|
|
sys.exit(1)
|
|
|
|
# Retrieve config filename from command line.
|
|
top_config_file = os.path.abspath(sys.argv[1])
|
|
|
|
# Determine current directory and set default TOP.
|
|
treetop = os.path.abspath(sys.argv[2])
|
|
|
|
# Set the default locations for config files.
|
|
makebase = os.path.join(treetop, "util/config/make.base")
|
|
crt0base = os.path.join(treetop, "arch/i386/init/crt0.base")
|
|
doxyscriptbase = os.path.join(treetop, "src/config/doxyscript.base")
|
|
|
|
# Now read in the customizing script...
|
|
doconfigfile(treetop, top_config_file)
|
|
|
|
# ...and write out the Makefile and other files.
|
|
# All submakfiles (Makefile.settings) must be written
|
|
# before the Makefile itself or there is a dependency issue
|
|
writemakefilesettings(target_dir)
|
|
writemakefile(target_dir)
|
|
writecrt0_includes(target_dir)
|
|
writesuperiofile(target_dir)
|
|
writedoxygenfile(target_dir)
|