Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b84678f authored by Vinh Tran's avatar Vinh Tran
Browse files

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
parent c1a6ceef
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -513,6 +513,7 @@ var (
		"libprotobuf_support",
		"libtinytemplate",
		"libserde_json",
		"libprotobuf",

		// ext
		"tagsoup",
+30 −0
Original line number Diff line number Diff line
@@ -16,6 +16,36 @@ func registerRustLibraryModuleTypes(ctx android.RegistrationContext) {
	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"`,
+80 −0
Original line number Diff line number Diff line
@@ -812,11 +812,21 @@ type rustLibraryAttributes struct {

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 @@ func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
		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
}