Skip to content

Feature: Minimum/maximum compatibility mode #956

Open
@matthijskooijman

Description

@matthijskooijman

This is something that I've been thinking about for quite some time. I might have proposed it already sometime, but I couldn't find anything :-) This is not strictly something for arduino-cli, but more something for the Arduino ecosystem as a whole, but this seemed like a good place to at least discuss this.

One of the things I've seen in the past is that making change to the Arduino cores to add features or fix bugs is hard when they affect compatibility. There are quite some things where we would want to fix things or change defaults, but breaking existing libraries prevents us.

Examples are setting a default timeout on the Wire library, a dummy Print::flush() implementation, the -fpermissive flag, deprecated functions in the SPI library and a recent one that triggered me writing this, is making failed memory allocation terminate instead of returning NULL.

In a lot of cases, one can create a deprecation scheme for this compatibility, e.g. by 1) first introducing an alternative function or extra argument, then 2) encourage people to switch to this new function or explicitly pass this argument, and then later 3) remove the old function or switch the default for the argument. If done properly, this produces sketches and libraries that are backward compatible across step 3 (e.g. a sketch will work with any core version after step 1), sometimes even across step 1 too.

However, encouring people to switch to a new function or similar is currently quite hard. We can update documentation, but that doesn't reach the right audience usually. Ideally, there would be some way where people could be automatically notified of potential incompatibilities in their code, helping them to future-proof their code.

What I envision we could implement, is three modes of compilation:

  1. The "Minimum compatibility" mode disables / removes everything that is deprecated or discouraged, causing any code that uses it to compile. This mode can be used to check your code and helps making it future-proof. We should encourage advanced users and library authors to use this mode by default.
  2. The default mode is pretty much as we have now, except we could maybe add some deprecated attributes to produce warnings.
  3. The "maximum compatibility" mode re-enables (some) constructs that have been removed from the default mode already. This can be used when you need to compile an older sketch or library that has not been updated for a long time.

When something is removed and/or changed in a backward incompatible way, this changes is first made only for mode 1. After some time, when people have had opportunity to use mode 1 to future-proof their code, the changes are also mode for mode 2. If feasible, the change should never be made for mode 3 (i.e. in mode 3 old stuff should be supported indefinitely), but I suspect that in practice this would prevent further improvements, so things might also disappear from mode 3 as well (alternatively some new features would not be enabled in mode 3).

One question is how should the user configure this mode? I see two options:

  1. The obvious way would be to add a configuration directive / UI in the tooling (arduino-cli, Arduino IDE), similar to how verbose building and warnings are implemented. Actually putting the -D option on the commandline should probably involve platform.txt somehow (like with warnings, or the -DARDUINO option).
  2. An alternative option would be to let each compare handle this separately by using menus (i.e. duplicating the menu for each board, or platform-wide if Feature Request: Support platform-wide "menu" options #922 is implemented).

Even though option 2. would be simpler (no changes to be coordinated and duplicated among all tooling, other than implementing #922), I do think 1. might prove more powerful. It would allow a user to configure this globally (unlike platform options which would probably be reset whenever you switch boards or platforms) and give the option a more official status (instead of each platform maybe defining slightly different meaning to each mode, or offering different modes). It would also mean that libraries could also respond to the same macros in addition to just the cores, making things even more powerful (this does require that we globally specify how the macro(s) is/are named and what their meaning is exactly).

One important aspect of this is of course documentation. Having a technical mechanism to check for compatibility issues is one thing, but we should make sure that cores and libraries have a good list of all stuff that is different between each of these modes, ideally with some hints on how to migrate existing code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions