Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8005513 authored by Jaewoong Jung's avatar Jaewoong Jung Committed by android-build-merger
Browse files

Merge "New AndroidMk authoring system based on entry map." am: 159a5852

am: 7cf4b875

Change-Id: I2b9e70d207146ba5a4d2c04489cc680b6f9d0d6f
parents 1044ef7d 7cf4b875
Loading
Loading
Loading
Loading
+238 −135
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ func init() {
	RegisterSingletonType("androidmk", AndroidMkSingleton)
}

// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to
// use the Custom function.
type AndroidMkDataProvider interface {
	AndroidMk() AndroidMkData
	BaseModuleName() string
@@ -57,6 +59,200 @@ type AndroidMkData struct {

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 {
	return &androidMkSingleton{}
}
@@ -159,6 +355,8 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M
		return translateAndroidModule(ctx, w, mod, x)
	case bootstrap.GoBinaryTool:
		return translateGoBinaryModule(ctx, w, mod, x)
	case AndroidMkEntriesProvider:
		return translateAndroidMkEntriesModule(ctx, w, mod, x)
	default:
		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,
	provider AndroidMkDataProvider) error {

	name := provider.BaseModuleName()
	amod := mod.(Module).base()

	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?
	if shouldSkipAndroidMkProcessing(amod) {
		return nil
	}

	data := provider.AndroidMk()

	if data.Include == "" {
		data.Include = "$(BUILD_PREBUILT)"
	}

	data.Required = append(data.Required, amod.commonProperties.Required...)
	data.Host_required = append(data.Host_required, amod.commonProperties.Host_required...)
	data.Target_required = append(data.Target_required, amod.commonProperties.Target_required...)

	// Make does not understand LinuxBionic
	if amod.Os() == LinuxBionic {
		return nil
	// Get the preamble content through AndroidMkEntries logic.
	entries := AndroidMkEntries{
		Class:           data.Class,
		SubName:         data.SubName,
		DistFile:        data.DistFile,
		OutputFile:      data.OutputFile,
		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 := ""
	if amod.ArchSpecific() {
@@ -227,112 +420,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
		}
	}

	if len(amod.commonProperties.Dist.Targets) > 0 {
		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")
	}

	name := provider.BaseModuleName()
	blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))

	if data.Custom != nil {
@@ -362,14 +450,29 @@ func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
	fmt.Fprintln(w, "include "+data.Include)
}

func WriteRequiredModulesSettings(w io.Writer, data AndroidMkData) {
	if len(data.Required) > 0 {
		fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(data.Required, " "))
func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
	provider AndroidMkEntriesProvider) error {
	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, " "))

	entries := provider.AndroidMkEntries()
	entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)

	entries.write(w)

	return nil
}
	if len(data.Target_required) > 0 {
		fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(data.Target_required, " "))

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
}
+16 −31
Original line number Diff line number Diff line
@@ -14,10 +14,7 @@

package android

import (
	"fmt"
	"io"
)
import "strconv"

// 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 {
	return AndroidMkData{
		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
func (p *PrebuiltEtc) AndroidMkEntries() AndroidMkEntries {
	nameSuffix := ""
	if p.inRecovery() && !p.onlyInRecovery() {
		nameSuffix = ".recovery"
	}
			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
			fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
			fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
			if p.commonProperties.Owner != nil {
				fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", *p.commonProperties.Owner)
			}
			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)
	return AndroidMkEntries{
		Class:      "ETC",
		SubName:    nameSuffix,
		OutputFile: OptionalPathForPath(p.outputFilePath),
		AddCustomEntries: func(name, prefix, moduleDir string, entries *AndroidMkEntries) {
			entries.SetString("LOCAL_MODULE_TAGS", "optional")
			entries.SetString("LOCAL_MODULE_PATH", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
			entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
			entries.SetString("LOCAL_UNINSTALLABLE_MODULE", strconv.FormatBool(!p.Installable()))
			if p.additionalDependencies != nil {
				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
				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)")
		},
	}
}
+20 −34
Original line number Diff line number Diff line
@@ -15,12 +15,10 @@
package android

import (
	"bufio"
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"reflect"
	"testing"
)

@@ -139,49 +137,37 @@ func TestPrebuiltEtcGlob(t *testing.T) {
}

func TestPrebuiltEtcAndroidMk(t *testing.T) {
	ctx, _ := testPrebuiltEtc(t, `
	ctx, config := testPrebuiltEtc(t, `
		prebuilt_etc {
			name: "foo",
			src: "foo.conf",
			owner: "abc",
			filename_from_src: true,
			required: ["modA", "moduleB"],
			host_required: ["hostModA", "hostModB"],
			target_required: ["targetModA"],
		}
	`)

	data := AndroidMkData{}
	data.Required = append(data.Required, "modA", "moduleB")
	data.Host_required = append(data.Host_required, "hostModA", "hostModB")
	data.Target_required = append(data.Target_required, "targetModA")

	expected := map[string]string{
		"LOCAL_MODULE":                  "foo",
		"LOCAL_MODULE_CLASS":            "ETC",
		"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",
	expected := map[string][]string{
		"LOCAL_MODULE":                  {"foo"},
		"LOCAL_MODULE_CLASS":            {"ETC"},
		"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)
	buf := &bytes.Buffer{}
	mod.AndroidMk().Custom(buf, "foo", "", "", data)
	for k, expected := range expected {
		found := false
		scanner := bufio.NewScanner(bytes.NewReader(buf.Bytes()))
		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)
				}
			}
		}

		if !found {
			t.Errorf("No %s defined, saw %s", k, buf.String())
	entries := AndroidMkEntriesForTest(t, config, "", mod)
	for k, expectedValue := range expected {
		if value, ok := entries.EntryMap[k]; ok {
			if !reflect.DeepEqual(value, expectedValue) {
				t.Errorf("Incorrect %s '%s', expected '%s'", k, value, expectedValue)
			}
		} else {
			t.Errorf("No %s defined, saw %q", k, entries.EntryMap)
		}
	}
}
+11 −0
Original line number Diff line number Diff line
@@ -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
}
+9 −1
Original line number Diff line number Diff line
@@ -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_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")
	}
}