Bolster comments in android/androidmk.go.

Bug: 173398138
Test: N/A
Change-Id: I46048b8398356d658fd5ae0299b59e6e18429198
This commit is contained in:
Jaewoong Jung 2020-11-16 12:50:29 -08:00
parent 93bfe6bf76
commit 7ef4a900f4

View file

@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// 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
import (
@ -36,8 +43,8 @@ func RegisterAndroidMkBuildComponents(ctx RegistrationContext) {
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
}
// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to
// use the Custom function.
// Deprecated: Use AndroidMkEntriesProvider instead, especially if you're not going to use the
// Custom function. It's easier to use and test.
type AndroidMkDataProvider interface {
AndroidMk() AndroidMkData
BaseModuleName() string
@ -63,37 +70,82 @@ type AndroidMkData struct {
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 {
// 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
// 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
}
// The core data struct that modules use to provide their Android.mk data.
type AndroidMkEntries struct {
Class string
SubName string
OverrideName string
DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
Required []string
Host_required []string
// Android.mk class string, e.g EXECUTABLES, JAVA_LIBRARIES, ETC
Class string
// Optional suffix to append to the module name. Useful when a module wants to return multiple
// AndroidMkEntries objects. For example, when a java_library returns an additional entry for
// its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
// different name than the parent's.
SubName string
// If set, this value overrides the base module name. SubName is still appended.
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
header 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
// 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
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
}
type AndroidMkExtraEntriesFunc func(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) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@ -101,6 +153,7 @@ func (a *AndroidMkEntries) SetString(name, value string) {
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) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@ -108,12 +161,15 @@ func (a *AndroidMkEntries) SetPath(name string, path Path) {
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) {
if path.Valid() {
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) {
if _, ok := a.EntryMap[name]; !ok {
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())
}
// 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) {
if path.Valid() {
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) {
if _, ok := a.EntryMap[name]; !ok {
a.entryOrder = append(a.entryOrder, name)
@ -134,12 +193,15 @@ func (a *AndroidMkEntries) SetPaths(name string, paths Paths) {
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) {
if len(paths) > 0 {
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) {
if _, ok := a.EntryMap[name]; !ok {
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()...)
}
// 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) {
if flag {
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) {
if _, ok := a.EntryMap[name]; !ok {
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) {
if len(value) == 0 {
return
@ -356,6 +422,8 @@ func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
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) {
a.EntryMap = make(map[string][]string)
amod := mod.(Module).base()
@ -476,6 +544,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) {
if a.Disabled {
return
@ -496,6 +566,8 @@ func (a *AndroidMkEntries) FooterLinesForTests() []string {
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 {
return &androidMkSingleton{}
}
@ -503,6 +575,7 @@ func AndroidMkSingleton() Singleton {
type androidMkSingleton struct{}
func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
// Skip if Soong wasn't invoked from Make.
if !ctx.Config().KatiEnabled() {
return
}
@ -513,6 +586,8 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
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 {
return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
})
@ -605,6 +680,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,
goBinary bootstrap.GoBinaryTool) error {
@ -637,6 +714,8 @@ func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprin
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,
provider AndroidMkDataProvider) error {
@ -683,6 +762,8 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
return nil
}
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
if data.Disabled {
return
@ -730,11 +811,14 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
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 {
var testFiles []string
for _, d := range data {
rel := d.SrcPath.Rel()
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) {
panic(fmt.Errorf("path %q does not end with %q", path, rel))
}