-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
libs: Add static compatiblity check for Rust #13245
base: master
Are you sure you want to change the base?
Conversation
Why not generate structure code dynamically, but bind statically? |
Please see #12960, generate structure code dynamically is OK on technical, but binary compatibility cannot be guaranteed. Thus the libc/libstd of Rust can not be built without NuttX develop enviroment, if you want to use them, you must use the nighlty toolchain of Rust instead of stable toolchain. Consider in Rust, the direct use of structs from libc is not very common, so there is an opportunity to implement binary compatibility for these structs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checking of Struct Sizes might become more complex in future, but it's a good start. Thanks!
752964e
to
f78bdcc
Compare
libc/libstd definitely needs the participation of nuttx to be compiled, similar to the WAMR glue code we did before, which allows rust to be bound to a certain configuration to avoid doing these meaningless work. It is a common practice for different nuttx header files to generate different lib/libstd. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm voting no on this PR unless there are other RTOS that use similar alternative practices.
Why not support both approach?
|
Hi @anchao are we thinking of the bindgen approach? As discussed, it's potentially possible, but it will require special tools because we don't want to recompile |
@anchao You can refer to the libc crate for other supported platforms, for example TEEOS: For NuttX, reuse the unix port is better. Only a few data structures need to be defined on the Rust side, and they should be kept in sync with the native definitions on the NuttX side, which are usually related to libc and POSIX/pthread. For function definitions, there should be no doubt; follow the standard definitions to proceed. For other NuttX private interfaces, such as various peripheral drivers and tasks, the bindgen method can be used for support. These additional packages are not within the scope of libstd and should be provided through additional crates. BTW:In fact, to make bindgen work out of the box requires support from libstd. If we want to use bindgen for libstd/libc itself, we need to hack it like: https://github.com/lvgl/lv_binding_rust mentions. |
aa7d49a
to
f5b5c35
Compare
Hi @acassis do you think we should proceed with this approach, to verify the NuttX Struct Sizes? This is for creating the initial version of Rust Standard Library for NuttX. Thanks! |
@no1wudi could we check the struct layout by parsing symbol from image's elf file, which is less intrusive and more accurate? |
That need NuttX to build with debug symbol enabled and add a post action after linking. But, why parsing symbol from elf file is more accurate than this approach? |
@no1wudi @lupyuen maybe we should have an option to let the user test it even when we don't have the guarantees of Struct Sizes case he/she enables EXPERIMENTAL, what to you think? Something like:
|
@acassis Do the test for more case is good idea but if the essential kconfig is missing, the test will fail and affects normal usage with Or we use a python script to do the check with elf file after build. |
@no1wudi I agree with Alan:
|
@lupyuen @acassis OK, indeed, a significant amount of work is still required before it stabilizes. I would like to clarify that the issue regarding the compatibility of struct definitions will take a longer period to address. Firstly, if NuttX introduces any breaking changes, these changes will first be integrated into libc. Then, we will wait for the libc crate to release a new version, followed by upgrading the Rust libstd's dependency on libc to the latest version. The entire cycle could potentially take several months. Currently, I would like to draw everyone's attention to the fact that, in order to reduce the likelihood of such occurrences, my current approach is to reserve space equivalent to two pointer sizes for each structure definition on the Rust side to accommodate updates on the NuttX side:
Regarding question 1, I personally believe that the structures currently under review are all included in the POSIX definition. POSIX defines the minimum set of members within these structures and allows OS implementations to extend them. Therefore, if modifications to these definitions are necessary, especially when adding internal data required by NuttX's implementation, special handling for them should be acceptable. For example, with Line 139 in 32801d3
If in the future we need to add other similar non-standard members that cause the reserved space to be insufficient, then we can wrap these members into an internal NuttX structure and point to this internal structure from If it is OK, I'll add |
The CI report error if
Should we enable the essential options for them in defconfig?
|
@no1wudi Sorry I didn't realise the implications. Could we remove |
Let's wait feedback from rust-lang/libc#3909 before merge this PR. |
This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
does this mean to require everyone here, who might not care rust at all, to maintain certain abi compatibility for rust? |
Not just for Rust, it's a common issue for NuttX now, image that you have a prebuilt .a library that referenced to NuttX header, and once the structure or config changed in NuttX side, you must re-compile the static library from source. Maybe by this approach, not only Rust but also can provide relative stable binary interface for this usage. |
my impression is that "recompile everything on configuration changes" isn't a big problem for many of users of nuttx. as it's a big policy change with pros and cons, i suspect we should discuss this topic with a wider audience. |
This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
Agree, so I open an issue to collect the idea from NuttX community: #12960 |
Hi @no1wudi could you share on the Mailing List the current approach for Rust Standard Library? And explain the tradeoff between Better Optimizations (smaller structures, lto, etc) vs ABI Stability? I think we need the community to agree on this. Thanks! |
OK |
@yamt @lupyuen The current approach is not to enforce a mandatory requirement that we cannot modify these structures or the values of macro definitions, but rather to strengthen the review of their modifications. If possible, we should try not to modify them. However, if these modifications are indeed necessary, we should make the changes in conjunction with the Rust side. |
Make it ready to review since rust-lang/libc#3909 merged |
This patch adds a static compatiblity check for most of structures from NuttX, which is used by Rust. Currently, for most of them have a reserved field, which is for possible future use, you can refer to https://github.com/no1wudi/libc/blob/39277b5357cb2aa7af1bd8344956ec292c35abed/src/unix/nuttx/mod.rs#L71 for more details. I think we should define the initial version carefully, to avoid compatiblity problems in future as much as possible: 1. Struct reserved size is 2 pointer size, is it sufficient? 2. Which option should we preferred to use? Such as SYSTEM_TIME64 and FS_LARGEFILE? 3. Should we enable it by default to cover more cases in build CI? It can prevent introduce compatiblity issues. Signed-off-by: Huang Qi <[email protected]>
It does not mean to enforce Rust compatibility, but rather to provide a way for maintainers to check if any breaking changes were introduced. Signed-off-by: Huang Qi <[email protected]>
This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |
should we move the code to apps(e.g. rustcheck)? since all of them is checking the size and offset of posix type. |
offsetof(struct stat, st_dev) + sizeof(dev_t), | ||
"st_ino offset mismatch"); | ||
static_assert(offsetof(struct stat, st_mode) == | ||
offsetof(struct stat, st_ino) + sizeof(mode_t), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why sizeof(mode_t)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some members have memory align issue:
- dev_t is 4 byte
- ino_t is 2 byte
- mode_t is 4 byte
so if use offsetof(struct stat, st_ino) + sizeof(ino_t) = 6, but offset of mode_t will be aligned to 8.
Summary
This patch adds a static compatiblity check
for most of structures from NuttX, which is used by Rust.
Currently, for most of them have a reserved field, which is for possible future use, you can refer to https://github.com/no1wudi/libc/blob/39277b5357cb2aa7af1bd8344956ec292c35abed/src/unix/nuttx/mod.rs#L71 for more details.
I think we should define the initial version carefully, to avoid compatiblity problems in future as much as possible:
Please feel free to comment