Skip to content

Commit d91c628

Browse files
feat: add publicly_expose_all_targets flag (#1345)
Attempt to solve #932. Following the example given in the linked issue, with the new flag `publicly_expose_all_targets `, it is possible to granularly expose the build files of individual packages, as an example: ``` swift_deps.configure_package( name = "swift-nio-transport-services", publicly_expose_all_targets = True, ) swift_deps.configure_package( name = "swift-protobuf", publicly_expose_all_targets = True, ) use_repo( swift_deps, "swift_deps_info", "swift_package", "swiftpkg_swift_nio_transport_services", "swiftpkg_swift_protobuf", ) ```
1 parent 951ac6e commit d91c628

File tree

7 files changed

+554
-432
lines changed

7 files changed

+554
-432
lines changed

docs/bzlmod_extensions_overview.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ On this page:
1616
<pre>
1717
swift_deps = use_extension("@rules_swift_package_manager//:extensions.bzl", "swift_deps")
1818
swift_deps.configure_package(<a href="#swift_deps.configure_package-name">name</a>, <a href="#swift_deps.configure_package-init_submodules">init_submodules</a>, <a href="#swift_deps.configure_package-patch_args">patch_args</a>, <a href="#swift_deps.configure_package-patch_cmds">patch_cmds</a>, <a href="#swift_deps.configure_package-patch_cmds_win">patch_cmds_win</a>,
19-
<a href="#swift_deps.configure_package-patch_tool">patch_tool</a>, <a href="#swift_deps.configure_package-patches">patches</a>, <a href="#swift_deps.configure_package-recursive_init_submodules">recursive_init_submodules</a>)
19+
<a href="#swift_deps.configure_package-patch_tool">patch_tool</a>, <a href="#swift_deps.configure_package-patches">patches</a>, <a href="#swift_deps.configure_package-publicly_expose_all_targets">publicly_expose_all_targets</a>,
20+
<a href="#swift_deps.configure_package-recursive_init_submodules">recursive_init_submodules</a>)
2021
swift_deps.configure_swift_package(<a href="#swift_deps.configure_swift_package-build_path">build_path</a>, <a href="#swift_deps.configure_swift_package-cache_path">cache_path</a>, <a href="#swift_deps.configure_swift_package-dependency_caching">dependency_caching</a>, <a href="#swift_deps.configure_swift_package-manifest_cache">manifest_cache</a>,
2122
<a href="#swift_deps.configure_swift_package-manifest_caching">manifest_caching</a>, <a href="#swift_deps.configure_swift_package-security_path">security_path</a>)
2223
swift_deps.from_package(<a href="#swift_deps.from_package-declare_swift_deps_info">declare_swift_deps_info</a>, <a href="#swift_deps.from_package-declare_swift_package">declare_swift_package</a>, <a href="#swift_deps.from_package-resolved">resolved</a>, <a href="#swift_deps.from_package-swift">swift</a>)
@@ -42,6 +43,7 @@ Used to add or override settings for a particular Swift package.
4243
| <a id="swift_deps.configure_package-patch_cmds_win"></a>patch_cmds_win | Sequence of Powershell commands to be applied on Windows after patches are applied. If this attribute is not set, patch_cmds will be executed on Windows, which requires Bash binary to exist. | List of strings | optional | `[]` |
4344
| <a id="swift_deps.configure_package-patch_tool"></a>patch_tool | The patch(1) utility to use. If this is specified, Bazel will use the specified patch tool instead of the Bazel-native patch implementation. | String | optional | `""` |
4445
| <a id="swift_deps.configure_package-patches"></a>patches | A list of files that are to be applied as patches after extracting the archive. By default, it uses the Bazel-native patch implementation which doesn't support fuzz match and binary patch, but Bazel will fall back to use patch command line tool if `patch_tool` attribute is specified or there are arguments other than `-p` in `patch_args` attribute. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
46+
| <a id="swift_deps.configure_package-publicly_expose_all_targets"></a>publicly_expose_all_targets | Allows to expose internal build targets required for package compilation. The structure and labels of exposed targets may change in future releases without requiring a major version bump. | Boolean | optional | `False` |
4547
| <a id="swift_deps.configure_package-recursive_init_submodules"></a>recursive_init_submodules | Whether to clone submodules recursively in the repository. | Boolean | optional | `True` |
4648

4749
<a id="swift_deps.configure_swift_package"></a>

