Merge "rust: Pass cc static libs to rustc."
diff --git a/android/apex.go b/android/apex.go
index b87ff09..6bb0751 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -749,74 +749,69 @@
}
return list
}(map[string]int{
- "adbd": 30,
- "android.net.ipsec.ike": 30,
- "androidx-constraintlayout_constraintlayout-solver": 30,
- "androidx.annotation_annotation": 28,
- "androidx.arch.core_core-common": 28,
- "androidx.collection_collection": 28,
- "androidx.lifecycle_lifecycle-common": 28,
- "apache-commons-compress": 29,
- "bouncycastle_ike_digests": 30,
- "brotli-java": 29,
- "captiveportal-lib": 28,
- "flatbuffer_headers": 30,
- "framework-permission": 30,
- "framework-statsd": 30,
- "gemmlowp_headers": 30,
- "ike-internals": 30,
- "kotlinx-coroutines-android": 28,
- "kotlinx-coroutines-core": 28,
- "libadb_crypto": 30,
- "libadb_pairing_auth": 30,
- "libadb_pairing_connection": 30,
- "libadb_pairing_server": 30,
- "libadb_protos": 30,
- "libadb_tls_connection": 30,
- "libadbconnection_client": 30,
- "libadbconnection_server": 30,
- "libadbd_core": 30,
- "libadbd_services": 30,
- "libadbd": 30,
- "libapp_processes_protos_lite": 30,
- "libasyncio": 30,
- "libbrotli": 30,
- "libbuildversion": 30,
- "libcrypto_static": 30,
- "libcrypto_utils": 30,
- "libdiagnose_usb": 30,
- "libeigen": 30,
- "liblz4": 30,
- "libmdnssd": 30,
- "libneuralnetworks_common": 30,
- "libneuralnetworks_headers": 30,
- "libneuralnetworks": 30,
- "libprocpartition": 30,
- "libprotobuf-java-lite": 30,
- "libprotoutil": 30,
- "libqemu_pipe": 30,
- "libstats_jni": 30,
- "libstatslog_statsd": 30,
- "libstatsmetadata": 30,
- "libstatspull": 30,
- "libstatssocket": 30,
- "libsync": 30,
- "libtextclassifier_hash_headers": 30,
- "libtextclassifier_hash_static": 30,
- "libtflite_kernel_utils": 30,
- "libwatchdog": 29,
- "libzstd": 30,
- "metrics-constants-protos": 28,
- "net-utils-framework-common": 29,
- "permissioncontroller-statsd": 28,
- "philox_random_headers": 30,
- "philox_random": 30,
- "service-permission": 30,
- "service-statsd": 30,
- "statsd-aidl-ndk_platform": 30,
- "statsd": 30,
- "tensorflow_headers": 30,
- "xz-java": 29,
+ "adbd": 30,
+ "android.net.ipsec.ike": 30,
+ "apache-commons-compress": 29,
+ "bouncycastle_ike_digests": 30,
+ "brotli-java": 29,
+ "captiveportal-lib": 28,
+ "flatbuffer_headers": 30,
+ "framework-permission": 30,
+ "framework-statsd": 30,
+ "gemmlowp_headers": 30,
+ "ike-internals": 30,
+ "kotlinx-coroutines-android": 28,
+ "kotlinx-coroutines-core": 28,
+ "libadb_crypto": 30,
+ "libadb_pairing_auth": 30,
+ "libadb_pairing_connection": 30,
+ "libadb_pairing_server": 30,
+ "libadb_protos": 30,
+ "libadb_tls_connection": 30,
+ "libadbconnection_client": 30,
+ "libadbconnection_server": 30,
+ "libadbd_core": 30,
+ "libadbd_services": 30,
+ "libadbd": 30,
+ "libapp_processes_protos_lite": 30,
+ "libasyncio": 30,
+ "libbrotli": 30,
+ "libbuildversion": 30,
+ "libcrypto_static": 30,
+ "libcrypto_utils": 30,
+ "libdiagnose_usb": 30,
+ "libeigen": 30,
+ "liblz4": 30,
+ "libmdnssd": 30,
+ "libneuralnetworks_common": 30,
+ "libneuralnetworks_headers": 30,
+ "libneuralnetworks": 30,
+ "libprocpartition": 30,
+ "libprotobuf-java-lite": 30,
+ "libprotoutil": 30,
+ "libqemu_pipe": 30,
+ "libstats_jni": 30,
+ "libstatslog_statsd": 30,
+ "libstatsmetadata": 30,
+ "libstatspull": 30,
+ "libstatssocket": 30,
+ "libsync": 30,
+ "libtextclassifier_hash_headers": 30,
+ "libtextclassifier_hash_static": 30,
+ "libtflite_kernel_utils": 30,
+ "libwatchdog": 29,
+ "libzstd": 30,
+ "metrics-constants-protos": 28,
+ "net-utils-framework-common": 29,
+ "permissioncontroller-statsd": 28,
+ "philox_random_headers": 30,
+ "philox_random": 30,
+ "service-permission": 30,
+ "service-statsd": 30,
+ "statsd-aidl-ndk_platform": 30,
+ "statsd": 30,
+ "tensorflow_headers": 30,
+ "xz-java": 29,
})
// Function called while walking an APEX's payload dependencies.
diff --git a/android/arch.go b/android/arch.go
index baee9be..b277381 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -436,7 +436,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
base := module.base()
@@ -576,7 +576,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
base := module.base()
@@ -647,10 +647,11 @@
}
// Recovery is always the primary architecture, filter out any other architectures.
+ // Common arch is also allowed
if image == RecoveryVariation {
primaryArch := mctx.Config().DevicePrimaryArchType()
- targets = filterToArch(targets, primaryArch)
- multiTargets = filterToArch(multiTargets, primaryArch)
+ targets = filterToArch(targets, primaryArch, Common)
+ multiTargets = filterToArch(multiTargets, primaryArch, Common)
}
// If there are no supported targets disable the module.
@@ -719,10 +720,17 @@
}
// filterToArch takes a list of Targets and an ArchType, and returns a modified list that contains
-// only Targets that have the specified ArchType.
-func filterToArch(targets []Target, arch ArchType) []Target {
+// only Targets that have the specified ArchTypes.
+func filterToArch(targets []Target, archs ...ArchType) []Target {
for i := 0; i < len(targets); i++ {
- if targets[i].Arch.ArchType != arch {
+ found := false
+ for _, arch := range archs {
+ if targets[i].Arch.ArchType == arch {
+ found = true
+ break
+ }
+ }
+ if !found {
targets = append(targets[:i], targets[i+1:]...)
i--
}
diff --git a/android/config.go b/android/config.go
index 8090889..e0f3a91 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1624,21 +1624,33 @@
func splitConfiguredJarPair(str string) (string, string, error) {
pair := strings.SplitN(str, ":", 2)
if len(pair) == 2 {
- return pair[0], pair[1], nil
+ apex := pair[0]
+ jar := pair[1]
+ if apex == "" {
+ return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
+ }
+ return apex, jar, nil
} else {
return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
}
}
-// CreateTestConfiguredJarList is a function to create ConfiguredJarList for
-// tests.
+// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
- apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
+ // Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
+ // a json list of strings and then unmarshalling into a ConfiguredJarList instance.
+ b, err := json.Marshal(list)
if err != nil {
panic(err)
}
- return ConfiguredJarList{apexes, jars}
+ var jarList ConfiguredJarList
+ err = json.Unmarshal(b, &jarList)
+ if err != nil {
+ panic(err)
+ }
+
+ return jarList
}
// EmptyConfiguredJarList returns an empty jar list.
diff --git a/android/config_test.go b/android/config_test.go
index 7bfc800..a11115d 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -100,6 +100,22 @@
assertStringEquals(t, "apex1:jarA", list1.String())
})
+ t.Run("create invalid - missing apex", func(t *testing.T) {
+ defer func() {
+ err := recover().(error)
+ assertStringEquals(t, "malformed (apex, jar) pair: 'jarA', expected format: <apex>:<jar>", err.Error())
+ }()
+ CreateTestConfiguredJarList([]string{"jarA"})
+ })
+
+ t.Run("create invalid - empty apex", func(t *testing.T) {
+ defer func() {
+ err := recover().(error)
+ assertStringEquals(t, "invalid apex '' in <apex>:<jar> pair ':jarA', expected format: <apex>:<jar>", err.Error())
+ }()
+ CreateTestConfiguredJarList([]string{":jarA"})
+ })
+
list2 := list1.Append("apex2", "jarB")
t.Run("append", func(t *testing.T) {
assertStringEquals(t, "apex1:jarA,apex2:jarB", list2.String())
diff --git a/android/filegroup.go b/android/filegroup.go
index 3d1bbc5..7a6cc4f 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -29,7 +29,7 @@
// https://docs.bazel.build/versions/master/be/general.html#filegroup
type bazelFilegroupAttributes struct {
Name *string
- Srcs []string
+ Srcs bazel.LabelList
}
type bazelFilegroup struct {
@@ -52,15 +52,18 @@
// TODO: Create helper functions to avoid this boilerplate.
func FilegroupBp2Build(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(*fileGroup); ok {
- name := "__bp2build__" + m.base().BaseModuleName()
- ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
- Name: proptools.StringPtr(name),
- Srcs: m.properties.Srcs,
- }, &bazel.BazelTargetModuleProperties{
- Rule_class: "filegroup",
- })
+ fg, ok := ctx.Module().(*fileGroup)
+ if !ok {
+ return
}
+
+ name := "__bp2build__" + fg.base().BaseModuleName()
+ ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
+ Name: proptools.StringPtr(name),
+ Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "filegroup",
+ })
}
type fileGroupProperties struct {
diff --git a/android/module.go b/android/module.go
index dcc2b84..1409d44 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2220,10 +2220,17 @@
}
var deps []dep
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if aModule, _ := module.(Module); aModule != nil {
+ if aModule.base().BaseModuleName() == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, dep{aModule, returnedTag})
+ }
+ }
+ } else if b.bp.OtherModuleName(module) == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(module)
if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
+ deps = append(deps, dep{module, returnedTag})
}
}
})
diff --git a/android/mutator.go b/android/mutator.go
index 6b19dc5..15be65f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -45,14 +45,30 @@
}
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, bp2buildMutators []RegisterMutatorFunc) {
- mctx := ®isterMutatorsContext{}
-
- sharedMutators := []RegisterMutatorFunc{
- RegisterDefaultsPreArchMutators,
+func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+ mctx := ®isterMutatorsContext{
+ bazelConversionMode: true,
}
- for _, f := range sharedMutators {
+ bp2buildPreArchMutators = append([]RegisterMutatorFunc{
+ RegisterNamespaceMutator,
+ RegisterDefaultsPreArchMutators,
+ // TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
+ // evaluate the impact on conversion.
+ RegisterPrebuiltsPreArchMutators,
+ },
+ preArchMutators...)
+
+ for _, f := range bp2buildPreArchMutators {
+ f(mctx)
+ }
+
+ bp2buildDepsMutators = append([]RegisterMutatorFunc{
+ registerDepsMutatorBp2Build,
+ registerPathDepsMutator,
+ }, depsMutators...)
+
+ for _, f := range bp2buildDepsMutators {
f(mctx)
}
@@ -77,7 +93,7 @@
register(preDeps)
- mctx.BottomUp("deps", depsMutator).Parallel()
+ register([]RegisterMutatorFunc{registerDepsMutator})
register(postDeps)
@@ -88,8 +104,9 @@
}
type registerMutatorsContext struct {
- mutators []*mutator
- finalPhase bool
+ mutators []*mutator
+ finalPhase bool
+ bazelConversionMode bool
}
type RegisterMutatorsContext interface {
@@ -211,6 +228,8 @@
finalDeps = append(finalDeps, f)
}
+var bp2buildPreArchMutators = []RegisterMutatorFunc{}
+var bp2buildDepsMutators = []RegisterMutatorFunc{}
var bp2buildMutators = []RegisterMutatorFunc{}
// RegisterBp2BuildMutator registers specially crafted mutators for
@@ -219,13 +238,24 @@
//
// TODO(b/178068862): bring this into TestContext.
func RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- mutatorName := moduleType + "_bp2build"
f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(mutatorName, m)
+ ctx.TopDown(moduleType, m)
}
bp2buildMutators = append(bp2buildMutators, f)
}
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+ bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func DepsBp2BuildMutators(f RegisterMutatorFunc) {
+ bp2buildDepsMutators = append(bp2buildDepsMutators, f)
+}
+
type BaseMutatorContext interface {
BaseModuleContext
@@ -370,32 +400,38 @@
// variant of the current module. The value should not be modified after being passed to
// SetVariationProvider.
SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
+
+ // BazelConversionMode returns whether this mutator is being run as part of Bazel Conversion.
+ BazelConversionMode() bool
}
type bottomUpMutatorContext struct {
bp blueprint.BottomUpMutatorContext
baseModuleContext
- finalPhase bool
+ finalPhase bool
+ bazelConversionMode bool
}
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
- finalPhase bool) BottomUpMutatorContext {
+ finalPhase, bazelConversionMode bool) BottomUpMutatorContext {
return &bottomUpMutatorContext{
- bp: ctx,
- baseModuleContext: a.base().baseModuleContextFactory(ctx),
- finalPhase: finalPhase,
+ bp: ctx,
+ baseModuleContext: a.base().baseModuleContextFactory(ctx),
+ finalPhase: finalPhase,
+ bazelConversionMode: bazelConversionMode,
}
}
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
+ bazelConversionMode := x.bazelConversionMode
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
- m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
+ m(bottomUpMutatorContextFactory(ctx, a, finalPhase, bazelConversionMode))
}
}
- mutator := &mutator{name: name, bottomUpMutator: f}
+ mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
@@ -406,6 +442,13 @@
return mutator
}
+func (x *registerMutatorsContext) mutatorName(name string) string {
+ if x.bazelConversionMode {
+ return name + "_bp2build"
+ }
+ return name
+}
+
func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
@@ -416,7 +459,7 @@
m(actx)
}
}
- mutator := &mutator{name: name, topDownMutator: f}
+ mutator := &mutator{name: x.mutatorName(name), topDownMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
@@ -449,6 +492,16 @@
}
}
+func registerDepsMutator(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
+func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) {
+ // TODO(b/179313531): Consider a separate mutator that only runs depsMutator for modules that are
+ // being converted to build targets.
+ ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
for _, p := range props {
err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
@@ -576,12 +629,28 @@
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
names ...string) []blueprint.Module {
+ if b.bazelConversionMode {
+ _, noSelfDeps := RemoveFromList(b.ModuleName(), names)
+ if len(noSelfDeps) == 0 {
+ return []blueprint.Module(nil)
+ }
+ // In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+ // dependency, the variations would not exist and the dependency could not be added, by
+ // specifying no variations, we will allow adding the dependency to succeed.
+ return b.bp.AddFarVariationDependencies(nil, tag, noSelfDeps...)
+ }
return b.bp.AddVariationDependencies(variations, tag, names...)
}
func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
tag blueprint.DependencyTag, names ...string) []blueprint.Module {
+ if b.bazelConversionMode {
+ // In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+ // dependency, the variations would not exist and the dependency could not be added, by
+ // specifying no variations, we will allow adding the dependency to succeed.
+ return b.bp.AddFarVariationDependencies(nil, tag, names...)
+ }
return b.bp.AddFarVariationDependencies(variations, tag, names...)
}
@@ -609,3 +678,7 @@
func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
b.bp.SetVariationProvider(module, provider, value)
}
+
+func (b *bottomUpMutatorContext) BazelConversionMode() bool {
+ return b.bazelConversionMode
+}
diff --git a/android/packaging.go b/android/packaging.go
index da745ff..9b901ce 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -49,6 +49,11 @@
return ""
}
+// Path relative to the root of the package
+func (p *PackagingSpec) RelPathInPackage() string {
+ return p.relPathInPackage
+}
+
type PackageModule interface {
Module
packagingBase() *PackagingBase
@@ -61,7 +66,7 @@
// returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
// followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
// etc.) from the extracted files
- CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) []string
+ CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) []string
}
// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
@@ -87,9 +92,17 @@
Lib64 depsProperty `android:"arch_variant"`
}
+type packagingArchProperties struct {
+ Arm64 depsProperty
+ Arm depsProperty
+ X86_64 depsProperty
+ X86 depsProperty
+}
+
type PackagingProperties struct {
Deps []string `android:"arch_variant"`
Multilib packagingMultilibProperties `android:"arch_variant"`
+ Arch packagingArchProperties
}
func InitPackageModule(p PackageModule) {
@@ -116,6 +129,7 @@
} else if arch == Common {
ret = append(ret, p.properties.Multilib.Common.Deps...)
}
+
for i, t := range ctx.MultiTargets() {
if t.Arch.ArchType == arch {
ret = append(ret, p.properties.Deps...)
@@ -124,6 +138,20 @@
}
}
}
+
+ if ctx.Arch().ArchType == Common {
+ switch arch {
+ case Arm64:
+ ret = append(ret, p.properties.Arch.Arm64.Deps...)
+ case Arm:
+ ret = append(ret, p.properties.Arch.Arm.Deps...)
+ case X86_64:
+ ret = append(ret, p.properties.Arch.X86_64.Deps...)
+ case X86:
+ ret = append(ret, p.properties.Arch.X86.Deps...)
+ }
+ }
+
return FirstUniqueStrings(ret)
}
@@ -152,7 +180,7 @@
}
// See PackageModule.CopyDepsToZip
-func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) (entries []string) {
+func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) {
m := make(map[string]PackagingSpec)
ctx.WalkDeps(func(child Module, parent Module) bool {
if !IsInstallDepNeeded(ctx.OtherModuleDependencyTag(child)) {
@@ -168,7 +196,7 @@
builder := NewRuleBuilder(pctx, ctx)
- dir := PathForModuleOut(ctx, ".zip").OutputPath
+ dir := PathForModuleOut(ctx, ".zip")
builder.Command().Text("rm").Flag("-rf").Text(dir.String())
builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 7269bfb..2c99b97 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -61,30 +61,45 @@
entries []string
}
-func packageTestModuleFactory() Module {
+func packageMultiTargetTestModuleFactory() Module {
module := &packageTestModule{}
InitPackageModule(module)
InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
return module
}
+func packageTestModuleFactory() Module {
+ module := &packageTestModule{}
+ InitPackageModule(module)
+ InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
+ return module
+}
+
func (m *packageTestModule) DepsMutator(ctx BottomUpMutatorContext) {
m.AddDeps(ctx, installDepTag{})
}
func (m *packageTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- zipFile := PathForModuleOut(ctx, "myzip.zip").OutputPath
+ zipFile := PathForModuleOut(ctx, "myzip.zip")
m.entries = m.CopyDepsToZip(ctx, zipFile)
}
-func runPackagingTest(t *testing.T, bp string, expected []string) {
+func runPackagingTest(t *testing.T, multitarget bool, bp string, expected []string) {
t.Helper()
config := TestArchConfig(buildDir, nil, bp, nil)
ctx := NewTestArchContext(config)
ctx.RegisterModuleType("component", componentTestModuleFactory)
- ctx.RegisterModuleType("package_module", packageTestModuleFactory)
+
+ var archVariant string
+ if multitarget {
+ archVariant = "android_common"
+ ctx.RegisterModuleType("package_module", packageMultiTargetTestModuleFactory)
+ } else {
+ archVariant = "android_arm64_armv8-a"
+ ctx.RegisterModuleType("package_module", packageTestModuleFactory)
+ }
ctx.Register()
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
@@ -92,7 +107,7 @@
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
- p := ctx.ModuleForTests("package", "android_common").Module().(*packageTestModule)
+ p := ctx.ModuleForTests("package", archVariant).Module().(*packageTestModule)
actual := p.entries
actual = SortedUniqueStrings(actual)
expected = SortedUniqueStrings(expected)
@@ -101,8 +116,9 @@
}
}
-func TestPackagingBase(t *testing.T) {
- runPackagingTest(t,
+func TestPackagingBaseMultiTarget(t *testing.T) {
+ multiTarget := true
+ runPackagingTest(t, multiTarget,
`
component {
name: "foo",
@@ -114,7 +130,7 @@
}
`, []string{"lib64/foo"})
- runPackagingTest(t,
+ runPackagingTest(t, multiTarget,
`
component {
name: "foo",
@@ -131,7 +147,7 @@
}
`, []string{"lib64/foo", "lib64/bar"})
- runPackagingTest(t,
+ runPackagingTest(t, multiTarget,
`
component {
name: "foo",
@@ -149,7 +165,7 @@
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo", "lib64/bar"})
- runPackagingTest(t,
+ runPackagingTest(t, multiTarget,
`
component {
name: "foo",
@@ -172,7 +188,7 @@
}
`, []string{"lib32/foo", "lib32/bar", "lib64/foo"})
- runPackagingTest(t,
+ runPackagingTest(t, multiTarget,
`
component {
name: "foo",
@@ -193,4 +209,136 @@
compile_multilib: "both",
}
`, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ component {
+ name: "baz",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ arch: {
+ arm64: {
+ deps: ["bar"],
+ },
+ x86_64: {
+ deps: ["baz"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
+}
+
+func TestPackagingBaseSingleTarget(t *testing.T) {
+ multiTarget := false
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ compile_multilib: "32",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ lib32: {
+ deps: ["bar"],
+ },
+ },
+ }
+ `, []string{"lib64/foo"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ lib64: {
+ deps: ["bar"],
+ },
+ },
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ component {
+ name: "baz",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ arch: {
+ arm64: {
+ deps: ["bar"],
+ },
+ x86_64: {
+ deps: ["baz"],
+ },
+ },
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
}
diff --git a/android/paths.go b/android/paths.go
index b5a1401..44221be 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -15,6 +15,7 @@
package android
import (
+ "android/soong/bazel"
"fmt"
"io/ioutil"
"os"
@@ -331,6 +332,115 @@
return ret
}
+// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
+// order to form a Bazel-compatible label for conversion.
+type BazelConversionPathContext interface {
+ EarlyModulePathContext
+
+ GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+ OtherModuleName(m blueprint.Module) string
+ OtherModuleDir(m blueprint.Module) string
+}
+
+// BazelLabelForModuleDeps returns a Bazel-compatible label for the requested modules which
+// correspond to dependencies on the module within the given ctx.
+func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
+ var labels bazel.LabelList
+ for _, module := range modules {
+ bpText := module
+ if m := SrcIsModule(module); m == "" {
+ module = ":" + module
+ }
+ if m, t := SrcIsModuleWithTag(module); m != "" {
+ l := getOtherModuleLabel(ctx, m, t)
+ l.Bp_text = bpText
+ labels.Includes = append(labels.Includes, l)
+ } else {
+ ctx.ModuleErrorf("%q, is not a module reference", module)
+ }
+ }
+ return labels
+}
+
+// BazelLabelForModuleSrc returns bazel.LabelList with paths rooted from the module's local source
+// directory. It expands globs, and resolves references to modules using the ":name" syntax to
+// bazel-compatible labels. Properties passed as the paths or excludes argument must have been
+// annotated with struct tag `android:"path"` so that dependencies on other modules will have
+// already been handled by the path_properties mutator.
+func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
+ return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
+}
+
+// BazelLabelForModuleSrcExcludes returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels. Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
+ excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
+ excluded := make([]string, 0, len(excludeLabels.Includes))
+ for _, e := range excludeLabels.Includes {
+ excluded = append(excluded, e.Label)
+ }
+ labels := expandSrcsForBazel(ctx, paths, excluded)
+ labels.Excludes = excludeLabels.Includes
+ return labels
+}
+
+// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels. Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
+ labels := bazel.LabelList{
+ Includes: []bazel.Label{},
+ }
+ for _, p := range paths {
+ if m, tag := SrcIsModuleWithTag(p); m != "" {
+ l := getOtherModuleLabel(ctx, m, tag)
+ if !InList(l.Label, expandedExcludes) {
+ l.Bp_text = fmt.Sprintf(":%s", m)
+ labels.Includes = append(labels.Includes, l)
+ }
+ } else {
+ var expandedPaths []bazel.Label
+ if pathtools.IsGlob(p) {
+ globbedPaths := GlobFiles(ctx, pathForModuleSrc(ctx, p).String(), expandedExcludes)
+ globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
+ for _, path := range globbedPaths {
+ s := path.Rel()
+ expandedPaths = append(expandedPaths, bazel.Label{Label: s})
+ }
+ } else {
+ if !InList(p, expandedExcludes) {
+ expandedPaths = append(expandedPaths, bazel.Label{Label: p})
+ }
+ }
+ labels.Includes = append(labels.Includes, expandedPaths...)
+ }
+ }
+ return labels
+}
+
+// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
+// module. The label will be relative to the current directory if appropriate. The dependency must
+// already be resolved by either deps mutator or path deps mutator.
+func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
+ m, _ := ctx.GetDirectDep(dep)
+ // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
+ otherModuleName := ctx.OtherModuleName(m)
+ var label bazel.Label
+ if otherDir, dir := ctx.OtherModuleDir(m), ctx.ModuleDir(); otherDir != dir {
+ label.Label = fmt.Sprintf("//%s:%s", otherDir, otherModuleName)
+ } else {
+ label.Label = fmt.Sprintf(":%s", otherModuleName)
+ }
+ return label
+}
+
// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
type OutputPaths []OutputPath
@@ -1011,8 +1121,13 @@
return p.config.buildDir
}
+func (p OutputPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
+ return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
+}
+
var _ Path = OutputPath{}
var _ WritablePath = OutputPath{}
+var _ objPathProvider = OutputPath{}
// toolDepPath is a Path representing a dependency of the build tool.
type toolDepPath struct {
diff --git a/android/register.go b/android/register.go
index 02fc97e..18c743f 100644
--- a/android/register.go
+++ b/android/register.go
@@ -115,7 +115,7 @@
ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
}
- RegisterMutatorsForBazelConversion(ctx.Context, bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
}
// Register the pipeline of singletons, module types, and mutators for
diff --git a/android/testing.go b/android/testing.go
index 5640c29..de338bf 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -56,9 +56,9 @@
type TestContext struct {
*Context
- preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
- bp2buildMutators []RegisterMutatorFunc
- NameResolver *NameResolver
+ preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
+ bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
+ NameResolver *NameResolver
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -85,13 +85,24 @@
// RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
// type to the equivalent Bazel target.
func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- mutatorName := moduleType + "_bp2build"
f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(mutatorName, m)
+ ctx.TopDown(moduleType, m)
}
ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
}
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+ ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
+ ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
+}
+
func (ctx *TestContext) Register() {
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
@@ -100,7 +111,7 @@
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 6dd49e5..5d00e06 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -52,6 +52,7 @@
android.hidl.safe_union@1.0(minSdkVersion:29)
android.hidl.token@1.0(minSdkVersion:29)
android.hidl.token@1.0-utils(minSdkVersion:29)
+android.net.ipsec.ike(minSdkVersion:30)
android.net.ipsec.ike(minSdkVersion:current)
android.net.ipsec.ike.xml(minSdkVersion:(no version))
androidx-constraintlayout_constraintlayout(minSdkVersion:14)
@@ -238,6 +239,7 @@
libbase(minSdkVersion:29)
libbase_headers(minSdkVersion:29)
libbinder_headers(minSdkVersion:29)
+libbinder_headers_platform_shared(minSdkVersion:29)
libbinderthreadstateutils(minSdkVersion:29)
libbluetooth-types-header(minSdkVersion:29)
libbrotli(minSdkVersion:(no version))
@@ -499,6 +501,7 @@
neuralnetworks_utils_hal_1_3(minSdkVersion:30)
neuralnetworks_utils_hal_common(minSdkVersion:30)
neuralnetworks_utils_hal_service(minSdkVersion:30)
+no_op(minSdkVersion:current)
note_memtag_heap_async(minSdkVersion:16)
note_memtag_heap_sync(minSdkVersion:16)
PermissionController(minSdkVersion:28)
diff --git a/apex/apex.go b/apex/apex.go
index c897042..724a50b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -54,6 +54,8 @@
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_apex_select_source", prebuiltSelectSourceMutator).Parallel()
+ ctx.BottomUp("deapexer_select_source", deapexerSelectSourceMutator).Parallel()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 651cadf..8f4a285 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -78,12 +78,17 @@
return p.prebuilt.Name(p.ModuleBase.Name())
}
-func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
- if err := p.apexFileProperties.selectSource(ctx); err != nil {
- ctx.ModuleErrorf("%s", err)
+func deapexerSelectSourceMutator(ctx android.BottomUpMutatorContext) {
+ p, ok := ctx.Module().(*Deapexer)
+ if !ok {
return
}
+ if err := p.apexFileProperties.selectSource(ctx); err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+}
+func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies from the java modules to which this exports files from the `.apex` file onto
// this module so that they can access the `DeapexerInfo` object that this provides.
for _, lib := range p.properties.Exported_java_libs {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index c72a9eb..3149952 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -250,12 +250,17 @@
return name
}
-func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
- if err := p.properties.selectSource(ctx); err != nil {
- ctx.ModuleErrorf("%s", err)
+func prebuiltSelectSourceMutator(ctx android.BottomUpMutatorContext) {
+ p, ok := ctx.Module().(*Prebuilt)
+ if !ok {
return
}
+ if err := p.properties.selectSource(ctx); err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+}
+func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
for _, lib := range p.properties.Exported_java_libs {
diff --git a/bazel/properties.go b/bazel/properties.go
index 79956e1..5b98d15 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -35,3 +35,26 @@
// The target label for the bzl file containing the definition of the rule class.
Bzl_load_location string
}
+
+// Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
+// string replacement.
+type Label struct {
+ Bp_text string
+ Label string
+}
+
+// LabelList is used to represent a list of Bazel labels.
+type LabelList struct {
+ Includes []Label
+ Excludes []Label
+}
+
+// Append appends the fields of other labelList to the corresponding fields of ll.
+func (ll *LabelList) Append(other LabelList) {
+ if len(ll.Includes) > 0 || len(other.Includes) > 0 {
+ ll.Includes = append(ll.Includes, other.Includes...)
+ }
+ if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
+ ll.Excludes = append(other.Excludes, other.Excludes...)
+ }
+}
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index a414f04..b89d0a0 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -28,7 +28,7 @@
ruleShims := CreateRuleShims(android.ModuleTypeFactories())
- buildToTargets := GenerateSoongModuleTargets(ctx.Context(), ctx.mode)
+ buildToTargets := GenerateBazelTargets(ctx.Context(), ctx.mode)
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets, ctx.mode)
for _, f := range filesToWrite {
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 1af1d60..2c293ea 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/bazel"
"fmt"
"reflect"
"strconv"
@@ -159,7 +160,7 @@
return attributes
}
-func GenerateSoongModuleTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string]BazelTargets {
+func GenerateBazelTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string]BazelTargets {
buildFileToTargets := make(map[string]BazelTargets)
ctx.VisitAllModules(func(m blueprint.Module) {
dir := ctx.ModuleDir(m)
@@ -177,7 +178,7 @@
panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
}
- buildFileToTargets[ctx.ModuleDir(m)] = append(buildFileToTargets[dir], t)
+ buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
})
return buildFileToTargets
}
@@ -349,6 +350,13 @@
ret += makeIndent(indent)
ret += "]"
case reflect.Struct:
+ if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
+ // TODO(b/165114590): convert glob syntax
+ return prettyPrint(reflect.ValueOf(labels.Includes), indent)
+ } else if label, ok := propertyValue.Interface().(bazel.Label); ok {
+ return fmt.Sprintf("%q", label.Label), nil
+ }
+
ret = "{\n"
// Sort and print the struct props by the key.
structProps := extractStructProperties(propertyValue, indent)
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index a01a7cd..081b0e5 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"android/soong/genrule"
+ "strings"
"testing"
)
@@ -201,7 +202,7 @@
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, QueryView)[dir]
+ bazelTargets := GenerateBazelTargets(ctx.Context.Context, QueryView)[dir]
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}
@@ -248,22 +249,26 @@
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
+ if Errored(t, "", errs) {
+ continue
+ }
_, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
- if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
- t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
+ if Errored(t, "", errs) {
+ continue
}
- actualBazelTarget := bazelTargets[0]
- if actualBazelTarget.content != testCase.expectedBazelTarget {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- testCase.expectedBazelTarget,
- actualBazelTarget.content,
- )
+ bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
+ t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
+ } else {
+ actualBazelTarget := bazelTargets[0]
+ if actualBazelTarget.content != testCase.expectedBazelTarget {
+ t.Errorf(
+ "Expected generated Bazel target to be '%s', got '%s'",
+ testCase.expectedBazelTarget,
+ actualBazelTarget.content,
+ )
+ }
}
}
}
@@ -408,7 +413,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
+ bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
}
@@ -434,13 +439,32 @@
}
func TestModuleTypeBp2Build(t *testing.T) {
+ otherGenruleBp := map[string]string{
+ "other/Android.bp": `genrule {
+ name: "foo.tool",
+ out: ["foo_tool.out"],
+ srcs: ["foo_tool.in"],
+ cmd: "cp $(in) $(out)",
+}
+genrule {
+ name: "other.tool",
+ out: ["other_tool.out"],
+ srcs: ["other_tool.in"],
+ cmd: "cp $(in) $(out)",
+}`,
+ }
+
testCases := []struct {
+ description string
moduleTypeUnderTest string
moduleTypeUnderTestFactory android.ModuleFactory
moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ preArchMutators []android.RegisterMutatorFunc
+ depsMutators []android.RegisterMutatorFunc
bp string
- expectedBazelTarget string
- description string
+ expectedBazelTargets []string
+ fs map[string]string
+ dir string
}{
{
description: "filegroup with no srcs",
@@ -448,14 +472,16 @@
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
bp: `filegroup {
- name: "foo",
- srcs: [],
+ name: "fg_foo",
+ srcs: [],
}`,
- expectedBazelTarget: `filegroup(
- name = "foo",
+ expectedBazelTargets: []string{
+ `filegroup(
+ name = "fg_foo",
srcs = [
],
)`,
+ },
},
{
description: "filegroup with srcs",
@@ -463,30 +489,140 @@
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
bp: `filegroup {
- name: "foo",
- srcs: ["a", "b"],
+ name: "fg_foo",
+ srcs: ["a", "b"],
}`,
- expectedBazelTarget: `filegroup(
- name = "foo",
+ expectedBazelTargets: []string{`filegroup(
+ name = "fg_foo",
srcs = [
"a",
"b",
],
)`,
+ },
+ },
+ {
+ description: "filegroup with excludes srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ bp: `filegroup {
+ name: "fg_foo",
+ srcs: ["a", "b"],
+ exclude_srcs: ["a"],
+}`,
+ expectedBazelTargets: []string{`filegroup(
+ name = "fg_foo",
+ srcs = [
+ "b",
+ ],
+)`,
+ },
+ },
+ {
+ description: "filegroup with glob",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ bp: `filegroup {
+ name: "foo",
+ srcs: ["**/*.txt"],
+}`,
+ expectedBazelTargets: []string{`filegroup(
+ name = "foo",
+ srcs = [
+ "other/a.txt",
+ "other/b.txt",
+ "other/subdir/a.txt",
+ ],
+)`,
+ },
+ fs: map[string]string{
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ },
+ {
+ description: "filegroup with glob in subdir",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ bp: `filegroup {
+ name: "foo",
+ srcs: ["a.txt"],
+}`,
+ dir: "other",
+ expectedBazelTargets: []string{`filegroup(
+ name = "fg_foo",
+ srcs = [
+ "a.txt",
+ "b.txt",
+ "subdir/a.txt",
+ ],
+)`,
+ },
+ fs: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+}`,
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ },
+ {
+ description: "depends_on_other_dir_module",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ bp: `filegroup {
+ name: "foobar",
+ srcs: [
+ ":foo",
+ "c",
+ ],
+}`,
+ expectedBazelTargets: []string{`filegroup(
+ name = "foobar",
+ srcs = [
+ "//other:foo",
+ "c",
+ ],
+)`,
+ },
+ fs: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "foo",
+ srcs: ["a", "b"],
+}`,
+ },
},
{
description: "genrule with command line variable replacements",
moduleTypeUnderTest: "genrule",
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
bp: `genrule {
+ name: "foo.tool",
+ out: ["foo_tool.out"],
+ srcs: ["foo_tool.in"],
+ cmd: "cp $(in) $(out)",
+}
+
+genrule {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tools: [":foo.tool"],
cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
}`,
- expectedBazelTarget: `genrule(
+ expectedBazelTargets: []string{
+ `genrule(
name = "foo",
cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
outs = [
@@ -499,20 +635,39 @@
":foo.tool",
],
)`,
+ `genrule(
+ name = "foo.tool",
+ cmd = "cp $(SRCS) $(OUTS)",
+ outs = [
+ "foo_tool.out",
+ ],
+ srcs = [
+ "foo_tool.in",
+ ],
+)`,
+ },
},
{
description: "genrule using $(locations :label)",
moduleTypeUnderTest: "genrule",
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
bp: `genrule {
+ name: "foo.tools",
+ out: ["foo_tool.out", "foo_tool2.out"],
+ srcs: ["foo_tool.in"],
+ cmd: "cp $(in) $(out)",
+ }
+
+genrule {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tools: [":foo.tools"],
cmd: "$(locations :foo.tools) -s $(out) $(in)",
}`,
- expectedBazelTarget: `genrule(
+ expectedBazelTargets: []string{`genrule(
name = "foo",
cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
outs = [
@@ -525,12 +680,83 @@
":foo.tools",
],
)`,
+ `genrule(
+ name = "foo.tools",
+ cmd = "cp $(SRCS) $(OUTS)",
+ outs = [
+ "foo_tool.out",
+ "foo_tool2.out",
+ ],
+ srcs = [
+ "foo_tool.in",
+ ],
+)`,
+ },
+ },
+ {
+ description: "genrule using $(locations //absolute:label)",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
+ bp: `genrule {
+ name: "foo",
+ out: ["foo.out"],
+ srcs: ["foo.in"],
+ tool_files: [":foo.tool"],
+ cmd: "$(locations :foo.tool) -s $(out) $(in)",
+}`,
+ expectedBazelTargets: []string{`genrule(
+ name = "foo",
+ cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
+ outs = [
+ "foo.out",
+ ],
+ srcs = [
+ "foo.in",
+ ],
+ tools = [
+ "//other:foo.tool",
+ ],
+)`,
+ },
+ fs: otherGenruleBp,
+ },
+ {
+ description: "genrule srcs using $(locations //absolute:label)",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
+ bp: `genrule {
+ name: "foo",
+ out: ["foo.out"],
+ srcs: [":other.tool"],
+ tool_files: [":foo.tool"],
+ cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
+}`,
+ expectedBazelTargets: []string{`genrule(
+ name = "foo",
+ cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
+ outs = [
+ "foo.out",
+ ],
+ srcs = [
+ "//other:other.tool",
+ ],
+ tools = [
+ "//other:foo.tool",
+ ],
+)`,
+ },
+ fs: otherGenruleBp,
},
{
description: "genrule using $(location) label should substitute first tool label automatically",
moduleTypeUnderTest: "genrule",
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
bp: `genrule {
name: "foo",
out: ["foo.out"],
@@ -538,9 +764,9 @@
tool_files: [":foo.tool", ":other.tool"],
cmd: "$(location) -s $(out) $(in)",
}`,
- expectedBazelTarget: `genrule(
+ expectedBazelTargets: []string{`genrule(
name = "foo",
- cmd = "$(location :foo.tool) -s $(OUTS) $(SRCS)",
+ cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
outs = [
"foo.out",
],
@@ -548,16 +774,19 @@
"foo.in",
],
tools = [
- ":foo.tool",
- ":other.tool",
+ "//other:foo.tool",
+ "//other:other.tool",
],
)`,
+ },
+ fs: otherGenruleBp,
},
{
description: "genrule using $(locations) label should substitute first tool label automatically",
moduleTypeUnderTest: "genrule",
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
bp: `genrule {
name: "foo",
out: ["foo.out"],
@@ -565,9 +794,9 @@
tools: [":foo.tool", ":other.tool"],
cmd: "$(locations) -s $(out) $(in)",
}`,
- expectedBazelTarget: `genrule(
+ expectedBazelTargets: []string{`genrule(
name = "foo",
- cmd = "$(locations :foo.tool) -s $(OUTS) $(SRCS)",
+ cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
outs = [
"foo.out",
],
@@ -575,23 +804,26 @@
"foo.in",
],
tools = [
- ":foo.tool",
- ":other.tool",
+ "//other:foo.tool",
+ "//other:other.tool",
],
)`,
+ },
+ fs: otherGenruleBp,
},
{
description: "genrule without tools or tool_files can convert successfully",
moduleTypeUnderTest: "genrule",
moduleTypeUnderTestFactory: genrule.GenRuleFactory,
moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{genrule.RegisterGenruleBp2BuildDeps},
bp: `genrule {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
cmd: "cp $(in) $(out)",
}`,
- expectedBazelTarget: `genrule(
+ expectedBazelTargets: []string{`genrule(
name = "foo",
cmd = "cp $(SRCS) $(OUTS)",
outs = [
@@ -601,39 +833,73 @@
"foo.in",
],
)`,
+ },
},
}
dir := "."
for _, testCase := range testCases {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+ fs := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ for f, content := range testCase.fs {
+ if strings.HasSuffix(f, "Android.bp") {
+ toParse = append(toParse, f)
+ }
+ fs[f] = []byte(content)
+ }
+ config := android.TestConfig(buildDir, nil, testCase.bp, fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ for _, m := range testCase.depsMutators {
+ ctx.DepsBp2BuildMutators(m)
+ }
ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
_, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
- if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
- t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ if Errored(t, testCase.description, errs) {
+ continue
}
- actualBazelTarget := bazelTargets[0]
- if actualBazelTarget.content != testCase.expectedBazelTarget {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- testCase.description,
- testCase.expectedBazelTarget,
- actualBazelTarget.content,
- )
+ checkDir := dir
+ if testCase.dir != "" {
+ checkDir = testCase.dir
+ }
+ bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
+ if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+ t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ w,
+ g,
+ )
+ }
+ }
}
}
}
+func Errored(t *testing.T, desc string, errs []error) bool {
+ t.Helper()
+ if len(errs) > 0 {
+ for _, err := range errs {
+ t.Errorf("%s: %s", desc, err)
+ }
+ return true
+ }
+ return false
+}
+
type bp2buildMutator = func(android.TopDownMutatorContext)
func TestBp2BuildInlinesDefaults(t *testing.T) {
@@ -815,7 +1081,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
+ bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount := len(bazelTargets); actualCount != 1 {
t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
}
diff --git a/cc/binary.go b/cc/binary.go
index 71c865b..999b82c 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -182,7 +182,7 @@
}
}
- if !binary.static() && inList("libc", deps.StaticLibs) {
+ if !binary.static() && inList("libc", deps.StaticLibs) && !ctx.BazelConversionMode() {
ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
"from static libs or set static_executable: true")
}
diff --git a/cc/cc.go b/cc/cc.go
index d282b6e..df38499 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1535,6 +1535,11 @@
var vndkVersion string
var nameSuffix string
if c.InProduct() {
+ if c.ProductSpecific() {
+ // If the module is product specific with 'product_specific: true',
+ // do not add a name suffix because it is a base module.
+ return ""
+ }
vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
nameSuffix = productSuffix
} else {
@@ -1741,7 +1746,7 @@
func (c *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
if c.cachedToolchain == nil {
- c.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
+ c.cachedToolchain = config.FindToolchainWithContext(ctx)
}
return c.cachedToolchain
}
@@ -1833,6 +1838,12 @@
deps.HeaderLibs = android.LastUniqueStrings(deps.HeaderLibs)
deps.RuntimeLibs = android.LastUniqueStrings(deps.RuntimeLibs)
+ // In Bazel conversion mode, we dependency and build validations will occur in Bazel, so there is
+ // no need to do so in Soong.
+ if ctx.BazelConversionMode() {
+ return deps
+ }
+
for _, lib := range deps.ReexportSharedLibHeaders {
if !inList(lib, deps.SharedLibs) {
ctx.PropertyErrorf("export_shared_lib_headers", "Shared library not in shared_libs: '%s'", lib)
@@ -2891,12 +2902,12 @@
ccDepModule, _ := ccDep.(*Module)
isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
isVendorPublicLib := inList(libName, *vendorPublicLibraries)
- bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
+ nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
- if c, ok := ccDep.(*Module); ok {
+ if ccDepModule != nil {
// Use base module name for snapshots when exporting to Makefile.
- if snapshotPrebuilt, ok := c.linker.(snapshotInterface); ok {
- baseName := c.BaseModuleName()
+ if snapshotPrebuilt, ok := ccDepModule.linker.(snapshotInterface); ok {
+ baseName := ccDepModule.BaseModuleName()
return baseName + snapshotPrebuilt.snapshotAndroidMkSuffix()
}
@@ -2907,10 +2918,10 @@
// The vendor module is a no-vendor-variant VNDK library. Depend on the
// core module instead.
return libName
- } else if c.UseVndk() && bothVendorAndCoreVariantsExist {
- // The vendor module in Make will have been renamed to not conflict with the core
- // module, so update the dependency name here accordingly.
- return libName + c.getNameSuffixWithVndkVersion(ctx)
+ } else if ccDep.UseVndk() && nonSystemVariantsExist && ccDepModule != nil {
+ // The vendor and product modules in Make will have been renamed to not conflict with the
+ // core module, so update the dependency name here accordingly.
+ return libName + ccDepModule.Properties.SubName
} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
return libName + vendorPublicLibrarySuffix
} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7288cc4..6403547 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2712,6 +2712,14 @@
system_shared_libs : [],
}
cc_library {
+ name: "libproduct_vendor",
+ product_specific: true,
+ vendor_available: true,
+ no_libcrt : true,
+ nocrt : true,
+ system_shared_libs : [],
+ }
+ cc_library {
name: "libcore",
runtime_libs: ["liball_available"],
no_libcrt : true,
@@ -2728,7 +2736,7 @@
cc_library {
name: "libvendor2",
vendor: true,
- runtime_libs: ["liball_available", "libvendor1"],
+ runtime_libs: ["liball_available", "libvendor1", "libproduct_vendor"],
no_libcrt : true,
nocrt : true,
system_shared_libs : [],
@@ -2751,7 +2759,7 @@
cc_library {
name: "libproduct2",
product_specific: true,
- runtime_libs: ["liball_available", "libproduct1"],
+ runtime_libs: ["liball_available", "libproduct1", "libproduct_vendor"],
no_libcrt : true,
nocrt : true,
system_shared_libs : [],
@@ -2781,7 +2789,7 @@
checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1", "libproduct_vendor.vendor"}, module)
// runtime_libs for product variants have '.product' suffixes if the modules have both core
// and product variants.
@@ -2791,7 +2799,7 @@
checkRuntimeLibs(t, []string{"liball_available.product"}, module)
module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1", "libproduct_vendor"}, module)
}
func TestExcludeRuntimeLibs(t *testing.T) {
@@ -2817,10 +2825,10 @@
checkRuntimeLibs(t, []string{"liball_available"}, module)
module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available", "libvendor1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available", "libvendor1", "libproduct_vendor"}, module)
module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available", "libproduct1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available", "libproduct1", "libproduct_vendor"}, module)
}
func checkStaticLibs(t *testing.T, expected []string, module *Module) {
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 35dd10f..71c7626 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -142,6 +142,9 @@
// Nested and array designated initialization is nice to have.
"-Wno-c99-designator",
+ // Warnings from clang-12
+ "-Wno-gnu-folding-constant",
+
// Calls to the APIs that are newer than the min sdk version of the caller should be
// guarded with __builtin_available.
"-Wunguarded-availability",
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index db9092d..59c0422 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -32,12 +32,42 @@
toolchainFactories[os][arch] = factory
}
+type toolchainContext interface {
+ Os() android.OsType
+ Arch() android.Arch
+}
+
+type conversionContext interface {
+ BazelConversionMode() bool
+}
+
+func FindToolchainWithContext(ctx toolchainContext) Toolchain {
+ t, err := findToolchain(ctx.Os(), ctx.Arch())
+ if err != nil {
+ if c, ok := ctx.(conversionContext); ok && c.BazelConversionMode() {
+ // TODO(b/179123288): determine conversion for toolchain
+ return &toolchainX86_64{}
+ } else {
+ panic(err)
+ }
+ }
+ return t
+}
+
func FindToolchain(os android.OsType, arch android.Arch) Toolchain {
+ t, err := findToolchain(os, arch)
+ if err != nil {
+ panic(err)
+ }
+ return t
+}
+
+func findToolchain(os android.OsType, arch android.Arch) (Toolchain, error) {
factory := toolchainFactories[os][arch.ArchType]
if factory == nil {
- panic(fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String()))
+ return nil, fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String())
}
- return factory(arch)
+ return factory(arch), nil
}
type Toolchain interface {
diff --git a/cc/linkable.go b/cc/linkable.go
index ab5a552..58919a0 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -106,6 +106,8 @@
IsVndkExt() bool
IsVndkPrivate() bool
HasVendorVariant() bool
+ HasProductVariant() bool
+ HasNonSystemVariants() bool
InProduct() bool
SdkVersion() string
diff --git a/cc/linker.go b/cc/linker.go
index ff07224..6d0d416 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -328,7 +328,9 @@
}
deps.SystemSharedLibs = linker.Properties.System_shared_libs
- if deps.SystemSharedLibs == nil {
+ // In Bazel conversion mode, variations have not been specified, so SystemSharedLibs may
+ // inaccuarately appear unset, which can cause issues with circular dependencies.
+ if deps.SystemSharedLibs == nil && !ctx.BazelConversionMode() {
// Provide a default system_shared_libs if it is unspecified. Note: If an
// empty list [] is specified, it implies that the module declines the
// default system_shared_libs.
diff --git a/cc/test.go b/cc/test.go
index f715a8d..17ac534 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -19,6 +19,8 @@
"strconv"
"strings"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/tradefed"
)
@@ -230,6 +232,7 @@
type testDecorator struct {
Properties TestProperties
linker *baseLinker
+ hod android.HostOrDeviceSupported
}
func (test *testDecorator) gtest() bool {
@@ -429,6 +432,10 @@
ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
}
+ // TODO(179092189): Clean up to use Ctx.Host() when generalizing to cc_test
+ if test.testDecorator.hod == android.HostSupported && test.gtest() && test.Properties.Test_options.Unit_test == nil {
+ test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
+ }
test.binaryDecorator.baseInstaller.install(ctx, file)
}
@@ -440,6 +447,7 @@
test := &testBinary{
testDecorator: testDecorator{
linker: binary.baseLinker,
+ hod: hod,
},
binaryDecorator: binary,
baseCompiler: NewBaseCompiler(),
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 9dcb5f3..c17e23d 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -100,7 +100,7 @@
if bazelConversionRequested(configuration) {
// Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files
// before everything else.
- runBp2Build(configuration, extraNinjaDeps)
+ runBp2Build(srcDir, configuration)
// Short-circuit and return.
return
}
@@ -162,7 +162,7 @@
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
+func runBp2Build(srcDir string, configuration android.Config) {
// Register an alternate set of singletons and mutators for bazel
// conversion for Bazel conversion.
bp2buildCtx := android.NewContext(configuration)
@@ -172,7 +172,20 @@
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
- // Run the loading and analysis pipeline.
+ // The bp2build process is a purely functional process that only depends on
+ // Android.bp files. It must not depend on the values of per-build product
+ // configurations or variables, since those will generate different BUILD
+ // files based on how the user has configured their tree.
+ bp2buildCtx.SetModuleListFile(bootstrap.ModuleListFile)
+ extraNinjaDeps, err := bp2buildCtx.ListModulePaths(srcDir)
+ if err != nil {
+ panic(err)
+ }
+ extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
+
+ // Run the loading and analysis pipeline to prepare the graph of regular
+ // Modules parsed from Android.bp files, and the BazelTargetModules mapped
+ // from the regular Modules.
bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
@@ -195,7 +208,6 @@
ninjaFileName := "build.ninja"
ninjaFile := android.PathForOutput(codegenContext, ninjaFileName)
ninjaFileD := android.PathForOutput(codegenContext, ninjaFileName+".d")
- extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
// A workaround to create the 'nothing' ninja target so `m nothing` works,
// since bp2build runs without Kati, and the 'nothing' target is declared in
// a Makefile.
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 5d61d0c..dc0b323 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -24,7 +24,7 @@
func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
- buildToTargets := bp2build.GenerateSoongModuleTargets(*ctx, bp2build.QueryView)
+ buildToTargets := bp2build.GenerateBazelTargets(*ctx, bp2build.QueryView)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
for _, f := range filesToWrite {
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 926df6e..9994241 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -7,6 +7,7 @@
"soong-android",
],
srcs: [
+ "bootimg.go",
"filesystem.go",
],
testSrcs: [
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
new file mode 100644
index 0000000..4bc1823
--- /dev/null
+++ b/filesystem/bootimg.go
@@ -0,0 +1,222 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 filesystem
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("bootimg", bootimgFactory)
+}
+
+type bootimg struct {
+ android.ModuleBase
+
+ properties bootimgProperties
+
+ output android.OutputPath
+ installDir android.InstallPath
+}
+
+type bootimgProperties struct {
+ // Path to the linux kernel prebuilt file
+ Kernel_prebuilt *string `android:"arch_variant,path"`
+
+ // Filesystem module that is used as ramdisk
+ Ramdisk_module *string
+
+ // Path to the device tree blob (DTB) prebuilt file to add to this boot image
+ Dtb_prebuilt *string `android:"arch_variant,path"`
+
+ // Header version number. Must be set to one of the version numbers that are currently
+ // supported. Refer to
+ // https://source.android.com/devices/bootloader/boot-image-header
+ Header_version *string
+
+ // Determines if this image is for the vendor_boot partition. Default is false. Refer to
+ // https://source.android.com/devices/bootloader/partitions/vendor-boot-partitions
+ Vendor_boot *bool
+
+ // Optional kernel commandline
+ Cmdline *string
+
+ // When set to true, sign the image with avbtool. Default is false.
+ Use_avb *bool
+
+ // Name of the partition stored in vbmeta desc. Defaults to the name of this module.
+ Partition_name *string
+
+ // Path to the private key that avbtool will use to sign this filesystem image.
+ // TODO(jiyong): allow apex_key to be specified here
+ Avb_private_key *string `android:"path"`
+
+ // Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
+ Avb_algorithm *string
+}
+
+// bootimg is the image for the boot partition. It consists of header, kernel, ramdisk, and dtb.
+func bootimgFactory() android.Module {
+ module := &bootimg{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+type bootimgDep struct {
+ blueprint.BaseDependencyTag
+ kind string
+}
+
+var bootimgRamdiskDep = bootimgDep{kind: "ramdisk"}
+
+func (b *bootimg) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ramdisk := proptools.String(b.properties.Ramdisk_module)
+ if ramdisk != "" {
+ ctx.AddDependency(ctx.Module(), bootimgRamdiskDep, ramdisk)
+ }
+}
+
+func (b *bootimg) installFileName() string {
+ return b.BaseModuleName() + ".img"
+}
+
+func (b *bootimg) partitionName() string {
+ return proptools.StringDefault(b.properties.Partition_name, b.BaseModuleName())
+}
+
+func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var unsignedOutput android.OutputPath
+ if proptools.Bool(b.properties.Vendor_boot) {
+ unsignedOutput = b.buildVendorBootImage(ctx)
+ } else {
+ // TODO(jiyong): fix this
+ ctx.PropertyErrorf("vendor_boot", "only vendor_boot:true is supported")
+ }
+
+ if proptools.Bool(b.properties.Use_avb) {
+ b.output = b.signImage(ctx, unsignedOutput)
+ } else {
+ b.output = unsignedOutput
+ }
+
+ b.installDir = android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(b.installDir, b.installFileName(), b.output)
+}
+
+func (b *bootimg) buildVendorBootImage(ctx android.ModuleContext) android.OutputPath {
+ output := android.PathForModuleOut(ctx, "unsigned.img").OutputPath
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command().BuiltTool("mkbootimg")
+
+ kernel := android.OptionalPathForModuleSrc(ctx, b.properties.Kernel_prebuilt)
+ if kernel.Valid() {
+ ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel")
+ return output
+ }
+
+ dtbName := proptools.String(b.properties.Dtb_prebuilt)
+ if dtbName == "" {
+ ctx.PropertyErrorf("dtb_prebuilt", "must be set")
+ return output
+ }
+ dtb := android.PathForModuleSrc(ctx, dtbName)
+ cmd.FlagWithInput("--dtb ", dtb)
+
+ cmdline := proptools.String(b.properties.Cmdline)
+ if cmdline != "" {
+ cmd.FlagWithArg("--vendor_cmdline ", "\""+cmdline+"\"")
+ }
+
+ headerVersion := proptools.String(b.properties.Header_version)
+ if headerVersion == "" {
+ ctx.PropertyErrorf("header_version", "must be set")
+ return output
+ }
+ verNum, err := strconv.Atoi(headerVersion)
+ if err != nil {
+ ctx.PropertyErrorf("header_version", "%q is not a number", headerVersion)
+ return output
+ }
+ if verNum < 3 {
+ ctx.PropertyErrorf("header_version", "must be 3 or higher for vendor_boot")
+ return output
+ }
+ cmd.FlagWithArg("--header_version ", headerVersion)
+
+ ramdiskName := proptools.String(b.properties.Ramdisk_module)
+ if ramdiskName == "" {
+ ctx.PropertyErrorf("ramdisk_module", "must be set")
+ return output
+ }
+ ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep)
+ if filesystem, ok := ramdisk.(*filesystem); ok {
+ cmd.FlagWithInput("--vendor_ramdisk ", filesystem.OutputPath())
+ } else {
+ ctx.PropertyErrorf("ramdisk", "%q is not android_filesystem module", ramdisk.Name())
+ return output
+ }
+
+ cmd.FlagWithOutput("--vendor_boot ", output)
+
+ builder.Build("build_vendor_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
+ return output
+}
+
+func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.OutputPath) android.OutputPath {
+ signedImage := android.PathForModuleOut(ctx, "signed.img").OutputPath
+ key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("cp").Input(unsignedImage).Output(signedImage)
+ builder.Command().
+ BuiltTool("avbtool").
+ Flag("add_hash_footer").
+ FlagWithArg("--partition_name ", b.partitionName()).
+ FlagWithInput("--key ", key).
+ FlagWithOutput("--image ", signedImage)
+
+ builder.Build("sign_bootimg", fmt.Sprintf("Signing %s", b.BaseModuleName()))
+
+ return signedImage
+}
+
+var _ android.AndroidMkEntriesProvider = (*bootimg)(nil)
+
+// Implements android.AndroidMkEntriesProvider
+func (b *bootimg) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(b.output),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", b.installDir.ToMakePath().String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", b.installFileName())
+ },
+ },
+ }}
+}
+
+var _ Filesystem = (*bootimg)(nil)
+
+func (b *bootimg) OutputPath() android.Path {
+ return b.output
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 654617c..c06fd4f 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -47,6 +47,13 @@
// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
Avb_algorithm *string
+
+ // Type of the filesystem. Currently, ext4 and compressed_cpio are supported. Default is
+ // ext4.
+ Type *string
+
+ // file_contexts file to make image. Currently, only ext4 is supported.
+ File_contexts *string `android:"path"`
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -71,6 +78,27 @@
f.AddDeps(ctx, dependencyTag)
}
+type fsType int
+
+const (
+ ext4Type fsType = iota
+ compressedCpioType
+ unknown
+)
+
+func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
+ typeStr := proptools.StringDefault(f.properties.Type, "ext4")
+ switch typeStr {
+ case "ext4":
+ return ext4Type
+ case "compressed_cpio":
+ return compressedCpioType
+ default:
+ ctx.PropertyErrorf("type", "%q not supported", typeStr)
+ return unknown
+ }
+}
+
func (f *filesystem) installFileName() string {
return f.BaseModuleName() + ".img"
}
@@ -78,6 +106,20 @@
var pctx = android.NewPackageContext("android/soong/filesystem")
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ switch f.fsType(ctx) {
+ case ext4Type:
+ f.output = f.buildImageUsingBuildImage(ctx)
+ case compressedCpioType:
+ f.output = f.buildCompressedCpioImage(ctx)
+ default:
+ return
+ }
+
+ f.installDir = android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(f.installDir, f.installFileName(), f.output)
+}
+
+func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.OutputPath {
zipFile := android.PathForModuleOut(ctx, "temp.zip").OutputPath
f.CopyDepsToZip(ctx, zipFile)
@@ -89,19 +131,28 @@
Input(zipFile)
propFile, toolDeps := f.buildPropFile(ctx)
- f.output = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
+ output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
builder.Command().BuiltTool("build_image").
Text(rootDir.String()). // input directory
Input(propFile).
Implicits(toolDeps).
- Output(f.output).
+ Output(output).
Text(rootDir.String()) // directory where to find fs_config_files|dirs
// rootDir is not deleted. Might be useful for quick inspection.
builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
- f.installDir = android.PathForModuleInstall(ctx, "etc")
- ctx.InstallFile(f.installDir, f.installFileName(), f.output)
+ return output
+}
+
+func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.OutputPath {
+ builder := android.NewRuleBuilder(pctx, ctx)
+ fcBin := android.PathForModuleOut(ctx, "file_contexts.bin")
+ builder.Command().BuiltTool("sefcontext_compile").
+ FlagWithOutput("-o ", fcBin).
+ Input(android.PathForModuleSrc(ctx, proptools.String(f.properties.File_contexts)))
+ builder.Build("build_filesystem_file_contexts", fmt.Sprintf("Creating filesystem file contexts for %s", f.BaseModuleName()))
+ return fcBin.OutputPath
}
func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
@@ -120,8 +171,17 @@
deps = append(deps, path)
}
- // TODO(jiyong): support more filesystem types other than ext4
- addStr("fs_type", "ext4")
+ // Type string that build_image.py accepts.
+ fsTypeStr := func(t fsType) string {
+ switch t {
+ // TODO(jiyong): add more types like f2fs, erofs, etc.
+ case ext4Type:
+ return "ext4"
+ }
+ panic(fmt.Errorf("unsupported fs type %v", t))
+ }
+
+ addStr("fs_type", fsTypeStr(f.fsType(ctx)))
addStr("mount_point", "system")
addStr("use_dynamic_partition_size", "true")
addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs"))
@@ -141,6 +201,10 @@
addStr("partition_name", f.Name())
}
+ if proptools.String(f.properties.File_contexts) != "" {
+ addPath("selinux_fc", f.buildFileContexts(ctx))
+ }
+
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("rm").Flag("-rf").Output(propFile)
@@ -154,6 +218,43 @@
return propFile, deps
}
+func (f *filesystem) buildCompressedCpioImage(ctx android.ModuleContext) android.OutputPath {
+ if proptools.Bool(f.properties.Use_avb) {
+ ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+
+ "Consider adding this to bootimg module and signing the entire boot image.")
+ }
+
+ if proptools.String(f.properties.File_contexts) != "" {
+ ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.")
+ }
+
+ zipFile := android.PathForModuleOut(ctx, "temp.zip").OutputPath
+ f.CopyDepsToZip(ctx, zipFile)
+
+ rootDir := android.PathForModuleOut(ctx, "root").OutputPath
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().
+ BuiltTool("zipsync").
+ FlagWithArg("-d ", rootDir.String()). // zipsync wipes this. No need to clear.
+ Input(zipFile)
+
+ output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
+ builder.Command().
+ BuiltTool("mkbootfs").
+ Text(rootDir.String()). // input directory
+ Text("|").
+ BuiltTool("lz4").
+ Flag("--favor-decSpeed"). // for faster boot
+ Flag("-12"). // maximum compression level
+ Flag("-l"). // legacy format for kernel
+ Text(">").Output(output)
+
+ // rootDir is not deleted. Might be useful for quick inspection.
+ builder.Build("build_compressed_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+
+ return output
+}
+
var _ android.AndroidMkEntriesProvider = (*filesystem)(nil)
// Implements android.AndroidMkEntriesProvider
@@ -170,6 +271,16 @@
}}
}
+var _ android.OutputFileProducer = (*filesystem)(nil)
+
+// Implements android.OutputFileProducer
+func (f *filesystem) OutputFiles(tag string) (android.Paths, error) {
+ if tag == "" {
+ return []android.Path{f.output}, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+}
+
// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex
// package to have access to the output file.
type Filesystem interface {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index ddfb459..62aa7f8 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -47,9 +47,14 @@
ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
})
+ android.DepsBp2BuildMutators(RegisterGenruleBp2BuildDeps)
android.RegisterBp2BuildMutator("genrule", GenruleBp2Build)
}
+func RegisterGenruleBp2BuildDeps(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("genrule_tool_deps", toolDepsMutator)
+}
+
var (
pctx = android.NewPackageContext("android/soong/genrule")
@@ -776,9 +781,9 @@
type bazelGenruleAttributes struct {
Name *string
- Srcs []string
+ Srcs bazel.LabelList
Outs []string
- Tools []string
+ Tools bazel.LabelList
Cmd string
}
@@ -795,45 +800,63 @@
}
func GenruleBp2Build(ctx android.TopDownMutatorContext) {
- if m, ok := ctx.Module().(*Module); ok {
- name := "__bp2build__" + m.Name()
- // Bazel only has the "tools" attribute.
- tools := append(m.properties.Tools, m.properties.Tool_files...)
-
- // Replace in and out variables with $< and $@
- var cmd string
- if m.properties.Cmd != nil {
- cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
- cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
- cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
- if len(tools) > 0 {
- cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools[0]), -1)
- cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools[0]), -1)
- }
- }
-
- // The Out prop is not in an immediately accessible field
- // in the Module struct, so use GetProperties and cast it
- // to the known struct prop.
- var outs []string
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*genRuleProperties); ok {
- outs = props.Out
- break
- }
- }
-
- // Create the BazelTargetModule.
- ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
- Name: proptools.StringPtr(name),
- Srcs: m.properties.Srcs,
- Outs: outs,
- Cmd: cmd,
- Tools: tools,
- }, &bazel.BazelTargetModuleProperties{
- Rule_class: "genrule",
- })
+ m, ok := ctx.Module().(*Module)
+ if !ok {
+ return
}
+ name := "__bp2build__" + m.Name()
+ // Bazel only has the "tools" attribute.
+ tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
+ tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
+ tools.Append(tool_files)
+
+ srcs := android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)
+
+ var allReplacements bazel.LabelList
+ allReplacements.Append(tools)
+ allReplacements.Append(srcs)
+
+ // Replace in and out variables with $< and $@
+ var cmd string
+ if m.properties.Cmd != nil {
+ cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
+ cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
+ cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
+ if len(tools.Includes) > 0 {
+ cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Includes[0].Label), -1)
+ cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Includes[0].Label), -1)
+ }
+ for _, l := range allReplacements.Includes {
+ bpLoc := fmt.Sprintf("$(location %s)", l.Bp_text)
+ bpLocs := fmt.Sprintf("$(locations %s)", l.Bp_text)
+ bazelLoc := fmt.Sprintf("$(location %s)", l.Label)
+ bazelLocs := fmt.Sprintf("$(locations %s)", l.Label)
+ cmd = strings.Replace(cmd, bpLoc, bazelLoc, -1)
+ cmd = strings.Replace(cmd, bpLocs, bazelLocs, -1)
+ }
+ }
+
+ // The Out prop is not in an immediately accessible field
+ // in the Module struct, so use GetProperties and cast it
+ // to the known struct prop.
+ var outs []string
+ for _, propIntf := range m.GetProperties() {
+ if props, ok := propIntf.(*genRuleProperties); ok {
+ outs = props.Out
+ break
+ }
+ }
+
+ // Create the BazelTargetModule.
+ ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
+ Name: proptools.StringPtr(name),
+ Srcs: srcs,
+ Outs: outs,
+ Cmd: cmd,
+ Tools: tools,
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "genrule",
+ })
}
func (m *bazelGenrule) Name() string {
diff --git a/java/dex.go b/java/dex.go
index 055d479..24600c2 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -263,10 +263,10 @@
}
func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion sdkSpec,
- classesJar android.Path, jarName string) android.ModuleOutPath {
+ classesJar android.Path, jarName string) android.OutputPath {
// Compile classes.jar into classes.dex and then javalib.jar
- javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
+ javalibJar := android.PathForModuleOut(ctx, "dex", jarName).OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
zipFlags := "--ignore_missing_files"
@@ -329,7 +329,7 @@
})
}
if proptools.Bool(d.dexProperties.Uncompress_dex) {
- alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName)
+ alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName).OutputPath
TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
javalibJar = alignedJavalibJar
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index ac00592..29c73c1 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -118,7 +118,7 @@
return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
}
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) {
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
// the dexpreopter struct hasn't been fully initialized before we're called,
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
@@ -129,8 +129,6 @@
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
- buildPath := android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath
-
providesUsesLib := ctx.ModuleName()
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
name := ulib.ProvidesUsesLib()
@@ -146,7 +144,6 @@
slimDexpreoptConfig := &dexpreopt.ModuleConfig{
Name: ctx.ModuleName(),
DexLocation: dexLocation,
- BuildPath: buildPath,
EnforceUsesLibraries: d.enforceUsesLibs,
ProvidesUsesLibrary: providesUsesLib,
ClassLoaderContexts: d.classLoaderContexts,
@@ -218,7 +215,7 @@
dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: ctx.ModuleName(),
DexLocation: dexLocation,
- BuildPath: buildPath,
+ BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
DexPath: dexJarFile,
ManifestPath: d.manifestFile,
UncompressedDex: d.uncompressedDex,
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 2cd025e..eafbf5d 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -89,8 +89,8 @@
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
-func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bool, dexJar android.ModuleOutPath,
- implementationJar android.Path, uncompressDex bool) android.ModuleOutPath {
+func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bool, dexJar android.OutputPath,
+ implementationJar android.Path, uncompressDex bool) android.OutputPath {
if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
// Modules whose names are of the format <x>-hiddenapi provide hiddenapi information
@@ -116,7 +116,7 @@
// hiddenapi information for a module on the boot jars list then encode
// the gathered information in the generated dex file.
if name == bootJarName {
- hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar")
+ hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath
// More than one library with the same classes can be encoded but only one can
// be added to the global set of flags, otherwise it will result in duplicate
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 0f9ef58..27f363e 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -65,7 +65,7 @@
srcs: ["a.java"],
compile_dex: true,
}
- `, []string{":foo"}, nil)
+ `, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -82,7 +82,7 @@
jars: ["a.jar"],
compile_dex: true,
}
- `, []string{":foo"}, nil)
+ `, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -106,7 +106,7 @@
compile_dex: true,
prefer: false,
}
- `, []string{":foo"}, nil)
+ `, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -135,7 +135,7 @@
compile_dex: true,
prefer: true,
}
- `, []string{":foo"}, nil)
+ `, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
@@ -236,7 +236,7 @@
jars: ["a.jar"],
compile_dex: true,
}
- `, []string{":foo"}, &prebuiltHiddenApiDir)
+ `, []string{"platform:foo"}, &prebuiltHiddenApiDir)
expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv"
diff --git a/java/java.go b/java/java.go
index 59ec94d..91944f6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1689,35 +1689,44 @@
// Combine the classes built from sources, any manifests, and any static libraries into
// classes.jar. If there is only one input jar this step will be skipped.
- var outputFile android.ModuleOutPath
+ var outputFile android.OutputPath
if len(jars) == 1 && !manifest.Valid() {
+ // Optimization: skip the combine step as there is nothing to do
+ // TODO(ccross): this leaves any module-info.class files, but those should only come from
+ // prebuilt dependencies until we support modules in the platform build, so there shouldn't be
+ // any if len(jars) == 1.
+
+ // Transform the single path to the jar into an OutputPath as that is required by the following
+ // code.
if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
- // Optimization: skip the combine step if there is nothing to do
- // TODO(ccross): this leaves any module-info.class files, but those should only come from
- // prebuilt dependencies until we support modules in the platform build, so there shouldn't be
- // any if len(jars) == 1.
- outputFile = moduleOutPath
+ // The path contains an embedded OutputPath so reuse that.
+ outputFile = moduleOutPath.OutputPath
+ } else if outputPath, ok := jars[0].(android.OutputPath); ok {
+ // The path is an OutputPath so reuse it directly.
+ outputFile = outputPath
} else {
+ // The file is not in the out directory so create an OutputPath into which it can be copied
+ // and which the following code can use to refer to it.
combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: jars[0],
Output: combinedJar,
})
- outputFile = combinedJar
+ outputFile = combinedJar.OutputPath
}
} else {
combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
false, nil, nil)
- outputFile = combinedJar
+ outputFile = combinedJar.OutputPath
}
// jarjar implementation jar if necessary
if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
- jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName)
+ jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName).OutputPath
TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
outputFile = jarjarFile
@@ -1762,7 +1771,7 @@
implementationAndResourcesJar := outputFile
if j.resourceJar != nil {
jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
- combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
false, nil, nil)
implementationAndResourcesJar = combinedJar
@@ -1788,7 +1797,7 @@
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
- var dexOutputFile android.ModuleOutPath
+ var dexOutputFile android.OutputPath
dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
@@ -1807,11 +1816,11 @@
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
- combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
- combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
dexOutputFile = combinedAlignedJar
} else {
@@ -1875,7 +1884,7 @@
jarName += strconv.Itoa(idx)
}
- classes := android.PathForModuleOut(ctx, "javac", jarName)
+ classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
if ctx.Config().EmitXrefRules() {
@@ -1955,12 +1964,12 @@
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.ModuleOutPath {
+ classesJar android.Path, jarName string) android.OutputPath {
specs := j.jacocoModuleToZipCommand(ctx)
jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
- instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)
+ instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
@@ -2374,7 +2383,7 @@
// list of files or filegroup modules that provide data that should be installed alongside
// the test
- Data []string `android:"path"`
+ Data []string `android:"path,arch_variant"`
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
@@ -2678,9 +2687,10 @@
}
func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Arch().ArchType == android.Common {
+ if ctx.Arch().ArchType == android.Common || ctx.BazelConversionMode() {
j.deps(ctx)
- } else {
+ }
+ if ctx.Arch().ArchType != android.Common || ctx.BazelConversionMode() {
// These dependencies ensure the host installation rules will install the jar file and
// the jni libraries when the wrapper is installed.
ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
@@ -2937,7 +2947,7 @@
}
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
- var dexOutputFile android.ModuleOutPath
+ var dexOutputFile android.OutputPath
dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
diff --git a/java/proto.go b/java/proto.go
index dc5519f..652a4da 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -82,7 +82,7 @@
case "lite", "":
ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-lite")
case "full":
- if ctx.Host() {
+ if ctx.Host() || ctx.BazelConversionMode() {
ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-full")
} else {
ctx.PropertyErrorf("proto.type", "full java protos only supported on the host")
diff --git a/kernel/Android.bp b/kernel/Android.bp
new file mode 100644
index 0000000..f8a48d9
--- /dev/null
+++ b/kernel/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+ name: "soong-kernel",
+ pkgPath: "android/soong/kernel",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-cc-config",
+ ],
+ srcs: [
+ "prebuilt_kernel_modules.go",
+ ],
+ testSrcs: [
+ "prebuilt_kernel_modules_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
new file mode 100644
index 0000000..14ac021
--- /dev/null
+++ b/kernel/prebuilt_kernel_modules.go
@@ -0,0 +1,166 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 kernel
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+ _ "android/soong/cc/config"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ android.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
+ pctx.Import("android/soong/cc/config")
+}
+
+type prebuiltKernelModules struct {
+ android.ModuleBase
+
+ properties prebuiltKernelModulesProperties
+
+ installDir android.InstallPath
+}
+
+type prebuiltKernelModulesProperties struct {
+ // List or filegroup of prebuilt kernel module files. Should have .ko suffix.
+ Srcs []string `android:"path,arch_variant"`
+
+ // Kernel version that these modules are for. Kernel modules are installed to
+ // /lib/modules/<kernel_version> directory in the corresponding partition. Default is "".
+ Kernel_version *string
+}
+
+// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory.
+// In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias
+// using depmod and installs them as well.
+func prebuiltKernelModulesFactory() android.Module {
+ module := &prebuiltKernelModules{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+func (pkm *prebuiltKernelModules) KernelVersion() string {
+ return proptools.StringDefault(pkm.properties.Kernel_version, "")
+}
+
+func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // do nothing
+}
+
+func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs)
+
+ depmodOut := runDepmod(ctx, modules)
+ strippedModules := stripDebugSymbols(ctx, modules)
+
+ installDir := android.PathForModuleInstall(ctx, "lib", "modules")
+ if pkm.KernelVersion() != "" {
+ installDir = installDir.Join(ctx, pkm.KernelVersion())
+ }
+
+ for _, m := range strippedModules {
+ ctx.InstallFile(installDir, filepath.Base(m.String()), m)
+ }
+ ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad)
+ ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep)
+ ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep)
+ ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias)
+}
+
+var (
+ pctx = android.NewPackageContext("android/soong/kernel")
+
+ stripRule = pctx.AndroidStaticRule("strip",
+ blueprint.RuleParams{
+ Command: "$stripCmd -o $out --strip-debug $in",
+ CommandDeps: []string{"$stripCmd"},
+ }, "stripCmd")
+)
+
+func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths {
+ dir := android.PathForModuleOut(ctx, "stripped").OutputPath
+ var outputs android.OutputPaths
+
+ for _, m := range modules {
+ stripped := dir.Join(ctx, filepath.Base(m.String()))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: stripRule,
+ Input: m,
+ Output: stripped,
+ Args: map[string]string{
+ "stripCmd": "${config.ClangBin}/llvm-strip",
+ },
+ })
+ outputs = append(outputs, stripped)
+ }
+
+ return outputs
+}
+
+type depmodOutputs struct {
+ modulesLoad android.OutputPath
+ modulesDep android.OutputPath
+ modulesSoftdep android.OutputPath
+ modulesAlias android.OutputPath
+}
+
+func runDepmod(ctx android.ModuleContext, modules android.Paths) depmodOutputs {
+ baseDir := android.PathForModuleOut(ctx, "depmod").OutputPath
+ fakeVer := "0.0" // depmod demands this anyway
+ modulesDir := baseDir.Join(ctx, "lib", "modules", fakeVer)
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+
+ // Copy the module files to a temporary dir
+ builder.Command().Text("rm").Flag("-rf").Text(modulesDir.String())
+ builder.Command().Text("mkdir").Flag("-p").Text(modulesDir.String())
+ for _, m := range modules {
+ builder.Command().Text("cp").Input(m).Text(modulesDir.String())
+ }
+
+ // Enumerate modules to load
+ modulesLoad := modulesDir.Join(ctx, "modules.load")
+ var basenames []string
+ for _, m := range modules {
+ basenames = append(basenames, filepath.Base(m.String()))
+ }
+ builder.Command().
+ Text("echo").Flag("\"" + strings.Join(basenames, " ") + "\"").
+ Text("|").Text("tr").Flag("\" \"").Flag("\"\\n\"").
+ Text(">").Output(modulesLoad)
+
+ // Run depmod to build modules.dep/softdep/alias files
+ modulesDep := modulesDir.Join(ctx, "modules.dep")
+ modulesSoftdep := modulesDir.Join(ctx, "modules.softdep")
+ modulesAlias := modulesDir.Join(ctx, "modules.alias")
+ builder.Command().
+ BuiltTool("depmod").
+ FlagWithArg("-b ", baseDir.String()).
+ Text(fakeVer).
+ ImplicitOutput(modulesDep).
+ ImplicitOutput(modulesSoftdep).
+ ImplicitOutput(modulesAlias)
+
+ builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName()))
+
+ return depmodOutputs{modulesLoad, modulesDep, modulesSoftdep, modulesAlias}
+}
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
new file mode 100644
index 0000000..433548b
--- /dev/null
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -0,0 +1,129 @@
+// 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 kernel
+
+import (
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func testKernelModules(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+ bp = bp + `
+ cc_binary_host {
+ name: "depmod",
+ srcs: ["depmod.cpp"],
+ stl: "none",
+ static_executable: true,
+ system_shared_libs: [],
+ }
+ `
+ bp = bp + cc.GatherRequiredDepsForTest(android.Android)
+
+ fs["depmod.cpp"] = nil
+ cc.GatherRequiredFilesForTest(fs)
+
+ config := android.TestArchConfig(buildDir, nil, bp, fs)
+
+ ctx := android.NewTestArchContext(config)
+ ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
+ ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ cc.RegisterRequiredBuildComponentsForTest(ctx)
+
+ ctx.Register()
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ return ctx, config
+}
+
+func ensureListContains(t *testing.T, result []string, expected string) {
+ t.Helper()
+ if !android.InList(expected, result) {
+ t.Errorf("%q is not found in %v", expected, result)
+ }
+}
+
+func ensureContains(t *testing.T, result string, expected string) {
+ t.Helper()
+ if !strings.Contains(result, expected) {
+ t.Errorf("%q is not found in %q", expected, result)
+ }
+}
+
+func TestKernelModulesFilelist(t *testing.T) {
+ ctx, _ := testKernelModules(t, `
+ prebuilt_kernel_modules {
+ name: "foo",
+ srcs: ["*.ko"],
+ kernel_version: "5.10",
+ }
+ `,
+ map[string][]byte{
+ "mod1.ko": nil,
+ "mod2.ko": nil,
+ })
+
+ expected := []string{
+ "lib/modules/5.10/mod1.ko",
+ "lib/modules/5.10/mod2.ko",
+ "lib/modules/5.10/modules.load",
+ "lib/modules/5.10/modules.dep",
+ "lib/modules/5.10/modules.softdep",
+ "lib/modules/5.10/modules.alias",
+ }
+
+ var actual []string
+ for _, ps := range ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().PackagingSpecs() {
+ actual = append(actual, ps.RelPathInPackage())
+ }
+ actual = android.SortedUniqueStrings(actual)
+ expected = android.SortedUniqueStrings(expected)
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("\ngot: %v\nexpected: %v\n", actual, expected)
+ }
+}
+
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_kernel_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
diff --git a/rust/binary.go b/rust/binary.go
index 3545424..df48916 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -133,7 +133,7 @@
return outputFile
}
-func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
// Binaries default to dylib dependencies for device, rlib for host.
if binary.preferRlib() {
return rlibAutoDep
diff --git a/rust/fuzz.go b/rust/fuzz.go
index da8f209..6035e68 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -91,6 +91,6 @@
return RlibLinkage
}
-func (fuzzer *fuzzDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (fuzzer *fuzzDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
return rlibAutoDep
}
diff --git a/rust/image.go b/rust/image.go
index 5ff10ae..ac8c1b3 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -71,6 +71,15 @@
return Bool(mod.VendorProperties.Vendor_available) || Bool(mod.VendorProperties.Odm_available)
}
+// Always returns false because rust modules do not support product variant.
+func (mod *Module) HasProductVariant() bool {
+ return Bool(mod.VendorProperties.Product_available)
+}
+
+func (mod *Module) HasNonSystemVariants() bool {
+ return mod.HasVendorVariant() || mod.HasProductVariant()
+}
+
func (c *Module) InProduct() bool {
return false
}
diff --git a/rust/library.go b/rust/library.go
index 22d9f7e..7ff13ec 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -219,13 +219,17 @@
library.MutatedProperties.VariantIsSource = true
}
-func (library *libraryDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
if library.preferRlib() {
return rlibAutoDep
} else if library.rlib() || library.static() {
return rlibAutoDep
} else if library.dylib() || library.shared() {
return dylibAutoDep
+ } else if ctx.BazelConversionMode() {
+ // In Bazel conversion mode, we are currently ignoring the deptag, so we just need to supply a
+ // compatible tag in order to add the dependency.
+ return rlibAutoDep
} else {
panic(fmt.Errorf("autoDep called on library %q that has no enabled variants.", ctx.ModuleName()))
}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index f753e7f..115045a 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -79,6 +79,6 @@
return stem + String(procMacro.baseCompiler.Properties.Suffix)
}
-func (procMacro *procMacroDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (procMacro *procMacroDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
return rlibAutoDep
}
diff --git a/rust/rust.go b/rust/rust.go
index f82dd54..e1af776 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -783,7 +783,7 @@
)
type autoDeppable interface {
- autoDep(ctx BaseModuleContext) autoDep
+ autoDep(ctx android.BottomUpMutatorContext) autoDep
}
func (mod *Module) begin(ctx BaseModuleContext) {
diff --git a/rust/test.go b/rust/test.go
index 92b4860..3fa5f95 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -141,7 +141,7 @@
return flags
}
-func (test *testDecorator) autoDep(ctx BaseModuleContext) autoDep {
+func (test *testDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
return rlibAutoDep
}
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index ea62af4..b8485ea 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -61,6 +61,9 @@
esac
}
+# Make sure this build builds from source, regardless of the default.
+export SOONG_CONFIG_art_module_source_build=true
+
OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 18749b5..66e493b 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -154,9 +154,6 @@
}
func (s *ShBinary) DepsMutator(ctx android.BottomUpMutatorContext) {
- if s.properties.Src == nil {
- ctx.PropertyErrorf("src", "missing prebuilt source file")
- }
}
func (s *ShBinary) OutputFile() android.OutputPath {
@@ -203,6 +200,10 @@
}
func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
+ if s.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ }
+
s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
filename := proptools.String(s.properties.Filename)
filenameFromSrc := proptools.Bool(s.properties.Filename_from_src)
@@ -275,7 +276,7 @@
ctx.AddFarVariationDependencies(ctx.Target().Variations(), shTestDataBinsTag, s.testProperties.Data_bins...)
ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...),
shTestDataLibsTag, s.testProperties.Data_libs...)
- if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 {
+ if (ctx.Target().Os.Class == android.Host || ctx.BazelConversionMode()) && len(ctx.Config().Targets[android.Android]) > 0 {
deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...)
ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...),