Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix "Argument list too long" error in qstr generation for large projects#18328

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
andrewleech wants to merge1 commit intomicropython:master
base:master
Choose a base branch
Loading
fromandrewleech:fix-qstr-long-cmdline

Conversation

@andrewleech
Copy link
Contributor

@andrewleechandrewleech commentedOct 26, 2025
edited
Loading

Problem

When building MicroPython projects with a large number of source files, the qstr generation step fails with shell errors like:

/bin/sh: Argument list too long

This occurs because themakeqstrdefs.py script receives all source file paths as command-line arguments, which can exceed the shell'sARG_MAX limit. This issue was first encountered when including large user C modules like LVGL, which adds 1200+ files to the qstr scanning list.

TheARG_MAX limit varies significantly between systems:

  • Typical Linux systems: 128KB - 2MB depending on kernel version
  • This explains why builds succeed on some machines but fail on others with identical source code
  • The same project may build successfully on a system with a newer kernel but fail on older systems with lower limits

The issue manifests during the qstr preprocessing step inpy/mkrules.mk when generating$(HEADER_BUILD)/qstr.i.last.

Solution

This PR implements support for response files (argument files) in the qstr generation toolchain. Response files allow passing the large file list via a file instead of on the command line, completely avoiding ARG_MAX limitations for the problematic argument.

Changes

  1. py/mkrules.mk: Modified the qstr generation rule to write only the source file list to a temporary file (qstr_sources.txt). All other arguments (CPP, flags, dependencies) remain as command-line arguments.

  2. py/mkrules.cmake: Modified to write the semicolon-separated source list to a file at configure time. This avoids passing the huge list as command-line arguments to any build-time process.

  3. py/makeqstrdefs.py: Enhanced the argument parser to detect and read response files when an argument starts with@. The parser now handles both newline-separated format (from Make builds) and semicolon-separated format (from CMake builds).

Implementation Details

  • Response files are indicated by prefixing the filename with@ (e.g.,sources @qstr_sources.txt)
  • Only the large source file list is moved to a response file; other arguments stay on the command line
  • The format is simple: one file path per line
  • Maintains backward compatibility with existing command-line invocations
  • Minimal, targeted code changes focused on the specific problem (file list too long)

Testing

This fix has been tested with:

  • Standard MicroPython ports (mimxrt, unix, stm32) using Make builds
  • ESP32 and RP2 ports using CMake builds
  • LVGL-based projects with 1200+ source files where the previous implementation would fail
  • Existing projects to verify backward compatibility

Related Issues

This addresses build failures in projects with extensive use of external libraries, particularly those using LVGL bindings or other large codebases that push against shell argument limits.

@andrewleechandrewleech added the py-coreRelates to py/ directory in source labelOct 26, 2025
@andrewleechandrewleech marked this pull request as draftOctober 26, 2025 02:05
@andrewleechandrewleechforce-pushed thefix-qstr-long-cmdline branch 2 times, most recently from0bb4f97 to5b602f5CompareOctober 26, 2025 02:21
@github-actions
Copy link

github-actionsbot commentedOct 26, 2025
edited
Loading

Code size report:

Reference:  rp2/boards: Add missing RP2350 RISC-V variants. [6773051]Comparison: py/mkrules,makeqstrdefs: Fix arg list too long error in qstr generation. [merge of 66ec367]  mpy-cross:    +0 +0.000%    bare-arm:    +0 +0.000% minimal x86:    +0 +0.000%    unix x64:    +0 +0.000% standard      stm32:    +0 +0.000% PYBV10     mimxrt:    +0 +0.000% TEENSY40        rp2:    +0 +0.000% RPI_PICO_W       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS  qemu rv32:    +0 +0.000% VIRT_RV32

@codecov
Copy link

codecovbot commentedOct 26, 2025
edited
Loading

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.38%. Comparing base (6773051) to head (66ec367).

Additional details and impacted files
@@           Coverage Diff           @@##           master   #18328   +/-   ##=======================================  Coverage   98.38%   98.38%           =======================================  Files         171      171             Lines       22297    22297           =======================================  Hits        21936    21936             Misses        361      361

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report?Share it here.

🚀 New features to boost your workflow:
  • ❄️Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@dlechdlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sounds like the most straight-forward solution. Do we also need to do this for cmake and msbuild?

Also, I'm wondering why are we parsing LVGL for qstrs? Usually we put 3rd party libraries somewhere where they don't get added toSRC_QSTR so that we don't waste time parsing them since they don't contain any MicroPython code.

