KEMBAR78
Implement `no_linkage` DSL to cover dependencies without linkage by Copilot · Pull Request #20807 · Homebrew/brew · GitHub
Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 2, 2025

Implementation of no_linkage DSL

Implements the no_linkage dependency tag to identify runtime dependencies without linkage. The agreed-upon syntax is depends_on "cryptography" => :no_linkage.

Changes Implemented:

  • ✅ Added :no_linkage to the RESERVED_TAGS in dependable.rb
  • ✅ Added no_linkage? method to Dependable module
  • ✅ Updated LinkageChecker#check_formula_deps to filter out :no_linkage dependencies
  • ✅ Updated LinkageChecker#display_normal_output to show no_linkage dependencies separately
  • ✅ Added detection for unexpected linkage on no_linkage dependencies (strict mode)
  • ✅ Added unit and integration tests for the new functionality
  • ✅ All typecheck, style, and tests pass

Behavior:

  • Dependencies marked with :no_linkage are treated as runtime dependencies
  • They are filtered out from "Dependencies with no linkage" warnings
  • They are shown separately as "Homebrew dependencies not requiring linkage"
  • If linkage is detected for a :no_linkage dependency, it is reported as "Unexpected linkage for no_linkage dependencies" and fails in strict mode

Example Usage:

class Awscli < Formula
  depends_on "cryptography" => :no_linkage
  depends_on "openssl@3"
end

Output Example:

╰─ brew linkage awscli
System libraries:
  /System/Library/Frameworks/Security.framework/Versions/A/Security
  /usr/lib/libSystem.B.dylib
Homebrew libraries:
  /opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib (openssl@3)
Homebrew dependencies not requiring linkage:
  cryptography

This feature helps maintainers ensure that all dependencies are used correctly, closing the loop on dependency auditing by explicitly marking runtime dependencies that don't require linkage.

Fixes #19697

Original prompt

This section details on the original issue you should resolve

<issue_title>Implement no_linkage DSL to cover dependencies without linkage</issue_title>
<issue_description>### Verification

Provide a detailed description of the proposed feature

We sometimes have formulae with runtime dependencies that do not have linkage. One example of this is awscli. For that specific formula, cryptography is required at runtime, but there is no linkage:

╰─ brew linkage awscli
System libraries:
  /System/Library/Frameworks/Security.framework/Versions/A/Security
  /usr/lib/libSystem.B.dylib
Homebrew libraries:
  /opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib (openssl@3)
Dependencies with no linkage:
  cryptography

Given how much work we've done on fixing indirect dependencies with linkage, I think it's time to look in the other direction. I'm envisioning something like:

depends_on "cryptography" => :no_linkage
╰─ brew linkage awscli
System libraries:
  /System/Library/Frameworks/Security.framework/Versions/A/Security
  /usr/lib/libSystem.B.dylib
Homebrew libraries:
  /opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib (openssl@3)
Homebrew dependencies not requiring linkage:
  cryptography

Naturally I'm proposing the concept here, rather than the exact wording and implementation. This would ensure that all dependencies that should be linked are, and that all dependencies that aren't linked are confirmed.

What is the motivation for the feature?

Tightening up our formulae, ensuring that every dependency declared is used correctly. We already are performing audits for indirect dependencies with linkage, so this would close the loop.

How will the feature be relevant to at least 90% of Homebrew users?

It wouldn't be. It would simply help us with maintaining formulae.

What alternatives to the feature have been considered?

Status quo</issue_description>

Comments on the Issue (you are @copilot in this section)

@MikeMcQuaid @p-linnane we previously had `:run` and `:linked` that we could resurrect; some code still exists for them. Would either of those names make sense? I think `:run` did exactly what you want here. @p-linnane So rather than declaring that a dependency won't have linkage, we'd use `:run` to indicate it's a runtime dep without linkage? I think that could work. It doesn't feel very clear to me from the name though, since there will be all the other runtime deps that do have linkage. That was why I was proposing `:no_linkage` since it's very explicit in what's expected. Do you think we could lift some of the remaining `:run` code into a `:no_linkage`? @MikeMcQuaid > That was why I was proposing `:no_linkage` since it's very explicit in what's expected. Do you think we could lift some of the remaining `:run` code into a `:no_linkage`?

