New AndroidMk authoring system based on entry map.
The new system collects all Android.mk variable assignments using a map and writes them to io.Writer. Compared to the previous system, which directly writes all entries to buffers, this new system is more robust and test-friendly. Test: Built without prebuilt_etc.go change and diffed the mk output. Test: prebuilt_etc_test.go Change-Id: Idd28443d129ff70053295015e69328a8fa3eca47
This commit is contained in:
parent
8bf9bd9f91
commit
9aa3ab1f3f
|
@ -32,6 +32,8 @@ func init() {
|
||||||
RegisterSingletonType("androidmk", AndroidMkSingleton)
|
RegisterSingletonType("androidmk", AndroidMkSingleton)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to
|
||||||
|
// use the Custom function.
|
||||||
type AndroidMkDataProvider interface {
|
type AndroidMkDataProvider interface {
|
||||||
AndroidMk() AndroidMkData
|
AndroidMk() AndroidMkData
|
||||||
BaseModuleName() string
|
BaseModuleName() string
|
||||||
|
@ -57,6 +59,200 @@ type AndroidMkData struct {
|
||||||
|
|
||||||
type AndroidMkExtraFunc func(w io.Writer, outputFile Path)
|
type AndroidMkExtraFunc func(w io.Writer, outputFile Path)
|
||||||
|
|
||||||
|
// Allows modules to customize their Android*.mk output.
|
||||||
|
type AndroidMkEntriesProvider interface {
|
||||||
|
AndroidMkEntries() AndroidMkEntries
|
||||||
|
BaseModuleName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AndroidMkEntries struct {
|
||||||
|
Class string
|
||||||
|
SubName string
|
||||||
|
DistFile OptionalPath
|
||||||
|
OutputFile OptionalPath
|
||||||
|
Disabled bool
|
||||||
|
Include string
|
||||||
|
Required []string
|
||||||
|
Host_required []string
|
||||||
|
Target_required []string
|
||||||
|
|
||||||
|
header bytes.Buffer
|
||||||
|
footer bytes.Buffer
|
||||||
|
|
||||||
|
AddCustomEntries func(name, prefix, moduleDir string, entries *AndroidMkEntries)
|
||||||
|
|
||||||
|
EntryMap map[string][]string
|
||||||
|
entryOrder []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AndroidMkEntries) SetString(name, value string) {
|
||||||
|
if _, ok := a.EntryMap[name]; !ok {
|
||||||
|
a.entryOrder = append(a.entryOrder, name)
|
||||||
|
}
|
||||||
|
a.EntryMap[name] = []string{value}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
|
||||||
|
if flag {
|
||||||
|
if _, ok := a.EntryMap[name]; !ok {
|
||||||
|
a.entryOrder = append(a.entryOrder, name)
|
||||||
|
}
|
||||||
|
a.EntryMap[name] = []string{"true"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
|
||||||
|
if len(value) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := a.EntryMap[name]; !ok {
|
||||||
|
a.entryOrder = append(a.entryOrder, name)
|
||||||
|
}
|
||||||
|
a.EntryMap[name] = append(a.EntryMap[name], value...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
|
||||||
|
a.EntryMap = make(map[string][]string)
|
||||||
|
amod := mod.(Module).base()
|
||||||
|
name := amod.BaseModuleName()
|
||||||
|
|
||||||
|
if a.Include == "" {
|
||||||
|
a.Include = "$(BUILD_PREBUILT)"
|
||||||
|
}
|
||||||
|
a.Required = append(a.Required, amod.commonProperties.Required...)
|
||||||
|
a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...)
|
||||||
|
a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...)
|
||||||
|
|
||||||
|
// Fill in the header part.
|
||||||
|
if len(amod.commonProperties.Dist.Targets) > 0 {
|
||||||
|
distFile := a.DistFile
|
||||||
|
if !distFile.Valid() {
|
||||||
|
distFile = a.OutputFile
|
||||||
|
}
|
||||||
|
if distFile.Valid() {
|
||||||
|
dest := filepath.Base(distFile.String())
|
||||||
|
|
||||||
|
if amod.commonProperties.Dist.Dest != nil {
|
||||||
|
var err error
|
||||||
|
if dest, err = validateSafePath(*amod.commonProperties.Dist.Dest); err != nil {
|
||||||
|
// This was checked in ModuleBase.GenerateBuildActions
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if amod.commonProperties.Dist.Suffix != nil {
|
||||||
|
ext := filepath.Ext(dest)
|
||||||
|
suffix := *amod.commonProperties.Dist.Suffix
|
||||||
|
dest = strings.TrimSuffix(dest, ext) + suffix + ext
|
||||||
|
}
|
||||||
|
|
||||||
|
if amod.commonProperties.Dist.Dir != nil {
|
||||||
|
var err error
|
||||||
|
if dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest); err != nil {
|
||||||
|
// This was checked in ModuleBase.GenerateBuildActions
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
|
||||||
|
fmt.Fprintln(&a.header, ".PHONY:", goals)
|
||||||
|
fmt.Fprintf(&a.header, "$(call dist-for-goals,%s,%s:%s)\n",
|
||||||
|
goals, distFile.String(), dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
|
||||||
|
|
||||||
|
// Collect make variable assignment entries.
|
||||||
|
a.SetString("LOCAL_PATH", filepath.Dir(bpPath))
|
||||||
|
a.SetString("LOCAL_MODULE", name+a.SubName)
|
||||||
|
a.SetString("LOCAL_MODULE_CLASS", a.Class)
|
||||||
|
a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
|
||||||
|
a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
|
||||||
|
a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
|
||||||
|
a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
|
||||||
|
|
||||||
|
archStr := amod.Arch().ArchType.String()
|
||||||
|
host := false
|
||||||
|
switch amod.Os().Class {
|
||||||
|
case Host:
|
||||||
|
// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
|
||||||
|
if archStr != "common" {
|
||||||
|
a.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
|
||||||
|
}
|
||||||
|
host = true
|
||||||
|
case HostCross:
|
||||||
|
// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
|
||||||
|
if archStr != "common" {
|
||||||
|
a.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
|
||||||
|
}
|
||||||
|
host = true
|
||||||
|
case Device:
|
||||||
|
// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
|
||||||
|
if archStr != "common" {
|
||||||
|
a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.AddStrings("LOCAL_INIT_RC", amod.commonProperties.Init_rc...)
|
||||||
|
a.AddStrings("LOCAL_VINTF_FRAGMENTS", amod.commonProperties.Vintf_fragments...)
|
||||||
|
a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(amod.commonProperties.Proprietary))
|
||||||
|
if Bool(amod.commonProperties.Vendor) || Bool(amod.commonProperties.Soc_specific) {
|
||||||
|
a.SetString("LOCAL_VENDOR_MODULE", "true")
|
||||||
|
}
|
||||||
|
a.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(amod.commonProperties.Device_specific))
|
||||||
|
a.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(amod.commonProperties.Product_specific))
|
||||||
|
a.SetBoolIfTrue("LOCAL_PRODUCT_SERVICES_MODULE", Bool(amod.commonProperties.Product_services_specific))
|
||||||
|
if amod.commonProperties.Owner != nil {
|
||||||
|
a.SetString("LOCAL_MODULE_OWNER", *amod.commonProperties.Owner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if amod.noticeFile.Valid() {
|
||||||
|
a.SetString("LOCAL_NOTICE_FILE", amod.noticeFile.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if host {
|
||||||
|
makeOs := amod.Os().String()
|
||||||
|
if amod.Os() == Linux || amod.Os() == LinuxBionic {
|
||||||
|
makeOs = "linux"
|
||||||
|
}
|
||||||
|
a.SetString("LOCAL_MODULE_HOST_OS", makeOs)
|
||||||
|
a.SetString("LOCAL_IS_HOST_MODULE", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := ""
|
||||||
|
if amod.ArchSpecific() {
|
||||||
|
switch amod.Os().Class {
|
||||||
|
case Host:
|
||||||
|
prefix = "HOST_"
|
||||||
|
case HostCross:
|
||||||
|
prefix = "HOST_CROSS_"
|
||||||
|
case Device:
|
||||||
|
prefix = "TARGET_"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if amod.Arch().ArchType != config.Targets[amod.Os()][0].Arch.ArchType {
|
||||||
|
prefix = "2ND_" + prefix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blueprintDir := filepath.Dir(bpPath)
|
||||||
|
if a.AddCustomEntries != nil {
|
||||||
|
a.AddCustomEntries(name, prefix, blueprintDir, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to footer.
|
||||||
|
fmt.Fprintln(&a.footer, "include "+a.Include)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AndroidMkEntries) write(w io.Writer) {
|
||||||
|
w.Write(a.header.Bytes())
|
||||||
|
for _, name := range a.entryOrder {
|
||||||
|
fmt.Fprintln(w, name+" := "+strings.Join(a.EntryMap[name], " "))
|
||||||
|
}
|
||||||
|
w.Write(a.footer.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
func AndroidMkSingleton() Singleton {
|
func AndroidMkSingleton() Singleton {
|
||||||
return &androidMkSingleton{}
|
return &androidMkSingleton{}
|
||||||
}
|
}
|
||||||
|
@ -159,6 +355,8 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M
|
||||||
return translateAndroidModule(ctx, w, mod, x)
|
return translateAndroidModule(ctx, w, mod, x)
|
||||||
case bootstrap.GoBinaryTool:
|
case bootstrap.GoBinaryTool:
|
||||||
return translateGoBinaryModule(ctx, w, mod, x)
|
return translateGoBinaryModule(ctx, w, mod, x)
|
||||||
|
case AndroidMkEntriesProvider:
|
||||||
|
return translateAndroidMkEntriesModule(ctx, w, mod, x)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -178,37 +376,32 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo
|
||||||
func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
|
func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
|
||||||
provider AndroidMkDataProvider) error {
|
provider AndroidMkDataProvider) error {
|
||||||
|
|
||||||
name := provider.BaseModuleName()
|
|
||||||
amod := mod.(Module).base()
|
amod := mod.(Module).base()
|
||||||
|
if shouldSkipAndroidMkProcessing(amod) {
|
||||||
if !amod.Enabled() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if amod.commonProperties.SkipInstall {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !amod.commonProperties.NamespaceExportedToMake {
|
|
||||||
// TODO(jeffrygaston) do we want to validate that there are no modules being
|
|
||||||
// exported to Kati that depend on this module?
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data := provider.AndroidMk()
|
data := provider.AndroidMk()
|
||||||
|
|
||||||
if data.Include == "" {
|
if data.Include == "" {
|
||||||
data.Include = "$(BUILD_PREBUILT)"
|
data.Include = "$(BUILD_PREBUILT)"
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Required = append(data.Required, amod.commonProperties.Required...)
|
// Get the preamble content through AndroidMkEntries logic.
|
||||||
data.Host_required = append(data.Host_required, amod.commonProperties.Host_required...)
|
entries := AndroidMkEntries{
|
||||||
data.Target_required = append(data.Target_required, amod.commonProperties.Target_required...)
|
Class: data.Class,
|
||||||
|
SubName: data.SubName,
|
||||||
// Make does not understand LinuxBionic
|
DistFile: data.DistFile,
|
||||||
if amod.Os() == LinuxBionic {
|
OutputFile: data.OutputFile,
|
||||||
return nil
|
Disabled: data.Disabled,
|
||||||
|
Include: data.Include,
|
||||||
|
Required: data.Required,
|
||||||
|
Host_required: data.Host_required,
|
||||||
|
Target_required: data.Target_required,
|
||||||
}
|
}
|
||||||
|
entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||||
|
// preamble doesn't need the footer content.
|
||||||
|
entries.footer = bytes.Buffer{}
|
||||||
|
entries.write(&data.preamble)
|
||||||
|
|
||||||
prefix := ""
|
prefix := ""
|
||||||
if amod.ArchSpecific() {
|
if amod.ArchSpecific() {
|
||||||
|
@ -227,112 +420,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(amod.commonProperties.Dist.Targets) > 0 {
|
name := provider.BaseModuleName()
|
||||||
distFile := data.DistFile
|
|
||||||
if !distFile.Valid() {
|
|
||||||
distFile = data.OutputFile
|
|
||||||
}
|
|
||||||
if distFile.Valid() {
|
|
||||||
dest := filepath.Base(distFile.String())
|
|
||||||
|
|
||||||
if amod.commonProperties.Dist.Dest != nil {
|
|
||||||
var err error
|
|
||||||
dest, err = validateSafePath(*amod.commonProperties.Dist.Dest)
|
|
||||||
if err != nil {
|
|
||||||
// This was checked in ModuleBase.GenerateBuildActions
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if amod.commonProperties.Dist.Suffix != nil {
|
|
||||||
ext := filepath.Ext(dest)
|
|
||||||
suffix := *amod.commonProperties.Dist.Suffix
|
|
||||||
dest = strings.TrimSuffix(dest, ext) + suffix + ext
|
|
||||||
}
|
|
||||||
|
|
||||||
if amod.commonProperties.Dist.Dir != nil {
|
|
||||||
var err error
|
|
||||||
dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest)
|
|
||||||
if err != nil {
|
|
||||||
// This was checked in ModuleBase.GenerateBuildActions
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
|
|
||||||
fmt.Fprintln(&data.preamble, ".PHONY:", goals)
|
|
||||||
fmt.Fprintf(&data.preamble, "$(call dist-for-goals,%s,%s:%s)\n",
|
|
||||||
goals, distFile.String(), dest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintln(&data.preamble, "\ninclude $(CLEAR_VARS)")
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_PATH :=", filepath.Dir(ctx.BlueprintFile(mod)))
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE :=", name+data.SubName)
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_CLASS :=", data.Class)
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_PREBUILT_MODULE_FILE :=", data.OutputFile.String())
|
|
||||||
WriteRequiredModulesSettings(&data.preamble, data)
|
|
||||||
|
|
||||||
archStr := amod.Arch().ArchType.String()
|
|
||||||
host := false
|
|
||||||
switch amod.Os().Class {
|
|
||||||
case Host:
|
|
||||||
// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
|
|
||||||
if archStr != "common" {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_HOST_ARCH :=", archStr)
|
|
||||||
}
|
|
||||||
host = true
|
|
||||||
case HostCross:
|
|
||||||
// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
|
|
||||||
if archStr != "common" {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
|
|
||||||
}
|
|
||||||
host = true
|
|
||||||
case Device:
|
|
||||||
// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
|
|
||||||
if archStr != "common" {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(amod.commonProperties.Init_rc) > 0 {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_INIT_RC := ", strings.Join(amod.commonProperties.Init_rc, " "))
|
|
||||||
}
|
|
||||||
if len(amod.commonProperties.Vintf_fragments) > 0 {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_VINTF_FRAGMENTS := ", strings.Join(amod.commonProperties.Vintf_fragments, " "))
|
|
||||||
}
|
|
||||||
if Bool(amod.commonProperties.Proprietary) {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_PROPRIETARY_MODULE := true")
|
|
||||||
}
|
|
||||||
if Bool(amod.commonProperties.Vendor) || Bool(amod.commonProperties.Soc_specific) {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_VENDOR_MODULE := true")
|
|
||||||
}
|
|
||||||
if Bool(amod.commonProperties.Device_specific) {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_ODM_MODULE := true")
|
|
||||||
}
|
|
||||||
if Bool(amod.commonProperties.Product_specific) {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_PRODUCT_MODULE := true")
|
|
||||||
}
|
|
||||||
if Bool(amod.commonProperties.Product_services_specific) {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_PRODUCT_SERVICES_MODULE := true")
|
|
||||||
}
|
|
||||||
if amod.commonProperties.Owner != nil {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_OWNER :=", *amod.commonProperties.Owner)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if amod.noticeFile.Valid() {
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_NOTICE_FILE :=", amod.noticeFile.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if host {
|
|
||||||
makeOs := amod.Os().String()
|
|
||||||
if amod.Os() == Linux || amod.Os() == LinuxBionic {
|
|
||||||
makeOs = "linux"
|
|
||||||
}
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_MODULE_HOST_OS :=", makeOs)
|
|
||||||
fmt.Fprintln(&data.preamble, "LOCAL_IS_HOST_MODULE := true")
|
|
||||||
}
|
|
||||||
|
|
||||||
blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
|
blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
|
||||||
|
|
||||||
if data.Custom != nil {
|
if data.Custom != nil {
|
||||||
|
@ -362,14 +450,29 @@ func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
|
||||||
fmt.Fprintln(w, "include "+data.Include)
|
fmt.Fprintln(w, "include "+data.Include)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteRequiredModulesSettings(w io.Writer, data AndroidMkData) {
|
func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
|
||||||
if len(data.Required) > 0 {
|
provider AndroidMkEntriesProvider) error {
|
||||||
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
|
if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
|
||||||
}
|
return nil
|
||||||
if len(data.Host_required) > 0 {
|
|
||||||
fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=", strings.Join(data.Host_required, " "))
|
|
||||||
}
|
|
||||||
if len(data.Target_required) > 0 {
|
|
||||||
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(data.Target_required, " "))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entries := provider.AndroidMkEntries()
|
||||||
|
entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||||
|
|
||||||
|
entries.write(w)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
|
||||||
|
if !module.commonProperties.NamespaceExportedToMake {
|
||||||
|
// TODO(jeffrygaston) do we want to validate that there are no modules being
|
||||||
|
// exported to Kati that depend on this module?
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return !module.Enabled() ||
|
||||||
|
module.commonProperties.SkipInstall ||
|
||||||
|
// Make does not understand LinuxBionic
|
||||||
|
module.Os() == LinuxBionic
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
|
|
||||||
package android
|
package android
|
||||||
|
|
||||||
import (
|
import "strconv"
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
|
// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
|
||||||
|
|
||||||
|
@ -134,37 +131,25 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrebuiltEtc) AndroidMk() AndroidMkData {
|
func (p *PrebuiltEtc) AndroidMkEntries() AndroidMkEntries {
|
||||||
return AndroidMkData{
|
nameSuffix := ""
|
||||||
Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
|
if p.inRecovery() && !p.onlyInRecovery() {
|
||||||
nameSuffix := ""
|
nameSuffix = ".recovery"
|
||||||
if p.inRecovery() && !p.onlyInRecovery() {
|
}
|
||||||
nameSuffix = ".recovery"
|
return AndroidMkEntries{
|
||||||
}
|
Class: "ETC",
|
||||||
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
SubName: nameSuffix,
|
||||||
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
OutputFile: OptionalPathForPath(p.outputFilePath),
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
|
AddCustomEntries: func(name, prefix, moduleDir string, entries *AndroidMkEntries) {
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
|
entries.SetString("LOCAL_MODULE_TAGS", "optional")
|
||||||
if p.commonProperties.Owner != nil {
|
entries.SetString("LOCAL_MODULE_PATH", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", *p.commonProperties.Owner)
|
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
|
||||||
}
|
entries.SetString("LOCAL_UNINSTALLABLE_MODULE", strconv.FormatBool(!p.Installable()))
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
|
|
||||||
if p.Host() {
|
|
||||||
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
|
|
||||||
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
|
|
||||||
fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
|
|
||||||
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable())
|
|
||||||
WriteRequiredModulesSettings(w, data)
|
|
||||||
if p.additionalDependencies != nil {
|
if p.additionalDependencies != nil {
|
||||||
fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
|
|
||||||
for _, path := range *p.additionalDependencies {
|
for _, path := range *p.additionalDependencies {
|
||||||
fmt.Fprint(w, " "+path.String())
|
entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", path.String())
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "")
|
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,10 @@
|
||||||
package android
|
package android
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -139,49 +137,37 @@ func TestPrebuiltEtcGlob(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrebuiltEtcAndroidMk(t *testing.T) {
|
func TestPrebuiltEtcAndroidMk(t *testing.T) {
|
||||||
ctx, _ := testPrebuiltEtc(t, `
|
ctx, config := testPrebuiltEtc(t, `
|
||||||
prebuilt_etc {
|
prebuilt_etc {
|
||||||
name: "foo",
|
name: "foo",
|
||||||
src: "foo.conf",
|
src: "foo.conf",
|
||||||
owner: "abc",
|
owner: "abc",
|
||||||
filename_from_src: true,
|
filename_from_src: true,
|
||||||
|
required: ["modA", "moduleB"],
|
||||||
|
host_required: ["hostModA", "hostModB"],
|
||||||
|
target_required: ["targetModA"],
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
data := AndroidMkData{}
|
expected := map[string][]string{
|
||||||
data.Required = append(data.Required, "modA", "moduleB")
|
"LOCAL_MODULE": {"foo"},
|
||||||
data.Host_required = append(data.Host_required, "hostModA", "hostModB")
|
"LOCAL_MODULE_CLASS": {"ETC"},
|
||||||
data.Target_required = append(data.Target_required, "targetModA")
|
"LOCAL_MODULE_OWNER": {"abc"},
|
||||||
|
"LOCAL_INSTALLED_MODULE_STEM": {"foo.conf"},
|
||||||
expected := map[string]string{
|
"LOCAL_REQUIRED_MODULES": {"modA", "moduleB"},
|
||||||
"LOCAL_MODULE": "foo",
|
"LOCAL_HOST_REQUIRED_MODULES": {"hostModA", "hostModB"},
|
||||||
"LOCAL_MODULE_CLASS": "ETC",
|
"LOCAL_TARGET_REQUIRED_MODULES": {"targetModA"},
|
||||||
"LOCAL_MODULE_OWNER": "abc",
|
|
||||||
"LOCAL_INSTALLED_MODULE_STEM": "foo.conf",
|
|
||||||
"LOCAL_REQUIRED_MODULES": "modA moduleB",
|
|
||||||
"LOCAL_HOST_REQUIRED_MODULES": "hostModA hostModB",
|
|
||||||
"LOCAL_TARGET_REQUIRED_MODULES": "targetModA",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
|
mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
|
||||||
buf := &bytes.Buffer{}
|
entries := AndroidMkEntriesForTest(t, config, "", mod)
|
||||||
mod.AndroidMk().Custom(buf, "foo", "", "", data)
|
for k, expectedValue := range expected {
|
||||||
for k, expected := range expected {
|
if value, ok := entries.EntryMap[k]; ok {
|
||||||
found := false
|
if !reflect.DeepEqual(value, expectedValue) {
|
||||||
scanner := bufio.NewScanner(bytes.NewReader(buf.Bytes()))
|
t.Errorf("Incorrect %s '%s', expected '%s'", k, value, expectedValue)
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
tok := strings.Split(line, " := ")
|
|
||||||
if tok[0] == k {
|
|
||||||
found = true
|
|
||||||
if tok[1] != expected {
|
|
||||||
t.Errorf("Incorrect %s '%s', expected '%s'", k, tok[1], expected)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
|
||||||
if !found {
|
|
||||||
t.Errorf("No %s defined, saw %s", k, buf.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,3 +371,14 @@ func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkEntries {
|
||||||
|
var p AndroidMkEntriesProvider
|
||||||
|
var ok bool
|
||||||
|
if p, ok = mod.(AndroidMkEntriesProvider); !ok {
|
||||||
|
t.Errorf("module does not implmement AndroidMkEntriesProvider: " + mod.Name())
|
||||||
|
}
|
||||||
|
entries := p.AndroidMkEntries()
|
||||||
|
entries.fillInEntries(config, bpPath, mod)
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,15 @@ func (library *Library) AndroidMkHostDex(w io.Writer, name string, data android.
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
|
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
|
||||||
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String())
|
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String())
|
||||||
android.WriteRequiredModulesSettings(w, data)
|
if len(data.Required) > 0 {
|
||||||
|
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
|
||||||
|
}
|
||||||
|
if len(data.Host_required) > 0 {
|
||||||
|
fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=", strings.Join(data.Host_required, " "))
|
||||||
|
}
|
||||||
|
if len(data.Target_required) > 0 {
|
||||||
|
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(data.Target_required, " "))
|
||||||
|
}
|
||||||
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
|
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue