diff --git a/apple/internal/aspects/resource_aspect.bzl b/apple/internal/aspects/resource_aspect.bzl index cefa971ea0..41f7597da2 100644 --- a/apple/internal/aspects/resource_aspect.bzl +++ b/apple/internal/aspects/resource_aspect.bzl @@ -286,15 +286,15 @@ def _apple_resource_aspect_impl(target, ctx): **collect_structured_args ) if structured_files: - if bundle_name: - structured_parent_dir_param = partial.make( - resources.structured_resources_parent_dir, - parent_dir = bundle_name, - ) - else: - structured_parent_dir_param = partial.make( - resources.structured_resources_parent_dir, - ) + structured_parent_dir_param = partial.make( + resources.structured_resources_parent_dir, + parent_dir = bundle_name, + strip_prefixes = getattr( + ctx.rule.attr, + "strip_structured_resources_prefixes", + [], + ), + ) # Avoid processing PNG files that are referenced through the structured_resources # attribute. This is mostly for legacy reasons and should get cleaned up in the future. diff --git a/apple/internal/resource_rules/apple_precompiled_resource_bundle.bzl b/apple/internal/resource_rules/apple_precompiled_resource_bundle.bzl index 723fda8fd7..6d67eb217b 100644 --- a/apple/internal/resource_rules/apple_precompiled_resource_bundle.bzl +++ b/apple/internal/resource_rules/apple_precompiled_resource_bundle.bzl @@ -146,6 +146,11 @@ def _apple_precompiled_resource_bundle_impl(ctx): structured_parent_dir_param = partial.make( resources.structured_resources_parent_dir, parent_dir = bundle_name, + strip_prefixes = getattr( + ctx.attr, + "strip_structured_resources_prefixes", + [], + ), ) # Avoid processing PNG files that are referenced through the structured_resources @@ -265,6 +270,19 @@ they will be placed in a directory of the same name in the app bundle. You can also add other `apple_precompiled_resource_bundle` and `apple_bundle_import` targets into `resources`, and the resource bundle structures will be propagated into the final bundle. +""", + ), + "strip_structured_resources_prefixes": attr.string_list( + doc = """ +A list of prefixes to strip from the paths of structured resources. For each +structured resource, if the path starts with one of these prefixes, the first +matching prefix will be removed from the path when the resource is placed in +the bundle root. This is useful for removing intermediate directories from the +resource paths. + +For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, +and `strip_structured_resources_prefixes` contains `["intermediate"]`, +`res/foo.png` will end up inside the bundle. """, ), "structured_resources": attr.label_list( diff --git a/apple/internal/resource_rules/apple_resource_bundle.bzl b/apple/internal/resource_rules/apple_resource_bundle.bzl index d9d0549df8..b3a31498c1 100644 --- a/apple/internal/resource_rules/apple_resource_bundle.bzl +++ b/apple/internal/resource_rules/apple_resource_bundle.bzl @@ -80,6 +80,19 @@ they will be placed in a directory of the same name in the app bundle. You can also add other `apple_resource_bundle` and `apple_bundle_import` targets into `resources`, and the resource bundle structures will be propagated into the final bundle. +""", + ), + "strip_structured_resources_prefixes": attr.string_list( + doc = """ +A list of prefixes to strip from the paths of structured resources. For each +structured resource, if the path starts with one of these prefixes, the first +matching prefix will be removed from the path when the resource is placed in +the bundle root. This is useful for removing intermediate directories from the +resource paths. + +For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, +and `strip_structured_resources_prefixes` contains `["intermediate"]`, +`res/foo.png` will end up inside the bundle. """, ), "structured_resources": attr.label_list( diff --git a/apple/internal/resource_rules/apple_resource_group.bzl b/apple/internal/resource_rules/apple_resource_group.bzl index 59b7169dc5..9eed9df51d 100644 --- a/apple/internal/resource_rules/apple_resource_group.bzl +++ b/apple/internal/resource_rules/apple_resource_group.bzl @@ -37,6 +37,19 @@ directory called *.lproj), they will be placed in a directory of the same name i You can also add apple_resource_bundle and apple_bundle_import targets into `resources`, and the resource bundle structures will be propagated into the final bundle. +""", + ), + "strip_structured_resources_prefixes": attr.string_list( + doc = """ +A list of prefixes to strip from the paths of structured resources. For each +structured resource, if the path starts with one of these prefixes, the first +matching prefix will be removed from the path when the resource is placed in +the bundle root. This is useful for removing intermediate directories from the +resource paths. + +For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, +and `strip_structured_resources_prefixes` contains `["intermediate"]`, +`res/foo.png` will end up inside the bundle. """, ), "structured_resources": attr.label_list( diff --git a/apple/internal/resources.bzl b/apple/internal/resources.bzl index a9e9ac57a6..368ba89749 100644 --- a/apple/internal/resources.bzl +++ b/apple/internal/resources.bzl @@ -786,12 +786,18 @@ def _populated_resource_fields(provider): if f not in ["owners", "unowned_resources", "processed_origins", "to_json", "to_proto"] ] -def _structured_resources_parent_dir(*, parent_dir = None, resource): +def _structured_resources_parent_dir( + *, + parent_dir = None, + resource, + strip_prefixes = []): """Returns the package relative path for the parent directory of a resource. Args: parent_dir: Parent directory to prepend to the package relative path. resource: The resource for which to calculate the package relative path. + strip_prefixes: A list of prefixes to strip from the package relative + path. The first prefix that matches will be used. Returns: The package relative path to the parent directory of the resource. @@ -801,6 +807,12 @@ def _structured_resources_parent_dir(*, parent_dir = None, resource): path = package_relative else: path = paths.dirname(package_relative).rstrip("/") + + for prefix in strip_prefixes: + if path.startswith(prefix): + path = path[(len(prefix) + 1):] + break + return paths.join(parent_dir or "", path or "") or None def _runfiles_resources_parent_dir(*, resource): diff --git a/doc/rules-resources.md b/doc/rules-resources.md index 8473a11644..622d00f723 100644 --- a/doc/rules-resources.md +++ b/doc/rules-resources.md @@ -106,7 +106,7 @@ Compiles Metal shader language sources into a Metal library.
 apple_precompiled_resource_bundle(name, resources, bundle_id, bundle_name, infoplists,
-                                  structured_resources)
+                                  strip_structured_resources_prefixes, structured_resources)
 
