[PATCH] Spec hierarchy dumping for a config

Philip Kirkpatrick p.kirkpatrick at reflexaerospace.com
Tue May 9 15:43:47 UTC 2023


On Wed, May 3, 2023 at 11:12 AM Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:

> Hello Philip,
>
> On 28.04.23 11:27, Philip Kirkpatrick wrote:
> > I don't know if anyone else will find this useful or if it already
> > exists and I duplicated some effort, but I find it difficult to just
> > read the files in the spec folder and understand how they are connected
> > and what files are used in BSPs I'm interested in.  I looked through the
> > wscript and didn't see an existing way to dump the item tree for a given
> > configuration, so I added it.  The patch is as follows:
>
> this looks like a useful addition. I would make it a new command, for
> example "./waf viewspec".
>
>
I originally didn't do it that way because I was having a hard time
figuring out how to add a new command that could get the build context for
the correct variant and I needed to move on.  I had some time today to look
into it again today and got it figured out.

>
> > ---
> > diff --git a/wscript b/wscript
> > index 567f42db2f..4e59188188 100755
> > --- a/wscript
> > +++ b/wscript
> > @@ -151,6 +151,61 @@ def _is_enabled(enabled, enabled_by):
> >           return _IS_ENABLED_OP[key](enabled, value)
> >       return enabled_by in enabled
> >
> > +color_true = '\x1b[32m'
> > +color_false = '\x1b[31m'
> > +color_clear = '\x1b[0m'
> > +
> > +def _get_enabler_op_and(enabled, enabled_by):
> > +    and_str = "{ "
> > +    first = True
> > +    for next_enabled_by in enabled_by:
> > +        if first:
> > +            first = False
> > +        else:
> > +            and_str = and_str + " and "
> > +        and_str = and_str + _get_enabler(enabled, next_enabled_by)
> > +    return and_str + " }"
>
> Can this be simplified to
>
> " and ".join(_get_enabler(enabled, next_enabled_by) for next_enabled_by
> in enabled_by)
>
> ?
>

Yes, it can!  Thinking as a C programmer, I had no idea python could do
that.  "_get_enabler_op_or" can (and has been) also be reduced.


> > +
> > +
> > +def _get_enabler_op_not(enabled, enabled_by):
> > +    return "{ " + color_true + "not " + color_false +
> > _get_enabler(enabled, enabled_by) + color_clear + " }"
> > +
> > +
> > +def _get_enabler_op_or(enabled, enabled_by):
> > +    or_str = "{ "
> > +    first = True
> > +    for next_enabled_by in enabled_by:
> > +        if first:
> > +            first = False
> > +        else:
> > +            or_str = or_str + " or "
> > +        if _is_enabled(enabled, next_enabled_by):
> > +            color_start = color_true
> > +            color_end = color_clear
> > +        else:
> > +            color_start = color_false
> > +            color_end = color_clear
> > +        or_str = or_str + color_start + _get_enabler(enabled,
> > next_enabled_by) + color_end
> > +    return or_str + " }"
> > +
> > +
> > +_GET_ENABLER_OP = {
> > +    "and": _get_enabler_op_and,
> > +    "not": _get_enabler_op_not,
> > +    "or": _get_enabler_op_or,
> > +}
> > +
> > +
> > +def _get_enabler(enabled, enabled_by):
> > +    if isinstance(enabled_by, bool):
> > +        return color_true + str(enabled_by) + color_clear
> > +    if isinstance(enabled_by, list):
> > +        return _get_enabler_op_or(enabled, enabled_by)
> > +    if isinstance(enabled_by, dict):
> > +        key, value = next(iter(enabled_by.items()))
> > +        return _GET_ENABLER_OP[key](enabled, value)
> > +    return enabled_by
> > +
> >
> >   def _asm_explicit_target(self, node):
> >       task = self.create_task("asm", node,
> > @@ -233,6 +288,14 @@ class Item(object):
> >                       "Build error related to item spec:{}: {}".format(
> >                           self.uid, str(e)))
> >
> > +
> > +    def dump_spec(self, bld, bic, depth):
> > +        if _is_enabled(bld.env.ENABLE, self.get_enabled_by()):
> > +            enabler = _get_enabler(bld.env.ENABLE,
> self.get_enabled_by())
> > +            print("│  " * depth + "├──" + self.uid + " # enabled-by: "
> > + enabler)
> > +            for p in self.links():
> > +                p.dump_spec(bld, bic, depth + 1)
> > +
> >       def do_defaults(self, enabled):
> >           return
> >
> > @@ -1320,6 +1383,14 @@ def options(ctx):
> >           help=
> >           "sets the option identified by KEY to the VALUE in the build
> > specification; it is intended for RTEMS maintainers and may be used in
> > the bspdefaults and configure commands",
> >       )
> > +    rg.add_option(
> > +        "--rtems-dumpspec",
> > +        action="store_true",
> > +        dest="rtems_dump_spec",
> > +        default=False,
> > +        help=
> > +        "dumps the currently enable spec yaml files and the links tree;
> > it is intended for RTEMS maintainers and may be used in the build
> commands",
> > +    )
> >
> >
> >   def check_environment(conf):
> > @@ -1587,8 +1658,14 @@ def build(bld):
> >       long_command_line_workaround(bld)
> >       bic = BuildItemContext(bld.env.ARCH_INCLUDES.split(), [], [], [],
> > [], [],
> >                              [])
> > -    bsps[bld.env.ARCH][bld.env.BSP_BASE].build(bld, bic)
> > -    items[bld.env.TOPGROUP].build(bld, bic)
> > +    if(bld.options.rtems_dump_spec):
> > +        print("BSPS:")
> > +        bsps[bld.env.ARCH][bld.env.BSP_BASE].dump_spec(bld, bic, 0)
> > +        print("items:")
> > +        items[bld.env.TOPGROUP].dump_spec(bld, bic, 0)
> > +    else:
> > +        bsps[bld.env.ARCH][bld.env.BSP_BASE].build(bld, bic)
> > +        items[bld.env.TOPGROUP].build(bld, bic)
> >
> >
> >   def add_log_filter(name):
> > ---
> >
> >
> > _______________________________________________
> > devel mailing list
> > devel at rtems.org
> > http://lists.rtems.org/mailman/listinfo/devel
>
> --
> embedded brains GmbH
> Herr Sebastian HUBER
> Dornierstr. 4
> 82178 Puchheim
> Germany
> email: sebastian.huber at embedded-brains.de
> phone: +49-89-18 94 741 - 16
> fax:   +49-89-18 94 741 - 08
>
> Registergericht: Amtsgericht München
> Registernummer: HRB 157899
> Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
> Unsere Datenschutzerklärung finden Sie hier:
> https://embedded-brains.de/datenschutzerklaerung/


