-
Notifications
You must be signed in to change notification settings - Fork 190
Book section: Tips for embedded C / C++ developers #9
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
Comments
From @diwic on July 21, 2018 7:5 I wrote an article some time ago, about some Rust patterns that replaces C pointers. Might be helpful in this context too? |
From @korken89 on July 21, 2018 10:4 One thing that is quite popular now is to use In C++ there is a continuous move towards If we can answer these a bit I believe it would be good for convincing the embedded C++ (library) developer. |
From @therealprof on July 21, 2018 10:19 @korken89 No idea where you got that from. It's pretty much exactly the other way around: In Rust variables are const by default and everything is fully propagated through the compilation passes meaning that most functions will just turn into hot air leaving only few instructions behind. All automatically and per default without fiddling with functions trying to convince the compiler to that something is const. It's truly zero cost abstractions something that C++ never really achieved. Mind you, the incredibly optimised binaries is something you will only get with release builds; debug builds are a bloat nightmare. The problems are more on the opposite side of the spectrum: The safety guarantees of Rust make it rather cumbersome to share data, work with self-referential data structures or (especially in embedded areas) work with dynamic amounts of data. |
From @korken89 on July 21, 2018 11:27
I got it from a lot of embedded development (libraries, OSes, and firmwares) in C++ together with participation in the embedded and metaprogramming C++ communities, and now rewriting my C++ libraries into Rust.
I am aware of what you speak, but it is up to the user to make sure that a function will be evaluated at compile time. The simple example, is to give inputs that are runtime dependent, without realizing it, and the compiler will gladly generate runtime code for it rather than to generate a compile time error. Moreover, the LLVM backend is not omnipotent, and assuming that the compiler will optimize everything away does not always happen (unless there is something new I have missed that guarantees this), there are some really good talks on YouTube by Chandler Carruth on the optimization LLVM does, which gives a good view into how well it will optimize and what the limits are.
Here you are misinformed, But indeed, there are some parts of C++ which truly are not zero cost.
Indeed, and this is a significant issue. One way to solve it in C++ is to use value based metaprogramming and a
I am talking about compile time data structures in this case (stored in flash or used to initialize a run-time data structure), run-time data follows the normal Rust way and it is assumed that the readers have read the Rust book before coming here. Please see the Back to the question at hand now, as coming from a C++ perspective these questions are still active and I still believe that it should be covered to some extent. |
From @therealprof on July 21, 2018 13:15
In Rust? No. It's not even possible to ensure that. (Well, with the exception of const functions but they're only usable for initialisation of static data and often not even that).
No, not quite. I'm fully aware that this is a goal of C++ and can be achieved by expert programmers but is except for a few exceptions not done due to being extremely time consuming. Also with C++ that works only inside a single compilation unit or when excessively using code in header files (which a lot of other people, me included, frown upon), which is neither possible in Rust nor necessary.
I also have some C++ background (and consider myself an expert C programmer) and have experienced the exact opposite of what you're trying to say needs fixing/documentation. Proper zero cost abstractions in C++ require a tremendous amount of effort to implement and ecosystem support (which often simply does not exist) and just happen to work out of the box in Rust, which is one of the main reasons why I completely gave up on embedded C/C++ development. I'd really like to learn more about the problems you're facing because I have a strong suspicion there's an easy fix to your problem and yes, that's something that should go in the book, too. |
From @Ixrec on July 21, 2018 20:27 The last few comments sound extremely confused to me, probably in part because In both C++ and Rust, it is trivial to force the compiler to evaluate something at compile-time or error if it cannot; you simply declare a variable to be For actual template metaprogramming that @korken89 Does that answer your questions? |
From @korken89 on July 22, 2018 16:15
Indeed, and I have been creating these kind of abstrations through header-only libraries as you said.
@Ixrec really hit it on the nail here, thanks for the clarifications! The building block that I use in libraries for embedded system is I was not aware about |
From @therealprof on July 22, 2018 17:12 @korken89 You might want to have a look at macros, too, to generate tables and/or runtime expressions at compile time. |
From @korken89 on July 22, 2018 18:21 @therealprof Thanks, I'm already there :) Trying to learn procedural macros now. |
From @Ekleog on August 2, 2018 8:25 IMO, how to use the build system for cross-compiling to embedded systems is the most important thing to put in this section, if it's not already somewhere else. At least that's what I had most issues with when switching to Rust for embedded development :) I guess that's going to be better with upstreaming of xargo into cargo, though. |
From @jamesmunns on August 2, 2018 8:36 @Ekleog check out rust-embedded/wg#48 |
By "build system" do you mean Cargo? The section after the introduction in the embedded book will cover how to use Cargo to cross compile a Rust program, but this info only applies to targets that have tier 1 or near tier 1 support. For the edition that's definitively going to cover Cortex-M, very likely RISCV and MSP430, and maybe Cortex-A and Cortex-R. For unsupported targets you should check out the last part of the embedonomicon. Cross compiling to embedded Linux is trickier because those programs depend on a cross compiled glibc and you need to install gcc. That should have a separate section. |
Triage: It sounds like we at least want to cover:
Anything else that should be covered? Also, we need help writing these tips! For the cross compilation stuff we can adapt my old rust-cross guide. If you want to help leave a comment here and proceed to send a PR to the embedded book and I'll review it! (the location of the markdown file is unimportant at this point) |
What I meant was this plus, for this section, how to link with C, whether with Rust-linking-to-C-library or with C-linking-to-Rust-library :) guess it could be a simple link to someplace in the official documentation, though, as once the Cargo side is done it's no longer really embedded-specific. |
Consider also talking about |
First draft in #81 |
Done in #81 |
Triage(2018-08-20)
We have identified 4 topics so far and need help writing them. See #9 (comment) for details.
From @japaric on July 17, 2018 14:44
We agreed on having a section containing tips for embedded developers that have a C / C++ background. For example, they may be used to using for loop + indexing on arrays but it's more efficient to use iterators in Rust so they should use that instead.
Anything else that should be covered? cc @thejpster
Copied from original issue: rust-embedded/wg#126
The text was updated successfully, but these errors were encountered: