diff --git a/android/config.go b/android/config.go index c28e6f835..5fe33cefb 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 f3db2ef5e..d9754df99 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1138,7 +1138,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 { @@ -1207,6 +1207,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 { @@ -1317,13 +1356,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)), @@ -1331,8 +1372,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 @@ -1347,10 +1405,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) } @@ -1361,8 +1424,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 } @@ -1383,7 +1450,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()) } } @@ -1750,9 +1817,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 }