- Why use Gazelle and Go?
- Why split the implementation between Go and Starlark?
- Is the same build file generation logic used for the Go/Gazelle and Starlark implementations?
- Does this replace rules_spm?
- Can I migrate from rules_spm to
rules_swift_package_manager
? - Can I just manage my external Swift packages and not generate Bazel build files for my project?
- After running
//:swift_update_pkgs
, I see a.build
directory. What is it? Do I need it? - Does the Gazelle plugin run Swift package manager with every execution?
- Can I store the Swift dependency files in a sub-package (i.e., not in the root of the workspace)?
- My project builds successfully with
bazel build ...
, but it does not build when usingrules_xcodeproj
. How can I fix this?
The Gazelle framework provides lots of great features for generating Bazel build and Starlark files. Right now, the best way to leverage the framework is to write the plugin in Go.
In addition, adoption of the Gazelle ecosystem has started to take off. There are lots of useful plugins for other languages. Letting Gazelle generate and maintain Bazel build files is a real game changer for developer productivity.
As mentioned previously, the easiest way to implement a Gazelle plugin is to write it in Go. This works great for generating build files in the primary workspace. However, there is a chicken-and-egg problem when it comes time to generate build files in a repository rule. The repository rule needs to generate files during the loading phase. The Go toolchain and the Gazelle framework defined in the workspace are not available to the repository rule during this phase. So, one needs to either perform some gymnastics to build the Gazelle plugin (see below) or use a language/runtime that is guaranteed to be available during the loading phase. Since Starlark is available during the loading phase, the build file generation logic for the repository rules is implemented in Starlark.
In short, they assume that if you are using the Gazelle plugin for Go, then you must have a Go toolchain installed on the host system. In essence, they shell out and run Go from the system.
No. The Gazelle plugin inspects the Swift source files and the directory structure to determine the
placement and content of the Bazel build files. The repository rules leverage information about the
Swift packages (e.g., dump and describe JSON). However, both implementations use the
module_index.json
to resolve module references to Bazel targets for the external dependencies.
Does this replace rules_spm?
Yes. There are some limitations with the rules_spm implementation. After receiving feedback and suggestions from the community, we opted to create a clean sheet implementation which includes new features and improvements:
- Bazel build file generation for the primary workspace.
- Build the external dependencies with rules_swift.
- Pin the exact versions for the direct and transitive dependencies.
Can I migrate from rules_spm to rules_swift_package_manager
?
Absolutely. A migration guide from rules_spm is on the roadmap.
Yes. Just omit the //:update_build_files
target that is mentioned in the quickstart.
The //:swift_update_pkgs
target runs the Gazelle plugin in update-repos
mode. This mode
resolves the external dependencies listed in your Package.swift
by running Swift package manager
commands. These commands result in a .build
directory being created. The directory is a side
effect of running the Swift package manager commands. It can be ignored and should not be checked
into source control. It is not used by the Gazelle plugin or the Starlark repository rules.
No. The Gazelle plugin only executes the Swift package manager when run in update-repos
mode. This
mode only needs to be run when modifying your external dependencies (e.g., add/remove a dependency,
update the version selection for a dependency). The update
mode for the Gazelle plugin generates
Bazel build files for your project. It uses information written to the swift_deps_index.json
and
the source files that exist in your project to generate the Bazel build files.
Yes. The vapor example demonstrates storing the Swift dependency files in a sub-package called
swift
.
My project builds successfully with bazel build ...
, but it does not build when using rules_xcodeproj
. How can I fix this?
tl;dr Add the following to your .bazelrc
.
# Ensure that sandboxed is added to the spawn strategy list when building with
# rules_xcodeproj.
build:rules_xcodeproj --spawn_strategy=remote,worker,sandboxed,local
Alternatively, you can use the --strategy_regexp flag to target the relevant targets. For
instance, if Sources/BranchSDK/BNCContentDiscoveryManager.m
is not building properly, you can
specify --strategy_regexp="Compiling Sources/BranchSDK/.*=sandboxed"
to use the sandboxed
strategy
for that file. The regular expression matches on the description for the action.
This can happen with some Swift packages (e.g. firebase-ios-sdk
). rules_xcodeproj removes the
sandboxed
spawn
strategy
in their default build configuration due to slow performance of the MacOS sandbox. The above bazelrc
stanza adds it back. An issue
exists tracking the work to allow these Swift packages to be built using the local
spawn strategy.