1*9e965d6fSRomain Jobredeaux# Copyright 2018 The Bazel Authors. All rights reserved. 2*9e965d6fSRomain Jobredeaux# 3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License"); 4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License. 5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at 6*9e965d6fSRomain Jobredeaux# 7*9e965d6fSRomain Jobredeaux# http://www.apache.org/licenses/LICENSE-2.0 8*9e965d6fSRomain Jobredeaux# 9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software 10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS, 11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and 13*9e965d6fSRomain Jobredeaux# limitations under the License. 14*9e965d6fSRomain Jobredeaux"""Transform contains data transformation methods.""" 15*9e965d6fSRomain Jobredeaux 16*9e965d6fSRomain Jobredeauxload(":constants.bzl", "constants") 17*9e965d6fSRomain Jobredeauxload(":utils.bzl", "utils") 18*9e965d6fSRomain Jobredeauxload("//rules/flags:flags.bzl", _flags = "flags") 19*9e965d6fSRomain Jobredeaux 20*9e965d6fSRomain Jobredeauxdef _declare_file(ctx, filename, sibling = None): 21*9e965d6fSRomain Jobredeaux return utils.isolated_declare_file(ctx, filename, sibling = sibling) 22*9e965d6fSRomain Jobredeaux 23*9e965d6fSRomain Jobredeauxdef filter_jars(name, data): 24*9e965d6fSRomain Jobredeaux """Filters out files that are not compiled Jars - includes header Jars. 25*9e965d6fSRomain Jobredeaux 26*9e965d6fSRomain Jobredeaux Args: 27*9e965d6fSRomain Jobredeaux name: Name of the file to filter, check uses endswith on the path. 28*9e965d6fSRomain Jobredeaux data: The list of tuples where each entry contains the originating file path 29*9e965d6fSRomain Jobredeaux and file to apply the filter. 30*9e965d6fSRomain Jobredeaux 31*9e965d6fSRomain Jobredeaux Returns: 32*9e965d6fSRomain Jobredeaux A list of tuples where each entry contains the originating Jar path and the 33*9e965d6fSRomain Jobredeaux Jar file. 34*9e965d6fSRomain Jobredeaux """ 35*9e965d6fSRomain Jobredeaux return [jar for jar in data if not jar.path.endswith(name)] 36*9e965d6fSRomain Jobredeaux 37*9e965d6fSRomain Jobredeauxdef dex( 38*9e965d6fSRomain Jobredeaux ctx, 39*9e965d6fSRomain Jobredeaux data, 40*9e965d6fSRomain Jobredeaux deps = constants.EMPTY_LIST, 41*9e965d6fSRomain Jobredeaux num_shards = None, 42*9e965d6fSRomain Jobredeaux create_file = _declare_file, 43*9e965d6fSRomain Jobredeaux desugar = True): 44*9e965d6fSRomain Jobredeaux """Dex a list of Jars. 45*9e965d6fSRomain Jobredeaux 46*9e965d6fSRomain Jobredeaux Args: 47*9e965d6fSRomain Jobredeaux ctx: The context. 48*9e965d6fSRomain Jobredeaux data: The list of tuples where each entry contains the originating Jar 49*9e965d6fSRomain Jobredeaux path and the Jar to Dex. 50*9e965d6fSRomain Jobredeaux deps: The list of dependencies for the Jar being desugared. 51*9e965d6fSRomain Jobredeaux num_shards: The number of shards to distribute the dexed files across, 52*9e965d6fSRomain Jobredeaux this value overrides the default provided by ctx.attr._mi_dex_shards. 53*9e965d6fSRomain Jobredeaux create_file: In rare occasions a custom method is required to 54*9e965d6fSRomain Jobredeaux create a unique file, override the default here. The method must 55*9e965d6fSRomain Jobredeaux implement the following interface: 56*9e965d6fSRomain Jobredeaux 57*9e965d6fSRomain Jobredeaux def create_file(ctx, filename, sibling = None) 58*9e965d6fSRomain Jobredeaux Args: 59*9e965d6fSRomain Jobredeaux ctx: The context. 60*9e965d6fSRomain Jobredeaux filename: string. The name of the file. 61*9e965d6fSRomain Jobredeaux sibling: File. The location of the new file. 62*9e965d6fSRomain Jobredeaux 63*9e965d6fSRomain Jobredeaux Returns: 64*9e965d6fSRomain Jobredeaux A File. 65*9e965d6fSRomain Jobredeaux desugar: A boolean that determines whether to apply desugaring. 66*9e965d6fSRomain Jobredeaux 67*9e965d6fSRomain Jobredeaux Returns: 68*9e965d6fSRomain Jobredeaux A list of tuples where each entry contains the originating Jar path and 69*9e965d6fSRomain Jobredeaux the Dex shards. 70*9e965d6fSRomain Jobredeaux """ 71*9e965d6fSRomain Jobredeaux if num_shards: 72*9e965d6fSRomain Jobredeaux num_dex_shards = num_shards 73*9e965d6fSRomain Jobredeaux elif _flags.get(ctx).use_custom_dex_shards: 74*9e965d6fSRomain Jobredeaux num_dex_shards = _flags.get(ctx).num_dex_shards 75*9e965d6fSRomain Jobredeaux else: 76*9e965d6fSRomain Jobredeaux num_dex_shards = ctx.attr._mi_dex_shards 77*9e965d6fSRomain Jobredeaux 78*9e965d6fSRomain Jobredeaux dex_files = [] 79*9e965d6fSRomain Jobredeaux for jar in data: 80*9e965d6fSRomain Jobredeaux out_dex_shards = [] 81*9e965d6fSRomain Jobredeaux dirname = jar.basename + "_dex" 82*9e965d6fSRomain Jobredeaux for i in range(num_shards or num_dex_shards): 83*9e965d6fSRomain Jobredeaux out_dex_shards.append(create_file( 84*9e965d6fSRomain Jobredeaux ctx, 85*9e965d6fSRomain Jobredeaux dirname + "/" + str(i) + ".zip", 86*9e965d6fSRomain Jobredeaux sibling = jar, 87*9e965d6fSRomain Jobredeaux )) 88*9e965d6fSRomain Jobredeaux utils.dex(ctx, jar, out_dex_shards, deps, desugar) 89*9e965d6fSRomain Jobredeaux dex_files.append(out_dex_shards) 90*9e965d6fSRomain Jobredeaux return dex_files 91*9e965d6fSRomain Jobredeaux 92*9e965d6fSRomain Jobredeauxdef extract_jar_resources(ctx, data, create_file = _declare_file): 93*9e965d6fSRomain Jobredeaux """Extracts the non-class files from the list of Jars. 94*9e965d6fSRomain Jobredeaux 95*9e965d6fSRomain Jobredeaux Args: 96*9e965d6fSRomain Jobredeaux ctx: The context 97*9e965d6fSRomain Jobredeaux data: The list of tuples where each entry contains the originating Jar 98*9e965d6fSRomain Jobredeaux path and the Jar with resources to extract. 99*9e965d6fSRomain Jobredeaux create_file: In rare occasions a custom method is required to 100*9e965d6fSRomain Jobredeaux create a unique file, override the default here. The method must 101*9e965d6fSRomain Jobredeaux implement the following interface: 102*9e965d6fSRomain Jobredeaux 103*9e965d6fSRomain Jobredeaux def create_file(ctx, filename, sibling = None) 104*9e965d6fSRomain Jobredeaux Args: 105*9e965d6fSRomain Jobredeaux ctx: The context. 106*9e965d6fSRomain Jobredeaux filename: string. The name of the file. 107*9e965d6fSRomain Jobredeaux sibling: File. The location of the new file. 108*9e965d6fSRomain Jobredeaux 109*9e965d6fSRomain Jobredeaux Returns: 110*9e965d6fSRomain Jobredeaux A File. 111*9e965d6fSRomain Jobredeaux 112*9e965d6fSRomain Jobredeaux Returns: 113*9e965d6fSRomain Jobredeaux A list of extracted resource zips. 114*9e965d6fSRomain Jobredeaux """ 115*9e965d6fSRomain Jobredeaux resources_files = [] 116*9e965d6fSRomain Jobredeaux for jar in data: 117*9e965d6fSRomain Jobredeaux out_resources_file = create_file( 118*9e965d6fSRomain Jobredeaux ctx, 119*9e965d6fSRomain Jobredeaux jar.basename + "_resources.zip", 120*9e965d6fSRomain Jobredeaux sibling = jar, 121*9e965d6fSRomain Jobredeaux ) 122*9e965d6fSRomain Jobredeaux utils.extract_jar_resources(ctx, jar, out_resources_file) 123*9e965d6fSRomain Jobredeaux resources_files.append(out_resources_file) 124*9e965d6fSRomain Jobredeaux return resources_files 125*9e965d6fSRomain Jobredeaux 126*9e965d6fSRomain Jobredeauxdef merge_dex_shards(ctx, data, sibling): 127*9e965d6fSRomain Jobredeaux """Merges all dex files in the transitive deps to a dex per shard. 128*9e965d6fSRomain Jobredeaux 129*9e965d6fSRomain Jobredeaux Given a list of dex files (and resources.zips) this will create an 130*9e965d6fSRomain Jobredeaux action per shard that runs dex_shard_merger on all dex files within that 131*9e965d6fSRomain Jobredeaux shard. 132*9e965d6fSRomain Jobredeaux 133*9e965d6fSRomain Jobredeaux Arguments: 134*9e965d6fSRomain Jobredeaux ctx: The context. 135*9e965d6fSRomain Jobredeaux data: A list of lists, where the inner list contains dex shards. 136*9e965d6fSRomain Jobredeaux sibling: A file used to root the merged_dex shards. 137*9e965d6fSRomain Jobredeaux 138*9e965d6fSRomain Jobredeaux Returns: 139*9e965d6fSRomain Jobredeaux A list of merged dex shards. 140*9e965d6fSRomain Jobredeaux """ 141*9e965d6fSRomain Jobredeaux merged_dex_shards = [] 142*9e965d6fSRomain Jobredeaux for idx, shard in enumerate(data): 143*9e965d6fSRomain Jobredeaux # To ensure resource is added at the beginning, R.zip is named as 00.zip 144*9e965d6fSRomain Jobredeaux # Thus data shards starts from 1 instead of 0 and ranges through 16 145*9e965d6fSRomain Jobredeaux idx += 1 146*9e965d6fSRomain Jobredeaux 147*9e965d6fSRomain Jobredeaux # Shards are sorted before deployment, to ensure all shards are correctly 148*9e965d6fSRomain Jobredeaux # ordered 0 is padded to single digit shard counts 149*9e965d6fSRomain Jobredeaux shard_name = "%s%s" % ("00"[len(str(idx)):], idx) 150*9e965d6fSRomain Jobredeaux merged_dex_shard = utils.isolated_declare_file( 151*9e965d6fSRomain Jobredeaux ctx, 152*9e965d6fSRomain Jobredeaux "dex_shards/" + shard_name + ".zip", 153*9e965d6fSRomain Jobredeaux sibling = sibling, 154*9e965d6fSRomain Jobredeaux ) 155*9e965d6fSRomain Jobredeaux utils.merge_dex_shards(ctx, shard, merged_dex_shard) 156*9e965d6fSRomain Jobredeaux merged_dex_shards.append(merged_dex_shard) 157*9e965d6fSRomain Jobredeaux return merged_dex_shards 158