This repository contains a Gazelle plugin and Bazel repository rules that can be used to download, build, and consume Swift packages. The rules in this repository build the external Swift packages using rules_swift 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.
MODULE.bazel
to use rules_swift_package_manager.Package.swift
file.swift package update
bazel mod tidy
.BUILD.bazel
at the root of your workspace.Package.swift
, Package.resolved
, and MODULE.bazel
.Be sure to install Xcode.
You will need to install Swift. Make sure
that running swift --version
works properly.
Don't forget that rules_swift
expects the use of
clang
. 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.
cat >>local.bazelrc <<EOF
build --action_env=PATH
EOF
This approach is necessary to successfully execute the examples on an Ubuntu runner using Github actions. See the CI GitHub workflow for more details.
The following provides a quick introduction on how to set up and use the features in this repository. These instructions assume that you are using Bazel modules to load your external dependencies. If you are using Bazel's legacy external dependency management, please review the legacy quickstart, instead.
Also, check out the examples for more information.
This repository supports bzlmod. While you can use this ruleset with [legacy WORKSPACE
dependencies], some of the automation will not be available in this mode. If you are starting a new
project, it is highly recommended to use bzlmod. To enable bzlmod, add the following to your
.bazelrc
.
common --enable_bzlmod
MODULE.bazel
to use rules_swift_package_manager.Add a dependency on rules_swift_package_manager
.
bazel_dep(name = "rules_swift_package_manager", version = "0.34.1")
In addition, add the following to load the external dependencies described in your Package.swift
and Package.resolved
files.
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 Gazelle and rules_swift
. Follow
the links below to get the latest bzlmod snippets to insert into your MODULE.bazel
.
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.
Package.swift
file.Create a minimal Package.swift
file that only contains the external dependencies that are directly
used by your Bazel workspace.
// swift-tools-version: 5.7
import 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, at this time.
swift package update
This will invoke Swift Package Manager and resolve all dependencies resulting in creation of Package.resolved file.
bazel mod tidy
.This will update your MODULE.bazel
with the correct use_repo
declaration.
BUILD.bazel
at the root of your workspace.Add the following to the BUILD.bazel
file at the root of your workspace.
load("@gazelle//:def.bzl", "gazelle", "gazelle_binary")
# Ignore the `.build` folder that is created by running Swift package manager
# commands. Be sure to configure your source control to ignore it, as well.
# (i.e., add it to your `.gitignore`).
# NOTE: Swift package manager is not used to build any of the external packages.
# gazelle:exclude .build
# This declaration builds a Gazelle binary that incorporates all of the Gazelle
# plugins for the languages that you use in your workspace. In this example, we
# are only listing the Gazelle plugin for Swift from rules_swift_package_manager.
gazelle_binary(
name = "gazelle_bin",
languages = [
"@rules_swift_package_manager//gazelle",
],
)
# This target updates the Bazel build files for your project. Run this target
# whenever you add or remove source files from your project. The
# `swift_deps_info` repository is generated by `rules_swift_package_manager`. It
# creates a target, `@swift_deps_info//:swift_deps_index`, that generates a JSON
# file which maps Swift module names to their respective Bazel target.
gazelle(
name = "update_build_files",
data = [
"@swift_deps_info//:swift_deps_index",
],
extra_args = [
"-swift_dependency_index=$(location @swift_deps_info//:swift_deps_index)",
],
gazelle = ":gazelle_bin",
)
Generate/update the Bazel build files for your project by running the following:
bazel run //:update_build_files
Build and test your project.
bazel test //...
Package.swift
, Package.resolved
, and MODULE.bazel
.Package.swift
file is used by rules_swift_package_manager
to generate information about
your project's dependencies.Package.resolved
file specifies that exact versions of the downloaded dependencies that were
identified.MODULE.bazel
contains the declarations for your external dependencies.You are ready to start coding.
The following are a few tips to consider as you work with your repository:
bazel run //:update_build_files
. This will
create/update the Bazel build files in your project. It is designed to be fast and unobtrusive.bazel run //:update_build_files
//:tidy
) that runs your repository
maintenance targets (e.g., //:update_build_files
, formatting utilities)
in the proper order. If you are looking for an easy way to set this up, check out the
//:tidy
declaration in this repository and the documentation for the tidy macro.