blob: 63bb1b73ba7e0f3f11431b47e89eec4b987bce41 [file] [log] [blame]
Jiyong Park9b409bc2019-10-11 14:59:13 +09001// Copyright (C) 2019 The Android Open Source Project
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 sdk
16
17import (
18 "fmt"
Jiyong Park9b409bc2019-10-11 14:59:13 +090019 "path/filepath"
Paul Duffinb645ec82019-11-27 17:43:54 +000020 "reflect"
Jiyong Park9b409bc2019-10-11 14:59:13 +090021 "strings"
22
Paul Duffin375058f2019-11-29 20:17:53 +000023 "github.com/google/blueprint"
Jiyong Park9b409bc2019-10-11 14:59:13 +090024 "github.com/google/blueprint/proptools"
25
26 "android/soong/android"
Jiyong Park73c54ee2019-10-22 20:31:18 +090027 "android/soong/cc"
Jiyong Park9b409bc2019-10-11 14:59:13 +090028 "android/soong/java"
29)
30
31var pctx = android.NewPackageContext("android/soong/sdk")
32
Paul Duffin375058f2019-11-29 20:17:53 +000033var (
34 repackageZip = pctx.AndroidStaticRule("SnapshotRepackageZip",
35 blueprint.RuleParams{
36 Command: `${config.Zip2ZipCmd} -i $in -o $out "**/*:$destdir"`,
37 CommandDeps: []string{
38 "${config.Zip2ZipCmd}",
39 },
40 },
41 "destdir")
42
43 zipFiles = pctx.AndroidStaticRule("SnapshotZipFiles",
44 blueprint.RuleParams{
45 Command: `${config.SoongZipCmd} -C $basedir -l $out.rsp -o $out`,
46 CommandDeps: []string{
47 "${config.SoongZipCmd}",
48 },
49 Rspfile: "$out.rsp",
50 RspfileContent: "$in",
51 },
52 "basedir")
53
54 mergeZips = pctx.AndroidStaticRule("SnapshotMergeZips",
55 blueprint.RuleParams{
56 Command: `${config.MergeZipsCmd} $out $in`,
57 CommandDeps: []string{
58 "${config.MergeZipsCmd}",
59 },
60 })
61)
62
Paul Duffinb645ec82019-11-27 17:43:54 +000063type generatedContents struct {
Jiyong Park73c54ee2019-10-22 20:31:18 +090064 content strings.Builder
65 indentLevel int
Jiyong Park9b409bc2019-10-11 14:59:13 +090066}
67
Paul Duffinb645ec82019-11-27 17:43:54 +000068// generatedFile abstracts operations for writing contents into a file and emit a build rule
69// for the file.
70type generatedFile struct {
71 generatedContents
72 path android.OutputPath
73}
74
Jiyong Park232e7852019-11-04 12:23:40 +090075func newGeneratedFile(ctx android.ModuleContext, path ...string) *generatedFile {
Jiyong Park9b409bc2019-10-11 14:59:13 +090076 return &generatedFile{
Paul Duffinb645ec82019-11-27 17:43:54 +000077 path: android.PathForModuleOut(ctx, path...).OutputPath,
Jiyong Park9b409bc2019-10-11 14:59:13 +090078 }
79}
80
Paul Duffinb645ec82019-11-27 17:43:54 +000081func (gc *generatedContents) Indent() {
82 gc.indentLevel++
Jiyong Park73c54ee2019-10-22 20:31:18 +090083}
84
Paul Duffinb645ec82019-11-27 17:43:54 +000085func (gc *generatedContents) Dedent() {
86 gc.indentLevel--
Jiyong Park73c54ee2019-10-22 20:31:18 +090087}
88
Paul Duffinb645ec82019-11-27 17:43:54 +000089func (gc *generatedContents) Printfln(format string, args ...interface{}) {
Jiyong Park9b409bc2019-10-11 14:59:13 +090090 // ninja consumes newline characters in rspfile_content. Prevent it by
Paul Duffin0e0cf1d2019-11-12 19:39:25 +000091 // escaping the backslash in the newline character. The extra backslash
Jiyong Park9b409bc2019-10-11 14:59:13 +090092 // is removed when the rspfile is written to the actual script file
Paul Duffinb645ec82019-11-27 17:43:54 +000093 fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format+"\\n", args...)
Jiyong Park9b409bc2019-10-11 14:59:13 +090094}
95
96func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
97 rb := android.NewRuleBuilder()
98 // convert \\n to \n
99 rb.Command().
100 Implicits(implicits).
101 Text("echo").Text(proptools.ShellEscape(gf.content.String())).
102 Text("| sed 's/\\\\n/\\n/g' >").Output(gf.path)
103 rb.Command().
104 Text("chmod a+x").Output(gf.path)
105 rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base())
106}
107
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000108func (s *sdk) javaLibs(ctx android.ModuleContext) []android.SdkAware {
109 result := []android.SdkAware{}
Jiyong Park9b409bc2019-10-11 14:59:13 +0900110 ctx.VisitDirectDeps(func(m android.Module) {
Jiyong Park73c54ee2019-10-22 20:31:18 +0900111 if j, ok := m.(*java.Library); ok {
112 result = append(result, j)
Jiyong Park9b409bc2019-10-11 14:59:13 +0900113 }
114 })
115 return result
116}
117
Paul Duffin91547182019-11-12 19:39:36 +0000118func (s *sdk) stubsSources(ctx android.ModuleContext) []android.SdkAware {
119 result := []android.SdkAware{}
120 ctx.VisitDirectDeps(func(m android.Module) {
121 if j, ok := m.(*java.Droidstubs); ok {
122 result = append(result, j)
123 }
124 })
125 return result
126}
127
Jiyong Park73c54ee2019-10-22 20:31:18 +0900128// archSpecificNativeLibInfo represents an arch-specific variant of a native lib
129type archSpecificNativeLibInfo struct {
130 name string
131 archType string
132 exportedIncludeDirs android.Paths
133 exportedSystemIncludeDirs android.Paths
134 exportedFlags []string
Jiyong Park232e7852019-11-04 12:23:40 +0900135 exportedDeps android.Paths
Jiyong Park73c54ee2019-10-22 20:31:18 +0900136 outputFile android.Path
137}
Jiyong Park9b409bc2019-10-11 14:59:13 +0900138
Jiyong Park73c54ee2019-10-22 20:31:18 +0900139func (lib *archSpecificNativeLibInfo) signature() string {
140 return fmt.Sprintf("%v %v %v %v",
141 lib.name,
142 lib.exportedIncludeDirs.Strings(),
143 lib.exportedSystemIncludeDirs.Strings(),
144 lib.exportedFlags)
145}
146
147// nativeLibInfo represents a collection of arch-specific modules having the same name
148type nativeLibInfo struct {
149 name string
150 archVariants []archSpecificNativeLibInfo
151 // hasArchSpecificFlags is set to true if modules for each architecture all have the same
152 // include dirs, flags, etc, in which case only those of the first arch is selected.
153 hasArchSpecificFlags bool
154}
155
156// nativeMemberInfos collects all cc.Modules that are member of an SDK.
157func (s *sdk) nativeMemberInfos(ctx android.ModuleContext) []*nativeLibInfo {
158 infoMap := make(map[string]*nativeLibInfo)
159
160 // Collect cc.Modules
161 ctx.VisitDirectDeps(func(m android.Module) {
162 ccModule, ok := m.(*cc.Module)
163 if !ok {
164 return
165 }
166 depName := ctx.OtherModuleName(m)
167
168 if _, ok := infoMap[depName]; !ok {
169 infoMap[depName] = &nativeLibInfo{name: depName}
170 }
171
172 info := infoMap[depName]
173 info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{
174 name: ccModule.BaseModuleName(),
175 archType: ccModule.Target().Arch.ArchType.String(),
176 exportedIncludeDirs: ccModule.ExportedIncludeDirs(),
177 exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
178 exportedFlags: ccModule.ExportedFlags(),
Jiyong Park232e7852019-11-04 12:23:40 +0900179 exportedDeps: ccModule.ExportedDeps(),
Jiyong Park73c54ee2019-10-22 20:31:18 +0900180 outputFile: ccModule.OutputFile().Path(),
181 })
182 })
183
184 // Determine if include dirs and flags for each module are different across arch-specific
185 // modules or not. And set hasArchSpecificFlags accordingly
186 for _, info := range infoMap {
187 // by default, include paths and flags are assumed to be the same across arches
188 info.hasArchSpecificFlags = false
189 oldSignature := ""
190 for _, av := range info.archVariants {
191 newSignature := av.signature()
192 if oldSignature == "" {
193 oldSignature = newSignature
194 }
195 if oldSignature != newSignature {
196 info.hasArchSpecificFlags = true
197 break
198 }
199 }
Jiyong Park9b409bc2019-10-11 14:59:13 +0900200 }
201
Jiyong Park73c54ee2019-10-22 20:31:18 +0900202 var list []*nativeLibInfo
203 for _, v := range infoMap {
204 list = append(list, v)
205 }
206 return list
207}
Jiyong Park9b409bc2019-10-11 14:59:13 +0900208
Jiyong Park73c54ee2019-10-22 20:31:18 +0900209// SDK directory structure
210// <sdk_root>/
211// Android.bp : definition of a 'sdk' module is here. This is a hand-made one.
212// <api_ver>/ : below this directory are all auto-generated
213// Android.bp : definition of 'sdk_snapshot' module is here
214// aidl/
215// frameworks/base/core/..../IFoo.aidl : an exported AIDL file
216// java/
Jiyong Park232e7852019-11-04 12:23:40 +0900217// <module_name>.jar : the stub jar for a java library 'module_name'
Jiyong Park73c54ee2019-10-22 20:31:18 +0900218// include/
219// bionic/libc/include/stdlib.h : an exported header file
220// include_gen/
Jiyong Park232e7852019-11-04 12:23:40 +0900221// <module_name>/com/android/.../IFoo.h : a generated header file
Jiyong Park73c54ee2019-10-22 20:31:18 +0900222// <arch>/include/ : arch-specific exported headers
223// <arch>/include_gen/ : arch-specific generated headers
224// <arch>/lib/
225// libFoo.so : a stub library
226
227const (
Jiyong Park73c54ee2019-10-22 20:31:18 +0900228 nativeIncludeDir = "include"
229 nativeGeneratedIncludeDir = "include_gen"
230 nativeStubDir = "lib"
231 nativeStubFileSuffix = ".so"
232)
233
Jiyong Park73c54ee2019-10-22 20:31:18 +0900234// path to the stub file of a native shared library. Relative to <sdk_root>/<api_dir>
235func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string {
236 return filepath.Join(lib.archType,
237 nativeStubDir, lib.name+nativeStubFileSuffix)
238}
239
240// paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
241func nativeIncludeDirPathsFor(ctx android.ModuleContext, lib archSpecificNativeLibInfo,
242 systemInclude bool, archSpecific bool) []string {
243 var result []string
Jiyong Park73c54ee2019-10-22 20:31:18 +0900244 var includeDirs []android.Path
245 if !systemInclude {
246 includeDirs = lib.exportedIncludeDirs
247 } else {
248 includeDirs = lib.exportedSystemIncludeDirs
249 }
250 for _, dir := range includeDirs {
251 var path string
Jiyong Park232e7852019-11-04 12:23:40 +0900252 if _, gen := dir.(android.WritablePath); gen {
253 path = filepath.Join(nativeGeneratedIncludeDir, lib.name)
Jiyong Park73c54ee2019-10-22 20:31:18 +0900254 } else {
255 path = filepath.Join(nativeIncludeDir, dir.String())
256 }
257 if archSpecific {
258 path = filepath.Join(lib.archType, path)
259 }
260 result = append(result, path)
261 }
262 return result
263}
264
Jiyong Park232e7852019-11-04 12:23:40 +0900265// A name that uniquely identifies a prebuilt SDK member for a version of SDK snapshot
Jiyong Park73c54ee2019-10-22 20:31:18 +0900266// This isn't visible to users, so could be changed in future.
267func versionedSdkMemberName(ctx android.ModuleContext, memberName string, version string) string {
268 return ctx.ModuleName() + "_" + memberName + string(android.SdkVersionSeparator) + version
269}
270
Jiyong Park232e7852019-11-04 12:23:40 +0900271// buildSnapshot is the main function in this source file. It creates rules to copy
272// the contents (header files, stub libraries, etc) into the zip file.
273func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000274 snapshotDir := android.PathForModuleOut(ctx, "snapshot")
Jiyong Park9b409bc2019-10-11 14:59:13 +0900275
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000276 bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
Paul Duffinb645ec82019-11-27 17:43:54 +0000277
278 bpFile := &bpFile{
279 modules: make(map[string]*bpModule),
280 }
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000281
282 builder := &snapshotBuilder{
Paul Duffinb645ec82019-11-27 17:43:54 +0000283 ctx: ctx,
Paul Duffine44358f2019-11-26 18:04:12 +0000284 sdk: s,
Paul Duffinb645ec82019-11-27 17:43:54 +0000285 version: "current",
286 snapshotDir: snapshotDir.OutputPath,
287 filesToZip: []android.Path{bp.path},
288 bpFile: bpFile,
289 prebuiltModules: make(map[string]*bpModule),
Jiyong Park73c54ee2019-10-22 20:31:18 +0900290 }
Paul Duffinac37c502019-11-26 18:02:20 +0000291 s.builderForTests = builder
Jiyong Park9b409bc2019-10-11 14:59:13 +0900292
Jiyong Park232e7852019-11-04 12:23:40 +0900293 // copy exported AIDL files and stub jar files
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000294 javaLibs := s.javaLibs(ctx)
295 for _, m := range javaLibs {
296 m.BuildSnapshot(ctx, builder)
Jiyong Park73c54ee2019-10-22 20:31:18 +0900297 }
298
Paul Duffin91547182019-11-12 19:39:36 +0000299 // copy stubs sources
300 stubsSources := s.stubsSources(ctx)
301 for _, m := range stubsSources {
302 m.BuildSnapshot(ctx, builder)
303 }
304
Jiyong Park232e7852019-11-04 12:23:40 +0900305 // copy exported header files and stub *.so files
Jiyong Park73c54ee2019-10-22 20:31:18 +0900306 nativeLibInfos := s.nativeMemberInfos(ctx)
307 for _, info := range nativeLibInfos {
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000308 buildSharedNativeLibSnapshot(ctx, info, builder)
Jiyong Park73c54ee2019-10-22 20:31:18 +0900309 }
Jiyong Park9b409bc2019-10-11 14:59:13 +0900310
Paul Duffinb645ec82019-11-27 17:43:54 +0000311 for _, unversioned := range builder.prebuiltOrder {
312 // Copy the unversioned module so it can be modified to make it versioned.
313 versioned := unversioned.copy()
314 name := versioned.properties["name"].(string)
315 versioned.setProperty("name", builder.versionedSdkMemberName(name))
316 versioned.insertAfter("name", "sdk_member_name", name)
317 bpFile.AddModule(versioned)
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000318
Paul Duffinb645ec82019-11-27 17:43:54 +0000319 // Set prefer: false - this is not strictly required as that is the default.
320 unversioned.insertAfter("name", "prefer", false)
321 bpFile.AddModule(unversioned)
322 }
323
324 // Create the snapshot module.
325 snapshotName := ctx.ModuleName() + string(android.SdkVersionSeparator) + builder.version
326 snapshotModule := bpFile.newModule("sdk_snapshot")
327 snapshotModule.AddProperty("name", snapshotName)
Paul Duffine44358f2019-11-26 18:04:12 +0000328 addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
Paul Duffin66905ed2019-11-28 13:44:47 +0000329 if len(s.properties.Java_libs) > 0 {
Paul Duffinb645ec82019-11-27 17:43:54 +0000330 snapshotModule.AddProperty("java_libs", builder.versionedSdkMemberNames(s.properties.Java_libs))
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000331 }
Paul Duffin66905ed2019-11-28 13:44:47 +0000332 if len(s.properties.Stubs_sources) > 0 {
Paul Duffinb645ec82019-11-27 17:43:54 +0000333 snapshotModule.AddProperty("stubs_sources", builder.versionedSdkMemberNames(s.properties.Stubs_sources))
Paul Duffin91547182019-11-12 19:39:36 +0000334 }
Paul Duffin66905ed2019-11-28 13:44:47 +0000335 if len(s.properties.Native_shared_libs) > 0 {
Paul Duffinb645ec82019-11-27 17:43:54 +0000336 snapshotModule.AddProperty("native_shared_libs", builder.versionedSdkMemberNames(s.properties.Native_shared_libs))
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000337 }
Paul Duffinb645ec82019-11-27 17:43:54 +0000338 bpFile.AddModule(snapshotModule)
339
340 // generate Android.bp
341 bp = newGeneratedFile(ctx, "snapshot", "Android.bp")
342 generateBpContents(&bp.generatedContents, bpFile)
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000343
344 bp.build(pctx, ctx, nil)
345
346 filesToZip := builder.filesToZip
Jiyong Park9b409bc2019-10-11 14:59:13 +0900347
Jiyong Park232e7852019-11-04 12:23:40 +0900348 // zip them all
Paul Duffin91547182019-11-12 19:39:36 +0000349 outputZipFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-current.zip").OutputPath
Paul Duffin91547182019-11-12 19:39:36 +0000350 outputDesc := "Building snapshot for " + ctx.ModuleName()
351
352 // If there are no zips to merge then generate the output zip directly.
353 // Otherwise, generate an intermediate zip file into which other zips can be
354 // merged.
355 var zipFile android.OutputPath
Paul Duffin91547182019-11-12 19:39:36 +0000356 var desc string
357 if len(builder.zipsToMerge) == 0 {
358 zipFile = outputZipFile
Paul Duffin91547182019-11-12 19:39:36 +0000359 desc = outputDesc
360 } else {
361 zipFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"-current.unmerged.zip").OutputPath
Paul Duffin91547182019-11-12 19:39:36 +0000362 desc = "Building intermediate snapshot for " + ctx.ModuleName()
363 }
364
Paul Duffin375058f2019-11-29 20:17:53 +0000365 ctx.Build(pctx, android.BuildParams{
366 Description: desc,
367 Rule: zipFiles,
368 Inputs: filesToZip,
369 Output: zipFile,
370 Args: map[string]string{
371 "basedir": builder.snapshotDir.String(),
372 },
373 })
Jiyong Park9b409bc2019-10-11 14:59:13 +0900374
Paul Duffin91547182019-11-12 19:39:36 +0000375 if len(builder.zipsToMerge) != 0 {
Paul Duffin375058f2019-11-29 20:17:53 +0000376 ctx.Build(pctx, android.BuildParams{
377 Description: outputDesc,
378 Rule: mergeZips,
379 Input: zipFile,
380 Inputs: builder.zipsToMerge,
381 Output: outputZipFile,
382 })
Paul Duffin91547182019-11-12 19:39:36 +0000383 }
384
385 return outputZipFile
Jiyong Park9b409bc2019-10-11 14:59:13 +0900386}
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000387
Paul Duffinb645ec82019-11-27 17:43:54 +0000388func generateBpContents(contents *generatedContents, bpFile *bpFile) {
389 contents.Printfln("// This is auto-generated. DO NOT EDIT.")
390 for _, bpModule := range bpFile.order {
391 contents.Printfln("")
392 contents.Printfln("%s {", bpModule.moduleType)
393 outputPropertySet(contents, &bpModule.bpPropertySet)
394 contents.Printfln("}")
395 }
396 contents.Printfln("")
397}
398
399func outputPropertySet(contents *generatedContents, set *bpPropertySet) {
400 contents.Indent()
401 for _, name := range set.order {
402 value := set.properties[name]
403
404 reflectedValue := reflect.ValueOf(value)
405 t := reflectedValue.Type()
406
407 kind := t.Kind()
408 switch kind {
409 case reflect.Slice:
410 length := reflectedValue.Len()
411 if length > 1 {
412 contents.Printfln("%s: [", name)
413 contents.Indent()
414 for i := 0; i < length; i = i + 1 {
415 contents.Printfln("%q,", reflectedValue.Index(i).Interface())
416 }
417 contents.Dedent()
418 contents.Printfln("],")
419 } else if length == 0 {
420 contents.Printfln("%s: [],", name)
421 } else {
422 contents.Printfln("%s: [%q],", name, reflectedValue.Index(0).Interface())
423 }
424 case reflect.Bool:
425 contents.Printfln("%s: %t,", name, reflectedValue.Bool())
426
427 case reflect.Ptr:
428 contents.Printfln("%s: {", name)
429 outputPropertySet(contents, reflectedValue.Interface().(*bpPropertySet))
430 contents.Printfln("},")
431
432 default:
433 contents.Printfln("%s: %q,", name, value)
434 }
435 }
436 contents.Dedent()
437}
438
Paul Duffinac37c502019-11-26 18:02:20 +0000439func (s *sdk) GetAndroidBpContentsForTests() string {
Paul Duffinb645ec82019-11-27 17:43:54 +0000440 contents := &generatedContents{}
441 generateBpContents(contents, s.builderForTests.bpFile)
442 return contents.content.String()
Paul Duffinac37c502019-11-26 18:02:20 +0000443}
444
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000445func buildSharedNativeLibSnapshot(ctx android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) {
446 // a function for emitting include dirs
447 printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
448 includeDirs := lib.exportedIncludeDirs
449 includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...)
450 if len(includeDirs) == 0 {
451 return
452 }
453 for _, dir := range includeDirs {
454 if _, gen := dir.(android.WritablePath); gen {
455 // generated headers are copied via exportedDeps. See below.
456 continue
457 }
458 targetDir := nativeIncludeDir
459 if info.hasArchSpecificFlags {
460 targetDir = filepath.Join(lib.archType, targetDir)
461 }
462
463 // TODO(jiyong) copy headers having other suffixes
464 headers, _ := ctx.GlobWithDeps(dir.String()+"/**/*.h", nil)
465 for _, file := range headers {
466 src := android.PathForSource(ctx, file)
467 dest := filepath.Join(targetDir, file)
468 builder.CopyToSnapshot(src, dest)
469 }
470 }
471
472 genHeaders := lib.exportedDeps
473 for _, file := range genHeaders {
474 targetDir := nativeGeneratedIncludeDir
475 if info.hasArchSpecificFlags {
476 targetDir = filepath.Join(lib.archType, targetDir)
477 }
478 dest := filepath.Join(targetDir, lib.name, file.Rel())
479 builder.CopyToSnapshot(file, dest)
480 }
481 }
482
483 if !info.hasArchSpecificFlags {
484 printExportedDirCopyCommandsForNativeLibs(info.archVariants[0])
485 }
486
487 // for each architecture
488 for _, av := range info.archVariants {
489 builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av))
490
491 if info.hasArchSpecificFlags {
492 printExportedDirCopyCommandsForNativeLibs(av)
493 }
494 }
495
Paul Duffinb645ec82019-11-27 17:43:54 +0000496 info.generatePrebuiltLibrary(ctx, builder)
Paul Duffin90102502019-11-25 19:49:33 +0000497}
498
Paul Duffinb645ec82019-11-27 17:43:54 +0000499func (info *nativeLibInfo) generatePrebuiltLibrary(ctx android.ModuleContext, builder android.SnapshotBuilder) {
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000500
501 // a function for emitting include dirs
Paul Duffinb645ec82019-11-27 17:43:54 +0000502 addExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, properties android.BpPropertySet, systemInclude bool) {
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000503 includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
504 if len(includeDirs) == 0 {
505 return
506 }
Paul Duffinb645ec82019-11-27 17:43:54 +0000507 var propertyName string
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000508 if !systemInclude {
Paul Duffinb645ec82019-11-27 17:43:54 +0000509 propertyName = "export_include_dirs"
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000510 } else {
Paul Duffinb645ec82019-11-27 17:43:54 +0000511 propertyName = "export_system_include_dirs"
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000512 }
Paul Duffinb645ec82019-11-27 17:43:54 +0000513 properties.AddProperty(propertyName, includeDirs)
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000514 }
515
Paul Duffinb645ec82019-11-27 17:43:54 +0000516 pbm := builder.AddPrebuiltModule(info.name, "cc_prebuilt_library_shared")
517
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000518 if !info.hasArchSpecificFlags {
Paul Duffinb645ec82019-11-27 17:43:54 +0000519 addExportedDirsForNativeLibs(info.archVariants[0], pbm, false /*systemInclude*/)
520 addExportedDirsForNativeLibs(info.archVariants[0], pbm, true /*systemInclude*/)
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000521 }
522
Paul Duffinb645ec82019-11-27 17:43:54 +0000523 archProperties := pbm.AddPropertySet("arch")
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000524 for _, av := range info.archVariants {
Paul Duffinb645ec82019-11-27 17:43:54 +0000525 archTypeProperties := archProperties.AddPropertySet(av.archType)
526 archTypeProperties.AddProperty("srcs", []string{nativeStubFilePathFor(av)})
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000527 if info.hasArchSpecificFlags {
528 // export_* properties are added inside the arch: {<arch>: {...}} block
Paul Duffinb645ec82019-11-27 17:43:54 +0000529 addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/)
530 addExportedDirsForNativeLibs(av, archTypeProperties, true /*systemInclude*/)
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000531 }
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000532 }
Paul Duffinb645ec82019-11-27 17:43:54 +0000533 pbm.AddProperty("stl", "none")
534 pbm.AddProperty("system_shared_libs", []string{})
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000535}
536
537type snapshotBuilder struct {
Paul Duffinb645ec82019-11-27 17:43:54 +0000538 ctx android.ModuleContext
Paul Duffine44358f2019-11-26 18:04:12 +0000539 sdk *sdk
Paul Duffinb645ec82019-11-27 17:43:54 +0000540 version string
541 snapshotDir android.OutputPath
542 bpFile *bpFile
543 filesToZip android.Paths
544 zipsToMerge android.Paths
545
546 prebuiltModules map[string]*bpModule
547 prebuiltOrder []*bpModule
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000548}
549
550func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) {
551 path := s.snapshotDir.Join(s.ctx, dest)
552 s.ctx.Build(pctx, android.BuildParams{
553 Rule: android.Cp,
554 Input: src,
555 Output: path,
556 })
557 s.filesToZip = append(s.filesToZip, path)
558}
559
Paul Duffin91547182019-11-12 19:39:36 +0000560func (s *snapshotBuilder) UnzipToSnapshot(zipPath android.Path, destDir string) {
561 ctx := s.ctx
562
563 // Repackage the zip file so that the entries are in the destDir directory.
564 // This will allow the zip file to be merged into the snapshot.
565 tmpZipPath := android.PathForModuleOut(ctx, "tmp", destDir+".zip").OutputPath
Paul Duffin375058f2019-11-29 20:17:53 +0000566
567 ctx.Build(pctx, android.BuildParams{
568 Description: "Repackaging zip file " + destDir + " for snapshot " + ctx.ModuleName(),
569 Rule: repackageZip,
570 Input: zipPath,
571 Output: tmpZipPath,
572 Args: map[string]string{
573 "destdir": destDir,
574 },
575 })
Paul Duffin91547182019-11-12 19:39:36 +0000576
577 // Add the repackaged zip file to the files to merge.
578 s.zipsToMerge = append(s.zipsToMerge, tmpZipPath)
579}
580
Paul Duffinb645ec82019-11-27 17:43:54 +0000581func (s *snapshotBuilder) AddPrebuiltModule(name string, moduleType string) android.BpModule {
582 if s.prebuiltModules[name] != nil {
583 panic(fmt.Sprintf("Duplicate module detected, module %s has already been added", name))
584 }
585
586 m := s.bpFile.newModule(moduleType)
587 m.AddProperty("name", name)
Paul Duffine44358f2019-11-26 18:04:12 +0000588 addHostDeviceSupportedProperties(&s.sdk.ModuleBase, m)
Paul Duffinb645ec82019-11-27 17:43:54 +0000589
590 s.prebuiltModules[name] = m
591 s.prebuiltOrder = append(s.prebuiltOrder, m)
592 return m
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000593}
594
Paul Duffine44358f2019-11-26 18:04:12 +0000595func addHostDeviceSupportedProperties(module *android.ModuleBase, bpModule *bpModule) {
596 if !module.DeviceSupported() {
597 bpModule.AddProperty("device_supported", false)
598 }
599 if module.HostSupported() {
600 bpModule.AddProperty("host_supported", true)
601 }
602}
603
Paul Duffinb645ec82019-11-27 17:43:54 +0000604// Get a versioned name appropriate for the SDK snapshot version being taken.
605func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string) string {
Paul Duffin0e0cf1d2019-11-12 19:39:25 +0000606 return versionedSdkMemberName(s.ctx, unversionedName, s.version)
607}
Paul Duffinb645ec82019-11-27 17:43:54 +0000608
609func (s *snapshotBuilder) versionedSdkMemberNames(members []string) []string {
610 var references []string = nil
611 for _, m := range members {
612 references = append(references, s.versionedSdkMemberName(m))
613 }
614 return references
615}