Convert libprotobuf to Bazel
Since this is a one-off just for building libprotobuf that will be removed when we handle cargo output more generically (b/297364081), I didn't write a unit test for this CL.
Test: b build //external/rust/crates/protobuf:libprotobuf
Bug: 295925256
Change-Id: I00cf44d54be27a09c184a96c13b250a2e54e2d10
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index dda125a..7163328 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -513,6 +513,7 @@
"libprotobuf_support",
"libtinytemplate",
"libserde_json",
+ "libprotobuf",
// ext
"tagsoup",
diff --git a/bp2build/rust_library_conversion_test.go b/bp2build/rust_library_conversion_test.go
index 296f57e..b860b76 100644
--- a/bp2build/rust_library_conversion_test.go
+++ b/bp2build/rust_library_conversion_test.go
@@ -16,6 +16,36 @@
ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
}
+func TestLibProtobuf(t *testing.T) {
+ runRustLibraryTestCase(t, Bp2buildTestCase{
+ Dir: "external/rust/crates/foo",
+ Blueprint: "",
+ Filesystem: map[string]string{
+ "external/rust/crates/foo/src/lib.rs": "",
+ "external/rust/crates/foo/Android.bp": `
+rust_library_host {
+ name: "libprotobuf",
+ crate_name: "protobuf",
+ srcs: ["src/lib.rs"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ },
+ ExpectedBazelTargets: []string{
+ // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+ makeBazelTargetHostOrDevice("rust_library", "libprotobuf", AttrNameToString{
+ "crate_name": `"protobuf"`,
+ "srcs": `["src/lib.rs"]`,
+ "deps": `[":libprotobuf_build_script"]`,
+ }, android.HostSupported),
+ makeBazelTargetHostOrDevice("cargo_build_script", "libprotobuf_build_script", AttrNameToString{
+ "srcs": `["build.rs"]`,
+ }, android.HostSupported),
+ },
+ },
+ )
+}
+
func TestRustLibrary(t *testing.T) {
expectedAttrs := AttrNameToString{
"crate_name": `"foo"`,
diff --git a/rust/library.go b/rust/library.go
index da2209a..3f031c1 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -812,11 +812,21 @@
func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
lib := m.compiler.(*libraryDecorator)
+
srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
+
deps := android.BazelLabelForModuleDeps(ctx, append(
lib.baseCompiler.Properties.Rustlibs,
lib.baseCompiler.Properties.Rlibs...,
))
+
+ cargoBuildScript := cargoBuildScriptBp2build(ctx, m)
+ if cargoBuildScript != nil {
+ deps.Add(&bazel.Label{
+ Label: ":" + *cargoBuildScript,
+ })
+ }
+
procMacroDeps := android.BazelLabelForModuleDeps(ctx, lib.baseCompiler.Properties.Proc_macros)
var rustcFLags []string
@@ -870,3 +880,73 @@
restriction,
)
}
+
+type cargoBuildScriptAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Edition bazel.StringAttribute
+ Version bazel.StringAttribute
+}
+
+func cargoBuildScriptBp2build(ctx android.TopDownMutatorContext, m *Module) *string {
+ // Soong treats some crates like libprotobuf as special in that they have
+ // cargo build script ran to produce an out folder and check it into AOSP
+ // For example, https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/out/
+ // is produced by cargo build script https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/build.rs
+ // The out folder is then fed into `rust_library` by a genrule
+ // https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/Android.bp;l=22
+ // This allows Soong to decouple from cargo completely.
+
+ // Soong decouples from cargo so that it has control over cc compilation.
+ // https://cs.android.com/android/platform/superproject/main/+/main:development/scripts/cargo2android.py;l=1033-1041;drc=8449944a50a0445a5ecaf9b7aed12608c81bf3f1
+ // generates a `cc_library_static` module to have custom cc flags.
+ // Since bp2build will convert the cc modules to cc targets which include the cflags,
+ // Bazel does not need to have this optimization.
+
+ // Performance-wise: rust_library -> cargo_build_script vs rust_library -> genrule (like Soong)
+ // don't have any major difference in build time in Bazel. So using cargo_build_script does not slow
+ // down the build.
+
+ // The benefit of using `cargo_build_script` here is that it would take care of setting correct
+ // `OUT_DIR` for us - similar to what Soong does here
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/rust/builder.go;l=202-218;drc=f29ca58e88c5846bbe8955e5192135e5ab4f14a1
+
+ // TODO(b/297364081): cargo2android.py has logic for when generate/not cc_library_static and out directory
+ // bp2build might be able use the same logic for when to use `cargo_build_script`.
+ // For now, we're building libprotobuf_build_script as a one-off until we have a more principled solution
+ if m.Name() != "libprotobuf" {
+ return nil
+ }
+
+ lib := m.compiler.(*libraryDecorator)
+
+ name := m.Name() + "_build_script"
+ attrs := &cargoBuildScriptAttributes{
+ Srcs: bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(ctx, []string{"build.rs"}),
+ ),
+ Edition: bazel.StringAttribute{
+ Value: lib.baseCompiler.Properties.Edition,
+ },
+ Version: bazel.StringAttribute{
+ Value: lib.baseCompiler.Properties.Cargo_pkg_version,
+ },
+ }
+
+ // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
+ var restriction bazel.BoolAttribute
+ restriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
+
+ ctx.CreateBazelTargetModuleWithRestrictions(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cargo_build_script",
+ Bzl_load_location: "@rules_rust//cargo:cargo_build_script.bzl",
+ },
+ android.CommonAttributes{
+ Name: name,
+ },
+ attrs,
+ restriction,
+ )
+
+ return &name
+}