Merge "Add prebuilt_apex."
am: 083bd3e971
Change-Id: Ibee60218605b28e90225b3470828b75530063ad4
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
|
"github.com/google/blueprint/proptools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file implements common functionality for handling modules that may exist as prebuilts,
|
// This file implements common functionality for handling modules that may exist as prebuilts,
|
||||||
@@ -42,6 +43,7 @@ type Prebuilt struct {
|
|||||||
properties PrebuiltProperties
|
properties PrebuiltProperties
|
||||||
module Module
|
module Module
|
||||||
srcs *[]string
|
srcs *[]string
|
||||||
|
src *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) Name(name string) string {
|
func (p *Prebuilt) Name(name string) string {
|
||||||
@@ -49,19 +51,27 @@ func (p *Prebuilt) Name(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
|
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
|
||||||
if len(*p.srcs) == 0 {
|
if p.srcs != nil {
|
||||||
ctx.PropertyErrorf("srcs", "missing prebuilt source file")
|
if len(*p.srcs) == 0 {
|
||||||
return nil
|
ctx.PropertyErrorf("srcs", "missing prebuilt source file")
|
||||||
}
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if len(*p.srcs) > 1 {
|
if len(*p.srcs) > 1 {
|
||||||
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the singleton source after expanding any filegroup in the
|
// Return the singleton source after expanding any filegroup in the
|
||||||
// sources.
|
// sources.
|
||||||
return PathForModuleSrc(ctx, (*p.srcs)[0])
|
return PathForModuleSrc(ctx, (*p.srcs)[0])
|
||||||
|
} else {
|
||||||
|
if proptools.String(p.src) == "" {
|
||||||
|
ctx.PropertyErrorf("src", "missing prebuilt source file")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return PathForModuleSrc(ctx, *p.src)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
|
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
|
||||||
@@ -70,13 +80,19 @@ func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
|
|||||||
p.srcs = srcs
|
p.srcs = srcs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, src *string) {
|
||||||
|
p := module.Prebuilt()
|
||||||
|
module.AddProperties(&p.properties)
|
||||||
|
p.src = src
|
||||||
|
}
|
||||||
|
|
||||||
type PrebuiltInterface interface {
|
type PrebuiltInterface interface {
|
||||||
Module
|
Module
|
||||||
Prebuilt() *Prebuilt
|
Prebuilt() *Prebuilt
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
|
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
|
||||||
ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
|
ctx.BottomUp("prebuilts", PrebuiltMutator).Parallel()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
|
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
|
||||||
@@ -84,9 +100,9 @@ func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
|
|||||||
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
|
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// prebuiltMutator ensures that there is always a module with an undecorated name, and marks
|
// PrebuiltMutator ensures that there is always a module with an undecorated name, and marks
|
||||||
// prebuilt modules that have both a prebuilt and a source module.
|
// prebuilt modules that have both a prebuilt and a source module.
|
||||||
func prebuiltMutator(ctx BottomUpMutatorContext) {
|
func PrebuiltMutator(ctx BottomUpMutatorContext) {
|
||||||
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
||||||
p := m.Prebuilt()
|
p := m.Prebuilt()
|
||||||
name := m.base().BaseModuleName()
|
name := m.base().BaseModuleName()
|
||||||
@@ -104,7 +120,7 @@ func prebuiltMutator(ctx BottomUpMutatorContext) {
|
|||||||
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
|
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
|
||||||
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
||||||
p := m.Prebuilt()
|
p := m.Prebuilt()
|
||||||
if p.srcs == nil {
|
if p.srcs == nil && p.src == nil {
|
||||||
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
|
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
|
||||||
}
|
}
|
||||||
if !p.properties.SourceExists {
|
if !p.properties.SourceExists {
|
||||||
@@ -143,7 +159,11 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
|
|||||||
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
|
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
|
||||||
// will be used if it is marked "prefer" or if the source module is disabled.
|
// will be used if it is marked "prefer" or if the source module is disabled.
|
||||||
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
|
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
|
||||||
if len(*p.srcs) == 0 {
|
if p.srcs != nil && len(*p.srcs) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.src != nil && *p.src == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
69
apex/apex.go
69
apex/apex.go
@@ -149,6 +149,7 @@ func init() {
|
|||||||
android.RegisterModuleType("apex", apexBundleFactory)
|
android.RegisterModuleType("apex", apexBundleFactory)
|
||||||
android.RegisterModuleType("apex_test", testApexBundleFactory)
|
android.RegisterModuleType("apex_test", testApexBundleFactory)
|
||||||
android.RegisterModuleType("apex_defaults", defaultsFactory)
|
android.RegisterModuleType("apex_defaults", defaultsFactory)
|
||||||
|
android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
|
||||||
|
|
||||||
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.TopDown("apex_deps", apexDepsMutator)
|
ctx.TopDown("apex_deps", apexDepsMutator)
|
||||||
@@ -1283,3 +1284,71 @@ func DefaultsFactory(props ...interface{}) android.Module {
|
|||||||
android.InitDefaultsModule(module)
|
android.InitDefaultsModule(module)
|
||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Prebuilt APEX
|
||||||
|
//
|
||||||
|
type Prebuilt struct {
|
||||||
|
android.ModuleBase
|
||||||
|
prebuilt android.Prebuilt
|
||||||
|
|
||||||
|
properties PrebuiltProperties
|
||||||
|
|
||||||
|
inputApex android.Path
|
||||||
|
installDir android.OutputPath
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrebuiltProperties struct {
|
||||||
|
// the path to the prebuilt .apex file to import.
|
||||||
|
Src string `android:"arch_variant"`
|
||||||
|
|
||||||
|
// the name of the apex_key module that contains the matching public key to be installed.
|
||||||
|
Key *string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
if String(p.properties.Key) == "" {
|
||||||
|
ctx.ModuleErrorf("key is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.AddDependency(ctx.Module(), keyTag, *p.properties.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
// TODO(jungjw): Check the key validity.
|
||||||
|
p.inputApex = p.prebuilt.SingleSourcePath(ctx)
|
||||||
|
p.installDir = android.PathForModuleInstall(ctx, "apex")
|
||||||
|
ctx.InstallFile(p.installDir, ctx.ModuleName()+imageApexSuffix, p.inputApex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) Prebuilt() *android.Prebuilt {
|
||||||
|
return &p.prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) Name() string {
|
||||||
|
return p.prebuilt.Name(p.ModuleBase.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) AndroidMk() android.AndroidMkData {
|
||||||
|
return android.AndroidMkData{
|
||||||
|
Class: "ETC",
|
||||||
|
OutputFile: android.OptionalPathForPath(p.inputApex),
|
||||||
|
Include: "$(BUILD_PREBUILT)",
|
||||||
|
Extra: []android.AndroidMkExtraFunc{
|
||||||
|
func(w io.Writer, outputFile android.Path) {
|
||||||
|
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", p.installDir.RelPathString()))
|
||||||
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", p.BaseModuleName()+imageApexSuffix)
|
||||||
|
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(p.properties.Key))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
|
||||||
|
func PrebuiltFactory() android.Module {
|
||||||
|
module := &Prebuilt{}
|
||||||
|
module.AddProperties(&module.properties)
|
||||||
|
android.InitSingleSourcePrebuiltModule(module, &module.properties.Src)
|
||||||
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
||||||
|
return module
|
||||||
|
}
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
package apex
|
package apex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -36,11 +38,14 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
|
ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
|
||||||
ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
|
ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
|
||||||
ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
|
ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
|
||||||
|
ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))
|
||||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||||
|
|
||||||
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.TopDown("apex_deps", apexDepsMutator)
|
ctx.TopDown("apex_deps", apexDepsMutator)
|
||||||
ctx.BottomUp("apex", apexMutator)
|
ctx.BottomUp("apex", apexMutator)
|
||||||
|
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
|
||||||
|
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
|
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
|
||||||
@@ -54,6 +59,9 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
|
ctx.RegisterModuleType("sh_binary", android.ModuleFactoryAdaptor(android.ShBinaryFactory))
|
||||||
ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
|
ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(java.AndroidAppCertificateFactory))
|
||||||
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
|
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
|
||||||
|
ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
|
ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
|
||||||
|
})
|
||||||
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.BottomUp("image", cc.ImageMutator).Parallel()
|
ctx.BottomUp("image", cc.ImageMutator).Parallel()
|
||||||
ctx.BottomUp("link", cc.LinkageMutator).Parallel()
|
ctx.BottomUp("link", cc.LinkageMutator).Parallel()
|
||||||
@@ -163,6 +171,7 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
"custom_notice": nil,
|
"custom_notice": nil,
|
||||||
"testkey2.avbpubkey": nil,
|
"testkey2.avbpubkey": nil,
|
||||||
"testkey2.pem": nil,
|
"testkey2.pem": nil,
|
||||||
|
"myapex.apex": nil,
|
||||||
})
|
})
|
||||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
@@ -1229,3 +1238,42 @@ func TestApexKeyFromOtherModule(t *testing.T) {
|
|||||||
t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
|
t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrebuilt(t *testing.T) {
|
||||||
|
ctx := testApex(t, `
|
||||||
|
prebuilt_apex {
|
||||||
|
name: "myapex",
|
||||||
|
src: "myapex.apex",
|
||||||
|
key: "myapex.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
product_specific: true,
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
prebuilt := ctx.ModuleForTests("myapex", "android_common").Module().(*Prebuilt)
|
||||||
|
|
||||||
|
// Check if the key module is added as a required module.
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
prebuilt.AndroidMk().Extra[0](buf, nil)
|
||||||
|
found := false
|
||||||
|
scanner := bufio.NewScanner(bytes.NewReader(buf.Bytes()))
|
||||||
|
expected := "myapex.key"
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
tok := strings.Split(line, " := ")
|
||||||
|
if tok[0] == "LOCAL_REQUIRED_MODULES" {
|
||||||
|
found = true
|
||||||
|
if tok[1] != "myapex.key" {
|
||||||
|
t.Errorf("Unexpected LOCAL_REQUIRED_MODULES '%s', expected '%s'", tok[1], expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("Couldn't find a LOCAL_REQUIRED_MODULES entry")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -93,7 +93,7 @@ func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
|
pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
|
||||||
privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
|
privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
|
||||||
|
|
||||||
if pubKeyName != privKeyName {
|
if m.properties.Public_key != nil && m.properties.Private_key != nil && pubKeyName != privKeyName {
|
||||||
ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
|
ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
|
||||||
m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
|
m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user