Skip to content

Feature: Compile-time Configuration Framework #3

@Rain336

Description

@Rain336

Feature: Compile-time Configuration Framework

Microdragon needs a compile-time configuration framework to simplify configuring the kernel for users and developers alike. Additionally a command line tool should be made to simplify configuring the kernel for end users who don't know or don't want to dig deeper into the kernel.

The Config.toml File

The configuration framework will add a new files to crates besides their Cargo.toml file. This Config.toml will contain the compile time configuration of the crate and it's schema is defined by how the crate uses it. Each crate should supply a default Config.toml with sane default values and comments describing each option.

The value! Macro

The configuration framework should supply a proc-macro value! that reads out a value from the config with an optional default if it's missing. The general syntax should be as follows:
value!($option:lit $(, $( $default:expr )?)?);
The second $option parameter has to be a string literal. If the macro parameters isn't given as displayed, a compile_error! with a descriptive message should be generated to fail compilation and notify the developer. The $option parameter is used to find which key to return from the config. It's a string literal allowing the same dotted key syntax as defined in the TOML spec to access values in the Config.toml. This syntax is slightly extended by allowing arrays to be accessed by tier index, so the second element of foo = [ "A", "B", "C" ] can be accessed using foo.2 returning "B". This also works for arrays of tables, so bar inside foo = [ { bar = 1 } ] can be accessed using foo.0.bar. Most data types are returned as their respective literals by this macro. Arrays and tables cannot be returned, doing so will generate a compile_error!. Date and time types are returned as ISO-8601 formatted strings, assuming the build computer's local time zone. It is recommended to cache the Config.toml to prevent further disk I/O.

The #[config(...)] Macro

A version of the built-in #[cfg(...)] macro that reads it's values out of the Config.toml. Similar to it's built-in counterpart, it can use any(...), all(...) and not(...) to match multiple options and invert options. For actually matching an option, a syntax similar to the built-in is used, but instead of a simple identifier, the dotted notation as described above can be used, with one exception. Only quoted keys with " are allowed due to the way that rust macros work. For the matching option not only strings, but any literal should be supported, using the same conversion as described above for the value! macro. If the type of the resolved key is a bool, the the = true/false can be left out in which case the option matches, if the resolved bool is true.

The #[config_attr(..., ...)] Macro

A version of the built-in #[cfg_attr(...)] macro that reads it's values out of the Config.toml. It accepts the same syntax as described above for #[config(...)] as it's first parameter with the second being the attribute to insert, if the first parameter matches.

Configuration CLI

Finally a CLI tool should be crated to help configure the kernel for users who don't plant to delve too deep into the kernel's code and instead just want to configure and build the kernel, be it manual or automated with scripts. This CLI tool should support two modes of usage, one setting, getting and listing keys using command line arguments and another mode using a terminal UI.

Command Line Args Mode

The command line mode allows doing multiple operations at once, each returning one line in the result. The operations are as follows:

  • -s <key> <value> / --set <key> <value>
    • Sets the given <key> to <value> in the current project's config.
    • The <key> uses the same syntax as the config! macro.
    • The <value> is type checked to have the same TOML data type as the existing value.
    • This operation prints a line of <key> = <value> with the newly set <value>.
  • -g <key> / --get <key>
    • Gets the given <key> from the current project's config.
    • The <key> uses the same syntax as the config! macro.
    • This operation prints a line of <key> = <value>, with <value> being the value from the config.
  • -l [key] / --list [key]
    • Lists the sub-keys of the given [key] from the current project's config, if [key] is supplied.
    • List of key in the TOML root, if [key] is missing.
    • This operation prints a line of <key-1> <key-2> <key-3> ..., where <key-n> is one of the listed sub key.
  • -p <project-path> / --project <project-path>
    • Switches the current project to <project-path>.
    • This is only valid if the tool is running in a cargo workspace, otherwise an error is returned.
    • This operation prints no output.

Terminal UI Mode

The terminal UI displays the config in a tree view, displaying a key's comment. The tree should be collapsed on start with the user expanding options they are interested in. The user should also be able to restrict their view onto a certain sub-tree, with the option to go back up a sub-tree restriction using a button press. Trying to go out of the root tree, will close the terminal UI. The key comments should be able to pick a widget for their option using a mnemonic line, otherwise a set of default widgets gets displayed. These mnemonic line are not displayed in the terminal UI. If the CLI is started in a cargo workspace, a tree of projects inside the workspace is displayed. Selecting a project, restricts the view onto that project's configuration tree. Trying to go out of that root tree will return the user back to the project select tree. Finally the terminal UI accepts some command line arguments too.

  • -p <project-path> / --project <project-path>
    • Makes the tool act as if it was opened in the given <project-path>'s project, even though it is run in a cargo workspace.
    • This is only valid if the tool is running in a cargo workspace, otherwise an error is returned.
  • -r <key> / --restrict <key>
    • Restricts the displayed view to the given <key>, similar to how the user could choose to.
    • If the terminal UI was opened with -r, the restricted view acts as the root, so trying to get out of it will close the terminal UI.
    • If the terminal UI is run in a cargo workspace, this option additionally requires -p.

Disambiguate -p <project-path>

The -p parameter is used in both command line mode and terminal UI mode. To disambiguate what mode should be used, the other arguments should be examined. If one of the unambiguous arguments is passed, -r for terminal UI mode and -s / -g / -l for command line mode, the corresponding mode should be use. If arguments from both modes are passed, the tool should error out with a message explaining the error. If only -p is passed, terminal UI mode should be assumed, since command line mode with only -p is basically a no-op.

Terminal UI Comment Mnemonics

  • Limit:
    • Takes an optional <min> and an optional <max> in the form of <min> - <max>
  • Slider:
    • Takes the limits from Limit: if present, but a custom range can be provided in the same format as Limit:
  • Stepper:
    • Takes the limits from Limit: if present, but a custom range can be provided in the same format as Limit:
    • After the optional limits, either a list of steps, separated by spaces, can be passed or an expression of every <step> meaning the steps will be all values from the min to the max, increasing by <step> each time.
  • Enum:
    • Following is a list of enum values per line in the format <value> - <description>

Metadata

Metadata

Assignees

No one assigned

    Labels

    featurePropsal for a bigger feature or change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions