Skip to content

Fix: Linux CI failing due to too many arguments in ar command#37

Open
Arctis-Fireblight wants to merge 3 commits into
Redot-Engine:masterfrom
Arctis-Fireblight:fix-linux-lines-too-long
Open

Fix: Linux CI failing due to too many arguments in ar command#37
Arctis-Fireblight wants to merge 3 commits into
Redot-Engine:masterfrom
Arctis-Fireblight:fix-linux-lines-too-long

Conversation

@Arctis-Fireblight
Copy link
Copy Markdown
Contributor

@Arctis-Fireblight Arctis-Fireblight commented May 16, 2026

Added logic to linux.py split long .o file lists into commands of 512 or less.

Summary by CodeRabbit

  • Chores
    • Improved Linux build tooling: more reliable process execution and consistent archiver flags.
    • Enhanced command handling for very long invocations to avoid failures and added clearer command logging.
  • Bug Fixes
    • Prevents build breaks caused by oversized command lines when invoking the archiver.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eead553b-e757-4e99-b9e7-b83f1a362d1b

📥 Commits

Reviewing files that changed from the base of the PR and between 9d0747a and fef86c2.

📒 Files selected for processing (2)
  • tools/linux.py
  • tools/my_spawn.py
 __________________________________________________
< My OKRs are all about finding bugs in your code. >
 --------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

tools/linux.py gains a new configure(env) function that establishes a custom subprocess wrapper for all spawned commands during Linux builds. The wrapper logs each invocation, executes commands via subprocess.Popen without a shell, captures and reports stderr on non-zero exits, and implements argument batching for ar archiver calls that exceed a length threshold. The function also forces env["ARFLAGS"] to ["q"]. The generate(env) function now invokes configure(env) to activate these behaviors.

Changes

Linux Build Spawn Wrapper

Layer / File(s) Summary
Configure custom subprocess wrapper with ar batching
tools/linux.py
The configure(env) function wraps subprocess execution with logging and error reporting, implements batching for large ar commands, and sets archiver flags; this configuration is activated during Linux build setup via a call from generate(env).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A spawner most clever, with logs it does keep,
Archives in batches, no args piling deep,
Stderr whispers softly when things go awry,
Linux builds faster—oh my, oh my!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and specifically describes the main fix: addressing Linux CI failures caused by excessive ar command arguments.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable poems in the walkthrough.

Disable the reviews.poem setting to disable the poems in the walkthrough.

