https://github.com/cgrindel/rules_swift_package_manager
Collection of utilities and Bazel rules to aid in the development and maintenance of Swift repositories using Bazel.
https://github.com/cgrindel/rules_swift_package_manager
bazel bazel-rules swift swift-package-manager
Last synced: 3 months ago
JSON representation
Collection of utilities and Bazel rules to aid in the development and maintenance of Swift repositories using Bazel.
- Host: GitHub
- URL: https://github.com/cgrindel/rules_swift_package_manager
- Owner: cgrindel
- License: apache-2.0
- Created: 2022-11-09T18:43:35.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-03-25T13:44:16.000Z (4 months ago)
- Last Synced: 2025-03-25T14:23:05.324Z (4 months ago)
- Topics: bazel, bazel-rules, swift, swift-package-manager
- Language: Starlark
- Homepage:
- Size: 5.72 MB
- Stars: 90
- Watchers: 4
- Forks: 35
- Open Issues: 103
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# Swift Package Manager Rules for Bazel
[](https://github.com/cgrindel/rules_swift_package_manager/actions/workflows/ci.yml)
This repository contains a Bazel ruleset that can be used to download, build, and consume Swift
packages. The rules in this repository build the external Swift packages using [rules_swift],
[rules_apple] and native C/C++ rulesets making the Swift package products and targets available as
Bazel targets.This repository is designed to fully replace [rules_spm] and provide utilities to ease Swift
development inside a Bazel workspace.## Table of Contents
* [Documentation](#documentation)
* [Prerequisites](#prerequisites)
* [Mac OS](#mac-os)
* [Linux](#linux)
* [Quickstart](#quickstart)
* [1. Enable bzlmod](#1-enable-bzlmod)
* [2. Configure your `MODULE.bazel` to use rules_swift_package_manager.](#2-configure-your-modulebazel-to-use-rules_swift_package_manager)
* [(Optional) Use `swift_package` repository for updating packages](#optional-use-swift_package-repository-for-updating-packages)
* [(Optional) Enable `swift_deps_info` generation for the Gazelle plugin](#optional-enable-swift_deps_info-generation-for-the-gazelle-plugin)
* [3. Create a minimal `Package.swift` file.](#3-create-a-minimal-packageswift-file)
* [4. Run `swift package update`](#4-run-swift-package-update)
* [5. Run `bazel mod tidy`.](#5-run-bazel-mod-tidy)
* [6. Build and test your project.](#6-build-and-test-your-project)
* [7. Check in `Package.swift`, `Package.resolved`, and `MODULE.bazel`.](#7-check-in-packageswift-packageresolved-and-modulebazel)
* [8. Start coding](#8-start-coding)
* [Using a Swift package registry](#using-a-swift-package-registry)
* [Tips and Tricks](#tips-and-tricks)## Documentation
- [Rules and API documentation](/docs/README.md)
- [High-level design](/docs/design/high-level.md)
- [Frequently Asked Questions](/docs/faq.md)## Prerequisites
### Mac OS
Be sure to install Xcode.
### Linux
You will need to [install Swift](https://swift.org/getting-started/#installing-swift). Make sure
that running `swift --version` works properly.Don't forget that `rules_swift` [expects the use of
`clang`](https://github.com/bazelbuild/rules_swift#3-additional-configuration-linux-only). Hence,
you will need to specify `CC=clang` before running Bazel.Finally, help [rules_swift] and [rules_swift_package_manager] find the Swift toolchain by ensuring
that a `PATH` that includes the Swift binary is available in the Bazel actions.```sh
cat >>local.bazelrc <
```python
bazel_dep(name = "rules_swift_package_manager", version = "1.0.0-rc1")
```In addition, add the following to load the external dependencies described in your `Package.swift`
and `Package.resolved` files.```bazel
swift_deps = use_extension(
"@rules_swift_package_manager//:extensions.bzl",
"swift_deps",
)
swift_deps.from_package(
resolved = "//:Package.resolved",
swift = "//:Package.swift",
)
use_repo(
swift_deps,
"swift_deps_info", # This is generated by the ruleset.
# The name of the Swift package repositories will be added to this declaration in step 4 after
# running `bazel mod tidy`.
# NOTE: The name of the Bazel external repository for a Swift package is `swiftpkg_xxx` where
# `xxx` is the Swift package identity, lowercase, with punctuation replaced by `hyphen`. For
# example, the repository name for apple/swift-nio is `swiftpkg_swift_nio`.
)
```You will also need to add a dependency on [rules_swift].
NOTE: Some Swift package manager features (e.g., resources) use rules from [rules_apple]. It is a
dependency for `rules_swift_package_manager`. However, you do not need to declare it unless you use
any of the rules in your project.#### (Optional) Use `swift_package` repository for updating packages
The `swift_deps` module extension will by default generate a `swift_package` repository which can be used to execute `swift package` commands.
This is useful if you'd like to control the flags and behavior of `swift package`, as well as for using the correct `swift` binary according to the Bazel configured toolchain.For example, to resolve the `Package.swift` file:
```sh
bazel run @swift_package//:resolve
```To update packages to their latest supported version:
```sh
bazel run @swift_package//:update
```Both targets support passing arguments as well, so for example, you could update a single package:
```sh
bazel run @swift_package//:update -- MyPackage
```These targets will update the `Package.resolved` file defined in `swift_deps.from_package`.
The targets come with default flags applied to enable the best Bazel compatibility, if you wish to configure it further, you can do so with `configure_swift_package`:```starlark
# MODULE.bazelswift_deps.configure_swift_package(
build_path = "spm-build",
cache_path = "spm-cache",
dependency_caching = "false",
manifest_cache = "none",
manifest_caching = "false",
)
```If you do not want to use the `swift_package` repository you can disable it in the `swift_deps.from_package` call:
```starlark
swift_deps.from_package(
declare_swift_package = False, # <=== Disable the `swift_package` repository
resolved = "//:Package.resolved",
swift = "//:Package.swift",
)
```#### (Optional) Enable `swift_deps_info` generation for the Gazelle plugin
If you will be using the [Gazelle plugin for Swift], you will need to enable the generation of
the `swift_deps_info` repository by enabling `declare_swift_deps_info`.```bazel
swift_deps.from_package(
declare_swift_deps_info = True, # <=== Enable swift_deps_info generation for the Gazelle plugin
resolved = "//:Package.resolved",
swift = "//:Package.swift",
)
```### 3. Create a minimal `Package.swift` file.
Create a minimal `Package.swift` file that only contains the external dependencies that are directly
used by your Bazel workspace.```swift
// swift-tools-version: 5.7import PackageDescription
let package = Package(
name: "my-project",
dependencies: [
// Replace these entries with your dependencies.
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.0"),
.package(url: "https://github.com/apple/swift-log", from: "1.4.4"),
]
)
```The name of the package can be whatever you like. It is required for the manifest, but it is not
used by [rules_swift_package_manager]. If your project is published and consumed as a Swift package,
feel free to populate the rest of the manifest so that your package works properly by Swift package
manager. Just note that the [Swift Gazelle plugin] does not use the manifest to generate Bazel build
files.### 4. Run `swift package update`
This will invoke Swift Package Manager and resolve all dependencies resulting in creation of
`Package.resolved` file.### 5. Run `bazel mod tidy`.
This will update your `MODULE.bazel` with the correct `use_repo` declaration.
### 6. Build and test your project.
Build and test your project.
```sh
bazel test //...
```### 7. Check in `Package.swift`, `Package.resolved`, and `MODULE.bazel`.
- The `Package.swift` file is used by `rules_swift_package_manager` to generate information about
your project's dependencies.
- The `Package.resolved` file specifies that exact versions of the downloaded dependencies that were
identified.
- The `MODULE.bazel` contains the declarations for your external dependencies.### 8. Start coding
You are ready to start coding.
## Using a Swift package registry
See [our document on using a Swift package registry](/docs/swift_package_registry.md).
## Tips and Tricks
The following are a few tips to consider as you work with your repository:
- Are you trying to use a Swift package and it just won't build under Bazel? If you can figure out
how to fix it, you can patch the Swift package. Check out [our document on patching Swift packages].[Bazel modules]: https://bazel.build/external/module
[Bazel's hybrid mode]: https://bazel.build/external/migration#hybrid-mode
[bzlmod]: https://bazel.build/external/overview#bzlmod
[our document on patching Swift packages]: docs/patch_swift_package.md
[CI GitHub workflow]: .github/workflows/ci.yml
[Gazelle plugin]: https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md
[Gazelle]: https://github.com/bazelbuild/bazel-gazelle
[Gazelle plugin for Swift]: https://github.com/cgrindel/swift_gazelle_plugin
[Swift Gazelle plugin]: https://github.com/cgrindel/swift_gazelle_plugin
[examples]: examples/
[rules_apple]: https://github.com/bazelbuild/rules_apple
[rules_spm]: https://github.com/cgrindel/rules_spm
[rules_swift]: https://github.com/bazelbuild/rules_swift
[rules_swift_package_manager]: https://github.com/cgrindel/rules_swift_package_manager
[tidy]: https://github.com/cgrindel/bazel-starlib/blob/main/doc/bzltidy/rules_and_macros_overview.md#tidy