diff options
Diffstat (limited to 'cc')
-rw-r--r-- | cc/Android.bp | 1 | ||||
-rw-r--r-- | cc/cc.go | 4 | ||||
-rw-r--r-- | cc/compiler.go | 26 | ||||
-rw-r--r-- | cc/library.go | 20 | ||||
-rw-r--r-- | cc/sabi.go | 103 | ||||
-rw-r--r-- | cc/sabi_test.go | 66 | ||||
-rw-r--r-- | cc/sanitize.go | 2 |
7 files changed, 165 insertions, 57 deletions
diff --git a/cc/Android.bp b/cc/Android.bp index 3688c8a9a..88a793cd8 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -102,6 +102,7 @@ bootstrap_go_package { "orderfile_test.go", "prebuilt_test.go", "proto_test.go", + "sabi_test.go", "sanitize_test.go", "sdk_test.go", "test_data_test.go", @@ -76,9 +76,9 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries).Parallel() }) - ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.PostApexMutators(func(ctx android.RegisterMutatorsContext) { // sabi mutator needs to be run after apex mutator finishes. - ctx.TopDown("sabi_deps", sabiDepsMutator) + ctx.Transition("sabi", &sabiTransitionMutator{}) }) ctx.RegisterParallelSingletonType("kythe_extract_all", kytheExtractAllFactory) diff --git a/cc/compiler.go b/cc/compiler.go index a6f623f5b..022b712e9 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -228,9 +228,6 @@ type BaseCompilerProperties struct { Static *bool `android:"arch_variant"` } `android:"arch_variant"` - // Stores the original list of source files before being cleared by library reuse - OriginalSrcs proptools.Configurable[[]string] `blueprint:"mutated"` - // Build and link with OpenMP Openmp *bool `android:"arch_variant"` } @@ -363,10 +360,20 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps tc := ctx.toolchain() modulePath := ctx.ModuleDir() - srcs := compiler.Properties.Srcs.GetOrDefault(ctx, nil) - exclude_srcs := compiler.Properties.Exclude_srcs.GetOrDefault(ctx, nil) - compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs) - compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...) + reuseObjs := false + if len(ctx.GetDirectDepsWithTag(reuseObjTag)) > 0 { + reuseObjs = true + } + + // If a reuseObjTag dependency exists then this module is reusing the objects (generally the shared variant + // reusing objects from the static variant), and doesn't need to compile any sources of its own. + var srcs []string + if !reuseObjs { + srcs = compiler.Properties.Srcs.GetOrDefault(ctx, nil) + exclude_srcs := compiler.Properties.Exclude_srcs.GetOrDefault(ctx, nil) + compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs) + compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...) + } cflags := compiler.Properties.Cflags.GetOrDefault(ctx, nil) cppflags := compiler.Properties.Cppflags.GetOrDefault(ctx, nil) @@ -721,11 +728,6 @@ func (compiler *baseCompiler) hasSrcExt(ctx BaseModuleContext, ext string) bool return true } } - for _, src := range compiler.Properties.OriginalSrcs.GetOrDefault(ctx, nil) { - if filepath.Ext(src) == ext { - return true - } - } return false } diff --git a/cc/library.go b/cc/library.go index 3833b9846..988a7fa0b 100644 --- a/cc/library.go +++ b/cc/library.go @@ -548,8 +548,7 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags, d return flags } -func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties { - m := ctx.Module().(*Module) +func (library *libraryDecorator) getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties { variantProps := &library.Properties.Target.Platform.Header_abi_checker if m.InVendor() { variantProps = &library.Properties.Target.Vendor.Header_abi_checker @@ -559,7 +558,7 @@ func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseM props := library.Properties.Header_abi_checker err := proptools.AppendProperties(&props, variantProps, nil) if err != nil { - ctx.ModuleErrorf("Cannot merge headerAbiCheckerProperties: %s", err.Error()) + panic(fmt.Errorf("Cannot merge headerAbiCheckerProperties: %s", err.Error())) } return props } @@ -718,7 +717,7 @@ type libraryInterface interface { setShared() // Gets the ABI properties for vendor, product, or platform variant - getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties + getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties // Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) @@ -1365,7 +1364,7 @@ func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext, sourceVersion, errorMessage string) { extraFlags := []string{"-target-version", sourceVersion} - headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx) + headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)) if Bool(headerAbiChecker.Check_all_apis) { extraFlags = append(extraFlags, "-check-all-apis") } else { @@ -1437,7 +1436,7 @@ func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, objs Objects, fileName string, soFile android.Path) { if library.sabi.shouldCreateSourceAbiDump() { exportedIncludeDirs := library.exportedIncludeDirsForAbiCheck(ctx) - headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx) + headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)) currSdkVersion := currRefAbiDumpSdkVersion(ctx) currVendorVersion := ctx.Config().VendorApiLevel() @@ -1451,7 +1450,7 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathD []string{} /* includeSymbolTags */, currSdkVersion, false /* isLlndk */) var llndkDump, apexVariantDump android.Path - tags := classifySourceAbiDump(ctx) + tags := classifySourceAbiDump(ctx.Module().(*Module)) optInTags := []lsdumpTag{} for _, tag := range tags { if tag == llndkLsdumpTag && currVendorVersion != "" { @@ -1868,7 +1867,7 @@ func (library *libraryDecorator) buildStubs() bool { } func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *string { - if props := library.getHeaderAbiCheckerProperties(ctx); props.Symbol_file != nil { + if props := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)); props.Symbol_file != nil { return props.Symbol_file } if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil { @@ -2071,12 +2070,7 @@ func reuseStaticLibrary(ctx android.BottomUpMutatorContext, shared *Module) { sharedCompiler.StaticProperties.Static.System_shared_libs == nil && sharedCompiler.SharedProperties.Shared.System_shared_libs == nil { - // TODO: namespaces? ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, reuseObjTag, ctx.ModuleName()) - sharedCompiler.baseCompiler.Properties.OriginalSrcs = - sharedCompiler.baseCompiler.Properties.Srcs - sharedCompiler.baseCompiler.Properties.Srcs = proptools.NewConfigurable[[]string](nil, nil) - sharedCompiler.baseCompiler.Properties.Generated_sources = nil } // This dep is just to reference static variant from shared variant diff --git a/cc/sabi.go b/cc/sabi.go index 64eab4160..2caf0d470 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -84,8 +84,8 @@ func (props *headerAbiCheckerProperties) explicitlyDisabled() bool { type SAbiProperties struct { // Whether ABI dump should be created for this module. - // Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static - // library that is depended on by an ABI checked library. + // Set by `sabiTransitionMutator` if this module is a shared library that needs ABI check, + // or a static library that is depended on by an ABI checked library. ShouldCreateSourceAbiDump bool `blueprint:"mutated"` // Include directories that may contain ABI information exported by a library. @@ -121,10 +121,9 @@ func (sabi *sabi) shouldCreateSourceAbiDump() bool { } // Returns a slice of strings that represent the ABI dumps generated for this module. -func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag { +func classifySourceAbiDump(m *Module) []lsdumpTag { result := []lsdumpTag{} - m := ctx.Module().(*Module) - headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx) + headerAbiChecker := m.library.getHeaderAbiCheckerProperties(m) if headerAbiChecker.explicitlyDisabled() { return result } @@ -149,24 +148,37 @@ func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag { return result } -// Called from sabiDepsMutator to check whether ABI dumps should be created for this module. +type shouldCreateAbiDumpContext interface { + android.ModuleProviderContext + Module() android.Module + Config() android.Config +} + +var _ shouldCreateAbiDumpContext = android.ModuleContext(nil) +var _ shouldCreateAbiDumpContext = android.OutgoingTransitionContext(nil) + +// Called from sabiTransitionMutator to check whether ABI dumps should be created for this module. // ctx should be wrapping a native library type module. -func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { - // Only generate ABI dump for device modules. - if !ctx.Device() { +func shouldCreateSourceAbiDumpForLibrary(ctx shouldCreateAbiDumpContext) bool { + m, ok := ctx.Module().(*Module) + if !ok { return false } - m := ctx.Module().(*Module) + // Only generate ABI dump for device modules. + if !m.Device() { + return false + } // Only create ABI dump for native library module types. if m.library == nil { return false } - // Create ABI dump for static libraries only if they are dependencies of ABI checked libraries. + // Don't create ABI dump for static libraries + // The sabi variant will be propagated to dependencies of ABI checked libraries. if m.library.static() { - return m.sabi.shouldCreateSourceAbiDump() + return false } // Module is shared library type. @@ -215,31 +227,64 @@ func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { return false } } - return len(classifySourceAbiDump(ctx)) > 0 + return len(classifySourceAbiDump(m)) > 0 } // Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps // of their dependencies would be generated. -func sabiDepsMutator(mctx android.TopDownMutatorContext) { +type sabiTransitionMutator struct{} + +func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string { + return []string{""} +} + +func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { // Escape hatch to not check any ABI dump. - if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { - return + if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { + return "" } + // Only create ABI dump for native shared libraries and their static library dependencies. - if m, ok := mctx.Module().(*Module); ok && m.sabi != nil { - if shouldCreateSourceAbiDumpForLibrary(mctx) { - // Mark this module so that .sdump / .lsdump for this library can be generated. + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + if shouldCreateSourceAbiDumpForLibrary(ctx) { + if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag { + return "sabi" + } + } else if sourceVariation == "sabi" { + if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag { + return "sabi" + } + } + } + + return "" +} + +func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if incomingVariation == "" { + return "" + } + + if incomingVariation == "sabi" { + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + return "sabi" + } + } + + return "" +} + +func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + if variation == "sabi" { m.sabi.Properties.ShouldCreateSourceAbiDump = true - // Mark all of its static library dependencies. - mctx.VisitDirectDeps(func(child android.Module) { - depTag := mctx.OtherModuleDependencyTag(child) - if IsStaticDepTag(depTag) || depTag == reuseObjTag { - if c, ok := child.(*Module); ok && c.sabi != nil { - // Mark this module so that .sdump for this static library can be generated. - c.sabi.Properties.ShouldCreateSourceAbiDump = true - } - } - }) + m.HideFromMake() + m.Properties.PreventInstall = true + } else if shouldCreateSourceAbiDumpForLibrary(ctx) { + // Escape hatch to not check any ABI dump. + if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { + m.sabi.Properties.ShouldCreateSourceAbiDump = true + } } } } diff --git a/cc/sabi_test.go b/cc/sabi_test.go new file mode 100644 index 000000000..6b8cc1759 --- /dev/null +++ b/cc/sabi_test.go @@ -0,0 +1,66 @@ +// Copyright 2024 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" + "testing" +) + +func TestSabi(t *testing.T) { + bp := ` + cc_library { + name: "libsabi", + srcs: ["sabi.cpp"], + static_libs: ["libdirect"], + header_abi_checker: { + enabled: true, + symbol_file: "libsabi.map.txt", + ref_dump_dirs: ["abi-dumps"], + }, + } + + cc_library { + name: "libdirect", + srcs: ["direct.cpp"], + whole_static_libs: ["libtransitive"], + } + + cc_library { + name: "libtransitive", + srcs: ["transitive.cpp"], + } + ` + + result := android.GroupFixturePreparers( + PrepareForTestWithCcDefaultModules, + ).RunTestWithBp(t, bp) + + libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static_sabi") + sabiObjSDump := libsabiStatic.Output("obj/sabi.sdump") + + libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static_sabi") + directObjSDump := libDirect.Output("obj/direct.sdump") + + libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static_sabi") + transitiveObjSDump := libTransitive.Output("obj/transitive.sdump") + + libsabiShared := result.ModuleForTests("libsabi", "android_arm64_armv8-a_shared") + sabiLink := libsabiShared.Rule("sAbiLink") + + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), sabiObjSDump.Output.String()) + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), directObjSDump.Output.String()) + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), transitiveObjSDump.Output.String()) +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 7f52ce1c7..85fdb023f 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -176,7 +176,7 @@ func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { switch t { case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack: sanitizer := &sanitizerSplitMutator{t} - ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator) + ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator).Parallel() ctx.Transition(t.variationName(), sanitizer) case Memtag_heap, Memtag_globals, intOverflow: // do nothing |