1// Copyright 2019 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "fmt" 19 "io" 20 21 "android/soong/android" 22 "android/soong/dexpreopt" 23 24 "github.com/google/blueprint/depset" 25) 26 27type DeviceHostConverter struct { 28 android.ModuleBase 29 android.DefaultableModuleBase 30 31 properties DeviceHostConverterProperties 32 33 headerJars android.Paths 34 implementationJars android.Paths 35 implementationAndResourceJars android.Paths 36 resourceJars android.Paths 37 38 srcJarArgs []string 39 srcJarDeps android.Paths 40 41 combinedHeaderJar android.Path 42 combinedImplementationJar android.Path 43} 44 45type DeviceHostConverterProperties struct { 46 // List of modules whose contents will be visible to modules that depend on this module. 47 Libs []string 48} 49 50type DeviceForHost struct { 51 DeviceHostConverter 52} 53 54// java_device_for_host makes the classes.jar output of a device java_library module available to host 55// java_library modules. 56// 57// It is rarely necessary, and its usage is restricted to a few allowed projects. 58func DeviceForHostFactory() android.Module { 59 module := &DeviceForHost{} 60 61 module.AddProperties(&module.properties) 62 63 InitJavaModule(module, android.HostSupported) 64 return module 65} 66 67type HostForDevice struct { 68 DeviceHostConverter 69} 70 71// java_host_for_device makes the classes.jar output of a host java_library module available to device 72// java_library modules. 73// 74// It is rarely necessary, and its usage is restricted to a few allowed projects. 75func HostForDeviceFactory() android.Module { 76 module := &HostForDevice{} 77 78 module.AddProperties(&module.properties) 79 80 InitJavaModule(module, android.DeviceSupported) 81 return module 82} 83 84var deviceHostConverterDepTag = dependencyTag{name: "device_host_converter"} 85 86func (d *DeviceForHost) DepsMutator(ctx android.BottomUpMutatorContext) { 87 ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), 88 deviceHostConverterDepTag, d.properties.Libs...) 89} 90 91func (d *HostForDevice) DepsMutator(ctx android.BottomUpMutatorContext) { 92 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), 93 deviceHostConverterDepTag, d.properties.Libs...) 94} 95 96func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleContext) { 97 if len(d.properties.Libs) < 1 { 98 ctx.PropertyErrorf("libs", "at least one dependency is required") 99 } 100 101 var transitiveHeaderJars []depset.DepSet[android.Path] 102 var transitiveImplementationJars []depset.DepSet[android.Path] 103 var transitiveResourceJars []depset.DepSet[android.Path] 104 105 ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) { 106 if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { 107 d.headerJars = append(d.headerJars, dep.HeaderJars...) 108 d.implementationJars = append(d.implementationJars, dep.ImplementationJars...) 109 d.implementationAndResourceJars = append(d.implementationAndResourceJars, dep.ImplementationAndResourcesJars...) 110 d.resourceJars = append(d.resourceJars, dep.ResourceJars...) 111 112 d.srcJarArgs = append(d.srcJarArgs, dep.SrcJarArgs...) 113 d.srcJarDeps = append(d.srcJarDeps, dep.SrcJarDeps...) 114 115 transitiveHeaderJars = append(transitiveHeaderJars, dep.TransitiveStaticLibsHeaderJars) 116 transitiveImplementationJars = append(transitiveImplementationJars, dep.TransitiveStaticLibsImplementationJars) 117 transitiveResourceJars = append(transitiveResourceJars, dep.TransitiveStaticLibsResourceJars) 118 } else { 119 ctx.PropertyErrorf("libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m)) 120 } 121 }) 122 123 jarName := ctx.ModuleName() + ".jar" 124 125 if len(d.implementationAndResourceJars) > 1 { 126 outputFile := android.PathForModuleOut(ctx, "combined", jarName) 127 TransformJarsToJar(ctx, outputFile, "combine", d.implementationAndResourceJars, 128 android.OptionalPath{}, false, nil, nil) 129 d.combinedImplementationJar = outputFile 130 } else if len(d.implementationAndResourceJars) == 1 { 131 d.combinedImplementationJar = d.implementationAndResourceJars[0] 132 } 133 134 if len(d.headerJars) > 1 { 135 outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName) 136 TransformJarsToJar(ctx, outputFile, "turbine combine", d.headerJars, 137 android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"}) 138 d.combinedHeaderJar = outputFile 139 } else if len(d.headerJars) == 1 { 140 d.combinedHeaderJar = d.headerJars[0] 141 } 142 143 android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{ 144 HeaderJars: d.headerJars, 145 LocalHeaderJars: d.headerJars, 146 TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, nil, transitiveHeaderJars), 147 TransitiveStaticLibsImplementationJars: depset.New(depset.PREORDER, nil, transitiveImplementationJars), 148 TransitiveStaticLibsResourceJars: depset.New(depset.PREORDER, nil, transitiveResourceJars), 149 ImplementationAndResourcesJars: d.implementationAndResourceJars, 150 ImplementationJars: d.implementationJars, 151 ResourceJars: d.resourceJars, 152 SrcJarArgs: d.srcJarArgs, 153 SrcJarDeps: d.srcJarDeps, 154 StubsLinkType: Implementation, 155 // TODO: Not sure if aconfig flags that have been moved between device and host variants 156 // make sense. 157 }) 158 159} 160 161func (d *DeviceHostConverter) HeaderJars() android.Paths { 162 return d.headerJars 163} 164 165func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths { 166 return d.implementationAndResourceJars 167} 168 169func (d *DeviceHostConverter) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path { 170 return nil 171} 172 173func (d *DeviceHostConverter) DexJarInstallPath() android.Path { 174 return nil 175} 176 177func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths { 178 return nil 179} 180 181func (d *DeviceHostConverter) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { 182 return nil 183} 184 185func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path { 186 return nil 187} 188 189func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData { 190 return android.AndroidMkData{ 191 Class: "JAVA_LIBRARIES", 192 OutputFile: android.OptionalPathForPath(d.combinedImplementationJar), 193 // Make does not support Windows Java modules 194 Disabled: d.Os() == android.Windows, 195 Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", 196 Extra: []android.AndroidMkExtraFunc{ 197 func(w io.Writer, outputFile android.Path) { 198 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") 199 fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", d.combinedHeaderJar.String()) 200 fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", d.combinedImplementationJar.String()) 201 }, 202 }, 203 } 204} 205 206// implement the following interface for IDE completion. 207var _ android.IDEInfo = (*DeviceHostConverter)(nil) 208 209func (d *DeviceHostConverter) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) { 210 ideInfo.Deps = append(ideInfo.Deps, d.properties.Libs...) 211 ideInfo.Libs = append(ideInfo.Libs, d.properties.Libs...) 212} 213