diff --git a/docs/bzlmod_extensions_overview.md b/docs/bzlmod_extensions_overview.md index ae15d0303..332edf2f3 100755 --- a/docs/bzlmod_extensions_overview.md +++ b/docs/bzlmod_extensions_overview.md @@ -16,7 +16,8 @@ On this page:
swift_deps = use_extension("@rules_swift_package_manager//:extensions.bzl", "swift_deps") swift_deps.configure_package(name, init_submodules, patch_args, patch_cmds, patch_cmds_win, - patch_tool, patches, recursive_init_submodules) + patch_tool, patches, publicly_expose_all_targets, + recursive_init_submodules) swift_deps.configure_swift_package(build_path, cache_path, dependency_caching, manifest_cache, manifest_caching, security_path) swift_deps.from_package(declare_swift_deps_info, declare_swift_package, resolved, swift) @@ -42,6 +43,7 @@ Used to add or override settings for a particular Swift package. | 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 | `[]` | | 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 | `""` | | 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. | List of labels | optional | `[]` | +| 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` | | recursive_init_submodules | Whether to clone submodules recursively in the repository. | Boolean | optional | `True` | diff --git a/docs/repository_rules_overview.md b/docs/repository_rules_overview.md index a69fb31c0..0996274cd 100755 --- a/docs/repository_rules_overview.md +++ b/docs/repository_rules_overview.md @@ -41,8 +41,9 @@ Used to build a local Swift package.swift_package(name, bazel_package_name, branch, commit, dependencies_index, env, init_submodules, - patch_args, patch_cmds, patch_cmds_win, patch_tool, patches, recursive_init_submodules, - remote, repo_mapping, shallow_since, tag, verbose, version) + patch_args, patch_cmds, patch_cmds_win, patch_tool, patches, + publicly_expose_all_targets, recursive_init_submodules, remote, repo_mapping, + shallow_since, tag, verbose, version)Used to download and build an external Swift package. @@ -64,6 +65,7 @@ Used to download and build an external Swift package. | 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 | `[]` | | 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 | `""` | | 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. | List of labels | optional | `[]` | +| 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` | | recursive_init_submodules | Whether to clone submodules recursively in the repository. | Boolean | optional | `True` | | remote | The version control location from where the repository should be downloaded. | String | required | | | 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.
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`).
This attribute is _not_ supported in `MODULE.bazel` context (when invoking a repository rule inside a module extension's implementation function). | Dictionary: String -> String | optional | | diff --git a/swiftpkg/bzlmod/swift_deps.bzl b/swiftpkg/bzlmod/swift_deps.bzl index c5c83465b..44d8d31da 100644 --- a/swiftpkg/bzlmod/swift_deps.bzl +++ b/swiftpkg/bzlmod/swift_deps.bzl @@ -5,7 +5,7 @@ load("//swiftpkg/internal:local_swift_package.bzl", "local_swift_package") load("//swiftpkg/internal:pkginfos.bzl", "pkginfos") load("//swiftpkg/internal:repository_utils.bzl", "repository_utils") 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.bzl", "PATCH_ATTRS", "TOOL_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") @@ -150,6 +150,16 @@ the Swift package to make it available.\ ) _declare_pkg_from_dependency(dep, config_pkg) + # Add all transitive dependencies to direct_dep_repo_names if `publicly_expose_all_targets` flag is set. + for dep in all_deps_by_id.values(): + config_pkg = config_pkgs.get(dep.name) or config_pkgs.get( + bazel_repo_names.from_identity(dep.identity), + ) + if config_pkg and config_pkg.publicly_expose_all_targets: + bazel_repo_name = bazel_repo_names.from_identity(dep.identity) + if bazel_repo_name not in direct_dep_repo_names: + direct_dep_repo_names.append(bazel_repo_name) + return direct_dep_repo_names def _declare_pkg_from_dependency(dep, config_pkg): @@ -162,6 +172,7 @@ def _declare_pkg_from_dependency(dep, config_pkg): patch_cmds_win = None patch_tool = None patches = None + publicly_expose_all_targets = None if config_pkg: init_submodules = config_pkg.init_submodules recursive_init_submodules = config_pkg.recursive_init_submodules @@ -170,6 +181,7 @@ def _declare_pkg_from_dependency(dep, config_pkg): patch_cmds_win = config_pkg.patch_cmds_win patch_tool = config_pkg.patch_tool patches = config_pkg.patches + publicly_expose_all_targets = config_pkg.publicly_expose_all_targets pin = dep.source_control.pin swift_package( @@ -186,6 +198,7 @@ def _declare_pkg_from_dependency(dep, config_pkg): patch_cmds_win = patch_cmds_win, patch_tool = patch_tool, patches = patches, + publicly_expose_all_targets = publicly_expose_all_targets, ) elif dep.file_system: @@ -291,7 +304,7 @@ The identity (i.e., name in the package's manifest) for the Swift package.\ default = True, doc = "Whether to clone submodules recursively in the repository.", ), - } | PATCH_ATTRS, + } | PATCH_ATTRS | TOOL_ATTRS, doc = "Used to add or override settings for a particular Swift package.", ) diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 08aa9a413..ab15f134b 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -600,6 +600,7 @@ def _new_from_parsed_json( url = None version = None + expose_build_targets = False if hasattr(repository_ctx, "attr"): # We only want to try to collect url and version when called from # `swift_package` @@ -609,6 +610,11 @@ def _new_from_parsed_json( "version", getattr(repository_ctx.attr, "commit", None), ) + expose_build_targets = getattr( + repository_ctx.attr, + "publicly_expose_all_targets", + False, + ) return _new( name = dump_manifest["name"], @@ -624,6 +630,7 @@ def _new_from_parsed_json( targets = targets, url = url, version = version, + expose_build_targets = expose_build_targets, c_language_standard = dump_manifest.get("cLanguageStandard"), cxx_language_standard = dump_manifest.get("cxxLanguageStandard"), ) @@ -641,6 +648,7 @@ def _new( targets = [], url = None, version = None, + expose_build_targets = False, c_language_standard = None, cxx_language_standard = None): """Returns a `struct` representing information about a Swift package. @@ -661,6 +669,8 @@ def _new( `pkginfos.new_target()`. url: Optional. The url of the package (`string`). version: Optional. The semantic version of the package (`string`). + expose_build_targets: Optional. Defaults to False. A boolean that specifies whether to expose + the package's internal build targets. c_language_standard: Optional. The c language standard (e.g. `c99`, `gnu99`, `c11`). cxx_language_standard: Optional. The c++ language standard (e.g. @@ -680,6 +690,7 @@ def _new( targets = targets, url = url, version = version, + expose_build_targets = expose_build_targets, c_language_standard = c_language_standard, cxx_language_standard = cxx_language_standard, ) diff --git a/swiftpkg/internal/swift_package.bzl b/swiftpkg/internal/swift_package.bzl index fb21b87af..e45ee856c 100644 --- a/swiftpkg/internal/swift_package.bzl +++ b/swiftpkg/internal/swift_package.bzl @@ -175,8 +175,20 @@ PATCH_ATTRS = { ), } +TOOL_ATTRS = { + "publicly_expose_all_targets": attr.bool( + default = False, + doc = """ +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. +""", + ), +} + _ALL_ATTRS = dicts.add( PATCH_ATTRS, + TOOL_ATTRS, _GIT_ATTRS, repo_rules.env_attrs, repo_rules.swift_attrs, diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index ba81c654c..3d5b8ad4f 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -29,7 +29,7 @@ def _new_for_target(repository_ctx, pkg_ctx, target, artifact_infos = []): lambda ai: ai.artifact_type == artifact_types.xcframework, ) if xcf_artifact_info != None: - return _xcframework_import_build_file(target, xcf_artifact_info) + return _xcframework_import_build_file(pkg_ctx, target, xcf_artifact_info) # GH046: Support plugins. return None @@ -44,7 +44,7 @@ def _swift_target_build_file(pkg_ctx, target): attrs = { "module_name": target.c99name, "srcs": pkginfo_targets.srcs(target), - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets), } def _update_attr_list(name, value): @@ -340,7 +340,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): "alwayslink": True, "copts": copts, "srcs": srcs, - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets), } if clang_src_info.hdrs: attrs["hdrs"] = clang_src_info.hdrs @@ -400,7 +400,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): "deps": [], "hdrs": clang_src_info.hdrs, "module_name": target.c99name, - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets), }, ), ) @@ -575,7 +575,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): ":{}".format(dname) for dname in child_dep_names ], - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets), } decls.append( build_decls.new( @@ -660,7 +660,7 @@ def _system_library_build_file(target): # MARK: - Apple xcframework Targets -def _xcframework_import_build_file(target, artifact_info): +def _xcframework_import_build_file(pkg_ctx, target, artifact_info): attrs = {} if artifact_info.link_type == link_types.static: load_stmts = [apple_static_xcframework_import_load_stmt] @@ -692,7 +692,7 @@ expected: {expected}\ kind = kind, name = pkginfo_targets.bazel_label_name(target), attrs = attrs | { - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(pkg_ctx.pkg_info.expose_build_targets), "xcframework_imports": glob, }, ), @@ -704,7 +704,7 @@ expected: {expected}\ # MARK: - Apple Resource Group -def _apple_resource_bundle(target, package_name, default_localization): +def _apple_resource_bundle(target, package_name, default_localization, expose_build_targets): bzl_target_name = pkginfo_targets.bazel_label_name(target) bundle_label_name = pkginfo_targets.resource_bundle_label_name(bzl_target_name) bundle_name = pkginfo_targets.resource_bundle_name(package_name, target.c99name) @@ -738,7 +738,7 @@ def _apple_resource_bundle(target, package_name, default_localization): # Based upon the code in SPM, it looks like they only support unstructured resources. # https://github.com/apple/swift-package-manager/blob/main/Sources/PackageModel/Resource.swift#L25-L33 "resources": resources, - "visibility": ["//:__subpackages__"], + "visibility": _target_visibility(expose_build_targets), }, ), ] @@ -753,6 +753,7 @@ def _apple_resource_bundle_for_swift(pkg_ctx, target): target, pkg_ctx.pkg_info.name, pkg_ctx.pkg_info.default_localization, + pkg_ctx.pkg_info.expose_build_targets, ) # Apparently, SPM provides a `Bundle.module` accessor. So, we do too. @@ -785,6 +786,7 @@ def _apple_resource_bundle_for_clang(pkg_ctx, target): target, pkg_ctx.pkg_info.name, pkg_ctx.pkg_info.default_localization, + pkg_ctx.pkg_info.expose_build_targets, ) all_build_files = [apple_res_bundle_info.build_file] objc_accessor_hdr_label_name = None @@ -1007,6 +1009,11 @@ def _new_for_license(pkg_info, license): decls = decls, ) +# MARK: - Build targets encapsulation + +def _target_visibility(expose_build_targets): + return ["//visibility:public"] if expose_build_targets else ["//:__subpackages__"] + # MARK: - Constants and API Definition swift_location = "@build_bazel_rules_swift//swift:swift.bzl" diff --git a/swiftpkg/tests/swiftpkg_build_files_tests.bzl b/swiftpkg/tests/swiftpkg_build_files_tests.bzl index 2c83ae21a..3a43d9c9b 100644 --- a/swiftpkg/tests/swiftpkg_build_files_tests.bzl +++ b/swiftpkg/tests/swiftpkg_build_files_tests.bzl @@ -30,454 +30,458 @@ load(":testutils.bzl", "testutils") _repo_name = "@swiftpkg_mypackage" -_pkg_info = pkginfos.new( - name = "MyPackage", - path = "/path/to/my-package", - tools_version = "5.9", - url = "https://github.com/my/package", - version = "0.4.2", - dependencies = [ - pkginfos.new_dependency( - identity = "swift-argument-parser", - name = "SwiftArgumentParser", - source_control = pkginfos.new_source_control( - pin = pkginfos.new_pin( - identity = "swift-argument-parser", - kind = "remoteSourceControl", - location = "https://github.com/apple/swift-argument-parser", - state = pkginfos.new_pin_state( - revision = "6c89474e62719ddcc1e9614989fff2f68208fe10", - version = "1.0.0", +def _pkg_info( + expose_build_targets = False): + return pkginfos.new( + name = "MyPackage", + path = "/path/to/my-package", + tools_version = "5.9", + url = "https://github.com/my/package", + version = "0.4.2", + dependencies = [ + pkginfos.new_dependency( + identity = "swift-argument-parser", + name = "SwiftArgumentParser", + source_control = pkginfos.new_source_control( + pin = pkginfos.new_pin( + identity = "swift-argument-parser", + kind = "remoteSourceControl", + location = "https://github.com/apple/swift-argument-parser", + state = pkginfos.new_pin_state( + revision = "6c89474e62719ddcc1e9614989fff2f68208fe10", + version = "1.0.0", + ), ), ), ), - ), - ], - products = [ - pkginfos.new_product( - name = "oldstyleexec", - type = pkginfos.new_product_type(executable = True), - targets = ["RegularTargetForExec"], - ), - pkginfos.new_product( - name = "RegularSwiftTargetAsLibrary", - type = pkginfos.new_product_type( - library = pkginfos.new_library_type( - library_type_kinds.automatic, - ), + ], + products = [ + pkginfos.new_product( + name = "oldstyleexec", + type = pkginfos.new_product_type(executable = True), + targets = ["RegularTargetForExec"], ), - targets = ["RegularSwiftTargetAsLibrary"], - ), - pkginfos.new_product( - name = "ObjcLibraryWithModulemap", - type = pkginfos.new_product_type( - library = pkginfos.new_library_type( - library_type_kinds.automatic, + pkginfos.new_product( + name = "RegularSwiftTargetAsLibrary", + type = pkginfos.new_product_type( + library = pkginfos.new_library_type( + library_type_kinds.automatic, + ), ), + targets = ["RegularSwiftTargetAsLibrary"], ), - targets = ["ObjcLibraryWithModulemap"], - ), - pkginfos.new_product( - name = "swiftexec", - type = pkginfos.new_product_type(executable = True), - targets = ["SwiftExecutableTarget"], - ), - ], - targets = [ - # Old-style regular library that is used to create a binary from an - # executable product. - pkginfos.new_target( - name = "RegularTargetForExec", - type = "regular", - c99name = "RegularTargetForExec", - module_type = "SwiftTarget", - path = "Source/RegularTargetForExec", - sources = [ - "main.swift", - ], - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference( - "RegularSwiftTargetAsLibrary", + pkginfos.new_product( + name = "ObjcLibraryWithModulemap", + type = pkginfos.new_product_type( + library = pkginfos.new_library_type( + library_type_kinds.automatic, ), ), - ], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "RegularSwiftTargetAsLibrary", - type = "regular", - c99name = "RegularSwiftTargetAsLibrary", - module_type = "SwiftTarget", - path = "Source/RegularSwiftTargetAsLibrary", - sources = [ - "RegularSwiftTargetAsLibrary.swift", - ], - dependencies = [], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "RegularSwiftTargetAsLibraryTests", - type = "test", - c99name = "RegularSwiftTargetAsLibraryTests", - module_type = "SwiftTarget", - path = "Tests/RegularSwiftTargetAsLibraryTests", - sources = [ - "RegularSwiftTargetAsLibraryTests.swift", - ], - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference( - "RegularSwiftTargetAsLibrary", + targets = ["ObjcLibraryWithModulemap"], + ), + pkginfos.new_product( + name = "swiftexec", + type = pkginfos.new_product_type(executable = True), + targets = ["SwiftExecutableTarget"], + ), + ], + targets = [ + # Old-style regular library that is used to create a binary from an + # executable product. + pkginfos.new_target( + name = "RegularTargetForExec", + type = "regular", + c99name = "RegularTargetForExec", + module_type = "SwiftTarget", + path = "Source/RegularTargetForExec", + sources = [ + "main.swift", + ], + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference( + "RegularSwiftTargetAsLibrary", + ), ), - ), - ], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "SwiftExecutableTarget", - type = "executable", - c99name = "SwiftExecutableTarget", - module_type = "SwiftTarget", - path = "Source/SwiftExecutableTarget", - sources = ["main.swift"], - dependencies = [], - swift_settings = pkginfos.new_swift_settings([ - pkginfos.new_build_setting( - kind = build_setting_kinds.define, - values = ["FOOBAR"], - condition = pkginfos.new_build_setting_condition( - platforms = [ - spm_platforms.ios, - spm_platforms.tvos, - ], + ], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), + ), + pkginfos.new_target( + name = "RegularSwiftTargetAsLibrary", + type = "regular", + c99name = "RegularSwiftTargetAsLibrary", + module_type = "SwiftTarget", + path = "Source/RegularSwiftTargetAsLibrary", + sources = [ + "RegularSwiftTargetAsLibrary.swift", + ], + dependencies = [], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), + ), + pkginfos.new_target( + name = "RegularSwiftTargetAsLibraryTests", + type = "test", + c99name = "RegularSwiftTargetAsLibraryTests", + module_type = "SwiftTarget", + path = "Tests/RegularSwiftTargetAsLibraryTests", + sources = [ + "RegularSwiftTargetAsLibraryTests.swift", + ], + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference( + "RegularSwiftTargetAsLibrary", + ), ), - ), - pkginfos.new_build_setting( - kind = build_setting_kinds.experimental_features, - values = ["BuiltinModule"], - ), - pkginfos.new_build_setting( - kind = build_setting_kinds.unsafe_flags, - values = ["-cross-module-optimization"], - condition = pkginfos.new_build_setting_condition( - configuration = spm_configurations.release, + ], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), + ), + pkginfos.new_target( + name = "SwiftExecutableTarget", + type = "executable", + c99name = "SwiftExecutableTarget", + module_type = "SwiftTarget", + path = "Source/SwiftExecutableTarget", + sources = ["main.swift"], + dependencies = [], + swift_settings = pkginfos.new_swift_settings([ + pkginfos.new_build_setting( + kind = build_setting_kinds.define, + values = ["FOOBAR"], + condition = pkginfos.new_build_setting_condition( + platforms = [ + spm_platforms.ios, + spm_platforms.tvos, + ], + ), ), - ), - ]), - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "ClangLibrary", - type = "regular", - c99name = "ClangLibrary", - module_type = "ClangTarget", - path = ".", - # NOTE: SPM does not report header files in the sources for clang - # targets. The `swift_package` code reads the filesystem to find - # the sources. - sources = [ - "src/foo.cc", - ], - source_paths = [ - "src/", - ], - exclude_paths = [ - "src/do_not_include_me.cc", - ], - public_hdrs_path = "include", - dependencies = [], - clang_settings = pkginfos.new_clang_settings([ - pkginfos.new_build_setting( - kind = build_setting_kinds.define, - values = ["PLATFORM_POSIX=1"], - ), - pkginfos.new_build_setting( - kind = build_setting_kinds.header_search_path, - values = ["./"], - ), - pkginfos.new_build_setting( - kind = build_setting_kinds.unsafe_flags, - values = ["-danger"], - condition = pkginfos.new_build_setting_condition( - configuration = spm_configurations.release, + pkginfos.new_build_setting( + kind = build_setting_kinds.experimental_features, + values = ["BuiltinModule"], ), - ), - ]), - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ + pkginfos.new_build_setting( + kind = build_setting_kinds.unsafe_flags, + values = ["-cross-module-optimization"], + condition = pkginfos.new_build_setting_condition( + configuration = spm_configurations.release, + ), + ), + ]), + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), + ), + pkginfos.new_target( + name = "ClangLibrary", + type = "regular", + c99name = "ClangLibrary", + module_type = "ClangTarget", + path = ".", + # NOTE: SPM does not report header files in the sources for clang + # targets. The `swift_package` code reads the filesystem to find + # the sources. + sources = [ "src/foo.cc", - "src/foo.h", ], - public_includes = ["include"], - private_includes = ["src"], - textual_hdrs = ["src/foo.cc"], - ), - ), - pkginfos.new_target( - name = "ObjcLibraryDep", - type = "regular", - c99name = "ObjcLibraryDep", - module_type = "ClangTarget", - path = ".", - sources = [ - "objc_dep/foo.m", - "objc_dep/foo.h", - ], - source_paths = [ - "objc_dep/", - ], - public_hdrs_path = "include", - dependencies = [], - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ - "src/foo.m", - "src/foo.h", + source_paths = [ + "src/", ], + exclude_paths = [ + "src/do_not_include_me.cc", + ], + public_hdrs_path = "include", + dependencies = [], + clang_settings = pkginfos.new_clang_settings([ + pkginfos.new_build_setting( + kind = build_setting_kinds.define, + values = ["PLATFORM_POSIX=1"], + ), + pkginfos.new_build_setting( + kind = build_setting_kinds.header_search_path, + values = ["./"], + ), + pkginfos.new_build_setting( + kind = build_setting_kinds.unsafe_flags, + values = ["-danger"], + condition = pkginfos.new_build_setting_condition( + configuration = spm_configurations.release, + ), + ), + ]), + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.cc", + "src/foo.h", + ], + public_includes = ["include"], + private_includes = ["src"], + textual_hdrs = ["src/foo.cc"], + ), ), - objc_src_info = pkginfos.new_objc_src_info(), - ), - pkginfos.new_target( - name = "ObjcLibrary", - type = "regular", - c99name = "ObjcLibrary", - module_type = "ClangTarget", - path = ".", - # NOTE: SPM does not report header files in the sources for clang - # targets. The `swift_package` code reads the filesystem to find - # the sources. - sources = [ - "src/foo.m", - "src/foo.h", - ], - source_paths = [ - "src/", - ], - public_hdrs_path = "include", - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), + pkginfos.new_target( + name = "ObjcLibraryDep", + type = "regular", + c99name = "ObjcLibraryDep", + module_type = "ClangTarget", + path = ".", + sources = [ + "objc_dep/foo.m", + "objc_dep/foo.h", + ], + source_paths = [ + "objc_dep/", + ], + public_hdrs_path = "include", + dependencies = [], + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.m", + "src/foo.h", + ], ), - ], - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ - "src/foo.h", + objc_src_info = pkginfos.new_objc_src_info(), + ), + pkginfos.new_target( + name = "ObjcLibrary", + type = "regular", + c99name = "ObjcLibrary", + module_type = "ClangTarget", + path = ".", + # NOTE: SPM does not report header files in the sources for clang + # targets. The `swift_package` code reads the filesystem to find + # the sources. + sources = [ "src/foo.m", + "src/foo.h", ], - public_includes = ["include"], - private_includes = ["src"], - textual_hdrs = ["src/foo.m"], - ), - objc_src_info = pkginfos.new_objc_src_info( - builtin_frameworks = [ - "Foundation", - "UIKit", + source_paths = [ + "src/", ], - ), - ), - pkginfos.new_target( - name = "ObjcLibraryWithModulemap", - type = "regular", - c99name = "ObjcLibraryWithModulemap", - module_type = "ClangTarget", - path = ".", - # NOTE: SPM does not report header files in the sources for clang - # targets. The `swift_package` code reads the filesystem to find - # the sources. - sources = [ - "src/foo.m", - "src/foo.h", - ], - source_paths = [ - "src/", - ], - public_hdrs_path = "include", - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), + public_hdrs_path = "include", + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), + ), + ], + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.h", + "src/foo.m", + ], + public_includes = ["include"], + private_includes = ["src"], + textual_hdrs = ["src/foo.m"], ), - ], - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ - "src/foo.h", + objc_src_info = pkginfos.new_objc_src_info( + builtin_frameworks = [ + "Foundation", + "UIKit", + ], + ), + ), + pkginfos.new_target( + name = "ObjcLibraryWithModulemap", + type = "regular", + c99name = "ObjcLibraryWithModulemap", + module_type = "ClangTarget", + path = ".", + # NOTE: SPM does not report header files in the sources for clang + # targets. The `swift_package` code reads the filesystem to find + # the sources. + sources = [ "src/foo.m", + "src/foo.h", ], - public_includes = ["include"], - private_includes = ["src"], - textual_hdrs = ["src/foo.m"], - modulemap_path = "include/module.modulemap", - ), - objc_src_info = pkginfos.new_objc_src_info( - builtin_frameworks = [ - "Foundation", - "UIKit", + source_paths = [ + "src/", ], - ), - ), - pkginfos.new_target( - name = "SwiftLibraryWithConditionalDep", - type = "regular", - c99name = "SwiftLibraryWithConditionalDep", - module_type = "SwiftTarget", - path = "Source/SwiftLibraryWithConditionalDep", - sources = [ - "SwiftLibraryWithConditionalDep.swift", - ], - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference("ClangLibrary"), - ), - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference( - "RegularSwiftTargetAsLibrary", - condition = pkginfos.new_target_dependency_condition( - platforms = ["ios", "tvos"], - ), + public_hdrs_path = "include", + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), ), + ], + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.h", + "src/foo.m", + ], + public_includes = ["include"], + private_includes = ["src"], + textual_hdrs = ["src/foo.m"], + modulemap_path = "include/module.modulemap", ), - ], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "ClangLibraryWithConditionalDep", - type = "regular", - c99name = "ClangLibraryWithConditionalDep", - module_type = "ClangTarget", - path = ".", - # NOTE: SPM does not report header files in the sources for clang - # targets. The `swift_package` code reads the filesystem to find - # the sources. - sources = [ - "src/foo.cc", - ], - source_paths = [ - "src/", - ], - public_hdrs_path = "include", - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference( - "ClangLibrary", - condition = pkginfos.new_target_dependency_condition( - platforms = ["ios", "tvos"], + objc_src_info = pkginfos.new_objc_src_info( + builtin_frameworks = [ + "Foundation", + "UIKit", + ], + ), + ), + pkginfos.new_target( + name = "SwiftLibraryWithConditionalDep", + type = "regular", + c99name = "SwiftLibraryWithConditionalDep", + module_type = "SwiftTarget", + path = "Source/SwiftLibraryWithConditionalDep", + sources = [ + "SwiftLibraryWithConditionalDep.swift", + ], + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference("ClangLibrary"), + ), + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference( + "RegularSwiftTargetAsLibrary", + condition = pkginfos.new_target_dependency_condition( + platforms = ["ios", "tvos"], + ), ), ), - ), - ], - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ - "src/foo.cc", - "src/foo.h", ], - public_includes = ["include"], - private_includes = ["src"], - textual_hdrs = ["src/foo.cc"], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), ), - ), - pkginfos.new_target( - name = "SwiftForObjcTarget", - type = "regular", - c99name = "SwiftForObjcTarget", - module_type = "SwiftTarget", - path = "Source/SwiftForObjcTarget", - sources = [ - "SwiftForObjcTarget.swift", - ], - dependencies = [ - pkginfos.new_target_dependency( - by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), - ), - ], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(has_objc_directive = True), - ), - pkginfos.new_target( - name = "SwiftLibraryWithFilePathResource", - type = "regular", - c99name = "SwiftLibraryWithFilePathResource", - module_type = "SwiftTarget", - path = "Source/SwiftLibraryWithFilePathResource", - sources = [ - "SwiftLibraryWithFilePathResource.swift", - ], - resources = [ - pkginfos.new_resource( - path = "Source/SwiftLibraryWithFilePathResource/Resources/chicken.json", - rule = pkginfos.new_resource_rule( - process = pkginfos.new_resource_rule_process(), + pkginfos.new_target( + name = "ClangLibraryWithConditionalDep", + type = "regular", + c99name = "ClangLibraryWithConditionalDep", + module_type = "ClangTarget", + path = ".", + # NOTE: SPM does not report header files in the sources for clang + # targets. The `swift_package` code reads the filesystem to find + # the sources. + sources = [ + "src/foo.cc", + ], + source_paths = [ + "src/", + ], + public_hdrs_path = "include", + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference( + "ClangLibrary", + condition = pkginfos.new_target_dependency_condition( + platforms = ["ios", "tvos"], + ), + ), ), + ], + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.cc", + "src/foo.h", + ], + public_includes = ["include"], + private_includes = ["src"], + textual_hdrs = ["src/foo.cc"], ), - ], - dependencies = [], - repo_name = _repo_name, - swift_src_info = pkginfos.new_swift_src_info(), - ), - pkginfos.new_target( - name = "ObjcLibraryWithResources", - type = "regular", - c99name = "ObjcLibraryWithResources", - module_type = "ClangTarget", - path = ".", - # NOTE: SPM does not report header files in the sources for clang - # targets. The `swift_package` code reads the filesystem to find - # the sources. - sources = [ - "src/foo.m", - "src/foo.h", - ], - source_paths = [ - "src/", - ], - public_hdrs_path = "include", - resources = [ - pkginfos.new_resource( - path = "Source/ObjcLibraryWithResources/Resources/chicken.json", - rule = pkginfos.new_resource_rule( - process = pkginfos.new_resource_rule_process(), + ), + pkginfos.new_target( + name = "SwiftForObjcTarget", + type = "regular", + c99name = "SwiftForObjcTarget", + module_type = "SwiftTarget", + path = "Source/SwiftForObjcTarget", + sources = [ + "SwiftForObjcTarget.swift", + ], + dependencies = [ + pkginfos.new_target_dependency( + by_name = pkginfos.new_by_name_reference("ObjcLibraryDep"), + ), + ], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(has_objc_directive = True), + ), + pkginfos.new_target( + name = "SwiftLibraryWithFilePathResource", + type = "regular", + c99name = "SwiftLibraryWithFilePathResource", + module_type = "SwiftTarget", + path = "Source/SwiftLibraryWithFilePathResource", + sources = [ + "SwiftLibraryWithFilePathResource.swift", + ], + resources = [ + pkginfos.new_resource( + path = "Source/SwiftLibraryWithFilePathResource/Resources/chicken.json", + rule = pkginfos.new_resource_rule( + process = pkginfos.new_resource_rule_process(), + ), ), - ), - ], - dependencies = [], - repo_name = _repo_name, - clang_src_info = pkginfos.new_clang_src_info( - hdrs = ["include/external.h"], - srcs = [ - "src/foo.h", - "src/foo.m", ], - public_includes = ["include"], - private_includes = ["src"], - textual_hdrs = ["src/foo.m"], + dependencies = [], + repo_name = _repo_name, + swift_src_info = pkginfos.new_swift_src_info(), ), - objc_src_info = pkginfos.new_objc_src_info( - builtin_frameworks = [ - "Foundation", - "UIKit", + pkginfos.new_target( + name = "ObjcLibraryWithResources", + type = "regular", + c99name = "ObjcLibraryWithResources", + module_type = "ClangTarget", + path = ".", + # NOTE: SPM does not report header files in the sources for clang + # targets. The `swift_package` code reads the filesystem to find + # the sources. + sources = [ + "src/foo.m", + "src/foo.h", ], + source_paths = [ + "src/", + ], + public_hdrs_path = "include", + resources = [ + pkginfos.new_resource( + path = "Source/ObjcLibraryWithResources/Resources/chicken.json", + rule = pkginfos.new_resource_rule( + process = pkginfos.new_resource_rule_process(), + ), + ), + ], + dependencies = [], + repo_name = _repo_name, + clang_src_info = pkginfos.new_clang_src_info( + hdrs = ["include/external.h"], + srcs = [ + "src/foo.h", + "src/foo.m", + ], + public_includes = ["include"], + private_includes = ["src"], + textual_hdrs = ["src/foo.m"], + ), + objc_src_info = pkginfos.new_objc_src_info( + builtin_frameworks = [ + "Foundation", + "UIKit", + ], + ), ), - ), - ], -) + ], + expose_build_targets = expose_build_targets, + ) -_pkg_ctx = pkg_ctxs.new( - pkg_info = _pkg_info, - repo_name = _repo_name, -) +def _pkg_ctx(pkg_info): + return pkg_ctxs.new( + pkg_info = pkg_info, + repo_name = _repo_name, + ) # MARK: - Tests @@ -488,6 +492,7 @@ def _target_generation_test(ctx): struct( msg = "Swift library target", name = "RegularSwiftTargetAsLibrary", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") @@ -514,6 +519,7 @@ swift_library( struct( msg = "Swift regular target associated with executable product", name = "RegularTargetForExec", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") @@ -538,6 +544,7 @@ swift_library( struct( msg = "Swift test target", name = "RegularSwiftTargetAsLibraryTests", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_test") @@ -559,6 +566,7 @@ swift_test( struct( msg = "Swift executable target", name = "SwiftExecutableTarget", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_binary") @@ -590,6 +598,7 @@ swift_binary( struct( msg = "simple clang target", name = "ClangLibrary", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint") load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap") @@ -648,6 +657,7 @@ swift_interop_hint( struct( msg = "Objc target", name = "ObjcLibrary", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint") load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap") @@ -719,6 +729,7 @@ swift_interop_hint( struct( msg = "Objc target with a modulemap", name = "ObjcLibraryWithModulemap", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint") @@ -778,6 +789,7 @@ swift_interop_hint( struct( msg = "Swift target with conditional dep", name = "SwiftLibraryWithConditionalDep", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") @@ -806,6 +818,7 @@ swift_library( struct( msg = "Clang target with conditional dep", name = "ClangLibraryWithConditionalDep", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint") load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap") @@ -864,6 +877,7 @@ swift_interop_hint( struct( msg = "Swift library target with @objc directives and Objc dep", name = "SwiftForObjcTarget", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") @@ -890,6 +904,7 @@ swift_library( struct( msg = "Swift library target with file path resource", name = "SwiftLibraryWithFilePathResource", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle") load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") @@ -937,6 +952,7 @@ swift_library( struct( msg = "Objc target with resources", name = "ObjcLibraryWithResources", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle") load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint") @@ -1032,20 +1048,72 @@ swift_interop_hint( module_map = "ObjcLibraryWithResources.rspm_modulemap", module_name = "ObjcLibraryWithResources", ) +""", + ), + struct( + msg = "Swift library target with default visibility", + name = "RegularSwiftTargetAsLibrary", + pkg_info = _pkg_info( + expose_build_targets = False, + ), + exp = """\ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "RegularSwiftTargetAsLibrary.rspm", + always_include_developer_search_paths = True, + alwayslink = True, + copts = [ + "-DSWIFT_PACKAGE", + "-Xcc", + "-DSWIFT_PACKAGE", + ], + module_name = "RegularSwiftTargetAsLibrary", + package_name = "MyPackage", + srcs = ["Source/RegularSwiftTargetAsLibrary/RegularSwiftTargetAsLibrary.swift"], + tags = ["manual"], + visibility = ["//:__subpackages__"], +) +""", + ), + struct( + msg = "Swift library target with public visibility", + name = "RegularSwiftTargetAsLibrary", + pkg_info = _pkg_info( + expose_build_targets = True, + ), + exp = """\ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "RegularSwiftTargetAsLibrary.rspm", + always_include_developer_search_paths = True, + alwayslink = True, + copts = [ + "-DSWIFT_PACKAGE", + "-Xcc", + "-DSWIFT_PACKAGE", + ], + module_name = "RegularSwiftTargetAsLibrary", + package_name = "MyPackage", + srcs = ["Source/RegularSwiftTargetAsLibrary/RegularSwiftTargetAsLibrary.swift"], + tags = ["manual"], + visibility = ["//visibility:public"], +) """, ), ] for t in tests: - target = pkginfo_targets.get(_pkg_info.targets, t.name) + target = pkginfo_targets.get(t.pkg_info.targets, t.name) repository_ctx = testutils.new_stub_repository_ctx( repo_name = _repo_name[1:], file_contents = { - paths.normalize(paths.join(_pkg_info.path, target.path, fname)): cnts + paths.normalize(paths.join(t.pkg_info.path, target.path, fname)): cnts for fname, cnts in getattr(t, "file_contents", {}).items() }, find_results = { - paths.normalize(paths.join(_pkg_info.path, dirname)): [ - paths.normalize(paths.join(_pkg_info.path, dirname, fp)) + paths.normalize(paths.join(t.pkg_info.path, dirname)): [ + paths.normalize(paths.join(t.pkg_info.path, dirname, fp)) for fp in file_paths ] for dirname, file_paths in getattr(t, "find_results", {}).items() @@ -1056,7 +1124,7 @@ swift_interop_hint( }, ) actual = scg.to_starlark( - swiftpkg_build_files.new_for_target(repository_ctx, _pkg_ctx, target), + swiftpkg_build_files.new_for_target(repository_ctx, _pkg_ctx(t.pkg_info), target), ) asserts.equals(env, t.exp, actual, t.msg) @@ -1071,6 +1139,7 @@ def _product_generation_test(ctx): struct( msg = "executable product referencing a regular target (old-style)", name = "oldstyleexec", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_binary") @@ -1084,6 +1153,7 @@ swift_binary( struct( msg = "Swift library product", name = "RegularSwiftTargetAsLibrary", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library_group") @@ -1097,6 +1167,7 @@ swift_library_group( struct( msg = "ObjC library with modulemap product", name = "ObjcLibraryWithModulemap", + pkg_info = _pkg_info(), exp = """\ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library_group") @@ -1110,6 +1181,7 @@ swift_library_group( struct( msg = "Swift exectable product", name = "swiftexec", + pkg_info = _pkg_info(), exp = """\ alias( @@ -1121,10 +1193,10 @@ alias( ), ] for t in tests: - product = lists.find(_pkg_info.products, lambda p: p.name == t.name) + product = lists.find(t.pkg_info.products, lambda p: p.name == t.name) actual = scg.to_starlark( swiftpkg_build_files.new_for_product( - pkg_ctx = _pkg_ctx, + pkg_ctx = _pkg_ctx(t.pkg_info), product = product, ), ) @@ -1141,6 +1213,7 @@ def _license_generation_test(ctx): struct( msg = "No license", license = None, + pkg_info = _pkg_info(), exp = """\ load("@rules_license//rules:package_info.bzl", "package_info") @@ -1159,6 +1232,7 @@ package_info( struct( msg = "Markdown license", license = "LICENSE.md", + pkg_info = _pkg_info(), exp = """\ load("@rules_license//rules:package_info.bzl", "package_info") load("@rules_license//rules:license.bzl", "license") @@ -1186,6 +1260,7 @@ license( struct( msg = "License", license = "LICENSE", + pkg_info = _pkg_info(), exp = """\ load("@rules_license//rules:package_info.bzl", "package_info") load("@rules_license//rules:license.bzl", "license") @@ -1214,7 +1289,7 @@ license( for t in tests: actual = scg.to_starlark( swiftpkg_build_files.new_for_license( - pkg_info = _pkg_info, + pkg_info = t.pkg_info, license = t.license, ), )