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 15*9e965d6fSRomain Jobredeaux"""Bazel Android IDL library for the Android rules.""" 16*9e965d6fSRomain Jobredeaux 17*9e965d6fSRomain Jobredeauxload(":java.bzl", _java = "java") 18*9e965d6fSRomain Jobredeauxload(":path.bzl", _path = "path") 19*9e965d6fSRomain Jobredeauxload(":utils.bzl", "ANDROID_TOOLCHAIN_TYPE", _log = "log") 20*9e965d6fSRomain Jobredeaux 21*9e965d6fSRomain Jobredeaux_AIDL_TOOLCHAIN_MISSING_ERROR = ( 22*9e965d6fSRomain Jobredeaux "IDL sources provided without the Android IDL toolchain." 23*9e965d6fSRomain Jobredeaux) 24*9e965d6fSRomain Jobredeaux 25*9e965d6fSRomain Jobredeaux_AIDL_JAVA_ROOT_UNDETERMINABLE_ERROR = ( 26*9e965d6fSRomain Jobredeaux "Cannot determine java/javatests root for import %s." 27*9e965d6fSRomain Jobredeaux) 28*9e965d6fSRomain Jobredeaux 29*9e965d6fSRomain JobredeauxIDLContextInfo = provider( 30*9e965d6fSRomain Jobredeaux doc = "Contains data from processing Android IDL.", 31*9e965d6fSRomain Jobredeaux fields = dict( 32*9e965d6fSRomain Jobredeaux idl_srcs = "List of IDL sources", 33*9e965d6fSRomain Jobredeaux idl_import_root = "IDL import root", 34*9e965d6fSRomain Jobredeaux idl_java_srcs = "List of IDL Java sources", 35*9e965d6fSRomain Jobredeaux idl_deps = 36*9e965d6fSRomain Jobredeaux "List of IDL targets required for Java compilation, Proguard, etc.", 37*9e965d6fSRomain Jobredeaux providers = "The list of all providers to propagate.", 38*9e965d6fSRomain Jobredeaux ), 39*9e965d6fSRomain Jobredeaux) 40*9e965d6fSRomain Jobredeaux 41*9e965d6fSRomain Jobredeauxdef _gen_java_from_idl( 42*9e965d6fSRomain Jobredeaux ctx, 43*9e965d6fSRomain Jobredeaux out_idl_java_src = None, 44*9e965d6fSRomain Jobredeaux idl_src = None, 45*9e965d6fSRomain Jobredeaux transitive_idl_import_roots = [], 46*9e965d6fSRomain Jobredeaux transitive_idl_imports = [], 47*9e965d6fSRomain Jobredeaux transitive_idl_preprocessed = [], 48*9e965d6fSRomain Jobredeaux aidl = None, 49*9e965d6fSRomain Jobredeaux aidl_lib = None, 50*9e965d6fSRomain Jobredeaux aidl_framework = None, 51*9e965d6fSRomain Jobredeaux uses_aosp_compiler = False, 52*9e965d6fSRomain Jobredeaux idlopts = []): 53*9e965d6fSRomain Jobredeaux args = ctx.actions.args() 54*9e965d6fSRomain Jobredeaux 55*9e965d6fSRomain Jobredeaux # Note: at the moment (2022/11/07), the flags that the AOSP compiler accepts is a superset of 56*9e965d6fSRomain Jobredeaux # the Google3 compiler, but that might not be true in the future. 57*9e965d6fSRomain Jobredeaux if uses_aosp_compiler: 58*9e965d6fSRomain Jobredeaux args.add("--use-aosp-compiler") 59*9e965d6fSRomain Jobredeaux 60*9e965d6fSRomain Jobredeaux for opt in idlopts: 61*9e965d6fSRomain Jobredeaux args.add(opt) 62*9e965d6fSRomain Jobredeaux 63*9e965d6fSRomain Jobredeaux args.add("-b") # fail on parcelable 64*9e965d6fSRomain Jobredeaux args.add_all(transitive_idl_import_roots, format_each = "-I%s") 65*9e965d6fSRomain Jobredeaux args.add(aidl_framework, format = "-p%s") 66*9e965d6fSRomain Jobredeaux args.add_all(transitive_idl_preprocessed, format_each = "-p%s") 67*9e965d6fSRomain Jobredeaux args.add(idl_src) 68*9e965d6fSRomain Jobredeaux args.add(out_idl_java_src) 69*9e965d6fSRomain Jobredeaux 70*9e965d6fSRomain Jobredeaux aidl_lib_files = [aidl_lib.files] if aidl_lib else [] 71*9e965d6fSRomain Jobredeaux 72*9e965d6fSRomain Jobredeaux ctx.actions.run( 73*9e965d6fSRomain Jobredeaux executable = aidl, 74*9e965d6fSRomain Jobredeaux arguments = [args], 75*9e965d6fSRomain Jobredeaux inputs = depset( 76*9e965d6fSRomain Jobredeaux [aidl_framework], 77*9e965d6fSRomain Jobredeaux transitive = aidl_lib_files + [ 78*9e965d6fSRomain Jobredeaux transitive_idl_imports, 79*9e965d6fSRomain Jobredeaux transitive_idl_preprocessed, 80*9e965d6fSRomain Jobredeaux ], 81*9e965d6fSRomain Jobredeaux ), 82*9e965d6fSRomain Jobredeaux outputs = [out_idl_java_src], 83*9e965d6fSRomain Jobredeaux mnemonic = "AndroidIDLGenerate", 84*9e965d6fSRomain Jobredeaux progress_message = "Android IDL generation %s" % idl_src.path, 85*9e965d6fSRomain Jobredeaux toolchain = ANDROID_TOOLCHAIN_TYPE, 86*9e965d6fSRomain Jobredeaux ) 87*9e965d6fSRomain Jobredeaux 88*9e965d6fSRomain Jobredeauxdef _get_idl_import_root_path( 89*9e965d6fSRomain Jobredeaux package, 90*9e965d6fSRomain Jobredeaux idl_import_root, 91*9e965d6fSRomain Jobredeaux idl_file_root_path): 92*9e965d6fSRomain Jobredeaux package_path = _path.relative( 93*9e965d6fSRomain Jobredeaux idl_file_root_path, 94*9e965d6fSRomain Jobredeaux package, 95*9e965d6fSRomain Jobredeaux ) 96*9e965d6fSRomain Jobredeaux return _path.relative( 97*9e965d6fSRomain Jobredeaux package_path, 98*9e965d6fSRomain Jobredeaux idl_import_root, 99*9e965d6fSRomain Jobredeaux ) 100*9e965d6fSRomain Jobredeaux 101*9e965d6fSRomain Jobredeauxdef _collect_unique_idl_import_root_paths( 102*9e965d6fSRomain Jobredeaux package, 103*9e965d6fSRomain Jobredeaux idl_import_root, 104*9e965d6fSRomain Jobredeaux idl_imports): 105*9e965d6fSRomain Jobredeaux idl_import_roots = dict() 106*9e965d6fSRomain Jobredeaux for idl_import in idl_imports: 107*9e965d6fSRomain Jobredeaux idl_import_roots[_get_idl_import_root_path( 108*9e965d6fSRomain Jobredeaux package, 109*9e965d6fSRomain Jobredeaux idl_import_root, 110*9e965d6fSRomain Jobredeaux idl_import.root.path, 111*9e965d6fSRomain Jobredeaux )] = True 112*9e965d6fSRomain Jobredeaux return sorted(idl_import_roots.keys()) 113*9e965d6fSRomain Jobredeaux 114*9e965d6fSRomain Jobredeauxdef _collect_unique_java_roots(idl_imports): 115*9e965d6fSRomain Jobredeaux idl_import_roots = dict() 116*9e965d6fSRomain Jobredeaux for idl_import in idl_imports: 117*9e965d6fSRomain Jobredeaux java_root = _java.root(idl_import.path) 118*9e965d6fSRomain Jobredeaux if not java_root: 119*9e965d6fSRomain Jobredeaux _log.error(_AIDL_JAVA_ROOT_UNDETERMINABLE_ERROR % idl_import.path) 120*9e965d6fSRomain Jobredeaux idl_import_roots[java_root] = True 121*9e965d6fSRomain Jobredeaux return sorted(idl_import_roots.keys()) 122*9e965d6fSRomain Jobredeaux 123*9e965d6fSRomain Jobredeauxdef _determine_idl_import_roots( 124*9e965d6fSRomain Jobredeaux package, 125*9e965d6fSRomain Jobredeaux idl_import_root = None, 126*9e965d6fSRomain Jobredeaux idl_imports = []): 127*9e965d6fSRomain Jobredeaux if idl_import_root == None: 128*9e965d6fSRomain Jobredeaux return _collect_unique_java_roots(idl_imports) 129*9e965d6fSRomain Jobredeaux return _collect_unique_idl_import_root_paths( 130*9e965d6fSRomain Jobredeaux package, 131*9e965d6fSRomain Jobredeaux idl_import_root, 132*9e965d6fSRomain Jobredeaux idl_imports, 133*9e965d6fSRomain Jobredeaux ) 134*9e965d6fSRomain Jobredeaux 135*9e965d6fSRomain Jobredeauxdef _process( 136*9e965d6fSRomain Jobredeaux ctx, 137*9e965d6fSRomain Jobredeaux idl_srcs = [], 138*9e965d6fSRomain Jobredeaux idl_parcelables = [], 139*9e965d6fSRomain Jobredeaux idl_import_root = None, 140*9e965d6fSRomain Jobredeaux idl_preprocessed = [], 141*9e965d6fSRomain Jobredeaux deps = [], 142*9e965d6fSRomain Jobredeaux exports = [], 143*9e965d6fSRomain Jobredeaux aidl = None, 144*9e965d6fSRomain Jobredeaux aidl_lib = None, 145*9e965d6fSRomain Jobredeaux aidl_framework = None, 146*9e965d6fSRomain Jobredeaux uses_aosp_compiler = False, 147*9e965d6fSRomain Jobredeaux idlopts = []): 148*9e965d6fSRomain Jobredeaux """Processes Android IDL. 149*9e965d6fSRomain Jobredeaux 150*9e965d6fSRomain Jobredeaux Args: 151*9e965d6fSRomain Jobredeaux ctx: The context. 152*9e965d6fSRomain Jobredeaux idl_srcs: sequence of Files. A list of the aidl source files to be 153*9e965d6fSRomain Jobredeaux processed into Java source files and then compiled. Optional. 154*9e965d6fSRomain Jobredeaux idl_parcelables: sequence of Files. A list of Android IDL definitions to 155*9e965d6fSRomain Jobredeaux supply as imports. These files will be made available as imports for any 156*9e965d6fSRomain Jobredeaux android_library target that depends on this library, directly or via its 157*9e965d6fSRomain Jobredeaux transitive closure, but will not be translated to Java or compiled. 158*9e965d6fSRomain Jobredeaux 159*9e965d6fSRomain Jobredeaux Only .aidl files that correspond directly to .java sources in this library 160*9e965d6fSRomain Jobredeaux should be included (e.g. custom implementations of Parcelable), otherwise 161*9e965d6fSRomain Jobredeaux idl_srcs should be used. 162*9e965d6fSRomain Jobredeaux 163*9e965d6fSRomain Jobredeaux These files must be placed appropriately for the aidl compiler to find 164*9e965d6fSRomain Jobredeaux them. See the description of idl_import_root for information about what 165*9e965d6fSRomain Jobredeaux this means. Optional. 166*9e965d6fSRomain Jobredeaux idl_import_root: string. Package-relative path to the root of the java 167*9e965d6fSRomain Jobredeaux package tree containing idl sources included in this library. This path 168*9e965d6fSRomain Jobredeaux will be used as the import root when processing idl sources that depend on 169*9e965d6fSRomain Jobredeaux this library. 170*9e965d6fSRomain Jobredeaux 171*9e965d6fSRomain Jobredeaux When idl_import_root is specified, both idl_parcelables and idl_srcs must 172*9e965d6fSRomain Jobredeaux be at the path specified by the java package of the object they represent 173*9e965d6fSRomain Jobredeaux under idl_import_root. When idl_import_root is not specified, both 174*9e965d6fSRomain Jobredeaux idl_parcelables and idl_srcs must be at the path specified by their 175*9e965d6fSRomain Jobredeaux package under a Java root. Optional. 176*9e965d6fSRomain Jobredeaux idl_preprocessed: sequence of Files. A list of preprocessed Android IDL 177*9e965d6fSRomain Jobredeaux definitions to supply as imports. These files will be made available as 178*9e965d6fSRomain Jobredeaux imports for any android_library target that depends on this library, 179*9e965d6fSRomain Jobredeaux directly or via its transitive closure, but will not be translated to 180*9e965d6fSRomain Jobredeaux Java or compiled. 181*9e965d6fSRomain Jobredeaux 182*9e965d6fSRomain Jobredeaux Only preprocessed .aidl files that correspond directly to .java sources 183*9e965d6fSRomain Jobredeaux in this library should be included (e.g. custom implementations of 184*9e965d6fSRomain Jobredeaux Parcelable), otherwise use idl_srcs for Android IDL definitions that 185*9e965d6fSRomain Jobredeaux need to be translated to Java interfaces and use idl_parcelable for 186*9e965d6fSRomain Jobredeaux non-preprcessed AIDL files. Optional. 187*9e965d6fSRomain Jobredeaux deps: sequence of Targets. A list of dependencies. Optional. 188*9e965d6fSRomain Jobredeaux exports: sequence of Targets. A list of exports. Optional. 189*9e965d6fSRomain Jobredeaux aidl: Target. A target pointing to the aidl executable to be used for 190*9e965d6fSRomain Jobredeaux Java code generation from *.idl source files. Optional, unless idl_srcs 191*9e965d6fSRomain Jobredeaux are supplied. 192*9e965d6fSRomain Jobredeaux aidl_lib: Target. A target pointing to the aidl_lib library required 193*9e965d6fSRomain Jobredeaux during Java compilation when Java code is generated from idl sources. 194*9e965d6fSRomain Jobredeaux Optional. 195*9e965d6fSRomain Jobredeaux aidl_framework: Target. A target pointing to the aidl framework. Optional, 196*9e965d6fSRomain Jobredeaux unless idl_srcs are supplied. 197*9e965d6fSRomain Jobredeaux uses_aosp_compiler: boolean. If True, the upstream AOSP AIDL compiler is 198*9e965d6fSRomain Jobredeaux used instead of the Google3-only AIDL compiler. This allows wider range 199*9e965d6fSRomain Jobredeaux of AIDL language features including the structured parcelable, enum, 200*9e965d6fSRomain Jobredeaux union, and many more. On the other hand, using this may cause noticeable 201*9e965d6fSRomain Jobredeaux regression in terms of code size and performance as the compiler doesn't 202*9e965d6fSRomain Jobredeaux implement several optimization techniques that the Google3 compiler has. 203*9e965d6fSRomain Jobredeaux idlopts: list of string. Additional flags to add to the AOSP AIDL compiler 204*9e965d6fSRomain Jobredeaux invocation. 205*9e965d6fSRomain Jobredeaux 206*9e965d6fSRomain Jobredeaux Returns: 207*9e965d6fSRomain Jobredeaux A IDLContextInfo provider. 208*9e965d6fSRomain Jobredeaux """ 209*9e965d6fSRomain Jobredeaux if idl_srcs and not (aidl and aidl_framework): 210*9e965d6fSRomain Jobredeaux _log.error(_AIDL_TOOLCHAIN_MISSING_ERROR) 211*9e965d6fSRomain Jobredeaux 212*9e965d6fSRomain Jobredeaux transitive_idl_import_roots = [] 213*9e965d6fSRomain Jobredeaux transitive_idl_imports = [] 214*9e965d6fSRomain Jobredeaux transitive_idl_preprocessed = [] 215*9e965d6fSRomain Jobredeaux for dep in deps + exports: 216*9e965d6fSRomain Jobredeaux transitive_idl_import_roots.append(dep.transitive_idl_import_roots) 217*9e965d6fSRomain Jobredeaux transitive_idl_imports.append(dep.transitive_idl_imports) 218*9e965d6fSRomain Jobredeaux transitive_idl_preprocessed.append(dep.transitive_idl_preprocessed) 219*9e965d6fSRomain Jobredeaux 220*9e965d6fSRomain Jobredeaux idl_java_srcs = [] 221*9e965d6fSRomain Jobredeaux for idl_src in idl_srcs: 222*9e965d6fSRomain Jobredeaux idl_java_src = ctx.actions.declare_file( 223*9e965d6fSRomain Jobredeaux ctx.label.name + "_aidl/" + idl_src.path.replace(".aidl", ".java"), 224*9e965d6fSRomain Jobredeaux ) 225*9e965d6fSRomain Jobredeaux idl_java_srcs.append(idl_java_src) 226*9e965d6fSRomain Jobredeaux _gen_java_from_idl( 227*9e965d6fSRomain Jobredeaux ctx, 228*9e965d6fSRomain Jobredeaux out_idl_java_src = idl_java_src, 229*9e965d6fSRomain Jobredeaux idl_src = idl_src, 230*9e965d6fSRomain Jobredeaux transitive_idl_import_roots = depset( 231*9e965d6fSRomain Jobredeaux _determine_idl_import_roots( 232*9e965d6fSRomain Jobredeaux ctx.label.package, 233*9e965d6fSRomain Jobredeaux idl_import_root, 234*9e965d6fSRomain Jobredeaux idl_parcelables + idl_srcs, 235*9e965d6fSRomain Jobredeaux ), 236*9e965d6fSRomain Jobredeaux transitive = transitive_idl_import_roots, 237*9e965d6fSRomain Jobredeaux order = "preorder", 238*9e965d6fSRomain Jobredeaux ), 239*9e965d6fSRomain Jobredeaux transitive_idl_imports = depset( 240*9e965d6fSRomain Jobredeaux idl_parcelables + idl_srcs, 241*9e965d6fSRomain Jobredeaux transitive = transitive_idl_imports, 242*9e965d6fSRomain Jobredeaux order = "preorder", 243*9e965d6fSRomain Jobredeaux ), 244*9e965d6fSRomain Jobredeaux transitive_idl_preprocessed = depset( 245*9e965d6fSRomain Jobredeaux transitive = transitive_idl_preprocessed, 246*9e965d6fSRomain Jobredeaux ), 247*9e965d6fSRomain Jobredeaux aidl = aidl, 248*9e965d6fSRomain Jobredeaux aidl_lib = aidl_lib, 249*9e965d6fSRomain Jobredeaux aidl_framework = aidl_framework, 250*9e965d6fSRomain Jobredeaux uses_aosp_compiler = uses_aosp_compiler, 251*9e965d6fSRomain Jobredeaux idlopts = idlopts, 252*9e965d6fSRomain Jobredeaux ) 253*9e965d6fSRomain Jobredeaux 254*9e965d6fSRomain Jobredeaux return IDLContextInfo( 255*9e965d6fSRomain Jobredeaux idl_srcs = idl_srcs, 256*9e965d6fSRomain Jobredeaux idl_import_root = idl_import_root, 257*9e965d6fSRomain Jobredeaux idl_java_srcs = idl_java_srcs, 258*9e965d6fSRomain Jobredeaux idl_deps = [aidl_lib] if (idl_java_srcs and aidl_lib) else [], 259*9e965d6fSRomain Jobredeaux providers = [ 260*9e965d6fSRomain Jobredeaux # TODO(b/146216105): Make this a Starlark provider. 261*9e965d6fSRomain Jobredeaux AndroidIdlInfo( 262*9e965d6fSRomain Jobredeaux depset( 263*9e965d6fSRomain Jobredeaux _determine_idl_import_roots( 264*9e965d6fSRomain Jobredeaux ctx.label.package, 265*9e965d6fSRomain Jobredeaux idl_import_root, 266*9e965d6fSRomain Jobredeaux idl_parcelables + idl_srcs + idl_preprocessed, 267*9e965d6fSRomain Jobredeaux ), 268*9e965d6fSRomain Jobredeaux transitive = transitive_idl_import_roots, 269*9e965d6fSRomain Jobredeaux order = "preorder", 270*9e965d6fSRomain Jobredeaux ), 271*9e965d6fSRomain Jobredeaux depset( 272*9e965d6fSRomain Jobredeaux idl_parcelables + idl_srcs + idl_preprocessed, 273*9e965d6fSRomain Jobredeaux transitive = transitive_idl_imports, 274*9e965d6fSRomain Jobredeaux order = "preorder", 275*9e965d6fSRomain Jobredeaux ), 276*9e965d6fSRomain Jobredeaux depset(), # TODO(b/146216105): Delete this field once in Starlark. 277*9e965d6fSRomain Jobredeaux depset(idl_preprocessed, transitive = transitive_idl_preprocessed), 278*9e965d6fSRomain Jobredeaux ), 279*9e965d6fSRomain Jobredeaux ], 280*9e965d6fSRomain Jobredeaux ) 281*9e965d6fSRomain Jobredeaux 282*9e965d6fSRomain Jobredeauxidl = struct( 283*9e965d6fSRomain Jobredeaux process = _process, 284*9e965d6fSRomain Jobredeaux) 285*9e965d6fSRomain Jobredeaux 286*9e965d6fSRomain Jobredeaux# Visible for testing. 287*9e965d6fSRomain Jobredeauxtesting = struct( 288*9e965d6fSRomain Jobredeaux get_idl_import_root_path = _get_idl_import_root_path, 289*9e965d6fSRomain Jobredeaux) 290