Merge changes from topic "fdo_profile"
* changes: Reimplement afdo support for rust Implement fdo_profile module type
This commit is contained in:
@@ -1418,6 +1418,21 @@ func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
|
|||||||
return c.config.productVariables.PgoAdditionalProfileDirs
|
return c.config.productVariables.PgoAdditionalProfileDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AfdoProfile returns fully qualified path associated to the given module name
|
||||||
|
func (c *deviceConfig) AfdoProfile(name string) (*string, error) {
|
||||||
|
for _, afdoProfile := range c.config.productVariables.AfdoProfiles {
|
||||||
|
split := strings.Split(afdoProfile, ":")
|
||||||
|
if len(split) != 3 {
|
||||||
|
return nil, fmt.Errorf("AFDO_PROFILES has invalid value: %s. "+
|
||||||
|
"The expected format is <module>:<fully-qualified-path-to-fdo_profile>", afdoProfile)
|
||||||
|
}
|
||||||
|
if split[0] == name {
|
||||||
|
return proptools.StringPtr(strings.Join([]string{split[1], split[2]}, ":")), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *deviceConfig) VendorSepolicyDirs() []string {
|
func (c *deviceConfig) VendorSepolicyDirs() []string {
|
||||||
return c.config.productVariables.BoardVendorSepolicyDirs
|
return c.config.productVariables.BoardVendorSepolicyDirs
|
||||||
}
|
}
|
||||||
|
@@ -464,6 +464,8 @@ type productVariables struct {
|
|||||||
|
|
||||||
IncludeTags []string `json:",omitempty"`
|
IncludeTags []string `json:",omitempty"`
|
||||||
SourceRootDirs []string `json:",omitempty"`
|
SourceRootDirs []string `json:",omitempty"`
|
||||||
|
|
||||||
|
AfdoProfiles []string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolPtr(v bool) *bool {
|
func boolPtr(v bool) *bool {
|
||||||
|
@@ -21,6 +21,8 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"afdo.go",
|
"afdo.go",
|
||||||
|
"fdo_profile.go",
|
||||||
|
|
||||||
"androidmk.go",
|
"androidmk.go",
|
||||||
"api_level.go",
|
"api_level.go",
|
||||||
"bp2build.go",
|
"bp2build.go",
|
||||||
|
169
cc/afdo.go
169
cc/afdo.go
@@ -18,11 +18,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/blueprint/proptools"
|
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
"github.com/google/blueprint/proptools"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
|
||||||
var (
|
var (
|
||||||
globalAfdoProfileProjects = []string{
|
globalAfdoProfileProjects = []string{
|
||||||
"vendor/google_data/pgo_profile/sampling/",
|
"vendor/google_data/pgo_profile/sampling/",
|
||||||
@@ -34,23 +36,23 @@ var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
|
|||||||
|
|
||||||
const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
|
const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
|
||||||
|
|
||||||
func getAfdoProfileProjects(config android.DeviceConfig) []string {
|
|
||||||
return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
|
|
||||||
return globalAfdoProfileProjects
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
|
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
|
||||||
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
|
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type afdoRdep struct {
|
||||||
|
VariationName *string
|
||||||
|
ProfilePath *string
|
||||||
|
}
|
||||||
|
|
||||||
type AfdoProperties struct {
|
type AfdoProperties struct {
|
||||||
// Afdo allows developers self-service enroll for
|
// Afdo allows developers self-service enroll for
|
||||||
// automatic feedback-directed optimization using profile data.
|
// automatic feedback-directed optimization using profile data.
|
||||||
Afdo bool
|
Afdo bool
|
||||||
|
|
||||||
AfdoTarget *string `blueprint:"mutated"`
|
FdoProfilePath *string `blueprint:"mutated"`
|
||||||
AfdoDeps []string `blueprint:"mutated"`
|
|
||||||
|
AfdoRDeps []afdoRdep `blueprint:"mutated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type afdo struct {
|
type afdo struct {
|
||||||
@@ -61,79 +63,73 @@ func (afdo *afdo) props() []interface{} {
|
|||||||
return []interface{}{&afdo.Properties}
|
return []interface{}{&afdo.Properties}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (afdo *afdo) AfdoEnabled() bool {
|
// afdoEnabled returns true for binaries and shared libraries
|
||||||
return afdo != nil && afdo.Properties.Afdo && afdo.Properties.AfdoTarget != nil
|
// that set afdo prop to True and there is a profile available
|
||||||
}
|
func (afdo *afdo) afdoEnabled() bool {
|
||||||
|
return afdo != nil && afdo.Properties.Afdo && afdo.Properties.FdoProfilePath != nil
|
||||||
// Get list of profile file names, ordered by level of specialisation. For example:
|
|
||||||
// 1. libfoo_arm64.afdo
|
|
||||||
// 2. libfoo.afdo
|
|
||||||
//
|
|
||||||
// Add more specialisation as needed.
|
|
||||||
func getProfileFiles(ctx android.BaseModuleContext, moduleName string) []string {
|
|
||||||
var files []string
|
|
||||||
files = append(files, moduleName+"_"+ctx.Arch().ArchType.String()+".afdo")
|
|
||||||
files = append(files, moduleName+".afdo")
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
func (props *AfdoProperties) GetAfdoProfileFile(ctx android.BaseModuleContext, module string) android.OptionalPath {
|
|
||||||
// Test if the profile_file is present in any of the Afdo profile projects
|
|
||||||
for _, profileFile := range getProfileFiles(ctx, module) {
|
|
||||||
for _, profileProject := range getAfdoProfileProjects(ctx.DeviceConfig()) {
|
|
||||||
path := android.ExistentPathForSource(ctx, profileProject, profileFile)
|
|
||||||
if path.Valid() {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record that this module's profile file is absent
|
|
||||||
missing := ctx.ModuleDir() + ":" + module
|
|
||||||
recordMissingAfdoProfileFile(ctx, missing)
|
|
||||||
|
|
||||||
return android.OptionalPathForPath(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (afdo *afdo) begin(ctx BaseModuleContext) {
|
|
||||||
if ctx.Host() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ctx.static() && !ctx.staticBinary() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if afdo.Properties.Afdo {
|
|
||||||
module := ctx.ModuleName()
|
|
||||||
if afdo.Properties.GetAfdoProfileFile(ctx, module).Valid() {
|
|
||||||
afdo.Properties.AfdoTarget = proptools.StringPtr(module)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
|
func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
|
||||||
if profile := afdo.Properties.AfdoTarget; profile != nil {
|
if path := afdo.Properties.FdoProfilePath; path != nil {
|
||||||
if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, *profile); profileFile.Valid() {
|
profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
|
||||||
profileFilePath := profileFile.Path()
|
|
||||||
|
|
||||||
profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, profileFile)
|
|
||||||
flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlag)
|
flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlag)
|
||||||
flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlag)
|
flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlag)
|
||||||
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-no-warn-sample-unused=true")
|
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-no-warn-sample-unused=true")
|
||||||
|
|
||||||
// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
|
// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
|
||||||
// if profileFile gets updated
|
// if profileFile gets updated
|
||||||
flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
|
pathForSrc := android.PathForSource(ctx, *path)
|
||||||
flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
|
flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
|
||||||
}
|
flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate afdo requirements down from binaries
|
func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
|
||||||
|
if ctx.Host() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.static() && !ctx.staticBinary() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
|
||||||
|
if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
|
||||||
|
actx.AddFarVariationDependencies(
|
||||||
|
[]blueprint.Variation{
|
||||||
|
{Mutator: "arch", Variation: actx.Target().ArchVariation()},
|
||||||
|
{Mutator: "os", Variation: "android"},
|
||||||
|
},
|
||||||
|
FdoProfileTag,
|
||||||
|
[]string{*fdoProfileName}...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
|
||||||
|
// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
|
||||||
|
func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
if !c.Enabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
|
||||||
|
if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
|
||||||
|
info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
|
||||||
|
c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ FdoProfileMutatorInterface = (*Module)(nil)
|
||||||
|
|
||||||
|
// Propagate afdo requirements down from binaries and shared libraries
|
||||||
func afdoDepsMutator(mctx android.TopDownMutatorContext) {
|
func afdoDepsMutator(mctx android.TopDownMutatorContext) {
|
||||||
if m, ok := mctx.Module().(*Module); ok && m.afdo.AfdoEnabled() {
|
if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
|
||||||
afdoTarget := *m.afdo.Properties.AfdoTarget
|
if path := m.afdo.Properties.FdoProfilePath; path != nil {
|
||||||
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
|
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
|
||||||
tag := mctx.OtherModuleDependencyTag(dep)
|
tag := mctx.OtherModuleDependencyTag(dep)
|
||||||
libTag, isLibTag := tag.(libraryDependencyTag)
|
libTag, isLibTag := tag.(libraryDependencyTag)
|
||||||
@@ -150,27 +146,48 @@ func afdoDepsMutator(mctx android.TopDownMutatorContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dep, ok := dep.(*Module); ok {
|
if dep, ok := dep.(*Module); ok {
|
||||||
dep.afdo.Properties.AfdoDeps = append(dep.afdo.Properties.AfdoDeps, afdoTarget)
|
dep.afdo.Properties.AfdoRDeps = append(
|
||||||
|
dep.afdo.Properties.AfdoRDeps,
|
||||||
|
afdoRdep{
|
||||||
|
VariationName: proptools.StringPtr(encodeTarget(m.Name())),
|
||||||
|
ProfilePath: path,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create afdo variants for modules that need them
|
// Create afdo variants for modules that need them
|
||||||
func afdoMutator(mctx android.BottomUpMutatorContext) {
|
func afdoMutator(mctx android.BottomUpMutatorContext) {
|
||||||
if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
|
if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
|
||||||
if m.afdo.AfdoEnabled() && !m.static() {
|
if !m.static() && m.afdo.Properties.Afdo && m.afdo.Properties.FdoProfilePath != nil {
|
||||||
afdoTarget := *m.afdo.Properties.AfdoTarget
|
mctx.SetDependencyVariation(encodeTarget(m.Name()))
|
||||||
mctx.SetDependencyVariation(encodeTarget(afdoTarget))
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
variationNames := []string{""}
|
variationNames := []string{""}
|
||||||
afdoDeps := android.FirstUniqueStrings(m.afdo.Properties.AfdoDeps)
|
|
||||||
for _, dep := range afdoDeps {
|
variantNameToProfilePath := make(map[string]*string)
|
||||||
variationNames = append(variationNames, encodeTarget(dep))
|
|
||||||
|
for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
|
||||||
|
variantName := *afdoRDep.VariationName
|
||||||
|
// An rdep can be set twice in AfdoRDeps because there can be
|
||||||
|
// more than one path from an afdo-enabled module to
|
||||||
|
// a static dep such as
|
||||||
|
// afdo_enabled_foo -> static_bar ----> static_baz
|
||||||
|
// \ ^
|
||||||
|
// ----------------------|
|
||||||
|
// We only need to create one variant per unique rdep
|
||||||
|
if variantNameToProfilePath[variantName] == nil {
|
||||||
|
variationNames = append(variationNames, variantName)
|
||||||
|
variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(variationNames) > 1 {
|
if len(variationNames) > 1 {
|
||||||
modules := mctx.CreateVariations(variationNames...)
|
modules := mctx.CreateVariations(variationNames...)
|
||||||
for i, name := range variationNames {
|
for i, name := range variationNames {
|
||||||
@@ -180,7 +197,7 @@ func afdoMutator(mctx android.BottomUpMutatorContext) {
|
|||||||
variation := modules[i].(*Module)
|
variation := modules[i].(*Module)
|
||||||
variation.Properties.PreventInstall = true
|
variation.Properties.PreventInstall = true
|
||||||
variation.Properties.HideFromMake = true
|
variation.Properties.HideFromMake = true
|
||||||
variation.afdo.Properties.AfdoTarget = proptools.StringPtr(decodeTarget(name))
|
variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
184
cc/afdo_test.go
184
cc/afdo_test.go
@@ -58,38 +58,77 @@ func TestAfdoDeps(t *testing.T) {
|
|||||||
srcs: ["bar.c"],
|
srcs: ["bar.c"],
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
|
|
||||||
|
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithFdoProfile,
|
||||||
prepareForCcTest,
|
prepareForCcTest,
|
||||||
prepareForAfdoTest,
|
android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"libTest://afdo_profiles_package:libTest_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
fdo_profile {
|
||||||
|
name: "libTest_afdo",
|
||||||
|
profile: "libTest.afdo",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
expectedCFlag := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
|
||||||
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
|
|
||||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
|
|
||||||
|
|
||||||
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||||
|
libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
|
||||||
|
libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
|
||||||
|
|
||||||
|
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
|
||||||
|
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||||
|
if !strings.Contains(cFlags, expectedCFlag) {
|
||||||
|
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
cFlags = libFooAfdoVariant.Rule("cc").Args["cFlags"]
|
||||||
|
if !strings.Contains(cFlags, expectedCFlag) {
|
||||||
|
t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
cFlags = libBarAfdoVariant.Rule("cc").Args["cFlags"]
|
||||||
|
if !strings.Contains(cFlags, expectedCFlag) {
|
||||||
|
t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check dependency edge from afdo-enabled module to static deps
|
||||||
|
if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
|
||||||
t.Errorf("libTest missing dependency on afdo variant of libFoo")
|
t.Errorf("libTest missing dependency on afdo variant of libFoo")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
|
||||||
t.Errorf("libTest missing dependency on afdo variant of libBar")
|
t.Errorf("libTest missing dependency on afdo variant of libBar")
|
||||||
}
|
}
|
||||||
|
|
||||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
// Verify non-afdo variant exists and doesn't contain afdo
|
||||||
if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
|
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
|
||||||
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", w, cFlags)
|
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
|
||||||
}
|
|
||||||
|
|
||||||
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
||||||
if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
|
if strings.Contains(cFlags, expectedCFlag) {
|
||||||
t.Errorf("Expected 'libFoo' to enable afdo, but did not find %q in cflags %q", w, cFlags)
|
t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
|
||||||
|
}
|
||||||
|
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||||
|
if strings.Contains(cFlags, expectedCFlag) {
|
||||||
|
t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
// Check dependency edges of static deps
|
||||||
if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
|
if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
||||||
t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", w, cFlags)
|
t.Errorf("libTest should not depend on non-afdo variant of libFoo")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
||||||
|
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,11 +152,21 @@ func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
|
|||||||
name: "libBar",
|
name: "libBar",
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", "TEST")
|
|
||||||
|
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
prepareForCcTest,
|
prepareForCcTest,
|
||||||
prepareForAfdoTest,
|
PrepareForTestWithFdoProfile,
|
||||||
|
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", ""),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
soong_namespace {
|
||||||
|
}
|
||||||
|
fdo_profile {
|
||||||
|
name: "libFoo_afdo",
|
||||||
|
profile: "libFoo.afdo",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
|
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
|
||||||
@@ -150,7 +199,6 @@ func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
|
|||||||
t.Errorf("Expected no afdo variant of 'bar', got %q", v)
|
t.Errorf("Expected no afdo variant of 'bar', got %q", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
|
func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
|
||||||
@@ -166,11 +214,24 @@ func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
|
|||||||
name: "libFoo",
|
name: "libFoo",
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
|
|
||||||
|
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
prepareForCcTest,
|
prepareForCcTest,
|
||||||
prepareForAfdoTest,
|
PrepareForTestWithFdoProfile,
|
||||||
|
android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"libTest://afdo_profiles_package:libTest_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
fdo_profile {
|
||||||
|
name: "libTest_afdo",
|
||||||
|
profile: "libTest.afdo",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
libFooVariants := result.ModuleVariantsForTests("libFoo")
|
libFooVariants := result.ModuleVariantsForTests("libFoo")
|
||||||
@@ -182,7 +243,6 @@ func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAfdoEnabledWithMultiArchs(t *testing.T) {
|
func TestAfdoEnabledWithMultiArchs(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
bp := `
|
bp := `
|
||||||
cc_library_shared {
|
cc_library_shared {
|
||||||
name: "foo",
|
name: "foo",
|
||||||
@@ -192,20 +252,43 @@ func TestAfdoEnabledWithMultiArchs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithFdoProfile,
|
||||||
prepareForCcTest,
|
prepareForCcTest,
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", "TEST"),
|
android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", "TEST"),
|
android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"foo://afdo_profiles_package:foo_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
soong_namespace {
|
||||||
|
}
|
||||||
|
fdo_profile {
|
||||||
|
name: "foo_afdo",
|
||||||
|
arch: {
|
||||||
|
arm: {
|
||||||
|
profile: "foo_arm.afdo",
|
||||||
|
},
|
||||||
|
arm64: {
|
||||||
|
profile: "foo_arm64.afdo",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
|
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
|
||||||
fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
|
fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
|
||||||
if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
|
if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
|
||||||
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
|
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
|
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
|
||||||
fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
|
fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
|
||||||
if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
|
if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
|
||||||
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
|
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,46 +317,65 @@ func TestMultipleAfdoRDeps(t *testing.T) {
|
|||||||
`
|
`
|
||||||
|
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithFdoProfile,
|
||||||
prepareForCcTest,
|
prepareForCcTest,
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST"),
|
android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libBar.afdo", "TEST"),
|
android.FixtureAddTextFile("afdo_profiles_package/libBar.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"libTest://afdo_profiles_package:libTest_afdo",
|
||||||
|
"libBar://afdo_profiles_package:libBar_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
fdo_profile {
|
||||||
|
name: "libTest_afdo",
|
||||||
|
profile: "libTest.afdo",
|
||||||
|
}
|
||||||
|
fdo_profile {
|
||||||
|
name: "libBar_afdo",
|
||||||
|
profile: "libBar.afdo",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
expectedCFlagLibTest := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libTest.afdo"
|
expectedCFlagLibTest := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
|
||||||
expectedCFlagLibBar := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libBar.afdo"
|
expectedCFlagLibBar := "-fprofile-sample-use=afdo_profiles_package/libBar.afdo"
|
||||||
|
|
||||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||||
libTestAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
|
libFooAfdoVariantWithLibTest := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
|
||||||
|
|
||||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
|
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
|
||||||
libBarAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
|
libFooAfdoVariantWithLibBar := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
|
||||||
|
|
||||||
// Check cFlags of afdo-enabled modules and the afdo-variant of their static deps
|
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
|
||||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||||
if !strings.Contains(cFlags, expectedCFlagLibTest) {
|
if !strings.Contains(cFlags, expectedCFlagLibTest) {
|
||||||
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
|
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
|
||||||
}
|
}
|
||||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||||
if !strings.Contains(cFlags, expectedCFlagLibBar) {
|
if !strings.Contains(cFlags, expectedCFlagLibBar) {
|
||||||
t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
|
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
cFlags = libTestAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
|
cFlags = libFooAfdoVariantWithLibTest.Rule("cc").Args["cFlags"]
|
||||||
if !strings.Contains(cFlags, expectedCFlagLibTest) {
|
if !strings.Contains(cFlags, expectedCFlagLibTest) {
|
||||||
t.Errorf("Expected 'libTestAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
|
t.Errorf("Expected 'libFooAfdoVariantWithLibTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
cFlags = libBarAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
|
cFlags = libFooAfdoVariantWithLibBar.Rule("cc").Args["cFlags"]
|
||||||
if !strings.Contains(cFlags, expectedCFlagLibBar) {
|
if !strings.Contains(cFlags, expectedCFlagLibBar) {
|
||||||
t.Errorf("Expected 'libBarAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
|
t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check dependency edges of static deps
|
// Check dependency edges of static deps
|
||||||
if !hasDirectDep(result, libTest.Module(), libTestAfdoVariantOfLibFoo.Module()) {
|
if !hasDirectDep(result, libTest.Module(), libFooAfdoVariantWithLibTest.Module()) {
|
||||||
t.Errorf("libTest missing dependency on afdo variant of libFoo")
|
t.Errorf("libTest missing dependency on afdo variant of libFoo")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasDirectDep(result, libBar.Module(), libBarAfdoVariantOfLibFoo.Module()) {
|
if !hasDirectDep(result, libBar.Module(), libFooAfdoVariantWithLibBar.Module()) {
|
||||||
t.Errorf("libBar missing dependency on afdo variant of libFoo")
|
t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
cc/cc.go
11
cc/cc.go
@@ -52,6 +52,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
|
|||||||
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
|
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
|
||||||
ctx.BottomUp("version", versionMutator).Parallel()
|
ctx.BottomUp("version", versionMutator).Parallel()
|
||||||
ctx.BottomUp("begin", BeginMutator).Parallel()
|
ctx.BottomUp("begin", BeginMutator).Parallel()
|
||||||
|
ctx.BottomUp("fdo_profile", fdoProfileMutator)
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
@@ -763,6 +764,7 @@ var (
|
|||||||
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
|
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
|
||||||
stubImplDepTag = dependencyTag{name: "stub_impl"}
|
stubImplDepTag = dependencyTag{name: "stub_impl"}
|
||||||
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
|
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
|
||||||
|
FdoProfileTag = dependencyTag{name: "fdo_profile"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
|
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
|
||||||
@@ -1336,7 +1338,7 @@ func (c *Module) IsVndk() bool {
|
|||||||
|
|
||||||
func (c *Module) isAfdoCompile() bool {
|
func (c *Module) isAfdoCompile() bool {
|
||||||
if afdo := c.afdo; afdo != nil {
|
if afdo := c.afdo; afdo != nil {
|
||||||
return afdo.Properties.AfdoTarget != nil
|
return afdo.Properties.FdoProfilePath != nil
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -2162,9 +2164,6 @@ func (c *Module) begin(ctx BaseModuleContext) {
|
|||||||
if c.lto != nil {
|
if c.lto != nil {
|
||||||
c.lto.begin(ctx)
|
c.lto.begin(ctx)
|
||||||
}
|
}
|
||||||
if c.afdo != nil {
|
|
||||||
c.afdo.begin(ctx)
|
|
||||||
}
|
|
||||||
if c.pgo != nil {
|
if c.pgo != nil {
|
||||||
c.pgo.begin(ctx)
|
c.pgo.begin(ctx)
|
||||||
}
|
}
|
||||||
@@ -2239,6 +2238,10 @@ func (c *Module) beginMutator(actx android.BottomUpMutatorContext) {
|
|||||||
}
|
}
|
||||||
ctx.ctx = ctx
|
ctx.ctx = ctx
|
||||||
|
|
||||||
|
if !actx.Host() || !ctx.static() || ctx.staticBinary() {
|
||||||
|
c.afdo.addDep(ctx, actx)
|
||||||
|
}
|
||||||
|
|
||||||
c.begin(ctx)
|
c.begin(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
cc/fdo_profile.go
Normal file
85
cc/fdo_profile.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2023 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"android/soong/android"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterFdoProfileBuildComponents(android.InitRegistrationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
|
||||||
|
ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fdoProfile struct {
|
||||||
|
android.ModuleBase
|
||||||
|
|
||||||
|
properties fdoProfileProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
type fdoProfileProperties struct {
|
||||||
|
Profile *string `android:"arch_variant"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FdoProfileInfo is provided by FdoProfileProvider
|
||||||
|
type FdoProfileInfo struct {
|
||||||
|
Path android.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
// FdoProfileProvider is used to provide path to an fdo profile
|
||||||
|
var FdoProfileProvider = blueprint.NewMutatorProvider(FdoProfileInfo{}, "fdo_profile")
|
||||||
|
|
||||||
|
// FdoProfileMutatorInterface is the interface implemented by fdo_profile module type
|
||||||
|
// module types that can depend on an fdo_profile module
|
||||||
|
type FdoProfileMutatorInterface interface {
|
||||||
|
// FdoProfileMutator eithers set or get FdoProfileProvider
|
||||||
|
fdoProfileMutator(ctx android.BottomUpMutatorContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ FdoProfileMutatorInterface = (*fdoProfile)(nil)
|
||||||
|
|
||||||
|
// GenerateAndroidBuildActions of fdo_profile does not have any build actions
|
||||||
|
func (fp *fdoProfile) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
|
||||||
|
|
||||||
|
// FdoProfileMutator sets FdoProfileProvider to fdo_profile module
|
||||||
|
// or sets afdo.Properties.FdoProfilePath to path in FdoProfileProvider of the depended fdo_profile
|
||||||
|
func (fp *fdoProfile) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
if fp.properties.Profile != nil {
|
||||||
|
path := android.PathForModuleSrc(ctx, *fp.properties.Profile)
|
||||||
|
ctx.SetProvider(FdoProfileProvider, FdoProfileInfo{
|
||||||
|
Path: path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fdoProfileMutator calls the generic fdoProfileMutator function of fdoProfileMutator
|
||||||
|
// which is implemented by cc and cc.FdoProfile
|
||||||
|
func fdoProfileMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
if f, ok := ctx.Module().(FdoProfileMutatorInterface); ok {
|
||||||
|
f.fdoProfileMutator(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fdoProfileFactory() android.Module {
|
||||||
|
m := &fdoProfile{}
|
||||||
|
m.AddProperties(&m.properties)
|
||||||
|
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
|
||||||
|
return m
|
||||||
|
}
|
@@ -670,6 +670,12 @@ var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
|
|||||||
`),
|
`),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
|
||||||
|
var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
|
||||||
|
ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
|
||||||
|
ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
|
||||||
|
})
|
||||||
|
|
||||||
// TestConfig is the legacy way of creating a test Config for testing cc modules.
|
// TestConfig is the legacy way of creating a test Config for testing cc modules.
|
||||||
//
|
//
|
||||||
// See testCc for an explanation as to how to stop using this deprecated method.
|
// See testCc for an explanation as to how to stop using this deprecated method.
|
||||||
|
47
rust/afdo.go
47
rust/afdo.go
@@ -17,7 +17,10 @@ package rust
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
)
|
)
|
||||||
|
|
||||||
const afdoFlagFormat = "-Zprofile-sample-use=%s"
|
const afdoFlagFormat = "-Zprofile-sample-use=%s"
|
||||||
@@ -30,19 +33,49 @@ func (afdo *afdo) props() []interface{} {
|
|||||||
return []interface{}{&afdo.Properties}
|
return []interface{}{&afdo.Properties}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (afdo *afdo) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
|
func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
|
||||||
|
// afdo is not supported outside of Android
|
||||||
|
if ctx.Host() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
|
||||||
|
fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName())
|
||||||
|
if err != nil {
|
||||||
|
ctx.ModuleErrorf("%s", err.Error())
|
||||||
|
}
|
||||||
|
if fdoProfileName != nil {
|
||||||
|
actx.AddFarVariationDependencies(
|
||||||
|
[]blueprint.Variation{
|
||||||
|
{Mutator: "arch", Variation: actx.Target().ArchVariation()},
|
||||||
|
{Mutator: "os", Variation: "android"},
|
||||||
|
},
|
||||||
|
cc.FdoProfileTag,
|
||||||
|
[]string{*fdoProfileName}...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (afdo *afdo) flags(ctx android.ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
|
||||||
if ctx.Host() {
|
if ctx.Host() {
|
||||||
return flags, deps
|
return flags, deps
|
||||||
}
|
}
|
||||||
|
|
||||||
if afdo != nil && afdo.Properties.Afdo {
|
if !afdo.Properties.Afdo {
|
||||||
if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, ctx.ModuleName()); profileFile.Valid() {
|
return flags, deps
|
||||||
profileUseFlag := fmt.Sprintf(afdoFlagFormat, profileFile)
|
}
|
||||||
|
|
||||||
|
ctx.VisitDirectDepsWithTag(cc.FdoProfileTag, func(m android.Module) {
|
||||||
|
if ctx.OtherModuleHasProvider(m, cc.FdoProfileProvider) {
|
||||||
|
info := ctx.OtherModuleProvider(m, cc.FdoProfileProvider).(cc.FdoProfileInfo)
|
||||||
|
path := info.Path
|
||||||
|
profileUseFlag := fmt.Sprintf(afdoFlagFormat, path.String())
|
||||||
flags.RustFlags = append(flags.RustFlags, profileUseFlag)
|
flags.RustFlags = append(flags.RustFlags, profileUseFlag)
|
||||||
|
|
||||||
profileFilePath := profileFile.Path()
|
deps.AfdoProfiles = append(deps.AfdoProfiles, path)
|
||||||
deps.AfdoProfiles = append(deps.AfdoProfiles, profileFilePath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return flags, deps
|
return flags, deps
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ package rust
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"android/soong/cc"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -31,13 +32,27 @@ func TestAfdoEnabled(t *testing.T) {
|
|||||||
`
|
`
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
prepareForRustTest,
|
prepareForRustTest,
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo.afdo", ""),
|
cc.PrepareForTestWithFdoProfile,
|
||||||
|
android.FixtureAddTextFile("afdo_profiles_package/foo.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"foo://afdo_profiles_package:foo_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
fdo_profile {
|
||||||
|
name: "foo_afdo",
|
||||||
|
profile: "foo.afdo",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
rustMockedFiles.AddToFixture(),
|
rustMockedFiles.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
|
foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
|
||||||
|
|
||||||
expectedCFlag := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo.afdo")
|
expectedCFlag := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo.afdo")
|
||||||
|
|
||||||
if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
|
if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
|
||||||
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
|
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
|
||||||
@@ -55,16 +70,37 @@ func TestAfdoEnabledWithMultiArchs(t *testing.T) {
|
|||||||
`
|
`
|
||||||
result := android.GroupFixturePreparers(
|
result := android.GroupFixturePreparers(
|
||||||
prepareForRustTest,
|
prepareForRustTest,
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", ""),
|
cc.PrepareForTestWithFdoProfile,
|
||||||
android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", ""),
|
android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
|
||||||
|
android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
|
||||||
|
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||||
|
variables.AfdoProfiles = []string{
|
||||||
|
"foo://afdo_profiles_package:foo_afdo",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
android.MockFS{
|
||||||
|
"afdo_profiles_package/Android.bp": []byte(`
|
||||||
|
fdo_profile {
|
||||||
|
name: "foo_afdo",
|
||||||
|
arch: {
|
||||||
|
arm: {
|
||||||
|
profile: "foo_arm.afdo",
|
||||||
|
},
|
||||||
|
arm64: {
|
||||||
|
profile: "foo_arm64.afdo",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
}.AddToFixture(),
|
||||||
rustMockedFiles.AddToFixture(),
|
rustMockedFiles.AddToFixture(),
|
||||||
).RunTestWithBp(t, bp)
|
).RunTestWithBp(t, bp)
|
||||||
|
|
||||||
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
|
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
|
||||||
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
|
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
|
||||||
|
|
||||||
expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm.afdo")
|
expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm.afdo")
|
||||||
expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm64.afdo")
|
expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm64.afdo")
|
||||||
|
|
||||||
if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
|
if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
|
||||||
t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
|
t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
|
||||||
|
@@ -39,7 +39,6 @@ func init() {
|
|||||||
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
|
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
|
||||||
ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
|
ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
|
||||||
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
|
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
|
||||||
|
|
||||||
})
|
})
|
||||||
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
|
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
|
||||||
@@ -920,7 +919,7 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
|
|
||||||
// Calculate rustc flags
|
// Calculate rustc flags
|
||||||
if mod.afdo != nil {
|
if mod.afdo != nil {
|
||||||
flags, deps = mod.afdo.flags(ctx, flags, deps)
|
flags, deps = mod.afdo.flags(actx, flags, deps)
|
||||||
}
|
}
|
||||||
if mod.compiler != nil {
|
if mod.compiler != nil {
|
||||||
flags = mod.compiler.compilerFlags(ctx, flags)
|
flags = mod.compiler.compilerFlags(ctx, flags)
|
||||||
@@ -1613,6 +1612,8 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||||||
|
|
||||||
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
|
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
|
||||||
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
|
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
|
||||||
|
|
||||||
|
mod.afdo.addDep(ctx, actx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
|
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
|
||||||
|
Reference in New Issue
Block a user