From bafb6d6612e9a5ba9082337b54e5b419e583f150 Mon Sep 17 00:00:00 2001 From: Wei Li Date: Fri, 10 Dec 2021 03:14:59 -0800 Subject: [PATCH] Add the initial implementation of bp2build converter for java_library, java_library_host, java_binary_host and cc_library_host_shared so signapk tool can be built with Bazel. Test: b build //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal Test: jarsigner -verify -verbose build.bazel.examples.apex.minimal.apex Bug: 209876137 Bug: 196204358 Bug: 210158864 Bug: 210159074 Bug: 210158872 Change-Id: I855884159d25e69d8f9623792c376da820a1eb4c --- android/bazel.go | 36 +++++- bp2build/java_binary_host_conversion_test.go | 63 +++++++++++ bp2build/java_library_conversion_test.go | 57 ++++++++++ bp2build/java_library_host_conversion_test.go | 57 ++++++++++ cc/cc.go | 4 - cc/library.go | 2 + java/base.go | 15 +++ java/java.go | 107 ++++++++++++++++++ 8 files changed, 334 insertions(+), 7 deletions(-) create mode 100644 bp2build/java_binary_host_conversion_test.go create mode 100644 bp2build/java_library_conversion_test.go create mode 100644 bp2build/java_library_host_conversion_test.go diff --git a/android/bazel.go b/android/bazel.go index fd3f23e62..8c63204b3 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -15,6 +15,8 @@ package android import ( + "bufio" + "errors" "fmt" "io/ioutil" "path/filepath" @@ -206,7 +208,8 @@ var ( "build/bazel/platforms":/* recursive = */ true, "build/bazel/product_variables":/* recursive = */ true, "build/bazel_common_rules":/* recursive = */ true, - "build/make/tools":/* recursive = */ true, + // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive. + "build/make/tools":/* recursive = */ false, "build/pesto":/* recursive = */ true, // external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails @@ -237,6 +240,7 @@ var ( "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue, "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively, "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively, + "build/make/tools/signapk": Bp2BuildDefaultTrue, "build/soong": Bp2BuildDefaultTrue, "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, @@ -279,7 +283,9 @@ var ( "development/sdk": Bp2BuildDefaultTrueRecursively, "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively, "external/boringssl": Bp2BuildDefaultTrueRecursively, + "external/bouncycastle": Bp2BuildDefaultTrue, "external/brotli": Bp2BuildDefaultTrue, + "external/conscrypt": Bp2BuildDefaultTrue, "external/fmtlib": Bp2BuildDefaultTrueRecursively, "external/google-benchmark": Bp2BuildDefaultTrueRecursively, "external/googletest": Bp2BuildDefaultTrueRecursively, @@ -349,6 +355,8 @@ var ( "system/timezone/output_data": Bp2BuildDefaultTrueRecursively, "system/unwinding/libbacktrace": Bp2BuildDefaultTrueRecursively, "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively, + "tools/apksig": Bp2BuildDefaultTrue, + "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively, } // Per-module denylist to always opt modules out of both bp2build and mixed builds. @@ -404,8 +412,11 @@ var ( "lib_linker_config_proto_lite", // contains .proto sources "libprotobuf-python", // contains .proto sources - "libprotobuf-internal-protos", // we don't handle path property for fileegroups - "libprotobuf-internal-python-srcs", // we don't handle path property for fileegroups + "libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups + "libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups + "libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups + "libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups + "conscrypt", // b/210751803, we don't handle path property for filegroups "libseccomp_policy", // b/201094425: depends on func_to_syscall_nrs, which depends on py_binary, which is unsupported in mixed builds. "libfdtrack", // depends on unconverted module libunwindstack @@ -640,3 +651,22 @@ func convertWithBp2build(ctx TopDownMutatorContext) { bModule.ConvertWithBp2build(ctx) } + +// GetMainClassInManifest scans the manifest file specified in filepath and returns +// the value of attribute Main-Class in the manifest file if it exists, or returns error. +// WARNING: this is for bp2build converters of java_* modules only. +func GetMainClassInManifest(c Config, filepath string) (string, error) { + file, err := c.fs.Open(filepath) + if err != nil { + return "", err + } + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "Main-Class:") { + return strings.TrimSpace(line[len("Main-Class:"):]), nil + } + } + + return "", errors.New("Main-Class is not found.") +} diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go new file mode 100644 index 000000000..96b895876 --- /dev/null +++ b/bp2build/java_binary_host_conversion_test.go @@ -0,0 +1,63 @@ +// 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" + "android/soong/java" +) + +func runJavaBinaryHostTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + (&tc).moduleTypeUnderTest = "java_binary_host" + (&tc).moduleTypeUnderTestFactory = java.BinaryHostFactory + runBp2BuildTestCase(t, func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory) + }, tc) +} + +var fs = map[string]string{ + "test.mf": "Main-Class: com.android.test.MainClass", + "other/Android.bp": `cc_library_host_shared { + name: "jni-lib-1", + stl: "none", +}`, +} + +func TestJavaBinaryHost(t *testing.T) { + runJavaBinaryHostTestCase(t, bp2buildTestCase{ + description: "java_binary_host with srcs, exclude_srcs, jni_libs and manifest.", + filesystem: fs, + blueprint: `java_binary_host { + name: "java-binary-host-1", + srcs: ["a.java", "b.java"], + exclude_srcs: ["b.java"], + manifest: "test.mf", + jni_libs: ["jni-lib-1"], + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("java_binary", "java-binary-host-1", attrNameToString{ + "srcs": `["a.java"]`, + "main_class": `"com.android.test.MainClass"`, + "deps": `["//other:jni-lib-1"]`, + "jvm_flags": `["-Djava.library.path=$${RUNPATH}other"]`, + }), + }, + }) +} diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go new file mode 100644 index 000000000..5c65ec230 --- /dev/null +++ b/bp2build/java_library_conversion_test.go @@ -0,0 +1,57 @@ +// 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/java" +) + +func runJavaLibraryTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + (&tc).moduleTypeUnderTest = "java_library" + (&tc).moduleTypeUnderTestFactory = java.LibraryFactory + runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc) +} + +func TestJavaLibrary(t *testing.T) { + runJavaLibraryTestCase(t, bp2buildTestCase{ + description: "java_library with srcs, exclude_srcs and libs", + blueprint: `java_library { + name: "java-lib-1", + srcs: ["a.java", "b.java"], + exclude_srcs: ["b.java"], + libs: ["java-lib-2"], + bazel_module: { bp2build_available: true }, +} + +java_library { + name: "java-lib-2", + srcs: ["b.java"], + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("java_library", "java-lib-1", attrNameToString{ + "srcs": `["a.java"]`, + "deps": `[":java-lib-2"]`, + }), + makeBazelTarget("java_library", "java-lib-2", attrNameToString{ + "srcs": `["b.java"]`, + }), + }, + }) +} diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go new file mode 100644 index 000000000..6ac82dbd2 --- /dev/null +++ b/bp2build/java_library_host_conversion_test.go @@ -0,0 +1,57 @@ +// 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/java" +) + +func runJavaLibraryHostTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + (&tc).moduleTypeUnderTest = "java_library_host" + (&tc).moduleTypeUnderTestFactory = java.LibraryHostFactory + runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc) +} + +func TestJavaLibraryHost(t *testing.T) { + runJavaLibraryHostTestCase(t, bp2buildTestCase{ + description: "java_library_host with srcs, exclude_srcs and libs", + blueprint: `java_library_host { + name: "java-lib-host-1", + srcs: ["a.java", "b.java"], + exclude_srcs: ["b.java"], + libs: ["java-lib-host-2"], + bazel_module: { bp2build_available: true }, +} + +java_library_host { + name: "java-lib-host-2", + srcs: ["c.java"], + bazel_module: { bp2build_available: true }, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("java_library", "java-lib-host-1", attrNameToString{ + "srcs": `["a.java"]`, + "deps": `[":java-lib-host-2"]`, + }), + makeBazelTarget("java_library", "java-lib-host-2", attrNameToString{ + "srcs": `["c.java"]`, + }), + }, + }) +} diff --git a/cc/cc.go b/cc/cc.go index 0904bd965..7211359d9 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -3458,10 +3458,6 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } else if c.Object() { objectBp2Build(ctx, c) } else if c.CcLibrary() { - if c.hod == android.HostSupported { - return - } - static := c.BuildStaticVariant() shared := c.BuildSharedVariant() prebuilt := c.IsPrebuilt() diff --git a/cc/library.go b/cc/library.go index aec699cbb..216c12409 100644 --- a/cc/library.go +++ b/cc/library.go @@ -447,6 +447,8 @@ func LibraryHostSharedFactory() android.Module { module, library := NewLibrary(android.HostSupported) library.BuildOnlyShared() module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType} + module.bazelable = true + module.bazelHandler = &ccLibraryBazelHandler{module: module} return module.Init() } diff --git a/java/base.go b/java/base.go index c0da21523..c45ef641e 100644 --- a/java/base.go +++ b/java/base.go @@ -372,6 +372,7 @@ type Module struct { android.DefaultableModuleBase android.ApexModuleBase android.SdkBase + android.BazelModuleBase // Functionality common to Module and Import. embeddableInModuleAndImport @@ -1952,3 +1953,17 @@ type ModuleWithStem interface { } var _ ModuleWithStem = (*Module)(nil) + +func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { + switch ctx.ModuleType() { + case "java_library", "java_library_host": + if lib, ok := ctx.Module().(*Library); ok { + javaLibraryBp2Build(ctx, lib) + } + case "java_binary_host": + if binary, ok := ctx.Module().(*Binary); ok { + javaBinaryHostBp2Build(ctx, binary) + } + } + +} diff --git a/java/java.go b/java/java.go index e7b1f4fe3..f77c694ba 100644 --- a/java/java.go +++ b/java/java.go @@ -21,7 +21,9 @@ package java import ( "fmt" "path/filepath" + "strings" + "android/soong/bazel" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -756,6 +758,7 @@ func LibraryFactory() android.Module { android.InitApexModule(module) android.InitSdkAwareModule(module) + android.InitBazelModule(module) InitJavaModule(module, android.HostAndDeviceSupported) return module } @@ -778,6 +781,7 @@ func LibraryHostFactory() android.Module { android.InitApexModule(module) android.InitSdkAwareModule(module) + android.InitBazelModule(module) InitJavaModule(module, android.HostSupported) return module } @@ -1228,6 +1232,8 @@ func BinaryFactory() android.Module { android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst) android.InitDefaultableModule(module) + android.InitBazelModule(module) + return module } @@ -1245,6 +1251,7 @@ func BinaryHostFactory() android.Module { android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst) android.InitDefaultableModule(module) + android.InitBazelModule(module) return module } @@ -1961,3 +1968,103 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, clcMap.AddContextMap(dep.ClassLoaderContexts(), depName) } } + +type javaLibraryAttributes struct { + Srcs bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Javacopts bazel.StringListAttribute +} + +func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { + srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)) + attrs := &javaLibraryAttributes{ + Srcs: srcs, + } + + if m.properties.Javacflags != nil { + attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags) + } + + if m.properties.Libs != nil { + attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Libs)) + } + + props := bazel.BazelTargetModuleProperties{ + Rule_class: "java_library", + Bzl_load_location: "//build/bazel/rules/java:library.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) +} + +type javaBinaryHostAttributes struct { + Srcs bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Main_class string + Jvm_flags bazel.StringListAttribute +} + +// JavaBinaryHostBp2Build is for java_binary_host bp2build. +func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { + mainClass := "" + if m.binaryProperties.Main_class != nil { + mainClass = *m.binaryProperties.Main_class + } + if m.properties.Manifest != nil { + mainClassInManifest, err := android.GetMainClassInManifest(ctx.Config(), android.PathForModuleSrc(ctx, *m.properties.Manifest).String()) + if err != nil { + return + } + mainClass = mainClassInManifest + } + srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)) + attrs := &javaBinaryHostAttributes{ + Srcs: srcs, + Main_class: mainClass, + } + + // Attribute deps + deps := []string{} + if m.properties.Static_libs != nil { + deps = append(deps, m.properties.Static_libs...) + } + if m.binaryProperties.Jni_libs != nil { + deps = append(deps, m.binaryProperties.Jni_libs...) + } + if len(deps) > 0 { + attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, deps)) + } + + // Attribute jvm_flags + if m.binaryProperties.Jni_libs != nil { + jniLibPackages := map[string]bool{} + for _, jniLibLabel := range android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs).Includes { + jniLibPackage := jniLibLabel.Label + indexOfColon := strings.Index(jniLibLabel.Label, ":") + if indexOfColon > 0 { + // JNI lib from other package + jniLibPackage = jniLibLabel.Label[2:indexOfColon] + } else if indexOfColon == 0 { + // JNI lib in the same package of java_binary + packageOfCurrentModule := m.GetBazelLabel(ctx, m) + jniLibPackage = packageOfCurrentModule[2:strings.Index(packageOfCurrentModule, ":")] + } + if _, inMap := jniLibPackages[jniLibPackage]; !inMap { + jniLibPackages[jniLibPackage] = true + } + } + jniLibPaths := []string{} + for jniLibPackage, _ := range jniLibPackages { + // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH + jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage) + } + attrs.Jvm_flags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")}) + } + + props := bazel.BazelTargetModuleProperties{ + Rule_class: "java_binary", + } + + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) +}