Skip to content

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

Merged
Arctis-Fireblight merged 4 commits into
Redot-Engine:masterfrom
Arctis-Fireblight:fix-linux-lines-too-long
May 16, 2026
Merged

Fix: Linux CI failing due to too many arguments in ar command#37
Arctis-Fireblight merged 4 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

Warning

Rate limit exceeded

@Arctis-Fireblight has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 13 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5eff3f5-da21-41e9-84fd-e3eb7aca15b7

📥 Commits

Reviewing files that changed from the base of the PR and between fef86c2 and 2e6daa0.

📒 Files selected for processing (1)
  • .github/workflows/ci-scons.yml
📝 Walkthrough

Walkthrough

Adds configure(env) to install a subprocess-based SPAWN wrapper (shell=False, wait) with ar argument batching and forces ARFLAGS; generate(env) now calls configure. Separately, my_spawn's mySubProcess uses simplified Popen/wait and mySpawn batches long ar invocations into length-limited subprocess calls.

Changes

Linux Build Spawn Wrapper

Layer / File(s) Summary
Configure custom subprocess wrapper with ar batching
tools/linux.py
Adds configure(env) that installs a SPAWN wrapper using subprocess.Popen(..., shell=False) with wait(), implements batching for long ar invocations, sets env["ARFLAGS"] = ["q"], and calls configure(env) from generate(env).
Batching and subprocess call simplification in my_spawn
tools/my_spawn.py
mySubProcess() now uses a reduced subprocess.Popen argument set and proc.wait(); mySpawn() builds a cmdline_base and batches remaining ar arguments into multiple subprocess calls limited by a 32,000-character threshold, running one subprocess per batch.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 In burrows of code I quietly hop,
Batching ar calls so lines never flop,
Spawn runs with care, no shell in the way,
Flags set to quiet, all tidy today,
Hooray for small rabbits who make builds less fray!

🚥 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 title accurately summarizes the main change: fixing Linux CI failures caused by excessive arguments in ar commands, which directly matches the PR objective of splitting long file lists to comply with argument limits.
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.

@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.
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.

🧹 Nitpick comments (1)
tools/linux.py (1)

36-44: 💤 Low value

Batching strategy differs from my_spawn.py.

This file batches by argument count (510 per batch), while tools/my_spawn.py batches by command-line length (32000 chars). Linux's ARG_MAX is typically ~2MB, so the 512-argument limit seems overly conservative for most systems. Consider documenting why this specific threshold was chosen, or aligning the approach with my_spawn.py for consistency.

🤖 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` around lines 36 - 44, The batching uses a fixed 510-argument
chunking in the block that constructs cmdline (vars: cmd, args, cmdline, loop
over range(3, len(args), 510)) which differs from tools/my_spawn.py's
length-based batching; update tools/linux.py to either document why 510/512 was
chosen or replace the argument-count split with a command-line length-based
splitter like my_spawn.py (use cumulative len(cmdline + " ".join(batch)) with a
safe max (e.g., 32000 or configurable ARG_MAX) to decide batch boundaries), and
keep the subprocess invocation using mySubProcess and the existing error-break
logic unchanged.
🤖 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.

Nitpick comments:
In `@tools/linux.py`:
- Around line 36-44: The batching uses a fixed 510-argument chunking in the
block that constructs cmdline (vars: cmd, args, cmdline, loop over range(3,
len(args), 510)) which differs from tools/my_spawn.py's length-based batching;
update tools/linux.py to either document why 510/512 was chosen or replace the
argument-count split with a command-line length-based splitter like my_spawn.py
(use cumulative len(cmdline + " ".join(batch)) with a safe max (e.g., 32000 or
configurable ARG_MAX) to decide batch boundaries), and keep the subprocess
invocation using mySubProcess and the existing error-break logic unchanged.

ℹ️ Review info
⚙️ 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

This job takes well over an hour to run even with the recent performance boosts. Something is very clearly wrong with how Scons is interacting with MinGW since the CMake jobs complete within a few minutes. Given this is not a common configuration, we are disabling this workflow and will rely on the CMake version of this test to check MinGW compatibility instead.
@Arctis-Fireblight Arctis-Fireblight merged commit 8e5fb13 into Redot-Engine:master May 16, 2026
18 checks passed
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