Merge "NDK library: collect NDK headers for ABI monitoring" into main
This commit is contained in:
@@ -82,6 +82,7 @@ type headerModule struct {
|
||||
|
||||
properties headerProperties
|
||||
|
||||
srcPaths android.Paths
|
||||
installPaths android.Paths
|
||||
licensePath android.Path
|
||||
}
|
||||
@@ -125,8 +126,8 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
|
||||
m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
|
||||
|
||||
srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
|
||||
for _, header := range srcFiles {
|
||||
m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
|
||||
for _, header := range m.srcPaths {
|
||||
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
|
||||
String(m.properties.To))
|
||||
installedPath := ctx.InstallFile(installDir, header.Base(), header)
|
||||
@@ -193,6 +194,7 @@ type versionedHeaderModule struct {
|
||||
|
||||
properties versionedHeaderProperties
|
||||
|
||||
srcPaths android.Paths
|
||||
installPaths android.Paths
|
||||
licensePath android.Path
|
||||
}
|
||||
@@ -211,9 +213,9 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo
|
||||
|
||||
fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From))
|
||||
toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
|
||||
srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
|
||||
m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
|
||||
var installPaths []android.WritablePath
|
||||
for _, header := range srcFiles {
|
||||
for _, header := range m.srcPaths {
|
||||
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
|
||||
installPath := installDir.Join(ctx, header.Base())
|
||||
installPaths = append(installPaths, installPath)
|
||||
@@ -224,11 +226,11 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo
|
||||
ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From))
|
||||
}
|
||||
|
||||
processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
|
||||
processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths)
|
||||
}
|
||||
|
||||
func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
|
||||
srcFiles android.Paths, installPaths []android.WritablePath) android.Path {
|
||||
srcPaths android.Paths, installPaths []android.WritablePath) android.Path {
|
||||
// The versioner depends on a dependencies directory to simplify determining include paths
|
||||
// when parsing headers. This directory contains architecture specific directories as well
|
||||
// as a common directory, each of which contains symlinks to the actually directories to
|
||||
@@ -253,7 +255,7 @@ func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir andro
|
||||
Rule: versionBionicHeaders,
|
||||
Description: "versioner preprocess " + srcDir.Rel(),
|
||||
Output: timestampFile,
|
||||
Implicits: append(srcFiles, depsGlob...),
|
||||
Implicits: append(srcPaths, depsGlob...),
|
||||
ImplicitOutputs: installPaths,
|
||||
Args: map[string]string{
|
||||
"depsPath": depsPath.String(),
|
||||
@@ -317,6 +319,7 @@ type preprocessedHeadersModule struct {
|
||||
|
||||
properties preprocessedHeadersProperties
|
||||
|
||||
srcPaths android.Paths
|
||||
installPaths android.Paths
|
||||
licensePath android.Path
|
||||
}
|
||||
@@ -329,9 +332,9 @@ func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.Modu
|
||||
preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor))
|
||||
m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
|
||||
|
||||
srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
|
||||
m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
|
||||
installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
|
||||
for _, src := range srcFiles {
|
||||
for _, src := range m.srcPaths {
|
||||
installPath := installDir.Join(ctx, src.Base())
|
||||
m.installPaths = append(m.installPaths, installPath)
|
||||
|
||||
|
@@ -43,11 +43,17 @@ var (
|
||||
CommandDeps: []string{"$ndkStubGenerator"},
|
||||
}, "arch", "apiLevel", "apiMap", "flags")
|
||||
|
||||
// $headersList should include paths to public headers. All types
|
||||
// that are defined outside of public headers will be excluded from
|
||||
// ABI monitoring.
|
||||
//
|
||||
// STG tool doesn't access content of files listed in $headersList,
|
||||
// so there is no need to add them to dependencies.
|
||||
stg = pctx.AndroidStaticRule("stg",
|
||||
blueprint.RuleParams{
|
||||
Command: "$stg -S :$symbolList --elf $in -o $out",
|
||||
Command: "$stg -S :$symbolList --file-filter :$headersList --elf $in -o $out",
|
||||
CommandDeps: []string{"$stg"},
|
||||
}, "symbolList")
|
||||
}, "symbolList", "headersList")
|
||||
|
||||
stgdiff = pctx.AndroidStaticRule("stgdiff",
|
||||
blueprint.RuleParams{
|
||||
@@ -347,14 +353,19 @@ func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
|
||||
this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
|
||||
this.apiLevel.String(), ctx.Arch().ArchType.String(),
|
||||
this.libraryName(ctx), "abi.stg")
|
||||
headersList := getNdkABIHeadersFile(ctx)
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: stg,
|
||||
Description: fmt.Sprintf("stg %s", implementationLibrary),
|
||||
Input: implementationLibrary,
|
||||
Implicit: symbolList,
|
||||
Output: this.abiDumpPath,
|
||||
Implicits: []android.Path{
|
||||
symbolList,
|
||||
headersList,
|
||||
},
|
||||
Output: this.abiDumpPath,
|
||||
Args: map[string]string{
|
||||
"symbolList": symbolList.String(),
|
||||
"symbolList": symbolList.String(),
|
||||
"headersList": headersList.String(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ package cc
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -96,15 +97,56 @@ func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath {
|
||||
return android.PathForOutput(ctx, "ndk.timestamp")
|
||||
}
|
||||
|
||||
// The list of all NDK headers as they are located in the repo.
|
||||
// Used for ABI monitoring to track only structures defined in NDK headers.
|
||||
func getNdkABIHeadersFile(ctx android.PathContext) android.WritablePath {
|
||||
return android.PathForOutput(ctx, "ndk_abi_headers.txt")
|
||||
}
|
||||
|
||||
func NdkSingleton() android.Singleton {
|
||||
return &ndkSingleton{}
|
||||
}
|
||||
|
||||
// Collect all NDK exported headers paths into a file that is used to
|
||||
// detect public types that should be ABI monitored.
|
||||
//
|
||||
// Assume that we have the following code in exported header:
|
||||
//
|
||||
// typedef struct Context Context;
|
||||
// typedef struct Output {
|
||||
// ...
|
||||
// } Output;
|
||||
// void DoSomething(Context* ctx, Output* output);
|
||||
//
|
||||
// If none of public headers exported to end-users contain definition of
|
||||
// "struct Context", then "struct Context" layout and members shouldn't be
|
||||
// monitored. However we use DWARF information from a real library, which
|
||||
// may have access to the definition of "string Context" from
|
||||
// implementation headers, and it will leak to ABI.
|
||||
//
|
||||
// STG tool doesn't access source and header files, only DWARF information
|
||||
// from compiled library. And the DWARF contains file name where a type is
|
||||
// defined. So we need a rule to build a list of paths to public headers,
|
||||
// so STG can distinguish private types from public and do not monitor
|
||||
// private types that are not accessible to library users.
|
||||
func writeNdkAbiSrcFilter(ctx android.BuilderContext,
|
||||
headerSrcPaths android.Paths, outputFile android.WritablePath) {
|
||||
var filterBuilder strings.Builder
|
||||
filterBuilder.WriteString("[decl_file_allowlist]\n")
|
||||
for _, headerSrcPath := range headerSrcPaths {
|
||||
filterBuilder.WriteString(headerSrcPath.String())
|
||||
filterBuilder.WriteString("\n")
|
||||
}
|
||||
|
||||
android.WriteFileRule(ctx, outputFile, filterBuilder.String())
|
||||
}
|
||||
|
||||
type ndkSingleton struct{}
|
||||
|
||||
func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
var staticLibInstallPaths android.Paths
|
||||
var headerPaths android.Paths
|
||||
var headerSrcPaths android.Paths
|
||||
var headerInstallPaths android.Paths
|
||||
var installPaths android.Paths
|
||||
var licensePaths android.Paths
|
||||
ctx.VisitAllModules(func(module android.Module) {
|
||||
@@ -113,19 +155,22 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
}
|
||||
|
||||
if m, ok := module.(*headerModule); ok {
|
||||
headerPaths = append(headerPaths, m.installPaths...)
|
||||
headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
|
||||
headerInstallPaths = append(headerInstallPaths, m.installPaths...)
|
||||
installPaths = append(installPaths, m.installPaths...)
|
||||
licensePaths = append(licensePaths, m.licensePath)
|
||||
}
|
||||
|
||||
if m, ok := module.(*versionedHeaderModule); ok {
|
||||
headerPaths = append(headerPaths, m.installPaths...)
|
||||
headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
|
||||
headerInstallPaths = append(headerInstallPaths, m.installPaths...)
|
||||
installPaths = append(installPaths, m.installPaths...)
|
||||
licensePaths = append(licensePaths, m.licensePath)
|
||||
}
|
||||
|
||||
if m, ok := module.(*preprocessedHeadersModule); ok {
|
||||
headerPaths = append(headerPaths, m.installPaths...)
|
||||
headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
|
||||
headerInstallPaths = append(headerInstallPaths, m.installPaths...)
|
||||
installPaths = append(installPaths, m.installPaths...)
|
||||
licensePaths = append(licensePaths, m.licensePath)
|
||||
}
|
||||
@@ -175,9 +220,11 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Touch,
|
||||
Output: getNdkHeadersTimestampFile(ctx),
|
||||
Implicits: headerPaths,
|
||||
Implicits: headerInstallPaths,
|
||||
})
|
||||
|
||||
writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx))
|
||||
|
||||
fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
|
||||
|
||||
// There's a phony "ndk" rule defined in core/main.mk that depends on this.
|
||||
|
Reference in New Issue
Block a user