Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
cd9dd29
Brought over bazel_build_declarations and build_declarations
cgrindel Dec 2, 2022
a47cf1f
Add starlark_utils
cgrindel Dec 2, 2022
f5669f8
Add tests for starlark_utils
cgrindel Dec 2, 2022
b63054b
Add starlark_utils.indent. Testing to_str convention
cgrindel Dec 2, 2022
105132f
Started adding starlark_utils.to_starlark()
cgrindel Dec 3, 2022
49875cd
Added indent to to_starlark
cgrindel Dec 3, 2022
60a1f14
Add dict support
cgrindel Dec 3, 2022
d3f2a54
Add support for empty list and dict
cgrindel Dec 3, 2022
bb26c04
Fixed mulit-level indent
cgrindel Dec 3, 2022
62dfba4
Clean up
cgrindel Dec 3, 2022
a9e284c
Add test for to_starlark_parts
cgrindel Dec 3, 2022
2585369
Some cleanup
cgrindel Dec 4, 2022
d1e0bb3
Renamed starlark_utils to starlark_codegen
cgrindel Dec 4, 2022
3bdf85a
Implement build_decls.to_starlark_parts
cgrindel Dec 4, 2022
ae9db2c
Put in plumbing for generating language declarations from package info
cgrindel Dec 4, 2022
c4d21fa
Started adding swift rule declarations
cgrindel Dec 5, 2022
290d97b
Add test for pkginfo_targets.srcs
cgrindel Dec 5, 2022
f3da11c
Add TODO
cgrindel Dec 5, 2022
db8a42f
Add skeleton for pkginfo_target_deps
cgrindel Dec 5, 2022
78eaa42
Add bazel_label_by_name_test
cgrindel Dec 5, 2022
fe3b1de
Add pkginfo_ext_deps.find_by_identity
cgrindel Dec 5, 2022
e9c4280
Add bazel_repo_names skeleton
cgrindel Dec 5, 2022
bc33ada
Add TODO comment
cgrindel Dec 5, 2022
e21f795
Add tests for bazel_repo_names.from_url
cgrindel Dec 6, 2022
66af72e
Add comments to keep repo name logic in-sync
cgrindel Dec 6, 2022
ebbe450
Add tests for pkginfo_target_deps.bazel_label
cgrindel Dec 6, 2022
f2c0619
Added tests for pkginfo_targets.deps.
cgrindel Dec 6, 2022
154e416
Add missing doc comment
cgrindel Dec 6, 2022
5614f31
Started adding load_statements
cgrindel Dec 6, 2022
4e9d4ee
Add load_statments.uniq
cgrindel Dec 6, 2022
7c3e01d
Add to_starlark_parts to load_statment instances
cgrindel Dec 6, 2022
a4fd052
Save work before rename
cgrindel Dec 6, 2022
f2ac7a2
Rename to swiftpkg_build_files
cgrindel Dec 6, 2022
bce1a64
More plumbing. Add build_decls.uniq.
cgrindel Dec 6, 2022
0086583
Add build_files.merge
cgrindel Dec 6, 2022
7ad4f0b
Update plumbing in swift_package.
cgrindel Dec 6, 2022
4f2be73
Add initial tests for swift_library
cgrindel Dec 6, 2022
c9b8de8
Rename swiftpkg_build_files.new to new_for_targets
cgrindel Dec 6, 2022
e6c040e
Plumbed for build file per target
cgrindel Dec 7, 2022
7dce6ea
Test new_for_target without deps
cgrindel Dec 7, 2022
6274e6c
Updated test to represent what I expect. Tests are red.
cgrindel Dec 7, 2022
1f8b862
Rewiring the generation of labels for target dependencies
cgrindel Dec 7, 2022
644566a
Tests are green
cgrindel Dec 7, 2022
5d2f9aa
Started reworking the swiftpkg_build_files_tests
cgrindel Dec 7, 2022
f5349d5
Add test for swift test target
cgrindel Dec 7, 2022
0fb46cb
Generating swift_binary for executable product if dep target is not
cgrindel Dec 7, 2022
7f2374b
Add support for library products
cgrindel Dec 7, 2022
147e3d9
Add TODO comments
cgrindel Dec 7, 2022
c3542db
Add missing doc
cgrindel Dec 7, 2022
2a867ba
Converted TODO comments to GHXXX comments
cgrindel Dec 7, 2022
259e867
Rename test to swiftpkg_build_files_for_old_style_pkg_tests
cgrindel Dec 7, 2022
f37ee01
Add doc to some modules
cgrindel Dec 7, 2022
72e975c
Add test for pkginfo_targets.bazel_label
cgrindel Dec 7, 2022
ec11b0e
Renamed package_infos to pkginfos.
cgrindel Dec 7, 2022
08e6708
Add validations module
cgrindel Dec 7, 2022
8513410
Clean up
cgrindel Dec 7, 2022
fe34084
Upgrade got bazel-starlib 0.10.0
cgrindel Dec 7, 2022
4d533bd
Clean up
cgrindel Dec 7, 2022
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
6 changes: 3 additions & 3 deletions deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def swift_bazel_dependencies():
maybe(
http_archive,
name = "cgrindel_bazel_starlib",
sha256 = "42a496dddbc089c68cd72b1f20dfe6acf474c53043dafe230ec887f617c0c252",
strip_prefix = "bazel-starlib-0.9.0",
sha256 = "99132d1074717e3952ebe57e9bddcd76e735bc83336093d8dc6a0820e6819998",
strip_prefix = "bazel-starlib-0.10.0",
urls = [
"http://github.com/cgrindel/bazel-starlib/archive/v0.9.0.tar.gz",
"http://github.com/cgrindel/bazel-starlib/archive/v0.10.0.tar.gz",
],
)
3 changes: 3 additions & 0 deletions gazelle/internal/swift/repo_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"github.com/cgrindel/swift_bazel/gazelle/internal/spreso"
)

