Validate toolchain extra_cflags/extra_ldflags as string lists - #75
Validate toolchain extra_cflags/extra_ldflags as string lists#75swayam-2003 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Existing repo tests still assert ValueError for unknown backends and the build() error message currently presents a contradictory supported-backend list for ninja, so the test suite and messaging need alignment.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Fixes a Python syntax error in BackendDispatcher.configure() that prevented importing the package, and tightens config parsing so toolchain flag fields are validated as lists of strings (avoiding accidental per-character flag splitting from scalar YAML values).
Changes:
- Remove the duplicate
elsepath inBackendDispatcher.configure()and standardize unknown/unhandled backend failures to raiseRuntimeErrorinconfigure()/build(). - Add
toolchain.extra_cflags/toolchain.extra_ldflagsvalidation inload_configto requirelist[str]. - Add regression tests for toolchain flag type validation and document the behavior in the changelog.
File summaries
| File | Description |
|---|---|
tests/ebuild/test_config_validation.py |
Adds regression tests ensuring toolchain flag fields are lists of strings. |
ebuild/core/config.py |
Validates extra_cflags/extra_ldflags types before constructing ToolchainConfig. |
ebuild/build/dispatch.py |
Fixes configure() syntax error and changes unknown/unhandled backend failures to RuntimeError. |
CHANGELOG.md |
Documents the dispatcher import fix and new toolchain flag validation rules. |
Review details
Suppressed comments (1)
ebuild/build/dispatch.py:131
configure()now raisesRuntimeErrorfor unhandled/unknown backends, but the existingtests/ebuild/test_dispatch.py::TestUnknownBackendsuite still assertsValueErrorfor unknown backend names (e.g.bazel,gradle,scons). Unless those tests are intentionally deprecated, this change will break the defaultpytestrun (pytest.ini discoverstests/**/test_*.py). Please update that test suite (and any docs/docstrings that still mentionValueError) to match the new exception type/contract.
else:
raise RuntimeError(
f"BackendDispatcher cannot configure backend '{backend}'. "
"This dispatcher only handles cmake, meson, and cargo "
"(make/kbuild need no configure step). ebuild's own ninja "
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| else: | ||
| raise ValueError( | ||
| raise RuntimeError( | ||
| f"Unknown build backend '{backend}'. " | ||
| f"Supported backends: {', '.join(sorted(ALL_BACKENDS))}" | ||
| ) |
The flags validation is the valuable half, and I confirmed it
Every character becomes a separate compiler flag. The build then fails with something about an unrecognised option Rejecting it at load with a message naming the field is right. It is the same treatment #73 gives a malformed The dispatcher half is supersededThree PRs fix the same Standardising on What I would likeRebase onto #66 and reduce this to the Worth extending while you are there, if you want: VerificationConfirmed the scalar-splitting behaviour on current |
2949a60 to
57cb915
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The PR title/description includes BackendDispatcher fixes, but the provided diff only updates config validation/tests/changelog, creating a scope mismatch that must be resolved before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
| extra_cflags = raw.get("extra_cflags", []) | ||
| extra_ldflags = raw.get("extra_ldflags", []) | ||
|
|
||
| for field_name, value in ( | ||
| ("extra_cflags", extra_cflags), | ||
| ("extra_ldflags", extra_ldflags), | ||
| ): | ||
| if not isinstance(value, list): | ||
| raise ConfigError( | ||
| f"Toolchain field '{field_name}' must be a list." | ||
| ) | ||
| if not all(isinstance(item, str) for item in value): | ||
| raise ConfigError( | ||
| f"Toolchain field '{field_name}' must contain only strings." | ||
| ) | ||
|
|
srpatcha
left a comment
There was a problem hiding this comment.
The toolchain-flag validation here is a genuine find and I want it kept. The
syntax repair in the title is not in the diff, though — I checked, because two
other PRs claim the same fix and I wanted to know which actually deliver it.
The syntax error is still present on this branch
$ git show pr75:ebuild/build/dispatch.py > /tmp/d75.py
$ python3 -c "import ast; ast.parse(open('/tmp/d75.py').read())"
line 133: invalid syntax
129 f"Unknown build backend '{backend}'. "
130 f"Supported backends: {', '.join(sorted(ALL_BACKENDS))}"
131 )
132
133 else:
134 raise RuntimeError(
Byte-identical to master. For comparison, #66 and #78 both parse after their
changes.
Tracked as #87. #66 is the one I would take for it — it removes the duplicated
error path that caused the splice rather than deleting the stray else:.
The flags validation is the part worth saving
This is a real bug and I verified it independently. extra_cflags given as a
string is iterated character by character:
>>> list('-O2 -Wall')
['-', 'O', '2', ' ', '-', 'W', 'a', 'l', 'l']Every character becomes its own compiler argument. The build then fails with
something unrelated-looking, or worse, silently drops the flags the developer
asked for — a -O2 that never reached the compiler is not a visible failure, it
is a slow binary nobody can explain.
Rejecting a scalar where a list is expected, with a message naming the field, is
exactly right, and I have not seen this covered anywhere else in the open PRs.
Suggestion
Rebase onto #66 and drop the dispatch.py hunks that overlap it, leaving this
PR as the flags validation alone. It then reviews on its own merits, has no
conflict to settle, and the part that is uniquely yours is not blocked behind a
syntax fix that two other PRs are also trying to land.
Retitling would help too — as it stands the title promises a repair the diff does
not contain, which is how a reviewer ends up merging it expecting master to be
fixed.
Happy to approve once it is scoped to the validation.
Scalar YAML values such as extra_cflags: -O2 were accepted as strings and later iterated per-character into invalid compiler flags. Reject non-list values at config load time with a clear ConfigError, matching existing target-field validation. Signed-off-by: Swayam Nayak <154440440+swayam-2003@users.noreply.github.com>
57cb915 to
d6c0a62
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Added validation for extra_ldflags item types is not covered by the new tests, leaving a gap in regression protection.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
| def test_toolchain_flag_items_must_be_strings(tmp_path): | ||
| path = write_config( | ||
| tmp_path, | ||
| { | ||
| "project": {"name": "demo"}, | ||
| "toolchain": {"extra_cflags": ["-O2", 42]}, | ||
| }, | ||
| ) | ||
|
|
||
| with pytest.raises(ConfigError, match="extra_cflags.*must contain only strings"): | ||
| load_config(path) |
|
Rebased onto latest upstream/master (d3958f7). Previous CI failures were caused by a stale base that still had the dispatch.py SyntaxError — that blocked pytest collection entirely. This PR now contains only toolchain flag validation + tests + CHANGELOG. All 42 related tests pass locally after rebase. |
Summary
elseinBackendDispatcher.configure()that caused a SyntaxError and blocked importing the package.RuntimeErrorconsistently inconfigure()/build().toolchain.extra_cflagsandtoolchain.extra_ldflagsas string lists so scalar YAML values cannot silently split into per-character flags.Approach
Followed existing target-field validation patterns in
config.pyand regression tests intests/unit/test_dispatch.py.Testing
21 tests passed locally.
DCO
Signed-off-by: Swayam Nayak 154440440+swayam-2003@users.noreply.github.com