docs/repository_rules_overview.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ Used to build a local Swift package.
4141

4242
<pre>
4343
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>,
44-
<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>,
45-
<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>, <a href="#swift_package-version">version</a>)
44+
<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>,
45+
<a href="#swift_package-publicly_expose_all_targets">publicly_expose_all_targets</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>,
46+
<a href="#swift_package-shallow_since">shallow_since</a>, <a href="#swift_package-tag">tag</a>, <a href="#swift_package-verbose">verbose</a>, <a href="#swift_package-version">version</a>)
4647
</pre>
4748

4849
Used to download and build an external Swift package.
@@ -64,6 +65,7 @@ Used to download and build an external Swift package.
6465
| <a id="swift_package-patch_cmds_win"></a>patch_cmds_win | Sequence of Powershell commands to be applied on Windows after patches are applied. If this attribute is not set, patch_cmds will be executed on Windows, which requires Bash binary to exist. | List of strings | optional | `[]` |
6566
| <a id="swift_package-patch_tool"></a>patch_tool | The patch(1) utility to use. If this is specified, Bazel will use the specified patch tool instead of the Bazel-native patch implementation. | String | optional | `""` |
6667
| <a id="swift_package-patches"></a>patches | A list of files that are to be applied as patches after extracting the archive. By default, it uses the Bazel-native patch implementation which doesn't support fuzz match and binary patch, but Bazel will fall back to use patch command line tool if `patch_tool` attribute is specified or there are arguments other than `-p` in `patch_args` attribute. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
68+
| <a id="swift_package-publicly_expose_all_targets"></a>publicly_expose_all_targets | Allows to expose internal build targets required for package compilation. The structure and labels of exposed targets may change in future releases without requiring a major version bump. | Boolean | optional | `False` |
6769
| <a id="swift_package-recursive_init_submodules"></a>recursive_init_submodules | Whether to clone submodules recursively in the repository. | Boolean | optional | `True` |
6870
| <a id="swift_package-remote"></a>remote | The version control location from where the repository should be downloaded. | String | required | |
6971
| <a id="swift_package-repo_mapping"></a>repo_mapping | In `WORKSPACE` context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<br><br>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).<br><br>This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | |

swiftpkg/bzlmod/swift_deps.bzl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ load("//swiftpkg/internal:local_swift_package.bzl", "local_swift_package")
55
load("//swiftpkg/internal:pkginfos.bzl", "pkginfos")
66
load("//swiftpkg/internal:repository_utils.bzl", "repository_utils")
77
load("//swiftpkg/internal:swift_deps_info.bzl", "swift_deps_info")
8-
load("//swiftpkg/internal:swift_package.bzl", "PATCH_ATTRS", "swift_package")
8+
load("//swiftpkg/internal:swift_package.bzl", "PATCH_ATTRS", "TOOL_ATTRS", "swift_package")
99
load("//swiftpkg/internal:swift_package_tool.bzl", "SWIFT_PACKAGE_CONFIG_ATTRS")
1010
load("//swiftpkg/internal:swift_package_tool_repo.bzl", "swift_package_tool_repo")
1111

@@ -150,6 +150,16 @@ the Swift package to make it available.\
150150
)
151151
_declare_pkg_from_dependency(dep, config_pkg)
152152

153+
# Add all transitive dependencies to direct_dep_repo_names if `publicly_expose_all_targets` flag is set.
154+
for dep in all_deps_by_id.values():
155+
config_pkg = config_pkgs.get(dep.name) or config_pkgs.get(
156+
bazel_repo_names.from_identity(dep.identity),
157+
)
158+
if config_pkg and config_pkg.publicly_expose_all_targets:
159+
bazel_repo_name = bazel_repo_names.from_identity(dep.identity)
160+
if bazel_repo_name not in direct_dep_repo_names:
161+
direct_dep_repo_names.append(bazel_repo_name)
162+
153163
return direct_dep_repo_names
154164

155165
def _declare_pkg_from_dependency(dep, config_pkg):
@@ -162,6 +172,7 @@ def _declare_pkg_from_dependency(dep, config_pkg):
162172
patch_cmds_win = None
163173
patch_tool = None
164174
patches = None
175+
publicly_expose_all_targets = None
165176
if config_pkg:
166177
init_submodules = config_pkg.init_submodules
167178
recursive_init_submodules = config_pkg.recursive_init_submodules
@@ -170,6 +181,7 @@ def _declare_pkg_from_dependency(dep, config_pkg):
170181
patch_cmds_win = config_pkg.patch_cmds_win
171182
patch_tool = config_pkg.patch_tool
172183
patches = config_pkg.patches
184+
publicly_expose_all_targets = config_pkg.publicly_expose_all_targets
173185

