New option behavior:

1. Options can only be set with 'option' statement in the target
   configuration file. Options can be set as many times as needed.
2  Option DEFAULT values can be changed (or set) in any configuration file.
   Changing a default value will display a warning message.
3. A default value is changed with the statement 'default <op> = <val>'.
4. Setting an option overrides the default value.
5. The 'mainboard' and 'arch' statements now set options implicitly. No
   'uses' statement is required.

The idea is that parts will define default values for options that
they need/use. Option overrides are only done in the target file.


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1258 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Greg Watson 2003-11-05 18:55:44 +00:00
parent ae83b36415
commit 8cb747942c
1 changed files with 108 additions and 101 deletions

View File

@ -175,7 +175,10 @@ def warning(string):
global warnings, loc global warnings, loc
warnings = warnings + 1 warnings = warnings + 1
print "===> WARNING: %s" % string print "===> WARNING: %s" % string
print "%s" % loc
def notice(string):
"""Print notice message"""
print "===> NOTE: %s" % string
def exitiferrors(): def exitiferrors():
"""Exit parser if an error has been encountered""" """Exit parser if an error has been encountered"""
@ -377,7 +380,7 @@ class romimage:
debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path)) debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path))
o = getdict(self.initincludes, path) o = getdict(self.initincludes, path)
if (o): if (o):
warning("Warning, init include for %s previously defined" % path) warning("init include for %s previously defined" % path)
o = initinclude(str, path) o = initinclude(str, path)
setdict(self.initincludes, path, o) setdict(self.initincludes, path, o)
self.initincludesorder.append(path) self.initincludesorder.append(path)
@ -487,6 +490,7 @@ class option:
self.exported = 0 # option is exported self.exported = 0 # option is exported
self.defined = 0 # option has a value self.defined = 0 # option has a value
self.format = '%s' # option print format self.format = '%s' # option print format
self.write = [] # parts that can set this option
def setvalue(self, value, values, loc): def setvalue(self, value, values, loc):
self.set = 1 self.set = 1
@ -514,8 +518,6 @@ class option:
def setdefault(self, value, loc): def setdefault(self, value, loc):
global global_option_values global global_option_values
if (self.default):
fatal("default value for %s already set" % self.name)
setdict(global_option_values, self.name, value) setdict(global_option_values, self.name, value)
self.defined = 1 self.defined = 1
self.default = 1 self.default = 1
@ -558,17 +560,17 @@ class option:
self.exported = 1 self.exported = 1
self.used = 1 self.used = 1
def setwrite(self, part):
self.write.append(part)
def isexported(self): def isexported(self):
return (self.exported and self.defined) return (self.exported and self.defined)
# def isdefined(self):
# return (self.defined)
def isset(self): def isset(self):
return (self.set) return (self.set)
# def isused(self): def iswritable(self, part):
# return (self.used) return (part in self.write)
class option_value: class option_value:
"""Value of a configuration option""" """Value of a configuration option"""
@ -849,28 +851,59 @@ def getoption(name, image):
v = o.getvalue(image, global_option_values) v = o.getvalue(image, global_option_values)
return v.contents() return v.contents()
def setoption(name, value): def setoption(name, value, imp):
"""Set an option from within a configuration file. Normally this
is only permitted in the target (top level) configuration file.
If 'imp' is true, then set an option implicitly (e.g. 'arch'
and 'mainboard' statements). Implicit options can be set anywhere
the statements are legal, but also performs an implicit 'uses'
for the option"""
global loc, global_options, global_option_values, curimage global loc, global_options, global_option_values, curimage
curpart = partstack.tos() curpart = partstack.tos()
if (curpart and curpart.part != 'mainboard'): if (not imp and curpart):
fatal("Options may only be set in top-level and mainboard configuration files") fatal("Options may only be set in target configuration file")
if (imp):
usesoption(name)
if (curpart):
o = getdict(curpart.uses_options, name)
else:
o = getdict(global_uses_options, name) o = getdict(global_uses_options, name)
if (o == 0): if (not o):
fatal("Attempt to set nonexistent option %s" % name) fatal("Attempt to set nonexistent option %s (missing USES?)" % name)
if (o.isset()):
warning("Changing option %s" % name)
v = option_value(value) v = option_value(value)
if (curimage): if (curimage):
o.setvalue(v, curimage.getvalues(), loc) o.setvalue(v, curimage.getvalues(), loc)
else: else:
o.setvalue(v, global_option_values, loc) o.setvalue(v, global_option_values, loc)
def setdefault(name, value): def setdefault(name, value, isdef):
"""Set the default value of an option from within a configuration
file. This is permitted from any configuration file, but will
result in a warning if the default is set more than once.
If 'isdef' is set, we're defining the option in Options.lb so
there is no need for 'uses'."""
global loc, global_options global loc, global_options
if (isdef):
o = getdict(global_options, name) o = getdict(global_options, name)
if (not o): if (not o):
return return
if (o.default): else:
print "setdefault: attempt to duplicate default for %s" % name curpart = partstack.tos()
return if (curpart):
o = getdict(curpart.uses_options, name)
else:
o = getdict(global_uses_options, name)
if (not o):
fatal("Attempt to set default for nonexistent option %s (missing USES?)" % name)
if (o.defined):
warning("Changing default value of %s" % name)
v = option_value(value) v = option_value(value)
o.setdefault(v, loc) o.setdefault(v, loc)
@ -932,6 +965,13 @@ def getformated(name, image):
f = o.getformat() f = o.getformat()
return (f % v.contents()) return (f % v.contents())
def setwrite(name, part):
global global_options
o = getdict(global_options, name)
if (not o):
fatal("setwrite: %s not here" % name)
o.setwrite(part)
def isexported(name): def isexported(name):
global global_options global global_options
o = getdict(global_options, name) o = getdict(global_options, name)
@ -939,16 +979,6 @@ def isexported(name):
return o.isexported() return o.isexported()
return 0 return 0
#def isdefined(name, part):
# global global_options
# if (part):
# o = getdict(part.uses_options, name)
# else:
# o = getdict(global_options, name)
# if (o):
# return o.isdefined()
# return 0
def isset(name, part): def isset(name, part):
global global_uses_options global global_uses_options
if (part): if (part):
@ -959,16 +989,6 @@ def isset(name, part):
return o.isset() return o.isset()
return 0 return 0
#def isused(name, part):
# global global_options
# if (part):
# o = getdict(part.uses_options, name)
# else:
# o = getdict(global_options, name)
# if (o):
# return o.isused()
# return 0
def usesoption(name): def usesoption(name):
global global_options, global_uses_options global global_options, global_uses_options
curpart = partstack.tos() curpart = partstack.tos()
@ -1072,11 +1092,11 @@ def endromimage():
def mainboard(path): def mainboard(path):
full_path = os.path.join(treetop, 'src', 'mainboard', path) full_path = os.path.join(treetop, 'src', 'mainboard', path)
setoption('MAINBOARD', full_path) setoption('MAINBOARD', full_path, 1)
vendor = re.sub("/.*", "", path) vendor = re.sub("/.*", "", path)
part_number = re.sub("[^/]*/", "", path) part_number = re.sub("[^/]*/", "", path)
setoption('MAINBOARD_VENDOR', vendor) setoption('MAINBOARD_VENDOR', vendor, 1)
setoption('MAINBOARD_PART_NUMBER', part_number) setoption('MAINBOARD_PART_NUMBER', part_number, 1)
dodir('/config', 'Config.lb') dodir('/config', 'Config.lb')
part('mainboard', path, 'Config.lb', 0, 0) part('mainboard', path, 'Config.lb', 0, 0)
curimage.setroot(partstack.tos()) curimage.setroot(partstack.tos())
@ -1136,9 +1156,6 @@ def part(type, path, file, name, link):
# arrange to source the directory /cpu/'type' # arrange to source the directory /cpu/'type'
if (type == 'cpu'): if (type == 'cpu'):
cpudir(path) cpudir(path)
else:
if (type == 'mainboard'):
doconfigfile(srcdir, partdir, file, 'mainboard_cfgfile')
else: else:
doconfigfile(srcdir, partdir, file, 'cfgfile') doconfigfile(srcdir, partdir, file, 'cfgfile')
@ -1151,7 +1168,7 @@ def partpop():
# Warn if options are used without being set in this part # Warn if options are used without being set in this part
for i in curpart.uses_options.keys(): for i in curpart.uses_options.keys():
if (not isset(i, curpart)): if (not isset(i, curpart)):
warning("Option %s using default value %s" % (i, getformated(i, curpart.image))) notice("Option %s using default value %s" % (i, getformated(i, curpart.image)))
dirstack.pop() dirstack.pop()
def dodir(path, file): def dodir(path, file):
@ -1197,7 +1214,7 @@ def setarch(my_arch):
"""arch is 'different' ... darn it.""" """arch is 'different' ... darn it."""
global curimage global curimage
curimage.setarch(my_arch) curimage.setarch(my_arch)
setoption('ARCH', my_arch) setoption('ARCH', my_arch, 1)
part('arch', my_arch, 'Config.lb', 0, 0) part('arch', my_arch, 'Config.lb', 0, 0)
def doconfigfile(path, confdir, file, rule): def doconfigfile(path, confdir, file, rule):
@ -1312,6 +1329,7 @@ parser Config:
token TARGET: 'target' token TARGET: 'target'
token USED: 'used' token USED: 'used'
token USES: 'uses' token USES: 'uses'
token WRITE: 'write'
token NUM: '[0-9]+' token NUM: '[0-9]+'
token HEX_NUM: '[0-9a-fA-F]+' token HEX_NUM: '[0-9a-fA-F]+'
token HEX_PREFIX: '0x' token HEX_PREFIX: '0x'
@ -1401,6 +1419,8 @@ parser Config:
rule dir<<C>>: DIR DIRPATH {{ if (C): dodir(DIRPATH, 'Config.lb') }} rule dir<<C>>: DIR DIRPATH {{ if (C): dodir(DIRPATH, 'Config.lb') }}
rule default<<C>>: DEFAULT ID EQ value {{ if (C): setdefault(ID, value, 0) }}
rule ldscript<<C>>: LDSCRIPT DIRPATH {{ if (C): addldscript(DIRPATH) }} rule ldscript<<C>>: LDSCRIPT DIRPATH {{ if (C): addldscript(DIRPATH) }}
rule iif<<C>>: IF ID {{ c = lookup(ID) }} rule iif<<C>>: IF ID {{ c = lookup(ID) }}
@ -1465,6 +1485,7 @@ parser Config:
rule stmt<<C>>: arch<<C>> {{ return arch}} rule stmt<<C>>: arch<<C>> {{ return arch}}
| addaction<<C>> {{ return addaction }} | addaction<<C>> {{ return addaction }}
| config<<C>> {{ return config}} | config<<C>> {{ return config}}
| default<<C>> {{ return default}}
| dir<<C>> {{ return dir}} | dir<<C>> {{ return dir}}
| driver<<C>> {{ return driver }} | driver<<C>> {{ return driver }}
| iif<<C>> {{ return iif }} | iif<<C>> {{ return iif }}
@ -1487,12 +1508,6 @@ parser Config:
rule cfgfile: (uses<<1>>)* rule cfgfile: (uses<<1>>)*
(stmt<<1>>)* (stmt<<1>>)*
EOF {{ return 1 }} EOF {{ return 1 }}
#mainboard config files are special, in that they can also have
# default values.
rule mainboard_cfgfile: (uses<<1>>)*
(defstmts<<1>>)*
(stmt<<1>>)*
EOF {{ return 1 }}
rule usesid<<C>>: ID {{ if (C): usesoption(ID) }} rule usesid<<C>>: ID {{ if (C): usesoption(ID) }}
@ -1502,7 +1517,7 @@ parser Config:
| expr {{ return expr }} | expr {{ return expr }}
| DELEXPR {{ return DELEXPR }} | DELEXPR {{ return DELEXPR }}
rule option<<C>>: OPTION ID EQ value {{ if (C): setoption(ID, value) }} rule option<<C>>: OPTION ID EQ value {{ if (C): setoption(ID, value, 0) }}
rule opif<<C>>: IF ID {{ c = lookup(ID) }} rule opif<<C>>: IF ID {{ c = lookup(ID) }}
(opstmt<<C and c>>)* (opstmt<<C and c>>)*
@ -1552,9 +1567,11 @@ parser Config:
# ENTRY for parsing a delayed value # ENTRY for parsing a delayed value
rule delexpr: "{" expr "}" EOF {{ return expr }} rule delexpr: "{" expr "}" EOF {{ return expr }}
rule wrstr<<ID>>: STR {{ setwrite(ID, dequote(STR)) }}
rule defstmts<<ID>>: {{ d = 0 }} rule defstmts<<ID>>: {{ d = 0 }}
( DEFAULT ( DEFAULT
( value {{ setdefault(ID, value) }} ( value {{ setdefault(ID, value, 1) }}
| NONE {{ setnodefault(ID) }} | NONE {{ setnodefault(ID) }}
) {{ d = d | 1 }} ) {{ d = d | 1 }}
| FORMAT STR {{ setformat(ID, dequote(STR)) }} | FORMAT STR {{ setformat(ID, dequote(STR)) }}
@ -1564,6 +1581,7 @@ parser Config:
| NEVER {{ setnoexport(ID) }} | NEVER {{ setnoexport(ID) }}
) {{ d = d | 2 }} ) {{ d = d | 2 }}
| COMMENT STR {{ setcomment(ID, dequote(STR)); d = d | 4 }} | COMMENT STR {{ setcomment(ID, dequote(STR)); d = d | 4 }}
| WRITE (wrstr<<ID>>)+
)+ {{ return d }} )+ {{ return d }}
rule define: DEFINE ID {{ newoption(ID) }} rule define: DEFINE ID {{ newoption(ID) }}
@ -1582,11 +1600,12 @@ def writemakefileheader(file, fname):
% (sys.argv[0], sys.argv[1], sys.argv[2])) % (sys.argv[0], sys.argv[1], sys.argv[2]))
def writemakefilesettings(path): 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."""
global treetop, target_dir global treetop, target_dir
# 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") filename = os.path.join(path, "Makefile.settings")
print "Creating", filename print "Creating", filename
@ -1594,23 +1613,17 @@ def writemakefilesettings(path):
writemakefileheader(file, filename) writemakefileheader(file, filename)
file.write("TOP:=%s\n" % (treetop)) file.write("TOP:=%s\n" % (treetop))
file.write("TARGET_DIR:=%s\n" % target_dir) file.write("TARGET_DIR:=%s\n" % target_dir)
# for i in global_options_by_order:
# if (isexported(i, 0)):
# file.write("export %s:=%s\n" % (i, getformated(i, 0)))
# file.write("export VARIABLES := ")
# for i in global_options.keys():
# if (isexported(i, 0)):
# file.write("%s " % i)
file.write("\n") file.write("\n")
file.close() file.close()
def writeimagesettings(image): def writeimagesettings(image):
"""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."""
global treetop global treetop
global global_options_by_order global global_options_by_order
# 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(image.gettargetdir(), "Makefile.settings") filename = os.path.join(image.gettargetdir(), "Makefile.settings")
print "Creating", filename print "Creating", filename
@ -1700,20 +1713,32 @@ def writeimagemakefile(image):
# Print out the user defines. # Print out the user defines.
file.write("\n# userdefines:\n") file.write("\n# userdefines:\n")
#for udef in image.userdefines:
#file.write("%s\n" % udef)
# Print out the base rules. # Print out the base rules.
# Need to have a rule that counts on 'all'. # Need to have a rule that counts on 'all'.
file.write("\n# mainrulelist:") file.write("\n# mainrulelist:")
#file.write("\nmainrule: %s\n" % image.mainrulelist)
# Print out any user rules. # Print out any user rules.
file.write("\n# From makerule or docipl commands:\n") file.write("\n# From makerule or docipl commands:\n")
# Old way (hash order): for target in makebaserules.keys():
# New way (config file order): file.write("\n# initobjectrules:\n")
#for target in image.makerule_targets: for irule, init in image.getinitobjectrules().items():
#image.makebaserules[target].write(file) source = topify(init[1])
type = init[2]
if (type == 'S'):
# for .S, .o depends on .s
file.write("%s: %s.s\n" % (init[0], init[3]))
file.write("\t@echo $(CC) ... -o $@ $<\n")
file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
# and .s depends on .S
file.write("%s.s: %s\n" % (init[3], source))
file.write("\t@echo $(CPP) ... $< > $@\n")
# Note: next 2 lines are ONE output line!
file.write("\t$(CPP) $(CPPFLAGS) $< ")
file.write(">$@.new && mv $@.new $@\n")
else:
file.write("%s: %s\n" % (init[0], source))
file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
file.write("\n# objectrules:\n") file.write("\n# objectrules:\n")
for objrule, obj in image.getobjectrules().items(): for objrule, obj in image.getobjectrules().items():
@ -1757,22 +1782,6 @@ def writeimagemakefile(image):
file.write("GENERATED += %s\n" % genfile) file.write("GENERATED += %s\n" % genfile)
file.write("GENERATED += %s\n" % image.getincludefilename()) file.write("GENERATED += %s\n" % image.getincludefilename())
#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 image.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)/config/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 = image.getroot().uses_options.keys()
keys = global_options_by_order keys = global_options_by_order
keys.sort() keys.sort()
file.write("\necho:\n") file.write("\necho:\n")
@ -1850,10 +1859,8 @@ def writeinitincludes(image):
outfile.close() outfile.close()
def writeldoptions(image): def writeldoptions(image):
# Write Makefile.settings to seperate the settings """Write Makefile.settings to seperate the settings
# from the actual makefile creation 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(image.gettargetdir(), "ldoptions") filename = os.path.join(image.gettargetdir(), "ldoptions")
print "Creating", filename print "Creating", filename