Create a AOSP Bazel overlay workspace with Soong

The Bazel overlay is a directory at out/soong/bazel_overlay that
replicates the layout of the AOSP Soong module tree, but as a Bazel
workspace. Each Soong module variant is represented as a BUILD target
created with the `soong_module` rule.

To create this overlay, run `m bazel_overlay`.

A `soong_module` target can depend on other `soong_module` targets.
These dependencies replicate each module's `directDeps` in the Blueprint
graph, just before `PrepareBuildActions`.

This enables users to use bazel query as a way to introspect the Soong
module graph. For example,

- Direct reverse dependencies of //bionic/libc:generated_android_ids in
//bionic/libc/...:

$ bazel query 'rdeps(//bionic/libc/...,
//bionic/libc:generated_android_ids, 1)'
//bionic/libc:libc_bionic_ndk--android_recovery_arm_armv7-a-neon_static
//bionic/libc:libc_bionic_ndk--android_ramdisk_arm_armv7-a-neon_static
//bionic/libc:libc_bionic_ndk--android_arm_armv7-a-neon_static_com.android.runtime
//bionic/libc:libc_bionic_ndk--android_arm_armv7-a-neon_static
//bionic/libc:generated_android_ids

- Why does com.android.runtime depend on lzma?

$ bazel query
'somepath(//bionic/apex:com.android.runtime--android_common_com.android.runtime_image,
//external/lzma/...)'
//bionic/apex:com.android.runtime--android_common_com.android.runtime_image
//bionic/libc/malloc_debug:libc_malloc_debug--android_arm_armv7-a-neon_shared_com.android.runtime
//system/core/libunwindstack:libunwindstack--android_arm_armv7-a-neon_shared_com.android.runtime
//external/lzma/C:liblzma--android_arm_armv7-a-neon_shared_com.android.runtime

- What does the dep graph of //bionic/libc:crtbegin_so look like?

$ bazel query
'deps(//bionic/libc:crtbegin_so--android_arm_armv7-a-neon)'
--output=graph > graph.in && dot -Tpng < graph.in > graph.png

https://photos.app.goo.gl/DfsdoFRNsRjGwTmy8

Test:  croot && m bazel_overlay && cd out/soong/bazel_overlay && bazel
query //... && bazel query 'rdeps(//bionic/libc/...,
//bionic/libc:generated_android_ids, 1)'

Signed-off-by: Jingwen Chen <jingwen@google.com>
Change-Id: I3bf40309bfb2d963bb8a688706385a57ee304c37#
diff --git a/android/bazel_overlay.go b/android/bazel_overlay.go
new file mode 100644
index 0000000..a034282
--- /dev/null
+++ b/android/bazel_overlay.go
@@ -0,0 +1,76 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/google/blueprint"
+)
+
+// The Bazel Overlay singleton is responsible for generating the Ninja actions
+// for calling the soong_build primary builder in the main build.ninja file.
+func init() {
+	RegisterSingletonType("bazel_overlay", BazelOverlaySingleton)
+}
+
+func BazelOverlaySingleton() Singleton {
+	return &bazelOverlaySingleton{}
+}
+
+type bazelOverlaySingleton struct{}
+
+func (c *bazelOverlaySingleton) GenerateBuildActions(ctx SingletonContext) {
+	// Create a build and rule statement, using the Bazel overlay's WORKSPACE
+	// file as the output file marker.
+	var deps Paths
+	moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
+	deps = append(deps, moduleListFilePath)
+	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
+	bazelOverlayDirectory := PathForOutput(ctx, "bazel_overlay")
+	bazelOverlayWorkspaceFile := bazelOverlayDirectory.Join(ctx, "WORKSPACE")
+	primaryBuilder := primaryBuilderPath(ctx)
+	bazelOverlay := ctx.Rule(pctx, "bazelOverlay",
+		blueprint.RuleParams{
+			Command: fmt.Sprintf(
+				"rm -rf ${outDir}/* && %s --bazel_overlay_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.overlay-depfile.d",
+				primaryBuilder.String(),
+				strings.Join(os.Args[1:], " "),
+				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+			),
+			CommandDeps: []string{primaryBuilder.String()},
+			Description: fmt.Sprintf(
+				"Creating the Bazel overlay workspace with %s at $outDir",
+				primaryBuilder.Base()),
+			Deps:    blueprint.DepsGCC,
+			Depfile: "${outDir}/.overlay-depfile.d",
+		},
+		"outDir")
+
+	ctx.Build(pctx, BuildParams{
+		Rule:   bazelOverlay,
+		Output: bazelOverlayWorkspaceFile,
+		Inputs: deps,
+		Args: map[string]string{
+			"outDir": bazelOverlayDirectory.String(),
+		},
+	})
+
+	// Add a phony target for building the bazel overlay
+	ctx.Phony("bazel_overlay", bazelOverlayWorkspaceFile)
+}