genrule: support deps files

If a genrule sets deps_file: true, use a file in the gen directory
as a GCC-style deps file.

Test: m -j libLLVMObject
Change-Id: Id410165847e4eaea1853a392512e38787c431523
diff --git a/android/module.go b/android/module.go
index 2b6f8ba..110f04c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -34,6 +34,8 @@
 
 type ModuleBuildParams struct {
 	Rule            blueprint.Rule
+	Deps            blueprint.Deps
+	Depfile         WritablePath
 	Output          WritablePath
 	Outputs         WritablePaths
 	ImplicitOutput  WritablePath
@@ -521,6 +523,7 @@
 func (a *androidModuleContext) ModuleBuild(pctx blueprint.PackageContext, params ModuleBuildParams) {
 	bparams := blueprint.BuildParams{
 		Rule:            params.Rule,
+		Deps:            params.Deps,
 		Outputs:         params.Outputs.Strings(),
 		ImplicitOutputs: params.ImplicitOutputs.Strings(),
 		Inputs:          params.Inputs.Strings(),
@@ -530,6 +533,9 @@
 		Optional:        !params.Default,
 	}
 
+	if params.Depfile != nil {
+		bparams.Depfile = params.Depfile.String()
+	}
 	if params.Output != nil {
 		bparams.Outputs = append(bparams.Outputs, params.Output.String())
 	}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 498858d..b1ce804 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -47,6 +47,7 @@
 	// $(location <label>): the path to the tool or tool_file with name <label>
 	// $(in): one or more input files
 	// $(out): a single output file
+	// $(deps): a file to which dependencies will be written, if the depfile property is set to true
 	// $(genDir): the sandbox directory for this tool; contains $(out)
 	// $$: a literal $
 	//
@@ -55,6 +56,9 @@
 	// change.
 	Cmd string
 
+	// Enable reading a file containing dependencies in gcc format after the command completes
+	Depfile bool
+
 	// name of the modules (if any) that produces the host executable.   Leave empty for
 	// prebuilts or scripts that do not need a module to build them.
 	Tools []string
@@ -156,6 +160,11 @@
 			return "${in}", nil
 		case "out":
 			return "${out}", nil
+		case "depfile":
+			if !g.properties.Depfile {
+				return "", fmt.Errorf("$(depfile) used without depfile property")
+			}
+			return "${depfile}", nil
 		case "genDir":
 			return g.genPath.String(), nil
 		default:
@@ -175,9 +184,15 @@
 		ctx.PropertyErrorf("cmd", "%s", err.Error())
 	}
 
-	g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
+	ruleParams := blueprint.RuleParams{
 		Command: cmd,
-	})
+	}
+	var args []string
+	if g.properties.Depfile {
+		ruleParams.Deps = blueprint.DepsGCC
+		args = append(args, "depfile")
+	}
+	g.rule = ctx.Rule(pctx, "generator", ruleParams, args...)
 
 	for _, task := range g.tasks(ctx) {
 		g.generateSourceFile(ctx, task)
@@ -185,12 +200,17 @@
 }
 
 func (g *generator) generateSourceFile(ctx android.ModuleContext, task generateTask) {
-	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+	params := android.ModuleBuildParams{
 		Rule:      g.rule,
 		Outputs:   task.out,
 		Inputs:    task.in,
 		Implicits: g.deps,
-	})
+	}
+	if g.properties.Depfile {
+		depfile := android.GenPathWithExt(ctx, "", task.out[0], task.out[0].Ext()+".d")
+		params.Depfile = depfile
+	}
+	ctx.ModuleBuild(pctx, params)
 
 	for _, outputFile := range task.out {
 		g.outputFiles = append(g.outputFiles, outputFile)