Generate VNDK snapshot with Soong except configs

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
This commit is contained in:
Inseob Kim 2019-05-09 13:29:15 +09:00
parent 0967b34dd9
commit 1f086e2f0d
6 changed files with 402 additions and 59 deletions

View File

@ -288,6 +288,10 @@ func TestArchConfig(buildDir string, env map[string]string) Config {
config.BuildOsVariant = config.Targets[BuildOs][0].String()
config.BuildOsCommonVariant = getCommonTargets(config.Targets[BuildOs])[0].String()
config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
return testConfig
}
@ -1100,3 +1104,23 @@ func (c *config) ProductPrivateSepolicyDirs() []string {
func (c *config) ProductCompatibleProperty() bool {
return Bool(c.productVariables.ProductCompatibleProperty)
}
func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
}
func (c *deviceConfig) DeviceArch() string {
return String(c.config.productVariables.DeviceArch)
}
func (c *deviceConfig) DeviceArchVariant() string {
return String(c.config.productVariables.DeviceArchVariant)
}
func (c *deviceConfig) DeviceSecondaryArch() string {
return String(c.config.productVariables.DeviceSecondaryArch)
}
func (c *deviceConfig) DeviceSecondaryArchVariant() string {
return String(c.config.productVariables.DeviceSecondaryArchVariant)
}

View File

@ -52,6 +52,31 @@ func JoinWithPrefix(strs []string, prefix string) string {
return string(ret)
}
func JoinWithSuffix(strs []string, suffix string, separator string) string {
if len(strs) == 0 {
return ""
}
if len(strs) == 1 {
return strs[0] + suffix
}
n := len(" ") * (len(strs) - 1)
for _, s := range strs {
n += len(suffix) + len(s)
}
ret := make([]byte, 0, n)
for i, s := range strs {
if i != 0 {
ret = append(ret, separator...)
}
ret = append(ret, s...)
ret = append(ret, suffix...)
}
return string(ret)
}
func sortedKeys(m map[string][]string) []string {
s := make([]string, 0, len(m))
for k := range m {

View File

@ -279,6 +279,8 @@ type productVariables struct {
BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
BoardSepolicyM4Defs []string `json:",omitempty"`
BoardVndkRuntimeDisable *bool `json:",omitempty"`
VendorVars map[string]map[string]string `json:",omitempty"`
Ndk_abis *bool `json:",omitempty"`

View File

@ -1011,7 +1011,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
}
}
if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
if c.installable() {
c.installer.install(ctx, c.outputFile.Path())
if ctx.Failed() {
return
@ -1968,6 +1968,10 @@ func (c *Module) IsInstallableToApex() bool {
return false
}
func (c *Module) installable() bool {
return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
}
func (c *Module) imageVariation() string {
variation := "core"
if c.useVndk() {

View File

@ -20,6 +20,7 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
@ -75,6 +76,7 @@ func createTestContext(t *testing.T, config android.Config, bp string, os androi
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
ctx.RegisterSingletonType("vndk-snapshot", android.SingletonFactoryAdaptor(VndkSnapshotSingleton))
ctx.Register()
// add some modules that are required by the compiler and/or linker
@ -286,8 +288,28 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string
}
}
func checkVndkSnapshot(t *testing.T, ctx *android.TestContext, name, subDir, variant string) {
vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
snapshotPath := filepath.Join(subDir, name+".so")
mod := ctx.ModuleForTests(name, variant).Module().(*Module)
if !mod.outputFile.Valid() {
t.Errorf("%q must have output\n", name)
return
}
out := vndkSnapshot.Output(snapshotPath)
if out.Input != mod.outputFile.Path() {
t.Errorf("The input of VNDK snapshot must be %q, but %q", out.Input.String(), mod.outputFile.String())
}
}
func TestVndk(t *testing.T) {
ctx := testCc(t, `
config := android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, `
cc_library {
name: "libvndk",
vendor_available: true,
@ -325,12 +347,35 @@ func TestVndk(t *testing.T) {
},
nocrt: true,
}
`)
`, config)
checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
// Check VNDK snapshot output.
snapshotDir := "vndk-snapshot"
snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
vndkLibPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
"arm64", "armv8-a"))
vndkLib2ndPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
"arm", "armv7-a-neon"))
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")
variant := "android_arm64_armv8-a_vendor_shared"
variant2nd := "android_arm_armv7-a-neon_vendor_shared"
checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLibPath, variant)
checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLibPath, variant)
checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
}
func TestVndkDepError(t *testing.T) {

View File

@ -16,6 +16,8 @@ package cc
import (
"errors"
"fmt"
"path/filepath"
"sort"
"strings"
"sync"
@ -197,9 +199,20 @@ var (
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{}
@ -230,66 +243,296 @@ func vndkUsingCoreVariantLibraries(config android.Config) *[]string {
}).(*[]string)
}
// gather list of vndk-core, vndk-sp, and ll-ndk libs
func VndkMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.Enabled() {
if lib, ok := m.linker.(*llndkStubDecorator); ok {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
func modulePaths(config android.Config) map[string]string {
return config.Once(modulePathsKey, func() interface{} {
return make(map[string]string)
}).(map[string]string)
}
llndkLibraries := llndkLibraries(mctx.Config())
vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
func vndkSnapshotOutputs(config android.Config) *vndkSnapshotOutputPaths {
return config.Once(vndkSnapshotOutputsKey, func() interface{} {
return &vndkSnapshotOutputPaths{}
}).(*vndkSnapshotOutputPaths)
}
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
if !inList(name, *llndkLibraries) {
*llndkLibraries = append(*llndkLibraries, name)
sort.Strings(*llndkLibraries)
}
if !Bool(lib.Properties.Vendor_available) {
if !inList(name, *vndkPrivateLibraries) {
*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
sort.Strings(*vndkPrivateLibraries)
}
}
} else {
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()) {
name := strings.TrimPrefix(m.Name(), "prebuilt_")
if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
lib := m.linker.(*llndkStubDecorator)
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
vndkSpLibraries := vndkSpLibraries(mctx.Config())
vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
if !inList(name, *vndkUsingCoreVariantLibraries) {
*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
sort.Strings(*vndkUsingCoreVariantLibraries)
}
}
if m.vndkdep.isVndkSp() {
if !inList(name, *vndkSpLibraries) {
*vndkSpLibraries = append(*vndkSpLibraries, name)
sort.Strings(*vndkSpLibraries)
}
} else {
if !inList(name, *vndkCoreLibraries) {
*vndkCoreLibraries = append(*vndkCoreLibraries, name)
sort.Strings(*vndkCoreLibraries)
}
}
if !Bool(m.VendorProperties.Vendor_available) {
if !inList(name, *vndkPrivateLibraries) {
*vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
sort.Strings(*vndkPrivateLibraries)
}
}
}
}
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)
}