-
Notifications
You must be signed in to change notification settings - Fork 216
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
RFC: We need some sort of configuration system #1111
Comments
This is related to #42 I guess I still think toml-cfg could be a nice option. We are also using it in esp-wifi already. Downside might be that it (at least I think so) only supports "flat" configs but I don't think we really need nested config structures (and maybe it's supported - just never tried). After unifying the HAL it would be even easier to use. Additionally, it was created by a well-known and trusted person. It would be a nice fit to replace things like As you already said: there are things which need and should be kept as features but there are a lot of other things which don't need to be features. I'm not entirely sure what "build system" means since it could mean a few different things. One thing I could think of: Have a crate which provides functionality we want in the fn main() {
awesome_esp_hal_build_support_crate::main();
} Not sure if we need or want something like that. Maybe it's not worth it at all I would say at least in the beginning we won't really need something like menuconfig/guiconfig. We won't have much options in the beginning - editing a config file would probably be good enough. Later we might want to have something like that |
I 2nd |
I'm not sure I understand why we need |
What we need is a way for the end user to configure things in our library crate. I don't see how But maybe I just don't see the obvious way - a POC might shed some light on this. If we are concerned, we could just ask James Munns about the support status of |
Regardless of how we configure things in future .... here are the current features of esp-hal-common and an initial guess what will be a config option - certainly needs some discussion
Edit by Scott: Removed the xtal features |
I had a look and tried to clean it up, I second that it is very nice for the purpose. |
So are we zeroing on |
I think that toml-cfg solves part of the problem, one thing I'm missing is how to turn config options into cfg flags. For instance, in the case of placing things in ram we will need to do something like |
Another thing is how do we validate the config? For instance, if someone puts their PSRAM speed value to 400mhz, which isn't supported, do we just let it die at runtime? I'd personally like to see some bounds or value sets that we can set on some fields of the configuration struct. |
My final concern, in regards this time to specifically cfg-toml, is maintainability concerns. What happens if/when cfg toml starts limiting us and we need to adapt/modify it? It's currently not actively maintained, now maybe we can help out here and become a maintainer of it, or perhaps its feature complete and the author doesn't expect to add more changes. |
We can definitely go with our own solution - we probably just need to "borrow" this from cfg-toml: https://github.com/jamesmunns/toml-cfg/blob/71f45258c4f8c9a23e5ac00c5220dd8b2f0f780a/src/lib.rs#L208-L240 And then we should be able to locate the config in our esp-hal build.rs. Then we can generate Rust code and/or cfg flags. The only thing I don't have a good idea for is validation. We could use a schema file but they are not fun to maintain |
I think there are some crates for validation we can take inspiration from. This is sorta what I have in my head: #[config]
pub struct Config {
#[cfg] // cfg converts bools to cfg flags, probably needs another name
place_spi_in_ram: bool,
#[values([40, 80])] // could also be a range?
psram_speed_mhz: usize
} This is just a rough design, but I think this would cover our use cases? Is there any other kind of configuration that this wouldn't work for? Maybe a schema file would be better than "in-code" validation, but you're right writing schema files are no fun. Maybe there is a format/crate that exists already that would make this less tiresome though, which might make this path viable. |
Probably would be good to provide feedback on this pre-rfc. toml-cfg as-is has some shortcomings since it breaks once --target-dir is declared. |
Another option would be to take inspiration from Kconfig ( https://www.kernel.org/doc/html/next/kbuild/kconfig-language.html ) and just do the same in TOML (somehow). Since it's around for some time I guess they have everything we could ever need - even when we someday come up with a GUI Or we just use their format. e.g. there is a parser https://crates.io/crates/nom-kconfig |
How complex would it be needed? Conceptually it would be similar figment but at compile time, so the proc_macro might reuse the serde notation. Ideally the same syn code could be used to make a configure-like that parses the crates to get the information like cbindgen does. But would be quite big and potentially overkill if something simpler might work. |
Another consideration would be whether it is possible to do some form of linker configuration. I.e #703? I would place this on the stretch goal side of things, but worth thinking about. |
Just copying in from chat:
Glad to see it's been (somewhat) working for you! |
This conversation seems to have diverged heavily from what I originally envisioned, so I guess somebody else can take over this. |
We haven't settled on anything yet, we're still gathering requirements and poking around to see what's already out there. This discussion would benefit greatly from your vision and input, so please stick around! |
Bumping this old thread: Could we just use |
Whilst I like the simplicity, it doesn't do any validation; it also doesn't do any name collision detection which could make things very annoying to debug. |
Could this be solved with a procedural macro (An enhanced version of #[entry(watchdog, psram(80))]
fn main() {
// stuff
} I think all the settings described above can be configured in the macro. Stuff like One of the big reasons I came to no_std was to run away from |
There will definitely never ever be a What I currently have in mind is a plain config file (TOML) side-by-side to the manifest file. If there is no config, defaults will apply. While Additionally, there might be a TUI/GUI (which isn't mandatory to use) - something like this: |
Oh okay that's great to hear. I'm guessing there will be some way to merge these toml files across crates in the same way cargo additively merges features? |
In my current POC there is really only one config file in the end looking something like this
(Those things are totally made up for an example - not actually tested yet with the real crates) We will still have things that remain features - the config is more meant for things where a feature is "overkill" (but the distinction is a bit blurry of cause) |
Is this really a problem that we need to solve using some random external tool/exotic build system? What problem do we have where Rust's type system isn't good enough by itself? |
I'm open to native solutions, but the only solution I'm aware of for something like setting heap size is using env variables which are not very ergonomic, and also doesn't offer any way to validate the options/value combinations (we probably could via some build scripts, but these are also not that pleasant). |
It looks like there is finally a fix for the |
to recap, the idea is to have an Then the entries can follow usual pattern for env overrides as seen in system-deps. |
This is by no means guaranteed, we haven't started designing anything around these parts yet. However, together with some of our additional plans, I think the most straightforward option is a project management tool that you can install from cargo, that you can then use to generate your project (clean or from a template) and manage its configuration. I think we can provide a menuconfig-like terminal app to manage the configuration that provides help on the options. The actual configuration format is undecided, there are subtleties around non-string configuration values. |
Just a bad idea: it's possible to make #[inline(always)] // (or maybe even place it into RAM?)
fn fn_name(...) {
if CONST {
fn_name_ram(...)
} else {
fn_name_flash(...)
}
} It's possibly a bad idea, but it's technically possible, so if we were to choose a system that uses generates constants instead of env vars, this wouldn't be a blocker. |
env vars can become cfg entries through build.rs |
Since opening this discussion esp-hal has been through several changes, so I took some time to reassess what we would actually need from a configuration system. Compile time valuesLess so for esp-hal, but definitely esp-wifi we have many tunable values that need to be known at compile time. Imo @bugadani's work on reworking the way the HAL is initialized can cover 99% of those cases, even something like heap initialization could be completed by taking a Conditional compilationMany of the original use cases for conditional compilation can be removed with a runtime config. We already did this for the ConclusionI think at this point, a full-blown configuration system with external tooling is not required. Not to say it never will be if our requirements change in the future, but for right now I believe we can achieve what we need to achieve with the tools cargo/rust give us natively through:
I'll be working on a small PoC to replace the |
Sounds great - for mostly just booleans asking to place things in RAM this should definitely be good enough. Only usability issue that comes to my mind would be when users have typos in env-var names (but if we have a common prefix, we can also check in build.rs that there is nothing we don't know) When we go with our own solution for an esp-template replacement we can even offer most of these options there (so users at least can initially benefit from a TUI to configure this) |
And for esp-wifi the current solution would probably also be good enough for now |
Here is the slightly more than PoC I came up with: #2156, which also resolves the esp-wifi configuration. I'm pretty happy with it, but feedback is welcome! |
Closed via #2156 |
As this project continues to grow, we increasingly are feeling a need for user-configurable features. IMO we have reached a point where we have outgrown Cargo features.
I believe that we need some sort of configuration file and build system in order to continue adding hardware support and functionality. I believe that Cargo features should largely be reserved for functionality which requires additional dependencies, and that we should move towards configuring hardware via a configuration file.
I think conceptually this task is not overly difficult; I could cobble something together in a day or two I'm sure. However, I think we need to put some serious thought into what the configuration format will look like, which things should be configurable, and how users will interact with this configuration (ie. do we want to build a tool similar to
idf.py menuconfig
?).I would like to open a discussion regarding potential paths forward on this work.
The text was updated successfully, but these errors were encountered: