arduino / arduino-cli

Arduino command line tool
https://arduino.github.io/arduino-cli/latest/
GNU General Public License v3.0
4.39k stars 384 forks source link

Feature Request: Support platform-wide "menu" options #922

Open matthijskooijman opened 4 years ago

matthijskooijman commented 4 years ago

Bug Report

Current behavior

Currently, boards.txt allows specifying "menu" options for a board. E.g. for the Arduino Mini, boards.txt contains the following (heavily redacted to just show the bare minimum):

menu.cpu=Processor

mini.name=Arduino Mini
mini.menu.cpu.atmega328=ATmega328P
mini.menu.cpu.atmega328.build.mcu=atmega328p
mini.menu.cpu.atmega168=ATmega168
mini.menu.cpu.atmega168.build.mcu=atmega168

When selecting the Arduino Mini board, this allows specifying the "cpu" option as part of the FQBN, and depending on its value the build.mcu option gets a different value. In the Java IDE, this also causes a menu to be shown that allows the user to select between the two options.

These menu options work fine for such board-specific "subselections" or board-specific options, but often there are also platform-wide options. For example, the Adafruit SAMD core defines a "debug" and "usbstack" menu that is used for pretty much all boards: https://github.com/adafruit/ArduinoCore-samd/blob/1e92424a500a8b3fc5be0701bbbab0da167f2cc6/boards.txt#L17-L22 Currently, this means that the menu options and resulting build properties must be repeated for all board definitions, which is less-than-ideal. The ESP32 and STM32 cores have an even bigger number of options.

This could be greatly simplified if platform-wide menus could be specified. Essentially, these would be menus that are defined outside of any board and are shown for all boards. They can probably also be implemented as such, which should make this rather easy. Specifying/storing the values for these menus can still happen as part of the FQBN, it's just the way the menus are specified that would be simplified.

One open question is where to specify these platform-wide menus? We could put them in platform.txt, which would make sense, or put them at the top of the boards.txt. The latter is probably easier and more consistent with the current menu.cpu=Processor line.

Boards-specific subsets of global options

Sometimes, you might want to have global options that apply to most but not all boards. For example, the Adafruit "usbstack" option is really a platform-wide option, but it only applies to boards with native USB. For this, it would be helpful if you could specify a menu globally, but enable/disable it on a board-by-board basis. Maybe this can be done by setting/clearing the menu title? E.g. (I invented a dummy board here, turns out all of the actual boards in the Adafruit SAMD core have USB):

menu.usbstack=USB Stack
menu.usbstack.arduino=Arduino
menu.usbstack.tinyusb=TinyUSB
menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB

adafruit_feather_m0.name=Adafruit Feather M0
# No menu options here, usbstack is inherit from global

board_without_usb.name=Foo board
# Unset usbstack title to hide it
board_without_usb.menu.usbstack=

Another option would be to do opt-in by not specifying the menu title globally, but specifying it per-board. This requires duplicating the title when a menu is used for multiple boards, though:

# Only specify options, no title
menu.usbstack.arduino=Arduino
menu.usbstack.tinyusb=TinyUSB
menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB

adafruit_feather_m0.name=Adafruit Feather M0
# Set a title to include this menu for this board
board_without_usb.menu.usbstack=USB Stack

board_without_usb.name=Foo board
# No title specified, so usbstack menu not used

A final option could be to make it more explicit by supporting an "disabled" subproperty (which defaults to "no" for compatibility). A downside of this approach is that it breaks a menu that wants to use "enabled" and "disabled" as valid options (maybe we can find a name that is less likely to collide than "disabled"?).

# Only specify options, no title
menu.usbstack=USB Stack
menu.usbstack.arduino=Arduino
menu.usbstack.tinyusb=TinyUSB
menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
menu.usbstack.disabled=yes

adafruit_feather_m0.name=Adafruit Feather M0
board_without_usb.menu.usbstack=USB Stack
board_without_usb.menu.usbstack.disabled=no

board_without_usb.name=Foo board

We could probably support multiple of these approaches (e.g. both the title based opt-in and opt-out together, or maybe all three of them by hiding options that either have no title, or have "disabled=yes").

The same approaches can also be considered to hide single options from a menu on a board-by-board basis, in addition to hiding complete menus.

Also note that currently, the menu title (e.g. menu.cpu=Processor) must be specified globally (outside of any board definition). Regardless of what we choose here, I would suggest allowing this line to be global or board-specific. If you then have a menu that is only defined for one particular board, it can just be specified for that board, without splitting up the definition of the menu and without cluttering the global definitions. More generally, you could just split the menu definitions arbitrarily between the global and board-specific parts of the file (even allowing something like a global menu with 2 options and then add a third option for just one board).

Implementation-wise, this could mean you just take all global menu options, apply the board-specific ones for the current board on top, and then treat the result just like menus are being treated now, making this fairly easy to implement.

matthijskooijman commented 4 years ago

One related improvement could be to also allow libraries to define such "menus" or "options", that can be configured by the user. This probably needs some other way to specify values for these options (part of the FQBN no longer makes sense), but this is probably something to do as part of per-sketch metadata as has been requested often before.

ubidefeo commented 4 years ago

@matthijskooijman in a few Sprints we'll get to work on defining what will constitute the bread and butter of Sketch.json, which right now is only really used in the web editor. Here there will be room for Sketch metadata, and your suggestions are as usual more than welcome :)