I think most of the code is gone. If you hate the :run name, cool, no problem, it's mainly just that it's a case that's previously been used.

I wouldn't be opposed to no_linkage or unlinked or something more explicit (provided it failed if there actually was linkage).</comment_new>
<comment_new>@p-linnane
It's not that I hate :run, it's just that I don't think it accurately describes what we're checking or confirming in this situation. Yes, it is a runtime dep, but the linkage is the thing we're primarily concerned about, since linkage happens with most runtime deps. I also agree it should fail if there is linkage, so we can investigate just like we do with the indirect deps with linkage. I'll think on it over the weekend.</comment_new>
<comment_new>@MikeMcQuaid
@p-linnane Cool, that's fair, I'm game for no_linkage or unlinked then.</comment_new>
<comment_new>@MikeMcQuaid
@gromgit Good shout, thanks for your input. I'm 👍🏻 to no_linkage.</comment_new>
<comment_new>@p-linnane
Assigned this to Copilot to see what it comes up with.</comment_new>

Fixes #19697

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@p-linnane
Copy link
Member

@copilot Try again.

@Copilot
Copy link
Contributor Author

Copilot AI commented Oct 2, 2025

@copilot Try again.

The no_linkage DSL implementation is complete and working correctly. Here's what was implemented:

Core Changes:

  • Added :no_linkage to RESERVED_TAGS in dependable.rb
  • Added no_linkage? method to check for the tag
  • Updated LinkageChecker to handle no_linkage dependencies

Features:

  1. Dependencies can be declared with depends_on "cryptography" => :no_linkage
  2. These dependencies are displayed under "Homebrew dependencies not requiring linkage" instead of "Dependencies with no linkage"
  3. If a :no_linkage dependency has unexpected linkage, it's reported as "Unexpected linkage for no_linkage dependencies" and fails in strict mode

Verification:

  • All tests pass (dependable, dependency, linkage)
  • Typecheck passes
  • Manual testing confirms the DSL works as expected

The implementation follows the agreed-upon design from the issue discussion and addresses the use case for formulae like awscli with runtime dependencies that don't have linkage.

Demo output:

1. Creating a dependency with :no_linkage tag:
   Code: Dependency.new("cryptography", [:no_linkage])
   Result:
   - Name: cryptography
   - no_linkage?: true
   - required?: true

@Copilot Copilot AI changed the title [WIP] Implement no_linkage DSL to cover dependencies without linkage Implement no_linkage DSL to cover dependencies without linkage Oct 2, 2025
@Copilot Copilot AI requested a review from p-linnane October 2, 2025 19:46
Copilot finished work on behalf of p-linnane October 2, 2025 19:46
Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com>
@MikeMcQuaid MikeMcQuaid force-pushed the copilot/fix-b4e0e263-3213-4acf-b48c-bb81fc3d5632 branch from be9ce7b to 0e8e680 Compare October 6, 2025 16:31
@MikeMcQuaid MikeMcQuaid marked this pull request as ready for review October 6, 2025 16:32
@MikeMcQuaid MikeMcQuaid enabled auto-merge October 6, 2025 16:32
@MikeMcQuaid MikeMcQuaid added this pull request to the merge queue Oct 6, 2025
Merged via the queue into main with commit d4815b2 Oct 6, 2025
38 checks passed
@MikeMcQuaid MikeMcQuaid deleted the copilot/fix-b4e0e263-3213-4acf-b48c-bb81fc3d5632 branch October 6, 2025 18:52
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.

Implement no_linkage DSL to cover dependencies without linkage

3 participants