// The logic in RepoNameFromURL must stay in-sync with bazel_repo_names.from_url in
// swiftpkg/internal/bazel_repo_names.bzl.

func RepoNameFromURL(url string) (string, error) {
if url == "" {
return "", fmt.Errorf("URL cannot be empty string")
Expand Down
81 changes: 78 additions & 3 deletions swiftpkg/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ bzl_library(
srcs = ["swift_package.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [
":package_infos",
":pkginfos",
":spm_versions",
"@bazel_skylib//lib:dicts",
"@bazel_skylib//lib:versions",
Expand All @@ -16,8 +16,8 @@ bzl_library(
)

bzl_library(
name = "package_infos",
srcs = ["package_infos.bzl"],
name = "pkginfos",
srcs = ["pkginfos.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [":repository_utils"],
)
Expand Down Expand Up @@ -49,8 +49,83 @@ bzl_library(
deps = ["@bazel_skylib//lib:paths"],
)

bzl_library(
name = "build_decls",
srcs = ["build_decls.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [":starlark_codegen"],
)

bzl_library(
name = "pkginfo_targets",
srcs = ["pkginfo_targets.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = ["@bazel_skylib//lib:paths"],
)

bzl_library(
name = "pkginfo_target_deps",
srcs = ["pkginfo_target_deps.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = ["@cgrindel_bazel_starlib//bzllib:defs"],
)

bzl_library(
name = "load_statements",
srcs = ["load_statements.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [
":starlark_codegen",
"@bazel_skylib//lib:sets",
],
)

bzl_library(
name = "swiftpkg_build_files",
srcs = ["swiftpkg_build_files.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [
":pkginfo_targets",
":pkginfos",
],
)

bzl_library(
name = "build_files",
srcs = ["build_files.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
deps = [
":build_decls",
":load_statements",
],
)

bzl_library(
name = "bazel_repo_names",
srcs = ["bazel_repo_names.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
)

bzl_library(
name = "pkginfo_ext_deps",
srcs = ["pkginfo_ext_deps.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
)

bzl_library(
name = "repository_files",
srcs = ["repository_files.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
)

bzl_library(
name = "starlark_codegen",
srcs = ["starlark_codegen.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
)

bzl_library(
name = "validations",
srcs = ["validations.bzl"],
visibility = ["//swiftpkg:__subpackages__"],
)
23 changes: 23 additions & 0 deletions swiftpkg/internal/bazel_repo_names.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Module for creating Bazel repository names."""

# The logic in from_url must stay in-sync with the RepoNameFromURL logic in
# gazelle/internal/swift/repo_name.go.
def _from_url(url):
if url.startswith("https://"):
host_and_path = url.removeprefix("https://")
elif url.startswith("http://"):
host_and_path = url.removeprefix("http://")
else:
fail("Only https:// and http:// URLs are supported. url:", url)
host_and_path = host_and_path.removesuffix(".git")
host_sep_idx = host_and_path.find("/")
if host_sep_idx < 0:
fail("Invalid URL: host separator was not found. url:", url)
elif host_sep_idx == 0:
fail("Invalid URL: host not specified. url:", url)
path = host_and_path[host_sep_idx + 1:]
return path.replace("/", "_").replace("-", "_")

bazel_repo_names = struct(
from_url = _from_url,
)
80 changes: 80 additions & 0 deletions swiftpkg/internal/build_decls.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""API for creating and managing build file declarations"""

load("@bazel_skylib//lib:sets.bzl", "sets")
load(":starlark_codegen.bzl", scg = "starlark_codegen")

def _new(kind, name, attrs = {}, comments = []):
return struct(
kind = kind,
name = name,
attrs = attrs,
comments = comments,
to_starlark_parts = _to_starlark_parts,
)

def _to_starlark_parts(decl, indent):
parts = []
for c in decl.comments:
parts.append(scg.indent(indent, "{}\n".format(c)))
parts.append(scg.indent(indent, "{}(\n".format(decl.kind)))
parts.extend(scg.attr("name", decl.name, indent + 1))

# Sort the keys to ensure that we have a consistent output. It would be
# ideal to output them in a manner that matches Buildifier output rules.
keys = sorted(decl.attrs.keys())
for key in keys:
val = decl.attrs[key]
parts.extend(scg.attr(key, val, indent + 1))
parts.append(scg.indent(indent, ")"))

return parts

def _uniq(decls):
"""Sort and check for duplicate declarations.

Args:
decls: A `list` of build declaration `struct` values as returned by
`build_decls.new`.

Returns:
A `list` of build declarations sorted by type-name.
"""
index_by_type_name = {}
for decl in decls:
key = "{kind}_{name}".format(
kind = decl.kind,
name = decl.name,
)
existing_values = index_by_type_name.get(key, default = [])
existing_values.append(decl)
index_by_type_name[key] = existing_values

# Collect in type-name order
results = []
for type_name in sorted(index_by_type_name.keys()):
existing_values = index_by_type_name[type_name]
results.extend(existing_values)

# Check for any duplicate decl names
names = sets.make()
for decl in results:
name = decl.name
if sets.contains(names, name):
fail("A duplicate decl name was found. name: {}".format(name))
sets.insert(names, name)

return results

def _get(decls, name, fail_if_not_found = True):
for decl in decls:
if decl.name == name:
return decl
if fail_if_not_found:
fail("Failed to find build declaration. name:", name)
return None

build_decls = struct(
new = _new,
uniq = _uniq,
get = _get,
)
58 changes: 58 additions & 0 deletions swiftpkg/internal/build_files.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Module for defining and generating Bazel build files."""

load("//swiftpkg/internal:build_decls.bzl", "build_decls")
load("//swiftpkg/internal:load_statements.bzl", "load_statements")

def _new(load_stmts = [], decls = []):
"""Create a `struct` that represents the parts of a Bazel build file.

Args:
load_stmts: A `list` of load statement `struct` values as returned
by `load_statements.new`.
decls: A `list` of declaration `struct` values as returned by
`build_decls.new`.

Returns:
A `struct` representing parts of a Bazel build file.
"""
if len(load_stmts) == 0 and len(decls) == 0:
fail("""\
Attempted to create a build file with no load statements or declarations.\
""")
return struct(
load_stmts = load_stmts,
decls = decls,
)

def _merge(*bld_files):
"""Merge build file `struct` values into a single value.

The load statements will be sorted and deduped. The targets will be sorted
by type and name.

Args:
*bld_files: A `sequence` of build file declaration `struct` values
as returned by `build_files.new`.

Returns:
A merged build file declaration `struct`.
"""
if len(bld_files) == 0:
fail("Attempted to merge build files, but none were provided.")

load_stmts = []
decls = []
for bf in bld_files:
load_stmts.extend(bf.load_stmts)
decls.extend(bf.decls)
load_stmts = load_statements.uniq(load_stmts)
decls = build_decls.uniq(decls)
return _new(
load_stmts = load_stmts,
decls = decls,
)

build_files = struct(
new = _new,
merge = _merge,
)
81 changes: 81 additions & 0 deletions swiftpkg/internal/load_statements.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""Module for creating and managing Starlark load statements."""

load("@bazel_skylib//lib:sets.bzl", "sets")
load(":starlark_codegen.bzl", scg = "starlark_codegen")

def _new(location, *symbols):
"""Create a load statement `struct`.

The list of symbols will be sorted and uniquified.

Args:
location: A `string` representing the location of a Starlark file.
*symbols: A `sequence` of symbols to be loaded from the location.

Returns:
A `struct` that includes the location and the cleaned up symbols.
"""
if len(symbols) < 1:
fail("""\
Expected at least one symbol to be specified. location: {location}\
""".format(location = location))

# Get a unique set
symbols_set = sets.make(symbols)
new_symbols = sorted(sets.to_list(symbols_set))
return struct(
location = location,
symbols = new_symbols,
to_starlark_parts = _to_starlark_parts,
)

def _to_starlark_parts(load_stmt, indent):
parts = [
scg.indent(indent),
"load(",
scg.normalize(load_stmt.location),
]

# The symbols should already be sorted and deduped.
for symbol in load_stmt.symbols:
parts.extend([", ", scg.normalize(symbol)])
parts.append(")")
return parts

def _index(load_stmts):
index_by_location = {}
for load_stmt in load_stmts:
location = load_stmt.location
existing_values = index_by_location.get(location, default = [])
existing_values.append(load_stmt)
index_by_location[location] = existing_values
return index_by_location

def _uniq(load_stmts):
"""Sort and dedupe load statements.

Args:
load_stmts: A `list` of load statements as created by
`load_statments.new`.

Returns:
A `list` of load statements sorted and deduplicated.
"""
index_by_location = _index(load_stmts)

# Collect results in location-sorted order
results = []
for location in sorted(index_by_location.keys()):
existing_values = index_by_location[location]
symbols = []
for load_stmt in existing_values:
symbols.extend(load_stmt.symbols)
new_load_stmt = _new(location, *symbols)
results.append(new_load_stmt)

return results

load_statements = struct(
new = _new,
uniq = _uniq,
)
13 changes: 13 additions & 0 deletions swiftpkg/internal/pkginfo_ext_deps.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Module for generating data from external dependencies created by `pkginfos`."""

def _find_by_identity(ext_deps, identity, fail_if_not_found = True):
for ext_dep in ext_deps:
if ext_dep.identity == identity:
return ext_dep
if fail_if_not_found:
fail("Failed to find external dependency with identity", identity)
return None

pkginfo_ext_deps = struct(
find_by_identity = _find_by_identity,
)
Loading