How to Use External Swift Packages in Bazel
NOTE: This article is about using
rules_spm to leverage Swift packages in Bazel. The
rules_spm project is being sunset. It has been superseded by swift_bazel. I have written a blog post on how to get started.
If you build Swift software in Bazel, you probably use the excellent rules_swift rules to develop modules and executables for your project. While working on your project, you almost certainly have wanted to import one of the many third-party Swift packages that exist. Unfortunately,
rules_swift does not provide a means to integrate these packages into your project quickly. So, I created rules_spm to address this very issue.
Table of Contents
rules_spm project contains Bazel rules and macros that allow a project to depend upon external Swift packages. It provides a means to declare dependent packages, much like Swift Package Manager (SPM). Under the covers, it downloads the external packages, builds them using SPM, and makes the artifacts available as Bazel binary targets for execution or Bazel library targets suitable for consumption by
A Simple Example
1. Download and Configure
First, we need to add
rules_spm to the
WORKSPACE file. The following code downloads the rules and configures them.
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "cgrindel_rules_spm", sha256 = "fab28a41793744f3944ad2606cdd9c0f8e2f4861dd29fb1d61aa4263c7a1400a", strip_prefix = "rules_spm-0.6.0", urls = ["https://github.com/cgrindel/rules_spm/archive/v0.6.0.tar.gz"], ) load( "@cgrindel_rules_spm//spm:deps.bzl", "spm_rules_dependencies", ) spm_rules_dependencies() load( "@build_bazel_rules_swift//swift:repositories.bzl", "swift_rules_dependencies", ) swift_rules_dependencies() load( "@build_bazel_rules_swift//swift:extras.bzl", "swift_rules_extra_dependencies", ) swift_rules_extra_dependencies()
rules_spm rules use
rules_swift under the covers. If your project requires a specific version of
rules_spm, add the appropriate
rules_swift declarations before running
2. Declare the Dependent Swift Packages
Next, we need to declare the Swift packages that we want to use in our project. We do that by adding a spm_repositories collection to the
WORKSPACE file. Then, we add an spm_pkg entry for each of the Swift packages that we want to import. Much like the SPM package dependency syntax,
spm_pkg accepts a URL, a minimum version, and, optionally, a name. The one additional piece of information required is the list of product names that our project will use.
load("@cgrindel_rules_spm//spm:spm.bzl", "spm_pkg", "spm_repositories") spm_repositories( name = "swift_pkgs", dependencies = [ spm_pkg( "https://github.com/apple/swift-log.git", from_version = "1.0.0", products = ["Logging"], ), ], )
3. Import the Logging module in the Swift Binary
Now, it’s time to use the
Logging module in the project’s Swift code. Add a dependency to the
swift_binary declaration in the BUILD file.
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_binary") swift_binary( name = "simple", srcs = ["main.swift"], visibility = ["//swift:__subpackages__"], deps = [ "@swift_pkgs//swift-log:Logging", ], )
The format for the dependency target is
collection-name is the name that you provide to the
spm_repositories declaration. The
swift-package-name is the name of the Swift package. Finally, the
SwiftModuleName is the name of the Swift module.
NOTE: The Swift package name is defined in the package’s
Package.swift. While the package name is often identical to the repository name. There are occasions when they are different.
Finally, import the module and use it in the Swift code.
import Logging let logger = Logger(label: "com.example.main") logger.info("Hello World!")