This rule encapsulates a target which is provided to dependers as a bundle. An @@ -124,6 +124,7 @@ library targets through the `data` attribute. | bundle_id | The bundle ID for this target. It will replace `$(PRODUCT_BUNDLE_IDENTIFIER)` found in the files from defined in the `infoplists` paramter. | String | optional | `""` | | bundle_name | The desired name of the bundle (without the `.bundle` extension). If this attribute is not set, then the `name` of the target will be used instead. | String | optional | `""` | | infoplists | A list of `.plist` files that will be merged to form the `Info.plist` that represents the extension. At least one file must be specified. Please see [Info.plist Handling](/doc/common_info.md#infoplist-handling") for what is supported.

Duplicate keys between infoplist files will cause an error if and only if the values conflict. Bazel will perform variable substitution on the Info.plist file for the following values (if they are strings in the top-level dict of the plist):

${BUNDLE_NAME}: This target's name and bundle suffix (.bundle or .app) in the form name.suffix. ${PRODUCT_NAME}: This target's name. ${TARGET_NAME}: This target's name. The key in ${} may be suffixed with :rfc1034identifier (for example ${PRODUCT_NAME::rfc1034identifier}) in which case Bazel will replicate Xcode's behavior and replace non-RFC1034-compliant characters with -. | List of labels | optional | `[]` | +| strip_structured_resources_prefixes | A list of prefixes to strip from the paths of structured resources. For each structured resource, if the path starts with one of these prefixes, the first matching prefix will be removed from the path when the resource is placed in the bundle root. This is useful for removing intermediate directories from the resource paths.

For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, and `strip_structured_resources_prefixes` contains `["intermediate"]`, `res/foo.png` will end up inside the bundle. | List of strings | optional | `[]` | | structured_resources | Files to include in the final resource bundle. They are not processed or compiled in any way besides the processing done by the rules that actually generate them. These files are placed in the bundle root in the same structure passed to this argument, so `["res/foo.png"]` will end up in `res/foo.png` inside the bundle. | List of labels | optional | `[]` | @@ -132,7 +133,8 @@ library targets through the `data` attribute. ## apple_resource_bundle
-apple_resource_bundle(name, resources, bundle_id, bundle_name, infoplists, structured_resources)
+apple_resource_bundle(name, resources, bundle_id, bundle_name, infoplists,
+                      strip_structured_resources_prefixes, structured_resources)
 
This rule encapsulates a target which is provided to dependers as a bundle. An @@ -150,6 +152,7 @@ library targets through the `data` attribute. | bundle_id | The bundle ID for this target. It will replace `$(PRODUCT_BUNDLE_IDENTIFIER)` found in the files from defined in the `infoplists` paramter. | String | optional | `""` | | bundle_name | The desired name of the bundle (without the `.bundle` extension). If this attribute is not set, then the `name` of the target will be used instead. | String | optional | `""` | | infoplists | A list of `.plist` files that will be merged to form the `Info.plist` that represents the extension. At least one file must be specified. Please see [Info.plist Handling](/doc/common_info.md#infoplist-handling") for what is supported.

Duplicate keys between infoplist files will cause an error if and only if the values conflict. Bazel will perform variable substitution on the Info.plist file for the following values (if they are strings in the top-level dict of the plist):

${BUNDLE_NAME}: This target's name and bundle suffix (.bundle or .app) in the form name.suffix. ${PRODUCT_NAME}: This target's name. ${TARGET_NAME}: This target's name. The key in ${} may be suffixed with :rfc1034identifier (for example ${PRODUCT_NAME::rfc1034identifier}) in which case Bazel will replicate Xcode's behavior and replace non-RFC1034-compliant characters with -. | List of labels | optional | `[]` | +| strip_structured_resources_prefixes | A list of prefixes to strip from the paths of structured resources. For each structured resource, if the path starts with one of these prefixes, the first matching prefix will be removed from the path when the resource is placed in the bundle root. This is useful for removing intermediate directories from the resource paths.

For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, and `strip_structured_resources_prefixes` contains `["intermediate"]`, `res/foo.png` will end up inside the bundle. | List of strings | optional | `[]` | | structured_resources | Files to include in the final resource bundle. They are not processed or compiled in any way besides the processing done by the rules that actually generate them. These files are placed in the bundle root in the same structure passed to this argument, so `["res/foo.png"]` will end up in `res/foo.png` inside the bundle. | List of labels | optional | `[]` | @@ -158,7 +161,7 @@ library targets through the `data` attribute. ## apple_resource_group
-apple_resource_group(name, resources, structured_resources)
+apple_resource_group(name, resources, strip_structured_resources_prefixes, structured_resources)
 
This rule encapsulates a target which provides resources to dependents. An @@ -175,6 +178,7 @@ to library targets through the `data` attribute, or to other | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | resources | Files to include in the final bundle that depends on this target. Files that are processable resources, like .xib, .storyboard, .strings, .png, and others, will be processed by the Apple bundling rules that have those files as dependencies. Other file types that are not processed will be copied verbatim. These files are placed in the root of the final bundle (e.g. Payload/foo.app/...) in most cases. However, if they appear to be localized (i.e. are contained in a directory called *.lproj), they will be placed in a directory of the same name in the app bundle.

You can also add apple_resource_bundle and apple_bundle_import targets into `resources`, and the resource bundle structures will be propagated into the final bundle. | List of labels | optional | `[]` | +| strip_structured_resources_prefixes | A list of prefixes to strip from the paths of structured resources. For each structured resource, if the path starts with one of these prefixes, the first matching prefix will be removed from the path when the resource is placed in the bundle root. This is useful for removing intermediate directories from the resource paths.

For example, if `structured_resources` contains `["intermediate/res/foo.png"]`, and `strip_structured_resources_prefixes` contains `["intermediate"]`, `res/foo.png` will end up inside the bundle. | List of strings | optional | `[]` | | structured_resources | Files to include in the final application bundle. They are not processed or compiled in any way besides the processing done by the rules that actually generate them. These files are placed in the bundle root in the same structure passed to this argument, so `["res/foo.png"]` will end up in `res/foo.png` inside the bundle. | List of labels | optional | `[]` | @@ -607,7 +611,7 @@ The package relative path to the parent directory of the resource. ## resources_common.structured_resources_parent_dir
-resources_common.structured_resources_parent_dir(parent_dir, resource)
+resources_common.structured_resources_parent_dir(parent_dir, resource, strip_prefixes)
 
Returns the package relative path for the parent directory of a resource. @@ -619,6 +623,7 @@ Returns the package relative path for the parent directory of a resource. | :------------- | :------------- | :------------- | | parent_dir | Parent directory to prepend to the package relative path. | `None` | | resource | The resource for which to calculate the package relative path. | none | +| strip_prefixes | A list of prefixes to strip from the package relative path. The first prefix that matches will be used. | `[]` | **RETURNS**