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

Commit 1988ccf5 authored by Dennis Shen's avatar Dennis Shen Committed by Gerrit Code Review
Browse files

Merge "Implement rust_aconfig_library" into main

parents b6e0a64b 457ddef2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ bootstrap_go_package {
        "soong-bazel",
        "soong-android",
        "soong-java",
        "soong-rust",
    ],
    srcs: [
        "aconfig_declarations.go",
@@ -24,6 +25,7 @@ bootstrap_go_package {
        "init.go",
        "java_aconfig_library.go",
        "testing.go",
        "rust_aconfig_library.go",
    ],
    testSrcs: [
        "aconfig_declarations_test.go",
+2 −1
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@ package aconfig
import (
	"android/soong/android"
	"fmt"
	"github.com/google/blueprint"
	"strings"

	"github.com/google/blueprint"
)

type DeclarationsModule struct {
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ package aconfig

import (
	"android/soong/android"

	"github.com/google/blueprint"
)

@@ -70,6 +71,20 @@ var (
			},
		}, "gendir")

	rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
		blueprint.RuleParams{
			Command: `rm -rf ${gendir}` +
				` && mkdir -p ${gendir}` +
				` && ${aconfig} create-rust-lib` +
				`    --mode ${mode}` +
				`    --cache ${in}` +
				`    --out ${gendir}`,
			CommandDeps: []string{
				"$aconfig",
				"$soong_zip",
			},
		}, "gendir", "mode")

	// For all_aconfig_declarations
	allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump",
		blueprint.RuleParams{
@@ -92,5 +107,6 @@ func registerBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
	ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
	ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
	ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
	ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
}
+83 −0
Original line number Diff line number Diff line
package aconfig

import (
	"android/soong/android"
	"android/soong/rust"
	"fmt"

	"github.com/google/blueprint"
)

type rustDeclarationsTagType struct {
	blueprint.BaseDependencyTag
}

var rustDeclarationsTag = rustDeclarationsTagType{}

type RustAconfigLibraryProperties struct {
	// name of the aconfig_declarations module to generate a library for
	Aconfig_declarations string
}

type aconfigDecorator struct {
	*rust.BaseSourceProvider

	Properties RustAconfigLibraryProperties
}

func NewRustAconfigLibrary(hod android.HostOrDeviceSupported) (*rust.Module, *aconfigDecorator) {
	aconfig := &aconfigDecorator{
		BaseSourceProvider: rust.NewSourceProvider(),
		Properties:         RustAconfigLibraryProperties{},
	}

	module := rust.NewSourceProviderModule(android.HostAndDeviceSupported, aconfig, false, false)
	return module, aconfig
}

// rust_aconfig_library generates aconfig rust code from the provided aconfig declaration. This module type will
// create library variants that can be used as a crate dependency by adding it to the rlibs, dylibs, and rustlibs
// properties of other modules.
func RustAconfigLibraryFactory() android.Module {
	module, _ := NewRustAconfigLibrary(android.HostAndDeviceSupported)
	return module.Init()
}

func (a *aconfigDecorator) SourceProviderProps() []interface{} {
	return append(a.BaseSourceProvider.SourceProviderProps(), &a.Properties)
}

func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
	generatedDir := android.PathForModuleGen(ctx)
	generatedSource := android.PathForModuleGen(ctx, "src", "lib.rs")

	declarationsModules := ctx.GetDirectDepsWithTag(rustDeclarationsTag)

	if len(declarationsModules) != 1 {
		panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
	}
	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)

	ctx.Build(pctx, android.BuildParams{
		Rule:  rustRule,
		Input: declarations.IntermediatePath,
		Outputs: []android.WritablePath{
			generatedSource,
		},
		Description: "rust_aconfig_library",
		Args: map[string]string{
			"gendir": generatedDir.String(),
			// TODO: Add test mode
			"mode": "production",
		},
	})
	a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
	return generatedSource
}

func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps {
	deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps)
	deps.Rustlibs = append(deps.Rustlibs, "libflags_rust")
	ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
	return deps
}
+60 −0
Original line number Diff line number Diff line
package aconfig

import (
	"android/soong/android"
	"android/soong/rust"
	"fmt"
	"testing"
)

func TestRustAconfigLibrary(t *testing.T) {
	result := android.GroupFixturePreparers(
		PrepareForTestWithAconfigBuildComponents,
		rust.PrepareForTestWithRustIncludeVndk,
		android.PrepareForTestWithArchMutator,
		android.PrepareForTestWithDefaults,
		android.PrepareForTestWithPrebuilts,
	).
		ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
		RunTestWithBp(t, fmt.Sprintf(`
			rust_library {
				name: "libflags_rust", // test mock
				crate_name: "flags_rust",
				srcs: ["lib.rs"],
			}
			aconfig_declarations {
				name: "my_aconfig_declarations",
				package: "com.example.package",
				srcs: ["foo.aconfig"],
			}

			rust_aconfig_library {
				name: "libmy_rust_aconfig_library",
				crate_name: "my_rust_aconfig_library",
				aconfig_declarations: "my_aconfig_declarations",
			}
		`))

	sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
	rule := sourceVariant.Rule("rust_aconfig_library")
	android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")

	dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
	rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
	rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")

	variants := []android.TestingModule{
		dylibVariant,
		rlibDylibStdVariant,
		rlibRlibStdVariant,
	}

	for _, variant := range variants {
		android.AssertStringEquals(
			t,
			"dylib variant builds from generated rust code",
			"out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
			variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
		)
	}
}