Merge "Respect THINLTO_USE_MLGO for ML inliner" into main
diff --git a/Android.bp b/Android.bp
index 34f9bf0..bd4b40f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -161,10 +161,11 @@
name: "system-build.prop",
stem: "build.prop",
product_config: ":product_config",
- // Currently, only microdroid and cf system image can refer to system-build.prop
+ // Currently, only microdroid, Ravenwood, and cf system image can refer to system-build.prop
visibility: [
"//build/make/target/product/generic",
"//packages/modules/Virtualization/build/microdroid",
+ "//frameworks/base/ravenwood",
],
}
diff --git a/android/Android.bp b/android/Android.bp
index 44cddcc..3b54326 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -52,6 +52,7 @@
"defs.go",
"depset_generic.go",
"deptag.go",
+ "dirgroup.go",
"early_module_context.go",
"expand.go",
"filegroup.go",
diff --git a/android/dirgroup.go b/android/dirgroup.go
new file mode 100644
index 0000000..20c4d13
--- /dev/null
+++ b/android/dirgroup.go
@@ -0,0 +1,63 @@
+// Copyright 2024 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 android
+
+import (
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterDirgroupBuildComponents(InitRegistrationContext)
+}
+
+func RegisterDirgroupBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("dirgroup", DirGroupFactory)
+}
+
+type dirGroupProperties struct {
+ // dirs lists directories that will be included in this dirgroup
+ Dirs proptools.Configurable[[]string] `android:"path"`
+}
+
+type dirGroup struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties dirGroupProperties
+}
+
+type DirInfo struct {
+ // TODO(b/358302178): Use DirectoryPaths instead of Paths
+ Dirs Paths
+}
+
+var DirProvider = blueprint.NewProvider[DirInfo]()
+
+// dirgroup contains a list of dirs that are referenced by other modules
+// properties using the syntax ":<name>". dirgroup are also be used to export
+// dirs across package boundaries. Currently the only allowed usage is genrule's
+// dir_srcs property.
+func DirGroupFactory() Module {
+ module := &dirGroup{}
+ module.AddProperties(&module.properties)
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+ return module
+}
+
+func (fg *dirGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
+ dirs := DirectoryPathsForModuleSrc(ctx, fg.properties.Dirs.GetOrDefault(ctx, nil))
+ SetProvider(ctx, DirProvider, DirInfo{Dirs: dirs})
+}
diff --git a/android/module.go b/android/module.go
index 3079b07..e3dabcc 100644
--- a/android/module.go
+++ b/android/module.go
@@ -113,6 +113,10 @@
VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string
ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator
+
+ // The usage of this method is experimental and should not be used outside of fsgen package.
+ // This will be removed once product packaging migration to Soong is complete.
+ DecodeMultilib(ctx ConfigContext) (string, string)
}
// Qualified id for a module
@@ -2282,6 +2286,10 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+func (m *ModuleBase) DecodeMultilib(ctx ConfigContext) (string, string) {
+ return decodeMultilib(ctx, m)
+}
+
type ConfigContext interface {
Config() Config
}
diff --git a/android/module_proxy.go b/android/module_proxy.go
index bc5090e..0f552dd 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -201,3 +201,7 @@
func (m ModuleProxy) ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator {
panic("method is not implemented on ModuleProxy")
}
+
+func (m ModuleProxy) DecodeMultilib(ctx ConfigContext) (string, string) {
+ panic("method is not implemented on ModuleProxy")
+}
diff --git a/android/neverallow.go b/android/neverallow.go
index e93763b..439fe2d 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -60,6 +60,8 @@
AddNeverAllowRules(createCcStubsRule())
AddNeverAllowRules(createProhibitHeaderOnlyRule())
AddNeverAllowRules(createLimitNdkExportRule()...)
+ AddNeverAllowRules(createLimitDirgroupRule()...)
+ AddNeverAllowRules(createFilesystemIsAutoGeneratedRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -275,6 +277,31 @@
}
}
+func createLimitDirgroupRule() []Rule {
+ reason := "dirgroup module and dir_srcs property of genrule is allowed only to Trusty build rule."
+ return []Rule{
+ NeverAllow().
+ ModuleType("dirgroup").
+ WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts"})).Because(reason),
+ NeverAllow().
+ ModuleType("dirgroup").
+ Without("visibility", "//trusty/vendor/google/aosp/scripts").Because(reason),
+ NeverAllow().
+ ModuleType("genrule").
+ Without("name", "lk.elf.arm64").
+ Without("name", "lk.elf.x86_64").
+ WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason),
+ }
+}
+
+func createFilesystemIsAutoGeneratedRule() Rule {
+ return NeverAllow().
+ NotIn("build/soong/fsgen").
+ ModuleType("filesystem", "android_system_image").
+ WithMatcher("is_auto_generated", isSetMatcherInstance).
+ Because("is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory")
+}
+
func neverallowMutator(ctx BottomUpMutatorContext) {
m, ok := ctx.Module().(Module)
if !ok {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 192c924..caec8c7 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -359,6 +359,21 @@
`headers_only can only be used for generating framework-minus-apex headers for non-updatable modules`,
},
},
+ // Test for the rule restricting use of is_auto_generated
+ {
+ name: `"is_auto_generated" outside allowed directory`,
+ fs: map[string][]byte{
+ "a/b/Android.bp": []byte(`
+ filesystem {
+ name: "baaz",
+ is_auto_generated: true,
+ }
+ `),
+ },
+ expectedErrors: []string{
+ `is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory`,
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -367,6 +382,7 @@
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("filesystem", newMockFilesystemModule)
}),
)
diff --git a/android/paths.go b/android/paths.go
index ec05831..371aed8 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -550,6 +550,58 @@
return ret
}
+// DirectoryPathsForModuleSrcExcludes returns a Paths{} containing the resolved references in
+// directory paths. Elements of paths are resolved as:
+// - filepath, relative to local module directory, resolves as a filepath relative to the local
+// source directory
+// - other modules using the ":name" syntax. These modules must implement DirProvider.
+//
+// TODO(b/358302178): Implement DirectoryPath and change the return type.
+func DirectoryPathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths {
+ var ret Paths
+
+ for _, path := range paths {
+ if m, t := SrcIsModuleWithTag(path); m != "" {
+ module := GetModuleFromPathDep(ctx, m, t)
+ if module == nil {
+ ctx.ModuleErrorf(`missing dependency on %q, is the property annotated with android:"path"?`, m)
+ continue
+ }
+ if t != "" {
+ ctx.ModuleErrorf("DirProvider dependency %q does not support the tag %q", module, t)
+ continue
+ }
+ mctx, ok := ctx.(OtherModuleProviderContext)
+ if !ok {
+ panic(fmt.Errorf("%s is not an OtherModuleProviderContext", ctx))
+ }
+ if dirProvider, ok := OtherModuleProvider(mctx, module, DirProvider); ok {
+ ret = append(ret, dirProvider.Dirs...)
+ } else {
+ ReportPathErrorf(ctx, "module %q does not implement DirProvider", module)
+ }
+ } else {
+ p := pathForModuleSrc(ctx, path)
+ if isDir, err := ctx.Config().fs.IsDir(p.String()); err != nil {
+ ReportPathErrorf(ctx, "%s: %s", p, err.Error())
+ } else if !isDir {
+ ReportPathErrorf(ctx, "module directory path %q is not a directory", p)
+ } else {
+ ret = append(ret, p)
+ }
+ }
+ }
+
+ seen := make(map[Path]bool, len(ret))
+ for _, path := range ret {
+ if seen[path] {
+ ReportPathErrorf(ctx, "duplicated path %q", path)
+ }
+ seen[path] = true
+ }
+ return ret
+}
+
// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
type OutputPaths []OutputPath
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 19f12f0..5d75b62 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -272,6 +272,25 @@
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
}
+// InitConfigurablePrebuiltModuleString is the same as InitPrebuiltModule, but uses a
+// Configurable string property instead of a regular list of strings. It only produces a single
+// source file.
+func InitConfigurablePrebuiltModuleString(module PrebuiltInterface, srcs *proptools.Configurable[string], propertyName string) {
+ if srcs == nil {
+ panic(fmt.Errorf("%s must not be nil", propertyName))
+ }
+
+ srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
+ src := srcs.GetOrDefault(ctx, "")
+ if src == "" {
+ return nil
+ }
+ return []string{src}
+ }
+
+ InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, propertyName)
+}
+
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
srcPropsValue := reflect.ValueOf(srcProps).Elem()
srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 1a2eeca..277be0f 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -2098,8 +2098,9 @@
}
type mockFilesystemModuleProperties struct {
- Partition_type *string
- Deps []string
+ Partition_type *string
+ Deps []string
+ Is_auto_generated *bool
}
type mockFilesystemModule struct {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 645778b..68978b2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11861,3 +11861,42 @@
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
)
}
+
+// partitions should not package the artifacts that are included inside the apex.
+func TestFilesystemWithApexDeps(t *testing.T) {
+ t.Parallel()
+ result := testApex(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ deps: ["myapex"],
+ }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ binaries: ["binfoo"],
+ native_shared_libs: ["libfoo"],
+ apps: ["appfoo"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ }
+ cc_binary {
+ name: "binfoo",
+ apex_available: ["myapex"],
+ }
+ cc_library {
+ name: "libfoo",
+ apex_available: ["myapex"],
+ }
+ android_app {
+ name: "appfoo",
+ sdk_version: "current",
+ apex_available: ["myapex"],
+ }
+ `, filesystem.PrepareForTestWithFilesystemBuildComponents)
+
+ partition := result.ModuleForTests("myfilesystem", "android_common")
+ fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
+ android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
+}
diff --git a/apex/builder.go b/apex/builder.go
index 371d7d5..20b4dbe 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -253,10 +253,10 @@
apexHostVerifierRule = pctx.StaticRule("apexHostVerifierRule", blueprint.RuleParams{
Command: `${host_apex_verifier} --deapexer=${deapexer} --debugfs=${debugfs_static} ` +
- `--fsckerofs=${fsck_erofs} --apex=${in} && touch ${out}`,
+ `--fsckerofs=${fsck_erofs} --apex=${in} --partition_tag=${partition_tag} && touch ${out}`,
CommandDeps: []string{"${host_apex_verifier}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}"},
Description: "run host_apex_verifier",
- })
+ }, "partition_tag")
assembleVintfRule = pctx.StaticRule("assembleVintfRule", blueprint.RuleParams{
Command: `rm -f $out && VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i $in -o $out`,
@@ -621,7 +621,8 @@
}
} else {
if installSymbolFiles {
- installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
+ // store installedPath. symlinks might be created if required.
+ installedPath = apexDir.Join(ctx, fi.installDir, fi.stem())
}
}
@@ -976,7 +977,7 @@
runApexElfCheckerUnwanted(ctx, unsignedOutputFile.OutputPath, a.properties.Unwanted_transitive_deps))
}
if !a.testApex && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
- validations = append(validations, runApexHostVerifier(ctx, unsignedOutputFile.OutputPath))
+ validations = append(validations, runApexHostVerifier(ctx, a, unsignedOutputFile.OutputPath))
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
@@ -1287,12 +1288,15 @@
return timestamp
}
-func runApexHostVerifier(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+func runApexHostVerifier(ctx android.ModuleContext, a *apexBundle, apexFile android.OutputPath) android.Path {
timestamp := android.PathForModuleOut(ctx, "host_apex_verifier.timestamp")
ctx.Build(pctx, android.BuildParams{
Rule: apexHostVerifierRule,
Input: apexFile,
Output: timestamp,
+ Args: map[string]string{
+ "partition_tag": a.PartitionTag(ctx.DeviceConfig()),
+ },
})
return timestamp
}
diff --git a/cc/Android.bp b/cc/Android.bp
index 88a793c..a5ad9ce 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -27,6 +27,7 @@
"builder.go",
"cc.go",
"ccdeps.go",
+ "cc_preprocess_no_configuration.go",
"check.go",
"coverage.go",
"gen.go",
@@ -88,6 +89,7 @@
testSrcs: [
"afdo_test.go",
"binary_test.go",
+ "cc_preprocess_no_configuration_test.go",
"cc_test.go",
"cc_test_only_property_test.go",
"cmake_snapshot_test.go",
diff --git a/cc/cc_preprocess_no_configuration.go b/cc/cc_preprocess_no_configuration.go
new file mode 100644
index 0000000..3d1d0a5
--- /dev/null
+++ b/cc/cc_preprocess_no_configuration.go
@@ -0,0 +1,108 @@
+// Copyright 2024 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 cc
+
+import (
+ "android/soong/android"
+ "strings"
+)
+
+func init() {
+ RegisterCCPreprocessNoConfiguration(android.InitRegistrationContext)
+}
+
+func RegisterCCPreprocessNoConfiguration(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_preprocess_no_configuration", ccPreprocessNoConfigurationFactory)
+}
+
+// cc_preprocess_no_configuration modules run the c preprocessor on a single input source file.
+// They also have "no configuration", meaning they don't have an arch or os associated with them,
+// they should be thought of as pure textual transformations of the input file. In some cases this
+// is good, in others you might want to do different transformations depending on what arch the
+// result will be compiled in, in which case you can use cc_object instead of this module.
+func ccPreprocessNoConfigurationFactory() android.Module {
+ m := &ccPreprocessNoConfiguration{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidModule(m)
+ return m
+}
+
+type ccPreprocessNoConfigurationProps struct {
+ // Called Srcs for consistency with the other cc module types, but only accepts 1 input source
+ // file.
+ Srcs []string `android:"path"`
+ // The flags to pass to the c compiler. Must include -E in order to enable preprocessing-only
+ // mode.
+ Cflags []string `android:"path"`
+}
+
+type ccPreprocessNoConfiguration struct {
+ android.ModuleBase
+ properties ccPreprocessNoConfigurationProps
+}
+
+func (m *ccPreprocessNoConfiguration) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
+ if len(srcs) != 1 {
+ ctx.PropertyErrorf("Srcs", "cc_preprocess_no_configuration only accepts 1 source file, found: %v", srcs.Strings())
+ return
+ }
+ src := srcs[0]
+
+ hasE := false
+ for _, cflag := range m.properties.Cflags {
+ if cflag == "-E" {
+ hasE = true
+ break
+ } else if cflag == "-P" || strings.HasPrefix(cflag, "-D") {
+ // do nothing, allow it
+ } else {
+ ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration only allows -D and -P flags, found: %q", cflag)
+ return
+ }
+ }
+ if !hasE {
+ ctx.PropertyErrorf("Cflags", "cc_preprocess_no_configuration must have a -E cflag")
+ return
+ }
+
+ var ccCmd string
+ switch src.Ext() {
+ case ".c":
+ ccCmd = "clang"
+ case ".cpp", ".cc", ".cxx", ".mm":
+ ccCmd = "clang++"
+ default:
+ ctx.PropertyErrorf("srcs", "File %s has unknown extension. Supported extensions: .c, .cpp, .cc, .cxx, .mm", src)
+ return
+ }
+
+ ccCmd = "${config.ClangBin}/" + ccCmd
+
+ outFile := android.PathForModuleOut(ctx, src.Base())
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: cc,
+ Description: ccCmd + " " + src.Rel(),
+ Output: outFile,
+ Input: src,
+ Args: map[string]string{
+ "cFlags": strings.Join(m.properties.Cflags, " "),
+ "ccCmd": ccCmd,
+ },
+ })
+
+ ctx.SetOutputFiles([]android.Path{outFile}, "")
+}
diff --git a/cc/cc_preprocess_no_configuration_test.go b/cc/cc_preprocess_no_configuration_test.go
new file mode 100644
index 0000000..43e726d
--- /dev/null
+++ b/cc/cc_preprocess_no_configuration_test.go
@@ -0,0 +1,40 @@
+// Copyright 2019 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 cc
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestCcPreprocessNoConfiguration(t *testing.T) {
+ fixture := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.FixtureRegisterWithContext(RegisterCCPreprocessNoConfiguration),
+ )
+
+ result := fixture.RunTestWithBp(t, `
+cc_preprocess_no_configuration {
+ name: "foo",
+ srcs: ["main.cc"],
+ cflags: ["-E", "-DANDROID"],
+}
+`)
+
+ foo := result.ModuleForTests("foo", "")
+ actual := foo.Rule("cc").Args["cFlags"]
+ expected := "-E -DANDROID"
+ android.AssertStringEquals(t, "cflags should be correct", expected, actual)
+}
diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go
index 5d183ee..46efce7 100644
--- a/cmd/release_config/build_flag/main.go
+++ b/cmd/release_config/build_flag/main.go
@@ -329,7 +329,7 @@
return err
}
updatedFiles = append(updatedFiles, flagPath)
- fmt.Printf("Added/Updated: %s\n", strings.Join(updatedFiles, " "))
+ fmt.Printf("\033[1mAdded/Updated: %s\033[0m\n", strings.Join(updatedFiles, " "))
return nil
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 1e816a7..4bdd0a4 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -145,6 +145,10 @@
Unchecked_module *bool `blueprint:"mutated"`
Erofs ErofsProperties
+
+ // Determines if the module is auto-generated from Soong or not. If the module is
+ // auto-generated, its deps are exempted from visibility enforcement.
+ Is_auto_generated *bool
}
// Additional properties required to generate erofs FS partitions.
@@ -179,13 +183,29 @@
android.InitDefaultableModule(module)
}
-var dependencyTag = struct {
+type depTag struct {
blueprint.BaseDependencyTag
android.PackagingItemAlwaysDepTag
-}{}
+}
+
+var dependencyTag = depTag{}
+
+type depTagWithVisibilityEnforcementBypass struct {
+ depTag
+}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil)
+
+func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {}
+
+var dependencyTagWithVisibilityEnforcementBypass = depTagWithVisibilityEnforcementBypass{}
func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
- f.AddDeps(ctx, dependencyTag)
+ if proptools.Bool(f.properties.Is_auto_generated) {
+ f.AddDeps(ctx, dependencyTagWithVisibilityEnforcementBypass)
+ } else {
+ f.AddDeps(ctx, dependencyTag)
+ }
}
type fsType int
@@ -198,6 +218,10 @@
unknown
)
+func (fs fsType) IsUnknown() bool {
+ return fs == unknown
+}
+
type FilesystemInfo struct {
// A text file containing the list of paths installed on the partition.
FileListFile android.Path
@@ -205,8 +229,7 @@
var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
-func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
- typeStr := proptools.StringDefault(f.properties.Type, "ext4")
+func GetFsTypeFromString(ctx android.EarlyModuleContext, typeStr string) fsType {
switch typeStr {
case "ext4":
return ext4Type
@@ -217,11 +240,19 @@
case "cpio":
return cpioType
default:
- ctx.PropertyErrorf("type", "%q not supported", typeStr)
return unknown
}
}
+func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
+ typeStr := proptools.StringDefault(f.properties.Type, "ext4")
+ fsType := GetFsTypeFromString(ctx, typeStr)
+ if fsType == unknown {
+ ctx.PropertyErrorf("type", "%q not supported", typeStr)
+ }
+ return fsType
+}
+
func (f *filesystem) installFileName() string {
return f.BaseModuleName() + ".img"
}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index ed0c390..f446c2b 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -43,49 +43,222 @@
func RegisterCollectFileSystemDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("fs_collect_deps", collectDepsMutator).MutatesGlobalState()
+ ctx.BottomUp("fs_set_deps", setDepsMutator)
}
-var fsDepsMutex = sync.Mutex{}
-var collectFsDepsOnceKey = android.NewOnceKey("CollectFsDeps")
-var depCandidatesOnceKey = android.NewOnceKey("DepCandidates")
+var fsGenStateOnceKey = android.NewOnceKey("FsGenState")
+
+// Map of partition module name to its partition that may be generated by Soong.
+// Note that it is not guaranteed that all modules returned by this function are successfully
+// created.
+func getAllSoongGeneratedPartitionNames(config android.Config, partitions []string) map[string]string {
+ ret := map[string]string{}
+ for _, partition := range partitions {
+ ret[generatedModuleNameForPartition(config, partition)] = partition
+ }
+ return ret
+}
+
+type depCandidateProps struct {
+ Namespace string
+ Multilib string
+ Arch []android.ArchType
+}
+
+// Map of module name to depCandidateProps
+type multilibDeps *map[string]*depCandidateProps
+
+// Information necessary to generate the filesystem modules, including details about their
+// dependencies
+type FsGenState struct {
+ // List of modules in `PRODUCT_PACKAGES` and `PRODUCT_PACKAGES_DEBUG`
+ depCandidates []string
+ // Map of names of partition to the information of modules to be added as deps
+ fsDeps map[string]multilibDeps
+ // List of name of partitions to be generated by the filesystem_creator module
+ soongGeneratedPartitions []string
+ // Mutex to protect the fsDeps
+ fsDepsMutex sync.Mutex
+}
+
+func newMultilibDeps() multilibDeps {
+ return &map[string]*depCandidateProps{}
+}
+
+func defaultDepCandidateProps(config android.Config) *depCandidateProps {
+ return &depCandidateProps{
+ Namespace: ".",
+ Arch: []android.ArchType{config.BuildArch},
+ }
+}
+
+func createFsGenState(ctx android.LoadHookContext) *FsGenState {
+ return ctx.Config().Once(fsGenStateOnceKey, func() interface{} {
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug))
+
+ generatedPartitions := []string{"system"}
+ if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
+ generatedPartitions = append(generatedPartitions, "system_ext")
+ }
+
+ return &FsGenState{
+ depCandidates: candidates,
+ fsDeps: map[string]multilibDeps{
+ // These additional deps are added according to the cuttlefish system image bp.
+ "system": &map[string]*depCandidateProps{
+ "com.android.apex.cts.shim.v1_prebuilt": defaultDepCandidateProps(ctx.Config()),
+ "dex_bootjars": defaultDepCandidateProps(ctx.Config()),
+ "framework_compatibility_matrix.device.xml": defaultDepCandidateProps(ctx.Config()),
+ "idc_data": defaultDepCandidateProps(ctx.Config()),
+ "init.environ.rc-soong": defaultDepCandidateProps(ctx.Config()),
+ "keychars_data": defaultDepCandidateProps(ctx.Config()),
+ "keylayout_data": defaultDepCandidateProps(ctx.Config()),
+ "libclang_rt.asan": defaultDepCandidateProps(ctx.Config()),
+ "libcompiler_rt": defaultDepCandidateProps(ctx.Config()),
+ "libdmabufheap": defaultDepCandidateProps(ctx.Config()),
+ "libgsi": defaultDepCandidateProps(ctx.Config()),
+ "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()),
+ "logpersist.start": defaultDepCandidateProps(ctx.Config()),
+ "preloaded-classes": defaultDepCandidateProps(ctx.Config()),
+ "public.libraries.android.txt": defaultDepCandidateProps(ctx.Config()),
+ "update_engine_sideload": defaultDepCandidateProps(ctx.Config()),
+ },
+ "vendor": newMultilibDeps(),
+ "odm": newMultilibDeps(),
+ "product": newMultilibDeps(),
+ "system_ext": newMultilibDeps(),
+ },
+ soongGeneratedPartitions: generatedPartitions,
+ fsDepsMutex: sync.Mutex{},
+ }
+ }).(*FsGenState)
+}
+
+func checkDepModuleInMultipleNamespaces(mctx android.BottomUpMutatorContext, foundDeps map[string]*depCandidateProps, module string, partitionName string) {
+ otherNamespace := mctx.Namespace().Path
+ if val, found := foundDeps[module]; found && otherNamespace != "." && !android.InList(val.Namespace, []string{".", otherNamespace}) {
+ mctx.ModuleErrorf("found in multiple namespaces(%s and %s) when including in %s partition", val.Namespace, otherNamespace, partitionName)
+ }
+}
+
+func appendDepIfAppropriate(mctx android.BottomUpMutatorContext, deps *map[string]*depCandidateProps, installPartition string) {
+ checkDepModuleInMultipleNamespaces(mctx, *deps, mctx.Module().Name(), installPartition)
+ if _, ok := (*deps)[mctx.Module().Name()]; ok {
+ // Prefer the namespace-specific module over the platform module
+ if mctx.Namespace().Path != "." {
+ (*deps)[mctx.Module().Name()].Namespace = mctx.Namespace().Path
+ }
+ (*deps)[mctx.Module().Name()].Arch = append((*deps)[mctx.Module().Name()].Arch, mctx.Module().Target().Arch.ArchType)
+ } else {
+ multilib, _ := mctx.Module().DecodeMultilib(mctx)
+ (*deps)[mctx.Module().Name()] = &depCandidateProps{
+ Namespace: mctx.Namespace().Path,
+ Multilib: multilib,
+ Arch: []android.ArchType{mctx.Module().Target().Arch.ArchType},
+ }
+ }
+}
func collectDepsMutator(mctx android.BottomUpMutatorContext) {
- // These additional deps are added according to the cuttlefish system image bp.
- fsDeps := mctx.Config().Once(collectFsDepsOnceKey, func() interface{} {
- deps := []string{
- "android_vintf_manifest",
- "com.android.apex.cts.shim.v1_prebuilt",
- "dex_bootjars",
- "framework_compatibility_matrix.device.xml",
- "idc_data",
- "init.environ.rc-soong",
- "keychars_data",
- "keylayout_data",
- "libclang_rt.asan",
- "libcompiler_rt",
- "libdmabufheap",
- "libgsi",
- "llndk.libraries.txt",
- "logpersist.start",
- "preloaded-classes",
- "public.libraries.android.txt",
- "update_engine_sideload",
- }
- return &deps
- }).(*[]string)
-
- depCandidates := mctx.Config().Once(depCandidatesOnceKey, func() interface{} {
- partitionVars := mctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
- candidates := slices.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug)
- return &candidates
- }).(*[]string)
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
m := mctx.Module()
- if slices.Contains(*depCandidates, m.Name()) {
- if installInSystem(mctx, m) {
- fsDepsMutex.Lock()
- *fsDeps = append(*fsDeps, m.Name())
- fsDepsMutex.Unlock()
+ if slices.Contains(fsGenState.depCandidates, m.Name()) {
+ installPartition := m.PartitionTag(mctx.DeviceConfig())
+ fsGenState.fsDepsMutex.Lock()
+ // Only add the module as dependency when:
+ // - its enabled
+ // - its namespace is included in PRODUCT_SOONG_NAMESPACES
+ if m.Enabled(mctx) && m.ExportedToMake() {
+ appendDepIfAppropriate(mctx, fsGenState.fsDeps[installPartition], installPartition)
+ }
+ fsGenState.fsDepsMutex.Unlock()
+ }
+}
+
+type depsStruct struct {
+ Deps []string
+}
+
+type multilibDepsStruct struct {
+ Common depsStruct
+ Lib32 depsStruct
+ Lib64 depsStruct
+ Both depsStruct
+ Prefer32 depsStruct
+}
+
+type packagingPropsStruct struct {
+ Deps []string
+ Multilib multilibDepsStruct
+}
+
+func fullyQualifiedModuleName(moduleName, namespace string) string {
+ if namespace == "." {
+ return moduleName
+ }
+ return fmt.Sprintf("//%s:%s", namespace, moduleName)
+}
+
+// Returns the sorted unique list of module names with namespace, if the module specifies one.
+func fullyQualifiedModuleNames(modules multilibDeps) (ret []string) {
+ for moduleName, moduleProp := range *modules {
+ ret = append(ret, fullyQualifiedModuleName(moduleName, moduleProp.Namespace))
+ }
+ return android.SortedUniqueStrings(ret)
+}
+
+func getBitness(archTypes []android.ArchType) (ret []string) {
+ for _, archType := range archTypes {
+ if archType.Multilib == "" {
+ ret = append(ret, android.COMMON_VARIANT)
+ } else {
+ ret = append(ret, archType.Bitness())
+ }
+ }
+ return ret
+}
+
+func setDepsMutator(mctx android.BottomUpMutatorContext) {
+ fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsDeps := fsGenState.fsDeps
+ soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions)
+ m := mctx.Module()
+ if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok {
+ depsStruct := packagingPropsStruct{}
+ for depName, depProps := range *fsDeps[partition] {
+ bitness := getBitness(depProps.Arch)
+ fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace)
+ if android.InList("32", bitness) && android.InList("64", bitness) {
+ // If both 32 and 64 bit variants are enabled for this module
+ switch depProps.Multilib {
+ case string(android.MultilibBoth):
+ depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName)
+ case string(android.MultilibCommon), string(android.MultilibFirst):
+ depsStruct.Deps = append(depsStruct.Deps, fullyQualifiedDepName)
+ case "32":
+ depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName)
+ case "64", "darwin_universal":
+ depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName)
+ case "prefer32", "first_prefer32":
+ depsStruct.Multilib.Prefer32.Deps = append(depsStruct.Multilib.Prefer32.Deps, fullyQualifiedDepName)
+ default:
+ depsStruct.Multilib.Both.Deps = append(depsStruct.Multilib.Both.Deps, fullyQualifiedDepName)
+ }
+ } else if android.InList("64", bitness) {
+ // If only 64 bit variant is enabled
+ depsStruct.Multilib.Lib64.Deps = append(depsStruct.Multilib.Lib64.Deps, fullyQualifiedDepName)
+ } else if android.InList("32", bitness) {
+ // If only 32 bit variant is enabled
+ depsStruct.Multilib.Lib32.Deps = append(depsStruct.Multilib.Lib32.Deps, fullyQualifiedDepName)
+ } else {
+ // If only common variant is enabled
+ depsStruct.Multilib.Common.Deps = append(depsStruct.Multilib.Common.Deps, fullyQualifiedDepName)
+ }
+ }
+ if err := proptools.AppendMatchingProperties(m.GetProperties(), &depsStruct, nil); err != nil {
+ mctx.ModuleErrorf(err.Error())
}
}
}
@@ -107,6 +280,7 @@
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
module.AddProperties(&module.properties)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ createFsGenState(ctx)
module.createInternalModules(ctx)
})
@@ -114,17 +288,19 @@
}
func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
- for _, partitionType := range []string{"system"} {
+ soongGeneratedPartitions := &ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions
+ for _, partitionType := range *soongGeneratedPartitions {
if f.createPartition(ctx, partitionType) {
f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
} else {
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
+ _, *soongGeneratedPartitions = android.RemoveFromList(partitionType, *soongGeneratedPartitions)
}
}
f.createDeviceModule(ctx)
}
-func (f *filesystemCreator) generatedModuleName(cfg android.Config, suffix string) string {
+func generatedModuleName(cfg android.Config, suffix string) string {
prefix := "soong"
if cfg.HasDeviceProduct() {
prefix = cfg.DeviceProduct()
@@ -132,44 +308,89 @@
return fmt.Sprintf("%s_generated_%s", prefix, suffix)
}
-func (f *filesystemCreator) generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
- return f.generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
+func generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
+ return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
}
func (f *filesystemCreator) createDeviceModule(ctx android.LoadHookContext) {
baseProps := &struct {
Name *string
}{
- Name: proptools.StringPtr(f.generatedModuleName(ctx.Config(), "device")),
+ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")),
}
- // Currently, only the system partition module is created.
+ // Currently, only the system and system_ext partition module is created.
partitionProps := &filesystem.PartitionNameProperties{}
if android.InList("system", f.properties.Generated_partition_types) {
- partitionProps.System_partition_name = proptools.StringPtr(f.generatedModuleNameForPartition(ctx.Config(), "system"))
+ partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ }
+ if android.InList("system_ext", f.properties.Generated_partition_types) {
+ partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
}
ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
}
+var (
+ // https://source.corp.google.com/h/googleplex-android/platform/build/+/639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0
+ partitionsWithAconfig = []string{"system", "product", "vendor"}
+)
+
// Creates a soong module to build the given partition. Returns false if we can't support building
// it.
func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool {
- baseProps := &struct {
- Name *string
- }{
- Name: proptools.StringPtr(f.generatedModuleNameForPartition(ctx.Config(), partitionType)),
+ baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
+
+ fsProps, supported := generateFsProps(ctx, partitionType)
+ if !supported {
+ return false
}
+ var module android.Module
+ if partitionType == "system" {
+ module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
+ } else {
+ // Explicitly set the partition.
+ fsProps.Partition_type = proptools.StringPtr(partitionType)
+ module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
+ }
+ module.HideFromMake()
+ return true
+}
+
+type filesystemBaseProperty struct {
+ Name *string
+ Compile_multilib *string
+}
+
+func generateBaseProps(namePtr *string) *filesystemBaseProperty {
+ return &filesystemBaseProperty{
+ Name: namePtr,
+ Compile_multilib: proptools.StringPtr("both"),
+ }
+}
+
+func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) {
fsProps := &filesystem.FilesystemProperties{}
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
+
+ // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
+ fsType := specificPartitionVars.BoardFileSystemType
+ if fsType == "" {
+ fsType = "ext4" //default
+ }
+ fsProps.Type = proptools.StringPtr(fsType)
+ if filesystem.GetFsTypeFromString(ctx, *fsProps.Type).IsUnknown() {
+ // Currently the android_filesystem module type only supports a handful of FS types like ext4, erofs
+ return nil, false
+ }
+
// Don't build this module on checkbuilds, the soong-built partitions are still in-progress
// and sometimes don't build.
fsProps.Unchecked_module = proptools.BoolPtr(true)
- partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
- specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
-
// BOARD_AVB_ENABLE
fsProps.Use_avb = proptools.BoolPtr(partitionVars.BoardAvbEnable)
// BOARD_AVB_KEY_PATH
@@ -182,18 +403,12 @@
}
fsProps.Partition_name = proptools.StringPtr(partitionType)
- // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
- fsProps.Type = proptools.StringPtr(specificPartitionVars.BoardFileSystemType)
- if *fsProps.Type != "ext4" {
- // TODO(b/372522486): Support other FS types.
- // Currently the android_filesystem module type only supports ext4:
- // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/filesystem/filesystem.go;l=416;drc=98047cfd07944b297a12d173453bc984806760d2
- return false
- }
fsProps.Base_dir = proptools.StringPtr(partitionType)
- fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(android.InList(partitionType, partitionsWithAconfig))
+
+ fsProps.Is_auto_generated = proptools.BoolPtr(true)
// Identical to that of the generic_system_image
fsProps.Fsverity.Inputs = []string{
@@ -218,18 +433,12 @@
// - filesystemProperties.Build_logtags
// - filesystemProperties.Fsverity.Libs
// - systemImageProperties.Linker_config_src
- var module android.Module
- if partitionType == "system" {
- module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
- } else {
- module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
- }
- module.HideFromMake()
- return true
+
+ return fsProps, true
}
func (f *filesystemCreator) createDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
- partitionModuleName := f.generatedModuleNameForPartition(ctx.Config(), partitionType)
+ partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType)
systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
if !ok {
@@ -273,7 +482,7 @@
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, partitionType := range f.properties.Generated_partition_types {
- ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, f.generatedModuleNameForPartition(ctx.Config(), partitionType))
+ ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType))
}
}
@@ -298,26 +507,21 @@
ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
}
-func installInSystem(ctx android.BottomUpMutatorContext, m android.Module) bool {
- return m.PartitionTag(ctx.DeviceConfig()) == "system" && !m.InstallInData() &&
- !m.InstallInTestcases() && !m.InstallInSanitizerDir() && !m.InstallInVendorRamdisk() &&
- !m.InstallInDebugRamdisk() && !m.InstallInRecovery() && !m.InstallInOdm() &&
- !m.InstallInVendor()
-}
-
-// TODO: assemble baseProps and fsProps here
func generateBpContent(ctx android.EarlyModuleContext, partitionType string) string {
// Currently only system partition is supported
if partitionType != "system" {
return ""
}
- deps := ctx.Config().Get(collectFsDepsOnceKey).(*[]string)
+ baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
+ fsProps, _ := generateFsProps(ctx, partitionType)
+
+ deps := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps
depProps := &android.PackagingProperties{
- Deps: android.NewSimpleConfigurable(android.SortedUniqueStrings(*deps)),
+ Deps: android.NewSimpleConfigurable(fullyQualifiedModuleNames(deps[partitionType])),
}
- result, err := proptools.RepackProperties([]interface{}{depProps})
+ result, err := proptools.RepackProperties([]interface{}{baseProps, fsProps, depProps})
if err != nil {
ctx.ModuleErrorf(err.Error())
}
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 554b66b..484cc38 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"android/soong/filesystem"
+ "android/soong/java"
"testing"
"github.com/google/blueprint/proptools"
@@ -28,6 +29,7 @@
result := android.GroupFixturePreparers(
android.PrepareForIntegrationTestWithAndroid,
android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
filesystem.PrepareForTestWithFilesystemBuildComponents,
prepareForTestWithFsgenBuildComponents,
android.FixtureModifyConfig(func(config android.Config) {
@@ -86,3 +88,132 @@
proptools.String(fooSystem.FsProps().Type),
)
}
+
+func TestFileSystemCreatorSetPartitionDeps(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar", "baz"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardFileSystemType: "ext4",
+ },
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ }),
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ }
+ java_library {
+ name: "baz",
+ srcs: ["A.java"],
+ product_specific: true,
+ }
+ `)
+
+ android.AssertBoolEquals(
+ t,
+ "Generated system image expected to depend on system partition installed \"bar\"",
+ true,
+ java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "bar"),
+ )
+ android.AssertBoolEquals(
+ t,
+ "Generated system image expected to not depend on product partition installed \"baz\"",
+ false,
+ java.CheckModuleHasDependency(t, result.TestContext, "test_product_generated_system_image", "android_common", "baz"),
+ )
+}
+
+func TestFileSystemCreatorDepsWithNamespace(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithNamespace,
+ android.PrepareForTestWithArchMutator,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"bar"}
+ config.TestProductVariables.NamespacesToExport = []string{"a/b"}
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardFileSystemType: "ext4",
+ },
+ }
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: "", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64", HostCross: false},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm", HostCross: false},
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ "a/b/Android.bp": []byte(`
+ soong_namespace{
+ }
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ compile_multilib: "64",
+ }
+ `),
+ "c/d/Android.bp": []byte(`
+ soong_namespace{
+ }
+ java_library {
+ name: "bar",
+ srcs: ["A.java"],
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ var packagingProps android.PackagingProperties
+ for _, prop := range result.ModuleForTests("test_product_generated_system_image", "android_common").Module().GetProperties() {
+ if packagingPropStruct, ok := prop.(*android.PackagingProperties); ok {
+ packagingProps = *packagingPropStruct
+ }
+ }
+ moduleDeps := packagingProps.Multilib.Lib64.Deps
+
+ eval := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringListContains(
+ t,
+ "Generated system image expected to depend on \"bar\" defined in \"a/b\" namespace",
+ moduleDeps.GetOrDefault(eval, nil),
+ "//a/b:bar",
+ )
+ android.AssertStringListDoesNotContain(
+ t,
+ "Generated system image expected to not depend on \"bar\" defined in \"c/d\" namespace",
+ moduleDeps.GetOrDefault(eval, nil),
+ "//c/d:bar",
+ )
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 349615f..f2a761c 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -219,6 +219,7 @@
// For nsjail tasks
useNsjail bool
+ dirSrcs android.Paths
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -579,10 +580,12 @@
}
if task.useNsjail {
- for _, input := range task.in {
- // can fail if input is a file.
+ for _, input := range task.dirSrcs {
+ cmd.Implicit(input)
if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
rule.NsjailImplicits(android.PathsForSource(ctx, paths))
+ } else {
+ ctx.PropertyErrorf("dir_srcs", "can't glob %q", input.String())
}
}
}
@@ -858,6 +861,12 @@
taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
useNsjail := Bool(properties.Use_nsjail)
+ dirSrcs := android.DirectoryPathsForModuleSrc(ctx, properties.Dir_srcs)
+ if len(dirSrcs) > 0 && !useNsjail {
+ ctx.PropertyErrorf("dir_srcs", "can't use dir_srcs if use_nsjail is false")
+ return nil
+ }
+
outs := make(android.WritablePaths, len(properties.Out))
for i, out := range properties.Out {
outs[i] = android.PathForModuleGen(ctx, out)
@@ -868,6 +877,7 @@
genDir: android.PathForModuleGen(ctx),
cmd: rawCommand,
useNsjail: useNsjail,
+ dirSrcs: dirSrcs,
}}
}
@@ -884,6 +894,10 @@
type genRuleProperties struct {
Use_nsjail *bool
+ // List of input directories. Can be set only when use_nsjail is true. Currently, usage of
+ // dir_srcs is limited only to Trusty build.
+ Dir_srcs []string `android:"path"`
+
// names of the output files that will be generated
Out []string `android:"arch_variant"`
}
diff --git a/java/app.go b/java/app.go
index dd99675..e112e93 100644
--- a/java/app.go
+++ b/java/app.go
@@ -30,7 +30,6 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/genrule"
"android/soong/tradefed"
)
@@ -1333,7 +1332,7 @@
Srcs: []string{":" + a.Name() + "{.apk}"},
Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $$($(location aapt2) dump packagename $(in)) $(out)"),
}
- ctx.CreateModule(genrule.GenRuleFactory, &rroManifestProperties)
+ ctx.CreateModule(GenRuleFactory, &rroManifestProperties)
rroProperties := struct {
Name *string
diff --git a/java/app_import.go b/java/app_import.go
index a54cf2f..f5d9f3e 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -61,6 +61,9 @@
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
+ ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("disable_prebuilts_without_apk", disablePrebuiltsWithoutApkMutator)
+ })
}
type AndroidAppImport struct {
@@ -90,7 +93,7 @@
type AndroidAppImportProperties struct {
// A prebuilt apk to import
- Apk *string `android:"path"`
+ Apk proptools.Configurable[string] `android:"path,replace_instead_of_append"`
// The name of a certificate in the default certificate directory or an android_app_certificate
// module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
@@ -193,13 +196,6 @@
}
}
}
-
- if String(a.properties.Apk) == "" {
- // Disable this module since the apk property is still empty after processing all matching
- // variants. This likely means there is no matching variant, and the default variant doesn't
- // have an apk property value either.
- a.Disable()
- }
}
func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
@@ -219,6 +215,30 @@
}
}
+// disablePrebuiltsWithoutApkMutator is a pre-arch mutator that disables AndroidAppImport or
+// AndroidTestImport modules that don't have an apk set. We need this separate mutator instead
+// of doing it in processVariants because processVariants is a defaultable hook, and configurable
+// properties can only be evaluated after the defaults (and eventually, base configurabtion)
+// mutators.
+func disablePrebuiltsWithoutApkMutator(ctx android.BottomUpMutatorContext) {
+ switch a := ctx.Module().(type) {
+ case *AndroidAppImport:
+ if a.properties.Apk.GetOrDefault(ctx, "") == "" {
+ // Disable this module since the apk property is still empty after processing all
+ // matching variants. This likely means there is no matching variant, and the default
+ // variant doesn't have an apk property value either.
+ a.Disable()
+ }
+ case *AndroidTestImport:
+ if a.properties.Apk.GetOrDefault(ctx, "") == "" {
+ // Disable this module since the apk property is still empty after processing all
+ // matching variants. This likely means there is no matching variant, and the default
+ // variant doesn't have an apk property value either.
+ a.Disable()
+ }
+ }
+}
+
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
@@ -409,7 +429,7 @@
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
- artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
+ artifactPath := android.PathForModuleSrc(ctx, a.properties.Apk.GetOrDefault(ctx, ""))
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
@@ -633,7 +653,7 @@
android.InitApexModule(module)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+ android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")
module.usesLibrary.enforce = true
@@ -686,7 +706,7 @@
android.InitApexModule(module)
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+ android.InitConfigurablePrebuiltModuleString(module, &module.properties.Apk, "Apk")
return module
}
diff --git a/java/builder.go b/java/builder.go
index e5d5109..895ddb6 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -301,7 +301,7 @@
gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}={state:bool}' ` +
+ Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}' ` +
`--out ${out} ` +
`${flags_path} ` +
`${filter_args} `,
diff --git a/java/java.go b/java/java.go
index 0b48873..288042b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2454,7 +2454,7 @@
ret := []string{}
ret = append(ret, al.properties.Libs.GetOrDefault(ctx, nil)...)
ret = append(ret, al.properties.Static_libs.GetOrDefault(ctx, nil)...)
- if al.properties.System_modules != nil {
+ if proptools.StringDefault(al.properties.System_modules, "none") != "none" {
ret = append(ret, proptools.String(al.properties.System_modules))
}
// Other non java_library dependencies like java_api_contribution are ignored for now.
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index 7a0fb10..1435000 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -134,3 +134,42 @@
android.AssertStringListContains(t, "IdeInfo.Deps should contain versioned sdk module", dpInfo.Deps, "sdk_public_29_android")
}
+
+func TestDoNotAddNoneSystemModulesToDeps(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t,
+ `
+ java_library {
+ name: "javalib",
+ srcs: ["foo.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+
+ java_api_library {
+ name: "javalib.stubs",
+ stubs_type: "everything",
+ api_contributions: ["javalib-current.txt"],
+ api_surface: "public",
+ system_modules: "none",
+ }
+ java_api_contribution {
+ name: "javalib-current.txt",
+ api_file: "javalib-current.txt",
+ api_surface: "public",
+ }
+ `)
+ javalib := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ dpInfo, _ := android.OtherModuleProvider(ctx, javalib, android.IdeInfoProviderKey)
+ android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
+
+ javalib_stubs := ctx.ModuleForTests("javalib.stubs", "android_common").Module().(*ApiLibrary)
+ dpInfo, _ = android.OtherModuleProvider(ctx, javalib_stubs, android.IdeInfoProviderKey)
+ android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
+}
diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh
index 9c48fdb..48efb7a 100755
--- a/scripts/keep-flagged-apis.sh
+++ b/scripts/keep-flagged-apis.sh
@@ -25,21 +25,12 @@
# Convert the list of feature flags in the input file to Metalava options
# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")`
# to prevent the annotated APIs from being hidden, i.e. include the annotated
-# APIs in the SDK snapshots. This also preserves the line comments, they will
-# be ignored by Metalava but might be useful when debugging.
+# APIs in the SDK snapshots.
while read -r line; do
- key=$(echo "$line" | cut -d= -f1)
- value=$(echo "$line" | cut -d= -f2)
-
- # Skip if value is not true and line does not start with '#'
- if [[ ( $value != "true" ) && ( $line =~ ^[^#] )]]; then
- continue
- fi
-
# Escape and quote the key for sed
- escaped_key=$(echo "$key" | sed "s/'/\\\'/g; s/ /\\ /g")
+ escaped_line=$(echo "$line" | sed "s/'/\\\'/g; s/ /\\ /g")
- echo $line | sed "s|^[^#].*$|--revert-annotation '!$FLAGGED(\"$escaped_key\")'|"
+ echo "--revert-annotation '!$FLAGGED(\"$escaped_line\")'"
done < "$FLAGS"
# Revert all flagged APIs, unless listed above.
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index 2ec8972..a8044df 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -16,6 +16,8 @@
import (
"strings"
+
+ "android/soong/android"
)
var androidmk_denylist []string = []string{
@@ -64,3 +66,29 @@
}
}
}
+
+// The Android.mk files in these directories are for NDK build system.
+var external_ndk_androidmks []string = []string{
+ "external/fmtlib/",
+ "external/google-breakpad/",
+ "external/googletest/",
+ "external/libaom/",
+ "external/libusb/",
+ "external/libvpx/",
+ "external/libwebm/",
+ "external/libwebsockets/",
+ "external/vulkan-validation-layers/",
+ "external/walt/",
+ "external/webp/",
+}
+
+func ignoreNdkAndroidMks(androidMks []string) []string {
+ return android.FilterListPred(androidMks, func(s string) bool {
+ for _, d := range external_ndk_androidmks {
+ if strings.HasPrefix(s, d) {
+ return false
+ }
+ }
+ return true
+ })
+}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 573df21..a899822 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -128,6 +128,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
+ androidMks = ignoreNdkAndroidMks(androidMks)
blockAndroidMks(ctx, androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {