Skip to content

Commit

Permalink
feat: add support for Swift package registries
Browse files Browse the repository at this point in the history
  • Loading branch information
luispadron committed Oct 30, 2024
1 parent d15b8ae commit 6739de1
Show file tree
Hide file tree
Showing 14 changed files with 301 additions and 4 deletions.
8 changes: 8 additions & 0 deletions examples/swift_package_registry/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Import Shared settings
import %workspace%/../../shared.bazelrc

# Import CI settings.
import %workspace%/../../ci.bazelrc

# Try to import a local.rc file; typically, written by CI
try-import %workspace%/../../local.bazelrc
9 changes: 9 additions & 0 deletions examples/swift_package_registry/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

swift_library(
name = "SwiftPackageRegistryExample",
srcs = ["main.swift"],
deps = [
"@swiftpkg_swift_collections//:Collections",
],
)
62 changes: 62 additions & 0 deletions examples/swift_package_registry/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module(
name = "interesting_deps_example",
version = "0.0.0",
)

bazel_dep(
name = "rules_swift_package_manager",
version = "0.0.0",
)
local_path_override(
module_name = "rules_swift_package_manager",
path = "../..",
)

bazel_dep(name = "cgrindel_bazel_starlib", version = "0.21.0")
bazel_dep(name = "bazel_skylib", version = "1.7.1")

# The apple_support bazel_dep must come before the rules_cc.
# https://github.com/bazelbuild/apple_support#incompatible-toolchain-resolution
bazel_dep(name = "apple_support", version = "1.17.1")
bazel_dep(
name = "rules_swift",
version = "2.2.2",
repo_name = "build_bazel_rules_swift",
)

bazel_dep(
name = "bazel_skylib_gazelle_plugin",
version = "1.7.1",
dev_dependency = True,
)
bazel_dep(
name = "gazelle",
version = "0.39.1",
dev_dependency = True,
repo_name = "bazel_gazelle",
)

apple_cc_configure = use_extension(
"@apple_support//crosstool:setup.bzl",
"apple_cc_configure_extension",
)
use_repo(apple_cc_configure, "local_config_apple_cc")

swift_deps = use_extension(
"@rules_swift_package_manager//:extensions.bzl",
"swift_deps",
)
swift_deps.from_package(
resolved = "//:Package.resolved",
swift = "//:Package.swift",
)
swift_deps.configure_swift_package(
registries = {
"[default]": "http://localhost:8000",
},
)

use_repo(
swift_deps,
"swift_package",
)
14 changes: 14 additions & 0 deletions examples/swift_package_registry/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"originHash" : "21c64ff306c68b30986eb70b9aa9bb2771832a6236d332312f98a602acd95942",
"pins" : [
{
"identity" : "apple.swift-collections",
"kind" : "registry",
"location" : "",
"state" : {
"version" : "1.1.3"
}
}
],
"version" : 3
}
10 changes: 10 additions & 0 deletions examples/swift_package_registry/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// swift-tools-version: 5.10

import PackageDescription

let package = Package(
name: "SwiftPackageRegistryExample",
dependencies: [
.package(id: "apple.swift-collections", exact: "1.1.3"),
]
)
6 changes: 6 additions & 0 deletions examples/swift_package_registry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example using a Swift Package Registry

This example demonstrates how to declare dependent Swift packages that are hosted in a Swift
Package Registry.

TODO: Add an example.
29 changes: 29 additions & 0 deletions examples/swift_package_registry/do_test
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

set -o errexit -o nounset -o pipefail

# Use the Bazel binary specified by the integration test. Otherise, fall back
# to bazel.
bazel="${BIT_BAZEL_BINARY:-bazel}"

# This example requires a local registry to be running on `localhost:8000`.
# As such we spin up a local registry using https://github.com/luispadron/fake-swift-package-registry
curl \
-L https://github.com/luispadron/fake-swift-package-registry/releases/download/0.3.0/fake-swift-package-registry \
-o /tmp/fake-swift-package-registry
chmod +x /tmp/fake-swift-package-registry
spctl --add /tmp/fake-swift-package-registry # the binary is not signed, allow it to run

# Start the fake registry in the background
/tmp/fake-swift-package-registry > /tmp/fake-swift-package-registry.log 2>&1 &
fake_swift_package_registry_pid=$!
trap "kill ${fake_swift_package_registry_pid}" EXIT ERR

# Test resolving the package via the `swift_package` repo.
"${bazel}" run @swift_package//:resolve

# Ensure that it builds and tests pass
"${bazel}" test //...

# Shutdown the fake registry
kill "${fake_swift_package_registry_pid}"
6 changes: 6 additions & 0 deletions examples/swift_package_registry/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Collections

let orderedSet = OrderedSet([1, 2, 3, 4, 5])

print("Hello, world!")
print(orderedSet)
8 changes: 8 additions & 0 deletions swiftpkg/bzlmod/swift_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ load("//swiftpkg/internal:swift_deps_info.bzl", "swift_deps_info")
load("//swiftpkg/internal:swift_package.bzl", "PATCH_ATTRS", "swift_package")
load("//swiftpkg/internal:swift_package_tool.bzl", "SWIFT_PACKAGE_CONFIG_ATTRS")
load("//swiftpkg/internal:swift_package_tool_repo.bzl", "swift_package_tool_repo")
load("//swiftpkg/internal:swift_registry_package.bzl", "swift_registry_package")

# MARK: - swift_deps bzlmod Extension

