blob: 357dc2c76e8471405a55e944d8703fbea80d805a [file] [log] [blame]
LaMont Jones8546f0c2025-01-30 13:51:14 -08001// 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 "github.com/google/blueprint/proptools"
26)
27
28type GenruleCombiner struct {
29 android.ModuleBase
30 android.DefaultableModuleBase
31
32 genruleCombinerProperties GenruleCombinerProperties
33
34 headerJars android.Paths
35 implementationJars android.Paths
36 implementationAndResourceJars android.Paths
37 resourceJars android.Paths
38 aconfigProtoFiles android.Paths
39
40 srcJarArgs []string
41 srcJarDeps android.Paths
42
43 headerDirs android.Paths
44
45 combinedHeaderJar android.Path
46 combinedImplementationJar android.Path
47}
48
49type GenruleCombinerProperties struct {
50 // List of modules whose implementation (and resources) jars will be visible to modules
51 // that depend on this module.
52 Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
53
54 // List of modules whose header jars will be visible to modules that depend on this module.
55 Headers proptools.Configurable[[]string] `android:"arch_variant"`
56}
57
58// java_genrule_combiner provides the implementation and resource jars from `static_libs`, with
59// the header jars from `headers`.
60//
61// This is useful when a java_genrule is used to change the implementation of a java library
62// without requiring a change in the header jars.
63func GenruleCombinerFactory() android.Module {
64 module := &GenruleCombiner{}
65
66 module.AddProperties(&module.genruleCombinerProperties)
67 InitJavaModule(module, android.HostAndDeviceSupported)
68 return module
69}
70
71var genruleCombinerHeaderDepTag = dependencyTag{name: "genrule_combiner_header"}
72
73func (j *GenruleCombiner) DepsMutator(ctx android.BottomUpMutatorContext) {
74 ctx.AddVariationDependencies(nil, staticLibTag,
75 j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
76 ctx.AddVariationDependencies(nil, genruleCombinerHeaderDepTag,
77 j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
78}
79
80func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext) {
81 if len(j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)) < 1 {
82 ctx.PropertyErrorf("static_libs", "at least one dependency is required")
83 }
84
85 if len(j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)) < 1 {
86 ctx.PropertyErrorf("headers", "at least one dependency is required")
87 }
88
89 var transitiveHeaderJars []depset.DepSet[android.Path]
90 var transitiveImplementationJars []depset.DepSet[android.Path]
91 var transitiveResourceJars []depset.DepSet[android.Path]
92 var sdkVersion android.SdkSpec
93 var stubsLinkType StubsLinkType
94 moduleWithSdkDepInfo := &ModuleWithSdkDepInfo{}
95
96 // Collect the headers first, so that aconfig flag values for the libraries will override
97 // values from the headers (if they are different).
98 ctx.VisitDirectDepsWithTag(genruleCombinerHeaderDepTag, func(m android.Module) {
99 if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
100 j.headerJars = append(j.headerJars, dep.HeaderJars...)
101
102 j.srcJarArgs = append(j.srcJarArgs, dep.SrcJarArgs...)
103 j.srcJarDeps = append(j.srcJarDeps, dep.SrcJarDeps...)
104 j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
105 sdkVersion = dep.SdkVersion
106 stubsLinkType = dep.StubsLinkType
107 *moduleWithSdkDepInfo = *dep.ModuleWithSdkDepInfo
108
109 transitiveHeaderJars = append(transitiveHeaderJars, dep.TransitiveStaticLibsHeaderJars)
110 } else if dep, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
111 j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
112 } else {
113 ctx.PropertyErrorf("headers", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
114 }
115 })
116 ctx.VisitDirectDepsWithTag(staticLibTag, func(m android.Module) {
117 if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
118 j.implementationJars = append(j.implementationJars, dep.ImplementationJars...)
119 j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.ImplementationAndResourcesJars...)
120 j.resourceJars = append(j.resourceJars, dep.ResourceJars...)
121
122 transitiveImplementationJars = append(transitiveImplementationJars, dep.TransitiveStaticLibsImplementationJars)
123 transitiveResourceJars = append(transitiveResourceJars, dep.TransitiveStaticLibsResourceJars)
124 j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
125 } else if dep, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
126 // This is provided by `java_genrule` modules.
127 j.implementationJars = append(j.implementationJars, dep.DefaultOutputFiles...)
128 j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.DefaultOutputFiles...)
129 stubsLinkType = Implementation
130 } else {
131 ctx.PropertyErrorf("static_libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
132 }
133 })
134
135 jarName := ctx.ModuleName() + ".jar"
136
137 if len(j.implementationAndResourceJars) > 1 {
138 outputFile := android.PathForModuleOut(ctx, "combined", jarName)
139 TransformJarsToJar(ctx, outputFile, "combine", j.implementationAndResourceJars,
140 android.OptionalPath{}, false, nil, nil)
141 j.combinedImplementationJar = outputFile
142 } else if len(j.implementationAndResourceJars) == 1 {
143 j.combinedImplementationJar = j.implementationAndResourceJars[0]
144 }
145
146 if len(j.headerJars) > 1 {
147 outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
148 TransformJarsToJar(ctx, outputFile, "turbine combine", j.headerJars,
149 android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"})
150 j.combinedHeaderJar = outputFile
151 j.headerDirs = append(j.headerDirs, android.PathForModuleOut(ctx, "turbine-combined"))
152 } else if len(j.headerJars) == 1 {
153 j.combinedHeaderJar = j.headerJars[0]
154 }
155
156 javaInfo := &JavaInfo{
157 HeaderJars: android.Paths{j.combinedHeaderJar},
158 LocalHeaderJars: android.Paths{j.combinedHeaderJar},
159 TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, android.Paths{j.combinedHeaderJar}, transitiveHeaderJars),
160 TransitiveStaticLibsImplementationJars: depset.New(depset.PREORDER, android.Paths{j.combinedImplementationJar}, transitiveImplementationJars),
161 TransitiveStaticLibsResourceJars: depset.New(depset.PREORDER, nil, transitiveResourceJars),
162 GeneratedSrcjars: android.Paths{j.combinedImplementationJar},
163 ImplementationAndResourcesJars: android.Paths{j.combinedImplementationJar},
164 ImplementationJars: android.Paths{j.combinedImplementationJar},
165 ModuleWithSdkDepInfo: moduleWithSdkDepInfo,
166 ResourceJars: j.resourceJars,
167 OutputFile: j.combinedImplementationJar,
168 SdkVersion: sdkVersion,
169 SrcJarArgs: j.srcJarArgs,
170 SrcJarDeps: j.srcJarDeps,
171 StubsLinkType: stubsLinkType,
172 AconfigIntermediateCacheOutputPaths: j.aconfigProtoFiles,
173 }
174 setExtraJavaInfo(ctx, j, javaInfo)
175 ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, "")
176 ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, android.DefaultDistTag)
177 ctx.SetOutputFiles(javaInfo.ImplementationAndResourcesJars, ".jar")
178 ctx.SetOutputFiles(javaInfo.HeaderJars, ".hjar")
179 android.SetProvider(ctx, JavaInfoProvider, javaInfo)
180
181}
182
183func (j *GenruleCombiner) GeneratedSourceFiles() android.Paths {
184 return append(android.Paths{}, j.combinedImplementationJar)
185}
186
187func (j *GenruleCombiner) GeneratedHeaderDirs() android.Paths {
188 return append(android.Paths{}, j.headerDirs...)
189}
190
191func (j *GenruleCombiner) GeneratedDeps() android.Paths {
192 return append(android.Paths{}, j.combinedImplementationJar)
193}
194
195func (j *GenruleCombiner) Srcs() android.Paths {
196 return append(android.Paths{}, j.implementationAndResourceJars...)
197}
198
199func (j *GenruleCombiner) HeaderJars() android.Paths {
200 return j.headerJars
201}
202
203func (j *GenruleCombiner) ImplementationAndResourcesJars() android.Paths {
204 return j.implementationAndResourceJars
205}
206
207func (j *GenruleCombiner) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
208 return nil
209}
210
211func (j *GenruleCombiner) DexJarInstallPath() android.Path {
212 return nil
213}
214
215func (j *GenruleCombiner) AidlIncludeDirs() android.Paths {
216 return nil
217}
218
219func (j *GenruleCombiner) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
220 return nil
221}
222
223func (j *GenruleCombiner) JacocoReportClassesFile() android.Path {
224 return nil
225}
226
227func (j *GenruleCombiner) AndroidMk() android.AndroidMkData {
228 return android.AndroidMkData{
229 Class: "JAVA_LIBRARIES",
230 OutputFile: android.OptionalPathForPath(j.combinedImplementationJar),
231 // Make does not support Windows Java modules
232 Disabled: j.Os() == android.Windows,
233 Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
234 Extra: []android.AndroidMkExtraFunc{
235 func(w io.Writer, outputFile android.Path) {
236 fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
237 fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", j.combinedHeaderJar.String())
238 fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", j.combinedImplementationJar.String())
239 },
240 },
241 }
242}
243
244// implement the following interface for IDE completion.
245var _ android.IDEInfo = (*GenruleCombiner)(nil)
246
247func (j *GenruleCombiner) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) {
248 ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
249 ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
250 ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
251 ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
252}