Skip to content

Commit 69a9836

Browse files
committed
feat: add ability to cache json responses in-repo
Besides a performance improvement, it allows cross-platform builds to work (e.g. Linux host building Apple code). Signed-off-by: Brentley Jones <github@brentleyjones.com>
1 parent 203e30a commit 69a9836

File tree

7 files changed

+113
-9
lines changed

7 files changed

+113
-9
lines changed

swiftpkg/bzlmod/swift_deps.bzl

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Implementation for `swift_deps` bzlmod extension."""
22

33
load("@bazel_skylib//lib:dicts.bzl", "dicts")
4+
load("@bazel_skylib//lib:paths.bzl", "paths")
45
load("//swiftpkg/internal:bazel_repo_names.bzl", "bazel_repo_names")
56
load("//swiftpkg/internal:local_swift_package.bzl", "local_swift_package")
67
load("//swiftpkg/internal:pkginfos.bzl", "pkginfos")
@@ -59,11 +60,21 @@ def _declare_pkgs_from_package(module_ctx, from_package, config_pkgs, config_swi
5960
# Get the package info.
6061
pkg_swift = module_ctx.path(from_package.swift)
6162
debug_path = module_ctx.path(".")
63+
workspace_root = str(pkg_swift.dirname)
64+
65+
root_cached_json_directory = None
66+
if from_package.cached_json_directory:
67+
root_cached_json_directory = paths.join(
68+
workspace_root,
69+
from_package.cached_json_directory,
70+
)
71+
6272
pkg_info = pkginfos.get(
6373
module_ctx,
64-
directory = str(pkg_swift.dirname),
74+
directory = workspace_root,
6575
env = env,
6676
debug_path = str(debug_path),
77+
cached_json_directory = root_cached_json_directory,
6778
resolved_pkg_map = resolved_pkg_map,
6879
collect_src_info = False,
6980
registries_directory = registries_directory,
@@ -157,10 +168,18 @@ the Swift package to make it available.\
157168
processing = to_process
158169
to_process = []
159170
for dep in processing:
171+
dep_cached_json_directory = None
172+
173+
if from_package.cached_json_directory:
174+
dep_cached_json_directory = paths.join(
175+
dep.file_system.path,
176+
from_package.cached_json_directory,
177+
)
160178
dep_pkg_info = pkginfos.get(
161179
module_ctx,
162180
directory = dep.file_system.path,
163181
debug_path = None,
182+
cached_json_directory = dep_cached_json_directory,
164183
resolved_pkg_map = None,
165184
collect_src_info = False,
166185
)
@@ -185,7 +204,13 @@ the Swift package to make it available.\
185204
config_pkg = config_pkgs.get(
186205
bazel_repo_names.from_identity(dep.identity),
187206
)
188-
_declare_pkg_from_dependency(dep, config_pkg, from_package, config_swift_package)
207+
_declare_pkg_from_dependency(
208+
dep,
209+
config_pkg,
210+
from_package,
211+
config_swift_package,
212+
from_package.cached_json_directory,
213+
)
189214

190215
# Add all transitive dependencies to direct_dep_repo_names if `publicly_expose_all_targets` flag is set.
191216
for dep in all_deps_by_id.values():
@@ -199,7 +224,15 @@ the Swift package to make it available.\
199224

200225
return direct_dep_repo_names
201226

202-
def _declare_pkg_from_dependency(dep, config_pkg, from_package, config_swift_package):
227+
def _declare_pkg_from_dependency(
228+
dep,
229+
config_pkg,
230+
from_package,
231+
config_swift_package,
232+
cached_json_directory):
233+
if cached_json_directory:
234+
cached_json_directory = paths.join(cached_json_directory, dep.name)
235+
203236
name = bazel_repo_names.from_identity(dep.identity)
204237
if dep.source_control:
205238
init_submodules = None
@@ -236,7 +269,7 @@ def _declare_pkg_from_dependency(dep, config_pkg, from_package, config_swift_pac
236269
dependencies_index = None,
237270
env = from_package.env,
238271
env_inherit = from_package.env_inherit,
239-
init_submodules = init_submodules,
272+
cached_json_directory = cached_json_directory, init_submodules = init_submodules,
240273
recursive_init_submodules = recursive_init_submodules,
241274
patch_args = patch_args,
242275
patch_cmds = patch_cmds,
@@ -256,6 +289,7 @@ def _declare_pkg_from_dependency(dep, config_pkg, from_package, config_swift_pac
256289
env_inherit = from_package.env_inherit,
257290
path = dep.file_system.path,
258291
dependencies_index = None,
292+
cached_json_directory = cached_json_directory,
259293
)
260294

261295
elif dep.registry:
@@ -350,6 +384,7 @@ bazel run @swift_package//:resolve
350384
```
351385
""",
352386
),
387+
"cached_json_directory": attr.string(),
353388
"env": attr.string_dict(
354389
doc = """\
355390
Environment variables that will be passed to the execution environments for \

swiftpkg/internal/local_swift_package.bzl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,19 @@ def _local_swift_package_impl(repository_ctx):
6262
repo_rules.write_workspace_file(repository_ctx, repo_dir)
6363

6464
# Generate the build file
65-
pkg_ctx = pkg_ctxs.read(repository_ctx, repo_dir, env)
65+
cached_json_directory = None
66+
if repository_ctx.attr.cached_json_directory:
67+
cached_json_directory = paths.join(
68+
str(repository_ctx.workspace_root),
69+
repository_ctx.attr.cached_json_directory,
70+
)
71+
72+
pkg_ctx = pkg_ctxs.read(
73+
repository_ctx,
74+
repo_dir,
75+
env,
76+
cached_json_directory,
77+
)
6678
repo_rules.gen_build_files(repository_ctx, pkg_ctx)
6779

6880
return update_attrs(repository_ctx.attr, _ALL_ATTRS.keys(), {})
@@ -78,6 +90,7 @@ _ALL_ATTRS = dicts.add(
7890
repo_rules.env_attrs,
7991
repo_rules.swift_attrs,
8092
_PATH_ATTRS,
93+
{"cached_json_directory": attr.string()},
8194
)
8295

8396
local_swift_package = repository_rule(

swiftpkg/internal/pkg_ctxs.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ def _read(
77
repository_ctx,
88
repo_dir,
99
env,
10+
cached_json_directory,
1011
resolved_pkg_map = None,
1112
registries_directory = None,
1213
replace_scm_with_registry = False):
1314
pkg_info = pkginfos.get(
1415
repository_ctx = repository_ctx,
1516
directory = repo_dir,
1617
env = env,
18+
cached_json_directory = cached_json_directory,
1719
resolved_pkg_map = resolved_pkg_map,
1820
registries_directory = registries_directory,
1921
replace_scm_with_registry = replace_scm_with_registry,

swiftpkg/internal/pkginfos.bzl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def _get_dump_manifest(
2828
env = {},
2929
working_directory = "",
3030
debug_path = None,
31+
cache_path = None,
3132
registries_directory = None,
3233
replace_scm_with_registry = False):
3334
"""Returns a dict representing the package dump for an SPM package.
@@ -52,6 +53,10 @@ def _get_dump_manifest(
5253
debug_path = str(repository_ctx.path("."))
5354
debug_json_path = paths.join(debug_path, "dump.json")
5455

56+
cached_json_path = None
57+
if cache_path:
58+
cached_json_path = paths.join(cache_path, "dump.json")
59+
5560
args = ["swift", "package"]
5661

5762
if registries_directory:
@@ -66,13 +71,15 @@ def _get_dump_manifest(
6671
env = env,
6772
working_directory = working_directory,
6873
debug_json_path = debug_json_path,
74+
cached_json_path = cached_json_path,
6975
)
7076

7177
def _get_desc_manifest(
7278
repository_ctx,
7379
env = {},
7480
working_directory = "",
7581
debug_path = None,
82+
cache_path = None,
7683
registries_directory = None,
7784
replace_scm_with_registry = False):
7885
"""Returns a dict representing the package description for an SPM package.
@@ -97,6 +104,10 @@ def _get_desc_manifest(
97104
debug_path = str(repository_ctx.path("."))
98105
debug_json_path = paths.join(debug_path, "desc.json")
99106

107+
cached_json_path = None
108+
if cache_path:
109+
cached_json_path = paths.join(cache_path, "desc.json")
110+
100111
args = ["swift", "package"]
101112

102113
if registries_directory:
@@ -112,13 +123,15 @@ def _get_desc_manifest(
112123
env = env,
113124
working_directory = working_directory,
114125
debug_json_path = debug_json_path,
126+
cached_json_path = cached_json_path,
115127
)
116128

117129
def _get(
118130
repository_ctx,
119131
directory,
120132
env = {},
121133
debug_path = None,
134+
cached_json_directory = None,
122135
resolved_pkg_map = None,
123136
collect_src_info = True,
124137
registries_directory = None,
@@ -150,11 +163,13 @@ def _get(
150163
if not paths.is_absolute(debug_path):
151164
# For backwards compatibility, resolve relative to the working directory.
152165
debug_path = paths.join(directory, debug_path)
166+
153167
dump_manifest = _get_dump_manifest(
154168
repository_ctx,
155169
env = env,
156170
working_directory = directory,
157171
debug_path = debug_path,
172+
cache_path = cached_json_directory,
158173
registries_directory = registries_directory,
159174
replace_scm_with_registry = replace_scm_with_registry,
160175
)
@@ -163,6 +178,7 @@ def _get(
163178
env = env,
164179
working_directory = directory,
165180
debug_path = debug_path,
181+
cache_path = cached_json_directory,
166182
registries_directory = registries_directory,
167183
replace_scm_with_registry = replace_scm_with_registry,
168184
)
@@ -1648,7 +1664,9 @@ def _new_resource_rule_process(localization = None):
16481664

16491665
def _new_resource_from_desc_map(desc_map, pkg_path):
16501666
path = desc_map["path"]
1651-
if paths.is_absolute(path):
1667+
if path.startswith("./"):
1668+
path = path[2:]
1669+
elif paths.is_absolute(path):
16521670
path = paths.relativize(path, pkg_path)
16531671
return _new_resource(
16541672
path = path,

swiftpkg/internal/registry_swift_package.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,18 @@ def _registry_swift_package_impl(repository_ctx):
235235
else:
236236
resolved_pkg_map = dict()
237237

238+
cached_json_directory = None
239+
if repository_ctx.attr.cached_json_directory:
240+
cached_json_directory = paths.join(
241+
str(repository_ctx.workspace_root),
242+
repository_ctx.attr.cached_json_directory,
243+
)
244+
238245
pkg_ctx = pkg_ctxs.read(
239246
repository_ctx,
240247
directory,
241248
env,
249+
cached_json_directory,
242250
resolved_pkg_map = resolved_pkg_map,
243251
registries_directory = registries_directory,
244252
replace_scm_with_registry = attr.replace_scm_with_registry,

swiftpkg/internal/repository_utils.bzl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,33 @@ def _parsed_json_from_spm_command(
7878
arguments,
7979
env = {},
8080
working_directory = "",
81-
debug_json_path = None):
81+
debug_json_path = None,
82+
cached_json_path = None):
83+
if cached_json_path:
84+
cached_json_path_path = repository_ctx.path(cached_json_path)
85+
if cached_json_path_path.exists:
86+
return json.decode(repository_ctx.read(cached_json_path_path))
87+
8288
json_str = repository_utils.exec_spm_command(
8389
repository_ctx,
8490
arguments,
8591
env = env,
8692
working_directory = working_directory,
87-
)
93+
).replace(working_directory, ".")
94+
8895
if debug_json_path:
8996
if not paths.is_absolute(debug_json_path):
9097
debug_json_path = paths.join(working_directory, debug_json_path)
9198
repository_ctx.file(debug_json_path, content = json_str, executable = False)
99+
if cached_json_path:
100+
if debug_json_path:
101+
tmp_path = debug_json_path
102+
else:
103+
tmp_path = paths.join(str(repository_ctx.path(".")), paths.basename(cached_json_path))
104+
repository_ctx.file(tmp_path, content = json_str, executable = False)
105+
repository_ctx.execute(["mkdir", "-p", paths.dirname(cached_json_path)])
106+
repository_ctx.execute(["cp", tmp_path, cached_json_path])
107+
92108
return json.decode(json_str)
93109

94110
def _package_name(repository_ctx):

swiftpkg/internal/swift_package.bzl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Implementation for `swift_package`."""
22

33
load("@bazel_skylib//lib:dicts.bzl", "dicts")
4+
load("@bazel_skylib//lib:paths.bzl", "paths")
45
load("@bazel_tools//tools/build_defs/repo:git_worker.bzl", "git_repo")
56
load(
67
"@bazel_tools//tools/build_defs/repo:utils.bzl",
@@ -68,10 +69,18 @@ def _swift_package_impl(repository_ctx):
6869
registries_directory = None
6970

7071
# Generate the build file
72+
cached_json_directory = None
73+
if repository_ctx.attr.cached_json_directory:
74+
cached_json_directory = paths.join(
75+
str(repository_ctx.workspace_root),
76+
repository_ctx.attr.cached_json_directory,
77+
)
78+
7179
pkg_ctx = pkg_ctxs.read(
7280
repository_ctx,
7381
directory,
7482
env,
83+
cached_json_directory,
7584
registries_directory = registries_directory,
7685
replace_scm_with_registry = replace_scm_with_registry,
7786
)
@@ -197,7 +206,10 @@ _ALL_ATTRS = dicts.add(
197206
_GIT_ATTRS,
198207
repo_rules.env_attrs,
199208
repo_rules.swift_attrs,
200-
{"version": attr.string(doc = "The resolved version of the package.")},
209+
{
210+
"cached_json_directory": attr.string(),
211+
"version": attr.string(doc = "The resolved version of the package."),
212+
},
201213
)
202214

203215
swift_package = repository_rule(

0 commit comments

Comments
 (0)