Quellcode durchsuchen

bp2build converts java_genrule and java_genrule_host

Bp2build currently supports building genrules for cc modules, but does
not support building java_genrule* modules. This commit adds this
functionality.

Bug: 213480907
Test: go test ./bp2build
Change-Id: I473196c5bcf5582ba0c8faa65b5005f81ac973a4
Sam Delmerico vor 2 Jahren
Ursprung
Commit
cd1b80f067

+ 5 - 1
android/bazel.go

@@ -468,9 +468,13 @@ var (
 		"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
 
 		// go deps:
-		"apex-protos",               // depends on unconverted modules: soong_zip
+		"apex-protos",               // depends on soong_zip, a go binary
+		"robolectric_tzdata",        // depends on soong_zip, a go binary
 		"host_bionic_linker_asm",    // depends on extract_linker, a go binary.
 		"host_bionic_linker_script", // depends on extract_linker, a go binary.
+
+		// java deps
+		"bin2c_fastdeployagent", // depends on deployagent, a java binary
 	}
 
 	// Per-module denylist of cc_library modules to only generate the static

+ 0 - 1
bp2build/Android.bp

@@ -38,7 +38,6 @@ bootstrap_go_package {
         "build_conversion_test.go",
         "bzl_conversion_test.go",
         "cc_binary_conversion_test.go",
-        "cc_genrule_conversion_test.go",
         "cc_library_conversion_test.go",
         "cc_library_headers_conversion_test.go",
         "cc_library_shared_conversion_test.go",

+ 0 - 235
bp2build/cc_genrule_conversion_test.go

@@ -1,235 +0,0 @@
-// Copyright 2021 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 bp2build
-
-import (
-	"testing"
-
-	"android/soong/android"
-	"android/soong/cc"
-)
-
-var otherCcGenruleBp = map[string]string{
-	"other/Android.bp": `cc_genrule {
-    name: "foo.tool",
-    out: ["foo_tool.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-}
-cc_genrule {
-    name: "other.tool",
-    out: ["other_tool.out"],
-    srcs: ["other_tool.in"],
-    cmd: "cp $(in) $(out)",
-}`,
-}
-
-func runCcGenruleTestCase(t *testing.T, tc bp2buildTestCase) {
-	t.Helper()
-	(&tc).moduleTypeUnderTest = "cc_genrule"
-	(&tc).moduleTypeUnderTestFactory = cc.GenRuleFactory
-	runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestCliVariableReplacement(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule with command line variable replacements",
-		blueprint: `cc_genrule {
-    name: "foo.tool",
-    out: ["foo_tool.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}
-
-cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tool"],
-    cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}`,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":   `"$(location :foo.tool) --genDir=$(RULEDIR) arg $(SRCS) $(OUTS)"`,
-				"outs":  `["foo.out"]`,
-				"srcs":  `["foo.in"]`,
-				"tools": `[":foo.tool"]`,
-			}),
-			makeBazelTarget("genrule", "foo.tool", attrNameToString{
-				"cmd":  `"cp $(SRCS) $(OUTS)"`,
-				"outs": `["foo_tool.out"]`,
-				"srcs": `["foo_tool.in"]`,
-			}),
-		},
-	})
-}
-
-func TestUsingLocationsLabel(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule using $(locations :label)",
-		blueprint: `cc_genrule {
-    name: "foo.tools",
-    out: ["foo_tool.out", "foo_tool2.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}
-
-cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tools"],
-    cmd: "$(locations :foo.tools) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":   `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
-				"outs":  `["foo.out"]`,
-				"srcs":  `["foo.in"]`,
-				"tools": `[":foo.tools"]`,
-			}),
-			makeBazelTarget("genrule", "foo.tools", attrNameToString{
-				"cmd": `"cp $(SRCS) $(OUTS)"`,
-				"outs": `[
-        "foo_tool.out",
-        "foo_tool2.out",
-    ]`,
-				"srcs": `["foo_tool.in"]`,
-			}),
-		},
-	})
-}
-
-func TestUsingLocationsAbsoluteLabel(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule using $(locations //absolute:label)",
-		blueprint: `cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tool_files: [":foo.tool"],
-    cmd: "$(locations :foo.tool) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-		filesystem: otherCcGenruleBp,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-				"outs":  `["foo.out"]`,
-				"srcs":  `["foo.in"]`,
-				"tools": `["//other:foo.tool"]`,
-			}),
-		},
-	})
-}
-
-func TestSrcsUsingAbsoluteLabel(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule srcs using $(locations //absolute:label)",
-		blueprint: `cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: [":other.tool"],
-    tool_files: [":foo.tool"],
-    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
-    bazel_module: { bp2build_available: true },
-}`,
-		filesystem: otherCcGenruleBp,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
-				"outs":  `["foo.out"]`,
-				"srcs":  `["//other:other.tool"]`,
-				"tools": `["//other:foo.tool"]`,
-			}),
-		},
-	})
-}
-
-func TestLocationsLabelUsesFirstToolFile(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule using $(location) label should substitute first tool label automatically",
-		blueprint: `cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tool_files: [":foo.tool", ":other.tool"],
-    cmd: "$(location) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-		filesystem: otherCcGenruleBp,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":  `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-				"outs": `["foo.out"]`,
-				"srcs": `["foo.in"]`,
-				"tools": `[
-        "//other:foo.tool",
-        "//other:other.tool",
-    ]`,
-			}),
-		},
-	})
-}
-
-func TestLocationsLabelUsesFirstTool(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule using $(locations) label should substitute first tool label automatically",
-		blueprint: `cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tool", ":other.tool"],
-    cmd: "$(locations) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-		filesystem: otherCcGenruleBp,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":  `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-				"outs": `["foo.out"]`,
-				"srcs": `["foo.in"]`,
-				"tools": `[
-        "//other:foo.tool",
-        "//other:other.tool",
-    ]`,
-			}),
-		},
-	})
-}
-
-func TestWithoutToolsOrToolFiles(t *testing.T) {
-	runCcGenruleTestCase(t, bp2buildTestCase{
-		description: "cc_genrule without tools or tool_files can convert successfully",
-		blueprint: `cc_genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}`,
-		expectedBazelTargets: []string{
-			makeBazelTarget("genrule", "foo", attrNameToString{
-				"cmd":  `"cp $(SRCS) $(OUTS)"`,
-				"outs": `["foo.out"]`,
-				"srcs": `["foo.in"]`,
-			}),
-		},
-	})
-}

+ 343 - 106
bp2build/genrule_conversion_test.go

@@ -16,7 +16,10 @@ package bp2build
 
 import (
 	"android/soong/android"
+	"android/soong/cc"
 	"android/soong/genrule"
+	"android/soong/java"
+	"fmt"
 	"testing"
 )
 
@@ -31,58 +34,114 @@ func runGenruleTestCase(t *testing.T, tc bp2buildTestCase) {
 	runBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
 }
 
-func TestGenruleBp2Build(t *testing.T) {
-	otherGenruleBp := map[string]string{
-		"other/Android.bp": `genrule {
+func otherGenruleBp(genruleTarget string) map[string]string {
+	return map[string]string{
+		"other/Android.bp": fmt.Sprintf(`%s {
     name: "foo.tool",
     out: ["foo_tool.out"],
     srcs: ["foo_tool.in"],
     cmd: "cp $(in) $(out)",
 }
-genrule {
+%s {
     name: "other.tool",
     out: ["other_tool.out"],
     srcs: ["other_tool.in"],
     cmd: "cp $(in) $(out)",
-}`,
+}`, genruleTarget, genruleTarget),
 	}
+}
 
-	testCases := []bp2buildTestCase{
+func TestGenruleCliVariableReplacement(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+		genDir     string
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+			genDir:     "$(GENDIR)",
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+			genDir:     "$(RULEDIR)",
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+			genDir:     "$(RULEDIR)",
+		},
 		{
-			description: "genrule with command line variable replacements",
-			blueprint: `genrule {
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+			genDir:     "$(RULEDIR)",
+		},
+	}
+
+	bp := `%s {
     name: "foo.tool",
     out: ["foo_tool.out"],
     srcs: ["foo_tool.in"],
     cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
+    bazel_module: { bp2build_available: false },
 }
 
-genrule {
+%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tools: [":foo.tool"],
     cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":   `"$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)"`,
-					"outs":  `["foo.out"]`,
-					"srcs":  `["foo.in"]`,
-					"tools": `[":foo.tool"]`,
-				}),
-				makeBazelTarget("genrule", "foo.tool", attrNameToString{
-					"cmd":  `"cp $(SRCS) $(OUTS)"`,
-					"outs": `["foo_tool.out"]`,
-					"srcs": `["foo_tool.in"]`,
-				}),
-			},
+}`
+
+	for _, tc := range testCases {
+		expectedBazelTargets := []string{
+			makeBazelTarget("genrule", "foo", attrNameToString{
+				"cmd":   fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
+				"outs":  `["foo.out"]`,
+				"srcs":  `["foo.in"]`,
+				"tools": `[":foo.tool"]`,
+			}),
+		}
+
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+				})
+		})
+	}
+}
+
+func TestGenruleLocationsLabel(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
 		},
 		{
-			description: "genrule using $(locations :label)",
-			blueprint: `genrule {
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo.tools",
     out: ["foo_tool.out", "foo_tool2.out"],
     srcs: ["foo_tool.in"],
@@ -90,144 +149,322 @@ genrule {
     bazel_module: { bp2build_available: true },
 }
 
-genrule {
+%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tools: [":foo.tools"],
     cmd: "$(locations :foo.tools) -s $(out) $(in)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":   `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
-					"outs":  `["foo.out"]`,
-					"srcs":  `["foo.in"]`,
-					"tools": `[":foo.tools"]`,
-				}),
-				makeBazelTarget("genrule", "foo.tools", attrNameToString{
-					"cmd": `"cp $(SRCS) $(OUTS)"`,
-					"outs": `[
+}`
+
+	expectedBazelTargets :=
+		[]string{
+			makeBazelTarget("genrule", "foo", attrNameToString{
+				"cmd":   `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
+				"outs":  `["foo.out"]`,
+				"srcs":  `["foo.in"]`,
+				"tools": `[":foo.tools"]`,
+			}),
+			makeBazelTarget("genrule", "foo.tools", attrNameToString{
+				"cmd": `"cp $(SRCS) $(OUTS)"`,
+				"outs": `[
         "foo_tool.out",
         "foo_tool2.out",
     ]`,
-					"srcs": `["foo_tool.in"]`,
-				}),
-			},
+				"srcs": `["foo_tool.in"]`,
+			}),
+		}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+				})
+		})
+	}
+}
+
+func TestGenruleLocationsAbsoluteLabel(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
 		},
 		{
-			description: "genrule using $(locations //absolute:label)",
-			blueprint: `genrule {
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tool_files: [":foo.tool"],
     cmd: "$(locations :foo.tool) -s $(out) $(in)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-					"outs":  `["foo.out"]`,
-					"srcs":  `["foo.in"]`,
-					"tools": `["//other:foo.tool"]`,
-				}),
-			},
-			filesystem: otherGenruleBp,
+}`
+
+	expectedBazelTargets := []string{
+		makeBazelTarget("genrule", "foo", attrNameToString{
+			"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+			"outs":  `["foo.out"]`,
+			"srcs":  `["foo.in"]`,
+			"tools": `["//other:foo.tool"]`,
+		}),
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+					filesystem:                 otherGenruleBp(tc.moduleType),
+				})
+		})
+	}
+}
+
+func TestGenruleSrcsLocationsAbsoluteLabel(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
 		},
 		{
-			description: "genrule srcs using $(locations //absolute:label)",
-			blueprint: `genrule {
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo",
     out: ["foo.out"],
     srcs: [":other.tool"],
     tool_files: [":foo.tool"],
     cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
-					"outs":  `["foo.out"]`,
-					"srcs":  `["//other:other.tool"]`,
-					"tools": `["//other:foo.tool"]`,
-				}),
-			},
-			filesystem: otherGenruleBp,
+}`
+
+	expectedBazelTargets := []string{
+		makeBazelTarget("genrule", "foo", attrNameToString{
+			"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
+			"outs":  `["foo.out"]`,
+			"srcs":  `["//other:other.tool"]`,
+			"tools": `["//other:foo.tool"]`,
+		}),
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+					filesystem:                 otherGenruleBp(tc.moduleType),
+				})
+		})
+	}
+}
+
+func TestGenruleLocationLabelShouldSubstituteFirstToolLabel(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
 		},
 		{
-			description: "genrule using $(location) label should substitute first tool label automatically",
-			blueprint: `genrule {
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     tool_files: [":foo.tool", ":other.tool"],
     cmd: "$(location) -s $(out) $(in)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":  `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-					"outs": `["foo.out"]`,
-					"srcs": `["foo.in"]`,
-					"tools": `[
+}`
+
+	expectedBazelTargets := []string{
+		makeBazelTarget("genrule", "foo", attrNameToString{
+			"cmd":  `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+			"outs": `["foo.out"]`,
+			"srcs": `["foo.in"]`,
+			"tools": `[
         "//other:foo.tool",
         "//other:other.tool",
     ]`,
-				}),
-			},
-			filesystem: otherGenruleBp,
+		})}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+					filesystem:                 otherGenruleBp(tc.moduleType),
+				})
+		})
+	}
+}
+
+func TestGenruleLocationsLabelShouldSubstituteFirstToolLabel(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
+		},
+		{
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
 		},
 		{
-			description: "genrule using $(locations) label should substitute first tool label automatically",
-			blueprint: `genrule {
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
-    tools: [":foo.tool", ":other.tool"],
+    tool_files: [":foo.tool", ":other.tool"],
     cmd: "$(locations) -s $(out) $(in)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":  `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
-					"outs": `["foo.out"]`,
-					"srcs": `["foo.in"]`,
-					"tools": `[
+}`
+
+	expectedBazelTargets := []string{
+		makeBazelTarget("genrule", "foo", attrNameToString{
+			"cmd":  `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+			"outs": `["foo.out"]`,
+			"srcs": `["foo.in"]`,
+			"tools": `[
         "//other:foo.tool",
         "//other:other.tool",
     ]`,
-				}),
-			},
-			filesystem: otherGenruleBp,
+		})}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+					filesystem:                 otherGenruleBp(tc.moduleType),
+				})
+		})
+	}
+}
+
+func TestGenruleWithoutToolsOrToolFiles(t *testing.T) {
+	testCases := []struct {
+		moduleType string
+		factory    android.ModuleFactory
+	}{
+		{
+			moduleType: "genrule",
+			factory:    genrule.GenRuleFactory,
 		},
 		{
-			description: "genrule without tools or tool_files can convert successfully",
-			blueprint: `genrule {
+			moduleType: "cc_genrule",
+			factory:    cc.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule",
+			factory:    java.GenRuleFactory,
+		},
+		{
+			moduleType: "java_genrule_host",
+			factory:    java.GenRuleFactoryHost,
+		},
+	}
+
+	bp := `%s {
     name: "foo",
     out: ["foo.out"],
     srcs: ["foo.in"],
     cmd: "cp $(in) $(out)",
     bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				makeBazelTarget("genrule", "foo", attrNameToString{
-					"cmd":  `"cp $(SRCS) $(OUTS)"`,
-					"outs": `["foo.out"]`,
-					"srcs": `["foo.in"]`,
-				}),
-			},
-		},
-	}
+}`
 
-	for _, testCase := range testCases {
-		t.Run(testCase.description, func(t *testing.T) {
-			runGenruleTestCase(t, testCase)
+	expectedBazelTargets := []string{
+		makeBazelTarget("genrule", "foo", attrNameToString{
+			"cmd":  `"cp $(SRCS) $(OUTS)"`,
+			"outs": `["foo.out"]`,
+			"srcs": `["foo.in"]`,
+		})}
+
+	for _, tc := range testCases {
+		t.Run(tc.moduleType, func(t *testing.T) {
+			runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+				bp2buildTestCase{
+					moduleTypeUnderTest:        tc.moduleType,
+					moduleTypeUnderTestFactory: tc.factory,
+					blueprint:                  fmt.Sprintf(bp, tc.moduleType),
+					expectedBazelTargets:       expectedBazelTargets,
+				})
 		})
 	}
 }
 
-func TestBp2BuildInlinesDefaults(t *testing.T) {
+func TestGenruleBp2BuildInlinesDefaults(t *testing.T) {
 	testCases := []bp2buildTestCase{
 		{
 			description: "genrule applies properties from a genrule_defaults dependency if not specified",

+ 1 - 1
genrule/genrule.go

@@ -862,7 +862,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
 		cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
 		cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
 		genDir := "$(GENDIR)"
-		if ctx.ModuleType() == "cc_genrule" {
+		if t := ctx.ModuleType(); t == "cc_genrule" || t == "java_genrule" || t == "java_genrule_host" {
 			genDir = "$(RULEDIR)"
 		}
 		cmd = strings.Replace(cmd, "$(genDir)", genDir, -1)

+ 8 - 6
java/genrule.go

@@ -24,8 +24,8 @@ func init() {
 }
 
 func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("java_genrule", genRuleFactory)
-	ctx.RegisterModuleType("java_genrule_host", genRuleFactoryHost)
+	ctx.RegisterModuleType("java_genrule", GenRuleFactory)
+	ctx.RegisterModuleType("java_genrule_host", GenRuleFactoryHost)
 }
 
 // java_genrule is a genrule that can depend on other java_* objects.
@@ -33,7 +33,7 @@ func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
 // By default a java_genrule has a single variant that will run against the device variant of its dependencies and
 // produce an output that can be used as an input to a device java rule.
 //
-// Specifying `host_supported: true` will produce two variants, one that uses device dependencie sand one that uses
+// Specifying `host_supported: true` will produce two variants, one that uses device dependencies and one that uses
 // host dependencies.  Each variant will run the command.
 //
 // Use a java_genrule instead of a genrule when it needs to depend on or be depended on by other java modules, unless
@@ -44,7 +44,7 @@ func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
 // Use a java_genrule to package generated java resources:
 //
 //     java_genrule {
-//     name: "generated_resources",
+//         name: "generated_resources",
 //         tools: [
 //             "generator",
 //             "soong_zip",
@@ -60,11 +60,12 @@ func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
 //         srcs: ["src/**/*.java"],
 //         static_libs: ["generated_resources"],
 //     }
-func genRuleFactory() android.Module {
+func GenRuleFactory() android.Module {
 	module := genrule.NewGenRule()
 
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitBazelModule(module)
 
 	return module
 }
@@ -73,11 +74,12 @@ func genRuleFactory() android.Module {
 //
 // A java_genrule_host has a single variant that will run against the host variant of its dependencies and
 // produce an output that can be used as an input to a host java rule.
-func genRuleFactoryHost() android.Module {
+func GenRuleFactoryHost() android.Module {
 	module := genrule.NewGenRule()
 
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitBazelModule(module)
 
 	return module
 }

+ 118 - 0
java/genrule_test.go

@@ -0,0 +1,118 @@
+// Copyright 2018 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 java
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+
+	"android/soong/android"
+)
+
+func testGenruleContext(config android.Config) *android.TestContext {
+	ctx := android.NewTestArchContext(config)
+	ctx.RegisterModuleType("java_genrule", GenRuleFactory)
+	ctx.Register()
+
+	return ctx
+}
+
+func TestGenruleCmd(t *testing.T) {
+	fs := map[string][]byte{
+		"tool": nil,
+		"foo":  nil,
+	}
+	bp := `
+				java_genrule {
+					name: "gen",
+					tool_files: ["tool"],
+					cmd: "$(location tool) $(in) $(out)",
+					srcs: ["foo"],
+					out: ["out"],
+				}
+			`
+	config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
+
+	ctx := testGenruleContext(config)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	if errs == nil {
+		_, errs = ctx.PrepareBuildActions(config)
+	}
+	if errs != nil {
+		t.Fatal(errs)
+	}
+
+	gen := ctx.ModuleForTests("gen", "android_common").Output("out")
+	expected := []string{"foo"}
+	if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
+		t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
+	}
+}
+
+func TestJarGenrules(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+		}
+
+		java_genrule {
+			name: "jargen",
+			tool_files: ["b.java"],
+			cmd: "$(location b.java) $(in) $(out)",
+			out: ["jargen.jar"],
+			srcs: [":foo"],
+		}
+
+		java_library {
+			name: "bar",
+			static_libs: ["jargen"],
+			srcs: ["c.java"],
+		}
+
+		java_library {
+			name: "baz",
+			libs: ["jargen"],
+			srcs: ["c.java"],
+		}
+	`)
+
+	foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
+	jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
+	bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
+	baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
+	barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
+
+	if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) {
+		t.Errorf("expected jargen inputs [%q], got %q", w, g)
+	}
+
+	if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
+		t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
+	}
+
+	if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
+		t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
+	}
+
+	if len(barCombined.Inputs) != 2 ||
+		barCombined.Inputs[0].String() != bar.Output.String() ||
+		barCombined.Inputs[1].String() != jargen.Output.String() {
+		t.Errorf("bar combined jar inputs %v is not [%q, %q]",
+			barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
+	}
+}

+ 0 - 54
java/java_test.go

@@ -997,60 +997,6 @@ func TestSharding(t *testing.T) {
 	}
 }
 
-func TestJarGenrules(t *testing.T) {
-	ctx, _ := testJava(t, `
-		java_library {
-			name: "foo",
-			srcs: ["a.java"],
-		}
-
-		java_genrule {
-			name: "jargen",
-			tool_files: ["b.java"],
-			cmd: "$(location b.java) $(in) $(out)",
-			out: ["jargen.jar"],
-			srcs: [":foo"],
-		}
-
-		java_library {
-			name: "bar",
-			static_libs: ["jargen"],
-			srcs: ["c.java"],
-		}
-
-		java_library {
-			name: "baz",
-			libs: ["jargen"],
-			srcs: ["c.java"],
-		}
-	`)
-
-	foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
-	jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
-	bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
-	baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
-	barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
-
-	if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) {
-		t.Errorf("expected jargen inputs [%q], got %q", w, g)
-	}
-
-	if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
-		t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
-	}
-
-	if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
-		t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
-	}
-
-	if len(barCombined.Inputs) != 2 ||
-		barCombined.Inputs[0].String() != bar.Output.String() ||
-		barCombined.Inputs[1].String() != jargen.Output.String() {
-		t.Errorf("bar combined jar inputs %v is not [%q, %q]",
-			barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
-	}
-}
-
 func TestExcludeFileGroupInSrcs(t *testing.T) {
 	ctx, _ := testJava(t, `
 		java_library {