Merge "Remove unused dist-related variables" into main
diff --git a/Android.bp b/Android.bp
index 523f55c..6c40661 100644
--- a/Android.bp
+++ b/Android.bp
@@ -147,16 +147,6 @@
// Framework guests.
cc_defaults {
name: "cc_baremetal_defaults",
- arch: {
- arm64: {
- cflags: [
- // Prevent the compiler from optimizing code using SVE, as the
- // baremetal environment might not have configured the hardware.
- "-Xclang -target-feature",
- "-Xclang -sve",
- ],
- },
- },
defaults_visibility: ["//visibility:public"],
}
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index 6e2964a..40aeee4 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -17,6 +17,7 @@
"aconfig_values.go",
"aconfig_value_set.go",
"all_aconfig_declarations.go",
+ "all_aconfig_declarations_extension.go",
"exported_java_aconfig_library.go",
"init.go",
"testing.go",
@@ -25,6 +26,7 @@
"aconfig_declarations_test.go",
"aconfig_values_test.go",
"aconfig_value_set_test.go",
+ "all_aconfig_declarations_extension_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index ec20099..b17820e 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -20,6 +20,7 @@
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -37,12 +38,18 @@
return module
}
+type allAconfigDeclarationsInfo struct {
+ parsedFlagsFile android.Path
+}
+
+var allAconfigDeclarationsInfoProvider = blueprint.NewProvider[allAconfigDeclarationsInfo]()
+
type allAconfigReleaseDeclarationsSingleton struct {
intermediateBinaryProtoPath android.OutputPath
intermediateTextProtoPath android.OutputPath
}
-type allAconfigReleaseDeclarationsProperties struct {
+type ApiSurfaceContributorProperties struct {
Api_signature_files proptools.Configurable[[]string] `android:"arch_variant,path"`
Finalized_flags_file string `android:"arch_variant,path"`
}
@@ -51,7 +58,9 @@
android.SingletonModuleBase
releaseMap map[string]allAconfigReleaseDeclarationsSingleton
- properties allAconfigReleaseDeclarationsProperties
+ properties ApiSurfaceContributorProperties
+
+ finalizedFlags android.OutputPath
}
func (this *allAconfigDeclarationsSingleton) sortedConfigNames() []string {
@@ -63,29 +72,38 @@
return names
}
-func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath android.WritablePath,
+ parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) {
+
apiSignatureFiles := android.Paths{}
- for _, apiSignatureFile := range this.properties.Api_signature_files.GetOrDefault(ctx, nil) {
+ for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) {
if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil {
apiSignatureFiles = append(apiSignatureFiles, path)
}
}
- finalizedFlagsFile := android.PathForModuleSrc(ctx, this.properties.Finalized_flags_file)
- parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
-
- output := android.PathForIntermediates(ctx, "finalized-flags.txt")
+ finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file)
ctx.Build(pctx, android.BuildParams{
Rule: RecordFinalizedFlagsRule,
Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile),
- Output: output,
+ Output: outputPath,
Args: map[string]string{
"api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "),
"finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(),
"parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(),
},
})
- ctx.Phony("all_aconfig_declarations", output)
+}
+
+func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
+ this.finalizedFlags = android.PathForIntermediates(ctx, "finalized-flags.txt")
+ GenerateFinalizedFlagsForApiSurface(ctx, this.finalizedFlags, parsedFlagsFile, this.properties)
+ ctx.Phony("all_aconfig_declarations", this.finalizedFlags)
+
+ android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{
+ parsedFlagsFile: parsedFlagsFile,
+ })
}
func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx android.SingletonContext) {
@@ -154,5 +172,5 @@
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
}
}
- ctx.DistForGoalWithFilename("sdk", android.PathForIntermediates(ctx, "finalized-flags.txt"), "finalized-flags.txt")
+ ctx.DistForGoalWithFilename("sdk", this.finalizedFlags, "finalized-flags.txt")
}
diff --git a/aconfig/all_aconfig_declarations_extension.go b/aconfig/all_aconfig_declarations_extension.go
new file mode 100644
index 0000000..44992cd
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension.go
@@ -0,0 +1,90 @@
+// Copyright 2025 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 aconfig
+
+import (
+ "android/soong/android"
+ "path"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func AllAconfigDeclarationsExtensionFactory() android.Module {
+ module := &allAconfigDeclarationsExtension{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type allAconfigDeclarationsExtensionProperties struct {
+ // all_aconfig_declarations module that this module extends. Defaults to
+ // all_aconfig_declarations.
+ Base *string
+
+ // Directory where the dist artifact should be placed in.
+ Dist_dir *string
+
+ ApiSurfaceContributorProperties
+}
+
+type allAconfigDeclarationsExtension struct {
+ android.ModuleBase
+
+ properties allAconfigDeclarationsExtensionProperties
+
+ finalizedFlags android.ModuleOutPath
+}
+
+type allAconfigDeclarationsDependencyTagStruct struct {
+ blueprint.BaseDependencyTag
+}
+
+var allAconfigDeclarationsDependencyTag allAconfigDeclarationsDependencyTagStruct
+
+func (ext *allAconfigDeclarationsExtension) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), allAconfigDeclarationsDependencyTag, proptools.StringDefault(ext.properties.Base, "all_aconfig_declarations"))
+}
+
+func (ext *allAconfigDeclarationsExtension) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+ var parsedFlagsFile android.Path
+ ctx.VisitDirectDepsProxyWithTag(allAconfigDeclarationsDependencyTag, func(proxy android.ModuleProxy) {
+ if info, ok := android.OtherModuleProvider(ctx, proxy, allAconfigDeclarationsInfoProvider); ok {
+ parsedFlagsFile = info.parsedFlagsFile
+ } else {
+ ctx.PropertyErrorf("base", "base must provide allAconfigDeclarationsInfo")
+ }
+ })
+
+ ext.finalizedFlags = android.PathForModuleOut(ctx, "finalized-flags.txt")
+
+ GenerateFinalizedFlagsForApiSurface(ctx,
+ ext.finalizedFlags,
+ parsedFlagsFile,
+ ext.properties.ApiSurfaceContributorProperties,
+ )
+
+ ctx.Phony(ctx.ModuleName(), ext.finalizedFlags)
+
+ // This module must not set any provider or call `ctx.SetOutputFiles`!
+ // This module is only used to depend on the singleton module all_aconfig_declarations and
+ // generate the custom finalized-flags.txt file in dist builds, and should not be depended
+ // by other modules.
+}
+
+func (ext *allAconfigDeclarationsExtension) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoalWithFilename("sdk", ext.finalizedFlags, path.Join(proptools.String(ext.properties.Dist_dir), "finalized-flags.txt"))
+}
diff --git a/aconfig/all_aconfig_declarations_extension_test.go b/aconfig/all_aconfig_declarations_extension_test.go
new file mode 100644
index 0000000..1207096
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension_test.go
@@ -0,0 +1,50 @@
+// Copyright 2025 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 aconfig
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestAllAconfigDeclarationsExtension(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ android.MockFS{
+ "a.txt": nil,
+ "flags.txt": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ all_aconfig_declarations {
+ name: "all_aconfig_declarations",
+ }
+
+ all_aconfig_declarations_extension {
+ name: "custom_aconfig_declarations",
+ base: "all_aconfig_declarations",
+ api_signature_files: [
+ "a.txt",
+ ],
+ finalized_flags_file: "flags.txt",
+ }
+ `)
+
+ finalizedFlags := result.ModuleForTests("custom_aconfig_declarations", "").Output("finalized-flags.txt")
+ android.AssertStringContainsEquals(t, "must depend on all_aconfig_declarations", strings.Join(finalizedFlags.Inputs.Strings(), " "), "all_aconfig_declarations.pb", true)
+}
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go
index 3b40755..e76db49 100644
--- a/aconfig/build_flags/build_flags_singleton.go
+++ b/aconfig/build_flags/build_flags_singleton.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "fmt"
)
// A singleton module that collects all of the build flags declared in the
@@ -120,4 +121,26 @@
ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
ctx.DistForGoalWithFilename(goal, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
}
+
+ if ctx.Config().HasDeviceProduct() {
+ flagsDir := android.PathForOutput(ctx, "release-config")
+ baseAllRelease := fmt.Sprintf("all_release_configs-%s", ctx.Config().DeviceProduct())
+
+ distAllReleaseConfigsArtifact := func(ext string) {
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("%s.%s", baseAllRelease, ext)),
+ fmt.Sprintf("build_flags/all_release_configs.%s", ext),
+ )
+ }
+
+ distAllReleaseConfigsArtifact("pb")
+ distAllReleaseConfigsArtifact("textproto")
+ distAllReleaseConfigsArtifact("json")
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("inheritance_graph-%s.dot", ctx.Config().DeviceProduct())),
+ fmt.Sprintf("build_flags/inheritance_graph-%s.dot", ctx.Config().DeviceProduct()),
+ )
+ }
}
diff --git a/aconfig/init.go b/aconfig/init.go
index 3dcec5c..b2fe5a3 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -104,6 +104,7 @@
` --mode=exported` +
` --allow-instrumentation ${use_new_storage}` +
` --new-exported ${use_new_exported}` +
+ ` --single-exported-file true` +
` --check-api-level ${check_api_level}` +
` --out ${out}.tmp; ` +
` fi ` +
@@ -131,4 +132,5 @@
ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
ctx.RegisterSingletonModuleType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
ctx.RegisterParallelSingletonType("exported_java_aconfig_library", ExportedJavaDeclarationsLibraryFactory)
+ ctx.RegisterModuleType("all_aconfig_declarations_extension", AllAconfigDeclarationsExtensionFactory)
}
diff --git a/android/module.go b/android/module.go
index 80275a3..3295e93 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1091,6 +1091,10 @@
InstallAlwaysNeededDependencyTag
}{}
+func IsVintfDepTag(depTag blueprint.DependencyTag) bool {
+ return depTag == vintfDepTag
+}
+
func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
// Vintf manifests in the recovery partition will be ignored.
if !ctx.Device() || ctx.Module().InstallInRecovery() {
@@ -1109,7 +1113,7 @@
// of nil pointer dereference errors, but we should resolve the missing dependencies.
continue
}
- if vintfModule, ok := vintf.(*vintfFragmentModule); ok {
+ if vintfModule, ok := vintf.(*VintfFragmentModule); ok {
vintfPartition := vintfModule.PartitionTag(deviceConfig)
if modPartition != vintfPartition {
ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
diff --git a/android/mutator.go b/android/mutator.go
index 76487fb..d6166d2 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -67,7 +67,6 @@
}
type RegisterMutatorsContext interface {
- TopDown(name string, m TopDownMutator) MutatorHandle
BottomUp(name string, m BottomUpMutator) MutatorHandle
BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle
Transition(name string, m VariationTransitionMutator) TransitionMutatorHandle
@@ -195,17 +194,6 @@
finalDeps = append(finalDeps, f)
}
-type TopDownMutator func(TopDownMutatorContext)
-
-type TopDownMutatorContext interface {
- BaseModuleContext
-}
-
-type topDownMutatorContext struct {
- bp blueprint.TopDownMutatorContext
- baseModuleContext
-}
-
type BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
@@ -281,8 +269,8 @@
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
-// for each transition mutator. bottomUpMutatorContext and topDownMutatorContext are created once for every module
-// for every BottomUp or TopDown mutator. Use a global pool for each to avoid reallocating every time.
+// for each transition mutator. bottomUpMutatorContext is created once for every module for every BottomUp mutator.
+// Use a global pool for each to avoid reallocating every time.
var (
outgoingTransitionContextPool = sync.Pool{
New: func() any { return &outgoingTransitionContextImpl{} },
@@ -293,10 +281,6 @@
bottomUpMutatorContextPool = sync.Pool{
New: func() any { return &bottomUpMutatorContext{} },
}
-
- topDownMutatorContextPool = sync.Pool{
- New: func() any { return &topDownMutatorContext{} },
- }
)
type bottomUpMutatorContext struct {
@@ -371,24 +355,6 @@
return name
}
-func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
- f := func(ctx blueprint.TopDownMutatorContext) {
- if a, ok := ctx.Module().(Module); ok {
- moduleContext := a.base().baseModuleContextFactory(ctx)
- actx := topDownMutatorContextPool.Get().(*topDownMutatorContext)
- defer topDownMutatorContextPool.Put(actx)
- *actx = topDownMutatorContext{
- bp: ctx,
- baseModuleContext: moduleContext,
- }
- m(actx)
- }
- }
- mutator := &mutator{name: x.mutatorName(name), topDownMutator: f}
- x.mutators = append(x.mutators, mutator)
- return mutator
-}
-
func (mutator *mutator) componentName() string {
return mutator.name
}
@@ -398,8 +364,6 @@
var handle blueprint.MutatorHandle
if mutator.bottomUpMutator != nil {
handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
- } else if mutator.topDownMutator != nil {
- handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
} else if mutator.transitionMutator != nil {
handle := blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
if mutator.neverFar {
@@ -529,11 +493,11 @@
ctx.BottomUp("deps", depsMutator).UsesReverseDependencies()
}
-// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
+// android.bottomUpMutatorContext either has to embed blueprint.BottomUpMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
-// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
+// ambiguous method errors, or it has to store a blueprint.BottomUpMutatorContext non-embedded, in which case every
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
-// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
+// methods forward to the identical blueprint versions for bottomUpMutatorContext.
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 60a6119..123c6b2 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -54,7 +54,7 @@
ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
}
-func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
+func addMissingDependenciesMutator(ctx BottomUpMutatorContext) {
ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
}
@@ -72,7 +72,7 @@
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
+ ctx.BottomUp("add_missing_dependencies", addMissingDependenciesMutator)
})
}),
FixtureWithRootAndroidBp(bp),
diff --git a/android/provider.go b/android/provider.go
index 81d17a1..b48fd91 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -4,8 +4,8 @@
"github.com/google/blueprint"
)
-// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in OtherModuleProvider.
+// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in OtherModuleProvider.
type OtherModuleProviderContext interface {
otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
}
@@ -13,7 +13,6 @@
var _ OtherModuleProviderContext = BaseModuleContext(nil)
var _ OtherModuleProviderContext = ModuleContext(nil)
var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
-var _ OtherModuleProviderContext = TopDownMutatorContext(nil)
var _ OtherModuleProviderContext = SingletonContext(nil)
var _ OtherModuleProviderContext = (*TestContext)(nil)
@@ -21,8 +20,7 @@
// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
//
-// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// OtherModuleProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
value, ok := ctx.otherModuleProvider(getWrappedModule(module), provider)
if !ok {
@@ -37,8 +35,8 @@
return value
}
-// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in ModuleProvider.
+// ModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in ModuleProvider.
type ModuleProviderContext interface {
provider(provider blueprint.AnyProviderKey) (any, bool)
}
@@ -46,14 +44,12 @@
var _ ModuleProviderContext = BaseModuleContext(nil)
var _ ModuleProviderContext = ModuleContext(nil)
var _ ModuleProviderContext = BottomUpMutatorContext(nil)
-var _ ModuleProviderContext = TopDownMutatorContext(nil)
// ModuleProvider reads the provider for the current module. If the provider has been set the value is
// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
//
-// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// ModuleProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func ModuleProvider[K any](ctx ModuleProviderContext, provider blueprint.ProviderKey[K]) (K, bool) {
value, ok := ctx.provider(provider)
if !ok {
@@ -63,8 +59,8 @@
return value.(K), ok
}
-// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in SetProvider.
+// SetProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in SetProvider.
type SetProviderContext interface {
setProvider(provider blueprint.AnyProviderKey, value any)
}
@@ -72,15 +68,13 @@
var _ SetProviderContext = BaseModuleContext(nil)
var _ SetProviderContext = ModuleContext(nil)
var _ SetProviderContext = BottomUpMutatorContext(nil)
-var _ SetProviderContext = TopDownMutatorContext(nil)
// SetProvider sets the value for a provider for the current module. It panics if not called
// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
// is not of the appropriate type, or if the value has already been set. The value should not
// be modified after being passed to SetProvider.
//
-// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// SetProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func SetProvider[K any](ctx SetProviderContext, provider blueprint.ProviderKey[K], value K) {
ctx.setProvider(provider, value)
}
diff --git a/android/register.go b/android/register.go
index 332ec27..10c9114 100644
--- a/android/register.go
+++ b/android/register.go
@@ -89,7 +89,6 @@
type mutator struct {
name string
bottomUpMutator blueprint.BottomUpMutator
- topDownMutator blueprint.TopDownMutator
transitionMutator blueprint.TransitionMutator
usesRename bool
diff --git a/android/util.go b/android/util.go
index 30d8ec6..e8d9301 100644
--- a/android/util.go
+++ b/android/util.go
@@ -221,13 +221,13 @@
diff2 := []T{}
m1 := setFromList(l1)
m2 := setFromList(l2)
- for t := range m1 {
+ for _, t := range l1 {
if _, ok := m2[t]; !ok {
diff1 = append(diff1, t)
listsDiffer = true
}
}
- for t := range m2 {
+ for _, t := range l2 {
if _, ok := m1[t]; !ok {
diff2 = append(diff2, t)
listsDiffer = true
diff --git a/android/vintf_fragment.go b/android/vintf_fragment.go
index a3343fd..85beb72 100644
--- a/android/vintf_fragment.go
+++ b/android/vintf_fragment.go
@@ -19,8 +19,9 @@
Src string `android:"path"`
}
-type vintfFragmentModule struct {
+type VintfFragmentModule struct {
ModuleBase
+ ApexModuleBase
properties vintfFragmentProperties
@@ -40,7 +41,7 @@
// Vintf fragment files formerly listed in vintf_fragment property would be transformed into
// this module type.
func vintfLibraryFactory() Module {
- m := &vintfFragmentModule{}
+ m := &VintfFragmentModule{}
m.AddProperties(
&m.properties,
)
@@ -49,7 +50,7 @@
return m
}
-func (m *vintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+func (m *VintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
builder := NewRuleBuilder(pctx, ctx)
srcVintfFragment := PathForModuleSrc(ctx, m.properties.Src)
processedVintfFragment := PathForModuleOut(ctx, srcVintfFragment.Base())
@@ -69,8 +70,12 @@
ctx.InstallFile(m.installDirPath, processedVintfFragment.Base(), processedVintfFragment)
}
+func (m *VintfFragmentModule) OutputFile() Path {
+ return m.outputFilePath
+}
+
// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files
-func (m *vintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
+func (m *VintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
return []AndroidMkEntries{{
Class: "ETC",
OutputFile: OptionalPathForPath(m.outputFilePath),
@@ -82,3 +87,11 @@
},
}}
}
+
+var _ ApexModule = (*VintfFragmentModule)(nil)
+
+// Implements android.ApexModule
+func (m *VintfFragmentModule) ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error {
+ // VintfFragmetModule is independent from the SDK version.
+ return nil
+}
diff --git a/apex/apex.go b/apex/apex.go
index 33538fb..0481658 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1475,6 +1475,12 @@
return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config)
}
+func apexFileForVintfFragment(ctx android.BaseModuleContext, vintfFragment *android.VintfFragmentModule) apexFile {
+ dirInApex := filepath.Join("etc", "vintf")
+
+ return newApexFile(ctx, vintfFragment.OutputFile(), vintfFragment.BaseModuleName(), dirInApex, etc, vintfFragment)
+}
+
// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same
// way.
type javaModule interface {
@@ -2160,7 +2166,13 @@
// nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
+ } else if android.IsVintfDepTag(depTag) {
+ if vf, ok := child.(*android.VintfFragmentModule); ok {
+ apexFile := apexFileForVintfFragment(ctx, vf)
+ vctx.filesInfo = append(vctx.filesInfo, apexFile)
+ }
}
+
return false
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f88c09e..6c1a2d6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -12184,3 +12184,35 @@
fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
}
+
+func TestVintfFragmentInApex(t *testing.T) {
+ t.Parallel()
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ binaries: [ "mybin" ],
+ updatable: false,
+ }
+
+ cc_binary {
+ name: "mybin",
+ srcs: ["mybin.cpp"],
+ vintf_fragment_modules: ["my_vintf_fragment.xml"],
+ apex_available: [ "myapex" ],
+ }
+
+ vintf_fragment {
+ name: "my_vintf_fragment.xml",
+ src: "my_vintf_fragment.xml",
+ }
+ `)
+
+ generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ // Ensure that vintf fragment file is being installed
+ ensureContains(t, cmd, "/etc/vintf/my_vintf_fragment.xml ")
+}
diff --git a/apex/builder.go b/apex/builder.go
index b34dc84..03a0bb9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -528,9 +528,10 @@
})
}
-func isVintfFragment(fi apexFile) bool {
+func shouldApplyAssembleVintf(fi apexFile) bool {
isVintfFragment, _ := path.Match("etc/vintf/*", fi.path())
- return isVintfFragment
+ _, fromVintfFragmentModule := fi.module.(*android.VintfFragmentModule)
+ return isVintfFragment && !fromVintfFragmentModule
}
func runAssembleVintf(ctx android.ModuleContext, vintfFragment android.Path) android.Path {
@@ -639,7 +640,7 @@
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
// Copy the file into APEX
- if !a.testApex && isVintfFragment(fi) {
+ if !a.testApex && shouldApplyAssembleVintf(fi) {
// copy the output of assemble_vintf instead of the original
vintfFragment := runAssembleVintf(ctx, fi.builtFile)
copyCommands = append(copyCommands, "cp -f "+vintfFragment.String()+" "+destPath)
diff --git a/cc/binary.go b/cc/binary.go
index 4b77bea..c4791c5 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -426,7 +426,7 @@
validations = append(validations, objs.tidyDepFiles...)
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
- if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
+ if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
deps.StaticLibs = append(deps.StaticLibs, generatedLib)
}
diff --git a/cc/builder.go b/cc/builder.go
index 16f006d..f4f8596 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -817,7 +817,7 @@
}
// Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty.
-func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
+func GenerateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 {
// This should only be reachable if a module defines Rust deps in static_libs and
// soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests).
diff --git a/cc/library.go b/cc/library.go
index dce3b92..532b7e9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1237,7 +1237,7 @@
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
- if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
+ if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
if ctx.Module().(*Module).WholeRustStaticlib {
deps.WholeStaticLibs = append(deps.WholeStaticLibs, generatedLib)
} else {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index b783d0f..960c96a 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -153,7 +153,7 @@
}
}
- //a.buildTargetFilesZip(ctx) TODO(b/393203512): re-enable target_files.zip
+ a.buildTargetFilesZip(ctx)
var deps []android.Path
if proptools.String(a.partitionProps.Super_partition_name) != "" {
superImage := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 9f2b239..3f77433 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -537,14 +537,27 @@
f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths)
f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths)
f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths)
+ // Assemeble the staging dir and output a timestamp
+ builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx))
+ builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName()))
+ // Create a new rule builder for build_image
+ builder = android.NewRuleBuilder(pctx, ctx)
var mapFile android.Path
- var outputHermetic android.Path
+ var outputHermetic android.WritablePath
var buildImagePropFile android.Path
var buildImagePropFileDeps android.Paths
switch f.fsType(ctx) {
case ext4Type, erofsType, f2fsType:
- f.output, outputHermetic, buildImagePropFile, buildImagePropFileDeps = f.buildImageUsingBuildImage(ctx, builder, rootDir, rebasedDir)
+ buildImagePropFile, buildImagePropFileDeps = f.buildPropFile(ctx)
+ output := android.PathForModuleOut(ctx, f.installFileName())
+ f.buildImageUsingBuildImage(ctx, builder, buildImageParams{rootDir, buildImagePropFile, buildImagePropFileDeps, output})
+ f.output = output
+ // Create the hermetic img file using a separate rule builder so that it can be built independently
+ hermeticBuilder := android.NewRuleBuilder(pctx, ctx)
+ outputHermetic = android.PathForModuleOut(ctx, "for_target_files", f.installFileName())
+ propFileHermetic := f.propFileForHermeticImg(ctx, hermeticBuilder, buildImagePropFile)
+ f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic})
mapFile = f.getMapFile(ctx)
case compressedCpioType:
f.output = f.buildCpioImage(ctx, builder, rootDir, true)
@@ -590,6 +603,10 @@
f.setVbmetaPartitionProvider(ctx)
}
+func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath {
+ return android.PathForModuleOut(ctx, "staging_dir.timestamp")
+}
+
func (f *filesystem) setVbmetaPartitionProvider(ctx android.ModuleContext) {
var extractedPublicKey android.ModuleOutPath
if f.properties.Avb_private_key != nil {
@@ -783,21 +800,26 @@
return f.partitionName()
}
+type buildImageParams struct {
+ // inputs
+ rootDir android.OutputPath
+ propFile android.Path
+ toolDeps android.Paths
+ // outputs
+ output android.WritablePath
+}
+
func (f *filesystem) buildImageUsingBuildImage(
ctx android.ModuleContext,
builder *android.RuleBuilder,
- rootDir android.OutputPath,
- rebasedDir android.OutputPath,
-) (android.Path, android.Path, android.Path, android.Paths) {
+ params buildImageParams) {
// run host_init_verifier
// Ideally we should have a concept of pluggable linters that verify the generated image.
// While such concept is not implement this will do.
// TODO(b/263574231): substitute with pluggable linter.
builder.Command().
BuiltTool("host_init_verifier").
- FlagWithArg("--out_system=", rootDir.String()+"/system")
-
- propFile, toolDeps := f.buildPropFile(ctx)
+ FlagWithArg("--out_system=", params.rootDir.String()+"/system")
// Most of the time, if build_image were to call a host tool, it accepts the path to the
// host tool in a field in the prop file. However, it doesn't have that option for fec, which
@@ -805,44 +827,32 @@
fec := ctx.Config().HostToolPath(ctx, "fec")
pathToolDirs := []string{filepath.Dir(fec.String())}
- output := android.PathForModuleOut(ctx, f.installFileName())
- builder.Command().Text("touch").Output(f.getMapFile(ctx))
builder.Command().
Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
BuiltTool("build_image").
- Text(rootDir.String()). // input directory
- Input(propFile).
- Implicits(toolDeps).
+ Text(params.rootDir.String()). // input directory
+ Input(params.propFile).
+ Implicits(params.toolDeps).
Implicit(fec).
- Output(output).
- Text(rootDir.String()) // directory where to find fs_config_files|dirs
-
- // TODO (b/393203512): Re-enable hermetic img file creation for target_files.zip
- // Add an additional cmd to create a hermetic img file. This will contain pinned timestamps e.g.
- //propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
- //builder.Command().Textf("cat").Input(propFile).Flag(">").Output(propFilePinnedTimestamp).
- // Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp).
- // Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output
-
- //outputHermetic := android.PathForModuleOut(ctx, "for_target_files", f.installFileName())
- //builder.Command().
- // Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
- // BuiltTool("build_image").
- // Text(rootDir.String()). // input directory
- // Flag(propFilePinnedTimestamp.String()).
- // Implicits(toolDeps).
- // Implicit(fec).
- // Output(outputHermetic).
- // Text(rootDir.String()) // directory where to find fs_config_files|dirs
+ Implicit(f.fileystemStagingDirTimestamp(ctx)). // assemble the staging directory
+ Output(params.output).
+ Text(params.rootDir.String()) // directory where to find fs_config_files|dirs
if f.properties.Partition_size != nil {
- assertMaxImageSize(builder, output, *f.properties.Partition_size, false)
+ assertMaxImageSize(builder, params.output, *f.properties.Partition_size, false)
}
// rootDir is not deleted. Might be useful for quick inspection.
- builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+ builder.Build("build_"+params.output.String(), fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+}
- return output, nil, propFile, toolDeps
+func (f *filesystem) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path {
+ propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
+ builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp).
+ Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp).
+ Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output
+ builder.Command().Text("touch").Output(f.getMapFile(ctx))
+ return propFilePinnedTimestamp
}
func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path {
@@ -1053,6 +1063,7 @@
output := android.PathForModuleOut(ctx, f.installFileName())
cmd := builder.Command().
BuiltTool("mkbootfs").
+ Implicit(f.fileystemStagingDirTimestamp(ctx)).
Text(rootDir.String()) // input directory
for i := range len(rootDirs) {
@@ -1373,3 +1384,9 @@
return true
})
}
+
+func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) {
+ if f.Name() == ctx.Config().SoongDefinedSystemImage() {
+ ctx.StrictRaw("SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String())
+ }
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index d9bf242..37260c1 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -332,7 +332,7 @@
`)
filesystem := result.ModuleForTests("myfilesystem", "android_common_cov")
- inputs := filesystem.Output("myfilesystem.img").Implicits
+ inputs := filesystem.Output("staging_dir.timestamp").Implicits
android.AssertStringListContains(t, "filesystem should have libfoo(cov)",
inputs.Strings(),
"out/soong/.intermediates/libfoo/android_arm64_armv8-a_shared_cov/libfoo.so")
diff --git a/java/base.go b/java/base.go
index d89c324..3a435a1 100644
--- a/java/base.go
+++ b/java/base.go
@@ -2948,14 +2948,18 @@
// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
// to "" won't be in this list because they shouldn't be renamed yet.
func getJarJarRuleText(provider *JarJarProviderData) string {
- result := ""
+ result := strings.Builder{}
for _, orig := range android.SortedKeys(provider.Rename) {
renamed := provider.Rename[orig]
if renamed != "" {
- result += "rule " + orig + " " + renamed + "\n"
+ result.WriteString("rule ")
+ result.WriteString(orig)
+ result.WriteString(" ")
+ result.WriteString(renamed)
+ result.WriteString("\n")
}
}
- return result
+ return result.String()
}
// Repackage the flags if the jarjar rule txt for the flags is generated
diff --git a/phony/phony.go b/phony/phony.go
index 807b95b..4f61c45 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -38,9 +38,11 @@
type phony struct {
android.ModuleBase
+
requiredModuleNames []string
hostRequiredModuleNames []string
targetRequiredModuleNames []string
+ outputDeps android.Paths
}
func PhonyFactory() android.Module {
@@ -54,6 +56,14 @@
p.requiredModuleNames = ctx.RequiredModuleNames(ctx)
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
+
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if o, ok := android.OtherModuleProvider(ctx, dep, android.OutputFilesProvider); ok {
+ p.outputDeps = append(p.outputDeps, o.DefaultOutputFiles...)
+ }
+ })
+
+ ctx.Phony(p.Name(), p.outputDeps...)
}
func (p *phony) AndroidMk() android.AndroidMkData {
@@ -77,6 +87,10 @@
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=",
strings.Join(p.targetRequiredModuleNames, " "))
}
+ if len(p.outputDeps) > 0 {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=",
+ strings.Join(p.outputDeps.Strings(), " "))
+ }
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
for _, extra := range data.Extra {
extra(w, nil)
diff --git a/rust/builder.go b/rust/builder.go
index 8a869aa..1b6a6c1 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -171,7 +171,7 @@
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
}
-// TransformRlibstoStaticlib is assumed to be called from the cc module, and
+// TransformRlibstoStaticlib is assumed to be callable from the cc module, and
// thus needs to reconstruct the common set of flags which need to be passed
// to the rustc compiler.
func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
@@ -185,7 +185,7 @@
rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
}
- ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
+ mod := ctx.Module().(cc.LinkableInterface)
toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
t := transformProperties{
// Crate name can be a predefined value as this is a staticlib and
@@ -195,10 +195,10 @@
crateName: "generated_rust_staticlib",
is64Bit: toolchain.Is64Bit(),
targetTriple: toolchain.RustTriple(),
- bootstrap: ccModule.Bootstrap(),
- inRecovery: ccModule.InRecovery(),
- inRamdisk: ccModule.InRamdisk(),
- inVendorRamdisk: ccModule.InVendorRamdisk(),
+ bootstrap: mod.Bootstrap(),
+ inRecovery: mod.InRecovery(),
+ inRamdisk: mod.InRamdisk(),
+ inVendorRamdisk: mod.InVendorRamdisk(),
// crateType indicates what type of crate to build
crateType: "staticlib",
@@ -402,6 +402,11 @@
linkFlags = append(linkFlags, dynamicLinker)
}
+ if generatedLib := cc.GenerateRustStaticlib(ctx, deps.ccRlibDeps); generatedLib != nil {
+ deps.StaticLibs = append(deps.StaticLibs, generatedLib)
+ linkFlags = append(linkFlags, generatedLib.String())
+ }
+
libFlags := makeLibFlags(deps)
// Collect dependencies
diff --git a/rust/library.go b/rust/library.go
index 24ae8b0..7f5861f 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -737,12 +737,15 @@
if library.rlib() {
library.flagExporter.exportStaticLibs(deps.staticLibObjects...)
}
-
// Since we have FFI rlibs, we need to collect their includes as well
if library.static() || library.shared() || library.rlib() || library.stubs() {
- android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ ccExporter := cc.FlagExporterInfo{
IncludeDirs: android.FirstUniquePaths(library.includeDirs),
- })
+ }
+ if library.rlib() {
+ ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...)
+ }
+ android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter)
}
if library.shared() || library.stubs() {
diff --git a/rust/rust.go b/rust/rust.go
index ad68d60..4eec5d2 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -495,6 +495,10 @@
depFlags []string
depLinkFlags []string
+ // track cc static-libs that have Rlib dependencies
+ reexportedCcRlibDeps []cc.RustRlibDep
+ ccRlibDeps []cc.RustRlibDep
+
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker
// Both of these are exported and propagate to dependencies.
linkDirs []string
@@ -1531,6 +1535,13 @@
}
}
+ if !mod.Rlib() {
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+ } else {
+ // rlibs need to reexport these
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+
case depTag == procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, linkableInfo)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1651,8 +1662,8 @@
} else {
// Otherwise add to staticLibObjects, which only propagate through rlibs to their dependents.
depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())
-
}
+
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
@@ -1660,6 +1671,14 @@
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
+
+ if !mod.Rlib() {
+ // rlibs don't need to build the generated static library, so they don't need to track these.
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+ } else {
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+
directStaticLibDeps = append(directStaticLibDeps, linkableInfo)
// Record baseLibName for snapshots.
@@ -1815,6 +1834,8 @@
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags)
+ depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, cc.EqRustRlibDeps)
+ depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps)
return depPaths
}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 4390f55..2e016f0 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -449,12 +449,26 @@
}
rust_ffi_static {
+ name: "libfoo_from_rlib",
+ crate_name: "foo_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["foo_includes"]
+ }
+
+ rust_ffi_static {
name: "libbuzz",
crate_name: "buzz",
srcs: ["src/lib.rs"],
export_include_dirs: ["buzz_includes"]
}
+ rust_ffi_static {
+ name: "libbuzz_from_rlib",
+ crate_name: "buzz_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["buzz_includes"]
+ }
+
cc_library_shared {
name: "libcc_shared",
srcs:["foo.c"],
@@ -468,12 +482,34 @@
whole_static_libs: ["libfoo"],
}
+ cc_library_static {
+ name: "libcc_static_from_rlib",
+ srcs:["foo.c"],
+ static_libs: ["libbuzz_from_rlib"],
+ whole_static_libs: ["libfoo_from_rlib"],
+ }
+
cc_binary {
name: "ccBin",
srcs:["foo.c"],
static_libs: ["libcc_static", "libbar"],
}
- `)
+
+ rust_library {
+ name: "librs",
+ srcs:["src/foo.rs"],
+ crate_name: "rs",
+ static_libs: ["libcc_static_from_rlib"],
+ }
+
+ rust_binary {
+ name: "rsBin",
+ srcs:["src/foo.rs"],
+ crate_name: "rsBin",
+ rlibs: ["librs", "libbar"],
+ static_libs: ["libcc_static"],
+ }
+ `)
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
libcc_shared_rustc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
@@ -482,6 +518,9 @@
ccbin_rustc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("rustc")
ccbin_ld := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("ld")
ccbin_cc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("cc")
+ rustbin_genlib := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("generated_rust_staticlib/librustlibs.a")
+ rustbin := ctx.ModuleForTests("rsBin", "android_arm64_armv8-a").Output("unstripped/rsBin")
+ librs_rlib := ctx.ModuleForTests("librs", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
if !strings.Contains(libbar.Args["rustcFlags"], "crate-type=rlib") {
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "rlib", libbar.Args["rustcFlags"])
@@ -513,7 +552,7 @@
// Make sure the static lib is included in the cc command
if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/librustlibs.a") {
t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
- "ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
+ "generated_rust_staticlib/librustlibs.a", ccbin_ld.Args["libFlags"])
}
// Make sure the static lib includes are in the ld command
@@ -534,11 +573,43 @@
t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
}
+ // Make sure the static lib is included in the rustc command
+ if !strings.Contains(rustbin.Args["linkFlags"], "generated_rust_staticlib/librustlibs.a") {
+ t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
+ "generated_rust_staticlib/librustlibs.a", rustbin.Args["libFlags"])
+ }
+
+ // Make sure that direct dependencies and indirect whole static dependencies are
+ // propagating correctly for the rlib -> cc_library_static -> rust_* generated library example.
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz=") {
+ t.Errorf("Indirect rlib dependency libbuzz from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern bar=") {
+ t.Errorf("Direct rlib dependency libbar getting included in the generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz_from_rlib=") {
+ // While static-libs propagate for rust modules, this is not the
+ // expected behavior for cc modules. Thus, libbuzz_from_rlib would
+ // be expected to have to be re-declared as a direct rlib dependency.
+ t.Errorf("Indirect rlib dependency libbuzz_from_rlib from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+
// Test indirect includes propagation
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ifoo_includes") {
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
"-Ifoo_includes", ccbin_cc.Args)
}
+
+ // Make sure we're not generating superfluous mto staticlibs.
+ if librs_rlib.Rule != nil {
+ t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+ }
}
func assertString(t *testing.T, got, expected string) {
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index ef0f44a..b600443 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -23,9 +23,18 @@
# TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64
# dependencies exist (currently blocked by http://b/273792258).
# TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655).
+#
+# LTO is disabled because the NDK compiler is not necessarily in-sync with the
+# compiler used to build the platform sysroot, and the sysroot includes static
+# libraries which would be incompatible with mismatched compilers when built
+# with LTO. Disabling LTO globally for the NDK sysroot is okay because the only
+# compiled code in the sysroot that will end up in apps is those static
+# libraries.
+# https://github.com/android/ndk/issues/1591
TARGET_RELEASE=trunk_staging \
ALLOW_MISSING_DEPENDENCIES=true \
BUILD_BROKEN_DISABLE_BAZEL=1 \
+DISABLE_LTO=true \
TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then