Support aidl cpp generation

Ideally we'd calculate the headers that are written here too, but I'll
add that in a later change that actually enforces the generated header
list.

Test: mmma -j system/tools/aidl
Change-Id: Ifd2e8e8ff444b0f67270fb5156e7bf7bceddb6be
diff --git a/cc/builder.go b/cc/builder.go
index ee53f41..d0b21ed 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -194,6 +194,7 @@
 	protoFlags  string
 	tidyFlags   string
 	yasmFlags   string
+	aidlFlags   string
 	toolchain   config.Toolchain
 	clang       bool
 	tidy        bool
diff --git a/cc/cc.go b/cc/cc.go
index a4f8e58..6525047 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -98,6 +98,7 @@
 	CppFlags    []string // Flags that apply to C++ source files
 	YaccFlags   []string // Flags that apply to Yacc source files
 	protoFlags  []string // Flags that apply to proto source files
+	aidlFlags   []string // Flags that apply to aidl source files
 	LdFlags     []string // Flags that apply to linker command lines
 	libFlags    []string // Flags to add libraries early to the link order
 	TidyFlags   []string // Flags that apply to clang-tidy
diff --git a/cc/compiler.go b/cc/compiler.go
index 04f536f..99f56b7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -87,6 +87,15 @@
 	// if set to false, use -std=c++* instead of -std=gnu++*
 	Gnu_extensions *bool
 
+	Aidl struct {
+		// list of directories that will be added to the aidl include paths.
+		Include_dirs []string
+
+		// list of directories relative to the Blueprints file that will
+		// be added to the aidl include paths.
+		Local_include_dirs []string
+	}
+
 	Debug, Release struct {
 		// list of module-specific flags that will be used for C and C++ compiles in debug or
 		// release builds
@@ -341,6 +350,20 @@
 			"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
 	}
 
+	if compiler.hasSrcExt(".aidl") {
+		if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
+			localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
+			flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(localAidlIncludeDirs))
+		}
+		if len(compiler.Properties.Aidl.Include_dirs) > 0 {
+			rootAidlIncludeDirs := android.PathsForSource(ctx, compiler.Properties.Aidl.Include_dirs)
+			flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
+		}
+
+		flags.GlobalFlags = append(flags.GlobalFlags,
+			"-I"+android.PathForModuleGen(ctx, "aidl").String())
+	}
+
 	return flags
 }
 
diff --git a/cc/gen.go b/cc/gen.go
index 1000bf8..808a681 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -28,6 +28,8 @@
 	pctx.SourcePathVariable("lexCmd", "prebuilts/misc/${config.HostPrebuiltTag}/flex/flex-2.5.39")
 	pctx.SourcePathVariable("yaccCmd", "prebuilts/misc/${config.HostPrebuiltTag}/bison/bison")
 	pctx.SourcePathVariable("yaccDataDir", "external/bison/data")
+
+	pctx.HostBinToolVariable("aidlCmd", "aidl-cpp")
 }
 
 var (
@@ -45,6 +47,16 @@
 			CommandDeps: []string{"$lexCmd"},
 			Description: "lex $out",
 		})
+
+	aidl = pctx.AndroidStaticRule("aidl",
+		blueprint.RuleParams{
+			Command:     "$aidlCmd -d${out}.d -ninja $aidlFlags $in $outDir $out",
+			CommandDeps: []string{"$aidlCmd"},
+			Depfile:     "${out}.d",
+			Deps:        blueprint.DepsGCC,
+			Description: "aidl $out",
+		},
+		"aidlFlags", "outDir")
 )
 
 func genYacc(ctx android.ModuleContext, yaccFile android.Path, outFile android.ModuleGenPath, yaccFlags string) (headerFile android.ModuleGenPath) {
@@ -64,6 +76,22 @@
 	return headerFile
 }
 
+func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths {
+
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:   aidl,
+		Output: outFile,
+		Input:  aidlFile,
+		Args: map[string]string{
+			"aidlFlags": aidlFlags,
+			"outDir":    android.PathForModuleGen(ctx, "aidl").String(),
+		},
+	})
+
+	// TODO: This should return the generated headers, not the source file.
+	return android.Paths{outFile}
+}
+
 func genLex(ctx android.ModuleContext, lexFile android.Path, outFile android.ModuleGenPath) {
 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
 		Rule:   lex,
@@ -99,6 +127,10 @@
 			cppFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags)
 			srcFiles[i] = cppFile
 			deps = append(deps, headerFile)
+		case ".aidl":
+			cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
+			srcFiles[i] = cppFile
+			deps = append(deps, genAidl(ctx, srcFile, cppFile, buildFlags.aidlFlags)...)
 		}
 	}
 
diff --git a/cc/library.go b/cc/library.go
index 7b7ac95..bdd8e79 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -55,6 +55,11 @@
 	// rename host libraries to prevent overlap with system installed libraries
 	Unique_host_soname *bool
 
+	Aidl struct {
+		// export headers generated from .aidl sources
+		Export_aidl_headers bool
+	}
+
 	Proto struct {
 		// export headers generated from .proto sources
 		Export_proto_headers bool
@@ -495,8 +500,17 @@
 	library.reexportFlags(deps.ReexportedFlags)
 	library.reexportDeps(deps.ReexportedFlagsDeps)
 
-	if library.baseCompiler.hasSrcExt(".proto") {
-		if library.Properties.Proto.Export_proto_headers {
+	if library.Properties.Aidl.Export_aidl_headers {
+		if library.baseCompiler.hasSrcExt(".aidl") {
+			library.reexportFlags([]string{
+				"-I" + android.PathForModuleGen(ctx, "aidl").String(),
+			})
+			library.reexportDeps(library.baseCompiler.deps) // TODO: restrict to aidl deps
+		}
+	}
+
+	if library.Properties.Proto.Export_proto_headers {
+		if library.baseCompiler.hasSrcExt(".proto") {
 			library.reexportFlags([]string{
 				"-I" + protoSubDir(ctx).String(),
 				"-I" + protoDir(ctx).String(),
diff --git a/cc/makevars.go b/cc/makevars.go
index fe3440c..af4ba28 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -64,6 +64,8 @@
 	ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks))
 	ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}")
 
+	ctx.Strict("AIDL_CPP", "${aidlCmd}")
+
 	includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes} ${config.CommonGlobalSystemIncludes}")
 	if err != nil {
 		panic(err)
diff --git a/cc/util.go b/cc/util.go
index 9f958d1..466266c 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -94,6 +94,7 @@
 		cppFlags:    strings.Join(in.CppFlags, " "),
 		yaccFlags:   strings.Join(in.YaccFlags, " "),
 		protoFlags:  strings.Join(in.protoFlags, " "),
+		aidlFlags:   strings.Join(in.aidlFlags, " "),
 		ldFlags:     strings.Join(in.LdFlags, " "),
 		libFlags:    strings.Join(in.libFlags, " "),
 		tidyFlags:   strings.Join(in.TidyFlags, " "),