py/mkrules.mk Outdated
$(HEADER_BUILD)/qstr.i.last:$(SRC_QSTR)$(QSTR_GLOBAL_DEPENDENCIES) |$(QSTR_GLOBAL_REQUIREMENTS)
$(ECHO)"GEN$@"
$(Q)$(PYTHON)$(PY_SRC)/makeqstrdefs.py pp$(CPP) output$(HEADER_BUILD)/qstr.i.last cflags$(QSTR_GEN_CFLAGS) cxxflags$(QSTR_GEN_CXXFLAGS) sources$^ dependencies$(QSTR_GLOBAL_DEPENDENCIES) changed_sources$?
$(Q)rm -f$(HEADER_BUILD)/qstr_sources.txt&&\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Do we really need the&& \ here? IIRC, running the recipe will already check each line for failure and stop.

andrewleech reacted with thumbs up emoji
py/mkrules.mk Outdated
$(Q)$(PYTHON)$(PY_SRC)/makeqstrdefs.py pp$(CPP) output$(HEADER_BUILD)/qstr.i.last cflags$(QSTR_GEN_CFLAGS) cxxflags$(QSTR_GEN_CXXFLAGS) sources$^ dependencies$(QSTR_GLOBAL_DEPENDENCIES) changed_sources$?
$(Q)rm -f$(HEADER_BUILD)/qstr_sources.txt&&\
forsrcin $^;doecho"$$src">>$(HEADER_BUILD)/qstr_sources.txt;done&&\
$(PYTHON)$(PY_SRC)/makeqstrdefs.py pp$(CPP) output$(HEADER_BUILD)/qstr.i.last cflags$(QSTR_GEN_CFLAGS) cxxflags$(QSTR_GEN_CXXFLAGS) sources @$(HEADER_BUILD)/qstr_sources.txt dependencies$(QSTR_GLOBAL_DEPENDENCIES) changed_sources$?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Should we split this us into two recipes now that there is an intermediate file generated?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'm open to direction here, though my feeling is you split to avoid the time re-processing a file. Considering this is just the file list I can't imagine splitting would speed it up in a measurable way, it just adds a few extra lines to the makefile.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I just mentioned it because I've had make get confused from intermediate files before. It's been too long though that I don't remember the details. Might be OK here since the file gets completely recreated each time the recipe runs.

# Support response files (starting with @) to avoid argument list too long errors
ifarg.startswith("@")andos.path.isfile(arg[1:]):
withopen(arg[1:],"r")asf:
named_args[current_tok].extend(f.read().split())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I guess this means that all file names are stored in a single line? It could be nice for troubleshooting purposes to put each file on a separate line to make it easier to read if someone ever needs to take a peek at it.

Copy link
ContributorAuthor

@andrewleechandrewleechOct 26, 2025
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Actually they are already one file per line but I'll make it a bit more explicit / clearer.

I initially wasn't going to submit this change at all until I figured out whether it was needed, or I just had a bug in my makefile.
Then I figured that having the listing in a fine would be the easiest way to diagnose the issue and that it could also be helpful for others.

@andrewleech
Copy link
ContributorAuthor

andrewleech commentedOct 26, 2025
edited
Loading

Sounds like the most straight-forward solution. Do we also need to do this for cmake and msbuild?

Oh yes they certainly would need the same change.

Update: msbuild shouldn't be affected, it uses a different approach where files are individually preprocessed then the outputs contatenated by custom C# taskConcatPreProcFiles

Also, I'm wondering why are we parsing LVGL for qstrs? Usually we put 3rd party libraries somewhere where they don't get added toSRC_QSTR so that we don't waste time parsing them since they don't contain any MicroPython code.

The parsing isn't (intended to be) lvgl itself but the user C module wrappers, including support libraries and to a limited extent some examples.

I do still need to debug the build scripts a bit more to check if there is indeed much more being added to the qstr list than needed; having them in a file was going to make that easier I figured.

The makefile snippet for the user C module includes some wildcard entries as the module itself involves a level of auto generated code / files.

Regardless I'm honestly not sure how close to an arg limit a "normal" micropython build is to know if this change is really necessary, or if there's just a bug in my user C module makefile.

@andrewleechandrewleechforce-pushed thefix-qstr-long-cmdline branch 9 times, most recently from38d5b09 to1213627CompareOctober 27, 2025 03:13
Support response files in makeqstrdefs.py to handle builds with largenumbers of source files. This prevents shell argument limit exceedederrors during the qstr preprocessing step.Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

1 more reviewer

@dlechdlechdlech left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

py-coreRelates to py/ directory in source

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@andrewleech@dlech@pi-anl

[8]ページ先頭

©2009-2025 Movatter.jp