Merge "Created an Orderfile go file for the build system. In addition, I added a test file to check if flags are added and propagated correctly." into main
This commit is contained in:
@@ -37,6 +37,7 @@ bootstrap_go_package {
|
||||
"linkable.go",
|
||||
"lto.go",
|
||||
"makevars.go",
|
||||
"orderfile.go",
|
||||
"pgo.go",
|
||||
"prebuilt.go",
|
||||
"proto.go",
|
||||
@@ -104,6 +105,7 @@ bootstrap_go_package {
|
||||
"lto_test.go",
|
||||
"ndk_test.go",
|
||||
"object_test.go",
|
||||
"orderfile_test.go",
|
||||
"prebuilt_test.go",
|
||||
"proto_test.go",
|
||||
"sanitize_test.go",
|
||||
|
27
cc/cc.go
27
cc/cc.go
@@ -74,6 +74,9 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
|
||||
ctx.TopDown("afdo_deps", afdoDepsMutator)
|
||||
ctx.BottomUp("afdo", afdoMutator).Parallel()
|
||||
|
||||
ctx.TopDown("orderfile_deps", orderfileDepsMutator)
|
||||
ctx.BottomUp("orderfile", orderfileMutator).Parallel()
|
||||
|
||||
ctx.TopDown("lto_deps", ltoDepsMutator)
|
||||
ctx.BottomUp("lto", ltoMutator).Parallel()
|
||||
|
||||
@@ -526,6 +529,7 @@ type ModuleContextIntf interface {
|
||||
getVndkExtendsModuleName() string
|
||||
isAfdoCompile() bool
|
||||
isPgoCompile() bool
|
||||
isOrderfileCompile() bool
|
||||
isCfi() bool
|
||||
isFuzzer() bool
|
||||
isNDKStubLibrary() bool
|
||||
@@ -885,6 +889,7 @@ type Module struct {
|
||||
lto *lto
|
||||
afdo *afdo
|
||||
pgo *pgo
|
||||
orderfile *orderfile
|
||||
|
||||
library libraryInterface
|
||||
|
||||
@@ -1259,6 +1264,9 @@ func (c *Module) Init() android.Module {
|
||||
if c.pgo != nil {
|
||||
c.AddProperties(c.pgo.props()...)
|
||||
}
|
||||
if c.orderfile != nil {
|
||||
c.AddProperties(c.orderfile.props()...)
|
||||
}
|
||||
for _, feature := range c.features {
|
||||
c.AddProperties(feature.props()...)
|
||||
}
|
||||
@@ -1392,6 +1400,13 @@ func (c *Module) isPgoCompile() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) isOrderfileCompile() bool {
|
||||
if orderfile := c.orderfile; orderfile != nil {
|
||||
return orderfile.Properties.OrderfileLoad
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) isCfi() bool {
|
||||
if sanitize := c.sanitize; sanitize != nil {
|
||||
return Bool(sanitize.Properties.SanitizeMutated.Cfi)
|
||||
@@ -1697,6 +1712,10 @@ func (ctx *moduleContextImpl) isPgoCompile() bool {
|
||||
return ctx.mod.isPgoCompile()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isOrderfileCompile() bool {
|
||||
return ctx.mod.isOrderfileCompile()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isCfi() bool {
|
||||
return ctx.mod.isCfi()
|
||||
}
|
||||
@@ -1806,6 +1825,7 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo
|
||||
module.lto = <o{}
|
||||
module.afdo = &afdo{}
|
||||
module.pgo = &pgo{}
|
||||
module.orderfile = &orderfile{}
|
||||
return module
|
||||
}
|
||||
|
||||
@@ -2234,6 +2254,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
if c.pgo != nil {
|
||||
flags = c.pgo.flags(ctx, flags)
|
||||
}
|
||||
if c.orderfile != nil {
|
||||
flags = c.orderfile.flags(ctx, flags)
|
||||
}
|
||||
for _, feature := range c.features {
|
||||
flags = feature.flags(ctx, flags)
|
||||
}
|
||||
@@ -2376,6 +2399,9 @@ func (c *Module) begin(ctx BaseModuleContext) {
|
||||
if c.lto != nil {
|
||||
c.lto.begin(ctx)
|
||||
}
|
||||
if c.orderfile != nil {
|
||||
c.orderfile.begin(ctx)
|
||||
}
|
||||
if c.pgo != nil {
|
||||
c.pgo.begin(ctx)
|
||||
}
|
||||
@@ -4284,6 +4310,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
|
||||
<OProperties{},
|
||||
&AfdoProperties{},
|
||||
&PgoProperties{},
|
||||
&OrderfileProperties{},
|
||||
&android.ProtoProperties{},
|
||||
// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
|
||||
&RustBindgenClangProperties{},
|
||||
|
257
cc/orderfile.go
Normal file
257
cc/orderfile.go
Normal file
@@ -0,0 +1,257 @@
|
||||
// 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.
|
||||
//
|
||||
// Note: If you want to know how to use orderfile for your binary or shared
|
||||
// library, you can go look at the README in toolchains/pgo-profiles/orderfiles
|
||||
|
||||
package cc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
// Order files are text files containing symbols representing functions names.
|
||||
// Linkers (lld) uses order files to layout functions in a specific order.
|
||||
// These binaries with ordered symbols will reduce page faults and improve a program's launch time
|
||||
// due to the efficient loading of symbols during a program’s cold-start.
|
||||
var (
|
||||
// Add flags to ignore warnings about symbols not be found
|
||||
// or not allowed to be ordered
|
||||
orderfileOtherFlags = []string{
|
||||
"-Wl,--no-warn-symbol-ordering",
|
||||
}
|
||||
|
||||
// Add folder projects for orderfiles
|
||||
globalOrderfileProjects = []string{
|
||||
"toolchain/pgo-profiles/orderfiles",
|
||||
"vendor/google_data/pgo_profile/orderfiles",
|
||||
}
|
||||
)
|
||||
|
||||
var orderfileProjectsConfigKey = android.NewOnceKey("OrderfileProjects")
|
||||
|
||||
const orderfileProfileFlag = "-forder-file-instrumentation"
|
||||
const orderfileUseFormat = "-Wl,--symbol-ordering-file=%s"
|
||||
|
||||
func getOrderfileProjects(config android.DeviceConfig) []string {
|
||||
return config.OnceStringSlice(orderfileProjectsConfigKey, func() []string {
|
||||
return globalOrderfileProjects
|
||||
})
|
||||
}
|
||||
|
||||
func recordMissingOrderfile(ctx BaseModuleContext, missing string) {
|
||||
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
|
||||
}
|
||||
|
||||
type OrderfileProperties struct {
|
||||
Orderfile struct {
|
||||
Instrumentation *bool
|
||||
Order_file_path *string `android:"arch_variant"`
|
||||
Load_order_file *bool `android:"arch_variant"`
|
||||
// Additional compiler flags to use when building this module
|
||||
// for orderfile profiling.
|
||||
Cflags []string `android:"arch_variant"`
|
||||
} `android:"arch_variant"`
|
||||
|
||||
ShouldProfileModule bool `blueprint:"mutated"`
|
||||
OrderfileLoad bool `blueprint:"mutated"`
|
||||
OrderfileInstrLink bool `blueprint:"mutated"`
|
||||
}
|
||||
|
||||
type orderfile struct {
|
||||
Properties OrderfileProperties
|
||||
}
|
||||
|
||||
func (props *OrderfileProperties) shouldInstrument() bool {
|
||||
return Bool(props.Orderfile.Instrumentation)
|
||||
}
|
||||
|
||||
// ShouldLoadOrderfile returns true if we need to load the order file rather than
|
||||
// profile the binary or shared library
|
||||
func (props *OrderfileProperties) shouldLoadOrderfile() bool {
|
||||
return Bool(props.Orderfile.Load_order_file) && props.Orderfile.Order_file_path != nil
|
||||
}
|
||||
|
||||
// orderfileEnabled returns true for binaries and shared libraries
|
||||
// if instrument flag is set to true
|
||||
func (orderfile *orderfile) orderfileEnabled() bool {
|
||||
return orderfile != nil && orderfile.Properties.shouldInstrument()
|
||||
}
|
||||
|
||||
// orderfileLinkEnabled returns true for binaries and shared libraries
|
||||
// if you should instrument dependencies
|
||||
func (orderfile *orderfile) orderfileLinkEnabled() bool {
|
||||
return orderfile != nil && orderfile.Properties.OrderfileInstrLink
|
||||
}
|
||||
|
||||
func (orderfile *orderfile) props() []interface{} {
|
||||
return []interface{}{&orderfile.Properties}
|
||||
}
|
||||
|
||||
// Get the path to the order file by checking it is valid and not empty
|
||||
func (props *OrderfileProperties) getOrderfile(ctx BaseModuleContext) android.OptionalPath {
|
||||
orderFile := *props.Orderfile.Order_file_path
|
||||
|
||||
// Test if the order file is present in any of the Orderfile projects
|
||||
for _, profileProject := range getOrderfileProjects(ctx.DeviceConfig()) {
|
||||
path := android.ExistentPathForSource(ctx, profileProject, orderFile)
|
||||
if path.Valid() {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
// Record that this module's order file is absent
|
||||
missing := *props.Orderfile.Order_file_path + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
|
||||
recordMissingOrderfile(ctx, missing)
|
||||
|
||||
return android.OptionalPath{}
|
||||
}
|
||||
|
||||
func (props *OrderfileProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
|
||||
flags.Local.CFlags = append(flags.Local.CFlags, props.Orderfile.Cflags...)
|
||||
flags.Local.CFlags = append(flags.Local.CFlags, orderfileProfileFlag)
|
||||
flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm -enable-order-file-instrumentation")
|
||||
flags.Local.LdFlags = append(flags.Local.LdFlags, orderfileProfileFlag)
|
||||
return flags
|
||||
}
|
||||
|
||||
|
||||
func (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string {
|
||||
flags := []string{fmt.Sprintf(orderfileUseFormat, file)}
|
||||
flags = append(flags, orderfileOtherFlags...)
|
||||
return flags
|
||||
}
|
||||
|
||||
func (props *OrderfileProperties) addLoadFlags(ctx ModuleContext, flags Flags) Flags {
|
||||
orderFile := props.getOrderfile(ctx)
|
||||
orderFilePath := orderFile.Path()
|
||||
loadFlags := props.loadOrderfileFlags(ctx, orderFilePath.String())
|
||||
|
||||
flags.Local.CFlags = append(flags.Local.CFlags, loadFlags...)
|
||||
flags.Local.LdFlags = append(flags.Local.LdFlags, loadFlags...)
|
||||
|
||||
// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
|
||||
// if orderfile gets updated
|
||||
flags.CFlagsDeps = append(flags.CFlagsDeps, orderFilePath)
|
||||
flags.LdFlagsDeps = append(flags.LdFlagsDeps, orderFilePath)
|
||||
return flags
|
||||
}
|
||||
|
||||
func (orderfile *orderfile) begin(ctx BaseModuleContext) {
|
||||
// Currently, we are not enabling orderfiles for host
|
||||
if ctx.Host() {
|
||||
return
|
||||
}
|
||||
|
||||
// Currently, we are not enabling orderfiles to begin from static libraries
|
||||
if ctx.static() && !ctx.staticBinary() {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.DeviceConfig().ClangCoverageEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
// Checking if orderfile is enabled for this module
|
||||
if !orderfile.orderfileEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
orderfile.Properties.OrderfileLoad = orderfile.Properties.shouldLoadOrderfile()
|
||||
orderfile.Properties.ShouldProfileModule = !orderfile.Properties.shouldLoadOrderfile()
|
||||
orderfile.Properties.OrderfileInstrLink = orderfile.orderfileEnabled() && !orderfile.Properties.shouldLoadOrderfile()
|
||||
}
|
||||
|
||||
func (orderfile *orderfile) flags(ctx ModuleContext, flags Flags) Flags {
|
||||
props := orderfile.Properties
|
||||
// Add flags to load the orderfile using the path in its Android.bp
|
||||
if orderfile.Properties.OrderfileLoad {
|
||||
flags = props.addLoadFlags(ctx, flags)
|
||||
return flags
|
||||
}
|
||||
|
||||
// Add flags to profile this module
|
||||
if props.ShouldProfileModule {
|
||||
flags = props.addInstrumentationProfileGatherFlags(ctx, flags)
|
||||
return flags
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
// Propagate profile orderfile flags down from binaries and shared libraries
|
||||
// We do not allow propagation for load flags because the orderfile is specific
|
||||
// to the module (binary / shared library)
|
||||
func orderfileDepsMutator(mctx android.TopDownMutatorContext) {
|
||||
if m, ok := mctx.Module().(*Module); ok {
|
||||
if !m.orderfile.orderfileLinkEnabled() {
|
||||
return
|
||||
}
|
||||
mctx.WalkDeps(func(dep android.
|
||||
Module, parent android.Module) bool {
|
||||
tag := mctx.OtherModuleDependencyTag(dep)
|
||||
libTag, isLibTag := tag.(libraryDependencyTag)
|
||||
|
||||
// Do not recurse down non-static dependencies
|
||||
if isLibTag {
|
||||
if !libTag.static() {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if tag != objDepTag && tag != reuseObjTag {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if dep, ok := dep.(*Module); ok {
|
||||
if m.orderfile.Properties.OrderfileInstrLink {
|
||||
dep.orderfile.Properties.OrderfileInstrLink = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Create orderfile variants for modules that need them
|
||||
func orderfileMutator(mctx android.BottomUpMutatorContext) {
|
||||
if m, ok := mctx.Module().(*Module); ok && m.orderfile != nil {
|
||||
if !m.static() && m.orderfile.orderfileEnabled() {
|
||||
mctx.SetDependencyVariation("orderfile")
|
||||
return
|
||||
}
|
||||
|
||||
variationNames := []string{""}
|
||||
if m.orderfile.Properties.OrderfileInstrLink {
|
||||
variationNames = append(variationNames, "orderfile")
|
||||
}
|
||||
|
||||
if len(variationNames) > 1 {
|
||||
modules := mctx.CreateVariations(variationNames...)
|
||||
for i, name := range variationNames {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
variation := modules[i].(*Module)
|
||||
variation.Properties.PreventInstall = true
|
||||
variation.Properties.HideFromMake = true
|
||||
variation.orderfile.Properties.ShouldProfileModule = true
|
||||
variation.orderfile.Properties.OrderfileLoad = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
493
cc/orderfile_test.go
Normal file
493
cc/orderfile_test.go
Normal file
@@ -0,0 +1,493 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
func TestOrderfileProfileSharedLibrary(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_shared {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: false,
|
||||
order_file_path: "",
|
||||
},
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-forder-file-instrumentation"
|
||||
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check ldFlags of orderfile-enabled module
|
||||
ldFlags := libTest.Rule("ld").Args["ldFlags"]
|
||||
if !strings.Contains(ldFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderfileLoadSharedLibrary(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_shared {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: true,
|
||||
order_file_path: "libTest.orderfile",
|
||||
},
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"),
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile"
|
||||
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check ldFlags of orderfile-enabled module
|
||||
ldFlags := libTest.Rule("ld").Args["ldFlags"]
|
||||
if !strings.Contains(ldFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderfileProfileBinary(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_binary {
|
||||
name: "test",
|
||||
srcs: ["test.c"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: false,
|
||||
order_file_path: "",
|
||||
},
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-forder-file-instrumentation"
|
||||
|
||||
test := result.ModuleForTests("test", "android_arm64_armv8-a")
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
cFlags := test.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check ldFlags of orderfile-enabled module
|
||||
ldFlags := test.Rule("ld").Args["ldFlags"]
|
||||
if !strings.Contains(ldFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderfileLoadBinary(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_binary {
|
||||
name: "test",
|
||||
srcs: ["test.c"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: true,
|
||||
order_file_path: "test.orderfile",
|
||||
},
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
|
||||
|
||||
test := result.ModuleForTests("test", "android_arm64_armv8-a")
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
cFlags := test.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'test' to load orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check ldFlags of orderfile-enabled module
|
||||
ldFlags := test.Rule("ld").Args["ldFlags"]
|
||||
if !strings.Contains(ldFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
|
||||
}
|
||||
}
|
||||
|
||||
// Profile flags should propagate through static libraries
|
||||
func TestOrderfileProfilePropagateStaticDeps(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_shared {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
static_libs: ["libFoo"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: false,
|
||||
order_file_path: "",
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libFoo",
|
||||
srcs: ["foo.c"],
|
||||
static_libs: ["libBar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libBar",
|
||||
srcs: ["bar.c"],
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-forder-file-instrumentation"
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check cFlags of orderfile variant static libraries
|
||||
libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
|
||||
libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
|
||||
|
||||
cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
cFlags = libBarOfVariant.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check dependency edge from orderfile-enabled module to orderfile variant static libraries
|
||||
if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) {
|
||||
t.Errorf("libTest missing dependency on orderfile variant of libFoo")
|
||||
}
|
||||
|
||||
if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) {
|
||||
t.Errorf("libTest missing dependency on orderfile variant of libBar")
|
||||
}
|
||||
|
||||
// Check cFlags of the non-orderfile variant static libraries
|
||||
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
|
||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
|
||||
|
||||
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries
|
||||
if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
||||
t.Errorf("libTest has dependency on non-orderfile variant of libFoo")
|
||||
}
|
||||
|
||||
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
||||
t.Errorf("libTest has dependency on non-orderfile variant of libBar")
|
||||
}
|
||||
}
|
||||
|
||||
// Load flags should never propagate
|
||||
func TestOrderfileLoadPropagateStaticDeps(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_shared {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
static_libs: ["libFoo"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: true,
|
||||
order_file_path: "test.orderfile",
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libFoo",
|
||||
srcs: ["foo.c"],
|
||||
static_libs: ["libBar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libBar",
|
||||
srcs: ["bar.c"],
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check cFlags of the non-orderfile variant static libraries
|
||||
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
|
||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
|
||||
|
||||
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libFoo' not load orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libBar' not load orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
|
||||
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
|
||||
}
|
||||
|
||||
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
|
||||
}
|
||||
|
||||
// Make sure no orderfile variants are created for static libraries because the flags were not propagated
|
||||
libFooVariants := result.ModuleVariantsForTests("libFoo")
|
||||
for _, v := range libFooVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
|
||||
libBarVariants := result.ModuleVariantsForTests("libBar")
|
||||
for _, v := range libBarVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Profile flags should not propagate through shared libraries
|
||||
func TestOrderfileProfilePropagateSharedDeps(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_shared {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
shared_libs: ["libFoo"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: false,
|
||||
order_file_path: "",
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libFoo",
|
||||
srcs: ["foo.c"],
|
||||
static_libs: ["libBar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libBar",
|
||||
srcs: ["bar.c"],
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-forder-file-instrumentation"
|
||||
|
||||
// Check cFlags of orderfile-enabled module
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
|
||||
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if !strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check cFlags of the static and shared libraries
|
||||
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
|
||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
|
||||
|
||||
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
|
||||
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
|
||||
}
|
||||
|
||||
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
|
||||
}
|
||||
|
||||
// Make sure no orderfile variants are created for libraries because the flags were not propagated
|
||||
libFooVariants := result.ModuleVariantsForTests("libFoo")
|
||||
for _, v := range libFooVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
|
||||
libBarVariants := result.ModuleVariantsForTests("libBar")
|
||||
for _, v := range libBarVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Profile flags should not work or be propagated if orderfile flags start at a static library
|
||||
func TestOrderfileProfileStaticLibrary(t *testing.T) {
|
||||
t.Parallel()
|
||||
bp := `
|
||||
cc_library_static {
|
||||
name: "libTest",
|
||||
srcs: ["test.c"],
|
||||
static_libs: ["libFoo"],
|
||||
orderfile : {
|
||||
instrumentation: true,
|
||||
load_order_file: false,
|
||||
order_file_path: "",
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libFoo",
|
||||
srcs: ["foo.c"],
|
||||
static_libs: ["libBar"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libBar",
|
||||
srcs: ["bar.c"],
|
||||
}
|
||||
`
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForCcTest,
|
||||
).RunTestWithBp(t, bp)
|
||||
|
||||
expectedCFlag := "-forder-file-instrumentation"
|
||||
|
||||
// Check cFlags of module
|
||||
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static")
|
||||
|
||||
cFlags := libTest.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check cFlags of the static libraries
|
||||
libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
|
||||
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
|
||||
|
||||
cFlags = libFoo.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
cFlags = libBar.Rule("cc").Args["cFlags"]
|
||||
if strings.Contains(cFlags, expectedCFlag) {
|
||||
t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
|
||||
}
|
||||
|
||||
// Check dependency edge from orderfile-enabled module to non-orderfile variant libraries
|
||||
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
|
||||
}
|
||||
|
||||
if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
|
||||
t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
|
||||
}
|
||||
|
||||
// Make sure no orderfile variants are created for static libraries because the flags were not propagated
|
||||
libFooVariants := result.ModuleVariantsForTests("libFoo")
|
||||
for _, v := range libFooVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
|
||||
libBarVariants := result.ModuleVariantsForTests("libBar")
|
||||
for _, v := range libBarVariants {
|
||||
if strings.Contains(v, "orderfile") {
|
||||
t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user