From 742d3f650c35b05d4c2839d596fc0c9610e63ec2 Mon Sep 17 00:00:00 2001 From: John Flanagan Date: Tue, 25 Mar 2025 14:37:37 -0500 Subject: [PATCH 1/4] extra_files aspect hint Signed-off-by: John Flanagan --- docs/BUILD | 7 ++- docs/bazel.md | 46 ++++++++++++++++ test/BUILD | 2 + test/internal/xcodeproj_extra_files/BUILD | 15 ++++++ .../xcodeproj_extra_files_tests.bzl | 38 +++++++++++++ xcodeproj/defs.bzl | 2 + xcodeproj/internal/docs/aspect_hints.bzl | 8 +++ xcodeproj/internal/docs/bazel.header.md | 2 + .../files/incremental_input_files.bzl | 8 +++ .../internal/files/xcodeproj_extra_files.bzl | 53 +++++++++++++++++++ 10 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 test/internal/xcodeproj_extra_files/BUILD create mode 100644 test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl create mode 100644 xcodeproj/internal/docs/aspect_hints.bzl create mode 100644 xcodeproj/internal/files/xcodeproj_extra_files.bzl diff --git a/docs/BUILD b/docs/BUILD index 6cb7212f32..917c7efca7 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -5,6 +5,7 @@ load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc") # Generating _DOC_COMPONENTS = [ + "aspect_hints", "project_options", "providers", "top_level_target", @@ -20,7 +21,10 @@ _DOC_COMPONENTS = [ out = "{}.md".format(component), input = "//xcodeproj/internal/docs:{}.bzl".format(component), tags = ["manual"], - deps = ["//xcodeproj/internal"], + deps = [ + "//xcodeproj/internal", + "//xcodeproj/internal/files", + ], ) for component in _DOC_COMPONENTS ] @@ -36,6 +40,7 @@ genrule( ":xcode_schemes", ":xcode_build_settings", ":providers", + ":aspect_hints", ], outs = ["bazel.generated.md"], cmd = """\ diff --git a/docs/bazel.md b/docs/bazel.md index ba029953c0..612d53cb83 100755 --- a/docs/bazel.md +++ b/docs/bazel.md @@ -50,6 +50,8 @@ load("@rules_xcodeproj//xcodeproj:defs.bzl", "xcodeproj") - [Providers](#providers) - [`XcodeProjAutomaticTargetProcessingInfo`](#XcodeProjAutomaticTargetProcessingInfo) - [`XcodeProjInfo`](#XcodeProjInfo) +- [Aspect Hints](#aspect-hints) + - [`xcodeproj_extra_files`](#xcodeproj_extra_files) # Core @@ -1095,3 +1097,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. + +This is only used when xcodeproj.generation_mode = "incremental" is set. + +**EXAMPLE** + +```starlark +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 abe59bfcc9..13c8ea2dbd 100644 --- a/test/BUILD +++ b/test/BUILD @@ -15,6 +15,7 @@ test_suite( "//test/internal/targets", "//test/internal/xcode_schemes", "//test/internal/xcschemes", + "//test/internal/xcodeproj_extra_files", ], ) @@ -32,6 +33,7 @@ bzl_library( "//test/internal/targets:bzls", "//test/internal/xcode_schemes:bzls", "//test/internal/xcschemes:bzls", + "//test/internal/xcodeproj_extra_files:bzls", ], ) diff --git a/test/internal/xcodeproj_extra_files/BUILD b/test/internal/xcodeproj_extra_files/BUILD new file mode 100644 index 0000000000..e2bdf5b582 --- /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 0000000000..bdb2990da2 --- /dev/null +++ b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl @@ -0,0 +1,38 @@ +load("@bazel_skylib//lib:unittest.bzl", "asserts", "analysistest") +load("//xcodeproj/internal/files:xcodeproj_extra_files.bzl", "xcodeproj_extra_files", "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", + ], + ) \ No newline at end of file diff --git a/xcodeproj/defs.bzl b/xcodeproj/defs.bzl index 344349608c..f7d51a55b7 100644 --- a/xcodeproj/defs.bzl +++ b/xcodeproj/defs.bzl @@ -23,6 +23,7 @@ load( _xcodeproj = "xcodeproj", ) load("//xcodeproj/internal:xcodeprojinfo.bzl", _XcodeProjInfo = "XcodeProjInfo") +load("//xcodeproj/internal/files:xcodeproj_extra_files.bzl", _xcodeproj_extra_files = "xcodeproj_extra_files") load("//xcodeproj/internal/xcschemes:xcschemes.bzl", _xcschemes = "xcschemes") # Re-exporting providers @@ -34,6 +35,7 @@ project_options = _project_options top_level_target = _top_level_target top_level_targets = _top_level_targets xcodeproj = _xcodeproj +xcodeproj_extra_files = _xcodeproj_extra_files xcode_provisioning_profile = _xcode_provisioning_profile # Re-exporting APIs diff --git a/xcodeproj/internal/docs/aspect_hints.bzl b/xcodeproj/internal/docs/aspect_hints.bzl new file mode 100644 index 0000000000..15af7364bd --- /dev/null +++ b/xcodeproj/internal/docs/aspect_hints.bzl @@ -0,0 +1,8 @@ +"""# Aspect Hints + +Aspect hints that can be used to provide additional information during project generation. +""" + +load("//xcodeproj/internal/files: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 ff4a63ccd9..6069afcf16 100644 --- a/xcodeproj/internal/docs/bazel.header.md +++ b/xcodeproj/internal/docs/bazel.header.md @@ -50,5 +50,7 @@ load("@rules_xcodeproj//xcodeproj:defs.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/incremental_input_files.bzl b/xcodeproj/internal/files/incremental_input_files.bzl index b509a9e402..e6e9606858 100644 --- a/xcodeproj/internal/files/incremental_input_files.bzl +++ b/xcodeproj/internal/files/incremental_input_files.bzl @@ -11,6 +11,7 @@ load( "memory_efficient_depset", ) load("//xcodeproj/internal:xcodeprojinfo.bzl", "XcodeProjInfo") +load(":xcodeproj_extra_files.bzl", "XcodeProjExtraFilesHintInfo") load(":incremental_resources.bzl", resources_module = "incremental_resources") load(":linker_input_files.bzl", "linker_input_files") @@ -408,6 +409,13 @@ def _collect_incremental_input_files( rule_files = ctx.rule.files, ) + # Collect any 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/files/xcodeproj_extra_files.bzl b/xcodeproj/internal/files/xcodeproj_extra_files.bzl new file mode 100644 index 0000000000..88fc74de27 --- /dev/null +++ b/xcodeproj/internal/files/xcodeproj_extra_files.bzl @@ -0,0 +1,53 @@ +"""Rule for providing extra files from targets to the project generator""" + +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.", + }, +) + +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. + +This is only used when xcodeproj.generation_mode = "incremental" is set. + +**EXAMPLE** + +```starlark +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, + ), + }, +) From 9a92f9f34e36862780be3b11b90a7f9888e67d1a Mon Sep 17 00:00:00 2001 From: John Flanagan Date: Fri, 16 May 2025 13:11:03 -0500 Subject: [PATCH 2/4] Move xcodeproj_extra_files to xcodeproj/ --- docs/BUILD | 2 +- .../xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl | 3 ++- xcodeproj/defs.bzl | 2 -- xcodeproj/internal/docs/aspect_hints.bzl | 2 +- xcodeproj/internal/files/incremental_input_files.bzl | 2 +- xcodeproj/internal/providers.bzl | 7 +++++++ xcodeproj/{internal/files => }/xcodeproj_extra_files.bzl | 8 +------- 7 files changed, 13 insertions(+), 13 deletions(-) rename xcodeproj/{internal/files => }/xcodeproj_extra_files.bzl (85%) diff --git a/docs/BUILD b/docs/BUILD index 917c7efca7..19e863e401 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -23,7 +23,7 @@ _DOC_COMPONENTS = [ tags = ["manual"], deps = [ "//xcodeproj/internal", - "//xcodeproj/internal/files", + "//xcodeproj", ], ) for component in _DOC_COMPONENTS diff --git a/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl index bdb2990da2..191c5a4363 100644 --- a/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl +++ b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl @@ -1,5 +1,6 @@ load("@bazel_skylib//lib:unittest.bzl", "asserts", "analysistest") -load("//xcodeproj/internal/files:xcodeproj_extra_files.bzl", "xcodeproj_extra_files", "XcodeProjExtraFilesHintInfo") +load("//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") def _provider_contents_test_impl(ctx): env = analysistest.begin(ctx) diff --git a/xcodeproj/defs.bzl b/xcodeproj/defs.bzl index f7d51a55b7..344349608c 100644 --- a/xcodeproj/defs.bzl +++ b/xcodeproj/defs.bzl @@ -23,7 +23,6 @@ load( _xcodeproj = "xcodeproj", ) load("//xcodeproj/internal:xcodeprojinfo.bzl", _XcodeProjInfo = "XcodeProjInfo") -load("//xcodeproj/internal/files:xcodeproj_extra_files.bzl", _xcodeproj_extra_files = "xcodeproj_extra_files") load("//xcodeproj/internal/xcschemes:xcschemes.bzl", _xcschemes = "xcschemes") # Re-exporting providers @@ -35,7 +34,6 @@ project_options = _project_options top_level_target = _top_level_target top_level_targets = _top_level_targets xcodeproj = _xcodeproj -xcodeproj_extra_files = _xcodeproj_extra_files xcode_provisioning_profile = _xcode_provisioning_profile # Re-exporting APIs diff --git a/xcodeproj/internal/docs/aspect_hints.bzl b/xcodeproj/internal/docs/aspect_hints.bzl index 15af7364bd..9c773b55e4 100644 --- a/xcodeproj/internal/docs/aspect_hints.bzl +++ b/xcodeproj/internal/docs/aspect_hints.bzl @@ -3,6 +3,6 @@ Aspect hints that can be used to provide additional information during project generation. """ -load("//xcodeproj/internal/files:xcodeproj_extra_files.bzl", _xcodeproj_extra_files = "xcodeproj_extra_files") +load("//xcodeproj:xcodeproj_extra_files.bzl", _xcodeproj_extra_files = "xcodeproj_extra_files") xcodeproj_extra_files = _xcodeproj_extra_files diff --git a/xcodeproj/internal/files/incremental_input_files.bzl b/xcodeproj/internal/files/incremental_input_files.bzl index e6e9606858..228d787fb4 100644 --- a/xcodeproj/internal/files/incremental_input_files.bzl +++ b/xcodeproj/internal/files/incremental_input_files.bzl @@ -11,7 +11,7 @@ load( "memory_efficient_depset", ) load("//xcodeproj/internal:xcodeprojinfo.bzl", "XcodeProjInfo") -load(":xcodeproj_extra_files.bzl", "XcodeProjExtraFilesHintInfo") +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") load(":incremental_resources.bzl", resources_module = "incremental_resources") load(":linker_input_files.bzl", "linker_input_files") diff --git a/xcodeproj/internal/providers.bzl b/xcodeproj/internal/providers.bzl index 397c7e3300..57df8ef08c 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/internal/files/xcodeproj_extra_files.bzl b/xcodeproj/xcodeproj_extra_files.bzl similarity index 85% rename from xcodeproj/internal/files/xcodeproj_extra_files.bzl rename to xcodeproj/xcodeproj_extra_files.bzl index 88fc74de27..1327315f90 100644 --- a/xcodeproj/internal/files/xcodeproj_extra_files.bzl +++ b/xcodeproj/xcodeproj_extra_files.bzl @@ -1,11 +1,5 @@ """Rule for providing extra files from targets to the project generator""" - -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.", - }, -) +load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") def _xcodeproj_extra_files_impl(ctx): """Create a provider to surface extra files via an aspect hint. From 71350596742d5afad8fe77772e4ae06fa44bf159 Mon Sep 17 00:00:00 2001 From: John Flanagan Date: Fri, 16 May 2025 13:20:09 -0500 Subject: [PATCH 3/4] buildifier.fix --- docs/BUILD | 2 +- test/BUILD | 4 ++-- .../xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl | 4 ++-- xcodeproj/internal/files/incremental_input_files.bzl | 2 +- xcodeproj/xcodeproj_extra_files.bzl | 1 + 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/BUILD b/docs/BUILD index 19e863e401..5762c6fdb8 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -22,8 +22,8 @@ _DOC_COMPONENTS = [ input = "//xcodeproj/internal/docs:{}.bzl".format(component), tags = ["manual"], deps = [ - "//xcodeproj/internal", "//xcodeproj", + "//xcodeproj/internal", ], ) for component in _DOC_COMPONENTS diff --git a/test/BUILD b/test/BUILD index 13c8ea2dbd..f4fd47a5a4 100644 --- a/test/BUILD +++ b/test/BUILD @@ -14,8 +14,8 @@ test_suite( "//test/internal/target_id", "//test/internal/targets", "//test/internal/xcode_schemes", - "//test/internal/xcschemes", "//test/internal/xcodeproj_extra_files", + "//test/internal/xcschemes", ], ) @@ -32,8 +32,8 @@ bzl_library( "//test/internal/target_id:bzls", "//test/internal/targets:bzls", "//test/internal/xcode_schemes:bzls", - "//test/internal/xcschemes:bzls", "//test/internal/xcodeproj_extra_files:bzls", + "//test/internal/xcschemes:bzls", ], ) diff --git a/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl index 191c5a4363..46a35af2e2 100644 --- a/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl +++ b/test/internal/xcodeproj_extra_files/xcodeproj_extra_files_tests.bzl @@ -1,4 +1,4 @@ -load("@bazel_skylib//lib:unittest.bzl", "asserts", "analysistest") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") @@ -36,4 +36,4 @@ def xcodeproj_extra_files_test_suite(name): tests = [ ":provider_contents_test", ], - ) \ No newline at end of file + ) diff --git a/xcodeproj/internal/files/incremental_input_files.bzl b/xcodeproj/internal/files/incremental_input_files.bzl index 228d787fb4..e030c193da 100644 --- a/xcodeproj/internal/files/incremental_input_files.bzl +++ b/xcodeproj/internal/files/incremental_input_files.bzl @@ -10,8 +10,8 @@ load( "EMPTY_LIST", "memory_efficient_depset", ) -load("//xcodeproj/internal:xcodeprojinfo.bzl", "XcodeProjInfo") load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") +load("//xcodeproj/internal:xcodeprojinfo.bzl", "XcodeProjInfo") load(":incremental_resources.bzl", resources_module = "incremental_resources") load(":linker_input_files.bzl", "linker_input_files") diff --git a/xcodeproj/xcodeproj_extra_files.bzl b/xcodeproj/xcodeproj_extra_files.bzl index 1327315f90..f5bf31909d 100644 --- a/xcodeproj/xcodeproj_extra_files.bzl +++ b/xcodeproj/xcodeproj_extra_files.bzl @@ -1,4 +1,5 @@ """Rule for providing extra files from targets to the project generator""" + load("//xcodeproj/internal:providers.bzl", "XcodeProjExtraFilesHintInfo") def _xcodeproj_extra_files_impl(ctx): From a6a1f82f22a9a58dd18bf9707aadcf24763c232f Mon Sep 17 00:00:00 2001 From: John Flanagan Date: Fri, 16 May 2025 13:39:43 -0500 Subject: [PATCH 4/4] Add example load statement --- docs/bazel.md | 2 ++ xcodeproj/xcodeproj_extra_files.bzl | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/bazel.md b/docs/bazel.md index 612d53cb83..c6870e9d29 100755 --- a/docs/bazel.md +++ b/docs/bazel.md @@ -1119,6 +1119,8 @@ This is only used when xcodeproj.generation_mode = "incremental" is set. **EXAMPLE** ```starlark +load("@rules_xcodeproj//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") + swift_library( ... aspect_hints = [":library_extra_files"], diff --git a/xcodeproj/xcodeproj_extra_files.bzl b/xcodeproj/xcodeproj_extra_files.bzl index f5bf31909d..af1afcfc54 100644 --- a/xcodeproj/xcodeproj_extra_files.bzl +++ b/xcodeproj/xcodeproj_extra_files.bzl @@ -25,6 +25,8 @@ This is only used when xcodeproj.generation_mode = "incremental" is set. **EXAMPLE** ```starlark +load("@rules_xcodeproj//xcodeproj:xcodeproj_extra_files.bzl", "xcodeproj_extra_files") + swift_library( ... aspect_hints = [":library_extra_files"],