diff --git a/CHANGELOG.md b/CHANGELOG.md index 64858100b..aad7b1f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,7 @@ END_UNRELEASED_TEMPLATE ### New -* TBD +* Added `xcodeproj_extra_files` aspect hint: [#3150](https://github.com/MobileNativeFoundation/rules_xcodeproj/pull/3150) ### Adjusted diff --git a/docs/BUILD b/docs/BUILD index 3cc8d16d6..395cc6393 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -6,6 +6,7 @@ load("@rules_shell//shell:sh_binary.bzl", "sh_binary") # Generating _DOC_COMPONENTS = [ + "aspect_hints", "project_options", "providers", "top_level_target", @@ -35,6 +36,7 @@ genrule( ":xcschemes", ":xcode_build_settings", ":providers", + ":aspect_hints", ], outs = ["bazel.generated.md"], cmd = """\ diff --git a/docs/bazel.md b/docs/bazel.md index 246f15918..655017e70 100755 --- a/docs/bazel.md +++ b/docs/bazel.md @@ -50,6 +50,8 @@ load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj") - [Providers](#providers) - [`XcodeProjAutomaticTargetProcessingInfo`](#XcodeProjAutomaticTargetProcessingInfo) - [`XcodeProjInfo`](#XcodeProjInfo) +- [Aspect Hints](#aspect-hints) + - [`xcodeproj_extra_files`](#xcodeproj_extra_files) # Core @@ -814,3 +816,47 @@ Provides information needed to generate an Xcode project. | xcode_targets | A `depset` of values from `xcode_targets.make`, which potentially will become targets in the Xcode project. | +# Aspect Hints + +Aspect hints that can be used to provide additional information during project generation. + + + +## xcodeproj_extra_files + +
+xcodeproj_extra_files(name, files) ++ +This rule is used to surface extra files that should be included in the Xcode +project navigator, but otherwise aren't inputs to a target. The provider +created by this rule should be attached to the related target via an aspect +hint. + +**EXAMPLE** + +```starlark +load("@rules_xcodeproj//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") + +swift_library( + ... + aspect_hints = [":library_extra_files"], + ... +) + +# Display the README.md file located alongside the Swift library in Xcode +xcodeproj_extra_files( + name = "library_extra_files", + files = ["README.md"], +) +``` + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| files | The list of extra files to surface in the Xcode navigator. | List of labels | optional | `[]` | + + diff --git a/test/BUILD b/test/BUILD index f8d54b5a8..d4b8b8181 100644 --- a/test/BUILD +++ b/test/BUILD @@ -13,6 +13,7 @@ test_suite( "//test/internal/target", "//test/internal/target_id", "//test/internal/targets", + "//test/internal/xcodeproj_extra_files", "//test/internal/xcschemes", ], ) @@ -29,6 +30,7 @@ bzl_library( "//test/internal/target:bzls", "//test/internal/target_id:bzls", "//test/internal/targets:bzls", + "//test/internal/xcodeproj_extra_files:bzls", "//test/internal/xcschemes:bzls", ], ) diff --git a/test/internal/xcodeproj_extra_files/BUILD b/test/internal/xcodeproj_extra_files/BUILD new file mode 100644 index 000000000..e2bdf5b58 --- /dev/null +++ b/test/internal/xcodeproj_extra_files/BUILD @@ -0,0 +1,15 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load(":xcodeproj_extra_files_tests.bzl", "xcodeproj_extra_files_test_suite") + +xcodeproj_extra_files_test_suite(name = "xcodeproj_extra_files_test") + +test_suite(name = "xcodeproj_extra_files") + +bzl_library( + name = "bzls", + srcs = glob( + ["*.bzl"], + exclude = ["utils.bzl"], + ), + visibility = ["//test:__pkg__"], +) diff --git a/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl new file mode 100644 index 000000000..d36ee2a65 --- /dev/null +++ b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl @@ -0,0 +1,47 @@ +"""Tests for the `xcodeproj_extra_files` module.""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") + +# buildifier: disable=bzl-visibility +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") + +def _provider_contents_test_impl(ctx): + env = analysistest.begin(ctx) + + target_under_test = analysistest.target_under_test(env) + + files_list = target_under_test[XcodeProjExtraFilesHintInfo].files.to_list() + + asserts.equals(env, len(files_list), 1) + asserts.equals( + env, + files_list[0].path, + "test/internal/xcodeproj_extra_files/BUILD", + ) + + return analysistest.end(env) + +provider_contents_test = analysistest.make(_provider_contents_test_impl) + +def _test_provider_contents(): + xcodeproj_extra_files( + name = "xcodeproj_extra_files_subject", + files = ["BUILD"], + tags = ["manual"], + ) + + provider_contents_test( + name = "provider_contents_test", + target_under_test = ":xcodeproj_extra_files_subject", + ) + +def xcodeproj_extra_files_test_suite(name): + _test_provider_contents() + + native.test_suite( + name = name, + tests = [ + ":provider_contents_test", + ], + ) diff --git a/xcodeproj/internal/docs/aspect_hints.bzl b/xcodeproj/internal/docs/aspect_hints.bzl new file mode 100644 index 000000000..8ab7c9bdc --- /dev/null +++ b/xcodeproj/internal/docs/aspect_hints.bzl @@ -0,0 +1,12 @@ +"""# Aspect Hints + +Aspect hints that can be used to provide additional information during \ +project generation. +""" + +load( + "//xcodeproj:xcodeproj_extra_files.bzl", + _xcodeproj_extra_files = "xcodeproj_extra_files", +) + +xcodeproj_extra_files = _xcodeproj_extra_files diff --git a/xcodeproj/internal/docs/bazel.header.md b/xcodeproj/internal/docs/bazel.header.md index 40fcd7aa9..1ebd20ce9 100644 --- a/xcodeproj/internal/docs/bazel.header.md +++ b/xcodeproj/internal/docs/bazel.header.md @@ -50,5 +50,7 @@ load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj") - [Providers](#providers) - [`XcodeProjAutomaticTargetProcessingInfo`](#XcodeProjAutomaticTargetProcessingInfo) - [`XcodeProjInfo`](#XcodeProjInfo) +- [Aspect Hints](#aspect-hints) + - [`xcodeproj_extra_files`](#xcodeproj_extra_files) # Core diff --git a/xcodeproj/internal/files/input_files.bzl b/xcodeproj/internal/files/input_files.bzl index 89423bc8d..7a850f35b 100644 --- a/xcodeproj/internal/files/input_files.bzl +++ b/xcodeproj/internal/files/input_files.bzl @@ -11,6 +11,7 @@ load( "EMPTY_LIST", "memory_efficient_depset", ) +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") load(":linker_input_files.bzl", "linker_input_files") load(":resources.bzl", resources_module = "resources") @@ -408,6 +409,13 @@ def _collect_input_files( rule_files = ctx.rule.files, ) + # Collect extra fila provided via the `xcodeproj_extra_files` aspect hint + for hint in rule_attr.aspect_hints: + if XcodeProjExtraFilesHintInfo in hint: + hint_extra_files = hint[XcodeProjExtraFilesHintInfo].files + if hint_extra_files: + extra_files.extend(hint_extra_files.to_list()) + product_framework_files = memory_efficient_depset( transitive = [ info.inputs._product_framework_files diff --git a/xcodeproj/internal/providers.bzl b/xcodeproj/internal/providers.bzl index 397c7e330..57df8ef08 100644 --- a/xcodeproj/internal/providers.bzl +++ b/xcodeproj/internal/providers.bzl @@ -15,3 +15,10 @@ XcodeProjRunnerOutputInfo = provider( "runner": "The xcodeproj runner.", }, ) + +XcodeProjExtraFilesHintInfo = provider( + doc = "Provides a list of extra files to include during project generation", + fields = { + "files": "List of files to include in the extra files.", + }, +) diff --git a/xcodeproj/xcodeproj_extra_files.bzl b/xcodeproj/xcodeproj_extra_files.bzl new file mode 100644 index 000000000..e8734d988 --- /dev/null +++ b/xcodeproj/xcodeproj_extra_files.bzl @@ -0,0 +1,48 @@ +"""Rule for providing extra files from targets to the project generator""" + +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") + +def _xcodeproj_extra_files_impl(ctx): + """Create a provider to surface extra files via an aspect hint. + + Args: + ctx: The rule context. + + Returns: + A `XcodeProjExtraFilesHintInfo` provider. + """ + return [XcodeProjExtraFilesHintInfo(files = depset(ctx.files.files))] + +xcodeproj_extra_files = rule( + doc = """\ +This rule is used to surface extra files that should be included in the Xcode +project navigator, but otherwise aren't inputs to a target. The provider +created by this rule should be attached to the related target via an aspect +hint. + +**EXAMPLE** + +```starlark +load("@rules_xcodeproj//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") + +swift_library( + ... + aspect_hints = [":library_extra_files"], + ... +) + +# Display the README.md file located alongside the Swift library in Xcode +xcodeproj_extra_files( + name = "library_extra_files", + files = ["README.md"], +) +``` +""", + implementation = _xcodeproj_extra_files_impl, + attrs = { + "files": attr.label_list( + doc = "The list of extra files to surface in the Xcode navigator.", + allow_files = True, + ), + }, +)