@Arctis-Fireblight Arctis-Fireblight force-pushed the fix-linux-lines-too-long branch from 9d0747a to 71e44a1 Compare May 16, 2026 06:24
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/linux.py`:
- Around line 14-16: The file tools/linux.py was changed but not formatted,
causing CI to fail; run the project's formatter (e.g., ruff format) on
tools/linux.py (or the repo) to apply the blank-line and style fixes, verify
changes around the configure() function and the other noted sections (around
lines ~56-60 and ~97-99), and commit the formatted file so the formatting job
passes the CI.
- Line 57: The global env.Replace(ARFLAGS=["q"]) should be removed and the
ARFLAGS=["q"] setting applied only inside the batched ar handling path (the code
block that implements the batched/concatenated ar invocation), so that other
archive operations are unaffected; locate the batched path in tools/linux.py
(the block that builds the batched ar command) and set ARFLAGS or pass the "q"
flag locally there before invoking ar, leaving the global env.ARFLAGS unchanged.
- Around line 17-24: The code in mySubProcess currently reparses a command
string with shlex.split and passes that to subprocess.Popen, which can mangle
original argv boundaries; change mySubProcess to accept and pass an argv list
(or, if cmdline can be a list, detect and use it directly) and remove
shlex.split so you call subprocess.Popen(argv, env=env, ...) with the original
sequence; apply the same change to the other occurrence that mirrors lines 43-52
in this file (replace any re-parsing of a cmdline string with using the original
argv list or explicit shell=True if you truly need shell parsing).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 749fb0ed-d13a-4165-b192-342acbe1c5ca

📥 Commits

Reviewing files that changed from the base of the PR and between 340cc56 and 9d0747a.

📒 Files selected for processing (1)
  • tools/linux.py

Comment thread tools/linux.py
Comment thread tools/linux.py
Comment thread tools/linux.py
return rv

env["SPAWN"] = mySpawn
env.Replace(ARFLAGS=["q"])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

fd -t f "linux.py" --path "*/tools/*"

Repository: Redot-Engine/redot-cpp

Length of output: 300


🏁 Script executed:

cat -n tools/linux.py | head -80

Repository: Redot-Engine/redot-cpp

Length of output: 2998


🏁 Script executed:

rg -i "batch.*ar|ar.*batch" tools/linux.py -B 2 -A 2

Repository: Redot-Engine/redot-cpp

Length of output: 308


🏁 Script executed:

wc -l tools/linux.py

Repository: Redot-Engine/redot-cpp

Length of output: 85


🏁 Script executed:

cat -n tools/linux.py

Repository: Redot-Engine/redot-cpp

Length of output: 3805


🏁 Script executed:

rg "use_llvm" tools/linux.py -B 3 -A 3

Repository: Redot-Engine/redot-cpp

Length of output: 447


🏁 Script executed:

rg "ARFLAGS|ar\.command|\bAR\b" tools/linux.py -B 2 -A 2

Repository: Redot-Engine/redot-cpp

Length of output: 127


🏁 Script executed:

git log --oneline tools/linux.py | head -20

Repository: Redot-Engine/redot-cpp

Length of output: 136


🏁 Script executed:

git diff HEAD~5 tools/linux.py

Repository: Redot-Engine/redot-cpp

Length of output: 255


🏁 Script executed:

fd -t f "\.py$" tools/ | xargs rg -l "batch.*ar|ar.*batch" 2>/dev/null

Repository: Redot-Engine/redot-cpp

Length of output: 81


🏁 Script executed:

rg -i "batch.*ar|ar.*batch|archived.*batch" --type py

Repository: Redot-Engine/redot-cpp

Length of output: 123


🏁 Script executed:

rg "ar\.command|ARFLAGS" --type py -B 3 -A 3

Repository: Redot-Engine/redot-cpp

Length of output: 906


🏁 Script executed:

find . -name "*.gn" -o -name "*.gni" | head -20

Repository: Redot-Engine/redot-cpp

Length of output: 48


🏁 Script executed:

rg "ARFLAGS|ar_command|ar\.command" --type gn --type gni -B 2 -A 2 2>/dev/null | head -50

Repository: Redot-Engine/redot-cpp

Length of output: 48


🏁 Script executed:

rg -i "batch" --type gn | head -20

Repository: Redot-Engine/redot-cpp

Length of output: 215


🏁 Script executed:

cat tools/linux.py

Repository: Redot-Engine/redot-cpp

Length of output: 3105


🌐 Web query:

GNU ar command q flag behavior replace update

💡 Result:

In GNU ar, the q (quick append) flag is designed to add files to the end of an archive without checking for existing members with the same name [1][2][3]. Because it skips this check, it is faster than the r (replace) operation [1][4]. Key behaviors of the q flag include: 1. No Replacement: It does not replace existing members; it simply appends new files to the end of the archive [1][2]. 2. Placement: Modifiers such as a, b, or i, which are used to specify the position of new members, do not affect the q operation; new members are always placed at the end [1][3]. 3. Symbol Table: Historically, q did not update the archive's symbol table index to maintain speed [1][2]. However, because many systems expect the index to be current, GNU ar will rebuild the symbol table even when using q [2]. 4. Compatibility Note: GNU ar treats the command qs as a synonym for r, meaning it will replace existing files and append new ones [2][4][3]. 5. Incompatibility with u: The u (update) modifier, which only inserts files newer than those already in the archive, is not allowed with q because checking timestamps would negate the speed advantage of the quick append operation [1][4][3].

Citations:


🌐 Web query:

llvm-ar q flag quick append behavior duplicates

💡 Result:

The q (quick append) flag in llvm-ar is used to append files to the end of an archive without checking for or removing duplicates [1][2]. Because it does not perform any deduplication, it is generally faster than the r (replace) operation, which must scan the archive to identify and replace existing members with the same name [1][2]. If the specified archive does not exist, llvm-ar will create it [1][2].

Citations:


🏁 Script executed:

rg "use_llvm|ARFLAGS" tools/ -B 5 -A 5

Repository: Redot-Engine/redot-cpp

Length of output: 7173


Fix global ARFLAGS setting.

The q flag applies globally to all ar invocations on Linux, but only the batched path (lines 44-50) requires special handling to work around command-line length limits. Both GNU ar and llvm-ar implement q as quick append without deduplication, so the concern about incompatible behavior across toolchains is unfounded. However, forcing q globally still affects all archive operations; if needed, apply it conditionally only within the batched path to avoid unintended side effects elsewhere.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/linux.py` at line 57, The global env.Replace(ARFLAGS=["q"]) should be
removed and the ARFLAGS=["q"] setting applied only inside the batched ar
handling path (the code block that implements the batched/concatenated ar
invocation), so that other archive operations are unaffected; locate the batched
path in tools/linux.py (the block that builds the batched ar command) and set
ARFLAGS or pass the "q" flag locally there before invoking ar, leaving the
global env.ARFLAGS unchanged.

Added logic to linux.py split long `.o` file lists into commands of 512 or less.
@Arctis-Fireblight Arctis-Fireblight force-pushed the fix-linux-lines-too-long branch from 71e44a1 to db53da2 Compare May 16, 2026 07:01
… commands.

In `my_spawn.py`, the command line length cannot exceed 32000 characters on windows. The previous implementation would break down linking to one `.obj` file at a time which was extremely slow. The new batching logic instead will batch as many `.obj` files as possible into a single linking operation resulting in significantly faster build times when compiling using MinGW on Windows.
@Arctis-Fireblight Arctis-Fireblight force-pushed the fix-linux-lines-too-long branch from 916313e to c18312f Compare May 16, 2026 07:17
…compiling with MinGW and on linux

The lines removed were forcing Scons to effectively run single threaded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant