Support source code cross-referencing for C++ and Java

Use Kythe (https://kythe.io) to build cross reference for the Android
source code. ~generate the input for it during the build. This is done
on demand: if XREF_CORPUS environment variable is set, build emits a
Ninja rule to generate Kythe input for each compilation rule. It
also emits two consolidation rules (`xref_cxx` and `xref_java`),
that depend on all Kythe input generation rules for C++ and Java.

The value of the XREF_CORPUS environment variable is recorded in the
generated files and thus passed to Kythe. For the AOSP master branch it is
`android.googlesource.com/platform/superproject`, so the command to build
all input for Kythe on that branch is:
```
XREF_CORPUS=android.googlesource.com/platform/superproject m xref_cxx xref_java
```

Each Kythe input generation rule generates a single file with .kzip
extension. Individual .kzip files have a lot of common information, so
there will be a post-build consolidation step run to combine them.
The consolidated .kzip file is then passed to Kythe backend.

The tools to generate .kzip files are provided by Kythe (it calls them
'extractors'). We are going to build them in toolbuilding branches
(clang-tools and build-tools) and check them in as binaries into master
and other PDK branches:
For C++,  `prebuilts/clang-tools/linux-x86/bin/cxx_extractor`
for Java, `prebuilts/build-tools/common/framework/javac_extractor.jar`

Bug: 121267023
Test: 1) When XREF_CORPUS is set, build generates Ninja rules to create
.kzip files; 2) When XREF_CORPUS is set, building
`xref_cxx`/`xref_java` creates .kzip files; 3) Unless XREF_CORPUS is
set, build generates the same Ninja rules as before

Change-Id: If957b35d7abc82dbfbb3665980e7c34afe7c789e
This commit is contained in:
Sasha Smundak
2018-11-05 16:49:08 -08:00
parent e515886a8b
commit 2a4549ec98
7 changed files with 215 additions and 0 deletions

View File

@@ -50,6 +50,7 @@ func init() {
android.RegisterModuleType("dex_import", DexImportFactory)
android.RegisterSingletonType("logtags", LogtagsSingleton)
android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
// TODO:
@@ -342,6 +343,9 @@ type Module struct {
hiddenAPI
dexpreopter
// list of the xref extraction files
kytheFiles android.Paths
}
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -382,6 +386,10 @@ type SrcDependency interface {
CompiledSrcJars() android.Paths
}
type xref interface {
XrefJavaFiles() android.Paths
}
func (j *Module) CompiledSrcs() android.Paths {
return j.compiledJavaSrcs
}
@@ -390,6 +398,10 @@ func (j *Module) CompiledSrcJars() android.Paths {
return j.compiledSrcJars
}
func (j *Module) XrefJavaFiles() android.Paths {
return j.kytheFiles
}
var _ SrcDependency = (*Module)(nil)
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
@@ -1138,6 +1150,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
TransformJavaToClasses(ctx, classes, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
jars = append(jars, classes)
}
if ctx.Config().EmitXrefRules() {
extractionFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".kzip")
emitXrefRule(ctx, extractionFile, uniqueSrcFiles, srcJars, flags, extraJarDeps, "xref")
j.kytheFiles = append(j.kytheFiles, extractionFile)
}
if ctx.Failed() {
return
}
@@ -2203,6 +2221,30 @@ func DefaultsFactory(props ...interface{}) android.Module {
return module
}
func kytheExtractJavaFactory() android.Singleton {
return &kytheExtractJavaSingleton{}
}
type kytheExtractJavaSingleton struct {
}
func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var xrefTargets android.Paths
ctx.VisitAllModules(func(module android.Module) {
if javaModule, ok := module.(xref); ok {
xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
}
})
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
if len(xrefTargets) > 0 {
ctx.Build(pctx, android.BuildParams{
Rule: blueprint.Phony,
Output: android.PathForPhony(ctx, "xref_java"),
Inputs: xrefTargets,
})
}
}
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String