Libuavcan repo diet

Being a professional that lives with the constant pain of dependency management hell I envy the Google engineers and their mono-repo. Last year we decided to remove the drivers folder from the libuavcan repo for the v2 version of this library. I regret that decision as it seems we may be heading towards a world where we have six or more of these repos.

One reason I’m bringing this up now is that I’d like to start an implementation “area” (read: I’d rather not make this another repo) called “libuavcan commons” that would provide some common, platform-specific implementations for auxiliary functions like logging and performance tracing. These would be optional implementations that could be ignored by default or compiled in when enabling a given introspection feature of the new library (or the user could chose to implement the feature themselves, of course). I guess this paragraph constitutes a proposal in its own right but before I can provide concrete examples I need to know where to submit the PR. So this post exists.

I have two proposals:

  1. Undo the decision to break out the driver repos and return them to libuavcan. We would then deprecate everything except for the libuavcan repo.

  2. Combine the drivers into one additional repo that we call “libuavcan_commons” which would contain actual implementations like drivers et-al. Libuavcan would then remain a header-only repo (with tests).

As stated in my opening I rather like (1) but would push for (2) as a compromise rather than (3) which is living with 5+ libuavcan repositories in github with no upper-bound.

That’s an interesting practice.

I think an important thing to consider here is that libuavcan platform adapters (I recall we decided to stop using the word “drivers” because of its ambiguity) are user-owned code, just like applications that use libuavcan:

     User's application        <-- user code
-----------------------------
Libuavcan header-only library  <-- our code
-----------------------------
       Platform adapter        <-- user code*
-----------------------------
       Platform (HW/SW)

The entities grouped under “platform adapter” are often to be supplied by users themsevles, despite the reference implementations we provide for popular platforms (STM32, SocketCAN, Kinetis, and LPC11); therefore, it is important to ensure that the interface between the library and the platform adapter is highly stable (at least as stable as the library’s top-side API).

From the user’s standpoint, a platform adapter is not a dependency of the library; quite the opposite: the adapter and the application require the library so they can function together, so the library is a dependee.

Platform adapters may require specific dependencies in the form of VCS submodules (for example, see the AVR platform-specific code for libcanard). Adding such submodules to the common library repository probably isn’t going to work well: a user who needs platform A shouldn’t be affected by one of the submodules required by a platform B becoming unavailable or obsolete.

Another minor argument against a centralized approach was somewhat discussed here: V1 reference hardware. I worry that a single mono-repo with a number of stock platform adapters might lead users to mistakenly believe that the library is designed to function with a predefined set of target platforms only, and that addition of a new platform amounts to a significant work, much like porting an operating system.

In general, in a safety-critical (or nearly so) setting, code changes of any kind shall be minimized. The mono-repo model seems to encourage the opposite by allowing easy changes to the API between our and third-party code (e.g., platform adapter API) and by increased churn due to the need to keep multiple dependencies (of which not more than one is needed by any single user) and auxiliary features up-to-date and working.

1 Like

Okay. We’ll keep the drivers out just because the universe hates me. That said I do want to create a “commons” area in the repo. Can you review my latest change in my fork for this and the changes I make to CMakeLists.txt? It doesn’t compile yet so I can’t submit it as a PR but it is about half way to getting the DSDL generated and compiling in the bluesky branch.

I’m going through quite the learning curve with cmake so any help would be appreciated.

Actually: I tweaked the state of my fork and found a do-no-harm integration point. PR submitted: https://github.com/UAVCAN/libuavcan/pull/204