Semi-manually generating QSTRs for a user MicroPython library? #9892
Replies: 7 comments 8 replies
-
Have you seen https://docs.micropython.org/en/latest/develop/qstr.html which at least provides a high-level overview of the steps involved in QSTR generation (might help you understand the makefiles). Realistically though, supporting this process across more build systems (we also do cmake, which is also a hassle) isn't really scalable. The same is true for IDE build systems (e.g. STM32 Cube IDE) and lots of others. Instead I think the better approach is to build MicroPython using the existing make system, and then integrate the output of that into your build system. See #9529 for the first step towards this -- the idea eventually is that you run the MicroPython build on micropython itself as well as your bindings, and the the output of this can just be included as .c (and .h) files into your SCons or whatever. |
Beta Was this translation helpful? Give feedback.
-
One potential issue I see with trying to patch together multiple "qstrdef" files, is the use of the word "index" 5 times on the linked qstr.html page. |
Beta Was this translation helpful? Give feedback.
-
So I managed to get an example of QSTRdefs generation from the "lv_micropython" port. Hacked and cobbled....over a week of exasperatingly frustrating days I managed to get a QSTR file built with the necessary QSTRs that DID work in the RT-Thread port. (And I do mean exasperating.) Anyway, looking at the verbose build output log (650KB!), I'm more confused than before. ALL I need for an output is the "qstrdefs.generated.h" output file. Which contains NOTHING except a bazillion QSTR definition lines (OK, well, 2,989). A QSTR definition example is:
This looks relatively straightforward. But the QSTR generation process starts with:
This generates a truly ginormous 150MB file, containing hundreds of duplicate lines. It appears to be entirely definitions, structs, and variables. What in the world is this used for? This call also appears to create a huge array of folders with ".qstr" files for every source file. Each of these files contain a list of very succinct QSTR definitions found in the source, i.e.:
Which this can be very easily utilized to generate a QSTRdef--at least every single part of it except for the one index argument. I can understand a lot of the GCC steps and arguments as necessary for interpreting #ifdef conditional defines and such like that. Personally, I don't care/need conditional QSTR generation. That can be omitted. The next QSTRdef generation step is:
This appears to generate "qstr.split" -- which at the end of the build process is a 0-byte empty file. Useless step? Next step:
This appears to go through all of the QSTR files in the "build-standard/genhdr/qstr" directory (created by the very first line?) and concatenate + alphabetically sort them into "qstrdefs.collected.h". This resulting file has thousands of duplicate entries (sometimes 10x duplicates of a single entry). Next instruction:
This generates "qstrdefs.preprocessed.h". This file appears to be some sort of SEVERELY condensed "qstr.i.last" followed by a direct dump of "qstrdefs.collected.h", duplicates and all. I still do not understand in the slightest what the purpose/need of "qstr.i.last" is in the generation of QSTRdefs. Closely related to the above line is:
which throws out all of the definitions, and pulls the actual QSTRdefs together into the only necessary output file. Unless there's some black magic with the number in the 2nd argument in a QSTRdef, I don't see why this can't be DRASTICALLY simplified * 100 into a VERY simple QSTR generation routine:
As I said, I don't care about conditional project #includes that determine what MicroPython modules are/aren't included--which will DRASTICALLY simplify the process, as the entire project's #include and #define structures do not need to be interpreted by the QSTR generation process. Heck, the RT-Thread stock "qstrdefs.generated.h" file just contains every single QSTR for every module--whether used or not. If all of the above is condensed into a succinct question, it would be: |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Does the micropython versions post 2023 have a build/genhdr/qstrdefs.generated.c file ? There is a .h file I know ,what about the .c? OK now I know the answer: No , post 2023 ish , there are only qstrdefs.generated.h file and the qstr.c traverses through the saved Qstrings in qstrdefs....h to find the qstrings and map them . |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Big question...resulting from big frustration...resulting from days of banging my head against every which wall.........
It appears to me that an "official" MicroPython build automatically generates the QSTR files at compile-time, and this is a non-issue.
Or that "most" people just use existing ports that "just work" on a very select number of hardware options. Or that "most" people don't try to push the limits to realize an intended vision.
While I could (and will!) be very specific as to what exactly I'm trying to do, I don't feel that this is a specific question--but rather one that has the potential to significantly ease the difficulty of porting MicroPython to ever more obscure boards/frameworks/compilers, etc.
So, first, my system setup/toolchains
I've been scouring the seemingly empty Web search results for the past couple of days trying to figure this stuff out. A lot of bugfixes required in RT-Thread to get things to compile (things like "return NULL;" in a stubbed-out [for BSP reasons] MicroPython function that's defined as "mp_uint_t"), but after the necessary corrections have been made, MicroPython works without any issues.
Next was generating the MicroPython bindings library, which interfaced between MicroPython endpoints and the LVGL C endpoints. A repository here seemed to provide a lot of help in that regard: https://github.com/lvgl/lv_binding_micropython/tree/master/gen
...well, after fixing numerous errors in it resulting from updates to "pycparser"...which would be my fault for cheating and installing "pycparser" via PIP3 instead of by Git download from the specified age...
Armed with the generated output file, I figured it should be easy to follow the rest of the instructions and patch the various parts all into the MicroPython ecosystem.
15,000 compile errors later (multiple errors for each line being complained about in the generated C library), I realized that something crucial was missing.
And that "something" appears to be an updated QSTR list in "/qstrdefs.generated.h".
Here then is the problem: The RT-Thread MicroPython port has never heard of automatic QSTR generation.
And the other problem: I'm horrible at understanding Makefiles. And I've only heard of Scons since I started using RT-Thread. So trying to translate between the 2...sometimes I wish I could snap my fingers and poof it'd be fixed...
So my question: How do I manually generate the QSTRdefs? I'm talking command prompt-level stuff...not a fully automated "push this button and say bingo" solution that most people seem to expect.
I have the generated bindings library (generated from my specific system setup), "lv_mpy.c". A cool 1.2MB.
I've noticed five Python files in the "micropython/py" folder, which seem that they are responsible and/or the tools I need to generate the necessary files.
Can someone provide the necessary command-line-level utilization steps/instructions for these scripts? Or even a copy of (verbose) compiler verbiage of the QSTR generation part of a normal compile of MicroPython? (I could definitely work with that.)
and yes, I do understand there's "best case practice", and then there "desperate case practice"! I don't mind doing this manually and/or manually regenerating the QSTR files specifically for my "lv_mpy.c" bindings file if/as necessary.
Obviously, once I understand how to manually do this, I will be able to figure out how to automate it with the Scons build environment. Or just wrap all of it into a bigger PY file...
EDIT: by "verbose compiler verbiage", I mean where the output includes the "make*******.py" tool command lines and all arguments, as well as any output from said tools.
Beta Was this translation helpful? Give feedback.
All reactions