174186
pin = dep.source_control.pin
175187
swift_package(
@@ -186,6 +198,7 @@ def _declare_pkg_from_dependency(dep, config_pkg):
186198
patch_cmds_win = patch_cmds_win,
187199
patch_tool = patch_tool,
188200
patches = patches,
201+
publicly_expose_all_targets = publicly_expose_all_targets,
189202
)
190203

191204
elif dep.file_system:
@@ -291,7 +304,7 @@ The identity (i.e., name in the package's manifest) for the Swift package.\
291304
default = True,
292305
doc = "Whether to clone submodules recursively in the repository.",
293306
),
294-
} | PATCH_ATTRS,
307+
} | PATCH_ATTRS | TOOL_ATTRS,
295308
doc = "Used to add or override settings for a particular Swift package.",
296309
)
297310

swiftpkg/internal/pkginfos.bzl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ def _new_from_parsed_json(
600600

601601
url = None
602602
version = None
603+
expose_build_targets = False
603604
if hasattr(repository_ctx, "attr"):
604605
# We only want to try to collect url and version when called from
605606
# `swift_package`
@@ -609,6 +610,11 @@ def _new_from_parsed_json(
609610
"version",
610611
getattr(repository_ctx.attr, "commit", None),
611612
)
613+
expose_build_targets = getattr(
614+
repository_ctx.attr,
615+
"publicly_expose_all_targets",
616+
False,
617+
)
612618

613619
return _new(
614620
name = dump_manifest["name"],
@@ -624,6 +630,7 @@ def _new_from_parsed_json(
624630
targets = targets,
625631
url = url,
626632
version = version,
633+
expose_build_targets = expose_build_targets,
627634
c_language_standard = dump_manifest.get("cLanguageStandard"),
628635
cxx_language_standard = dump_manifest.get("cxxLanguageStandard"),
629636
)
@@ -641,6 +648,7 @@ def _new(
641648
targets = [],
642649
url = None,
643650
version = None,
651+
expose_build_targets = False,
644652
c_language_standard = None,
645653
cxx_language_standard = None):
646654
"""Returns a `struct` representing information about a Swift package.
@@ -661,6 +669,8 @@ def _new(
661669
`pkginfos.new_target()`.
662670
url: Optional. The url of the package (`string`).
663671
version: Optional. The semantic version of the package (`string`).
672+
expose_build_targets: Optional. Defaults to False. A boolean that specifies whether to expose
673+
the package's internal build targets.
664674
c_language_standard: Optional. The c language standard (e.g. `c99`,
665675
`gnu99`, `c11`).
666676
cxx_language_standard: Optional. The c++ language standard (e.g.
@@ -680,6 +690,7 @@ def _new(
680690
targets = targets,
681691
url = url,
682692
version = version,
693+
expose_build_targets = expose_build_targets,
683694
c_language_standard = c_language_standard,
684695
cxx_language_standard = cxx_language_standard,
685696
)

swiftpkg/internal/swift_package.bzl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,20 @@ PATCH_ATTRS = {
175175
),
176176
}
177177

178+
TOOL_ATTRS = {
179+
"publicly_expose_all_targets": attr.bool(
180+
default = False,
181+
doc = """
182+
Allows to expose internal build targets required for package compilation.
183+
The structure and labels of exposed targets may change in future releases
184+
without requiring a major version bump.
185+
""",
186+
),
187+
}
188+
178189
_ALL_ATTRS = dicts.add(
179190
PATCH_ATTRS,
191+
TOOL_ATTRS,
180192
_GIT_ATTRS,
181193
repo_rules.env_attrs,
182194
repo_rules.swift_attrs,

swiftpkg/internal/swiftpkg_build_files.bzl

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def _new_for_target(repository_ctx, pkg_ctx, target, artifact_infos = []):
2929
lambda ai: ai.artifact_type == artifact_types.xcframework,
3030
)
3131
if xcf_artifact_info != None:
32-
return _xcframework_import_build_file(target, xcf_artifact_info)
32+
return _xcframework_import_build_file(pkg_ctx, target, xcf_artifact_info)
3333

3434
# GH046: Support plugins.
3535
return None
@@ -44,7 +44,7 @@ def _swift_target_build_file(pkg_ctx, target):
4444
attrs = {
4545
"module_name": target.c99name,
4646
"srcs": pkginfo_targets.srcs(target),
47-
"visibility": ["//:__subpackages__"],
47+
"visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets),
4848
}
4949

5050
def _update_attr_list(name, value):
@@ -340,7 +340,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
340340
"alwayslink": True,
341341
"copts": copts,
342342
"srcs": srcs,
343-
"visibility": ["//:__subpackages__"],
343+
"visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets),
344344
}
345345
if clang_src_info.hdrs:
346346
attrs["hdrs"] = clang_src_info.hdrs
@@ -400,7 +400,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
400400
"deps": [],
401401
"hdrs": clang_src_info.hdrs,
402402
"module_name": target.c99name,
403-
"visibility": ["//:__subpackages__"],
403+
"visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets),
404404
},
405405
),
406406
)
@@ -575,7 +575,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
575575
":{}".format(dname)
576576
for dname in child_dep_names
577577
],
578-
"visibility": ["//:__subpackages__"],
578+
"visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets),
579579
}
580580
decls.append(
581581
build_decls.new(
@@ -660,7 +660,7 @@ def _system_library_build_file(target):
660660

661661
# MARK: - Apple xcframework Targets
662662

663-
def _xcframework_import_build_file(target, artifact_info):
663+
def _xcframework_import_build_file(pkg_ctx, target, artifact_info):
664664
attrs = {}
665665
if artifact_info.link_type == link_types.static:
666666
load_stmts = [apple_static_xcframework_import_load_stmt]
@@ -692,7 +692,7 @@ expected: {expected}\
692692
kind = kind,
693693
name = pkginfo_targets.bazel_label_name(target),
694694
attrs = attrs | {
695-
"visibility": ["//:__subpackages__"],
695+
"visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets),
696696
"xcframework_imports": glob,
697697
},
698698
),
@@ -704,7 +704,7 @@ expected: {expected}\
704704

705705
# MARK: - Apple Resource Group
706706

707-
def _apple_resource_bundle(target, package_name, default_localization):
707+
def _apple_resource_bundle(target, package_name, default_localization, expose_build_targets):
708708
bzl_target_name = pkginfo_targets.bazel_label_name(target)
709709
bundle_label_name = pkginfo_targets.resource_bundle_label_name(bzl_target_name)
710710
bundle_name = pkginfo_targets.resource_bundle_name(package_name, target.c99name)
@@ -738,7 +738,7 @@ def _apple_resource_bundle(target, package_name, default_localization):
738738
# Based upon the code in SPM, it looks like they only support unstructured resources.
739739
# https://github.com/apple/swift-package-manager/blob/main/Sources/PackageModel/Resource.swift#L25-L33
740740
"resources": resources,
741-
"visibility": ["//:__subpackages__"],
741+
"visibility": _target_visibility(expose_build_targets),
742742
},
743743
),
744744
]
@@ -753,6 +753,7 @@ def _apple_resource_bundle_for_swift(pkg_ctx, target):
753753
target,
754754
pkg_ctx.pkg_info.name,
755755
pkg_ctx.pkg_info.default_localization,
756+
pkg_ctx.pkg_info.expose_build_targets,
756757
)
757758

758759
# Apparently, SPM provides a `Bundle.module` accessor. So, we do too.
@@ -785,6 +786,7 @@ def _apple_resource_bundle_for_clang(pkg_ctx, target):
785786
target,
786787
pkg_ctx.pkg_info.name,
787788
pkg_ctx.pkg_info.default_localization,
789+
pkg_ctx.pkg_info.expose_build_targets,
788790
)
789791
all_build_files = [apple_res_bundle_info.build_file]
790792
objc_accessor_hdr_label_name = None
@@ -1007,6 +1009,11 @@ def _new_for_license(pkg_info, license):
10071009
decls = decls,
10081010
)
10091011

1012+
# MARK: - Build targets encapsulation
1013+
1014+
def _target_visibility(expose_build_targets):
1015+
return ["//visibility:public"] if expose_build_targets else ["//:__subpackages__"]
1016+
10101017
# MARK: - Constants and API Definition
10111018

10121019
swift_location = "@build_bazel_rules_swift//swift:swift.bzl"

0 commit comments

Comments
 (0)