bp2build: add python_binary_host converter.

This CL adds a simple python_binary_host to native py_binary converter
for standalone modules that don't depend on libs. It also adds support
for the conditional py2/py3 build target based on the version prop.

Test: milestone-2/demo.sh full
Test: bazel query 'kind("py_binary rule", //bionic/...)'
Test: bazel run //bionic/libc/tools:genfunctosyscallnrs
Test: bazel run //bionic/libc/tools:genseccomp
Test: go tests
Fixes: 182236395
Change-Id: Ibe5ec6cd0dc12a61b3a449a8c723d80b891fae42
diff --git a/python/binary.go b/python/binary.go
index 416a7ee..372b8a8 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -20,10 +20,92 @@
 	"fmt"
 
 	"android/soong/android"
+	"android/soong/bazel"
+
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
 	android.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
+	android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
+}
+
+type bazelPythonBinaryAttributes struct {
+	Main           string
+	Srcs           bazel.LabelList
+	Data           bazel.LabelList
+	Python_version string
+}
+
+type bazelPythonBinary struct {
+	android.BazelTargetModuleBase
+	bazelPythonBinaryAttributes
+}
+
+func BazelPythonBinaryFactory() android.Module {
+	module := &bazelPythonBinary{}
+	module.AddProperties(&module.bazelPythonBinaryAttributes)
+	android.InitBazelTargetModule(module)
+	return module
+}
+
+func (m *bazelPythonBinary) Name() string {
+	return m.BaseModuleName()
+}
+
+func (m *bazelPythonBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) {
+	m, ok := ctx.Module().(*Module)
+	if !ok || !m.ConvertWithBp2build() {
+		return
+	}
+
+	// a Module can be something other than a python_binary_host
+	if ctx.ModuleType() != "python_binary_host" {
+		return
+	}
+
+	var main string
+	for _, propIntf := range m.GetProperties() {
+		if props, ok := propIntf.(*BinaryProperties); ok {
+			// main is optional.
+			if props.Main != nil {
+				main = *props.Main
+				break
+			}
+		}
+	}
+	// TODO(b/182306917): this doesn't fully handle all nested props versioned
+	// by the python version, which would have been handled by the version split
+	// mutator. This is sufficient for very simple python_binary_host modules
+	// under Bionic.
+	py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
+	py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+	var python_version string
+	if py3Enabled && py2Enabled {
+		panic(fmt.Errorf(
+			"error for '%s' module: bp2build's python_binary_host converter does not support "+
+				"converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
+	} else if py2Enabled {
+		python_version = "PY2"
+	} else {
+		// do nothing, since python_version defaults to PY3.
+	}
+
+	attrs := &bazelPythonBinaryAttributes{
+		Main:           main,
+		Srcs:           android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs),
+		Data:           android.BazelLabelForModuleSrc(ctx, m.properties.Data),
+		Python_version: python_version,
+	}
+
+	props := bazel.BazelTargetModuleProperties{
+		// Use the native py_binary rule.
+		Rule_class: "py_binary",
+	}
+
+	ctx.CreateBazelTargetModule(BazelPythonBinaryFactory, m.Name(), props, attrs)
 }
 
 type BinaryProperties struct {
@@ -81,6 +163,8 @@
 func PythonBinaryHostFactory() android.Module {
 	module, _ := NewBinary(android.HostSupported)
 
+	android.InitBazelModule(module)
+
 	return module.init()
 }