Implement bp2build converter for fdo_profile

Ignore-AOSP-First: ag/24746588, in the same topic, is in an internal repo. This CL will be cherry-picked to AOSP afterward.
Test: go test
Bug: 277091218
Change-Id: I389d9535ea176991a1faa9beb46352b93363acd2
Merged-In: I389d9535ea176991a1faa9beb46352b93363acd2
This commit is contained in:
Vinh Tran 2023-06-05 12:57:55 -04:00
parent 3671c385c7
commit ce40b92c84
6 changed files with 149 additions and 21 deletions

View file

@ -63,6 +63,7 @@ bootstrap_go_package {
"cc_yasm_conversion_test.go", "cc_yasm_conversion_test.go",
"conversion_test.go", "conversion_test.go",
"droiddoc_exported_dir_conversion_test.go", "droiddoc_exported_dir_conversion_test.go",
"fdo_profile_conversion_test.go",
"filegroup_conversion_test.go", "filegroup_conversion_test.go",
"genrule_conversion_test.go", "genrule_conversion_test.go",
"gensrcs_conversion_test.go", "gensrcs_conversion_test.go",

View file

@ -3640,8 +3640,8 @@ cc_library {
{ {
description: "cc_library with afdo enabled and existing profile", description: "cc_library with afdo enabled and existing profile",
filesystem: map[string]string{ filesystem: map[string]string{
"vendor/google_data/pgo_profile/sampling/BUILD": "", "vendor/google_data/pgo_profile/sampling/Android.bp": "",
"vendor/google_data/pgo_profile/sampling/foo.afdo": "", "vendor/google_data/pgo_profile/sampling/foo.afdo": "",
}, },
expectedBazelTargets: []string{ expectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
@ -3653,8 +3653,8 @@ cc_library {
{ {
description: "cc_library with afdo enabled and existing profile in AOSP", description: "cc_library with afdo enabled and existing profile in AOSP",
filesystem: map[string]string{ filesystem: map[string]string{
"toolchain/pgo-profiles/sampling/BUILD": "", "toolchain/pgo-profiles/sampling/Android.bp": "",
"toolchain/pgo-profiles/sampling/foo.afdo": "", "toolchain/pgo-profiles/sampling/foo.afdo": "",
}, },
expectedBazelTargets: []string{ expectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
@ -3666,8 +3666,8 @@ cc_library {
{ {
description: "cc_library with afdo enabled but profile filename doesn't match with module name", description: "cc_library with afdo enabled but profile filename doesn't match with module name",
filesystem: map[string]string{ filesystem: map[string]string{
"toolchain/pgo-profiles/sampling/BUILD": "", "toolchain/pgo-profiles/sampling/Android.bp": "",
"toolchain/pgo-profiles/sampling/bar.afdo": "", "toolchain/pgo-profiles/sampling/bar.afdo": "",
}, },
expectedBazelTargets: []string{ expectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),

View 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 bp2build
import (
"testing"
"android/soong/android"
"android/soong/cc"
)
func runFdoProfileTestCase(t *testing.T, tc Bp2buildTestCase) {
t.Helper()
(&tc).ModuleTypeUnderTest = "fdo_profile"
(&tc).ModuleTypeUnderTestFactory = cc.FdoProfileFactory
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
}
func TestFdoProfile(t *testing.T) {
testcases := []struct {
name string
bp string
expectedBazelAttrs AttrNameToString
}{
{
name: "fdo_profile with arch-specific profiles",
bp: `
fdo_profile {
name: "foo",
arch: {
arm: {
profile: "foo_arm.afdo",
},
arm64: {
profile: "foo_arm64.afdo",
}
}
}`,
expectedBazelAttrs: AttrNameToString{
"profile": `select({
"//build/bazel/platforms/arch:arm": "foo_arm.afdo",
"//build/bazel/platforms/arch:arm64": "foo_arm64.afdo",
"//conditions:default": None,
})`,
},
},
{
name: "fdo_profile with arch-agnostic profile",
bp: `
fdo_profile {
name: "foo",
profile: "foo.afdo",
}`,
expectedBazelAttrs: AttrNameToString{
"profile": `"foo.afdo"`,
},
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
expectedBazelTargets := []string{
// TODO(b/276287371): Add device-only restriction back to fdo_profile targets
MakeBazelTargetNoRestrictions("fdo_profile", "foo", test.expectedBazelAttrs),
}
runFdoProfileTestCase(t, Bp2buildTestCase{
Description: test.name,
Blueprint: test.bp,
ExpectedBazelTargets: expectedBazelTargets,
})
})
}
}

View file

@ -1000,6 +1000,8 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
if module.afdo != nil && module.afdo.Properties.Afdo { if module.afdo != nil && module.afdo.Properties.Afdo {
fdoProfileDep := bp2buildFdoProfile(ctx, module) fdoProfileDep := bp2buildFdoProfile(ctx, module)
if fdoProfileDep != nil { if fdoProfileDep != nil {
// TODO(b/276287371): Only set fdo_profile for android platform
// https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/afdo.go;l=105;drc=2dbe160d1af445de32725098570ec594e3944fc5
(&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep) (&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep)
} }
} }
@ -1109,22 +1111,15 @@ func bp2buildFdoProfile(
ctx android.Bp2buildMutatorContext, ctx android.Bp2buildMutatorContext,
m *Module, m *Module,
) *bazel.Label { ) *bazel.Label {
// TODO(b/267229066): Convert to afdo boolean attribute and let Bazel handles finding
// fdo_profile target from AfdoProfiles product var
for _, project := range globalAfdoProfileProjects { for _, project := range globalAfdoProfileProjects {
// Ensure handcrafted BUILD file exists in the project // Ensure it's a Soong package
BUILDPath := android.ExistentPathForSource(ctx, project, "BUILD") bpPath := android.ExistentPathForSource(ctx, project, "Android.bp")
if BUILDPath.Valid() { if bpPath.Valid() {
// We handcraft a BUILD file with fdo_profile targets that use the existing profiles in the project
// This implementation is assuming that every afdo profile in globalAfdoProfileProjects already has
// an associated fdo_profile target declared in the same package.
// TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`) // TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`)
path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo") path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo")
if path.Valid() { if path.Valid() {
// FIXME: Some profiles only exist internally and are not released to AOSP.
// When generated BUILD files are checked in, we'll run into merge conflict.
// The cc_library_shared target in AOSP won't have reference to an fdo_profile target because
// the profile doesn't exist. Internally, the same cc_library_shared target will
// have reference to the fdo_profile.
// For more context, see b/258682955#comment2
fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name() fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name()
return &bazel.Label{ return &bazel.Label{
Label: fdoProfileLabel, Label: fdoProfileLabel,

View file

@ -16,8 +16,10 @@ package cc
import ( import (
"android/soong/android" "android/soong/android"
"android/soong/bazel"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
) )
func init() { func init() {
@ -25,11 +27,12 @@ func init() {
} }
func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) { func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("fdo_profile", fdoProfileFactory) ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
} }
type fdoProfile struct { type fdoProfile struct {
android.ModuleBase android.ModuleBase
android.BazelModuleBase
properties fdoProfileProperties properties fdoProfileProperties
} }
@ -38,6 +41,49 @@ type fdoProfileProperties struct {
Profile *string `android:"arch_variant"` Profile *string `android:"arch_variant"`
} }
type bazelFdoProfileAttributes struct {
Profile bazel.StringAttribute
}
func (fp *fdoProfile) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
var profileAttr bazel.StringAttribute
archVariantProps := fp.GetArchVariantProperties(ctx, &fdoProfileProperties{})
for axis, configToProps := range archVariantProps {
for config, _props := range configToProps {
if archProps, ok := _props.(*fdoProfileProperties); ok {
if axis.String() == "arch" || axis.String() == "no_config" {
if archProps.Profile != nil {
profileAttr.SetSelectValue(axis, config, archProps.Profile)
}
}
}
}
}
// Ideally, cc_library_shared's fdo_profile attr can be a select statement so that we
// don't lift the restriction here. However, in cc_library_shared macro, fdo_profile
// is used as a string, we need to temporarily lift the host restriction until we can
// pass use fdo_profile attr with select statement
// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/cc_library_shared.bzl;l=127;drc=cc01bdfd39857eddbab04ef69ab6db22dcb1858a
// TODO(b/276287371): Drop the restriction override after fdo_profile path is handled properly
var noRestriction bazel.BoolAttribute
noRestriction.SetSelectValue(bazel.NoConfigAxis, "", proptools.BoolPtr(true))
ctx.CreateBazelTargetModuleWithRestrictions(
bazel.BazelTargetModuleProperties{
Rule_class: "fdo_profile",
},
android.CommonAttributes{
Name: fp.Name(),
},
&bazelFdoProfileAttributes{
Profile: profileAttr,
},
noRestriction,
)
}
// FdoProfileInfo is provided by FdoProfileProvider // FdoProfileInfo is provided by FdoProfileProvider
type FdoProfileInfo struct { type FdoProfileInfo struct {
Path android.Path Path android.Path
@ -77,9 +123,10 @@ func fdoProfileMutator(ctx android.BottomUpMutatorContext) {
} }
} }
func fdoProfileFactory() android.Module { func FdoProfileFactory() android.Module {
m := &fdoProfile{} m := &fdoProfile{}
m.AddProperties(&m.properties) m.AddProperties(&m.properties)
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth) android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
android.InitBazelModule(m)
return m return m
} }

View file

@ -671,7 +671,7 @@ var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
// PrepareForTestWithFdoProfile registers module types to test with fdo_profile // PrepareForTestWithFdoProfile registers module types to test with fdo_profile
var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory) ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
ctx.RegisterModuleType("fdo_profile", fdoProfileFactory) 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.