Skip to content

Commit

Permalink
feat: implement swift_deps bzlmod extension (#290)
Browse files Browse the repository at this point in the history
- Disable Bazel 5.4.0 integration tests while adding support for bzlmod.
- Remove nogo target. Not used and was not compiling with bzlmod
enabled.
- Add `MODULE.bazel`.
- Add `swift_deps` bzlmod extension to support generating Swift packages
from info in `swift_deps_index.json`.
- Add `bazel_package_name` attribute to `local_swift_package` and
`swift_package`. It provides the unmolested Bazel repo name for the
Swift package. In bzlmod mode, the `repository_ctx.name` value is the
canonical repo name (i.e., includes the parent repo name).

Related to #276.
  • Loading branch information
cgrindel authored Mar 19, 2023
1 parent c3a6afb commit 12d0e9d
Show file tree
Hide file tree
Showing 20 changed files with 257 additions and 37 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@ jobs:
include:
- example: http_archive_ext_deps
bazel_version: .bazelversion
- example: http_archive_ext_deps
bazel_version: "5_4_0"
- example: pkg_manifest_minimal
bazel_version: .bazelversion
- example: pkg_manifest_minimal
bazel_version: "5_4_0"
- example: soto_example
bazel_version: .bazelversion
- example: vapor_example
Expand Down Expand Up @@ -88,12 +84,8 @@ jobs:
include:
- example: http_archive_ext_deps
bazel_version: .bazelversion
- example: http_archive_ext_deps
bazel_version: "5_4_0"
- example: pkg_manifest_minimal
bazel_version: .bazelversion
- example: pkg_manifest_minimal
bazel_version: "5_4_0"
- example: soto_example
bazel_version: .bazelversion
- example: vapor_example
Expand Down
19 changes: 8 additions & 11 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy")
load("@cgrindel_bazel_starlib//markdown:defs.bzl", "markdown_pkg")
load("@cgrindel_bazel_starlib//shlib/rules:execute_binary.bzl", "execute_binary")
load("@cgrindel_bazel_starlib//updatesrc:defs.bzl", "updatesrc_diff_and_update", "updatesrc_update_all")
load("@io_bazel_rules_go//go:def.bzl", "TOOLS_NOGO", "nogo")
load(
"@rules_bazel_integration_test//bazel_integration_test:defs.bzl",
"integration_test_utils",
Expand Down Expand Up @@ -61,16 +60,6 @@ tidy(
],
)

# MARK: - nogo Code Analysis

# https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst
nogo(
name = "nogo",
config = "nogo_config.json",
visibility = ["//visibility:public"],
deps = TOOLS_NOGO,
)

# MARK: - Gazelle

gazelle_binary(
Expand Down Expand Up @@ -154,6 +143,7 @@ filegroup(
srcs = [
".bazelrc",
"BUILD.bazel",
"MODULE.bazel",
"WORKSPACE",
"ci.bazelrc",
"shared.bazelrc",
Expand Down Expand Up @@ -231,6 +221,13 @@ updatesrc_diff_and_update(
],
)

bzl_library(
name = "extensions",
srcs = ["extensions.bzl"],
visibility = ["//visibility:public"],
deps = ["//swiftpkg/bzlmod:swift_deps"],
)

bzl_library(
name = "bazel_versions",
srcs = ["bazel_versions.bzl"],
Expand Down
79 changes: 79 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module(
name = "cgrindel_swift_bazel",
version = "0.0.0",
)

# MARK: - Runtime Dependencies

bazel_dep(name = "cgrindel_bazel_starlib", version = "0.14.9")
bazel_dep(name = "bazel_skylib", version = "1.4.1")
bazel_dep(
name = "rules_go",
version = "0.38.1",
repo_name = "io_bazel_rules_go",
)
bazel_dep(name = "rules_cc", version = "0.0.6")
bazel_dep(name = "platforms", version = "0.0.6")

# With bzlmod enabled, any dependencies for repositories generated by
# swift_bazel _must_ be a runtime dependency of swift_bazel.
bazel_dep(
name = "rules_swift",
version = "1.6.0",
repo_name = "build_bazel_rules_swift",
)
bazel_dep(
name = "rules_apple",
version = "2.1.0",
repo_name = "build_bazel_rules_apple",
)

# TODO(chuck): FIX ME! Gazelle needs a new release to get the following fix:
# https://github.com/bazelbuild/bazel-gazelle/pull/1413
bazel_dep(
name = "gazelle",
version = "0.29.0",
repo_name = "bazel_gazelle",
)

go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
use_repo(
go_sdk,
go_sdk = "go_default_sdk",
)

go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
"com_github_bazelbuild_buildtools",
"com_github_creasty_defaults",
"com_github_deckarep_golang_set_v2",
"com_github_stretchr_testify",
"in_gopkg_yaml_v3",
"org_golang_x_exp",
"org_golang_x_tools",
)

# MARK: - Dev Dependencies

bazel_dep(
name = "rules_bazel_integration_test",
version = "0.11.1",
dev_dependency = True,
)
bazel_dep(
name = "bazel_skylib_gazelle_plugin",
version = "1.4.1",
dev_dependency = True,
)

bazel_binaries = use_extension(
"@rules_bazel_integration_test//:extensions.bzl",
"bazel_binaries",
)
bazel_binaries.download(version_file = "//:.bazelversion")
use_repo(
bazel_binaries,
"build_bazel_bazel_.bazelversion",
)
2 changes: 2 additions & 0 deletions WORKSPACE.bzlmod
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Intentionally blank
# This exists to force Bazel in bzlmod mode to be strict.
1 change: 0 additions & 1 deletion bazel_versions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ CURRENT_BAZEL_VERSION = "//:.bazelversion"

SUPPORTED_BAZEL_VERSIONS = [
CURRENT_BAZEL_VERSION,
"5.4.0",
]
10 changes: 6 additions & 4 deletions docs/repository_rules_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ On this page:
## local_swift_package

<pre>
local_swift_package(<a href="#local_swift_package-name">name</a>, <a href="#local_swift_package-dependencies_index">dependencies_index</a>, <a href="#local_swift_package-env">env</a>, <a href="#local_swift_package-path">path</a>, <a href="#local_swift_package-repo_mapping">repo_mapping</a>)
local_swift_package(<a href="#local_swift_package-name">name</a>, <a href="#local_swift_package-bazel_package_name">bazel_package_name</a>, <a href="#local_swift_package-dependencies_index">dependencies_index</a>, <a href="#local_swift_package-env">env</a>, <a href="#local_swift_package-path">path</a>, <a href="#local_swift_package-repo_mapping">repo_mapping</a>)
</pre>

Used to build a local Swift package.
Expand All @@ -28,6 +28,7 @@ Used to build a local Swift package.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="local_swift_package-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="local_swift_package-bazel_package_name"></a>bazel_package_name | The short name for the Swift package's Bazel repository. | String | optional | <code>""</code> |
| <a id="local_swift_package-dependencies_index"></a>dependencies_index | A JSON file that contains a mapping of Swift products and Swift modules. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
| <a id="local_swift_package-env"></a>env | Environment variables that will be passed to the execution environments for this repository rule. (e.g. SPM version check, SPM dependency resolution, SPM package description generation) | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{}</code> |
| <a id="local_swift_package-path"></a>path | The path to the local Swift package directory. | String | required | |
Expand All @@ -39,9 +40,9 @@ Used to build a local Swift package.
## swift_package

<pre>
swift_package(<a href="#swift_package-name">name</a>, <a href="#swift_package-branch">branch</a>, <a href="#swift_package-commit">commit</a>, <a href="#swift_package-dependencies_index">dependencies_index</a>, <a href="#swift_package-env">env</a>, <a href="#swift_package-init_submodules">init_submodules</a>, <a href="#swift_package-patch_args">patch_args</a>,
<a href="#swift_package-patch_cmds">patch_cmds</a>, <a href="#swift_package-patch_cmds_win">patch_cmds_win</a>, <a href="#swift_package-patch_tool">patch_tool</a>, <a href="#swift_package-patches">patches</a>, <a href="#swift_package-recursive_init_submodules">recursive_init_submodules</a>, <a href="#swift_package-remote">remote</a>,
<a href="#swift_package-repo_mapping">repo_mapping</a>, <a href="#swift_package-shallow_since">shallow_since</a>, <a href="#swift_package-tag">tag</a>, <a href="#swift_package-verbose">verbose</a>)
swift_package(<a href="#swift_package-name">name</a>, <a href="#swift_package-bazel_package_name">bazel_package_name</a>, <a href="#swift_package-branch">branch</a>, <a href="#swift_package-commit">commit</a>, <a href="#swift_package-dependencies_index">dependencies_index</a>, <a href="#swift_package-env">env</a>, <a href="#swift_package-init_submodules">init_submodules</a>,
<a href="#swift_package-patch_args">patch_args</a>, <a href="#swift_package-patch_cmds">patch_cmds</a>, <a href="#swift_package-patch_cmds_win">patch_cmds_win</a>, <a href="#swift_package-patch_tool">patch_tool</a>, <a href="#swift_package-patches">patches</a>, <a href="#swift_package-recursive_init_submodules">recursive_init_submodules</a>,
<a href="#swift_package-remote">remote</a>, <a href="#swift_package-repo_mapping">repo_mapping</a>, <a href="#swift_package-shallow_since">shallow_since</a>, <a href="#swift_package-tag">tag</a>, <a href="#swift_package-verbose">verbose</a>)
</pre>

Used to download and build an external Swift package.
Expand All @@ -53,6 +54,7 @@ Used to download and build an external Swift package.
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="swift_package-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="swift_package-bazel_package_name"></a>bazel_package_name | The short name for the Swift package's Bazel repository. | String | optional | <code>""</code> |
| <a id="swift_package-branch"></a>branch | branch in the remote repository to checked out. Precisely one of branch, tag, or commit must be specified. | String | optional | <code>""</code> |
| <a id="swift_package-commit"></a>commit | The commit or revision to download from version control. | String | required | |
| <a id="swift_package-dependencies_index"></a>dependencies_index | A JSON file that contains a mapping of Swift products and Swift modules. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
Expand Down
46 changes: 46 additions & 0 deletions examples/pkg_manifest_minimal/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
bazel_dep(
name = "cgrindel_swift_bazel",
version = "0.0.0",
)
local_path_override(
module_name = "cgrindel_swift_bazel",
path = "../..",
)

bazel_dep(name = "cgrindel_bazel_starlib", version = "0.14.9")
bazel_dep(name = "bazel_skylib", version = "1.4.1")
bazel_dep(
name = "rules_swift",
version = "1.6.0",
repo_name = "build_bazel_rules_swift",
)

bazel_dep(
name = "bazel_skylib_gazelle_plugin",
version = "1.4.1",
dev_dependency = True,
)
bazel_dep(
name = "gazelle",
version = "0.29.0",
dev_dependency = True,
repo_name = "bazel_gazelle",
)

swift_deps = use_extension(
"@cgrindel_swift_bazel//:extensions.bzl",
"swift_deps",
)
swift_deps.from_file(
deps_index = "//:swift_deps_index.json",
)
use_repo(
swift_deps,
"swiftpkg_my_local_package",
"swiftpkg_swift_argument_parser",
"swiftpkg_swift_log",
"swiftpkg_swiftformat",
)

# IDEA
# use_repo(swift_deps, "swift_deps")
2 changes: 2 additions & 0 deletions examples/pkg_manifest_minimal/WORKSPACE.bzlmod
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Intentionally blank
# This exists to force Bazel in bzlmod mode to be strict.
4 changes: 2 additions & 2 deletions examples/pkg_manifest_minimal/swift_deps_index.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"direct_dep_identities": [
"my_local_package",
"swift-argument-parser",
"swift-log",
"swiftformat",
"my_local_package"
"swiftformat"
],
"modules": [
{
Expand Down
5 changes: 5 additions & 0 deletions extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Bazel module extensions."""

load("//swiftpkg/bzlmod:swift_deps.bzl", _swift_deps = "swift_deps")

swift_deps = _swift_deps
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/cgrindel/swift_bazel

go 1.19
go 1.18

require (
github.com/bazelbuild/bazel-gazelle v0.29.0
Expand Down
5 changes: 5 additions & 0 deletions shared.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ build --incompatible_strict_action_env=true

# Test output information
test --test_output=errors --test_summary=detailed

# GH276: Enable bzlmod
# # Enable bzlmod
# common --enable_bzlmod
# build --@cgrindel_bazel_starlib//bzlmod:enabled
11 changes: 11 additions & 0 deletions swiftpkg/bzlmod/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@cgrindel_bazel_starlib//bzlformat:defs.bzl", "bzlformat_pkg")

bzlformat_pkg(name = "bzlformat")

bzl_library(
name = "swift_deps",
srcs = ["swift_deps.bzl"],
visibility = ["//visibility:public"],
deps = ["//swiftpkg/internal:deps_indexes"],
)
56 changes: 56 additions & 0 deletions swiftpkg/bzlmod/swift_deps.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Implementation for `swift_deps` bzlmod extension."""

load("//swiftpkg/internal:deps_indexes.bzl", "deps_indexes")
load("//swiftpkg/internal:local_swift_package.bzl", "local_swift_package")
load("//swiftpkg/internal:swift_package.bzl", "swift_package")

# MARK: - swift_deps bzlmod Extension

def _declare_pkg_from_package(package, deps_index_label):
if package.remote_pkg != None:
swift_package(
name = package.name,
bazel_package_name = package.name,
commit = package.remote_pkg.commit,
remote = package.remote_pkg.remote,
dependencies_index = deps_index_label,
)
elif package.local_pkg != None:
local_swift_package(
name = package.name,
bazel_package_name = package.name,
path = package.local_pkg.path,
dependencies_index = deps_index_label,
)
else:
fail("Found package '{}' without a remote or local.".format(
package.identity,
))

def _declare_pkgs_from_file(module_ctx, from_file):
index_json = module_ctx.read(from_file.deps_index)
deps_index = deps_indexes.new_from_json(index_json)
for package in deps_index.packages_by_id.values():
_declare_pkg_from_package(package, from_file.deps_index)

def _swift_deps_impl(module_ctx):
for mod in module_ctx.modules:
for from_file in mod.tags.from_file:
_declare_pkgs_from_file(module_ctx, from_file)

_from_file_tag = tag_class(
attrs = {
"deps_index": attr.label(
mandatory = True,
doc = "A `swift_deps_index.json`.",
),
},
doc = "Load Swift packages from a file generated by the Gazelle extension.",
)

swift_deps = module_extension(
implementation = _swift_deps_impl,
tag_classes = {
"from_file": _from_file_tag,
},
)
6 changes: 3 additions & 3 deletions swiftpkg/internal/local_swift_package.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _local_swift_package_impl(repository_ctx):
pkg_ctx = pkg_ctxs.read(repository_ctx, repo_dir, env)
repo_rules.gen_build_files(repository_ctx, pkg_ctx)

return update_attrs(repository_ctx.attr, _COMMON_ATTRS.keys(), {})
return update_attrs(repository_ctx.attr, _ALL_ATTRS.keys(), {})

_PATH_ATTRS = {
"path": attr.string(
Expand All @@ -69,14 +69,14 @@ _PATH_ATTRS = {
),
}

_COMMON_ATTRS = dicts.add(
_ALL_ATTRS = dicts.add(
repo_rules.env_attrs,
repo_rules.swift_attrs,
_PATH_ATTRS,
)

local_swift_package = repository_rule(
implementation = _local_swift_package_impl,
attrs = _COMMON_ATTRS,
attrs = _ALL_ATTRS,
doc = "Used to build a local Swift package.",
)
3 changes: 2 additions & 1 deletion swiftpkg/internal/pkg_ctxs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
load(":deps_indexes.bzl", "deps_indexes")
load(":pkginfo_ext_deps.bzl", "pkginfo_ext_deps")
load(":pkginfos.bzl", "pkginfos")
load(":repository_utils.bzl", "repository_utils")

def _read(repository_ctx, repo_dir, env):
deps_index_json = repository_ctx.read(
Expand All @@ -17,7 +18,7 @@ def _read(repository_ctx, repo_dir, env):
)
return _new(
pkg_info = pkg_info,
repo_name = repository_ctx.name,
repo_name = repository_utils.package_name(repository_ctx),
deps_index = deps_index,
)

Expand Down
Loading

0 comments on commit 12d0e9d

Please sign in to comment.