---
--- /home/phil-k/RTEMS/TMP/rtems/wscript
+++ /home/phil-k/RTEMS/rtems-tools/rtems/wscript
@@ -151,6 +151,40 @@
         return _IS_ENABLED_OP[key](enabled, value)
     return enabled_by in enabled

+color_true = '\x1b[32m'
+color_false = '\x1b[31m'
+color_clear = '\x1b[0m'
+
+def _get_enabler_op_and(enabled, enabled_by):
+    return "{ " + " and ".join(_get_enabler(enabled, next_enabled_by) for
next_enabled_by in enabled_by) + " }"
+
+
+def _get_enabler_op_not(enabled, enabled_by):
+    return "{ " + color_true + "not " + color_false +
_get_enabler(enabled, enabled_by) + color_clear + " }"
+
+
+def _get_enabler_op_or(enabled, enabled_by):
+    return "{ " + " or ".join((color_true if _is_enabled(enabled,
next_enabled_by) else color_false) + \
+    _get_enabler(enabled, next_enabled_by) + color_clear for
next_enabled_by in enabled_by) + " }"
+
+
+_GET_ENABLER_OP = {
+    "and": _get_enabler_op_and,
+    "not": _get_enabler_op_not,
+    "or": _get_enabler_op_or,
+}
+
+
+def _get_enabler(enabled, enabled_by):
+    if isinstance(enabled_by, bool):
+        return color_true + str(enabled_by) + color_clear
+    if isinstance(enabled_by, list):
+        return _get_enabler_op_or(enabled, enabled_by)
+    if isinstance(enabled_by, dict):
+        key, value = next(iter(enabled_by.items()))
+        return _GET_ENABLER_OP[key](enabled, value)
+    return enabled_by
+

 def _asm_explicit_target(self, node):
     task = self.create_task("asm", node,
@@ -232,6 +266,14 @@
                 raise type(e)(
                     "Build error related to item spec:{}: {}".format(
                         self.uid, str(e)))
+
+
+    def dump_spec(self, bld, bic, depth):
+        if _is_enabled(bld.env.ENABLE, self.get_enabled_by()):
+            enabler = _get_enabler(bld.env.ENABLE, self.get_enabled_by())
+            print("│  "*depth + "├──" + self.uid + " # enabled-by: " +
enabler)
+            for p in self.links():
+                p.dump_spec(bld, bic, depth + 1)

     def do_defaults(self, enabled):
         return
@@ -1683,3 +1725,47 @@
                 print(variant)
     if first:
         no_matches_error(ctx, white_list)
+
+
+def append_variant_viewspec(bld):
+    import waflib.Options
+    from waflib.Build import BuildContext
+
+    for var in bld.env["VARIANTS"]:
+        class magic(BuildContext):
+            cmd = "viewspec_" + var
+            fun = "viewspec"
+            variant = var
+
+        waflib.Options.commands.append(bld.cmd + "_" + var)
+
+def viewspec(bld):
+    if not bld.variant:
+        check_forbidden_options(
+            bld,
+            [
+                "compiler",
+                "config",
+                "options",
+                "specs",
+                "tools",
+                "top_group",
+                "version",
+            ],
+        )
+        load_items(bld, bld.env.SPECS)
+        append_variant_viewspec(bld)
+        return
+    long_command_line_workaround(bld)
+    bic = BuildItemContext([], [], [], [], [], [],
+                           [])
+
+    print("BSPS:")
+    bsps[bld.env.ARCH][bld.env.BSP_BASE].dump_spec(bld, bic, 0)
+    print("items:")
+    items[bld.env.TOPGROUP].dump_spec(bld, bic, 0)
+
+from waflib.Build import BuildContext
+class viewspec_magic(BuildContext):
+        cmd = 'viewspec'
+        fun = 'viewspec'
---
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20230509/f67e3f0f/attachment.htm>


More information about the devel mailing list