Repository navigation
formula: deuniversalize the keg being installed - #24327
Conversation
- With no targets, `deuniversalize_machos` searched `any_installed_keg`, which returns the opt-linked keg when one exists. - During a source upgrade that is the previous version's keg, already thinned, so the call raised "No universal binaries found to deuniversalize" (e.g. `balena-cli` 25.2.6 -> 25.2.7). Had it not raised, the new keg would have stayed universal. - Bottling CI installs into a clean prefix, so it never hits this. - Search `prefix` instead: inside `install` it is the versioned keg being built.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Summary
Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
0ec05cce-05ad-411a-b6b0-dde7b91b9934
📒 Files selected for processing: 2
Library/Homebrew/formula.rbLibrary/Homebrew/test/os/mac/formula_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
MikeMcQuaid
left a comment
There was a problem hiding this comment.
Thanks! Coderabbit comment matches my concern.
@MikeMcQuaid I can implement the code rabbit suggested fix, but it seems like it's basically unreachable code to me. I'm happy to do whatever you prefer. # Prefer `prefix` to `any_installed_keg`: during an upgrade the latter
# is the old opt-linked keg rather than the keg being installed.
keg = prefix.directory? ? Keg.new(prefix) : any_installed_keg
targets = keg&.mach_o_files&.select do |file| |
- Outside `install`, `post_install` and `test`, `prefix` may not exist when only an older version is installed. - Search `any_installed_keg` in that case, as before, instead of raising from `Keg.new`.
brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?I did not use AI/LLM to create this PR, orI disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.AI use: Claude Opus 5.5 (high effort), in Claude Code. It traced the
balena-cliupgrade failure toany_installed_keg, then drafted thefix, the spec, and this description. I reviewed the diff and the
formula.rbcode paths it relies on (prefix,any_installed_prefix,Keg#mach_o_files).Verification (macOS 26, Intel):
RuntimeError: No universal binaries found to deuniversalize) and passes with it.brew lgtmpasses (typecheck, style, andbrew tests --changed).brew tests --only=formula,os/mac/formula,formula_installer,keg: pass.deuniversalize_machoswith no arguments looks for universal binaries inany_installed_keg. When the formula is already installed, that returnsthe opt-linked keg. During a source upgrade, the opt-linked keg is the
previous version, whose binaries were already thinned when it was
installed. So the call finds nothing and raises, and the build fails at
its last step:
Even if it had not raised, the new keg would have been left universal.
This affects any formula that calls
deuniversalize_machoswith noarguments, on any macOS architecture, whenever it is upgraded from
source. Bottling CI installs into a clean prefix, so it never sees an
old keg and never hits this.
The fix searches
prefixinstead. Insideinstall,prefixis theversioned keg being built. Outside
install, it still resolves toopt_prefixwhen the formula is opt-linked, as before.Reproduce
With an older
balena-cliinstalled (any formula that callsdeuniversalize_machoswith no arguments behaves the same):brew reinstall --build-from-sourceof the installed version does notreproduce it (checked with
balena-cli25.2.7 on unpatched brew):reinstall renames the old keg to
<version>.reinstall, and the opt linkthen points at the new keg being built at the same path.
Tests
Added a macOS spec. An opt-linked 1.0 keg holds a thin dylib and the 2.0
keg holds a universal one. The spec checks that
deuniversalize_machosthins the 2.0 dylib. It fails with the old code, which raises the error
above.