Merge "Use blueprint/pool" 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/androidmk.go b/android/androidmk.go
index 951e03c..7d6b056 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -64,7 +64,6 @@
type AndroidMkData struct {
Class string
SubName string
- DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -1093,7 +1092,6 @@
data.Entries = AndroidMkEntries{
Class: data.Class,
SubName: data.SubName,
- DistFiles: data.DistFiles,
OutputFile: data.OutputFile,
Disabled: data.Disabled,
Include: data.Include,
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/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..c2a571c 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)
@@ -237,6 +237,26 @@
ctx.CheckbuildFile(allImagesStamp)
a.setVbmetaPhonyTargets(ctx)
+
+ a.distFiles(ctx)
+}
+
+func (a *androidDevice) distFiles(ctx android.ModuleContext) {
+ if !ctx.Config().KatiEnabled() {
+ if proptools.Bool(a.deviceProps.Main_device) {
+ fsInfoMap := a.getFsInfos(ctx)
+ for _, partition := range android.SortedKeys(fsInfoMap) {
+ fsInfo := fsInfoMap[partition]
+ if fsInfo.InstalledFiles.Json != nil {
+ ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json)
+ }
+ if fsInfo.InstalledFiles.Txt != nil {
+ ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt)
+ }
+ }
+ }
+ }
+
}
func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) {
@@ -398,8 +418,12 @@
superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
for _, partition := range android.SortedKeys(info.SubImageInfo) {
- builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].OutputHermetic).Textf(" %s/IMAGES/", targetFilesDir.String())
- builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String())
+ if info.SubImageInfo[partition].OutputHermetic != nil {
+ builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].OutputHermetic).Textf(" %s/IMAGES/", targetFilesDir.String())
+ }
+ if info.SubImageInfo[partition].MapFile != nil {
+ builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String())
+ }
}
} else {
ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 9f2b239..84daab0 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -36,6 +36,7 @@
func init() {
registerBuildComponents(android.InitRegistrationContext)
registerMutators(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("fileslist", "fileslist")
}
func registerBuildComponents(ctx android.RegistrationContext) {
@@ -54,11 +55,24 @@
})
}
-// Remember to add referenced files to implicits!
-var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
- Command: "build/soong/scripts/text_file_processor.py $in $out",
- CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
-})
+var (
+ // Remember to add referenced files to implicits!
+ textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
+ Command: "build/soong/scripts/text_file_processor.py $in $out",
+ CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
+ })
+
+ // Remember to add the output image file as an implicit dependency!
+ installedFilesJsonRule = pctx.AndroidStaticRule("installed_files_json", blueprint.RuleParams{
+ Command: `${fileslist} ${rootDir} > ${out}`,
+ CommandDeps: []string{"${fileslist}"},
+ }, "rootDir")
+
+ installedFilesTxtRule = pctx.AndroidStaticRule("installed_files_txt", blueprint.RuleParams{
+ Command: `build/make/tools/fileslist_util.py -c ${in} > ${out}`,
+ CommandDeps: []string{"build/make/tools/fileslist_util.py"},
+ })
+)
type filesystem struct {
android.ModuleBase
@@ -358,6 +372,11 @@
return fs == unknown
}
+type InstalledFilesStruct struct {
+ Txt android.Path
+ Json android.Path
+}
+
type FilesystemInfo struct {
// The built filesystem image
Output android.Path
@@ -391,6 +410,9 @@
SpecsForSystemOther map[string]android.PackagingSpec
FullInstallPaths []FullInstallPathInfo
+
+ // Installed files list
+ InstalledFiles InstalledFilesStruct
}
// FullInstallPathInfo contains information about the "full install" paths of all the files
@@ -498,6 +520,34 @@
}
}
+func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) (txt android.ModuleOutPath, json android.ModuleOutPath) {
+ fileName := "installed-files"
+ if len(partition) > 0 {
+ fileName += fmt.Sprintf("-%s", partition)
+ }
+ txt = android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName))
+ json = android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName))
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: installedFilesJsonRule,
+ Implicit: image,
+ Output: json,
+ Description: "Installed file list json",
+ Args: map[string]string{
+ "rootDir": rootDir.String(),
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: installedFilesTxtRule,
+ Input: json,
+ Output: txt,
+ Description: "Installed file list txt",
+ })
+
+ return txt, json
+}
+
var pctx = android.NewPackageContext("android/soong/filesystem")
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -537,14 +587,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)
@@ -565,6 +628,12 @@
fileListFile := android.PathForModuleOut(ctx, "fileList")
android.WriteFileRule(ctx, fileListFile, f.installedFilesList())
+ partitionName := f.partitionName()
+ if partitionName == "system" {
+ partitionName = ""
+ }
+ installedFileTxt, installedFileJson := buildInstalledFiles(ctx, partitionName, rootDir, f.output)
+
fsInfo := FilesystemInfo{
Output: f.output,
OutputHermetic: outputHermetic,
@@ -577,6 +646,10 @@
BuildImagePropFileDeps: buildImagePropFileDeps,
SpecsForSystemOther: f.systemOtherFiles(ctx),
FullInstallPaths: fullInstallPaths,
+ InstalledFiles: InstalledFilesStruct{
+ Txt: installedFileTxt,
+ Json: installedFileJson,
+ },
}
android.SetProvider(ctx, FilesystemProvider, fsInfo)
@@ -590,6 +663,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 +860,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 +887,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 +1123,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 +1444,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/filesystem/super_image.go b/filesystem/super_image.go
index da007bb..58c938a 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -291,8 +291,6 @@
switch p {
case "system":
handleSubPartition("system", s.partitionProps.System_partition)
- // TODO: add system_other to deps after it can be generated
- //getFsInfo("system_other", s.partitionProps.System_other_partition, &subImageInfo.System_other)
case "system_dlkm":
handleSubPartition("system_dlkm", s.partitionProps.System_dlkm_partition)
case "system_ext":
@@ -321,8 +319,7 @@
if len(systemOtherFiles) != 1 {
ctx.PropertyErrorf("system_other_partition", "Expected 1 output file from module %q", *&s.properties.System_other_partition)
} else {
- addStr("system_other_image", systemOtherFiles[0].String())
- deps = append(deps, systemOtherFiles[0])
+ handleSubPartition("system_other", s.partitionProps.System_other_partition)
}
}
diff --git a/filesystem/system_other.go b/filesystem/system_other.go
index 28fe1ce..1c00dd3 100644
--- a/filesystem/system_other.go
+++ b/filesystem/system_other.go
@@ -85,6 +85,7 @@
output := android.PathForModuleOut(ctx, "system_other.img")
stagingDir := android.PathForModuleOut(ctx, "staging_dir")
+ stagingDirTimestamp := android.PathForModuleOut(ctx, "staging_dir.timestamp")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Textf("rm -rf %s && mkdir -p %s", stagingDir, stagingDir)
@@ -113,6 +114,8 @@
if len(m.properties.Preinstall_dexpreopt_files_from) > 0 {
builder.Command().Textf("touch %s", filepath.Join(stagingDir.String(), "system-other-odex-marker"))
}
+ builder.Command().Textf("touch").Output(stagingDirTimestamp)
+ builder.Build("assemble_filesystem_staging_dir", "Assemble filesystem staging dir")
// 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
@@ -120,6 +123,7 @@
fec := ctx.Config().HostToolPath(ctx, "fec")
pathToolDirs := []string{filepath.Dir(fec.String())}
+ builder = android.NewRuleBuilder(pctx, ctx)
builder.Command().
Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
BuiltTool("build_image").
@@ -127,11 +131,44 @@
Input(systemInfo.BuildImagePropFile).
Implicits(systemInfo.BuildImagePropFileDeps).
Implicit(fec).
+ Implicit(stagingDirTimestamp).
Output(output).
Text(stagingDir.String())
builder.Build("build_system_other", "build system other")
+ // Create a hermetic system_other.img with pinned timestamps
+ builder = android.NewRuleBuilder(pctx, ctx)
+ outputHermetic := android.PathForModuleOut(ctx, "for_target_files", "system_other.img")
+ outputHermeticPropFile := m.propFileForHermeticImg(ctx, builder, systemInfo.BuildImagePropFile)
+ builder.Command().
+ Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
+ BuiltTool("build_image").
+ Text(stagingDir.String()). // input directory
+ Input(outputHermeticPropFile).
+ Implicits(systemInfo.BuildImagePropFileDeps).
+ Implicit(fec).
+ Implicit(stagingDirTimestamp).
+ Output(outputHermetic).
+ Text(stagingDir.String())
+
+ builder.Build("build_system_other_hermetic", "build system other")
+
+ fsInfo := FilesystemInfo{
+ Output: output,
+ OutputHermetic: outputHermetic,
+ RootDir: stagingDir,
+ }
+
+ android.SetProvider(ctx, FilesystemProvider, fsInfo)
+
ctx.SetOutputFiles(android.Paths{output}, "")
ctx.CheckbuildFile(output)
}
+
+func (f *systemOtherImage) 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)
+ return propFilePinnedTimestamp
+}
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/androidmk.go b/rust/androidmk.go
index 8de6b60..9894684 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -92,9 +92,6 @@
func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, binary.baseCompiler)
- if binary.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
- }
ret.Class = "EXECUTABLES"
}
@@ -143,9 +140,6 @@
} else if library.shared() {
ret.Class = "SHARED_LIBRARIES"
}
- if library.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
- }
ret.ExtraEntries = append(ret.ExtraEntries,
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if library.tocFile.Valid() {
@@ -158,10 +152,6 @@
ctx.SubAndroidMk(ret, procMacro.baseCompiler)
ret.Class = "PROC_MACRO_LIBRARIES"
- if procMacro.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(procMacro.distFile.Path())
- }
-
}
func (sourceProvider *BaseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
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/compiler.go b/rust/compiler.go
index f186ef3..c3bc937 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -257,8 +257,6 @@
location installLocation
sanitize *sanitize
- distFile android.OptionalPath
-
installDeps android.InstallPaths
// unstripped output file.
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