diff options
Diffstat (limited to 'cc')
| -rw-r--r-- | cc/cc.go | 24 | ||||
| -rw-r--r-- | cc/cc_test.go | 41 | ||||
| -rw-r--r-- | cc/config/arm_device.go | 9 | ||||
| -rw-r--r-- | cc/coverage.go | 93 | ||||
| -rw-r--r-- | cc/lto.go | 145 | ||||
| -rw-r--r-- | cc/lto_test.go | 5 | ||||
| -rw-r--r-- | cc/object_test.go | 12 | ||||
| -rw-r--r-- | cc/orderfile.go | 103 |
8 files changed, 266 insertions, 166 deletions
@@ -68,16 +68,14 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("fuzz_deps", fuzzMutatorDeps) - ctx.BottomUp("coverage", coverageMutator).Parallel() + ctx.Transition("coverage", &coverageTransitionMutator{}) ctx.TopDown("afdo_deps", afdoDepsMutator) ctx.BottomUp("afdo", afdoMutator).Parallel() - ctx.TopDown("orderfile_deps", orderfileDepsMutator) - ctx.BottomUp("orderfile", orderfileMutator).Parallel() + ctx.Transition("orderfile", &orderfileTransitionMutator{}) - ctx.TopDown("lto_deps", ltoDepsMutator) - ctx.BottomUp("lto", ltoMutator).Parallel() + ctx.Transition("lto", <oTransitionMutator{}) ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel() ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel() @@ -1608,9 +1606,10 @@ func (ctx *moduleContextImpl) useSdk() bool { func (ctx *moduleContextImpl) sdkVersion() string { if ctx.ctx.Device() { - if ctx.useVndk() { + config := ctx.ctx.Config() + if !config.IsVndkDeprecated() && ctx.useVndk() { vndkVer := ctx.mod.VndkVersion() - if inList(vndkVer, ctx.ctx.Config().PlatformVersionActiveCodenames()) { + if inList(vndkVer, config.PlatformVersionActiveCodenames()) { return "current" } return vndkVer @@ -1628,6 +1627,17 @@ func (ctx *moduleContextImpl) minSdkVersion() string { if ver == "apex_inherit" || ver == "" { ver = ctx.sdkVersion() } + + if ctx.ctx.Device() { + config := ctx.ctx.Config() + if config.IsVndkDeprecated() && ctx.inVendor() { + // If building for vendor with final API, then use the latest _stable_ API as "current". + if config.VendorApiLevelFrozen() && (ver == "" || ver == "current") { + ver = config.PlatformSdkVersion().String() + } + } + } + // For crt objects, the meaning of min_sdk_version is very different from other types of // module. For them, min_sdk_version defines the oldest version that the build system will // create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of diff --git a/cc/cc_test.go b/cc/cc_test.go index 321bd380b..6cc500b5f 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -43,6 +43,7 @@ var prepareForCcTest = android.GroupFixturePreparers( android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.VendorApiLevel = StringPtr("202404") variables.DeviceVndkVersion = StringPtr("current") + variables.KeepVndk = BoolPtr(true) variables.Platform_vndk_version = StringPtr("29") }), ) @@ -4843,3 +4844,43 @@ func TestImageVariantsWithoutVndk(t *testing.T) { testDepWithVariant("vendor") testDepWithVariant("product") } + +func TestVendorSdkVersionWithoutVndk(t *testing.T) { + t.Parallel() + + bp := ` + cc_library { + name: "libfoo", + srcs: ["libfoo.cc"], + vendor_available: true, + } + + cc_library { + name: "libbar", + srcs: ["libbar.cc"], + vendor_available: true, + min_sdk_version: "29", + } + ` + + ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp) + testSdkVersionFlag := func(module, version string) { + flags := ctx.ModuleForTests(module, "android_vendor_arm64_armv8-a_static").Rule("cc").Args["cFlags"] + android.AssertStringDoesContain(t, "min sdk version", flags, "-target aarch64-linux-android"+version) + } + + testSdkVersionFlag("libfoo", "10000") + testSdkVersionFlag("libbar", "29") + + ctx = android.GroupFixturePreparers( + prepareForCcTestWithoutVndk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + if variables.BuildFlags == nil { + variables.BuildFlags = make(map[string]string) + } + variables.BuildFlags["RELEASE_BOARD_API_LEVEL_FROZEN"] = "true" + }), + ).RunTestWithBp(t, bp) + testSdkVersionFlag("libfoo", "30") + testSdkVersionFlag("libbar", "29") +} diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go index 3d6890cf0..603bc6de7 100644 --- a/cc/config/arm_device.go +++ b/cc/config/arm_device.go @@ -28,13 +28,20 @@ var ( armCflags = []string{ "-fomit-frame-pointer", + // Revert this after b/322359235 is fixed + "-mllvm", "-enable-shrink-wrap=false", } - armCppflags = []string{} + armCppflags = []string{ + // Revert this after b/322359235 is fixed + "-mllvm", "-enable-shrink-wrap=false", + } armLdflags = []string{ "-Wl,--hash-style=gnu", "-Wl,-m,armelf", + // Revert this after b/322359235 is fixed + "-Wl,-mllvm", "-Wl,-enable-shrink-wrap=false", } armLldflags = armLdflags diff --git a/cc/coverage.go b/cc/coverage.go index 393a8a6b4..43f5e0762 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -246,7 +246,7 @@ func SetCoverageProperties(ctx android.BaseModuleContext, properties CoveragePro type UseCoverage interface { android.Module - IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool + IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool } // Coverage is an interface for non-CC modules to implement to be mutated for coverage @@ -258,43 +258,86 @@ type Coverage interface { EnableCoverageIfNeeded() } -func coverageMutator(mctx android.BottomUpMutatorContext) { - if c, ok := mctx.Module().(*Module); ok && c.coverage != nil { - needCoverageVariant := c.coverage.Properties.NeedCoverageVariant - needCoverageBuild := c.coverage.Properties.NeedCoverageBuild - if needCoverageVariant { - m := mctx.CreateVariations("", "cov") +type coverageTransitionMutator struct{} + +var _ android.TransitionMutator = (*coverageTransitionMutator)(nil) +func (c coverageTransitionMutator) Split(ctx android.BaseModuleContext) []string { + if c, ok := ctx.Module().(*Module); ok && c.coverage != nil { + if c.coverage.Properties.NeedCoverageVariant { + return []string{"", "cov"} + } + } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) { + // APEX and Rust modules fall here + + // Note: variant "" is also created because an APEX can be depended on by another + // module which are split into "" and "cov" variants. e.g. when cc_test refers + // to an APEX via 'data' property. + return []string{"", "cov"} + } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) { + // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of + // deps. + return []string{"cov"} + } + + return []string{""} +} + +func (c coverageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + return sourceVariation +} + +func (c coverageTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if c, ok := ctx.Module().(*Module); ok && c.coverage != nil { + if !c.coverage.Properties.NeedCoverageVariant { + return "" + } + } else if cov, ok := ctx.Module().(Coverage); ok { + if !cov.IsNativeCoverageNeeded(ctx) { + return "" + } + } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) { + // Module only has a "cov" variation, so all incoming variations should use "cov". + return "cov" + } else { + return "" + } + + return incomingVariation +} + +func (c coverageTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if c, ok := ctx.Module().(*Module); ok && c.coverage != nil { + if variation == "" && c.coverage.Properties.NeedCoverageVariant { // Setup the non-coverage version and set HideFromMake and // PreventInstall to true. - m[0].(*Module).coverage.Properties.CoverageEnabled = false - m[0].(*Module).coverage.Properties.IsCoverageVariant = false - m[0].(*Module).Properties.HideFromMake = true - m[0].(*Module).Properties.PreventInstall = true - + c.coverage.Properties.CoverageEnabled = false + c.coverage.Properties.IsCoverageVariant = false + c.Properties.HideFromMake = true + c.Properties.PreventInstall = true + } else if variation == "cov" { // The coverage-enabled version inherits HideFromMake, // PreventInstall from the original module. - m[1].(*Module).coverage.Properties.CoverageEnabled = needCoverageBuild - m[1].(*Module).coverage.Properties.IsCoverageVariant = true + c.coverage.Properties.CoverageEnabled = c.coverage.Properties.NeedCoverageBuild + c.coverage.Properties.IsCoverageVariant = true } - } else if cov, ok := mctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(mctx) { + } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) { // APEX and Rust modules fall here // Note: variant "" is also created because an APEX can be depended on by another // module which are split into "" and "cov" variants. e.g. when cc_test refers // to an APEX via 'data' property. - m := mctx.CreateVariations("", "cov") - m[0].(Coverage).MarkAsCoverageVariant(false) - m[0].(Coverage).SetPreventInstall() - m[0].(Coverage).HideFromMake() - - m[1].(Coverage).MarkAsCoverageVariant(true) - m[1].(Coverage).EnableCoverageIfNeeded() - } else if cov, ok := mctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(mctx) { + if variation == "" { + cov.MarkAsCoverageVariant(false) + cov.SetPreventInstall() + cov.HideFromMake() + } else if variation == "cov" { + cov.MarkAsCoverageVariant(true) + cov.EnableCoverageIfNeeded() + } + } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) { // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of // deps. - mctx.CreateVariations("cov") - mctx.AliasVariation("cov") } } @@ -15,9 +15,12 @@ package cc import ( - "android/soong/android" + "fmt" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" + + "android/soong/android" ) // LTO (link-time optimization) allows the compiler to optimize and generate @@ -49,11 +52,6 @@ type LTOProperties struct { LtoEnabled bool `blueprint:"mutated"` LtoDefault bool `blueprint:"mutated"` - // Dep properties indicate that this module needs to be built with LTO - // since it is an object dependency of an LTO module. - LtoDep bool `blueprint:"mutated"` - NoLtoDep bool `blueprint:"mutated"` - // Use -fwhole-program-vtables cflag. Whole_program_vtables *bool } @@ -176,86 +174,83 @@ func (lto *lto) Never() bool { return lto != nil && proptools.Bool(lto.Properties.Lto.Never) } -// Propagate lto requirements down from binaries -func ltoDepsMutator(mctx android.TopDownMutatorContext) { - if m, ok := mctx.Module().(*Module); ok { - if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault { - return - } - - mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { - tag := mctx.OtherModuleDependencyTag(dep) - libTag, isLibTag := tag.(libraryDependencyTag) +func ltoPropagateViaDepTag(tag blueprint.DependencyTag) bool { + libTag, isLibTag := tag.(libraryDependencyTag) + // Do not recurse down non-static dependencies + if isLibTag { + return libTag.static() + } else { + return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag + } +} - // Do not recurse down non-static dependencies - if isLibTag { - if !libTag.static() { - return false - } - } else { - if tag != objDepTag && tag != reuseObjTag { - return false - } - } +// ltoTransitionMutator creates LTO variants of cc modules. Variant "" is the default variant, which may +// or may not have LTO enabled depending on the config and the module's type and properties. "lto-thin" or +// "lto-none" variants are created when a module needs to compile in the non-default state for that module. +type ltoTransitionMutator struct{} - if dep, ok := dep.(*Module); ok { - if m.lto.Properties.LtoEnabled { - dep.lto.Properties.LtoDep = true - } else { - dep.lto.Properties.NoLtoDep = true - } - } +const LTO_NONE_VARIATION = "lto-none" +const LTO_THIN_VARIATION = "lto-thin" - // Recursively walk static dependencies - return true - }) - } +func (l *ltoTransitionMutator) Split(ctx android.BaseModuleContext) []string { + return []string{""} } -// Create lto variants for modules that need them -func ltoMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && m.lto != nil { - // Create variations for LTO types required as static - // dependencies - variationNames := []string{""} - if m.lto.Properties.LtoDep { - variationNames = append(variationNames, "lto-thin") - } - if m.lto.Properties.NoLtoDep { - variationNames = append(variationNames, "lto-none") +func (l *ltoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + if m, ok := ctx.Module().(*Module); ok && m.lto != nil { + if !ltoPropagateViaDepTag(ctx.DepTag()) { + return "" } - if !m.lto.Properties.LtoEnabled { - mctx.SetDependencyVariation("lto-none") + if sourceVariation != "" { + return sourceVariation } + + // Always request an explicit variation, IncomingTransition will rewrite it back to the default variation + // if necessary. if m.lto.Properties.LtoEnabled { - mctx.SetDependencyVariation("lto-thin") + return LTO_THIN_VARIATION + } else { + return LTO_NONE_VARIATION } + } + return "" +} - if len(variationNames) > 1 { - modules := mctx.CreateVariations(variationNames...) - for i, name := range variationNames { - variation := modules[i].(*Module) - // Default module which will be - // installed. Variation set above according to - // explicit LTO properties - if name == "" { - continue - } - - // LTO properties for dependencies - if name == "lto-thin" { - variation.lto.Properties.LtoEnabled = true - } - if name == "lto-none" { - variation.lto.Properties.LtoEnabled = false - } - variation.Properties.PreventInstall = true - variation.Properties.HideFromMake = true - variation.lto.Properties.LtoDefault = m.lto.Properties.LtoDefault - variation.lto.Properties.LtoDep = false - variation.lto.Properties.NoLtoDep = false - } +func (l *ltoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if m, ok := ctx.Module().(*Module); ok && m.lto != nil { + if m.lto.Never() { + return "" + } + // Rewrite explicit variations back to the default variation if the default variation matches. + if incomingVariation == LTO_THIN_VARIATION && m.lto.Properties.LtoDefault { + return "" + } else if incomingVariation == LTO_NONE_VARIATION && !m.lto.Properties.LtoDefault { + return "" + } + return incomingVariation + } + return "" +} + +func (l *ltoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + // Default module which will be installed. Variation set above according to explicit LTO properties. + if variation == "" { + return + } + + if m, ok := ctx.Module().(*Module); ok && m.lto != nil { + // Non-default variation, set the LTO properties to match the variation. + switch variation { + case LTO_THIN_VARIATION: + m.lto.Properties.LtoEnabled = true + case LTO_NONE_VARIATION: + m.lto.Properties.LtoEnabled = false + default: + panic(fmt.Errorf("unknown variation %s", variation)) } + // Non-default variations are never installed. + m.Properties.PreventInstall = true + m.Properties.HideFromMake = true } } diff --git a/cc/lto_test.go b/cc/lto_test.go index 7b7fe8c8a..e4b5a3a01 100644 --- a/cc/lto_test.go +++ b/cc/lto_test.go @@ -146,8 +146,9 @@ func TestThinLtoOnlyOnStaticDep(t *testing.T) { t.Errorf("'root' missing dependency on the default variant of 'foo'") } - if !hasDep(result, libRootLtoNever, libFoo.Module()) { - t.Errorf("'root_no_lto' missing dependency on the default variant of 'foo'") + libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none") + if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) { + t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'") } libFooCFlags := libFoo.Rule("cc").Args["cFlags"] diff --git a/cc/object_test.go b/cc/object_test.go index e6a3fdd45..c0d133190 100644 --- a/cc/object_test.go +++ b/cc/object_test.go @@ -22,7 +22,7 @@ import ( ) func TestMinSdkVersionsOfCrtObjects(t *testing.T) { - ctx := testCc(t, ` + bp := ` cc_object { name: "crt_foo", srcs: ["foo.c"], @@ -30,8 +30,8 @@ func TestMinSdkVersionsOfCrtObjects(t *testing.T) { stl: "none", min_sdk_version: "28", vendor_available: true, - }`) - + } + ` variants := []struct { variant string num string @@ -43,11 +43,17 @@ func TestMinSdkVersionsOfCrtObjects(t *testing.T) { {"android_arm64_armv8-a_sdk_current", "10000"}, {"android_vendor.29_arm64_armv8-a", "29"}, } + + ctx := prepareForCcTest.RunTestWithBp(t, bp) for _, v := range variants { cflags := ctx.ModuleForTests("crt_foo", v.variant).Rule("cc").Args["cFlags"] expected := "-target aarch64-linux-android" + v.num + " " android.AssertStringDoesContain(t, "cflag", cflags, expected) } + ctx = prepareForCcTestWithoutVndk.RunTestWithBp(t, bp) + android.AssertStringDoesContain(t, "cflag", + ctx.ModuleForTests("crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"], + "-target aarch64-linux-android10000 ") } func TestUseCrtObjectOfCorrectVersion(t *testing.T) { diff --git a/cc/orderfile.go b/cc/orderfile.go index 9192e8168..38b89059b 100644 --- a/cc/orderfile.go +++ b/cc/orderfile.go @@ -20,6 +20,8 @@ package cc import ( "fmt" + "github.com/google/blueprint" + "android/soong/android" ) @@ -190,66 +192,61 @@ func (orderfile *orderfile) flags(ctx ModuleContext, flags Flags) 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 - }) +func orderfilePropagateViaDepTag(tag blueprint.DependencyTag) bool { + libTag, isLibTag := tag.(libraryDependencyTag) + // Do not recurse down non-static dependencies + if isLibTag { + return libTag.static() + } else { + return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag } } -// 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 +// orderfileTransitionMutator creates orderfile variants of cc modules. +type orderfileTransitionMutator struct{} + +const ORDERFILE_VARIATION = "orderfile" + +func (o *orderfileTransitionMutator) Split(ctx android.BaseModuleContext) []string { + return []string{""} +} + +func (o *orderfileTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { + if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { + if !orderfilePropagateViaDepTag(ctx.DepTag()) { + return "" } - variationNames := []string{""} - if m.orderfile.Properties.OrderfileInstrLink { - variationNames = append(variationNames, "orderfile") + if sourceVariation != "" { + return sourceVariation } - 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 - } + // Propagate profile orderfile flags down from binaries and shared libraries + if m.orderfile.orderfileLinkEnabled() { + return ORDERFILE_VARIATION } } + return "" +} + +func (o *orderfileTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { + return incomingVariation + } + return "" +} + +func (o *orderfileTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if variation == "" { + return + } + + if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil { + m.Properties.PreventInstall = true + m.Properties.HideFromMake = true + m.orderfile.Properties.ShouldProfileModule = true + // We do not allow propagation for load flags because the orderfile is specific + // to the module (binary / shared library) + m.orderfile.Properties.OrderfileLoad = false + } } |