Merge "Bolster comments in android/androidmk.go."

This commit is contained in:
Jaewoong Jung 2020-12-02 15:16:27 +00:00 committed by Gerrit Code Review
commit 2b2bc8c712

View file

@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// This file offers AndroidMkEntriesProvider, which individual modules implement to output
// Android.mk entries that contain information about the modules built through Soong. Kati reads
// and combines them with the legacy Make-based module definitions to produce the complete view of
// the source tree, which makes this a critical point of Make-Soong interoperability.
//
// Naturally, Soong-only builds do not rely on this mechanism.
package android package android
import ( import (
@ -36,8 +43,8 @@ func RegisterAndroidMkBuildComponents(ctx RegistrationContext) {
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton) ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
} }
// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to // Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
// use the Custom function. // Custom function. It's easier to use and test.
type AndroidMkDataProvider interface { type AndroidMkDataProvider interface {
AndroidMk() AndroidMkData AndroidMk() AndroidMkData
BaseModuleName() string BaseModuleName() string
@ -63,37 +70,82 @@ 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. // Interface for modules to declare their Android.mk outputs. Note that every module needs to
// implement this in order to be included in the final Android-<product_name>.mk output, even if
// they only need to output the common set of entries without any customizations.
type AndroidMkEntriesProvider interface { type AndroidMkEntriesProvider interface {
// Returns AndroidMkEntries objects that contain all basic info plus extra customization data
// if needed. This is the core func to implement.
// Note that one can return multiple objects. For example, java_library may return an additional
// AndroidMkEntries object for its hostdex sub-module.
AndroidMkEntries() []AndroidMkEntries AndroidMkEntries() []AndroidMkEntries
// Modules don't need to implement this as it's already implemented by ModuleBase.
// AndroidMkEntries uses BaseModuleName() instead of ModuleName() because certain modules
// e.g. Prebuilts, override the Name() func and return modified names.
// If a different name is preferred, use SubName or OverrideName in AndroidMkEntries.
BaseModuleName() string BaseModuleName() string
} }
// The core data struct that modules use to provide their Android.mk data.
type AndroidMkEntries struct { type AndroidMkEntries struct {
Class string // Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC
SubName string Class string
OverrideName string // Optional suffix to append to the module name. Useful when a module wants to return multiple
DistFiles TaggedDistFiles // AndroidMkEntries objects. For example, when a java_library returns an additional entry for
OutputFile OptionalPath // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
Disabled bool // different name than the parent's.
Include string SubName string
Required []string // If set, this value overrides the base module name. SubName is still appended.
Host_required []string OverrideName string
// Dist files to output
DistFiles TaggedDistFiles
// The output file for Kati to process and/or install. If absent, the module is skipped.
OutputFile OptionalPath
// If true, the module is skipped and does not appear on the final Android-<product name>.mk
// file. Useful when a module needs to be skipped conditionally.
Disabled bool
// The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_prebuilt.mk
// If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
Include string
// Required modules that need to be built and included in the final build output when building
// this module.
Required []string
// Required host modules that need to be built and included in the final build output when
// building this module.
Host_required []string
// Required device modules that need to be built and included in the final build output when
// building this module.
Target_required []string Target_required []string
header bytes.Buffer header bytes.Buffer
footer bytes.Buffer footer bytes.Buffer
// Funcs to append additional Android.mk entries or modify the common ones. Multiple funcs are
// accepted so that common logic can be factored out as a shared func.
ExtraEntries []AndroidMkExtraEntriesFunc ExtraEntries []AndroidMkExtraEntriesFunc
// Funcs to add extra lines to the module's Android.mk output. Unlike AndroidMkExtraEntriesFunc,
// which simply sets Make variable values, this can be used for anything since it can write any
// Make statements directly to the final Android-*.mk file.
// Primarily used to call macros or declare/update Make targets.
ExtraFooters []AndroidMkExtraFootersFunc ExtraFooters []AndroidMkExtraFootersFunc
EntryMap map[string][]string // A map that holds the up-to-date Make variable values. Can be accessed from tests.
EntryMap map[string][]string
// A list of EntryMap keys in insertion order. This serves a few purposes:
// 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
// the outputted Android-*.mk file may change even though there have been no content changes.
// 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
// without worrying about the variables being mixed up in the actual mk file.
// 3. Makes troubleshooting and spotting errors easier.
entryOrder []string entryOrder []string
} }
type AndroidMkExtraEntriesFunc func(entries *AndroidMkEntries) type AndroidMkExtraEntriesFunc func(entries *AndroidMkEntries)
type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries) type AndroidMkExtraFootersFunc func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries)
// Utility funcs to manipulate Android.mk variable entries.
// SetString sets a Make variable with the given name to the given value.
func (a *AndroidMkEntries) SetString(name, value string) { func (a *AndroidMkEntries) SetString(name, value string) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -101,6 +153,7 @@ func (a *AndroidMkEntries) SetString(name, value string) {
a.EntryMap[name] = []string{value} a.EntryMap[name] = []string{value}
} }
// SetPath sets a Make variable with the given name to the given path string.
func (a *AndroidMkEntries) SetPath(name string, path Path) { func (a *AndroidMkEntries) SetPath(name string, path Path) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -108,12 +161,15 @@ func (a *AndroidMkEntries) SetPath(name string, path Path) {
a.EntryMap[name] = []string{path.String()} a.EntryMap[name] = []string{path.String()}
} }
// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
// It is a no-op if the given path is invalid.
func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) { func (a *AndroidMkEntries) SetOptionalPath(name string, path OptionalPath) {
if path.Valid() { if path.Valid() {
a.SetPath(name, path.Path()) a.SetPath(name, path.Path())
} }
} }
// AddPath appends the given path string to a Make variable with the given name.
func (a *AndroidMkEntries) AddPath(name string, path Path) { func (a *AndroidMkEntries) AddPath(name string, path Path) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -121,12 +177,15 @@ func (a *AndroidMkEntries) AddPath(name string, path Path) {
a.EntryMap[name] = append(a.EntryMap[name], path.String()) a.EntryMap[name] = append(a.EntryMap[name], path.String())
} }
// AddOptionalPath appends the given path string to a Make variable with the given name if it is
// valid. It is a no-op if the given path is invalid.
func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) { func (a *AndroidMkEntries) AddOptionalPath(name string, path OptionalPath) {
if path.Valid() { if path.Valid() {
a.AddPath(name, path.Path()) a.AddPath(name, path.Path())
} }
} }
// SetPaths sets a Make variable with the given name to a slice of the given path strings.
func (a *AndroidMkEntries) SetPaths(name string, paths Paths) { func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -134,12 +193,15 @@ func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
a.EntryMap[name] = paths.Strings() a.EntryMap[name] = paths.Strings()
} }
// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
// only if there are a non-zero amount of paths.
func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) { func (a *AndroidMkEntries) SetOptionalPaths(name string, paths Paths) {
if len(paths) > 0 { if len(paths) > 0 {
a.SetPaths(name, paths) a.SetPaths(name, paths)
} }
} }
// AddPaths appends the given path strings to a Make variable with the given name.
func (a *AndroidMkEntries) AddPaths(name string, paths Paths) { func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -147,6 +209,8 @@ func (a *AndroidMkEntries) AddPaths(name string, paths Paths) {
a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...) a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
} }
// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
// It is a no-op if the given flag is false.
func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) { func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
if flag { if flag {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
@ -156,6 +220,7 @@ func (a *AndroidMkEntries) SetBoolIfTrue(name string, flag bool) {
} }
} }
// SetBool sets a Make variable with the given name to if the given bool flag value.
func (a *AndroidMkEntries) SetBool(name string, flag bool) { func (a *AndroidMkEntries) SetBool(name string, flag bool) {
if _, ok := a.EntryMap[name]; !ok { if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name) a.entryOrder = append(a.entryOrder, name)
@ -167,6 +232,7 @@ func (a *AndroidMkEntries) SetBool(name string, flag bool) {
} }
} }
// AddStrings appends the given strings to a Make variable with the given name.
func (a *AndroidMkEntries) AddStrings(name string, value ...string) { func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
if len(value) == 0 { if len(value) == 0 {
return return
@ -368,6 +434,8 @@ func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
return generateDistContributionsForMake(distContributions) return generateDistContributionsForMake(distContributions)
} }
// fillInEntries goes through the common variable processing and calls the extra data funcs to
// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) { func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
a.EntryMap = make(map[string][]string) a.EntryMap = make(map[string][]string)
amod := mod.(Module).base() amod := mod.(Module).base()
@ -488,6 +556,8 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep
} }
} }
// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
// given Writer object.
func (a *AndroidMkEntries) write(w io.Writer) { func (a *AndroidMkEntries) write(w io.Writer) {
if a.Disabled { if a.Disabled {
return return
@ -508,6 +578,8 @@ func (a *AndroidMkEntries) FooterLinesForTests() []string {
return strings.Split(string(a.footer.Bytes()), "\n") return strings.Split(string(a.footer.Bytes()), "\n")
} }
// AndroidMkSingleton is a singleton to collect Android.mk data from all modules and dump them into
// the final Android-<product_name>.mk file output.
func AndroidMkSingleton() Singleton { func AndroidMkSingleton() Singleton {
return &androidMkSingleton{} return &androidMkSingleton{}
} }
@ -515,6 +587,7 @@ func AndroidMkSingleton() Singleton {
type androidMkSingleton struct{} type androidMkSingleton struct{}
func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) { func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
// Skip if Soong wasn't invoked from Make.
if !ctx.Config().KatiEnabled() { if !ctx.Config().KatiEnabled() {
return return
} }
@ -525,6 +598,8 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
androidMkModulesList = append(androidMkModulesList, module) androidMkModulesList = append(androidMkModulesList, module)
}) })
// Sort the module list by the module names to eliminate random churns, which may erroneously
// invoke additional build processes.
sort.SliceStable(androidMkModulesList, func(i, j int) bool { sort.SliceStable(androidMkModulesList, func(i, j int) bool {
return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j]) return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
}) })
@ -617,6 +692,8 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M
} }
} }
// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
// m by making them phony targets.
func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
goBinary bootstrap.GoBinaryTool) error { goBinary bootstrap.GoBinaryTool) error {
@ -649,6 +726,8 @@ func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprin
data.Target_required = data.Entries.Target_required data.Target_required = data.Entries.Target_required
} }
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
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 {
@ -695,6 +774,8 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
return nil return nil
} }
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
func WriteAndroidMkData(w io.Writer, data AndroidMkData) { func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
if data.Disabled { if data.Disabled {
return return
@ -742,11 +823,14 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
module.Os() == LinuxBionic module.Os() == LinuxBionic
} }
// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
// to use this func.
func AndroidMkDataPaths(data []DataPath) []string { func AndroidMkDataPaths(data []DataPath) []string {
var testFiles []string var testFiles []string
for _, d := range data { for _, d := range data {
rel := d.SrcPath.Rel() rel := d.SrcPath.Rel()
path := d.SrcPath.String() path := d.SrcPath.String()
// LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
if !strings.HasSuffix(path, rel) { if !strings.HasSuffix(path, rel) {
panic(fmt.Errorf("path %q does not end with %q", path, rel)) panic(fmt.Errorf("path %q does not end with %q", path, rel))
} }