Merge "Bp2build support for sdk_version and java_version."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 9d28592..d7e598b 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -365,6 +365,8 @@
"system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively,
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/testdata": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/testing": Bp2BuildDefaultTrueRecursively,
"system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue,
"system/tools/aidl/metadata": Bp2BuildDefaultTrue,
"system/tools/hidl/metadata": Bp2BuildDefaultTrue,
@@ -471,6 +473,7 @@
"libgralloctypes",
"libnativewindow",
"libneuralnetworks",
+ "libneuralnetworks_static",
"libgraphicsenv",
"libhardware",
"libhardware_headers",
@@ -1480,6 +1483,7 @@
// M5: tzdata launch
"com.android.tzdata",
"test1_com.android.tzdata",
+ "test3_com.android.tzdata",
// M7: adbd launch
"com.android.adbd",
"test_com.android.adbd",
@@ -1499,6 +1503,8 @@
// also be built - do not add them to this list.
StagingMixedBuildsEnabledList = []string{
"com.android.neuralnetworks",
+ "libneuralnetworks",
+ "libneuralnetworks_static",
}
// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 44dc055..5c429e2 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -960,9 +960,13 @@
// request type.
func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
+ requestTypes := []cqueryRequest{}
for _, val := range context.requests {
cqueryId := getCqueryId(val)
mapEntryString := fmt.Sprintf("%q : True", cqueryId)
+ if _, seenKey := requestTypeToCqueryIdEntries[val.requestType]; !seenKey {
+ requestTypes = append(requestTypes, val.requestType)
+ }
requestTypeToCqueryIdEntries[val.requestType] =
append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
}
@@ -984,7 +988,7 @@
return id_string + ">>" + %s(target, id_string)
`
- for requestType := range requestTypeToCqueryIdEntries {
+ for _, requestType := range requestTypes {
labelMapName := requestType.Name() + "_Labels"
functionName := requestType.Name() + "_Fn"
labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
diff --git a/android/config.go b/android/config.go
index 6765f1f..2904581 100644
--- a/android/config.go
+++ b/android/config.go
@@ -420,6 +420,8 @@
fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
"\n", `
product_vars = _product_vars
+
+# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
product_var_constraints = _product_var_constraints
arch_variant_product_var_constraints = _arch_variant_product_var_constraints
`,
@@ -429,6 +431,13 @@
if err != nil {
return fmt.Errorf("Could not write .bzl config file %s", err)
}
+ err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
+product_var_constraints = %s
+arch_variant_product_var_constraints = %s
+`, nonArchVariantProductVariablesJson, archVariantProductVariablesJson)), 0644)
+ if err != nil {
+ return fmt.Errorf("Could not write .bzl config file %s", err)
+ }
err = pathtools.WriteFileIfChanged(filepath.Join(dir, "BUILD"),
[]byte(bazel.GeneratedBazelFileWarning), 0644)
if err != nil {
@@ -824,6 +833,10 @@
return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
}
+func (c *config) RawPlatformSdkVersion() *int {
+ return c.productVariables.Platform_sdk_version
+}
+
func (c *config) PlatformSdkFinal() bool {
return Bool(c.productVariables.Platform_sdk_final)
}
diff --git a/android/module.go b/android/module.go
index 76fe8dc..ba47453 100644
--- a/android/module.go
+++ b/android/module.go
@@ -550,6 +550,7 @@
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
+ EffectiveLicenseKinds() []string
EffectiveLicenseFiles() Paths
AddProperties(props ...interface{})
@@ -2024,6 +2025,10 @@
return m.commonProperties.NamespaceExportedToMake
}
+func (m *ModuleBase) EffectiveLicenseKinds() []string {
+ return m.commonProperties.Effective_license_kinds
+}
+
func (m *ModuleBase) EffectiveLicenseFiles() Paths {
result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
for _, p := range m.commonProperties.Effective_license_text {
diff --git a/android/namespace.go b/android/namespace.go
index c47a1c5..ebf85a1 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -325,8 +325,8 @@
namespace.id = strconv.Itoa(id)
}
-func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string) (err error) {
- text := fmt.Sprintf("%q depends on undefined module %q", depender, depName)
+func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string, guess []string) (err error) {
+ text := fmt.Sprintf("%q depends on undefined module %q.", depender, depName)
_, _, isAbs := r.parseFullyQualifiedName(depName)
if isAbs {
@@ -345,9 +345,10 @@
}
_, skipped := namespace.moduleContainer.SkippedModuleFromName(depName, nil)
if skipped {
- skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName))
+ skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName, nil))
}
}
+
if len(foundInNamespaces) > 0 {
// determine which namespaces are visible to dependerNamespace
dependerNs := dependerNamespace.(*Namespace)
@@ -363,6 +364,10 @@
text += fmt.Sprintf("\n%s", err.Error())
}
+ if len(guess) > 0 {
+ text += fmt.Sprintf("\nOr did you mean %q?", guess)
+ }
+
return fmt.Errorf(text)
}
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 7a387a0..ea51c6e 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -174,9 +174,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a".
Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."]
-Module "a" can be found in these namespaces: ["dir1" "dir2"]\E`)).
+Module "a" can be found in these namespaces: ["dir1" "dir2"]\E
+Or did you mean ["soong_namespace"]?`)).
RunTest(t)
}
@@ -421,9 +422,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a".
Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["soong_namespace"]?`)).
RunTest(t)
}
@@ -481,9 +483,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a".
Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["b"]?`)).
RunTest(t)
}
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/visibility.go b/android/visibility.go
index 5955133..3130135 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -47,7 +47,6 @@
// the dependency. If it cannot then an error is reported.
//
// TODO(b/130631145) - Make visibility work properly with prebuilts.
-// TODO(b/130796911) - Make visibility work properly with defaults.
// Patterns for the values that can be specified in visibility property.
const (
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 05c888a..8a02a4a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7101,7 +7101,7 @@
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
updatable: true,
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
apex_key {
@@ -7124,7 +7124,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
cc_library {
@@ -7137,7 +7137,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
cc_library {
@@ -7151,7 +7151,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
java_library {
@@ -7165,7 +7165,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
java_library {
@@ -7178,7 +7178,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
`
diff --git a/apex/builder.go b/apex/builder.go
index e3b6f8e..94aef49 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -71,6 +71,9 @@
pctx.HostBinToolVariable("make_erofs", "make_erofs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
pctx.HostBinToolVariable("dexdeps", "dexdeps")
+ pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
+ pctx.HostBinToolVariable("deapexer", "deapexer")
+ pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
}
@@ -226,7 +229,12 @@
Description: "Generate symbol list used by Apex",
}, "image_dir", "readelf")
- // Don't add more rules here. Consider using android.NewRuleBuilder instead.
+ apexSepolicyTestsRule = pctx.StaticRule("apexSepolicyTestsRule", blueprint.RuleParams{
+ Command: `${deapexer} --debugfs_path ${debugfs_static} list -Z ${in} > ${out}.fc` +
+ `&& ${apex_sepolicy_tests} -f ${out}.fc && touch ${out}`,
+ CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
+ Description: "run apex_sepolicy_tests",
+ })
)
// buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -872,6 +880,10 @@
args["implicits"] = strings.Join(implicits.Strings(), ",")
args["outCommaList"] = signedOutputFile.String()
}
+ var validations android.Paths
+ if suffix == imageApexSuffix {
+ validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "signapk",
@@ -879,6 +891,7 @@
Input: unsignedOutputFile,
Implicits: implicits,
Args: args,
+ Validations: validations,
})
if suffix == imageApexSuffix {
a.outputApexFile = signedOutputFile
@@ -1172,3 +1185,17 @@
return cannedFsConfig.OutputPath
}
+
+// Runs apex_sepolicy_tests
+//
+// $ deapexer list -Z {apex_file} > {file_contexts}
+// $ apex_sepolicy_tests -f {file_contexts}
+func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "sepolicy_tests.timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexSepolicyTestsRule,
+ Input: apexFile,
+ Output: timestamp,
+ })
+ return timestamp
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6a39e25..608fcd8 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,8 +1,11 @@
package bp2build
import (
+ "android/soong/starlark_fmt"
"encoding/json"
+ "fmt"
"reflect"
+ "strconv"
"strings"
"android/soong/android"
@@ -48,7 +51,9 @@
if err != nil {
panic(err)
}
+ files = append(files, newFile("metrics", GeneratedBuildFileName, "")) // Creates a //metrics package.
files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
+ files = append(files, newFile("metrics", "converted_modules_path_map.bzl", "modules = "+strings.ReplaceAll(string(convertedModulePathMap), "\\", "\\\\")))
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
@@ -62,6 +67,7 @@
// TODO(b/269691302) value of apiLevelsContent is product variable dependent and should be avoided for soong injection
files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
+ files = append(files, newFile("api_levels", "platform_versions.bzl", platformVersionContents(cfg)))
files = append(files, newFile("allowlists", GeneratedBuildFileName, ""))
files = append(files, newFile("allowlists", "env.bzl", android.EnvironmentVarsFile(cfg)))
@@ -72,6 +78,31 @@
return files, nil
}
+func platformVersionContents(cfg android.Config) string {
+ // Despite these coming from cfg.productVariables, they are actually hardcoded in global
+ // makefiles, not set in individual product config makesfiles, so they're safe to just export
+ // and load() directly.
+
+ platformVersionActiveCodenames := make([]string, 0, len(cfg.PlatformVersionActiveCodenames()))
+ for _, codename := range cfg.PlatformVersionActiveCodenames() {
+ platformVersionActiveCodenames = append(platformVersionActiveCodenames, fmt.Sprintf("%q", codename))
+ }
+
+ platformSdkVersion := "None"
+ if cfg.RawPlatformSdkVersion() != nil {
+ platformSdkVersion = strconv.Itoa(*cfg.RawPlatformSdkVersion())
+ }
+
+ return fmt.Sprintf(`
+platform_versions = struct(
+ platform_sdk_final = %s,
+ platform_sdk_version = %s,
+ platform_sdk_codename = %q,
+ platform_version_active_codenames = [%s],
+)
+`, starlark_fmt.PrintBool(cfg.PlatformSdkFinal()), platformSdkVersion, cfg.PlatformSdkCodename(), strings.Join(platformVersionActiveCodenames, ", "))
+}
+
func CreateBazelFiles(
cfg android.Config,
ruleShims map[string]RuleShim,
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 8c1d2ae..2f5dc3c 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -131,9 +131,17 @@
},
{
dir: "metrics",
+ basename: "BUILD.bazel",
+ },
+ {
+ dir: "metrics",
basename: "converted_modules_path_map.json",
},
{
+ dir: "metrics",
+ basename: "converted_modules_path_map.bzl",
+ },
+ {
dir: "product_config",
basename: "soong_config_variables.bzl",
},
@@ -154,6 +162,10 @@
basename: "api_levels.bzl",
},
{
+ dir: "api_levels",
+ basename: "platform_versions.bzl",
+ },
+ {
dir: "allowlists",
basename: GeneratedBuildFileName,
},
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/config/global.go b/cc/config/global.go
index 5b2191a..a2d5cf4 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -111,6 +111,9 @@
// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
"-ffp-contract=off",
+
+ // Turn off stack protector check for noreturn calls. (http://b/264965700)
+ "-mllvm -disable-check-noreturn-call",
}
commonGlobalConlyflags = []string{}
@@ -147,6 +150,9 @@
commonGlobalLldflags = []string{
"-fuse-ld=lld",
"-Wl,--icf=safe",
+
+ // Turn off stack protector check for noreturn calls. (http://b/264965700)
+ "-Wl,-mllvm,-disable-check-noreturn-call",
}
deviceGlobalCppflags = []string{
@@ -315,6 +321,9 @@
}
VersionScriptFlagPrefix = "-Wl,--version-script,"
+
+ VisibilityHiddenFlag = "-fvisibility=hidden"
+ VisibilityDefaultFlag = "-fvisibility=default"
)
// BazelCcToolchainVars generates bzl file content containing variables for
@@ -405,6 +414,9 @@
exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
+ exportedVars.ExportString("VisibilityHiddenFlag", VisibilityHiddenFlag)
+ exportedVars.ExportString("VisibilityDefaultFlag", VisibilityDefaultFlag)
+
// Everything in these lists is a crime against abstraction and dependency tracking.
// Do not add anything to this list.
commonGlobalIncludes := []string{
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/ndk_sysroot.go b/cc/ndk_sysroot.go
index 622558e..dffc6c6 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -142,6 +142,13 @@
staticLibInstallPaths, library.ndkSysrootPath)
}
}
+
+ if object, ok := m.linker.(*objectLinker); ok {
+ if object.ndkSysrootPath != nil {
+ staticLibInstallPaths = append(
+ staticLibInstallPaths, object.ndkSysrootPath)
+ }
+ }
}
})
diff --git a/cc/object.go b/cc/object.go
index ef44467..d65cdea 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -44,6 +44,10 @@
type objectLinker struct {
*baseLinker
Properties ObjectLinkerProperties
+
+ // Location of the object in the sysroot. Empty if the object is not
+ // included in the NDK.
+ ndkSysrootPath android.Path
}
type objectBazelHandler struct {
@@ -99,6 +103,10 @@
// Indicates that this module is a CRT object. CRT objects will be split
// into a variant per-API level between min_sdk_version and current.
Crt *bool
+
+ // Indicates that this module should not be included in the NDK sysroot.
+ // Only applies to CRT objects. Defaults to false.
+ Exclude_from_ndk_sysroot *bool
}
func newObject(hod android.HostOrDeviceSupported) *Module {
@@ -268,17 +276,28 @@
objs = objs.Append(deps.Objs)
- var outputFile android.Path
+ var output android.WritablePath
builderFlags := flagsToBuilderFlags(flags)
outputName := ctx.ModuleName()
if !strings.HasSuffix(outputName, objectExtension) {
outputName += objectExtension
}
- if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
- output := android.PathForModuleOut(ctx, outputName)
- outputFile = output
+ // isForPlatform is terribly named and actually means isNotApex.
+ if Bool(object.Properties.Crt) &&
+ !Bool(object.Properties.Exclude_from_ndk_sysroot) && ctx.useSdk() &&
+ ctx.isSdkVariant() && ctx.isForPlatform() {
+ output = getVersionedLibraryInstallPath(ctx,
+ nativeApiLevelOrPanic(ctx, ctx.sdkVersion())).Join(ctx, outputName)
+ object.ndkSysrootPath = output
+ } else {
+ output = android.PathForModuleOut(ctx, outputName)
+ }
+
+ outputFile := output
+
+ if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
if String(object.Properties.Prefix_symbols) != "" {
transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
builderFlags, output)
@@ -290,9 +309,6 @@
})
}
} else {
- output := android.PathForModuleOut(ctx, outputName)
- outputFile = output
-
if String(object.Properties.Prefix_symbols) != "" {
input := android.PathForModuleOut(ctx, "unprefixed", outputName)
transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
diff --git a/cc/object_test.go b/cc/object_test.go
index 5359a35..b1e2a0f 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -65,7 +65,7 @@
variant := "android_arm64_armv8-a_sdk"
crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
- variant+"_29/crtbegin_dynamic.o")
+ "29/crtbegin_dynamic.o")
// platform variant uses the crt object built for platform
variant = "android_arm64_armv8-a"
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f19659c..4601ee6 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -64,12 +64,13 @@
cfiBlocklistPath = "external/compiler-rt/lib/cfi"
cfiBlocklistFilename = "cfi_blocklist.txt"
- cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
+ cfiCrossDsoFlag = "-fsanitize-cfi-cross-dso"
+ cfiCflags = []string{"-flto", cfiCrossDsoFlag,
"-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
// used, but have no effect on assembly files
cfiAsflags = []string{"-flto", "-fvisibility=default"}
- cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
+ cfiLdflags = []string{"-flto", cfiCrossDsoFlag, "-fsanitize=cfi",
"-Wl,-plugin-opt,O1"}
cfiExportsMapPath = "build/soong/cc/config"
cfiExportsMapFilename = "cfi_exports.map"
@@ -393,11 +394,13 @@
exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
// Leave out "-flto" from the slices exported to bazel, as we will use the
- // dedicated LTO feature for this
- exportedVars.ExportStringList("CfiCFlags", cfiCflags[1:])
+ // dedicated LTO feature for this. For C Flags and Linker Flags, also leave
+ // out the cross DSO flag which will be added separately by transitions.
+ exportedVars.ExportStringList("CfiCFlags", cfiCflags[2:])
+ exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
- exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[1:])
+ exportedVars.ExportString("CfiCrossDsoFlag", cfiCrossDsoFlag)
exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
@@ -613,6 +616,10 @@
if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
s.Scs = nil
}
+ // ...but temporarily globally disabled on riscv64 (http://b/277909695).
+ if ctx.Arch().ArchType == android.Riscv64 {
+ s.Scs = nil
+ }
// Memtag_heap is only implemented on AArch64.
// Memtag ABI is Android specific for now, so disable for host.
diff --git a/cc/vndk.go b/cc/vndk.go
index 3b7c87d..be66cd7 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -674,8 +674,12 @@
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
configsDir := filepath.Join(snapshotArchDir, "configs")
+ noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
includeDir := filepath.Join(snapshotArchDir, "include")
+ // set of notice files copied.
+ noticeBuilt := make(map[string]bool)
+
// paths of VNDK modules for GPL license checking
modulePaths := make(map[string]string)
@@ -700,28 +704,36 @@
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))
+ // json struct to export snapshot information
+ prop := struct {
+ LicenseKinds []string `json:",omitempty"`
+ LicenseTexts []string `json:",omitempty"`
+ ExportedDirs []string `json:",omitempty"`
+ ExportedSystemDirs []string `json:",omitempty"`
+ ExportedFlags []string `json:",omitempty"`
+ RelativeInstallPath string `json:",omitempty"`
+ }{}
+
+ prop.LicenseKinds = m.EffectiveLicenseKinds()
+ prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
+
if ctx.Config().VndkSnapshotBuildArtifacts() {
- prop := struct {
- ExportedDirs []string `json:",omitempty"`
- ExportedSystemDirs []string `json:",omitempty"`
- ExportedFlags []string `json:",omitempty"`
- RelativeInstallPath string `json:",omitempty"`
- }{}
exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
prop.ExportedFlags = exportedInfo.Flags
prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
prop.RelativeInstallPath = m.RelativeInstallPath()
-
- propOut := snapshotLibOut + ".json"
-
- j, err := json.Marshal(prop)
- if err != nil {
- ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
- return nil, false
- }
- ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
}
+
+ propOut := snapshotLibOut + ".json"
+
+ j, err := json.Marshal(prop)
+ if err != nil {
+ ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
+ return nil, false
+ }
+ ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
+
return ret, true
}
@@ -761,6 +773,14 @@
moduleNames[stem] = ctx.ModuleName(m)
modulePaths[stem] = ctx.ModuleDir(m)
+ for _, notice := range m.EffectiveLicenseFiles() {
+ if _, ok := noticeBuilt[notice.String()]; !ok {
+ noticeBuilt[notice.String()] = true
+ snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
+ pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
+ }
+ }
+
if ctx.Config().VndkSnapshotBuildArtifacts() {
headers = append(headers, m.SnapshotHeaders()...)
}
diff --git a/java/java.go b/java/java.go
index d235103..2de4ea9 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1612,7 +1612,7 @@
}
type JavaApiLibraryDepsInfo struct {
- StubsJar android.Path
+ JavaInfo
StubsSrcJar android.Path
}
@@ -1821,7 +1821,7 @@
staticLibs = append(staticLibs, provider.HeaderJars...)
case depApiSrcsTag:
provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo)
- classPaths = append(classPaths, provider.StubsJar)
+ classPaths = append(classPaths, provider.HeaderJars...)
depApiSrcsStubsSrcJar = provider.StubsSrcJar
}
})
@@ -1900,7 +1900,9 @@
})
ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
- StubsJar: al.stubsJar,
+ JavaInfo: JavaInfo{
+ HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ },
StubsSrcJar: al.stubsSrcJar,
})
}
diff --git a/java/testing.go b/java/testing.go
index 8a0db9c..0764d26 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -368,14 +368,6 @@
"core.current.stubs",
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
- "android_stubs_current.from-text",
- "android_system_stubs_current.from-text",
- "android_test_stubs_current.from-text",
- "android_module_lib_stubs_current.from-text",
- "android_system_server_stubs_current.from-text",
- "core.current.stubs.from-text",
- "legacy.core.platform.api.stubs.from-text",
- "stable.core.platform.api.stubs.from-text",
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
@@ -396,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",
diff --git a/mk2rbc/soong_variables.go b/mk2rbc/soong_variables.go
index a52ec4f..7a6aa5f 100644
--- a/mk2rbc/soong_variables.go
+++ b/mk2rbc/soong_variables.go
@@ -67,7 +67,11 @@
var valueType starlarkType
switch typeString {
case "bool":
- valueType = starlarkTypeBool
+ // TODO: We run into several issues later on if we type this as a bool:
+ // - We still assign bool-typed variables to strings
+ // - When emitting the final results as make code, some bool's false values have to
+ // be an empty string, and some have to be false in order to match the make variables.
+ valueType = starlarkTypeString
case "csv":
// Only PLATFORM_VERSION_ALL_CODENAMES, and it's a list
valueType = starlarkTypeList
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 26fe432..9367ff0 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -189,6 +189,7 @@
libs: [
"linker_config_proto",
],
+ visibility: ["//system/linkerconfig"],
}
python_test_host {
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
index 064fc21..a97f71b 100644
--- a/starlark_fmt/format.go
+++ b/starlark_fmt/format.go
@@ -35,7 +35,11 @@
// PrintBool returns a Starlark compatible bool string.
func PrintBool(item bool) string {
- return strings.Title(fmt.Sprintf("%t", item))
+ if item {
+ return "True"
+ } else {
+ return "False"
+ }
}
// PrintsStringList returns a Starlark-compatible string of a list of Strings/Labels.
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index a507349..2f154cd 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -98,19 +98,15 @@
-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_dlkm/etc"
- function diff_files {
- file_list_file="$1";
- files_in_spdx_file="$2"
- partition_name="$3"
+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]}
@@ -168,9 +164,9 @@
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
- type=$(echo $entry | awk -F ' ' '{print $2}')
+ inode_type=$(echo $entry | awk -F ' ' '{print $2}')
name=$(echo $entry | awk -F ' ' '{print $3}')
- case $type in
+ case $inode_type in
"2") # directory
all_dirs=$(echo "$all_dirs $dir/$name" | sed 's/^\s*//')
;;
@@ -204,6 +200,11 @@
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"