Merge "Update min_sdk_version used in TestSymlinksFromApexToSystem"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index ff0d33e..1ece9fa 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -132,6 +132,7 @@
"external/f2fs-tools": Bp2BuildDefaultTrue,
"external/flac": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
+ "external/guava": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
"external/gwp_asan": Bp2BuildDefaultTrueRecursively,
@@ -385,6 +386,7 @@
"build/bazel":/* recursive = */ true,
"build/make/core":/* recursive = */ false,
"build/bazel_common_rules":/* recursive = */ true,
+ "build/make/target/product/security":/* recursive = */ false,
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
"build/pesto":/* recursive = */ true,
@@ -396,7 +398,6 @@
"external/bazelbuild-rules_license":/* recursive = */ true,
"external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
- "external/guava":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
"external/python/absl-py":/* recursive = */ true,
@@ -710,6 +711,8 @@
// allowlisting for kotlinx_coroutines
"kotlinx_coroutines",
+ "kotlinx_coroutines-device",
+ "kotlinx_coroutines-host",
"annotations",
"kotlinx-coroutines-android-annotation-stubs",
diff --git a/android/api_levels.go b/android/api_levels.go
index ea2afdf..7214ccb 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -344,14 +344,17 @@
}
}
- canonical := ReplaceFinalizedCodenames(config, raw)
- asInt, err := strconv.Atoi(canonical)
- if err != nil {
- return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", canonical)
+ canonical, ok := getApiLevelsMapReleasedVersions()[raw]
+ if !ok {
+ asInt, err := strconv.Atoi(raw)
+ if err != nil {
+ return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw)
+ }
+ return uncheckedFinalApiLevel(asInt), nil
}
- apiLevel := uncheckedFinalApiLevel(asInt)
- return apiLevel, nil
+ return uncheckedFinalApiLevel(canonical), nil
+
}
// ApiLevelForTest returns an ApiLevel constructed from the supplied raw string.
diff --git a/android/config.go b/android/config.go
index 33deba5..6765f1f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -913,8 +913,16 @@
return c.PlatformSdkVersion()
}
codename := c.PlatformSdkCodename()
+ hostOnlyBuild := c.productVariables.DeviceArch == nil
if codename == "" {
- return NoneApiLevel
+ // There are some host-only builds (those are invoked by build-prebuilts.sh) which
+ // don't set platform sdk codename. Platform sdk codename makes sense only when we
+ // are building the platform. So we don't enforce the below panic for the host-only
+ // builds.
+ if hostOnlyBuild {
+ return NoneApiLevel
+ }
+ panic("Platform_sdk_codename must be set")
}
if codename == "REL" {
panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true")
@@ -1418,6 +1426,21 @@
return c.config.productVariables.PgoAdditionalProfileDirs
}
+// AfdoProfile returns fully qualified path associated to the given module name
+func (c *deviceConfig) AfdoProfile(name string) (*string, error) {
+ for _, afdoProfile := range c.config.productVariables.AfdoProfiles {
+ split := strings.Split(afdoProfile, ":")
+ if len(split) != 3 {
+ return nil, fmt.Errorf("AFDO_PROFILES has invalid value: %s. "+
+ "The expected format is <module>:<fully-qualified-path-to-fdo_profile>", afdoProfile)
+ }
+ if split[0] == name {
+ return proptools.StringPtr(strings.Join([]string{split[1], split[2]}, ":")), nil
+ }
+ }
+ return nil, nil
+}
+
func (c *deviceConfig) VendorSepolicyDirs() []string {
return c.config.productVariables.BoardVendorSepolicyDirs
}
@@ -1894,3 +1917,7 @@
func (c *config) BuildFromTextStub() bool {
return c.buildFromTextStub
}
+
+func (c *config) SetBuildFromTextStub(b bool) {
+ c.buildFromTextStub = b
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index 38de855..c259f21 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -126,7 +126,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
}
ctx.CreateBazelTargetModule(
diff --git a/android/packaging.go b/android/packaging.go
index 4a9b591..c764a6d 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -238,11 +238,11 @@
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
-func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir ModuleOutPath) (entries []string) {
+func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
seenDir := make(map[string]bool)
for _, k := range SortedKeys(specs) {
ps := specs[k]
- destPath := dir.Join(ctx, ps.relPathInPackage).String()
+ destPath := filepath.Join(dir.String(), ps.relPathInPackage)
destDir := filepath.Dir(destPath)
entries = append(entries, ps.relPathInPackage)
if _, ok := seenDir[destDir]; !ok {
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 1f01dc6..0ae8073 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -86,7 +86,7 @@
// JavaLibraryName returns the soong module containing the Java APIs of that API surface.
func (k SdkKind) JavaLibraryName(c Config) string {
- name := k.defaultJavaLibraryName()
+ name := k.DefaultJavaLibraryName()
return JavaApiLibraryName(c, name)
}
@@ -100,7 +100,7 @@
return name
}
-func (k SdkKind) defaultJavaLibraryName() string {
+func (k SdkKind) DefaultJavaLibraryName() string {
switch k {
case SdkPublic:
return "android_stubs_current"
diff --git a/android/variable.go b/android/variable.go
index 1da5974..249d53b 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -464,6 +464,8 @@
IncludeTags []string `json:",omitempty"`
SourceRootDirs []string `json:",omitempty"`
+
+ AfdoProfiles []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index 3678636..5451a04 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1986,9 +1986,9 @@
// Set the output file to .apex or .capex depending on the compression configuration.
a.setCompression(ctx)
if a.isCompressed {
- a.outputApexFile = android.PathForBazelOut(ctx, outputs.SignedCompressedOutput)
+ a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedCompressedOutput)
} else {
- a.outputApexFile = android.PathForBazelOut(ctx, outputs.SignedOutput)
+ a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedOutput)
}
a.outputFile = a.outputApexFile
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 6edd78a..598ca32 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -61,6 +61,7 @@
"genrule_conversion_test.go",
"gensrcs_conversion_test.go",
"java_binary_host_conversion_test.go",
+ "java_host_for_device_conversion_test.go",
"java_import_conversion_test.go",
"java_library_conversion_test.go",
"java_library_host_conversion_test.go",
diff --git a/bp2build/java_host_for_device_conversion_test.go b/bp2build/java_host_for_device_conversion_test.go
new file mode 100644
index 0000000..d908d00
--- /dev/null
+++ b/bp2build/java_host_for_device_conversion_test.go
@@ -0,0 +1,63 @@
+// Copyright 2023 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 bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "java_host_for_device"
+ (&tc).ModuleTypeUnderTestFactory = java.HostForDeviceFactory
+ RunBp2BuildTestCase(t, registrationCtxFunc, tc)
+}
+
+func runJavaHostForDeviceTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ })
+}
+
+func TestJavaHostForDevice(t *testing.T) {
+ runJavaHostForDeviceTestCase(t, Bp2buildTestCase{
+ Description: "java_host_for_device test",
+ Blueprint: `java_host_for_device {
+ name: "java-lib-1",
+ libs: ["java-lib-2"],
+ bazel_module: { bp2build_available: true },
+}
+
+java_library {
+ name: "java-lib-2",
+ srcs: ["b.java"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_host_for_device", "java-lib-1", AttrNameToString{
+ "deps": `[":java-lib-2"]`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+ MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
+ "srcs": `["b.java"]`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
+ },
+ })
+}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 69d0db9..683ee27 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -740,7 +740,7 @@
})
}
-func TestJavaLibraryArchVariantLibs(t *testing.T) {
+func TestJavaLibraryArchVariantDeps(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
Description: "java_library with arch variant libs",
Blueprint: `java_library {
@@ -750,6 +750,7 @@
target: {
android: {
libs: ["java-lib-3"],
+ static_libs: ["java-lib-4"],
},
},
bazel_module: { bp2build_available: true },
@@ -762,12 +763,23 @@
java_library{
name: "java-lib-3",
}
+
+ java_library{
+ name: "java-lib-4",
+}
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"srcs": `["a.java"]`,
+ "exports": `select({
+ "//build/bazel/platforms/os:android": [":java-lib-4"],
+ "//conditions:default": [],
+ })`,
"deps": `[":java-lib-2-neverlink"] + select({
- "//build/bazel/platforms/os:android": [":java-lib-3-neverlink"],
+ "//build/bazel/platforms/os:android": [
+ ":java-lib-3-neverlink",
+ ":java-lib-4",
+ ],
"//conditions:default": [],
})`,
}),
@@ -776,6 +788,8 @@
MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
MakeBazelTarget("java_library", "java-lib-3", AttrNameToString{}),
MakeNeverlinkDuplicateTarget("java_library", "java-lib-3"),
+ MakeBazelTarget("java_library", "java-lib-4", AttrNameToString{}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-4"),
},
})
}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index aac5e7d..5c33308 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -21,10 +21,13 @@
"path/filepath"
"regexp"
"sort"
+ "strconv"
+ "strings"
"sync"
"sync/atomic"
"android/soong/shared"
+
"github.com/google/blueprint/pathtools"
)
@@ -35,6 +38,13 @@
// excluded from symlinking. Otherwise, the node is not excluded, but one of its
// descendants is (otherwise the node in question would not exist)
+// This is a version int written to a file called symlink_forest_version at the root of the
+// symlink forest. If the version here does not match the version in the file, then we'll
+// clean the whole symlink forest and recreate it. This number can be bumped whenever there's
+// an incompatible change to the forest layout or a bug in incrementality that needs to be fixed
+// on machines that may still have the bug present in their forest.
+const symlinkForestVersion = 1
+
type instructionsNode struct {
name string
excluded bool // If false, this is just an intermediate node
@@ -123,6 +133,34 @@
}
newContents = append(newContents, srcBuildFileContent...)
+ // Say you run bp2build 4 times:
+ // - The first time there's only an Android.bp file. bp2build will convert it to a build file
+ // under out/soong/bp2build, then symlink from the forest to that generated file
+ // - Then you add a handcrafted BUILD file in the same directory. bp2build will merge this with
+ // the generated one, and write the result to the output file in the forest. But the output
+ // file was a symlink to out/soong/bp2build from the previous step! So we erroneously update
+ // the file in out/soong/bp2build instead. So far this doesn't cause any problems...
+ // - You run a 3rd bp2build with no relevant changes. Everything continues to work.
+ // - You then add a comment to the handcrafted BUILD file. This causes a merge with the
+ // generated file again. But since we wrote to the generated file in step 2, the generated
+ // file has an old copy of the handcrafted file in it! This probably causes duplicate bazel
+ // targets.
+ // To solve this, if we see that the output file is a symlink from a previous build, remove it.
+ stat, err := os.Lstat(output)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ } else if err == nil {
+ if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Removing symlink so that we can replace it with a merged file: %s\n", output)
+ }
+ err = os.Remove(output)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
return pathtools.WriteFileIfChanged(output, newContents, 0666)
}
@@ -202,6 +240,46 @@
return false
}
+// maybeCleanSymlinkForest will remove the whole symlink forest directory if the version recorded
+// in the symlink_forest_version file is not equal to symlinkForestVersion.
+func maybeCleanSymlinkForest(topdir, forest string, verbose bool) error {
+ versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
+ versionFileContents, err := os.ReadFile(versionFilePath)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ versionFileString := strings.TrimSpace(string(versionFileContents))
+ symlinkForestVersionString := strconv.Itoa(symlinkForestVersion)
+ if err != nil || versionFileString != symlinkForestVersionString {
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Old symlink_forest_version was %q, current is %q. Cleaning symlink forest before recreating...\n", versionFileString, symlinkForestVersionString)
+ }
+ err = os.RemoveAll(shared.JoinPath(topdir, forest))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// maybeWriteVersionFile will write the symlink_forest_version file containing symlinkForestVersion
+// if it doesn't exist already. If it exists we know it must contain symlinkForestVersion because
+// we checked for that already in maybeCleanSymlinkForest
+func maybeWriteVersionFile(topdir, forest string) error {
+ versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
+ _, err := os.Stat(versionFilePath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ }
+ err = os.WriteFile(versionFilePath, []byte(strconv.Itoa(symlinkForestVersion)+"\n"), 0666)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// Recursively plants a symlink forest at forestDir. The symlink tree will
// contain every file in buildFilesDir and srcDir excluding the files in
// instructions. Collects every directory encountered during the traversal of
@@ -395,6 +473,12 @@
symlinkCount: atomic.Uint64{},
}
+ err := maybeCleanSymlinkForest(topdir, forest, verbose)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
instructions := instructionsFromExcludePathList(exclude)
go func() {
context.wg.Add(1)
@@ -407,5 +491,11 @@
deps = append(deps, dep)
}
+ err = maybeWriteVersionFile(topdir, forest)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
return deps, context.mkdirCount.Load(), context.symlinkCount.Load()
}
diff --git a/cc/Android.bp b/cc/Android.bp
index 5fd9afe..be2cc5a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -21,6 +21,8 @@
],
srcs: [
"afdo.go",
+ "fdo_profile.go",
+
"androidmk.go",
"api_level.go",
"bp2build.go",
diff --git a/cc/afdo.go b/cc/afdo.go
index d36f4af..be4f50a 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -18,11 +18,13 @@
"fmt"
"strings"
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
+// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
var (
globalAfdoProfileProjects = []string{
"vendor/google_data/pgo_profile/sampling/",
@@ -34,23 +36,23 @@
const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
-func getAfdoProfileProjects(config android.DeviceConfig) []string {
- return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
- return globalAfdoProfileProjects
- })
-}
-
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
}
+type afdoRdep struct {
+ VariationName *string
+ ProfilePath *string
+}
+
type AfdoProperties struct {
// Afdo allows developers self-service enroll for
// automatic feedback-directed optimization using profile data.
Afdo bool
- AfdoTarget *string `blueprint:"mutated"`
- AfdoDeps []string `blueprint:"mutated"`
+ FdoProfilePath *string `blueprint:"mutated"`
+
+ AfdoRDeps []afdoRdep `blueprint:"mutated"`
}
type afdo struct {
@@ -61,116 +63,131 @@
return []interface{}{&afdo.Properties}
}
-func (afdo *afdo) AfdoEnabled() bool {
- return afdo != nil && afdo.Properties.Afdo && afdo.Properties.AfdoTarget != nil
-}
-
-// Get list of profile file names, ordered by level of specialisation. For example:
-// 1. libfoo_arm64.afdo
-// 2. libfoo.afdo
-//
-// Add more specialisation as needed.
-func getProfileFiles(ctx android.BaseModuleContext, moduleName string) []string {
- var files []string
- files = append(files, moduleName+"_"+ctx.Arch().ArchType.String()+".afdo")
- files = append(files, moduleName+".afdo")
- return files
-}
-
-func (props *AfdoProperties) GetAfdoProfileFile(ctx android.BaseModuleContext, module string) android.OptionalPath {
- // Test if the profile_file is present in any of the Afdo profile projects
- for _, profileFile := range getProfileFiles(ctx, module) {
- for _, profileProject := range getAfdoProfileProjects(ctx.DeviceConfig()) {
- path := android.ExistentPathForSource(ctx, profileProject, profileFile)
- if path.Valid() {
- return path
- }
- }
- }
-
- // Record that this module's profile file is absent
- missing := ctx.ModuleDir() + ":" + module
- recordMissingAfdoProfileFile(ctx, missing)
-
- return android.OptionalPathForPath(nil)
-}
-
-func (afdo *afdo) begin(ctx BaseModuleContext) {
- if ctx.Host() {
- return
- }
- if ctx.static() && !ctx.staticBinary() {
- return
- }
- if afdo.Properties.Afdo {
- module := ctx.ModuleName()
- if afdo.Properties.GetAfdoProfileFile(ctx, module).Valid() {
- afdo.Properties.AfdoTarget = proptools.StringPtr(module)
- }
- }
+// afdoEnabled returns true for binaries and shared libraries
+// that set afdo prop to True and there is a profile available
+func (afdo *afdo) afdoEnabled() bool {
+ return afdo != nil && afdo.Properties.Afdo && afdo.Properties.FdoProfilePath != nil
}
func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
- if profile := afdo.Properties.AfdoTarget; profile != nil {
- if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, *profile); profileFile.Valid() {
- profileFilePath := profileFile.Path()
+ if path := afdo.Properties.FdoProfilePath; path != nil {
+ // The flags are prepended to allow overriding.
+ profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
+ flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
+ flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
- profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, profileFile)
- flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-no-warn-sample-unused=true")
-
- // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
- // if profileFile gets updated
- flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
- }
+ // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+ // if profileFile gets updated
+ pathForSrc := android.PathForSource(ctx, *path)
+ flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
+ flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
}
return flags
}
-// Propagate afdo requirements down from binaries
+func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
+ if ctx.Host() {
+ return
+ }
+
+ if ctx.static() && !ctx.staticBinary() {
+ return
+ }
+
+ if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
+ if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
+ actx.AddFarVariationDependencies(
+ []blueprint.Variation{
+ {Mutator: "arch", Variation: actx.Target().ArchVariation()},
+ {Mutator: "os", Variation: "android"},
+ },
+ FdoProfileTag,
+ []string{*fdoProfileName}...,
+ )
+ }
+ }
+}
+
+// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
+// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
+func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if !c.Enabled() {
+ return
+ }
+
+ ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
+ if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
+ info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
+ c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
+ }
+ })
+}
+
+var _ FdoProfileMutatorInterface = (*Module)(nil)
+
+// Propagate afdo requirements down from binaries and shared libraries
func afdoDepsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok && m.afdo.AfdoEnabled() {
- afdoTarget := *m.afdo.Properties.AfdoTarget
- mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
- tag := mctx.OtherModuleDependencyTag(dep)
- libTag, isLibTag := tag.(libraryDependencyTag)
+ if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
+ if path := m.afdo.Properties.FdoProfilePath; path != nil {
+ mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ tag := mctx.OtherModuleDependencyTag(dep)
+ libTag, isLibTag := tag.(libraryDependencyTag)
- // Do not recurse down non-static dependencies
- if isLibTag {
- if !libTag.static() {
- return false
+ // Do not recurse down non-static dependencies
+ if isLibTag {
+ if !libTag.static() {
+ return false
+ }
+ } else {
+ if tag != objDepTag && tag != reuseObjTag {
+ return false
+ }
}
- } else {
- if tag != objDepTag && tag != reuseObjTag {
- return false
+
+ if dep, ok := dep.(*Module); ok {
+ dep.afdo.Properties.AfdoRDeps = append(
+ dep.afdo.Properties.AfdoRDeps,
+ afdoRdep{
+ VariationName: proptools.StringPtr(encodeTarget(m.Name())),
+ ProfilePath: path,
+ },
+ )
}
- }
- if dep, ok := dep.(*Module); ok {
- dep.afdo.Properties.AfdoDeps = append(dep.afdo.Properties.AfdoDeps, afdoTarget)
- }
-
- return true
- })
+ return true
+ })
+ }
}
}
// Create afdo variants for modules that need them
func afdoMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
- if m.afdo.AfdoEnabled() && !m.static() {
- afdoTarget := *m.afdo.Properties.AfdoTarget
- mctx.SetDependencyVariation(encodeTarget(afdoTarget))
+ if !m.static() && m.afdo.Properties.Afdo && m.afdo.Properties.FdoProfilePath != nil {
+ mctx.SetDependencyVariation(encodeTarget(m.Name()))
+ return
}
variationNames := []string{""}
- afdoDeps := android.FirstUniqueStrings(m.afdo.Properties.AfdoDeps)
- for _, dep := range afdoDeps {
- variationNames = append(variationNames, encodeTarget(dep))
+
+ variantNameToProfilePath := make(map[string]*string)
+
+ for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
+ variantName := *afdoRDep.VariationName
+ // An rdep can be set twice in AfdoRDeps because there can be
+ // more than one path from an afdo-enabled module to
+ // a static dep such as
+ // afdo_enabled_foo -> static_bar ----> static_baz
+ // \ ^
+ // ----------------------|
+ // We only need to create one variant per unique rdep
+ if variantNameToProfilePath[variantName] == nil {
+ variationNames = append(variationNames, variantName)
+ variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
+ }
}
+
if len(variationNames) > 1 {
modules := mctx.CreateVariations(variationNames...)
for i, name := range variationNames {
@@ -180,7 +197,7 @@
variation := modules[i].(*Module)
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
- variation.afdo.Properties.AfdoTarget = proptools.StringPtr(decodeTarget(name))
+ variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
}
}
}
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index 40f705b..1c20bfc 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -58,38 +58,77 @@
srcs: ["bar.c"],
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
prepareForCcTest,
- prepareForAfdoTest,
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+ expectedCFlag := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
- if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+
+ // Check cFlags of afdo-enabled module and the afdo-variant of its static deps
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libFooAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBarAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edge from afdo-enabled module to static deps
+ if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libBar")
}
- cFlags := libTest.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", w, cFlags)
- }
+ // Verify non-afdo variant exists and doesn't contain afdo
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libFoo' to enable afdo, but did not find %q in cflags %q", w, cFlags)
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ }
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
}
- cFlags = libBar.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", w, cFlags)
+ // Check dependency edges of static deps
+ if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest should not depend on non-afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
}
@@ -113,11 +152,21 @@
name: "libBar",
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", "TEST")
result := android.GroupFixturePreparers(
prepareForCcTest,
- prepareForAfdoTest,
+ PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", ""),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ soong_namespace {
+ }
+ fdo_profile {
+ name: "libFoo_afdo",
+ profile: "libFoo.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
@@ -150,7 +199,6 @@
t.Errorf("Expected no afdo variant of 'bar', got %q", v)
}
}
-
}
func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
@@ -166,11 +214,24 @@
name: "libFoo",
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
result := android.GroupFixturePreparers(
prepareForCcTest,
- prepareForAfdoTest,
+ PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
libFooVariants := result.ModuleVariantsForTests("libFoo")
@@ -182,7 +243,6 @@
}
func TestAfdoEnabledWithMultiArchs(t *testing.T) {
- t.Parallel()
bp := `
cc_library_shared {
name: "foo",
@@ -192,20 +252,43 @@
}
`
result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
prepareForCcTest,
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", "TEST"),
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", "TEST"),
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ soong_namespace {
+ }
+ fdo_profile {
+ name: "foo_afdo",
+ arch: {
+ arm: {
+ profile: "foo_arm.afdo",
+ },
+ arm64: {
+ profile: "foo_arm64.afdo",
+ }
+ }
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
+ if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
}
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
+ if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
}
}
@@ -234,46 +317,65 @@
`
result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
prepareForCcTest,
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST"),
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libBar.afdo", "TEST"),
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/libBar.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ "libBar://afdo_profiles_package:libBar_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ fdo_profile {
+ name: "libBar_afdo",
+ profile: "libBar.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
- expectedCFlagLibTest := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libTest.afdo"
- expectedCFlagLibBar := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libBar.afdo"
+ expectedCFlagLibTest := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
+ expectedCFlagLibBar := "-fprofile-sample-use=afdo_profiles_package/libBar.afdo"
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libTestAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libFooAfdoVariantWithLibTest := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
- libBarAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
+ libFooAfdoVariantWithLibBar := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
- // Check cFlags of afdo-enabled modules and the afdo-variant of their static deps
+ // Check cFlags of afdo-enabled module and the afdo-variant of its static deps
cFlags := libTest.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlagLibTest) {
t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
}
cFlags = libBar.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlagLibBar) {
- t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
}
- cFlags = libTestAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+ cFlags = libFooAfdoVariantWithLibTest.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlagLibTest) {
- t.Errorf("Expected 'libTestAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+ t.Errorf("Expected 'libFooAfdoVariantWithLibTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
}
- cFlags = libBarAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+ cFlags = libFooAfdoVariantWithLibBar.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlagLibBar) {
- t.Errorf("Expected 'libBarAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
}
// Check dependency edges of static deps
- if !hasDirectDep(result, libTest.Module(), libTestAfdoVariantOfLibFoo.Module()) {
+ if !hasDirectDep(result, libTest.Module(), libFooAfdoVariantWithLibTest.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libBar.Module(), libBarAfdoVariantOfLibFoo.Module()) {
- t.Errorf("libBar missing dependency on afdo variant of libFoo")
+ if !hasDirectDep(result, libBar.Module(), libFooAfdoVariantWithLibBar.Module()) {
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 7c817a2..c8f516c 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -915,7 +915,7 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
android.CommonAttributes{Name: aidlLibName},
&aidlLibraryAttributes{
diff --git a/cc/cc.go b/cc/cc.go
index b029d71..9c555a1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,7 @@
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", versionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
+ ctx.BottomUp("fdo_profile", fdoProfileMutator)
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -763,6 +764,7 @@
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
stubImplDepTag = dependencyTag{name: "stub_impl"}
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
+ FdoProfileTag = dependencyTag{name: "fdo_profile"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
@@ -1336,7 +1338,7 @@
func (c *Module) isAfdoCompile() bool {
if afdo := c.afdo; afdo != nil {
- return afdo.Properties.AfdoTarget != nil
+ return afdo.Properties.FdoProfilePath != nil
}
return false
}
@@ -2162,9 +2164,6 @@
if c.lto != nil {
c.lto.begin(ctx)
}
- if c.afdo != nil {
- c.afdo.begin(ctx)
- }
if c.pgo != nil {
c.pgo.begin(ctx)
}
@@ -2239,6 +2238,10 @@
}
ctx.ctx = ctx
+ if !actx.Host() || !ctx.static() || ctx.staticBinary() {
+ c.afdo.addDep(ctx, actx)
+ }
+
c.begin(ctx)
}
diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go
new file mode 100644
index 0000000..7fbe719
--- /dev/null
+++ b/cc/fdo_profile.go
@@ -0,0 +1,85 @@
+// Copyright 2023 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"
+
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterFdoProfileBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+}
+
+type fdoProfile struct {
+ android.ModuleBase
+
+ properties fdoProfileProperties
+}
+
+type fdoProfileProperties struct {
+ Profile *string `android:"arch_variant"`
+}
+
+// FdoProfileInfo is provided by FdoProfileProvider
+type FdoProfileInfo struct {
+ Path android.Path
+}
+
+// FdoProfileProvider is used to provide path to an fdo profile
+var FdoProfileProvider = blueprint.NewMutatorProvider(FdoProfileInfo{}, "fdo_profile")
+
+// FdoProfileMutatorInterface is the interface implemented by fdo_profile module type
+// module types that can depend on an fdo_profile module
+type FdoProfileMutatorInterface interface {
+ // FdoProfileMutator eithers set or get FdoProfileProvider
+ fdoProfileMutator(ctx android.BottomUpMutatorContext)
+}
+
+var _ FdoProfileMutatorInterface = (*fdoProfile)(nil)
+
+// GenerateAndroidBuildActions of fdo_profile does not have any build actions
+func (fp *fdoProfile) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+// FdoProfileMutator sets FdoProfileProvider to fdo_profile module
+// or sets afdo.Properties.FdoProfilePath to path in FdoProfileProvider of the depended fdo_profile
+func (fp *fdoProfile) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if fp.properties.Profile != nil {
+ path := android.PathForModuleSrc(ctx, *fp.properties.Profile)
+ ctx.SetProvider(FdoProfileProvider, FdoProfileInfo{
+ Path: path,
+ })
+ }
+}
+
+// fdoProfileMutator calls the generic fdoProfileMutator function of fdoProfileMutator
+// which is implemented by cc and cc.FdoProfile
+func fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if f, ok := ctx.Module().(FdoProfileMutatorInterface); ok {
+ f.fdoProfileMutator(ctx)
+ }
+}
+
+func fdoProfileFactory() android.Module {
+ m := &fdoProfile{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
+ return m
+}
diff --git a/cc/library.go b/cc/library.go
index a9ada97..7504302 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -26,7 +26,6 @@
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
- "android/soong/cc/config"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
@@ -2261,8 +2260,7 @@
!ctx.useVndk() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
ctx.isForPlatform() && !ctx.isPreventInstall() {
- installPath := getNdkSysrootBase(ctx).Join(
- ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
+ installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: android.Cp,
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2473ba2..a824361 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -528,17 +528,20 @@
return false
}
-func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) {
- arch := ctx.Target().Arch.ArchType.Name
- // arm64 isn't actually a multilib toolchain, so unlike the other LP64
- // architectures it's just installed to lib.
- libDir := "lib"
- if ctx.toolchain().Is64Bit() && arch != "arm64" {
- libDir = "lib64"
- }
+// Returns the install path for unversioned NDK libraries (currently only static
+// libraries).
+func getUnversionedLibraryInstallPath(ctx ModuleContext) android.InstallPath {
+ return getNdkSysrootBase(ctx).Join(ctx, "usr/lib", config.NDKTriple(ctx.toolchain()))
+}
- installDir := getNdkInstallBase(ctx).Join(ctx, fmt.Sprintf(
- "platforms/android-%s/arch-%s/usr/%s", stub.apiLevel, arch, libDir))
+// Returns the install path for versioned NDK libraries. These are most often
+// stubs, but the same paths are used for CRT objects.
+func getVersionedLibraryInstallPath(ctx ModuleContext, apiLevel android.ApiLevel) android.InstallPath {
+ return getUnversionedLibraryInstallPath(ctx).Join(ctx, apiLevel.String())
+}
+
+func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) {
+ installDir := getVersionedLibraryInstallPath(ctx, stub.apiLevel)
stub.installPath = ctx.InstallFile(installDir, path.Base(), path)
}
diff --git a/cc/testing.go b/cc/testing.go
index f78ea0f..ced0929 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -670,6 +670,12 @@
`),
)
+// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
+var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
+ ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+})
+
// TestConfig is the legacy way of creating a test Config for testing cc modules.
//
// See testCc for an explanation as to how to stop using this deprecated method.
diff --git a/java/base.go b/java/base.go
index 1bcff2e..9911323 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1923,7 +1923,7 @@
func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
switch name {
- case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ case android.SdkCore.JavaLibraryName(ctx.Config()), "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
"stub-annotations", "private-stub-annotations-jar",
"core-lambda-stubs", "core-generated-annotation-stubs":
return javaCore, true
diff --git a/java/config/config.go b/java/config/config.go
index 13670ee..b82a137 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -95,11 +95,13 @@
"-JXX:TieredStopAtLevel=1",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{
"-JXmx2048M",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index b9332dd..958f4ce 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -79,16 +79,25 @@
],
}
+// Defaults module to strip out android annotations
+java_defaults {
+ name: "system-modules-no-annotations",
+ sdk_version: "none",
+ system_modules: "none",
+ jarjar_rules: "jarjar-strip-annotations-rules.txt",
+}
+
// Same as core-current-stubs-for-system-modules, but android annotations are
// stripped.
java_library {
name: "core-current-stubs-for-system-modules-no-annotations",
visibility: ["//development/sdk"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
static_libs: [
"core-current-stubs-for-system-modules",
],
- sdk_version: "none",
- system_modules: "none",
dists: [
{
// Legacy dist location for the public file.
@@ -100,7 +109,6 @@
targets: dist_targets,
},
],
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code against core.current.stubs.
@@ -158,16 +166,16 @@
java_library {
name: "core-module-lib-stubs-for-system-modules-no-annotations",
visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
static_libs: [
"core-module-lib-stubs-for-system-modules",
],
- sdk_version: "none",
- system_modules: "none",
dist: {
dest: "system-modules/module-lib/core-for-system-modules-no-annotations.jar",
targets: dist_targets,
},
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code with sdk_version "module_current"
@@ -212,16 +220,16 @@
java_library {
name: "legacy.core.platform.api.no.annotations.stubs",
visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
hostdex: true,
compile_dex: true,
- sdk_version: "none",
- system_modules: "none",
static_libs: [
"legacy.core.platform.api.stubs",
],
patch_module: "java.base",
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
java_library {
@@ -247,16 +255,16 @@
java_library {
name: "stable.core.platform.api.no.annotations.stubs",
visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
hostdex: true,
compile_dex: true,
- sdk_version: "none",
- system_modules: "none",
static_libs: [
"stable.core.platform.api.stubs",
],
patch_module: "java.base",
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code against *.core.platform.api.stubs.
@@ -307,12 +315,6 @@
// the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi
// annotations.
"art.module.api.annotations.for.system.modules",
-
- // Make nullability annotations available when compiling public stubs.
- // They are provided as a separate library because while the
- // annotations are not themselves part of the public API provided by
- // this module they are used in the stubs.
- "stub-annotations",
],
}
@@ -349,3 +351,7 @@
"art-module-intra-core-api-stubs-system-modules-lib",
],
}
+
+build = [
+ "TxtStubLibraries.bp",
+]
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
new file mode 100644
index 0000000..813187e
--- /dev/null
+++ b/java/core-libraries/TxtStubLibraries.bp
@@ -0,0 +1,156 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file contains java_system_modules provided by the SDK.
+// These system modules transitively depend on core stub libraries generated from .txt files.
+
+// Same as core-public-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "core-public-stubs-system-modules.from-text",
+ visibility: ["//visibility:public"],
+ libs: [
+ "core-current-stubs-for-system-modules-no-annotations.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core-current-stubs-for-system-modules-no-annotations.from-text",
+ visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ static_libs: [
+ "core.current.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as core-module-lib-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "core-module-lib-stubs-system-modules.from-text",
+ visibility: ["//visibility:public"],
+ libs: [
+ "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
+ visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ static_libs: [
+ "core.module_lib.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core.module_lib.stubs.from-text",
+ static_libs: [
+ "art.module.public.api.stubs.module_lib.from-text",
+
+ // Replace the following with the module-lib correspondence when Conscrypt or i18N module
+ // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
+ // @SystemApi(MODULE_LIBRARIES).
+ "conscrypt.module.public.api.stubs.from-text",
+ "i18n.module.public.api.stubs.from-text",
+ ],
+ sdk_version: "none",
+ system_modules: "none",
+ visibility: ["//visibility:private"],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as legacy-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "legacy-core-platform-api-stubs-system-modules.from-text",
+ visibility: core_platform_visibility,
+ libs: [
+ "legacy.core.platform.api.no.annotations.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "legacy.core.platform.api.no.annotations.stubs.from-text",
+ visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ hostdex: true,
+ compile_dex: true,
+
+ static_libs: [
+ "legacy.core.platform.api.stubs.from-text",
+ ],
+ patch_module: "java.base",
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as stable-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "stable-core-platform-api-stubs-system-modules.from-text",
+ visibility: core_platform_visibility,
+ libs: [
+ "stable.core.platform.api.no.annotations.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "stable.core.platform.api.no.annotations.stubs.from-text",
+ visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ hostdex: true,
+ compile_dex: true,
+
+ static_libs: [
+ "stable.core.platform.api.stubs.from-text",
+ ],
+ patch_module: "java.base",
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_api_library {
+ name: "core-lambda-stubs.from-text",
+ api_surface: "toolchain",
+ api_contributions: [
+ "art.module.toolchain.api.api.contribution",
+ ],
+ libs: [
+ // LambdaMetaFactory depends on CallSite etc. which is part of the Core API surface
+ "core.current.stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 4abdcc6..656c866 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -19,12 +19,14 @@
"io"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/dexpreopt"
)
type DeviceHostConverter struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.BazelModuleBase
properties DeviceHostConverterProperties
@@ -76,6 +78,7 @@
module.AddProperties(&module.properties)
InitJavaModule(module, android.DeviceSupported)
+ android.InitBazelModule(module)
return module
}
@@ -186,3 +189,30 @@
},
}
}
+
+type bazelDeviceHostConverterAttributes struct {
+ Deps bazel.LabelListAttribute
+}
+
+func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "java_host_for_device",
+ Bzl_load_location: "//build/bazel/rules/java:host_for_device.bzl",
+ },
+ android.CommonAttributes{Name: d.Name()},
+ &bazelDeviceHostConverterAttributes{
+ Deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
+ },
+ )
+ neverlinkProp := true
+ neverLinkAttrs := &javaLibraryAttributes{
+ Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + d.Name()}),
+ Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+ }
+ ctx.CreateBazelTargetModule(
+ javaLibraryBazelTargetModuleProperties(),
+ android.CommonAttributes{Name: d.Name() + "-neverlink"},
+ neverLinkAttrs)
+
+}
diff --git a/java/java.go b/java/java.go
index 499a6b6..d400b0c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -388,6 +388,8 @@
jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
+ javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+ depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
@@ -1609,6 +1611,13 @@
})
}
+type JavaApiLibraryDepsInfo struct {
+ JavaInfo
+ StubsSrcJar android.Path
+}
+
+var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{})
+
type ApiLibrary struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -1618,8 +1627,10 @@
properties JavaApiLibraryProperties
- stubsSrcJar android.WritablePath
- stubsJar android.WritablePath
+ stubsSrcJar android.WritablePath
+ stubsJar android.WritablePath
+ stubsJarWithoutStaticLibs android.WritablePath
+ extractedSrcJar android.WritablePath
// .dex of stubs, used for hiddenapi processing
dexJarFile OptionalDexJarPath
}
@@ -1645,8 +1656,13 @@
Libs []string
// List of java libs that this module has static dependencies to and will be
- // passed in metalava invocation
+ // merge zipped after metalava invocation
Static_libs []string
+
+ // Java Api library to provide the full API surface text files and jar file.
+ // If this property is set, the provided full API surface text files and
+ // jar file are passed to metalava invocation.
+ Dep_api_srcs *string
}
func ApiLibraryFactory() android.Module {
@@ -1725,7 +1741,36 @@
}
}
-var javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+// This method extracts the stub java files from the srcjar file provided from dep_api_srcs module
+// and replaces the java stubs generated by invoking metalava in this module.
+// This method is used because metalava can generate compilable from-text stubs only when
+// the codebase encompasses all classes listed in the input API text file, but a class can extend
+// a class that is not within the same API domain.
+func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, depApiSrcsSrcJar android.Path) {
+ generatedStubsList := android.PathForModuleOut(ctx, "metalava", "sources.txt")
+ unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
+
+ rule.Command().
+ BuiltTool("list_files").
+ Text(stubsDir.String()).
+ FlagWithOutput("--out ", generatedStubsList).
+ FlagWithArg("--extensions ", ".java").
+ FlagWithArg("--root ", unzippedSrcJarDir.String())
+
+ rule.Command().
+ Text("unzip").
+ Flag("-q").
+ Input(depApiSrcsSrcJar).
+ FlagWithArg("-d ", unzippedSrcJarDir.String())
+
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-srcjar").
+ Flag("-write_if_changed").
+ FlagWithArg("-C ", unzippedSrcJarDir.String()).
+ FlagWithInput("-l ", generatedStubsList).
+ FlagWithOutput("-o ", al.stubsSrcJar)
+}
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
@@ -1734,6 +1779,9 @@
}
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
+ if al.properties.Dep_api_srcs != nil {
+ ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Dep_api_srcs))
+ }
}
func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1754,6 +1802,7 @@
var srcFiles android.Paths
var classPaths android.Paths
var staticLibs android.Paths
+ var depApiSrcsStubsSrcJar android.Path
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
@@ -1770,6 +1819,10 @@
case staticLibTag:
provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
staticLibs = append(staticLibs, provider.HeaderJars...)
+ case depApiSrcsTag:
+ provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo)
+ classPaths = append(classPaths, provider.HeaderJars...)
+ depApiSrcsStubsSrcJar = provider.StubsSrcJar
}
})
@@ -1780,21 +1833,31 @@
srcFiles = append(srcFiles, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), api))
}
+ if srcFiles == nil {
+ ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
+ }
+
cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
al.stubsFlags(ctx, cmd, stubsDir)
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", al.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+
+ if depApiSrcsStubsSrcJar != nil {
+ al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsSrcJar)
+ } else {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", al.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+ }
rule.Build("metalava", "metalava merged")
- compiledStubs := android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
+
+ al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
var flags javaBuilderFlags
@@ -1802,14 +1865,14 @@
flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
flags.classpath = classpath(classPaths)
- TransformJavaToClasses(ctx, compiledStubs, 0, android.Paths{},
+ TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
android.Paths{al.stubsSrcJar}, flags, android.Paths{})
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().
BuiltTool("merge_zips").
Output(al.stubsJar).
- Inputs(android.Paths{compiledStubs}).
+ Inputs(android.Paths{al.stubsJarWithoutStaticLibs}).
Inputs(staticLibs)
builder.Build("merge_zips", "merge jar files")
@@ -1835,6 +1898,13 @@
ImplementationJars: android.PathsIfNonNil(al.stubsJar),
AidlIncludeDirs: android.Paths{},
})
+
+ ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
+ JavaInfo: JavaInfo{
+ HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ },
+ StubsSrcJar: al.stubsSrcJar,
+ })
}
func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
@@ -2772,7 +2842,7 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
android.CommonAttributes{Name: aidlLibName},
&aidlLibraryAttributes{
@@ -2787,7 +2857,7 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "java_aidl_library",
- Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl",
+ Bzl_load_location: "//build/bazel/rules/java:java_aidl_library.bzl",
},
android.CommonAttributes{Name: javaAidlLibName},
&javaAidlLibraryAttributes{
@@ -2837,10 +2907,6 @@
}
}
- if m.properties.Static_libs != nil {
- staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs))))
- }
-
protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
// Soong does not differentiate between a java_library and the Bazel equivalent of
// a java_proto_library + proto_library pair. Instead, in Soong proto sources are
@@ -2852,7 +2918,18 @@
depLabels := &javaDependencyLabels{}
depLabels.Deps = deps
- depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
+
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*CommonProperties); ok {
+ archStaticLibs := android.BazelLabelForModuleDeps(
+ ctx,
+ android.LastUniqueStrings(android.CopyOf(archProps.Static_libs)))
+ depLabels.StaticDeps.SetSelectValue(axis, config, archStaticLibs)
+ }
+ }
+ }
+ depLabels.StaticDeps.Value.Append(staticDeps)
hasKotlin := !kotlinSrcs.IsEmpty()
commonAttrs.kotlinAttributes = &kotlinAttributes{
diff --git a/java/java_test.go b/java/java_test.go
index 68b749b..553b762 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2209,6 +2209,50 @@
}
}
+func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
+ provider_bp_a := `
+ java_api_contribution {
+ name: "foo1",
+ api_file: "foo1.txt",
+ }
+ `
+ provider_bp_b := `
+ java_api_contribution {
+ name: "foo2",
+ api_file: "foo2.txt",
+ }
+ `
+ lib_bp_a := `
+ java_api_library {
+ name: "lib1",
+ api_surface: "public",
+ api_contributions: ["foo1", "foo2"],
+ }
+ `
+
+ ctx, _ := testJavaWithFS(t, `
+ java_api_library {
+ name: "bar1",
+ api_surface: "public",
+ api_contributions: ["foo1"],
+ dep_api_srcs: "lib1",
+ }
+ `,
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ })
+
+ m := ctx.ModuleForTests("bar1", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+
+ android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
+ android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
+}
+
func TestTradefedOptions(t *testing.T) {
result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
java_test_host {
diff --git a/java/sdk.go b/java/sdk.go
index 72a5006..8b4918a 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -148,10 +148,11 @@
toModule := func(module string, aidl android.Path) sdkDep {
// Select the kind of system modules needed for the sdk version.
systemModulesKind := systemModuleKind(sdkVersion.Kind, android.FutureApiLevel)
+ systemModules := android.JavaApiLibraryName(ctx.Config(), fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind))
return sdkDep{
useModule: true,
- bootclasspath: []string{module, config.DefaultLambdaStubsLibrary},
- systemModules: fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind),
+ bootclasspath: []string{module, android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+ systemModules: systemModules,
java9Classpath: []string{module},
frameworkResModule: "framework-res",
aidl: android.OptionalPathForPath(aidl),
@@ -196,8 +197,8 @@
case android.SdkCore:
return sdkDep{
useModule: true,
- bootclasspath: []string{"core.current.stubs", config.DefaultLambdaStubsLibrary},
- systemModules: "core-public-stubs-system-modules",
+ bootclasspath: []string{android.SdkCore.JavaLibraryName(ctx.Config()), android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+ systemModules: android.JavaApiLibraryName(ctx.Config(), "core-public-stubs-system-modules"),
noFrameworksLibs: true,
}
case android.SdkModule:
diff --git a/java/testing.go b/java/testing.go
index 63d7dba..0764d26 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -368,6 +368,7 @@
"core.current.stubs",
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
+
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -387,6 +388,27 @@
`, extra)
}
+ extraApiLibraryModules := map[string]string{
+ "android_stubs_current.from-text": "api/current.txt",
+ "android_system_stubs_current.from-text": "api/system-current.txt",
+ "android_test_stubs_current.from-text": "api/test-current.txt",
+ "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt",
+ "android_system_server_stubs_current.from-text": "api/system-server-current.txt",
+ "core.current.stubs.from-text": "api/current.txt",
+ "legacy.core.platform.api.stubs.from-text": "api/current.txt",
+ "stable.core.platform.api.stubs.from-text": "api/current.txt",
+ "core-lambda-stubs.from-text": "api/current.txt",
+ }
+
+ for libName, apiFile := range extraApiLibraryModules {
+ bp += fmt.Sprintf(`
+ java_api_library {
+ name: "%s",
+ api_files: ["%s"],
+ }
+ `, libName, apiFile)
+ }
+
bp += `
java_library {
name: "framework",
@@ -409,6 +431,10 @@
"core-module-lib-stubs-system-modules",
"legacy-core-platform-api-stubs-system-modules",
"stable-core-platform-api-stubs-system-modules",
+ "core-public-stubs-system-modules.from-text",
+ "core-module-lib-stubs-system-modules.from-text",
+ "legacy-core-platform-api-stubs-system-modules.from-text",
+ "stable-core-platform-api-stubs-system-modules.from-text",
}
for _, extra := range systemModules {
diff --git a/rust/afdo.go b/rust/afdo.go
index 996fd7e..3534ee6 100644
--- a/rust/afdo.go
+++ b/rust/afdo.go
@@ -17,7 +17,10 @@
import (
"fmt"
+ "android/soong/android"
"android/soong/cc"
+
+ "github.com/google/blueprint"
)
const afdoFlagFormat = "-Zprofile-sample-use=%s"
@@ -30,19 +33,49 @@
return []interface{}{&afdo.Properties}
}
-func (afdo *afdo) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
+func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
+ // afdo is not supported outside of Android
+ if ctx.Host() {
+ return
+ }
+
+ if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
+ fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName())
+ if err != nil {
+ ctx.ModuleErrorf("%s", err.Error())
+ }
+ if fdoProfileName != nil {
+ actx.AddFarVariationDependencies(
+ []blueprint.Variation{
+ {Mutator: "arch", Variation: actx.Target().ArchVariation()},
+ {Mutator: "os", Variation: "android"},
+ },
+ cc.FdoProfileTag,
+ []string{*fdoProfileName}...,
+ )
+ }
+ }
+}
+
+func (afdo *afdo) flags(ctx android.ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
if ctx.Host() {
return flags, deps
}
- if afdo != nil && afdo.Properties.Afdo {
- if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, ctx.ModuleName()); profileFile.Valid() {
- profileUseFlag := fmt.Sprintf(afdoFlagFormat, profileFile)
+ if !afdo.Properties.Afdo {
+ return flags, deps
+ }
+
+ ctx.VisitDirectDepsWithTag(cc.FdoProfileTag, func(m android.Module) {
+ if ctx.OtherModuleHasProvider(m, cc.FdoProfileProvider) {
+ info := ctx.OtherModuleProvider(m, cc.FdoProfileProvider).(cc.FdoProfileInfo)
+ path := info.Path
+ profileUseFlag := fmt.Sprintf(afdoFlagFormat, path.String())
flags.RustFlags = append(flags.RustFlags, profileUseFlag)
- profileFilePath := profileFile.Path()
- deps.AfdoProfiles = append(deps.AfdoProfiles, profileFilePath)
+ deps.AfdoProfiles = append(deps.AfdoProfiles, path)
}
- }
+ })
+
return flags, deps
}
diff --git a/rust/afdo_test.go b/rust/afdo_test.go
index fa20eef..0cdf704 100644
--- a/rust/afdo_test.go
+++ b/rust/afdo_test.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/cc"
"fmt"
"strings"
"testing"
@@ -31,13 +32,27 @@
`
result := android.GroupFixturePreparers(
prepareForRustTest,
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo.afdo", ""),
+ cc.PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/foo.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "foo_afdo",
+ profile: "foo.afdo",
+ }
+ `),
+ }.AddToFixture(),
rustMockedFiles.AddToFixture(),
).RunTestWithBp(t, bp)
foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
- expectedCFlag := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo.afdo")
+ expectedCFlag := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo.afdo")
if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
@@ -55,16 +70,37 @@
`
result := android.GroupFixturePreparers(
prepareForRustTest,
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", ""),
- android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", ""),
+ cc.PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "foo_afdo",
+ arch: {
+ arm: {
+ profile: "foo_arm.afdo",
+ },
+ arm64: {
+ profile: "foo_arm64.afdo",
+ }
+ }
+ }
+ `),
+ }.AddToFixture(),
rustMockedFiles.AddToFixture(),
).RunTestWithBp(t, bp)
fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
- expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm.afdo")
- expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm64.afdo")
+ expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm.afdo")
+ expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm64.afdo")
if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
diff --git a/rust/builder.go b/rust/builder.go
index b89e7ad..0aef13d 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -208,6 +208,9 @@
outDirPrefix = ""
}
envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
+ } else {
+ // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
+ envVars = append(envVars, "OUT_DIR=out")
}
return envVars
diff --git a/rust/rust.go b/rust/rust.go
index f85babc..56b4631 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -39,7 +39,6 @@
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
-
})
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
@@ -920,7 +919,7 @@
// Calculate rustc flags
if mod.afdo != nil {
- flags, deps = mod.afdo.flags(ctx, flags, deps)
+ flags, deps = mod.afdo.flags(actx, flags, deps)
}
if mod.compiler != nil {
flags = mod.compiler.compilerFlags(ctx, flags)
@@ -1516,7 +1515,7 @@
for _, lib := range deps.Rustlibs {
if autoDep.depTag == rlibDepTag {
// Handle the rlib deptag case
- addRlibDependency(actx, lib, mod, snapshotInfo, rlibDepVariations)
+ addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
} else {
// autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
// Check for the existence of the dylib deptag variant. Select it if available,
@@ -1527,7 +1526,7 @@
actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
} else {
// If there's no dylib dependency available, try to add the rlib dependency instead.
- addRlibDependency(actx, lib, mod, snapshotInfo, rlibDepVariations)
+ addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
}
}
}
@@ -1613,11 +1612,13 @@
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
+
+ mod.afdo.addDep(ctx, actx)
}
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
-func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo *cc.SnapshotInfo, variations []blueprint.Variation) {
- lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
+func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation) {
+ lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Rlibs)
actx.AddVariationDependencies(variations, rlibDepTag, lib)
}
diff --git a/tests/lib.sh b/tests/lib.sh
index 26608b8..715eac1 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -94,9 +94,11 @@
symlink_directory external/compiler-rt
symlink_directory external/go-cmp
symlink_directory external/golang-protobuf
+ symlink_directory external/licenseclassifier
symlink_directory external/starlark-go
symlink_directory external/python
symlink_directory external/sqlite
+ symlink_directory external/spdx-tools
touch "$MOCK_TOP/Android.bp"
}
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 6066d70..2f154cd 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -37,9 +37,14 @@
out_dir=out
droid_target=
fi
+
+function run_soong {
+ TARGET_PRODUCT="aosp_cf_x86_64_phone" TARGET_BUILD_VARIANT=userdebug OUT_DIR=$out_dir \
+ build/soong/soong_ui.bash --make-mode "$@"
+}
+
# m droid, build sbom later in case additional dependencies might be built and included in partition images.
-TARGET_PRODUCT="aosp_cf_x86_64_phone" TARGET_BUILD_VARIANT=userdebug OUT_DIR=$out_dir \
- build/soong/soong_ui.bash --make-mode $droid_target dump.erofs
+run_soong $droid_target dump.erofs lz4
product_out=$out_dir/target/product/vsoc_x86_64
sbom_test=$product_out/sbom_test
@@ -47,11 +52,11 @@
cp $product_out/*.img $sbom_test
# m sbom
-TARGET_PRODUCT="aosp_cf_x86_64_phone" TARGET_BUILD_VARIANT=userdebug OUT_DIR=$out_dir \
- build/soong/soong_ui.bash --make-mode sbom
+run_soong sbom
# Generate installed file list from .img files in PRODUCT_OUT
dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
+lz4=$out_dir/host/linux-x86/bin/lz4
declare -A diff_excludes
diff_excludes[odm]="-I /odm/lib/modules"
@@ -60,24 +65,12 @@
-I /vendor/lib/modules \
-I /vendor/odm"
diff_excludes[system]=\
-"-I /acct/ \
- -I /adb_keys \
- -I /apex/ \
- -I /bin \
+"-I /bin \
-I /bugreports \
-I /cache \
- -I /config/ \
-I /d \
- -I /data/ \
- -I /data_mirror/ \
- -I /debug_ramdisk/ \
- -I /dev/ \
-I /etc \
-I /init \
- -I /init.environ.rc \
- -I /linkerconfig/ \
- -I /metadata/ \
- -I /mnt/ \
-I /odm/app \
-I /odm/bin \
-I /odm_dlkm/etc \
@@ -89,16 +82,7 @@
-I /odm/overlay \
-I /odm/priv-app \
-I /odm/usr \
- -I /oem/ \
- -I /postinstall/ \
- -I /proc/ \
- -I /product/ \
-I /sdcard \
- -I /second_stage_resources/ \
- -I /storage/ \
- -I /sys/ \
- -I /system_dlkm/ \
- -I /system_ext/ \
-I /system/lib64/android.hardware.confirmationui@1.0.so \
-I /system/lib64/android.hardware.confirmationui-V1-ndk.so \
-I /system/lib64/android.hardware.keymaster@4.1.so \
@@ -114,22 +98,32 @@
-I /system/lib64/libkm_compat.so \
-I /system/lib64/vndk-29 \
-I /system/lib64/vndk-sp-29 \
- -I /system/lib/modules \
-I /system/lib/vndk-29 \
-I /system/lib/vndk-sp-29 \
- -I /system/product \
- -I /system/system_ext \
-I /system/usr/icu \
- -I /system/vendor \
- -I /vendor/ \
-I /vendor_dlkm/etc"
+function diff_files {
+ file_list_file="$1"; shift
+ files_in_spdx_file="$1"; shift
+ partition_name="$1"; shift
+ exclude=
+ if [ -v 'diff_excludes[$partition_name]' ]; then
+ exclude=${diff_excludes[$partition_name]}
+ fi
+
+ diff "$file_list_file" "$files_in_spdx_file" $exclude
+ if [ $? != "0" ]; then
+ echo Found diffs in $f and SBOM.
+ exit 1
+ else
+ echo No diffs.
+ fi
+ }
+
# Example output of dump.erofs is as below, and the data used in the test start
# at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
-# Each line is captured in variable "entry", sed is used to trim the leading
-# spaces and cut is used to get field 1 every time. Once a field is extracted,
-# "cut --complement" is used to remove the extracted field so next field can be
-# processed in the same way and to be processed field is always field 1.
+# Each line is captured in variable "entry", awk is used to get type and name.
# Output of dump.erofs:
# File : /
# Size: 160 On-disk size: 160 directory
@@ -170,16 +164,13 @@
all_dirs=$(echo "$all_dirs" | cut -d ' ' -f1 --complement -s)
entries=$($dump_erofs --ls --path "$dir" $f | tail -n +11)
while read -r entry; do
- nid=$(echo $entry | sed 's/^\s*//' | cut -d ' ' -f1)
- entry=$(echo $entry | sed 's/^\s*//' | cut -d ' ' -f1 --complement)
- type=$(echo $entry | sed 's/^\s*//' | cut -d ' ' -f1)
- entry=$(echo $entry | sed 's/^\s*//' | cut -d ' ' -f1 --complement)
- name=$(echo $entry | sed 's/^\s*//' | cut -d ' ' -f1)
- case $type in
+ inode_type=$(echo $entry | awk -F ' ' '{print $2}')
+ name=$(echo $entry | awk -F ' ' '{print $3}')
+ case $inode_type in
"2") # directory
all_dirs=$(echo "$all_dirs $dir/$name" | sed 's/^\s*//')
;;
- *)
+ "1"|"7") # 1: file, 7: symlink
(
if [ "$partition_name" != "system" ]; then
# system partition is mounted to /, not to prepend partition name.
@@ -193,18 +184,31 @@
done
sort -n -o "$file_list_file" "$file_list_file"
- # Diff
+ grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' > "$files_in_spdx_file"
+ if [ "$partition_name" = "system" ]; then
+ # system partition is mounted to /, so include FileName starts with /root/ too.
+ grep "FileName: /root/" $product_out/sbom.spdx | sed 's/^FileName: \/root//' >> "$files_in_spdx_file"
+ fi
+ sort -n -o "$files_in_spdx_file" "$files_in_spdx_file"
+
echo ============ Diffing files in $f and SBOM
+ diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
+done
+
+RAMDISK_IMAGES="$product_out/ramdisk.img"
+for f in $RAMDISK_IMAGES; do
+ partition_name=$(basename $f | cut -d. -f1)
+ file_list_file="${sbom_test}/sbom-${partition_name}-files.txt"
+ files_in_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-spdx.txt"
+ # lz4 decompress $f to stdout
+ # cpio list all entries like ls -l
+ # grep filter normal files and symlinks
+ # awk get entry names
+ # sed remove partition name from entry names
+ $lz4 -c -d $f | cpio -tv 2>/dev/null | grep '^[-l]' | awk -F ' ' '{print $9}' | sed "s:^:/$partition_name/:" | sort -n > "$file_list_file"
+
grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' | sort -n > "$files_in_spdx_file"
- exclude=
- if [ -v 'diff_excludes[$partition_name]' ]; then
- exclude=${diff_excludes[$partition_name]}
- fi
- diff "$file_list_file" "$files_in_spdx_file" $exclude
- if [ $? != "0" ]; then
- echo Found diffs in $f and SBOM.
- exit 1
- else
- echo No diffs.
- fi
+
+ echo ============ Diffing files in $f and SBOM
+ diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
done
\ No newline at end of file