Loading android/androidmk.go +238 −135 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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{} } Loading Loading @@ -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 } Loading @@ -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() { Loading @@ -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 { Loading Loading @@ -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 } android/prebuilt_etc.go +16 −31 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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)") }, } } Loading android/prebuilt_etc_test.go +20 −34 Original line number Diff line number Diff line Loading @@ -15,12 +15,10 @@ package android import ( "bufio" "bytes" "io/ioutil" "os" "path/filepath" "strings" "reflect" "testing" ) Loading Loading @@ -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) } } } Loading android/testing.go +11 −0 Original line number Diff line number Diff line Loading @@ -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 } java/androidmk.go +9 −1 Original line number Diff line number Diff line Loading @@ -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") } } Loading Loading
android/androidmk.go +238 −135 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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{} } Loading Loading @@ -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 } Loading @@ -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() { Loading @@ -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 { Loading Loading @@ -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 }
android/prebuilt_etc.go +16 −31 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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)") }, } } Loading
android/prebuilt_etc_test.go +20 −34 Original line number Diff line number Diff line Loading @@ -15,12 +15,10 @@ package android import ( "bufio" "bytes" "io/ioutil" "os" "path/filepath" "strings" "reflect" "testing" ) Loading Loading @@ -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) } } } Loading
android/testing.go +11 −0 Original line number Diff line number Diff line Loading @@ -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 }
java/androidmk.go +9 −1 Original line number Diff line number Diff line Loading @@ -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") } } Loading