This is the first commit to generate VNDK snapshot with Soong: .so files, some txt files, and notice files are captured with Soong. As ld.config.txt is currently in Android.mk and will be deprecated soon, configs files (and zipping all of artifacts) are still handled with Makefile. Bug: 131564934 Test: 1) DIST_DIR=out/dist development/vndk/snapshot/build.sh Test: 2) try installing vndk snapshot with: development/vndk/snapshot/update.py Change-Id: I8629e1e25bfc461fd495565bb4872c9af176cf92
539 lines
16 KiB
Go
539 lines
16 KiB
Go
// Copyright 2017 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cc
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
"android/soong/android"
|
|
"android/soong/cc/config"
|
|
)
|
|
|
|
type VndkProperties struct {
|
|
Vndk struct {
|
|
// declared as a VNDK or VNDK-SP module. The vendor variant
|
|
// will be installed in /system instead of /vendor partition.
|
|
//
|
|
// `vendor_vailable` must be explicitly set to either true or
|
|
// false together with `vndk: {enabled: true}`.
|
|
Enabled *bool
|
|
|
|
// declared as a VNDK-SP module, which is a subset of VNDK.
|
|
//
|
|
// `vndk: { enabled: true }` must set together.
|
|
//
|
|
// All these modules are allowed to link to VNDK-SP or LL-NDK
|
|
// modules only. Other dependency will cause link-type errors.
|
|
//
|
|
// If `support_system_process` is not set or set to false,
|
|
// the module is VNDK-core and can link to other VNDK-core,
|
|
// VNDK-SP or LL-NDK modules only.
|
|
Support_system_process *bool
|
|
|
|
// Extending another module
|
|
Extends *string
|
|
}
|
|
}
|
|
|
|
type vndkdep struct {
|
|
Properties VndkProperties
|
|
}
|
|
|
|
func (vndk *vndkdep) props() []interface{} {
|
|
return []interface{}{&vndk.Properties}
|
|
}
|
|
|
|
func (vndk *vndkdep) begin(ctx BaseModuleContext) {}
|
|
|
|
func (vndk *vndkdep) deps(ctx BaseModuleContext, deps Deps) Deps {
|
|
return deps
|
|
}
|
|
|
|
func (vndk *vndkdep) isVndk() bool {
|
|
return Bool(vndk.Properties.Vndk.Enabled)
|
|
}
|
|
|
|
func (vndk *vndkdep) isVndkSp() bool {
|
|
return Bool(vndk.Properties.Vndk.Support_system_process)
|
|
}
|
|
|
|
func (vndk *vndkdep) isVndkExt() bool {
|
|
return vndk.Properties.Vndk.Extends != nil
|
|
}
|
|
|
|
func (vndk *vndkdep) getVndkExtendsModuleName() string {
|
|
return String(vndk.Properties.Vndk.Extends)
|
|
}
|
|
|
|
func (vndk *vndkdep) typeName() string {
|
|
if !vndk.isVndk() {
|
|
return "native:vendor"
|
|
}
|
|
if !vndk.isVndkExt() {
|
|
if !vndk.isVndkSp() {
|
|
return "native:vendor:vndk"
|
|
}
|
|
return "native:vendor:vndksp"
|
|
}
|
|
if !vndk.isVndkSp() {
|
|
return "native:vendor:vndkext"
|
|
}
|
|
return "native:vendor:vndkspext"
|
|
}
|
|
|
|
func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag dependencyTag) {
|
|
if to.linker == nil {
|
|
return
|
|
}
|
|
if !vndk.isVndk() {
|
|
// Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
|
|
// vendor_available: false.
|
|
violation := false
|
|
if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
|
|
violation = true
|
|
} else {
|
|
if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
|
|
// Vendor_available == nil && !Bool(Vendor_available) should be okay since
|
|
// it means a vendor-only library which is a valid dependency for non-VNDK
|
|
// modules.
|
|
violation = true
|
|
}
|
|
}
|
|
if violation {
|
|
ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name())
|
|
}
|
|
}
|
|
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
|
|
// Check only shared libraries.
|
|
// Other (static and LL-NDK) libraries are allowed to link.
|
|
return
|
|
}
|
|
if !to.Properties.UseVndk {
|
|
ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
|
|
vndk.typeName(), to.Name())
|
|
return
|
|
}
|
|
if tag == vndkExtDepTag {
|
|
// Ensure `extends: "name"` property refers a vndk module that has vendor_available
|
|
// and has identical vndk properties.
|
|
if to.vndkdep == nil || !to.vndkdep.isVndk() {
|
|
ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name())
|
|
return
|
|
}
|
|
if vndk.isVndkSp() != to.vndkdep.isVndkSp() {
|
|
ctx.ModuleErrorf(
|
|
"`extends` refers a module %q with mismatched support_system_process",
|
|
to.Name())
|
|
return
|
|
}
|
|
if !Bool(to.VendorProperties.Vendor_available) {
|
|
ctx.ModuleErrorf(
|
|
"`extends` refers module %q which does not have `vendor_available: true`",
|
|
to.Name())
|
|
return
|
|
}
|
|
}
|
|
if to.vndkdep == nil {
|
|
return
|
|
}
|
|
|
|
// Check the dependencies of VNDK shared libraries.
|
|
if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil {
|
|
ctx.ModuleErrorf("(%s) should not link to %q (%s): %v",
|
|
vndk.typeName(), to.Name(), to.vndkdep.typeName(), err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error {
|
|
// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
|
|
if from.isVndkExt() {
|
|
if from.isVndkSp() {
|
|
if to.isVndk() && !to.isVndkSp() {
|
|
return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions")
|
|
}
|
|
return nil
|
|
}
|
|
// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
|
|
return nil
|
|
}
|
|
if from.isVndk() {
|
|
if to.isVndkExt() {
|
|
return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions")
|
|
}
|
|
if from.isVndkSp() {
|
|
if !to.isVndkSp() {
|
|
return errors.New("VNDK-SP must only depend on VNDK-SP")
|
|
}
|
|
return nil
|
|
}
|
|
if !to.isVndk() {
|
|
return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP")
|
|
}
|
|
return nil
|
|
}
|
|
// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibrarires")
|
|
vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires")
|
|
llndkLibrariesKey = android.NewOnceKey("llndkLibrarires")
|
|
vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires")
|
|
vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
|
|
modulePathsKey = android.NewOnceKey("modulePaths")
|
|
vndkSnapshotOutputsKey = android.NewOnceKey("vndkSnapshotOutputs")
|
|
vndkLibrariesLock sync.Mutex
|
|
)
|
|
|
|
type vndkSnapshotOutputPaths struct {
|
|
configs android.Paths
|
|
notices android.Paths
|
|
vndkCoreLibs android.Paths
|
|
vndkCoreLibs2nd android.Paths
|
|
vndkSpLibs android.Paths
|
|
vndkSpLibs2nd android.Paths
|
|
}
|
|
|
|
func vndkCoreLibraries(config android.Config) *[]string {
|
|
return config.Once(vndkCoreLibrariesKey, func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
func vndkSpLibraries(config android.Config) *[]string {
|
|
return config.Once(vndkSpLibrariesKey, func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
func llndkLibraries(config android.Config) *[]string {
|
|
return config.Once(llndkLibrariesKey, func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
func vndkPrivateLibraries(config android.Config) *[]string {
|
|
return config.Once(vndkPrivateLibrariesKey, func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
func vndkUsingCoreVariantLibraries(config android.Config) *[]string {
|
|
return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} {
|
|
return &[]string{}
|
|
}).(*[]string)
|
|
}
|
|
|
|
func modulePaths(config android.Config) map[string]string {
|
|
return config.Once(modulePathsKey, func() interface{} {
|
|
return make(map[string]string)
|
|
}).(map[string]string)
|
|
}
|
|
|
|
func vndkSnapshotOutputs(config android.Config) *vndkSnapshotOutputPaths {
|
|
return config.Once(vndkSnapshotOutputsKey, func() interface{} {
|
|
return &vndkSnapshotOutputPaths{}
|
|
}).(*vndkSnapshotOutputPaths)
|
|
}
|
|
|
|
func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
|
|
lib := m.linker.(*llndkStubDecorator)
|
|
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
|
|
|
|
vndkLibrariesLock.Lock()
|
|
defer vndkLibrariesLock.Unlock()
|
|
|
|
llndkLibraries := llndkLibraries(mctx.Config())
|
|
if !inList(name, *llndkLibraries) {
|
|
*llndkLibraries = append(*llndkLibraries, name)
|
|
sort.Strings(*llndkLibraries)
|
|
}
|
|
if !Bool(lib.Properties.Vendor_available) {
|
|
vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
|
|
if !inList(name, *vndkPrivateLibraries) {
|
|
*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
|
|
sort.Strings(*vndkPrivateLibraries)
|
|
}
|
|
}
|
|
}
|
|
|
|
func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
|
|
name := strings.TrimPrefix(m.Name(), "prebuilt_")
|
|
|
|
vndkLibrariesLock.Lock()
|
|
defer vndkLibrariesLock.Unlock()
|
|
|
|
modulePaths := modulePaths(mctx.Config())
|
|
if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
|
|
vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
|
|
if !inList(name, *vndkUsingCoreVariantLibraries) {
|
|
*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
|
|
sort.Strings(*vndkUsingCoreVariantLibraries)
|
|
}
|
|
}
|
|
if m.vndkdep.isVndkSp() {
|
|
vndkSpLibraries := vndkSpLibraries(mctx.Config())
|
|
if !inList(name, *vndkSpLibraries) {
|
|
*vndkSpLibraries = append(*vndkSpLibraries, name)
|
|
sort.Strings(*vndkSpLibraries)
|
|
modulePaths[name] = mctx.ModuleDir()
|
|
}
|
|
} else {
|
|
vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
|
|
if !inList(name, *vndkCoreLibraries) {
|
|
*vndkCoreLibraries = append(*vndkCoreLibraries, name)
|
|
sort.Strings(*vndkCoreLibraries)
|
|
modulePaths[name] = mctx.ModuleDir()
|
|
}
|
|
}
|
|
if !Bool(m.VendorProperties.Vendor_available) {
|
|
vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
|
|
if !inList(name, *vndkPrivateLibraries) {
|
|
*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
|
|
sort.Strings(*vndkPrivateLibraries)
|
|
}
|
|
}
|
|
}
|
|
|
|
// gather list of vndk-core, vndk-sp, and ll-ndk libs
|
|
func VndkMutator(mctx android.BottomUpMutatorContext) {
|
|
m, ok := mctx.Module().(*Module)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if !m.Enabled() {
|
|
return
|
|
}
|
|
|
|
if _, ok := m.linker.(*llndkStubDecorator); ok {
|
|
processLlndkLibrary(mctx, m)
|
|
return
|
|
}
|
|
|
|
lib, is_lib := m.linker.(*libraryDecorator)
|
|
prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
|
|
|
|
if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
|
|
if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
|
|
processVndkLibrary(mctx, m)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
|
|
android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
|
|
outputs := vndkSnapshotOutputs(ctx.Config())
|
|
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_CONFIGS", strings.Join(outputs.configs.Strings(), " "))
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_NOTICES", strings.Join(outputs.notices.Strings(), " "))
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_CORE_LIBS", strings.Join(outputs.vndkCoreLibs.Strings(), " "))
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_SP_LIBS", strings.Join(outputs.vndkSpLibs.Strings(), " "))
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_CORE_LIBS_2ND", strings.Join(outputs.vndkCoreLibs2nd.Strings(), " "))
|
|
ctx.Strict("SOONG_VNDK_SNAPSHOT_SP_LIBS_2ND", strings.Join(outputs.vndkSpLibs2nd.Strings(), " "))
|
|
})
|
|
}
|
|
|
|
func VndkSnapshotSingleton() android.Singleton {
|
|
return &vndkSnapshotSingleton{}
|
|
}
|
|
|
|
type vndkSnapshotSingleton struct{}
|
|
|
|
func installVndkSnapshotLib(ctx android.SingletonContext, name string, module *Module, dir string) android.Path {
|
|
if !module.outputFile.Valid() {
|
|
panic(fmt.Errorf("module %s has no outputFile\n", name))
|
|
}
|
|
|
|
out := android.PathForOutput(ctx, dir, name+".so")
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.Cp,
|
|
Input: module.outputFile.Path(),
|
|
Output: out,
|
|
Description: "vndk snapshot " + dir + "/" + name + ".so",
|
|
Args: map[string]string{
|
|
"cpFlags": "-f -L",
|
|
},
|
|
})
|
|
|
|
return out
|
|
}
|
|
|
|
func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
|
|
if ctx.DeviceConfig().VndkVersion() != "current" {
|
|
return
|
|
}
|
|
|
|
if ctx.DeviceConfig().PlatformVndkVersion() == "" {
|
|
return
|
|
}
|
|
|
|
if ctx.DeviceConfig().BoardVndkRuntimeDisable() {
|
|
return
|
|
}
|
|
|
|
outputs := vndkSnapshotOutputs(ctx.Config())
|
|
|
|
snapshotDir := "vndk-snapshot"
|
|
|
|
var vndkLibPath, vndkLib2ndPath string
|
|
|
|
snapshotVariantPath := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
|
|
if ctx.DeviceConfig().BinderBitness() == "32" {
|
|
vndkLibPath = filepath.Join(snapshotVariantPath, "binder32", fmt.Sprintf(
|
|
"arch-%s-%s", ctx.DeviceConfig().DeviceArch(), ctx.DeviceConfig().DeviceArchVariant()))
|
|
vndkLib2ndPath = filepath.Join(snapshotVariantPath, "binder32", fmt.Sprintf(
|
|
"arch-%s-%s", ctx.DeviceConfig().DeviceSecondaryArch(), ctx.DeviceConfig().DeviceSecondaryArchVariant()))
|
|
} else {
|
|
vndkLibPath = filepath.Join(snapshotVariantPath, fmt.Sprintf(
|
|
"arch-%s-%s", ctx.DeviceConfig().DeviceArch(), ctx.DeviceConfig().DeviceArchVariant()))
|
|
vndkLib2ndPath = filepath.Join(snapshotVariantPath, fmt.Sprintf(
|
|
"arch-%s-%s", ctx.DeviceConfig().DeviceSecondaryArch(), ctx.DeviceConfig().DeviceSecondaryArchVariant()))
|
|
}
|
|
|
|
vndkCoreLibPath := filepath.Join(vndkLibPath, "shared", "vndk-core")
|
|
vndkSpLibPath := filepath.Join(vndkLibPath, "shared", "vndk-sp")
|
|
vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
|
|
vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
|
|
noticePath := filepath.Join(snapshotVariantPath, "NOTICE_FILES")
|
|
noticeBuilt := make(map[string]bool)
|
|
|
|
tryBuildNotice := func(m *Module) {
|
|
name := ctx.ModuleName(m)
|
|
|
|
if _, ok := noticeBuilt[name]; ok {
|
|
return
|
|
}
|
|
|
|
noticeBuilt[name] = true
|
|
|
|
if m.NoticeFile().Valid() {
|
|
out := android.PathForOutput(ctx, noticePath, name+".so.txt")
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.Cp,
|
|
Input: m.NoticeFile().Path(),
|
|
Output: out,
|
|
Description: "vndk snapshot notice " + name + ".so.txt",
|
|
Args: map[string]string{
|
|
"cpFlags": "-f -L",
|
|
},
|
|
})
|
|
outputs.notices = append(outputs.notices, out)
|
|
}
|
|
}
|
|
|
|
vndkCoreLibraries := vndkCoreLibraries(ctx.Config())
|
|
vndkSpLibraries := vndkSpLibraries(ctx.Config())
|
|
vndkPrivateLibraries := vndkPrivateLibraries(ctx.Config())
|
|
|
|
ctx.VisitAllModules(func(module android.Module) {
|
|
m, ok := module.(*Module)
|
|
if !ok || !m.Enabled() || !m.useVndk() || !m.installable() {
|
|
return
|
|
}
|
|
|
|
lib, is_lib := m.linker.(*libraryDecorator)
|
|
prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
|
|
|
|
if !(is_lib && lib.shared()) && !(is_prebuilt_lib && prebuilt_lib.shared()) {
|
|
return
|
|
}
|
|
|
|
is_2nd := m.Target().Arch.ArchType != ctx.Config().DevicePrimaryArchType()
|
|
|
|
name := ctx.ModuleName(module)
|
|
|
|
if inList(name, *vndkCoreLibraries) {
|
|
if is_2nd {
|
|
out := installVndkSnapshotLib(ctx, name, m, vndkCoreLib2ndPath)
|
|
outputs.vndkCoreLibs2nd = append(outputs.vndkCoreLibs2nd, out)
|
|
} else {
|
|
out := installVndkSnapshotLib(ctx, name, m, vndkCoreLibPath)
|
|
outputs.vndkCoreLibs = append(outputs.vndkCoreLibs, out)
|
|
}
|
|
tryBuildNotice(m)
|
|
} else if inList(name, *vndkSpLibraries) {
|
|
if is_2nd {
|
|
out := installVndkSnapshotLib(ctx, name, m, vndkSpLib2ndPath)
|
|
outputs.vndkSpLibs2nd = append(outputs.vndkSpLibs2nd, out)
|
|
} else {
|
|
out := installVndkSnapshotLib(ctx, name, m, vndkSpLibPath)
|
|
outputs.vndkSpLibs = append(outputs.vndkSpLibs, out)
|
|
}
|
|
tryBuildNotice(m)
|
|
}
|
|
})
|
|
|
|
configsPath := filepath.Join(snapshotVariantPath, "configs")
|
|
vndkCoreTxt := android.PathForOutput(ctx, configsPath, "vndkcore.libraries.txt")
|
|
vndkPrivateTxt := android.PathForOutput(ctx, configsPath, "vndkprivate.libraries.txt")
|
|
modulePathTxt := android.PathForOutput(ctx, configsPath, "module_paths.txt")
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.WriteFile,
|
|
Output: vndkCoreTxt,
|
|
Description: "vndk snapshot vndkcore.libraries.txt",
|
|
Args: map[string]string{
|
|
"content": android.JoinWithSuffix(*vndkCoreLibraries, ".so", "\\n"),
|
|
},
|
|
})
|
|
outputs.configs = append(outputs.configs, vndkCoreTxt)
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.WriteFile,
|
|
Output: vndkPrivateTxt,
|
|
Description: "vndk snapshot vndkprivate.libraries.txt",
|
|
Args: map[string]string{
|
|
"content": android.JoinWithSuffix(*vndkPrivateLibraries, ".so", "\\n"),
|
|
},
|
|
})
|
|
outputs.configs = append(outputs.configs, vndkPrivateTxt)
|
|
|
|
var modulePathTxtBuilder strings.Builder
|
|
|
|
first := true
|
|
for lib, dir := range modulePaths(ctx.Config()) {
|
|
if first {
|
|
first = false
|
|
} else {
|
|
modulePathTxtBuilder.WriteString("\\n")
|
|
}
|
|
modulePathTxtBuilder.WriteString(lib)
|
|
modulePathTxtBuilder.WriteString(".so ")
|
|
modulePathTxtBuilder.WriteString(dir)
|
|
}
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: android.WriteFile,
|
|
Output: modulePathTxt,
|
|
Description: "vndk snapshot module_paths.txt",
|
|
Args: map[string]string{
|
|
"content": modulePathTxtBuilder.String(),
|
|
},
|
|
})
|
|
outputs.configs = append(outputs.configs, modulePathTxt)
|
|
}
|