diff --git a/android/arch.go b/android/arch.go index 7f9abc6b2..af3919cfa 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1072,19 +1072,30 @@ func getCommonTargets(targets []Target) []Target { return ret } +func preferTargets(targets []Target, filters ...string) []Target { + for _, filter := range filters { + buildTargets := filterMultilibTargets(targets, filter) + if len(buildTargets) > 0 { + return buildTargets + } + } + return nil +} + // Use the module multilib setting to select one or more targets from a target list func decodeMultilib(multilib string, targets []Target, prefer32 bool) ([]Target, error) { buildTargets := []Target{} - if multilib == "first" { - if prefer32 { - multilib = "prefer32" - } else { - multilib = "prefer64" - } - } + switch multilib { case "common": - buildTargets = append(buildTargets, getCommonTargets(targets)...) + buildTargets = getCommonTargets(targets) + case "common_first": + buildTargets = getCommonTargets(targets) + if prefer32 { + buildTargets = append(buildTargets, preferTargets(targets, "lib32", "lib64")...) + } else { + buildTargets = append(buildTargets, preferTargets(targets, "lib64", "lib32")...) + } case "both": if prefer32 { buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...) @@ -1097,16 +1108,14 @@ func decodeMultilib(multilib string, targets []Target, prefer32 bool) ([]Target, buildTargets = filterMultilibTargets(targets, "lib32") case "64": buildTargets = filterMultilibTargets(targets, "lib64") + case "first": + if prefer32 { + buildTargets = preferTargets(targets, "lib32", "lib64") + } else { + buildTargets = preferTargets(targets, "lib64", "lib32") + } case "prefer32": - buildTargets = filterMultilibTargets(targets, "lib32") - if len(buildTargets) == 0 { - buildTargets = filterMultilibTargets(targets, "lib64") - } - case "prefer64": - buildTargets = filterMultilibTargets(targets, "lib64") - if len(buildTargets) == 0 { - buildTargets = filterMultilibTargets(targets, "lib32") - } + buildTargets = preferTargets(targets, "lib32", "lib64") default: return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`, multilib) diff --git a/android/module.go b/android/module.go index e6766a346..865764f58 100644 --- a/android/module.go +++ b/android/module.go @@ -248,10 +248,11 @@ type hostAndDeviceProperties struct { type Multilib string const ( - MultilibBoth Multilib = "both" - MultilibFirst Multilib = "first" - MultilibCommon Multilib = "common" - MultilibDefault Multilib = "" + MultilibBoth Multilib = "both" + MultilibFirst Multilib = "first" + MultilibCommon Multilib = "common" + MultilibCommonFirst Multilib = "common_first" + MultilibDefault Multilib = "" ) type HostOrDeviceSupported int diff --git a/java/androidmk.go b/java/androidmk.go index 2e676399a..f52d5e957 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -95,28 +95,35 @@ func (prebuilt *Import) AndroidMk() android.AndroidMkData { } func (binary *Binary) AndroidMk() android.AndroidMkData { - return android.AndroidMkData{ - Class: "JAVA_LIBRARIES", - OutputFile: android.OptionalPathForPath(binary.implementationJarFile), - Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", - Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { - android.WriteAndroidMkData(w, data) - fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)") - fmt.Fprintln(w, "include $(CLEAR_VARS)") - fmt.Fprintln(w, "LOCAL_MODULE := "+name) - fmt.Fprintln(w, "LOCAL_MODULE_CLASS := EXECUTABLES") - if strings.Contains(prefix, "HOST_") { - fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true") - } - fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false") - fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", binary.wrapperFile.String()) - fmt.Fprintln(w, "include $(BUILD_PREBUILT)") + if !binary.isWrapperVariant { + return android.AndroidMkData{ + Class: "JAVA_LIBRARIES", + OutputFile: android.OptionalPathForPath(binary.implementationJarFile), + Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", + Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + android.WriteAndroidMkData(w, data) - // Ensure that the wrapper script timestamp is always updated when the jar is updated - fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)") - fmt.Fprintln(w, "jar_installed_module :=") - }, + fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)") + }, + } + } else { + return android.AndroidMkData{ + Class: "EXECUTABLES", + OutputFile: android.OptionalPathForPath(binary.wrapperFile), + Extra: []android.AndroidMkExtraFunc{ + func(w io.Writer, outputFile android.Path) { + fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false") + }, + }, + Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + android.WriteAndroidMkData(w, data) + + // Ensure that the wrapper script timestamp is always updated when the jar is updated + fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)") + fmt.Fprintln(w, "jar_installed_module :=") + }, + } } } diff --git a/java/java.go b/java/java.go index 0a47db02e..0e54e3c61 100644 --- a/java/java.go +++ b/java/java.go @@ -1014,6 +1014,8 @@ type Binary struct { binaryProperties binaryProperties + isWrapperVariant bool + wrapperFile android.SourcePath binaryFile android.OutputPath } @@ -1023,21 +1025,32 @@ func (j *Binary) HostToolPath() android.OptionalPath { } func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { - j.Library.GenerateAndroidBuildActions(ctx) - - // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by - // another build rule before the jar has been installed. - if String(j.binaryProperties.Wrapper) != "" { - j.wrapperFile = android.PathForModuleSrc(ctx, String(j.binaryProperties.Wrapper)).SourcePath + if ctx.Arch().ArchType == android.Common { + // Compile the jar + j.Library.GenerateAndroidBuildActions(ctx) } else { - j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh") + // Handle the binary wrapper + j.isWrapperVariant = true + + if String(j.binaryProperties.Wrapper) != "" { + j.wrapperFile = android.PathForModuleSrc(ctx, String(j.binaryProperties.Wrapper)).SourcePath + } else { + j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh") + } + + // Depend on the installed jar so that the wrapper doesn't get executed by + // another build rule before the jar has been installed. + jarFile := ctx.PrimaryModule().(*Binary).installFile + + j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"), + ctx.ModuleName(), j.wrapperFile, jarFile) } - j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"), - ctx.ModuleName(), j.wrapperFile, j.installFile) } func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { - j.deps(ctx) + if ctx.Arch().ArchType == android.Common { + j.deps(ctx) + } } func BinaryFactory() android.Module { @@ -1049,7 +1062,8 @@ func BinaryFactory() android.Module { &module.Module.protoProperties, &module.binaryProperties) - InitJavaModule(module, android.HostAndDeviceSupported) + android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst) + android.InitDefaultableModule(module) return module } @@ -1062,7 +1076,8 @@ func BinaryHostFactory() android.Module { &module.Module.protoProperties, &module.binaryProperties) - InitJavaModule(module, android.HostSupported) + android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst) + android.InitDefaultableModule(module) return module } diff --git a/java/java_test.go b/java/java_test.go index 58b27c30f..78fbd41e0 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -62,6 +62,7 @@ func testContext(config android.Config, bp string, ctx := android.NewTestArchContext() ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory)) + ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory)) ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory(true))) ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory)) ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(ImportFactory)) @@ -147,6 +148,8 @@ func testContext(config android.Config, bp string, // For framework-res, which is an implicit dependency for framework "AndroidManifest.xml": nil, "build/target/product/security/testkey": nil, + + "build/soong/scripts/jar-wrapper.sh": nil, } for k, v := range fs { @@ -159,6 +162,7 @@ func testContext(config android.Config, bp string, } func run(t *testing.T, ctx *android.TestContext, config android.Config) { + t.Helper() _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) fail(t, errs) _, errs = ctx.PrepareBuildActions(config) @@ -166,6 +170,7 @@ func run(t *testing.T, ctx *android.TestContext, config android.Config) { } func testJava(t *testing.T, bp string) *android.TestContext { + t.Helper() config := testConfig(nil) ctx := testContext(config, bp, nil) run(t, ctx, config) @@ -250,6 +255,35 @@ func TestArchSpecific(t *testing.T) { } } +func TestBinary(t *testing.T) { + ctx := testJava(t, ` + java_library_host { + name: "foo", + srcs: ["a.java"], + } + + java_binary_host { + name: "bar", + srcs: ["b.java"], + static_libs: ["foo"], + } + `) + + buildOS := android.BuildOs.String() + + bar := ctx.ModuleForTests("bar", buildOS+"_common") + barJar := bar.Output("bar.jar").Output.String() + barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64") + barWrapperDeps := barWrapper.Output("bar").Implicits.Strings() + + // Test that the install binary wrapper depends on the installed jar file + if len(barWrapperDeps) != 1 || barWrapperDeps[0] != barJar { + t.Errorf("expected binary wrapper implicits [%q], got %v", + barJar, barWrapperDeps) + } + +} + var classpathTestcases = []struct { name string moduleType string @@ -831,6 +865,7 @@ func TestJarGenrules(t *testing.T) { } func fail(t *testing.T, errs []error) { + t.Helper() if len(errs) > 0 { for _, err := range errs { t.Error(err)