| # Copyright 2018 The Bazel Authors. All rights reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Transform contains data transformation methods.""" |
| |
| load("//rules:visibility.bzl", "PROJECT_VISIBILITY") |
| load("//rules/flags:flags.bzl", _flags = "flags") |
| load(":constants.bzl", "constants") |
| load(":utils.bzl", "utils") |
| |
| visibility(PROJECT_VISIBILITY) |
| |
| def _declare_file(ctx, filename, sibling = None): |
| return utils.isolated_declare_file(ctx, filename, sibling = sibling) |
| |
| def filter_jars(name, data): |
| """Filters out files that are not compiled Jars - includes header Jars. |
| |
| Args: |
| name: Name of the file to filter, check uses endswith on the path. |
| data: The list of tuples where each entry contains the originating file path |
| and file to apply the filter. |
| |
| Returns: |
| A list of tuples where each entry contains the originating Jar path and the |
| Jar file. |
| """ |
| return [jar for jar in data if not jar.path.endswith(name)] |
| |
| def dex( |
| ctx, |
| data, |
| deps = constants.EMPTY_LIST, |
| num_shards = None, |
| create_file = _declare_file): |
| """Dex a list of Jars. |
| |
| Args: |
| ctx: The context. |
| data: The list of tuples where each entry contains the originating Jar |
| path and the Jar to Dex. |
| deps: The list of dependencies for the Jar being desugared. |
| num_shards: The number of shards to distribute the dexed files across, |
| this value overrides the default provided by ctx.attr._mi_dex_shards. |
| create_file: In rare occasions a custom method is required to |
| create a unique file, override the default here. The method must |
| implement the following interface: |
| |
| def create_file(ctx, filename, sibling = None) |
| Args: |
| ctx: The context. |
| filename: string. The name of the file. |
| sibling: File. The location of the new file. |
| |
| Returns: |
| A File. |
| |
| Returns: |
| A list of tuples where each entry contains the originating Jar path and |
| the Dex shards. |
| """ |
| if num_shards: |
| num_dex_shards = num_shards |
| elif _flags.get(ctx).use_custom_dex_shards: |
| num_dex_shards = _flags.get(ctx).num_dex_shards |
| else: |
| num_dex_shards = ctx.attr._mi_dex_shards |
| |
| dex_files = [] |
| for jar in data: |
| out_dex_shards = [] |
| dirname = jar.basename + "_dex" |
| for i in range(num_shards or num_dex_shards): |
| out_dex_shards.append(create_file( |
| ctx, |
| dirname + "/" + str(i) + ".zip", |
| sibling = jar, |
| )) |
| utils.dex(ctx, jar, out_dex_shards, deps) |
| dex_files.append(out_dex_shards) |
| return dex_files |
| |
| def extract_jar_resources(ctx, data, create_file = _declare_file): |
| """Extracts the non-class files from the list of Jars. |
| |
| Args: |
| ctx: The context |
| data: The list of tuples where each entry contains the originating Jar |
| path and the Jar with resources to extract. |
| create_file: In rare occasions a custom method is required to |
| create a unique file, override the default here. The method must |
| implement the following interface: |
| |
| def create_file(ctx, filename, sibling = None) |
| Args: |
| ctx: The context. |
| filename: string. The name of the file. |
| sibling: File. The location of the new file. |
| |
| Returns: |
| A File. |
| |
| Returns: |
| A list of extracted resource zips. |
| """ |
| resources_files = [] |
| for jar in data: |
| out_resources_file = create_file( |
| ctx, |
| jar.basename + "_resources.zip", |
| sibling = jar, |
| ) |
| utils.extract_jar_resources(ctx, jar, out_resources_file) |
| resources_files.append(out_resources_file) |
| return resources_files |
| |
| def merge_dex_shards(ctx, data, sibling): |
| """Merges all dex files in the transitive deps to a dex per shard. |
| |
| Given a list of dex files (and resources.zips) this will create an |
| action per shard that runs dex_shard_merger on all dex files within that |
| shard. |
| |
| Arguments: |
| ctx: The context. |
| data: A list of lists, where the inner list contains dex shards. |
| sibling: A file used to root the merged_dex shards. |
| |
| Returns: |
| A list of merged dex shards. |
| """ |
| merged_dex_shards = [] |
| for idx, shard_archives in enumerate(data): |
| # To ensure resource is added at the beginning, R.zip is named as 00.zip |
| # Thus data shards starts from 1 instead of 0 and ranges through 16 |
| idx += 1 |
| |
| # Shards are sorted before deployment, to ensure all shards are correctly |
| # ordered 0 is padded to single digit shard counts |
| shard_name = "%s%s" % ("00"[len(str(idx)):], idx) |
| merged_dex_shard = utils.isolated_declare_file( |
| ctx, |
| "dex_shards/" + shard_name + ".zip", |
| sibling = sibling, |
| ) |
| utils.merge_dex_shards(ctx, shard_archives, merged_dex_shard) |
| merged_dex_shards.append(merged_dex_shard) |
| return merged_dex_shards |