rules_swift_package_manager icon indicating copy to clipboard operation
rules_swift_package_manager copied to clipboard

Support depending on Bazel modules which also use rules_swift_package_manager

Open luispadron opened this issue 2 years ago • 12 comments

Use case

External repository

I have an external repository: External which is built using SPM. To support Bazel as well, the repository uses rules_swift_package_manager to generate BUILD files for its dependencies and its products. These dependencies are generated into the External repositories MODULE.bazel file using the gazelle plugin.

External has two dependencies: Foo and Bar.

Client repository

I have a repository: Client which is built using Bazel. I'd like to depend on External since it provides a functional MODULE.bazel.

Client has two dependencies: Foo (same as External) and External

I add a bazel_dep(name = "External") to Clients MODULE.bazel. I use Externals public targets via @External//:Target.

The version in External/Foo does not conflict with Client/Foo and is resolved correctly, ideally with as little duplication as possible.

Current issues

This currently fails to resolve at all with the following error:

Error in repository_rule: A repo named swiftpkg_{PACKAGE_NAME} is already generated by this module extension at /private/var/tmp/_bazel_{USER}/{HASH}/external/rules_swift_package_manager~0.21.0/swiftpkg/bzlmod/swift_deps.bzl:31:22
ERROR: error evaluating module extension swift_deps in @rules_swift_package_manager~0.21.0//:extensions.bzl. Type 'bazel help mod' for syntax and help.
 checking cached actions

Solution

TODO

luispadron avatar Nov 21 '23 19:11 luispadron

A current workaround: instead of using MODULE.bazel depend on this via Package.swift and use the gazelle plugin to generate MODULE.bazel use_repo delcartions.

luispadron avatar Nov 21 '23 19:11 luispadron

@cgrindel What are your thoughts on this issue and how to move it forward? Would the simple workaround of just suffixing the repo with the Bazel module name be enough? I imagine that would also break a lot of build files that depended on @swiftpkg

luispadron avatar Dec 04 '23 20:12 luispadron

I think that we need SPM to resolve the deps. So, I don't think prefixing the names will be enough. If we don't we could end up with duplicate symbol errors in Swift.

Perhaps, we can come up with a way for a Bazel module to declare itself and its direct deps to the root workspace and then have the root workspace generate a temporary Package.swift that is used for SPM resolution. However, this would ignore any Bazel-specific functionality that you might have in the Bazel module that you are providing as a Swift package. 🤔

In short, I don't have any good ideas on this, right now.

cgrindel avatar Dec 05 '23 13:12 cgrindel

@luispadron A couple of questions:

Is there a publicly available repository that we can reference as a real-world example?

Is the Package.swift for theExternal repository a minimal one (i.e., what rspm needs) or can it build the project? In other words, can a regular Swift package consume External?

cgrindel avatar Jan 02 '24 23:01 cgrindel

Interesting and possibly related conversations / issues:

  • https://github.com/bazelbuild/bazel/issues/19055

cgrindel avatar Jan 03 '24 00:01 cgrindel

To implement this, we would want to convert each Swift package to a Bazel module. Today, we generate repositories and build files which is close but not a complete module. If we went this route, we would need to figure out how the root module would load these generated, on-the-fly, Bazel modules.

I think that we would need to generate a Bazel module for every requested version for every Swift package. Then, Bazel's version selection logic would select the version to use. 🤔

cgrindel avatar Jan 17 '24 21:01 cgrindel

@cgrindel I like the generate Bazel modules idea and it works for folks who'd like to use SPM as the source of truth (because they primarily have downstream SPM users) but would like to also support Bazel (without maintaining two sources of truth). This allows Bazel users who are not using rules_swift_package_manager to use the module. It also would make adding Swift packages to the Bazel registry easier.

Some questions/thoughts on implementation:

  • It would need to be flexible enough to support custom Bazel rules and deps being added to the MODULE.bazel/workspace.
  • How would these generated Bazel modules be made, can that be done via an bzlmod extensions?

luispadron avatar Jan 17 '24 21:01 luispadron

Keith asked about generating modules. Answer: No. I mean generating them during the repository load. We could still generate them using a separate utility.

cgrindel avatar Jan 18 '24 19:01 cgrindel

How would these generated Bazel modules be made, can that be done via an bzlmod extensions?

Based upon the link that I just posted. No.

cgrindel avatar Jan 18 '24 19:01 cgrindel

Just an FYI that this issue was a blocker for me adopting rules_swift_package_manager.

ileitch avatar Aug 24 '24 16:08 ileitch

@ileitch Which Swift package do you use that is also a Bazel module?

cgrindel avatar Aug 24 '24 22:08 cgrindel

My aim was to add Bazel module support to https://github.com/peripheryapp/periphery, however a key place I tried to use it is a private iOS app already using rules_swift_package_manager. Essentially the same scenario described in the original issue.

ileitch avatar Aug 24 '24 23:08 ileitch