-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
edtlib: Preserve paths of properties from included child bindings #78095
base: main
Are you sure you want to change the base?
edtlib: Preserve paths of properties from included child bindings #78095
Conversation
7c72a6c
to
a253116
Compare
Fixed CI error:
Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we stumbled upon the same issue:
a04f0b4
@benediktibk , yes, and I don't have eyeballs either, I also got that from the linter. IIUC, the fix is part of #78159: I'll rebase and remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more general thing: I think it would be better to split up the test cases (test functions as well as the test bindings) into separate tests. It is way easier to comprehend the whole setup and the assertions when there is basically one aspect tested per test.
# + child-prop-1 | ||
# | ||
# grandchild-binding: | ||
# + gandchild-prop-1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nitpick: There are some "r"s missing in grandchild
Btw, I really like your approach with trying to test all the edge cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not reviewing details until we're sure that we really need such a complex fix. See my comment.
@@ -455,6 +474,126 @@ def _add_included_prop2specs(self, fname: str, contents: dict, | |||
if prop not in self.prop2specs: | |||
self.prop2specs[prop] = spec | |||
|
|||
# Add child-binding definitions inherited from an included binding. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrm, while this (and #65221) seems to work, it introduces quite some additional complexity to the code.
TLDR;
This (and #65221) seem to work around design problems that we should rather fix.
Side notes:
- It seems that this change alters the inheritance of child bindings from override to merge. Maybe I overlooked s.th.? Otherwise it would be a breaking change. Then we should ensure that we clarify this with the arch WG maybe? And we might have to document the change in the migration README of the release.
- While analyzing this problem I think I discovered another bug. It seems as if child bindings are only taken from the direct parent during validation rather than from all ancestors. But maybe I'm wrong on that. The code is a bit hard to follow. If it exists, this problem should go away, with the proposed fixes.
Fixing the binding model:
- I think the main problem with the binding model is that we keep the path in the binding rather than in the prop spec or even on property attribute level (for overridable property attributes like "required"). Whether an attribute is overridable or not can be kept as a class property.
- We may derive a (deprecated) binding-level path property for backwards compat. But keeping the info at the right place immutably should simplify the merging.
- There should also be a way to share more code between merging properties and merging child bindings. And also fix the load/merge duplication.
- I think we should recurse right in the beginning of the
__init__
function to the deepest level and then work our way upwards rather than mixing the two directions to simplify the merge process. - Additionally it may make sense to have a Compat class that extends Binding. Things like "requires compatible" would go away with polymorphism.
Update (2024-09-26): fixed an oversight in my first proposal.
Fixing node validation:
Attaching bindings verbatim to nodes seems to make validation unnecessarily complex. It adds path dependent constraints to subnodes with distinct bindings and possibly conflicting rules across node levels. I think we should merge bindings applied to the same node. In the end we only want a list of property specs attached to each node. Or am I being too naive maybe?
If I'm right then we should be able to establish those validations by merging bindings from top to bottom:
- Iterate the device tree breadth first
- For each node: Merge all property specs of the
Compat
s of the current node and child bindings applied by anchestors to the current node into a single list. Here we can check for conflicts and apply well-defined merging rules. - Validate the current node's values against the merged property specs.
- Distribute property specs of child bindings to the current node's descendants.
- iterate or recurse
This should do away with the need to have a derived property2specs list. And I wouldn't be surprised if we found that other derived state could also be removed.
Update (2024-09-26): simplified.
I'll have some bandwidth over the next days to look into this and try it out. I'll have to tinker around with edtlib anyway to make a poc for some new features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh - of course I can help with the refactoring if you're afraid of such a structural fix. I'm onto some refactoring of edtlib anyway.
Not sure what you mean by that, but this sounds like a bug to me as the intention of updating only the required field should quite obviously inherit the rest. Should be fixed in transit by the design fixes I propose (see the attribute-level inheritance approach). |
Yes, what you quote was actually the description of a bug, caught by the CI and fixed (see this comment). Thanks for your review. |
But your use of edtlib is highly welcome and there are a lot of obvious synergies with more general activities going on in the configuration/provisioning area that might further expand the applicability of edtlib (think DTShell -> Config, DT and Provisioning Shell). That's why I have high stakes in making this work. :-) |
These tests show a known issue and will fail with the version of edtlib at the time of writing. See also: zephyrproject-rtos#78095 Signed-off-by: Christophe Dufaza <[email protected]>
a253116
to
3584a8d
Compare
Bindings initialization supports a rich include mechanism: - a base binding may be "include:"ed at any level: binding, child-binding, grandchild-binding, etc, the defined properties being injected (in cascade) at the level of inclusion - whenever an "include:" appears, the including binding may filter the properties it expects at the binding, child-binding, etc, levels; these filters must apply transitively across included files - when base bindings are inherited which contain definitions about a same property, rules apply: sometimes the last one "wins", but not always, and quite a few things are not allowed (e.g. downgrading a "required: true" or changing a "const:" value) All this happens (recursively) in the Binding constructor, independently of any actual devicetree model (EDT instance). These additional unit tests try to cover somewhat systematically what we finally get at the exit of the constructor once the object is completely initialized. Signed-off-by: Christophe Dufaza <[email protected]>
These tests show a known issue and will fail with the version of edtlib at the time of writing. See also: zephyrproject-rtos#78095 Signed-off-by: Christophe Dufaza <[email protected]>
3584a8d
to
4208824
Compare
Three parts in this comment:
Unit tests and issuesWorking inside the These tests revealed inconsistencies that I initially considered to be regressions introduced while working on this, but:
These tests now constitute the main content of this PR:
You'll find them in a separate source file, Details are also available in the CI tests report for this PR, e.g. in "Devicetree script tests (3.11, ubuntu-22.04) failed". @benediktibk, you also showed some interest in testing: the additional unit tests in commit 3584a8d may as well be helpful independently of this issue, do you think I should open another PR with just this commit ? Indirect
|
Thanks for your review. Right, the test cases weren't well organized/structured. |
UPDATE: We don't have the right smileys to say enough thanks to you for adding that much of extra test coverage. Also see my efforts to extract bindings into a separate generic layer. This combines nicely with what you're doing here. This PR vs. RFC vs. PoCYou're working with the library for much longer than I and I saw that in some aspects, my initial analysis - while being generally correct - shot too quickly. I tend to be overconfident sometimes (sorry for that). So I fully agree with you that a larger refactoring should not be part of this PR. I love the focus of your PR as it stands right now. In the meantime I worked full time on a PoC with the library and get to know it better. I actually find it well designed except for the few things I mentioned. So yes, I'd be really happy to work on an RFC together with you. The initial bug you reported can be fixed with reasonable effort by introducing more fine-grained path tracking as proposed in my comment (which I've mostly implemented in the meantime but not published yet). As you say: this is probably better introduced in a separate PR. For an RFC it's important for you to understand what drives me and see whether we can find common ground to work on... Zephyr as an application programming framworkI'm trying to conceive Zephyr more as an application programming framework rather than an OS. One of the major things that differ between the two approaches is: application frameworks provide an integrated view onto configuration and data modeling while an OS is a rather wild collection of independent applications that all have their own data models and configuration approaches. I think Zephyr's usability as an application programming framework could be improved in that sense. Its configuration is sometimes hard to understand, partly redundant and fragmented. That's why I'm so involved in configuration and developer experience. Related configuration work in the arch WGIt has been decided in the architecture working group that we base future subsystem configuration and provisioning on YAML files. This will be exemplified for network configuration in a first step but should be extensible to arbitrary subsystems in the future. This includes drivers and "upper" subsystems (networking, sensing, bluetooth, ...). There exist isolated solutions to visualize Kconfig and (due to Nordic's efforts) also DT. But nothing similar exists for the envisioned YAML subsystem configuration. We must therefore be very careful to not increase complexity, inconsistency and fragmentation further when throwing yet another configuration approach into the mix. I'm personally very concerned about that although I understand why we cannot extend existing config approaches to multi-instance software configuration and provisioning. RFC outline (including dtsh's role in it)My idea therefore is to enforce a unified view onto configuration in a single tree - something like a combination of sysfs (for read-only, kernel-managed, build-time configuration - think Kconfig + DT) and configfs (for runtime/provisioning read/write, application-managed configuration). You can imagine that I'd love to see dtsh extended as a potential viewer for such a combined configuration tree as it already shares the "filesystem metaphor". While you seem to be interested in the visualization part, my interest is in creating the capabilities in the background required to integrate Kconfig, DT and YAML (hence the sysfs/configfs metaphor). Implementation approachOn the implementation side, my approach is to share the existing, generic overlay/binding/validation system between DT and YAML to re-use existing community knowledge and code and to protect investment into these technologies. [1] As far as Kconfig is still involved in software configuration (as opposed to "feature selection") a partial mapping of legacy Kconfig options to the same data model will be added - initially for the network subsystem configuration which was based on Kconfig so far. My main focus is on integrating hardware (DT) and software (YAML) configuration, though, because that's where the distinction is most ambiguous, confusing and contentious in practice. I want to shortcut dogmatic fights and flame wars that regularly hold the community back in these areas by making the distinction less relevant in practice (at least from a user and migration point-of-view). Currently purists block pragmatists and vice versa. I want all maintainers to strive with their individual approach w/o user experience being damaged. What has been done so farTo achieve that, I've done a profound refactoring of edtlib to extract generic parts (binding, validation, dependency management, overlays, etc.) and base a YAML-to-config-converter on top of it. DT- and YAML-specific subtrees are built on top of that common library which in a final step are merged into a single tree for validation of cross-references and also to deal with migration issues (e.g. software properties being moved from DT to YAML in the future on an as-needed basis). I also developed two alternative configuration/provisioning approaches in my PoC: A zero-footprint-by-default macro target (build-time) and a prototypical NVS settings image generator (provisioning and runtime support). The image generator can easily be extended to littlefs, cbor or any other storage format. NVS is just the more complicated legacy case that's why I tested feasibility with it first. The images are compatible ootb with the existing Zephyr settings subsystem. The image can be flashed into its own partition independently from the build. Compatibility of my changes with edtlib and dtshThe merged tree API is staying 99% the same as what edtlib exposed before, just a few changed imports, changes to the way the API is instantiated and some casting involved if one wants to work with one of the two subtrees rather than with the generic tree. The differences are not in structure but in processing DT vs. YAML internally, so they can be largely hidden behind existing abstractions. Proof: All existing edtlib tests run on top of my refactoring with only minor API changes due to the new dual nature of the tree and the newly introduced type composition feature (except for 3 all failing due to a missing update of ControllerAndData which is not relevant for my PoC - so I'd like to postpone the fix). It should be really easy to adapt dtsh to that combined view and thereby immediately let it visualize configuration, too. I think that in about one week I'll have a preview of this ready for you to inspect. Relevance of an integrated settings view to provisioningThe unified settings view will be most important when it comes to provisioning and migration/backwards compat. Provisioning/Runtime settingsWhat part of the overall tree needs to be provisioned (as opposed to built into the firmware) is strongly application dependent. No dogmatic definition will ever be able to capture for all times what goes where. Users will neither want to provision too much (due to obvious resource overhead as compared to build-time config) nor too little (as some applications will have to be more adaptable than others). I introduce a very basic "path language" based on full paths or DT/config node labels. It basically selects the "folders" to be exported to the image. These folders will then be exposed 1:1 to the application via the settings subsystem. As the settings subsystem uses the "directory/file" model itself, we won't see any impedance mismatch there. It is important that we keep "folder" selection as well as the configuration model very flexible, such that users can easily extend it to their custom runtime/provisioning time configuration needs. Migration supportSee the implementation approach above. The integrated settings view hides legacy settings and structures from client code so that the client code can evolve freely w/o having to deal with backwards compatibility. The importance of "dtsh" (aka "configsh") for an integratied settings viewSomething like "configsh" would be ideal to let users debug and visualize their configuration variants or select the branches to be provisioned or even script per-device "mass provisioning" in the future. I could also imagine extending the existing settings subsys integration into a "light weight" version of configsh in the application shell to browse through and set configuration at runtime as a replacement of the many individual subsystem configuration approaches we have now. This of course only concerns parts that are actually in flash or memory - no one wants the full config tree to be materialized in an embedded system with restricted resources, hence the per-default macro-based approach and the importance of something like "configsh" to assist users with the full model. Next steps on my sideConceptualI'm currently preparing some slides that I'll present in the arch WG to elevate awareness of the topics raised in this comment and elsewhere before. PoCFrom the merged representation, I'll in a next step extract canonical DT_ and CFG_ macro views no matter whether the sources use legacy DT or even Kconfig properties to describe configuration aspects or whether they already migrated to YAML. This is especially relevant in the network area where software configuration aspects are scattered across Kconfig and DT right now. So network configuration is a good "worst case" scenario to start with. Decoupling of sources from targets becomes even more relevant in the provisioning area where data may be coming from third-party systems like large device databases that are also used for device management, OTA, etc. An integration of network configuration with the macro target does already exist. So next comes the integration of the now available settings from the settings subsystem with the network configuration code. Change log:
[1] Of course our home-grown binding approach (which is actually just a Zephyr-specific schema language) has its weaknesses. But while evaluating alternative approaches (pykwalify, JSON schema) it also became obvious that those approaches are not very well suited either. And having our own approach has the advantage that we can tailor it exactly to our needs. That's why I've decided to vote for extending the existing schema modeling to YAML rather than having yet another technology being introduced and re-invent all the wheels. |
Tough question, depends on how far you want to go with refactoring. It might be not worth the time and effort to add tests for stuff which you want to throw out of the window anyway. In my opinion it would make sense to split the test cases you have added here in two categories:
The latter ones could then be added in a separate PR, as they are in general a good thing to have that nothing breaks. |
Way easier to read, IMHO. So far I've skipped only over the tests, as actually verifying their correctness will take me a considerable amount of time. I'll happily invest this, as I will also learn a bunch about these so far to me unknown features, but I would like to do so after you have decided about the approach you want to go ahead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
I propose that we leave the failing tests in the tree and just inactivate them for CI. These tests are perfect for me to check whether my fix works.
I agree with your analysis. Both problems should be documented in their own issues - can you do that? IMO you could use your description verbatim. You may assign me to those issues unless you want to fix them yourself.
Great, I've tried to update my RFC-related comment now such that some of its paragraphs can become part of an RFC almost verbatim if you agree with the basic approach. My RFC-comment misses the design fix for the "last modified source path" issue from my initial comment, therefore I'll re-summrize it here based on my updated knowledge:
100% agree. The additional design fixes I proposed in my original comment re compositional bindings plus related dependency management improvements have already been implemented in my PoC. I think those should be covered by the arch WG's configuration work, though, IMO no need to include them in another RFC. There are still some simplifications pending in my PoC:
Yes, you're right. This is one of the things where I "shot too quickly". I've updated my understanding in the meantime and agree with you. Sorry for the noise.
I couldn't agree more. This is even more true as our co-operation with the devicetree specification project has officially ended and will not be taken up again in the foreseeable future. That's why I didn't make an effort to consider such artificial stakes. My policy on edtlib (tentatively renamed to settingslib in my PoC) would clearly be: Touch/add/fix whatever we think is required for Zephyr. Just as always: keep the API as stable as possible when refactoring (what I did) including improved protection against regressions (what you did). I think with the changes in my PoC and your additional test coverage, edtlib/settingslib would be even more useful externally. I could think of many more tools that could be built on top of it in the Zephyr community in addition to "dtsh" aka "configsh":
I therefore propose that we return to publishing and versioning the library on PyPi so that you and others can properly import it without moving the source code out of the Zephyr tree again. My handling of dtlib would be very conservative, though. I think dtlib doesn't have to be touched at all unless we want to support more recent DT features already built into dtc. The library should be 100% focused on being compatible with the standard and Linux extensions to it.
No of course not. What I did comes close to a full structural re-write. The thorny logic with all its edge cases could be re-used almost 100%, though, except for shuffling some features around for improved encapsulation. Therefore I didn't have any relevant regressions in the tests. In this sense it was simply a re-factoring. |
Echo'ing a discussion from Discord on request of @fgrandel wrt inherited properties. This maybe not be exactly related to this PR but worth mentioning nonetheless. Currently, it is not possible for a node to obtain properties from both its parent's Tentative implementation detailsDummy controller binding# Binding for 'xxx' protocol controller implemented by ST
# For example, this could be I²C or SPI.
include: base.yaml
description: ST 'xxx' controller
compatible: "st,xxx-controller"
properties:
# Controller node must provide its location.
reg:
required: true
# Child nodes ('xxx' devices) are designated
# by a single-cell address (no size)
"#address-cells":
const: 1
"#size-cells":
const: 0
child-binding:
properties:
# For the ST-specific 'xxx' controller, we must indicate
# some device-specific information, e.g. timings. But not
# all vendors will require this - maybe another will want
# operating volatge or something else...
st,xxx-dev-property:
type: int
required: true
description: "'xxx' device property for ST controller" Dummy device binding# Binding for a device communicated with via 'xxx' protocol.
# This is implemented by a "third-party" vendor (i.e., not SoC maker)
include: base.yaml
description: "'xxx' device by vendor 'yyy'"
compatible: "yyy,dummy-xxx-device"
properties:
# Address on the 'xxx' protocol
reg:
required: true
# device-specific property
# this could be a configuration value for example
device-property:
type: int
required: true
description: yyy device property Example instanciation in board DTS
Attempting to build
So it looks like the |
Just to let you know I'm on it. |
Exactly, we currently implement "oneOf" logic, giving preference to explicitly specified compatibles over child-bindings.
AFAIK this is intended. I found an old message by @mbolivar mentioning it. Just speculating: It seemed too complicated to implement type composition properly at the time.
Yes, good example. There are really many such examples. And a certain flavor of composition was actually intended by the standard that's why you can add several comptibles in the first place. Re implementation: I already have this implemented in a way that I believe is well founded on first principles and our needs. Should cover your example case nicely. You'll be invited for review of course as soon as I'm making a PR out of it. If you follow some of the links in my comments, you'll see that bindings (plural) have replaced binding everywhere. :-) |
This unit test was added specifically to cover a regression reported by the CI while working on [1]. Further work on related issues [2] showed that: - [1] and [2] are dead end: we need to first rethink how bindings (and especially child-bindings) are initialized - the inclusion mechanism supported by Zephyr deserves more systematic testing in edtlib if we want to work with confidence The approach we choose is to: - revert all changes made in [1] - from there, systematically add unit tests as we address the issues we identified (or the additional features we need) one after the other [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 33bb3b6. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added to cover the change introduced by [1]. Further work on related issues [2] showed that the chosen approach is dead end. We're reverting all changes made in [1]. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 70eaa61. Signed-off-by: Christophe Dufaza <[email protected]>
[1] was introduced to get more valuable answers from the PropertySpec.path API, which is supposed to tell in which file the property's specification was "last modfied". Further work on related issues [2] showed that the approach chosen in [1] is dead end: we need to first rethink how bindings (and especially child-bindings) are initialized. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit b3b5ad8. Signed-off-by: Christophe Dufaza <[email protected]>
Regarding I also had a look at @fgrandel, sorry for such a brief and late feedback, my (less exciting) priority was to try to do something with the most annoying issues accidentally raised by this PR. |
Except for the renaming of the public class from EDT to EDTree and the different way in which it is instantiated via STree, there should be no difference in the public API or behavior of the resulting object, because I actually paid a lot of attention to backwards compat. I adapted the tests and you'll see that they run mostly unchanged except for the instantiation of STree/EDTree and the changes that map to new features (e.g. type composition). There should be only 3 failing tests and that's on purpose because some feature is missing there. The tests exemplify how to use the generic settings library for EDT only. But of course this is just a PoC and if there's any part of the change that would be problematic to you, then I'd try to co-operate with you as best as I can to keep the changes to the bare minimum required.
No, as a PoC it's far from being PR level or being agreed upon in arch WG even in principle. The purpose of this code is to show that certain claims I'm making regarding re-usability of existing code for configuration are actually feasible. This needs to be discussed step by step in arch WG and then transformed into actual reviewable pieces and only if it actually becomes arch WG policy. I very recently did a first presentation of the PoC in arch WG, though, presenting its high-level design: https://docs.google.com/presentation/d/1JXk1IPPqogRg3Ir6_BK19txXpSQ3KZGaUKNYpIMRGDA/edit?usp=sharing
No, it just gives you a bit of background and it is the discussion that triggered the PoC.
Oh sure, that's entirely possible. I might not have rebased properly or maybe a test for that feature was missing. But certainly there's not problem in principle, it's probably just a small bug in the PoC.
No problem of course. Just fyi: In the next iteration of my PoC that I'll showcase next Tuesday, I'll publish the changes to the binding class that also contain the fix for the path issue. I'll let you know when the code is out, so you can inspect it. The re-design simplifies binding class instantiation considerably, as expected. |
This unit test was added specifically to cover a regression reported by the CI while working on [1]. Further work on related issues [2] showed that: - [1] and [2] are dead end: we need to first rethink how bindings (and especially child-bindings) are initialized - the inclusion mechanism supported by Zephyr deserves more systematic testing in edtlib if we want to work with confidence The approach we choose is to: - revert all changes made in [1] - from there, systematically add unit tests as we address the issues we identified (or the additional features we need) one after the other [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: #65221, #78095 This reverts commit 33bb3b6. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added to cover the change introduced by [1]. Further work on related issues [2] showed that the chosen approach is dead end. We're reverting all changes made in [1]. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: #65221, #78095 This reverts commit 70eaa61. Signed-off-by: Christophe Dufaza <[email protected]>
[1] was introduced to get more valuable answers from the PropertySpec.path API, which is supposed to tell in which file the property's specification was "last modfied". Further work on related issues [2] showed that the approach chosen in [1] is dead end: we need to first rethink how bindings (and especially child-bindings) are initialized. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: #65221, #78095 This reverts commit b3b5ad8. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added specifically to cover a regression reported by the CI while working on [1]. Further work on related issues [2] showed that: - [1] and [2] are dead end: we need to first rethink how bindings (and especially child-bindings) are initialized - the inclusion mechanism supported by Zephyr deserves more systematic testing in edtlib if we want to work with confidence The approach we choose is to: - revert all changes made in [1] - from there, systematically add unit tests as we address the issues we identified (or the additional features we need) one after the other [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 33bb3b6. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added to cover the change introduced by [1]. Further work on related issues [2] showed that the chosen approach is dead end. We're reverting all changes made in [1]. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 70eaa61. Signed-off-by: Christophe Dufaza <[email protected]>
[1] was introduced to get more valuable answers from the PropertySpec.path API, which is supposed to tell in which file the property's specification was "last modfied". Further work on related issues [2] showed that the approach chosen in [1] is dead end: we need to first rethink how bindings (and especially child-bindings) are initialized. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit b3b5ad8. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added specifically to cover a regression reported by the CI while working on [1]. Further work on related issues [2] showed that: - [1] and [2] are dead end: we need to first rethink how bindings (and especially child-bindings) are initialized - the inclusion mechanism supported by Zephyr deserves more systematic testing in edtlib if we want to work with confidence The approach we choose is to: - revert all changes made in [1] - from there, systematically add unit tests as we address the issues we identified (or the additional features we need) one after the other [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 33bb3b6. Signed-off-by: Christophe Dufaza <[email protected]>
This unit test was added to cover the change introduced by [1]. Further work on related issues [2] showed that the chosen approach is dead end. We're reverting all changes made in [1]. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit 70eaa61. Signed-off-by: Christophe Dufaza <[email protected]>
[1] was introduced to get more valuable answers from the PropertySpec.path API, which is supposed to tell in which file the property's specification was "last modfied". Further work on related issues [2] showed that the approach chosen in [1] is dead end: we need to first rethink how bindings (and especially child-bindings) are initialized. [1] edtlib: fix last modified semantic in included property specs [2] edtlib: Preserve paths of properties from included child bindings See also: zephyrproject-rtos#65221, zephyrproject-rtos#78095 This reverts commit b3b5ad8. Signed-off-by: Christophe Dufaza <[email protected]>
The problem to be solved is similar to an issue (#65135) we fixed (#65221) for included property specifications, but here for child bindings.
Issue
All child bindings are initialized at once after included binding files have been merged, with the including binding file set as their origin.
As a result, properties of child bindings all appear to be specified (the last modified semantic of
PropertySpec.path
) by the top-level binding.For example, properties of a channel child of an ADC controller with compatible "nordic,nrf-saadc" (e.g.
zephyr,gain
) will all appear last modified bynordic,nrf-saadc.yaml
instead ofadc-controller.yaml
.Changes
We can use the same approach we've already applied for property specifications:
child-binding:
element of the top-level binding's file, updating any inherited definitionsWith this patch:
adc-controller.yaml
whennordic,nrf-saadc.yaml
is simply included withinclude: nordic,nrf-saadc.yaml
Note:
edtlib: fix Pylint error W0101 (unreachable)
is just while we're at it, does not deserve a PR for itself alone.How has this been tested? ?
We have to be careful when it comes to touching child bindings initialization:
scripts/dts/python-devicetree/tests
to catch obvious regressions (this patch does not cause regressions in DTSh either, where it's in the testing branch)What hasn't been tested ?
specifier2cells
is quite simple)required: true
, will truncate its definition, likely loosing its type and description. This is not tested.I'll comment the fix when all CI tests pass.]
Thanks.