Expand Down Expand Up @@ -196,6 +197,13 @@ def _declare_pkg_from_dependency(dep, config_pkg):
dependencies_index = None,
)

elif dep.registry:
swift_registry_package(
name = name,
id = dep.registry.pin.identity,
version = dep.registry.pin.state.version,
)

def _declare_swift_package_repo(name, from_package, config_swift_package):
config_swift_package_kwargs = repository_utils.struct_to_kwargs(
struct = config_swift_package,
Expand Down
10 changes: 10 additions & 0 deletions swiftpkg/internal/bazel_repo_names.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ def _from_identity(identity):
Returns:
A Bazel repository name as a `string`.
"""

# TODO: Should we do this replacement for registry packages?
# This potentially conflicts with Swift Package Manager's `--use-registry-identity-for-scm` flag.
# Without this though, what would have been generated as `swiftpkg_swift_collections` is instead
# `swiftpkg_apple.swift_collections` which seems more confusing and build breaking if going from registry
# to non-registry.
registry_org_identity_split = identity.split(".")
if len(registry_org_identity_split) > 1:
identity = registry_org_identity_split[1]

return "swiftpkg_" + identity.replace("-", "_")

def _normalize(repo_name):
Expand Down
39 changes: 35 additions & 4 deletions swiftpkg/internal/pkginfos.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ def _new_dependency_from_desc_json_map(dep_names_by_id, dep_map, resolved_dep_ma

source_control = None
file_system = None
registry = None

if type == "sourceControl":
pin = None
if resolved_dep_map:
Expand All @@ -160,6 +162,13 @@ def _new_dependency_from_desc_json_map(dep_names_by_id, dep_map, resolved_dep_ma
)
elif type == "fileSystem":
file_system = _new_file_system(path = dep_map["path"])
elif type == "registry":
pin = None
if resolved_dep_map:
pin = _new_pin_from_resolved_dep_map(resolved_dep_map)
registry = _new_registry(
pin = pin,
)
else:
fail("Unrecognized dependency type {type} for {identity}.".format(
type = type,
Expand All @@ -171,6 +180,7 @@ def _new_dependency_from_desc_json_map(dep_names_by_id, dep_map, resolved_dep_ma
name = name,
source_control = source_control,
file_system = file_system,
registry = registry,
)

def _new_pin_from_resolved_dep_map(resolved_dep_map):
Expand All @@ -180,7 +190,7 @@ def _new_pin_from_resolved_dep_map(resolved_dep_map):
kind = resolved_dep_map["kind"],
location = resolved_dep_map["location"],
state = _new_pin_state(
revision = state_map["revision"],
revision = state_map.get("revision"),
version = state_map.get("version"),
),
)
Expand Down Expand Up @@ -499,7 +509,7 @@ def _new_dependency_identity_to_name_map(dump_deps):
result = {}
for dep in dump_deps:
identity_provider_list = (
dep.get("sourceControl") or dep.get("fileSystem")
dep.get("sourceControl") or dep.get("fileSystem") or dep.get("registry")
)
if not identity_provider_list:
continue
Expand Down Expand Up @@ -703,7 +713,7 @@ def _new_platform(name, version):

# MARK: - External Dependency

def _new_dependency(identity, name, source_control = None, file_system = None):
def _new_dependency(identity, name, source_control = None, file_system = None, registry = None):
"""Creates a `struct` representing an external dependency for a Swift \
package.
Expand All @@ -716,6 +726,9 @@ def _new_dependency(identity, name, source_control = None, file_system = None):
file_system: Optional. A `struct` as returned by
`pkginfos.new_file_system()`. If present, it identifies the
dependency as being loaded from a local file system.
registry: Optional. A `struct` as returned by
`pkginfos.new_registry()`. If present, it identifies the
dependency as being loaded from a Swift package registry.
Returns:
A `struct` representing an external dependency.
Expand All @@ -726,6 +739,7 @@ def _new_dependency(identity, name, source_control = None, file_system = None):
name = pkginfo_dependencies.normalize_name(name),
source_control = source_control,
file_system = file_system,
registry = registry,
)

def _new_source_control(pin):
Expand Down Expand Up @@ -767,8 +781,11 @@ def _new_pin(identity, kind, location, state):
def _new_pin_state(revision, version = None):
"""Create a `struct` representing the state for a pin.
`revision` is not provided for Swift package registry pins.
`version` is not provided for git ref pins.
Args:
revision: The commit hash as a `string`.
revision: Optional. The commit hash as a `string`.
version: Optional. The version string for the commit as a `string`.
Returns:
Expand All @@ -792,6 +809,19 @@ def _new_file_system(path):
path = path,
)

def _new_registry(pin):
"""Create a `struct` representing a registry dependency.
Args:
pin: A `struct` as returned by `pkginfos.new_pin()`.
Returns:
A `struct` representing a registry dependency.
"""
return struct(
pin = pin,
)

def _new_dependency_requirement(ranges = None):
"""Creates a `struct` representing the requirements for an external \
dependency.
Expand Down Expand Up @@ -1667,6 +1697,7 @@ pkginfos = struct(
new_product = _new_product,
new_product_reference = _new_product_reference,
new_product_type = _new_product_type,
new_registry = _new_registry,
new_resource = _new_resource,
new_resource_rule = _new_resource_rule,
new_resource_rule_process = _new_resource_rule_process,
Expand Down
Loading

0 comments on commit 6739de1

Please sign in to comment.