Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: prepare for initial release #130

Merged
merged 7 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Gazelle Plugin for Swift and Swit Package Rules for Bazel

[![Build](https://github.com/cgrindel/swift_bazel/actions/workflows/ci.yml/badge.svg?event=schedule)](https://github.com/cgrindel/swift_bazel/actions/workflows/ci.yml)

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
Expand Down Expand Up @@ -179,16 +181,18 @@ Add the following to the `BUILD.bazel` file at the root of your workspace.
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")

# Ignore the `.build` folder that is created by running Swift package manager
# commands. The Swift Gazelle plugin executes some Swift package manager commands to resolve
# external dependencies. This results in a `.build` file being created.
# NOTE: Swift package manager is not used to build any of the external packages. The `.build`
# directory should be ignored. Be sure to configure your source control to ignore it (i.e., add it
# to your `.gitignore`).
# commands. The Swift Gazelle plugin executes some Swift package manager
# commands to resolve external dependencies. This results in a `.build` file
# being created.
# NOTE: Swift package manager is not used to build any of the external packages.
# The `.build` directory should be ignored. Be sure to configure your source
# control to ignore it (i.e., add it to your `.gitignore`).
# 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 using the Gazelle plugin for
# Starlark from bazel_skylib and the Gazelle plugin for Swift from cgrindel_swift_bazel.
# 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 using the Gazelle plugin for Starlark from bazel_skylib and the Gazelle
# plugin for Swift from cgrindel_swift_bazel.
gazelle_binary(
name = "gazelle_bin",
languages = [
Expand All @@ -197,9 +201,10 @@ gazelle_binary(
],
)

# This target should be run whenever the list of external dependencies is updated in the
# `Package.swift`. Running this target will populate the `swift_deps.bzl` with `swift_package`
# declarations for all of the direct and transitive Swift packages that your project uses.
# This target should be run whenever the list of external dependencies is
# updated in the `Package.swift`. Running this target will populate the
# `swift_deps.bzl` with `swift_package` declarations for all of the direct and
# transitive Swift packages that your project uses.
gazelle(
name = "swift_update_repos",
args = [
Expand All @@ -211,8 +216,8 @@ gazelle(
gazelle = ":gazelle_bin",
)

# This target updates the Bazel build files for your project. Run this target whenever you add or
# remove source files from your project.
# This target updates the Bazel build files for your project. Run this target
# whenever you add or remove source files from your project.
gazelle(
name = "update_build_files",
gazelle = ":gazelle_bin",
Expand Down
10 changes: 5 additions & 5 deletions docs/design/high-level.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ by the Swift Bazel repository.

The implementation in this repository is separated into two parts:

1. A [Gazelle](https://github.com/bazelbuild/bazel-gazelle) plugin
2. Bazel repository rules: `swift_package` and `local_swift_package`
1. A [Gazelle](https://github.com/bazelbuild/bazel-gazelle) plugin.
2. Bazel repository rules: `swift_package` and `local_swift_package`.

The Gazelle plugin generates Bazel build and Starlark files for your project. The `swift_package`
repository rule generates Bazel build files for the external Swift packages.
Expand All @@ -35,14 +35,14 @@ operation: `update-repos` and `update`.

The `update-repos` mode

1. Resolves the direct and transitive dependencies for the project using the `Package.swift`.
1. Resolves the direct and transitive dependencies for the project using a `Package.swift` file.
2. Writes a `Package.resolved` file.
3. Writes a `module_index.json` file.
3. Writes a `swift_deps_index.json` file.
2. Writes `swift_package` declarations for the direct and transitive dependencies.

The `update` mode

1. Reads the `module_index.json` file.
1. Reads the `swift_deps_index.json` file.
2. Inspects the project looking for Swift source files.
3. Identifies the Bazel packages that should contain Swift declarations.
4. Writes the Swift declarations to Bazel build files.
Expand Down
51 changes: 39 additions & 12 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
* [Is the same build file generation logic used for the Go/Gazelle and Starlark implementations?](#is-the-same-build-file-generation-logic-used-for-the-gogazelle-and-starlark-implementations)
* [Does this replace rules\_spm ?](https://github.com/cgrindel/rules_spm/)
* [Can I migrate from rules\_spm to swift\_bazel ?](https://github.com/cgrindel/rules_spm/)
* [Can I just manage my external Swift packages and not generate Bazel build files for my project?](#can-i-just-manage-my-external-swift-packages-and-not-generate-bazel-build-files-for-my-project)
* [After running //:swift\_update\_repos , I see a \.build directory\. What is it? Do I need it?](#after-running-swift_update_repos-i-see-a-build-directory-what-is-it-do-i-need-it)
* [Does the Gazelle plugin run Swift package manager with every execution?](#does-the-gazelle-plugin-run-swift-package-manager-with-every-execution)
<!-- MARKDOWN TOC: END -->

## Why use Gazelle and Go?

The [Gazelle framework](https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md) 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.
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](https://github.com/bazelbuild/bazel-gazelle#supported-languages).
Expand All @@ -27,12 +29,11 @@ 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](https://bazel.build/run/build#loading). 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.
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.

### How does the Gazelle plugin for Go handle this?

Expand All @@ -46,19 +47,45 @@ placement and content of the Bazel build files. The repository rules leverage in
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](https://github.com/cgrindel/rules_spm/)?
## Does this replace [rules_spm]?

Yes. There are some [limitations with the rules_spm
implementation](https://github.com/cgrindel/rules_spm/discussions/157). 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](https://github.com/bazelbuild/rules_swift).
- Build the external dependencies with [rules_swift].
- Pin the exact versions for the direct and transitive dependencies.

## Can I migrate from [rules_spm](https://github.com/cgrindel/rules_spm/) to `swift_bazel`?
## Can I migrate from [rules_spm] to `swift_bazel`?

Absolutely. A [migration guide from rules_spm](https://github.com/cgrindel/swift_bazel/issues/99) is
on the roadmap.

## Can I just manage my external Swift packages and not generate Bazel build files for my project?

Yes. Just omit the `//:update_build_files` target that is mentioned in the [quickstart].

## After running `//:swift_update_repos`, I see a `.build` directory. What is it? Do I need it?

The `//:swift_update_repos` 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.

## Does the Gazelle plugin run Swift package manager with every execution?

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.


[loading phase]: https://bazel.build/run/build#loading
[quickstart]: https://github.com/cgrindel/swift_bazel/blob/main/README.md#quickstart
[rules_spm]: https://github.com/cgrindel/rules_spm/
[rules_swift]: https://github.com/bazelbuild/rules_swift
[Gazelle framework]: https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md