From 19f131811f4e805a63d921801934e4de780397a6 Mon Sep 17 00:00:00 2001 From: Amar Takhar Date: Wed, 10 Jun 2015 08:31:19 -0400 Subject: Turn RTEMS Config into a real library. * Stop self-registration of configs and options * Create helper tools for loading options and configs * Add a stub RTEMSConfig class which will be the main entry point TODO: * Make all interaction through RTEMSConfig to avoid passing around an instance of RC. --- py/config/__init__.py | 9 +++++---- py/config/base.py | 53 +++++++++++++++++++-------------------------------- py/config/options.py | 14 -------------- py/config/tool.py | 16 +++++++++++++++- py/waf/configure.py | 7 +++++-- py/waf/tools.py | 8 ++++++-- 6 files changed, 51 insertions(+), 56 deletions(-) diff --git a/py/config/__init__.py b/py/config/__init__.py index ed1cd181e8..9270b198ad 100644 --- a/py/config/__init__.py +++ b/py/config/__init__.py @@ -1,11 +1,12 @@ from .base import BuildConfig, Config, Default, Feature, Disable -from .feature import * -from .options import * +#from .feature import * +#from .options import * class RTEMSConfig(object): options_map = {} # Global options map. features_list = [] # Global features list. config_list = [] # Global config list. - def __init__(self, defaults): - self.defaults = defaults + def __init__(self, default, config): + self.default = default + self.config = config diff --git a/py/config/base.py b/py/config/base.py index d07737e345..428f7fd5eb 100644 --- a/py/config/base.py +++ b/py/config/base.py @@ -4,15 +4,11 @@ except ImportError: from ConfigParser import ConfigParser, NoOptionError from os.path import exists -#from __init__ import options_map, Default, features_list, config_list -from py.waf.compat import add_metaclass #2to3 from sys import version_info Default = None # Default value. Disable = "-DISABLED-" # Disable this option -options_map = {} # Global options map. features_list = [] # Global features list. -config_list = [] # Global config list. def fatal(str): @@ -23,8 +19,9 @@ def fatal(str): class Value(object): """Holds an option value internally. This acts in a similar fashion to a dictionary.""" - def __init__(self): + def __init__(self, rc): self.__dict__["options"] = {} + self.__dict__["rc"] = rc def __setattr__(self, key, value): """Set a value, this either fetches the option or sets it if it already exists.""" @@ -52,14 +49,14 @@ class Value(object): return if option not in self.options: - if option not in options_map: + if option not in self.rc.default: fatal("Missing default option: %s" % option) - opt = options_map[option] # Get option class - i = opt(value) # Create option with value - self.options[i.name] = i # Set in dictionary + opt = self.rc.default[option] # Get option class + i = opt(value) # Create option with value + self.options[i.name] = i # Set in dictionary else: i = self.options[option] - i.set(value) # Set value + i.set(value) # Set value def __str__(self): """String representation of a value object.""" @@ -71,26 +68,15 @@ class Value(object): -# Self register configs. -class ConfigMeta(type): - """Automatically register configs classes.""" - def __new__(cls, name, bases, dct): - new = type.__new__(cls, name, bases, dct) - if hasattr(new, "is_feature") and new.is_feature is True: # XXX: Find a better way to differentiate. - features_list.append(new) - elif hasattr(new, "name"): - config_list.append(new) - return new - -@add_metaclass(ConfigMeta) class Config(object): feature = () #: Feature list (XXX: Why is this required?) feature_default = ("gcc", "debug") #: Default features. - def __init__(self): + def __init__(self, rc): + self.rc = rc self.base = False #: Whether this is a base config or not. - self.option_header = Value() #: Internal header options - self.option_build = Value() #: Internal build options + self.option_header = Value(rc) #: Internal header options + self.option_build = Value(rc) #: Internal build options # Iterate over base classes in reverse order so the 'latest' # defined option is taken. @@ -216,10 +202,11 @@ class BuildConfig(object): """ file_config = "config.cfg" #: Default config file name. - def __init__(self, list_bsp=[]): - self.cfg_default = [cfg_general(), cfg_host(), cfg_bsp()] #: Default BSP configuration. + def __init__(self, rc, list_bsp=[]): + self.cfg_default = [cfg_general(rc), cfg_host(rc), cfg_bsp(rc)] #: Default BSP configuration. self.cfg = list(self.cfg_default) #: BSP config. self.list_bsp = [] + self.rc = rc if list_bsp: self.list_bsp = sorted(list_bsp) @@ -233,7 +220,7 @@ class BuildConfig(object): # Set BSP list. # XXX: Far too complicated due to chicken-and-egg issue. # This will be refactored in the future. - tmp = cfg_general() + tmp = cfg_general(self.rc) opt = tmp.option_build["BSP"] o = self.cfg_user.get("general", "BSP") if version_info < (3,) and type(o) is unicode: #2to3 @@ -262,17 +249,17 @@ class BuildConfig(object): # Make this simplier bsp_map = {} for b in self.list_bsp: - bsp = [x for x in config_list if x.name == b][0] - bsp_arch = [x for x in config_list if x.name == bsp.arch][0] + bsp = [x for x in self.rc.config if x.name == b][0] + bsp_arch = [x for x in self.rc.config if x.name == bsp.arch][0] bsp_map.setdefault((bsp_arch.name, bsp_arch), []).append(bsp) # Save for usage in config_set self.bsp_map = bsp_map for bsp_name, bsp_arch in sorted(bsp_map): - self.cfg.append(bsp_arch()) + self.cfg.append(bsp_arch(self.rc)) for bsp in bsp_map[(bsp_name, bsp_arch)]: - self.cfg.append(bsp()) + self.cfg.append(bsp(self.rc)) def save(self): @@ -317,7 +304,7 @@ class BuildConfig(object): def bsp_get_detail(self, arch, bsp): cfg = None - for c in config_list: + for c in self.rc.config: if c.name == "%s/%s" % (arch, bsp): cfg = c break diff --git a/py/config/options.py b/py/config/options.py index eb2faaed85..eb1840b2eb 100644 --- a/py/config/options.py +++ b/py/config/options.py @@ -1,6 +1,4 @@ from textwrap import TextWrapper -from .base import options_map -from py.waf.compat import add_metaclass # 2to3 wrapper = TextWrapper() wrapper.width = 75 @@ -15,18 +13,6 @@ tag_map = { "storage": "Storage option" } -class OptionMeta(type): - """Self register options.""" - skip = ("Option", "Boolean", "String", "StringList", "Integer") - def __new__(cls, name, bases, dct): - new = type.__new__(cls, name, bases, dct) - if name not in cls.skip: - if name in options_map: - raise Exception("Duplicate option: %s" % name) - options_map[name] = new - return new - -@add_metaclass(OptionMeta) class Option(object): """ Base class for all Options diff --git a/py/config/tool.py b/py/config/tool.py index 6afa5e8526..c178242c58 100755 --- a/py/config/tool.py +++ b/py/config/tool.py @@ -2,7 +2,7 @@ import inspect # Collect a list of options from a module. -# XXX: check to make sure only options are fed to this. +# XXX: check to make sure only options are fed to this, remove the 'skip' list. def get_option_class(module): map = {} skip = ("Option", "Boolean", "String", "StringList", "Integer") @@ -15,3 +15,17 @@ def get_option_class(module): return map +# Collect a list of configs from a module +# XXX: Check to make sure only configs are passed to this, remove the 'skip' list. +def get_config_class(module): + config_list = [] + skip = ("__class__", "Base", "Config") + + for tmp_name, tmp_obj in inspect.getmembers(module): # XXX: This is a hack need to find a better way to 'flatten' the module + for name, obj in inspect.getmembers(tmp_obj): + if inspect.isclass(obj) and name not in skip: + config_list.append(obj) + + return config_list + + diff --git a/py/waf/configure.py b/py/waf/configure.py index 783af45b3c..dae73c6641 100644 --- a/py/waf/configure.py +++ b/py/waf/configure.py @@ -203,9 +203,12 @@ def build_config(ctx): def cmd_configure(ctx, config): ctx.load('waf', tooldir='py/waf/') - from py.config import BuildConfig - cfg = BuildConfig() + from py.config.tool import get_option_class, get_config_class + from py.config import BuildConfig, RTEMSConfig + from py.waf import defaults + rc = RTEMSConfig(get_option_class(defaults), get_config_class(defaults.bsp)) + cfg = BuildConfig(rc) # Misc funcs def yesno(val): diff --git a/py/waf/tools.py b/py/waf/tools.py index 4bd9ad8952..841ecc9008 100644 --- a/py/waf/tools.py +++ b/py/waf/tools.py @@ -170,8 +170,12 @@ def rtems_cmd_config(ctx): if not bsp_list: ctx.fatal("You must specify a single or comma separated list of BSPs using --bsp") - from py.config import BuildConfig - cfg = BuildConfig(bsp_list) + from py.config import BuildConfig, RTEMSConfig + from py.config.tool import get_option_class, get_config_class + from py.waf import defaults + + rc = RTEMSConfig(get_option_class(defaults), get_config_class(defaults.bsp)) + cfg = BuildConfig(rc, bsp_list) cfg.option_set("general", "PATH_TOOLS", ctx.options.path_tools or "") cfg.option_set("general", "PREFIX", ctx.options.prefix or "") cfg.save() -- cgit v1.2.3