From 64b2d0389c5f4a41b9d2e08510e8d8a2e05c75b0 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Chen Date: Fri, 29 Mar 2024 19:12:35 +0800 Subject: [PATCH] Filter ABI dumps by LLNDK headers and version scripts This commit changes the parameters to create LLNDK ABI dumps for 202404 and later versions. Soong invokes header-abi-linker with LLNDK headers and version script rather than the implementation library's parameters. The output dump contains more precise ABI information. When soong compares the ABI with the prebuilt dumps in old versions, it creates the source ABI dumps with the old parameters. Test: make findlsdumps Bug: 314010764 Change-Id: I228736188d07029ee1588b3502fd7c0061c104b9 --- android/config.go | 5 +++ cc/cc_test.go | 30 +++++++++++++---- cc/library.go | 82 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/android/config.go b/android/config.go index f2f7d7de9..47e10d6aa 100644 --- a/android/config.go +++ b/android/config.go @@ -1409,6 +1409,11 @@ func (c *config) PrevVendorApiLevel() string { return strconv.Itoa(vendorApiLevel - 100) } +func IsTrunkStableVendorApiLevel(level string) bool { + levelInt, err := strconv.Atoi(level) + return err == nil && levelInt >= 202404 +} + func (c *config) VendorApiLevelFrozen() bool { return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN") } diff --git a/cc/cc_test.go b/cc/cc_test.go index 74fae04f4..d4955c615 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -998,12 +998,30 @@ func TestLlndkLibrary(t *testing.T) { expectedDirs, f.IncludeDirs) } - checkExportedIncludeDirs("libllndk", "android_arm64_armv8-a_shared", "include") - checkExportedIncludeDirs("libllndk", "android_vendor_arm64_armv8-a_shared", "include") - checkExportedIncludeDirs("libllndk_with_external_headers", "android_arm64_armv8-a_shared", "include") - checkExportedIncludeDirs("libllndk_with_external_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk") - checkExportedIncludeDirs("libllndk_with_override_headers", "android_arm64_armv8-a_shared", "include") - checkExportedIncludeDirs("libllndk_with_override_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk") + checkExportedIncludeDirs("libllndk", coreVariant, "include") + checkExportedIncludeDirs("libllndk", vendorVariant, "include") + checkExportedIncludeDirs("libllndk_with_external_headers", coreVariant, "include") + checkExportedIncludeDirs("libllndk_with_external_headers", vendorVariant, "include_llndk") + checkExportedIncludeDirs("libllndk_with_override_headers", coreVariant, "include") + checkExportedIncludeDirs("libllndk_with_override_headers", vendorVariant, "include_llndk") + + checkAbiLinkerIncludeDirs := func(module string) { + t.Helper() + coreModule := result.ModuleForTests(module, coreVariant) + abiCheckFlags := "" + for _, output := range coreModule.AllOutputs() { + if strings.HasSuffix(output, ".so.llndk.lsdump") { + abiCheckFlags = coreModule.Output(output).Args["exportedHeaderFlags"] + } + } + vendorModule := result.ModuleForTests(module, vendorVariant).Module() + vendorInfo, _ := android.SingletonModuleProvider(result, vendorModule, FlagExporterInfoProvider) + android.AssertStringEquals(t, module+" has different exported include dirs for vendor variant and ABI check", + android.JoinPathsWithPrefix(vendorInfo.IncludeDirs, "-I"), abiCheckFlags) + } + checkAbiLinkerIncludeDirs("libllndk") + checkAbiLinkerIncludeDirs("libllndk_with_override_headers") + checkAbiLinkerIncludeDirs("libllndk_with_external_headers") } func TestLlndkHeaders(t *testing.T) { diff --git a/cc/library.go b/cc/library.go index 9119821a9..2677d2870 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1153,7 +1153,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...) library.coverageOutputFile = transformCoverageFilesToZip(ctx, objs, library.getLibName(ctx)) - library.linkSAbiDumpFiles(ctx, objs, fileName, unstrippedOutputFile) + library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile) var transitiveStaticLibrariesForOrdering *android.DepSet[android.Path] if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 { @@ -1222,6 +1222,45 @@ func (library *libraryDecorator) exportedIncludeDirsForAbiCheck(ctx ModuleContex return exportIncludeDirs } +func (library *libraryDecorator) llndkIncludeDirsForAbiCheck(ctx ModuleContext, deps PathDeps) []string { + // The ABI checker does not need the preprocess which adds macro guards to function declarations. + includeDirs := android.PathsForModuleSrc(ctx, library.Properties.Llndk.Export_preprocessed_headers).Strings() + + if library.Properties.Llndk.Override_export_include_dirs != nil { + includeDirs = append(includeDirs, android.PathsForModuleSrc( + ctx, library.Properties.Llndk.Override_export_include_dirs).Strings()...) + } else { + includeDirs = append(includeDirs, library.flagExporter.exportedIncludes(ctx).Strings()...) + // Ignore library.sabi.Properties.ReexportedIncludes because + // LLNDK does not reexport the implementation's dependencies, such as export_header_libs. + } + + systemIncludeDirs := []string{} + if Bool(library.Properties.Llndk.Export_headers_as_system) { + systemIncludeDirs = append(systemIncludeDirs, includeDirs...) + includeDirs = nil + } + // Header libs. + includeDirs = append(includeDirs, deps.LlndkIncludeDirs.Strings()...) + systemIncludeDirs = append(systemIncludeDirs, deps.LlndkSystemIncludeDirs.Strings()...) + // The ABI checker does not distinguish normal and system headers. + return append(includeDirs, systemIncludeDirs...) +} + +func (library *libraryDecorator) linkLlndkSAbiDumpFiles(ctx ModuleContext, + deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string, + excludeSymbolVersions, excludeSymbolTags []string) android.Path { + // NDK symbols in version 34 are LLNDK symbols. Those in version 35 are not. + // TODO(b/314010764): Add parameters to read LLNDK symbols from the symbol file. + return transformDumpToLinkedDump(ctx, + sAbiDumpFiles, soFile, libFileName+".llndk", + library.llndkIncludeDirsForAbiCheck(ctx, deps), + android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file), + append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...), + append([]string{"platform-only"}, excludeSymbolTags...), + "34") +} + func getRefAbiDumpFile(ctx android.ModuleInstallPathContext, versionedDumpDir, fileName string) android.OptionalPath { @@ -1332,13 +1371,15 @@ func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, false /* isLlndkOrNdk */, false /* allowExtensions */, "current", errorMessage) } -func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) { +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) currSdkVersion := currRefAbiDumpSdkVersion(ctx) currVendorVersion := ctx.Config().VendorApiLevel() - sourceDump := transformDumpToLinkedDump(ctx, + + // Generate source dumps. + implDump := transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedIncludeDirs, android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)), @@ -1346,8 +1387,25 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec headerAbiChecker.Exclude_symbol_tags, currSdkVersion) - for _, tag := range classifySourceAbiDump(ctx) { - addLsdumpPath(string(tag) + ":" + sourceDump.String()) + var llndkDump android.Path + tags := classifySourceAbiDump(ctx) + for _, tag := range tags { + if tag == llndkLsdumpTag { + if llndkDump == nil { + // TODO(b/323447559): Evaluate if replacing sAbiDumpFiles with implDump is faster + llndkDump = library.linkLlndkSAbiDumpFiles(ctx, + deps, objs.sAbiDumpFiles, soFile, fileName, + headerAbiChecker.Exclude_symbol_versions, + headerAbiChecker.Exclude_symbol_tags) + } + addLsdumpPath(string(tag) + ":" + llndkDump.String()) + } else { + addLsdumpPath(string(tag) + ":" + implDump.String()) + } + } + + // Diff source dumps and reference dumps. + for _, tag := range tags { dumpDirName := tag.dirName() if dumpDirName == "" { continue @@ -1362,10 +1420,15 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec } // Check against the previous version. var prevVersion, currVersion string + sourceDump := implDump // If this release config does not define VendorApiLevel, fall back to the old policy. if isLlndk && currVendorVersion != "" { prevVersion = ctx.Config().PrevVendorApiLevel() currVersion = currVendorVersion + // LLNDK dumps are generated by different rules after trunk stable. + if android.IsTrunkStableVendorApiLevel(prevVersion) { + sourceDump = llndkDump + } } else { prevVersion, currVersion = crossVersionAbiDiffSdkVersions(ctx, dumpDir) } @@ -1376,8 +1439,12 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec fileName, isLlndk || isNdk, currVersion, nameExt+prevVersion) } // Check against the current version. + sourceDump = implDump if isLlndk && currVendorVersion != "" { currVersion = currVendorVersion + if android.IsTrunkStableVendorApiLevel(currVersion) { + sourceDump = llndkDump + } } else { currVersion = currSdkVersion } @@ -1398,7 +1465,7 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec continue } library.optInAbiDiff(ctx, - sourceDump, optInDumpFile.Path(), + implDump, optInDumpFile.Path(), fileName, "opt"+strconv.Itoa(i), optInDumpDirPath.String()) } } @@ -1765,9 +1832,6 @@ func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *strin if props := library.getHeaderAbiCheckerProperties(ctx); props.Symbol_file != nil { return props.Symbol_file } - if ctx.Module().(*Module).IsLlndk() { - return library.Properties.Llndk.Symbol_file - } if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil { return library.Properties.Stubs.Symbol_file }