Skip to content

Commit

Permalink
Add the strip_structured_resources_prefixes attribute where `struct…
Browse files Browse the repository at this point in the history
…ured_resources` exists (#2570)

This allows removing intermediate directories from structured resource
paths, without having to do wasteful file copies.

Signed-off-by: Brentley Jones <[email protected]>
  • Loading branch information
brentleyjones authored Oct 29, 2024
1 parent 784216c commit ba0db8b
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 14 deletions.
18 changes: 9 additions & 9 deletions apple/internal/aspects/resource_aspect.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
13 changes: 13 additions & 0 deletions apple/internal/resource_rules/apple_resource_bundle.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
13 changes: 13 additions & 0 deletions apple/internal/resource_rules/apple_resource_group.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
14 changes: 13 additions & 1 deletion apple/internal/resources.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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):
Expand Down
13 changes: 9 additions & 4 deletions doc/rules-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Compiles Metal shader language sources into a Metal library.

<pre>
apple_precompiled_resource_bundle(<a href="#apple_precompiled_resource_bundle-name">name</a>, <a href="#apple_precompiled_resource_bundle-resources">resources</a>, <a href="#apple_precompiled_resource_bundle-bundle_id">bundle_id</a>, <a href="#apple_precompiled_resource_bundle-bundle_name">bundle_name</a>, <a href="#apple_precompiled_resource_bundle-infoplists">infoplists</a>,
<a href="#apple_precompiled_resource_bundle-structured_resources">structured_resources</a>)
<a href="#apple_precompiled_resource_bundle-strip_structured_resources_prefixes">strip_structured_resources_prefixes</a>, <a href="#apple_precompiled_resource_bundle-structured_resources">structured_resources</a>)
</pre>

This rule encapsulates a target which is provided to dependers as a bundle. An
Expand All @@ -124,6 +124,7 @@ library targets through the `data` attribute.
| <a id="apple_precompiled_resource_bundle-bundle_id"></a>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 | `""` |
| <a id="apple_precompiled_resource_bundle-bundle_name"></a>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 | `""` |
| <a id="apple_precompiled_resource_bundle-infoplists"></a>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.<br><br>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):<br><br>${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 -. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="apple_precompiled_resource_bundle-strip_structured_resources_prefixes"></a>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.<br><br>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 | `[]` |
| <a id="apple_precompiled_resource_bundle-structured_resources"></a>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. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |


Expand All @@ -132,7 +133,8 @@ library targets through the `data` attribute.
## apple_resource_bundle

<pre>
apple_resource_bundle(<a href="#apple_resource_bundle-name">name</a>, <a href="#apple_resource_bundle-resources">resources</a>, <a href="#apple_resource_bundle-bundle_id">bundle_id</a>, <a href="#apple_resource_bundle-bundle_name">bundle_name</a>, <a href="#apple_resource_bundle-infoplists">infoplists</a>, <a href="#apple_resource_bundle-structured_resources">structured_resources</a>)
apple_resource_bundle(<a href="#apple_resource_bundle-name">name</a>, <a href="#apple_resource_bundle-resources">resources</a>, <a href="#apple_resource_bundle-bundle_id">bundle_id</a>, <a href="#apple_resource_bundle-bundle_name">bundle_name</a>, <a href="#apple_resource_bundle-infoplists">infoplists</a>,
<a href="#apple_resource_bundle-strip_structured_resources_prefixes">strip_structured_resources_prefixes</a>, <a href="#apple_resource_bundle-structured_resources">structured_resources</a>)
</pre>

This rule encapsulates a target which is provided to dependers as a bundle. An
Expand All @@ -150,6 +152,7 @@ library targets through the `data` attribute.
| <a id="apple_resource_bundle-bundle_id"></a>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 | `""` |
| <a id="apple_resource_bundle-bundle_name"></a>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 | `""` |
| <a id="apple_resource_bundle-infoplists"></a>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.<br><br>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):<br><br>${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 -. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="apple_resource_bundle-strip_structured_resources_prefixes"></a>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.<br><br>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 | `[]` |
| <a id="apple_resource_bundle-structured_resources"></a>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. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |


Expand All @@ -158,7 +161,7 @@ library targets through the `data` attribute.
## apple_resource_group

<pre>
apple_resource_group(<a href="#apple_resource_group-name">name</a>, <a href="#apple_resource_group-resources">resources</a>, <a href="#apple_resource_group-structured_resources">structured_resources</a>)
apple_resource_group(<a href="#apple_resource_group-name">name</a>, <a href="#apple_resource_group-resources">resources</a>, <a href="#apple_resource_group-strip_structured_resources_prefixes">strip_structured_resources_prefixes</a>, <a href="#apple_resource_group-structured_resources">structured_resources</a>)
</pre>

This rule encapsulates a target which provides resources to dependents. An
Expand All @@ -175,6 +178,7 @@ to library targets through the `data` attribute, or to other
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="apple_resource_group-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="apple_resource_group-resources"></a>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.<br><br>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. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="apple_resource_group-strip_structured_resources_prefixes"></a>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.<br><br>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 | `[]` |
| <a id="apple_resource_group-structured_resources"></a>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. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |


Expand Down Expand Up @@ -607,7 +611,7 @@ The package relative path to the parent directory of the resource.
## resources_common.structured_resources_parent_dir

<pre>
resources_common.structured_resources_parent_dir(<a href="#resources_common.structured_resources_parent_dir-parent_dir">parent_dir</a>, <a href="#resources_common.structured_resources_parent_dir-resource">resource</a>)
resources_common.structured_resources_parent_dir(<a href="#resources_common.structured_resources_parent_dir-parent_dir">parent_dir</a>, <a href="#resources_common.structured_resources_parent_dir-resource">resource</a>, <a href="#resources_common.structured_resources_parent_dir-strip_prefixes">strip_prefixes</a>)
</pre>

Returns the package relative path for the parent directory of a resource.
Expand All @@ -619,6 +623,7 @@ Returns the package relative path for the parent directory of a resource.
| :------------- | :------------- | :------------- |
| <a id="resources_common.structured_resources_parent_dir-parent_dir"></a>parent_dir | Parent directory to prepend to the package relative path. | `None` |
| <a id="resources_common.structured_resources_parent_dir-resource"></a>resource | The resource for which to calculate the package relative path. | none |
| <a id="resources_common.structured_resources_parent_dir-strip_prefixes"></a>strip_prefixes | A list of prefixes to strip from the package relative path. The first prefix that matches will be used. | `[]` |

**RETURNS**

Expand Down

0 comments on commit ba0db8b

Please sign in to comment.