G
YouTube TikTok Games
Skip to content

Keep compatible outdated runtime dependencies - #24384

Merged
MikeMcQuaid merged 2 commits into
Homebrew:mainfrom
HaraldNordgren:keep-compatible-runtime-dependencies
Oct 29, 2026
Merged

MikeMcQuaid merged 2 commits into
Homebrew:mainfrom
HaraldNordgren:keep-compatible-runtime-dependencies

Conversation

@HaraldNordgren

@HaraldNordgren HaraldNordgren commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

On my MacBook Air (macOS 12.7.6, Xcode 14.2, so no bottles), brew install nmap wanted to rebuild four dependencies from source to go from nmap 7.991 to 7.993:

==> Would upgrade 1 formula:
nmap 7.991 -> 7.993
==> Would upgrade 4 dependencies for nmap:
openssl@4          4.0.3  -> 4.1.0
sqlite             3.54.0 -> 3.54.1
python@3.15        3.15.0 -> 3.15.2
python-setuptools  84.0.0 -> 84.2.1

sqlite is a runtime dependency of python@3.15, and the installed 3.54.0 has the same compatibility_version as the current formula. By the Formula Cookbook's definition, that means nothing built against 3.54.0 needs rebuilding when it's upgraded, so upgrading it before building python@3.15 gains nothing. Since #24273, source builds already keep an outdated build dependency in this case, but runtime dependencies are still always upgraded.

This applies the same rule to runtime dependencies: when the dependent is built from source, keep an outdated runtime dependency whose installed compatibility_version matches, along with the dependencies it was built against. As with build dependencies, it's still upgraded if this install would incompatibly upgrade one of those. Pouring a bottle is unchanged, since #15927 already keeps outdated runtime dependencies that the bottle's tab says are new enough. Building a bottle still upgrades everything.

With this branch, the plan drops sqlite:

==> Would upgrade 1 formula:
nmap 7.991 -> 7.993
==> Would upgrade 3 dependencies for nmap:
openssl@4          4.0.3  -> 4.1.0
python@3.15        3.15.0 -> 3.15.2
python-setuptools  84.0.0 -> 84.2.1

The other three are still upgraded because their formulae don't set compatibility_version, so there's nothing to compare.

One trade-off: if a new version of a dependent needs something newer from a kept runtime dependency, its build fails, just as it would with a kept build dependency, and brew upgrade on that dependency fixes it.

Changes

  • FormulaInstaller: when the dependent is built from source, an outdated runtime dependency now takes the same keep path as build dependencies. :no_linkage still only keeps build dependencies whatever their compatibility_version. kept_build_dependencies and keepable_build_dependencies are renamed to match.
  • Specs: the example that expected an outdated runtime dependency with a matching compatibility_version to be upgraded now expects it to be kept, plus a new example for pouring a bottle. Three specs that stubbed install_bottle_for?: false only to simplify their setup now stub true, since they cover bottle tab metadata and satisfaction caching for runtime dependencies.

AI usage

Claude Code (Claude Opus 5.5) helped trace the dependency resolution and audit code and write the change and specs. I verified it by running brew install nmap on my macOS 12 machine with this branch, which dropped sqlite from the plan as shown above. brew style, brew typecheck and the formula_installer specs pass locally.


  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • I did not use AI/LLM to create this PR, or I 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.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

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: c5ee9946-00e6-4175-a058-c6b15ffd11c9
Commits

Reviewing files that changed from the base of the PR and between 3aa27f5 and f40f6ae.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved dependency handling during formula installation, retaining eligible installed dependencies and accounting for their own runtime dependencies.
    • Corrected handling of runtime dependencies with matching compatibility versions: compatible dependencies are retained during normal installation, while dependencies may be upgraded when their opt prefix is unavailable or a bottle is being poured.

Dependency expansion now retains eligible runtime dependencies as well as build dependencies. Bottle builds skip retention. Updated tests cover bottle-installation conditions and compatibility-version handling.

Changes: Dependency retention

Layer / File(s) Summary
Dependency retention and re-expansion
Library/Homebrew/formula_installer.rb, Library/Homebrew/test/formula_installer_spec.rb
The expansion method applies retention to build and runtime dependencies, subject to bottle-build and installed-runtime-dependency conditions. It records installed kegs’ runtime dependencies and excludes kept dependencies when those runtime dependencies require upgrades. Tests cover bottle metadata, dependency caching and compatibility-version cases.

Priority: Normal

Merge Risk: Moderate · previous review 3aa27

A source build can keep a dependency installed without options it requires and omit the needed rebuild. Check those options before merging.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: retaining compatible outdated runtime dependencies.
Description check Passed The description directly explains the problem, implementation, scope, tests, and verification for keeping compatible outdated runtime dependencies.
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.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: 28f6ed6a-2587-44bf-bb67-0ac0e0caa6fa
Commits

Reviewing files that changed from the base of the PR and between 3ef701b and 0f98717.

Files selected for processing: 2
  • Library/Homebrew/formula_installer.rb
  • Library/Homebrew/test/formula_installer_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.

Comment thread Library/Homebrew/formula_installer.rb Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: b8999f11-e85b-4ace-a0fd-2bc5bbc2282d
Commits

Reviewing files that changed from the base of the PR and between 0f98717 and 3aa27f5.

Files selected for processing: 2
  • Library/Homebrew/formula_installer.rb
  • Library/Homebrew/test/formula_installer_spec.rb

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Comment thread Library/Homebrew/formula_installer.rb Resolved
- Since Homebrew#24273, building from source keeps an outdated build
  dependency whose installed `compatibility_version` matches. Runtime
  dependencies are still always upgraded, so e.g. `brew install nmap`
  on Intel macOS rebuilds `sqlite` although the installed and current
  versions both have `compatibility_version 1`.
- Keep those too when their dependent is built from source, along
  with the dependencies they were built against. Upgrade them anyway
  if this install would incompatibly upgrade one of those.
- Pouring or building a bottle still upgrades them as before.
- `:no_linkage` still only keeps build dependencies whatever their
  `compatibility_version`.
- `Build` expands each runtime dependency's current formula and fails
  in `fixopt` when one of the dependencies it finds isn't installed.
  Keeping a runtime dependency prunes its dependencies from the
  install plan, so any that its current formula gained since it was
  installed would be missing.
- Upgrade it instead if any of its current recursive runtime
  dependencies isn't installed. Build dependencies don't need this
  because `Build` doesn't expand their dependencies.
@HaraldNordgren
HaraldNordgren force-pushed the keep-compatible-runtime-dependencies branch from 3aa27f5 to f40f6ae Compare October 29, 2026 15:45

@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@MikeMcQuaid
MikeMcQuaid added this pull request to the merge queue Oct 29, 2026
Merged via the queue into Homebrew:main with commit 9226bdf Oct 29, 2026
53 checks passed
@HaraldNordgren
HaraldNordgren deleted the keep-compatible-runtime-dependencies branch October 29, 2026 18:14
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.

2 participants