Merge "Allowlist jni libs of FrameworksNetsTests" into main
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 556e177..16e2328 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -582,6 +582,7 @@
"tagsoup",
// framework-minus-apex
+ "AndroidFrameworkLintChecker",
"ImmutabilityAnnotationProcessor",
"debian.mime.types.minimized",
"framework-javastream-protos",
@@ -676,6 +677,7 @@
// prebuilts
"prebuilt_stats-log-api-gen",
+ "prebuilt_aapt2",
// fastboot
"fastboot",
@@ -857,6 +859,7 @@
"kotlinx_coroutines",
"kotlinx_coroutines-device",
"kotlinx_coroutines-host",
+ "kotlinx_coroutines_android",
// for building com.android.neuralnetworks
"libimapper_stablec",
diff --git a/android/config.go b/android/config.go
index 8da97b2..04b43ac 100644
--- a/android/config.go
+++ b/android/config.go
@@ -167,7 +167,8 @@
}
// DisableHiddenApiChecks returns true if hiddenapi checks have been disabled.
-// For 'eng' target variant hiddenapi checks are disabled by default for performance optimisation,
+// For 'eng' target variant hiddenapi checks are disabled by default for performance optimisation
+// Hiddenapi checks are also disabled when RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE is set to false
// but can be enabled by setting environment variable ENABLE_HIDDENAPI_FLAGS=true.
// For other target variants hiddenapi check are enabled by default but can be disabled by
// setting environment variable UNSAFE_DISABLE_HIDDENAPI_FLAGS=true.
@@ -176,7 +177,8 @@
func (c Config) DisableHiddenApiChecks() bool {
return !c.IsEnvTrue("ENABLE_HIDDENAPI_FLAGS") &&
(c.IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") ||
- Bool(c.productVariables.Eng))
+ Bool(c.productVariables.Eng) ||
+ !c.ReleaseDefaultModuleBuildFromSource())
}
// MaxPageSizeSupported returns the max page size supported by the device. This
@@ -221,6 +223,13 @@
return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
}
+// The flag indicating behavior for the tree wrt building modules or using prebuilts
+// derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE
+func (c Config) ReleaseDefaultModuleBuildFromSource() bool {
+ return c.config.productVariables.ReleaseDefaultModuleBuildFromSource == nil ||
+ Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -1002,12 +1011,18 @@
func (c *config) PreviewApiLevels() []ApiLevel {
var levels []ApiLevel
- for i, codename := range c.PlatformVersionActiveCodenames() {
+ i := 0
+ for _, codename := range c.PlatformVersionActiveCodenames() {
+ if codename == "REL" {
+ continue
+ }
+
levels = append(levels, ApiLevel{
value: codename,
number: i,
isPreview: true,
})
+ i++
}
return levels
}
@@ -1442,7 +1457,7 @@
}
func (c *deviceConfig) VndkUseCoreVariant() bool {
- return Bool(c.config.productVariables.VndkUseCoreVariant)
+ return Bool(c.config.productVariables.VndkUseCoreVariant) && Bool(c.config.productVariables.KeepVndk)
}
func (c *deviceConfig) SystemSdkVersions() []string {
diff --git a/android/variable.go b/android/variable.go
index 8882e80..006a77f 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -479,6 +479,8 @@
ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
+ ReleaseDefaultModuleBuildFromSource *bool `json:",omitempty"`
+
KeepVndk *bool `json:",omitempty"`
CheckVendorSeappViolations *bool `json:",omitempty"`
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 966b94a..15a6df0 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -22,7 +22,6 @@
"regexp"
"sort"
"strconv"
- "strings"
"sync"
"sync/atomic"
@@ -32,19 +31,12 @@
)
// A tree structure that describes what to do at each directory in the created
-// symlink tree. Currently it is used to enumerate which files/directories
+// symlink tree. Currently, it is used to enumerate which files/directories
// should be excluded from symlinking. Each instance of "node" represents a file
// or a directory. If excluded is true, then that file/directory should be
// 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 = 2
-
type instructionsNode struct {
name string
excluded bool // If false, this is just an intermediate node
@@ -193,7 +185,7 @@
srcPath := shared.JoinPath(topdir, src)
dstPath := shared.JoinPath(topdir, dst)
- // Check if a symlink already exists.
+ // Check whether a symlink already exists.
if dstInfo, err := os.Lstat(dstPath); err != nil {
if !os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "Failed to lstat '%s': %s", dst, err)
@@ -240,44 +232,49 @@
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
+// Returns the mtime of the soong_build binary to determine whether we should
+// force symlink_forest to re-execute
+func getSoongBuildMTime() (int64, error) {
+ binaryPath, err := os.Executable()
+ if err != nil {
+ return 0, 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
- }
+
+ info, err := os.Stat(binaryPath)
+ if err != nil {
+ return 0, err
}
- return nil
+
+ return info.ModTime().UnixMilli(), 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)
+// cleanSymlinkForest will remove the whole symlink forest directory
+func cleanSymlinkForest(topdir, forest string) error {
+ return os.RemoveAll(shared.JoinPath(topdir, forest))
+}
+
+// This returns whether symlink forest should clean and replant symlinks.
+// It compares the mtime of this executable with the mtime of the last-run
+// soong_build binary. If they differ, then we should clean and replant.
+func shouldCleanSymlinkForest(topdir string, forest string, soongBuildMTime int64) (bool, error) {
+ mtimeFilePath := shared.JoinPath(topdir, forest, "soong_build_mtime")
+ mtimeFileContents, err := os.ReadFile(mtimeFilePath)
if err != nil {
- if !os.IsNotExist(err) {
- return err
- }
- err = os.WriteFile(versionFilePath, []byte(strconv.Itoa(symlinkForestVersion)+"\n"), 0666)
- if err != nil {
- return err
+ if os.IsNotExist(err) {
+ // This is likely the first time this has run with this functionality - clean away!
+ return true, nil
+ } else {
+ return false, err
}
}
- return nil
+ return strconv.FormatInt(soongBuildMTime, 10) != string(mtimeFileContents), nil
+}
+
+func writeSoongBuildMTimeFile(topdir, forest string, mtime int64) error {
+ mtimeFilePath := shared.JoinPath(topdir, forest, "soong_build_mtime")
+ contents := []byte(strconv.FormatInt(mtime, 10))
+
+ return os.WriteFile(mtimeFilePath, contents, 0666)
}
// Recursively plants a symlink forest at forestDir. The symlink tree will
@@ -473,12 +470,26 @@
symlinkCount: atomic.Uint64{},
}
- err := maybeCleanSymlinkForest(topdir, forest, verbose)
+ // Check whether soong_build has been modified since the last run
+ soongBuildMTime, err := getSoongBuildMTime()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
+ shouldClean, err := shouldCleanSymlinkForest(topdir, forest, soongBuildMTime)
+
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ } else if shouldClean {
+ err = cleanSymlinkForest(topdir, forest)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ }
+
instructions := instructionsFromExcludePathList(exclude)
go func() {
context.wg.Add(1)
@@ -491,11 +502,10 @@
deps = append(deps, dep)
}
- err = maybeWriteVersionFile(topdir, forest)
+ err = writeSoongBuildMTimeFile(topdir, forest, soongBuildMTime)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
-
return deps, context.mkdirCount.Load(), context.symlinkCount.Load()
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f7eb8d2..794c5ee 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -677,6 +677,7 @@
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+ config.TestProductVariables.KeepVndk = BoolPtr(true)
setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
diff --git a/cc/lto.go b/cc/lto.go
index df9ca0a..281b527 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -35,11 +35,11 @@
// optimized at link time and may not be compatible with features that require
// LTO, such as CFI.
//
-// This file adds support to soong to automatically propogate LTO options to a
+// This file adds support to soong to automatically propagate LTO options to a
// new variant of all static dependencies for each module with LTO enabled.
type LTOProperties struct {
- // Lto must violate capitialization style for acronyms so that it can be
+ // Lto must violate capitalization style for acronyms so that it can be
// referred to in blueprint files as "lto"
Lto struct {
Never *bool `android:"arch_variant"`
@@ -67,10 +67,12 @@
}
func (lto *lto) begin(ctx BaseModuleContext) {
- // First, determine the module indepedent default LTO mode.
+ // First, determine the module independent default LTO mode.
ltoDefault := GlobalThinLTO(ctx)
if ctx.Config().IsEnvTrue("DISABLE_LTO") {
ltoDefault = false
+ } else if lto.Never() {
+ ltoDefault = false
} else if ctx.Host() {
// Performance and binary size are less important for host binaries.
ltoDefault = false
diff --git a/cc/lto_test.go b/cc/lto_test.go
index e0afd4a..7b7fe8c 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -23,11 +23,19 @@
"github.com/google/blueprint"
)
-var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
+var LTOPreparer = android.GroupFixturePreparers(
prepareForCcTest,
- android.FixtureModifyEnv(func(env map[string]string) {
- env["GLOBAL_THINLTO"] = "false"
- }))
+)
+
+func hasDep(result *android.TestResult, m android.Module, wantDep android.Module) bool {
+ var found bool
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+}
func TestThinLtoDeps(t *testing.T) {
t.Parallel()
@@ -37,9 +45,6 @@
srcs: ["src.c"],
static_libs: ["foo", "lib_never_lto"],
shared_libs: ["bar"],
- lto: {
- thin: true,
- }
}
cc_library_static {
name: "foo",
@@ -63,50 +68,40 @@
}
`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
+ libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libLto, libFoo) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'")
}
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libFoo) {
- t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
+ libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libFoo, libBaz) {
+ t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libFoo, libBaz) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
- }
-
- libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libNeverLto) {
- t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
+ libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libLto, libNeverLto) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'")
}
libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
- if !hasDep(libLto, libBar) {
- t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
+ if !hasDep(result, libLto, libBar) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'")
}
barVariants := result.ModuleVariantsForTests("bar")
for _, v := range barVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
+ if strings.Contains(v, "lto-none") {
+ t.Errorf("Expected variants for 'bar' to not contain 'lto-none', but found %q", v)
}
}
quxVariants := result.ModuleVariantsForTests("qux")
for _, v := range quxVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
+ if strings.Contains(v, "lto-none") {
+ t.Errorf("Expected variants for 'qux' to not contain 'lto-none', but found %q", v)
}
}
}
@@ -141,28 +136,18 @@
}
`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
- if !hasDep(libRoot, libFoo.Module()) {
- t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
+ if !hasDep(result, libRoot, libFoo.Module()) {
+ t.Errorf("'root' missing dependency on the default variant of 'foo'")
}
- if !hasDep(libRootLtoNever, libFoo.Module()) {
- t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
+ if !hasDep(result, libRootLtoNever, libFoo.Module()) {
+ t.Errorf("'root_no_lto' missing dependency on the default variant of 'foo'")
}
libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
@@ -170,9 +155,9 @@
t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
- if !hasDep(libFoo.Module(), libBaz.Module()) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
+ libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static")
+ if !hasDep(result, libFoo.Module(), libBaz.Module()) {
+ t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
@@ -199,7 +184,7 @@
},
},
}`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
@@ -227,7 +212,7 @@
},
}`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2064b1b..4936559 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -61,7 +61,7 @@
// because we don't want to spam the build output with "nothing
// changed" messages, so redirect output message to $out, and if
// changes were detected print the output and fail.
- Command: "$stgdiff $args --stg $in -o $out || (cat $out && false; echo 'Run $$ANDROID_BUILD_TOP/development/tools/ndk/update_ndk_abi.sh to update the ABI dumps.')",
+ Command: "$stgdiff $args --stg $in -o $out || (cat $out && echo 'Run $$ANDROID_BUILD_TOP/development/tools/ndk/update_ndk_abi.sh to update the ABI dumps.' && false)",
CommandDeps: []string{"$stgdiff"},
}, "args")
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 6329e97..6624d4b 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -86,7 +86,7 @@
memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
- deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all", "-ftrap-function=abort"}
+ deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"}
noSanitizeLinkRuntimeFlag = "-fno-sanitize-link-runtime"
)
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 3e92706..9647a18 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -17,6 +17,7 @@
var (
DepfileAllowList = []string{
"depfile_allowed_for_test",
+ "tflite_support_metadata_schema",
"tflite_support_spm_config",
"tflite_support_spm_encoder_config",
"gen_uwb_core_proto",
@@ -249,6 +250,13 @@
"ue_unittest_erofs_imgs",
"vts_vndk_abi_dump_zip",
"atest_integration_fake_src",
+ "VehicleServerProtoStub_cc@2.0-grpc-trout",
+ "VehicleServerProtoStub_cc@default-grpc",
+ "VehicleServerProtoStub_h@default-grpc",
+ "VehicleServerProtoStub_h@2.0-grpc-trout",
+ "chre_atoms_log.h",
+ "checkIn-service-stub-lite",
+ "seller-frontend-service-stub-lite",
}
SandboxingDenyPathList = []string{
diff --git a/java/androidmk.go b/java/androidmk.go
index b7e2d2f..97b303d 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -20,6 +20,8 @@
"strings"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
@@ -79,7 +81,7 @@
} else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
// Platform variant. If not available for the platform, we don't need Make module.
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
- } else if library.properties.Headers_only {
+ } else if proptools.Bool(library.properties.Headers_only) {
// If generating headers only then don't expose to Make.
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
} else {
diff --git a/java/base.go b/java/base.go
index ec98dfe..03198b5 100644
--- a/java/base.go
+++ b/java/base.go
@@ -194,7 +194,7 @@
Generated_srcjars []android.Path `android:"mutated"`
// If true, then only the headers are built and not the implementation jar.
- Headers_only bool
+ Headers_only *bool
}
// Properties that are specific to device modules. Host module factories should not add these when
@@ -582,7 +582,7 @@
func (j *Module) checkHeadersOnly(ctx android.ModuleContext) {
if _, ok := ctx.Module().(android.SdkContext); ok {
- headersOnly := proptools.Bool(&j.properties.Headers_only)
+ headersOnly := proptools.Bool(j.properties.Headers_only)
installable := proptools.Bool(j.properties.Installable)
if headersOnly && installable {
@@ -1180,7 +1180,7 @@
flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...)
// If compiling headers then compile them and skip the rest
- if j.properties.Headers_only {
+ if proptools.Bool(j.properties.Headers_only) {
if srcFiles.HasExt(".kt") {
ctx.ModuleErrorf("Compiling headers_only with .kt not supported")
}
diff --git a/java/robolectric.go b/java/robolectric.go
index 0041af4..af56339 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -34,7 +34,7 @@
var robolectricDefaultLibs = []string{
"mockito-robolectric-prebuilt",
- "truth-prebuilt",
+ "truth",
// TODO(ccross): this is not needed at link time
"junitxml",
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 8225df6..78ab771 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -635,6 +635,13 @@
case "+=":
asgn.flavor = asgnAppend
case "?=":
+ if _, ok := lhs.(*productConfigVariable); ok {
+ // Make sets all product configuration variables to empty strings before running product
+ // config makefiles. ?= will have no effect on a variable that has been assigned before,
+ // even if assigned to an empty string. So just skip emitting any code for this
+ // assignment.
+ return nil
+ }
asgn.flavor = asgnMaybeSet
default:
panic(fmt.Errorf("unexpected assignment type %s", a.Type))
@@ -941,6 +948,8 @@
func (ctx *parseContext) handleInclude(v *mkparser.Directive) []starlarkNode {
loadAlways := v.Name[0] != '-'
+ v.Args.TrimRightSpaces()
+ v.Args.TrimLeftSpaces()
return ctx.handleSubConfig(v, ctx.parseMakeString(v, v.Args), loadAlways, func(im inheritedModule) starlarkNode {
return &includeNode{im, loadAlways}
})
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 7e68026..0c4d213 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -193,6 +193,31 @@
},
{
+ desc: "Include with trailing whitespace",
+ mkname: "product.mk",
+ in: `
+# has a trailing whitespace after cfg.mk
+include vendor/$(foo)/cfg.mk
+`,
+ expected: `# has a trailing whitespace after cfg.mk
+load("//build/make/core:product_config.rbc", "rblf")
+load("//vendor/foo1:cfg.star|init", _cfg_init = "init")
+load("//vendor/bar/baz:cfg.star|init", _cfg1_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ _entry = {
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ "vendor/bar/baz/cfg.mk": ("vendor/bar/baz/cfg", _cfg1_init),
+ }.get("vendor/%s/cfg.mk" % _foo)
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("vendor/%s/cfg.mk" % _foo))
+ _varmod_init(g, handle)
+`,
+ },
+
+ {
desc: "Synonymous inherited configurations",
mkname: "path/product.mk",
in: `
@@ -898,8 +923,6 @@
cfg["PRODUCT_LIST2"] += ["a"]
cfg["PRODUCT_LIST1"] += ["b"]
cfg["PRODUCT_LIST2"] += ["b"]
- if cfg.get("PRODUCT_LIST3") == None:
- cfg["PRODUCT_LIST3"] = ["a"]
cfg["PRODUCT_LIST1"] = ["c"]
g.setdefault("PLATFORM_LIST", [])
g["PLATFORM_LIST"] += ["x"]
@@ -941,9 +964,10 @@
PRODUCT_LIST2 ?= a $(PRODUCT_LIST2)
PRODUCT_LIST3 += a
-# Now doing them again should not have a setdefault because they've already been set
+# Now doing them again should not have a setdefault because they've already been set, except 2
+# which did not emit an assignment before
PRODUCT_LIST1 = a $(PRODUCT_LIST1)
-PRODUCT_LIST2 ?= a $(PRODUCT_LIST2)
+PRODUCT_LIST2 = a $(PRODUCT_LIST2)
PRODUCT_LIST3 += a
`,
expected: `# All of these should have a setdefault because they're self-referential and not defined before
@@ -954,18 +978,15 @@
rblf.setdefault(handle, "PRODUCT_LIST1")
cfg["PRODUCT_LIST1"] = (["a"] +
cfg.get("PRODUCT_LIST1", []))
- if cfg.get("PRODUCT_LIST2") == None:
- rblf.setdefault(handle, "PRODUCT_LIST2")
- cfg["PRODUCT_LIST2"] = (["a"] +
- cfg.get("PRODUCT_LIST2", []))
rblf.setdefault(handle, "PRODUCT_LIST3")
cfg["PRODUCT_LIST3"] += ["a"]
- # Now doing them again should not have a setdefault because they've already been set
+ # Now doing them again should not have a setdefault because they've already been set, except 2
+ # which did not emit an assignment before
cfg["PRODUCT_LIST1"] = (["a"] +
cfg["PRODUCT_LIST1"])
- if cfg.get("PRODUCT_LIST2") == None:
- cfg["PRODUCT_LIST2"] = (["a"] +
- cfg["PRODUCT_LIST2"])
+ rblf.setdefault(handle, "PRODUCT_LIST2")
+ cfg["PRODUCT_LIST2"] = (["a"] +
+ cfg.get("PRODUCT_LIST2", []))
cfg["PRODUCT_LIST3"] += ["a"]
`,
},
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index 0a26ed8..95e1f8e 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -109,14 +109,11 @@
}
emitAppend()
case asgnMaybeSet:
- gctx.writef("if cfg.get(%q) == None:", pcv.nam)
- gctx.indentLevel++
- gctx.newLine()
- if needsSetDefault {
- emitSetDefault()
- }
- emitAssignment()
- gctx.indentLevel--
+ // In mk2rbc.go we never emit a maybeSet assignment for product config variables, because
+ // they are set to empty strings before running product config.
+ panic("Should never get here")
+ default:
+ panic("Unknown assignment flavor")
}
gctx.setHasBeenAssigned(&pcv)
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 564168b..6c021c7 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -54,6 +54,7 @@
strings.Join(rustFlags, " "))
}
+ ExportedVars.ExportStringListStaticVariable("DEVICE_ARM64_RUSTC_FLAGS", Arm64RustFlags)
}
type toolchainArm64 struct {
diff --git a/rust/config/global.go b/rust/config/global.go
index c37ac4e..4397d58 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -23,7 +23,7 @@
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- exportedVars = android.NewExportedVariables(pctx)
+ ExportedVars = android.NewExportedVariables(pctx)
RustDefaultVersion = "1.72.0"
RustDefaultBase = "prebuilts/rust/"
@@ -111,9 +111,17 @@
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
- exportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
- exportedVars.ExportStringListStaticVariable("GLOBAL_RUSTC_FLAGS", GlobalRustFlags)
- exportedVars.ExportStringListStaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", LinuxHostGlobalLinkFlags)
+ ExportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
+ ExportedVars.ExportStringListStaticVariable("GLOBAL_RUSTC_FLAGS", GlobalRustFlags)
+ ExportedVars.ExportStringListStaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", LinuxHostGlobalLinkFlags)
+
+ ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_RUSTC_FLAGS", deviceGlobalRustFlags)
+ ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_LINK_FLAGS",
+ android.RemoveListFromList(deviceGlobalLinkFlags, []string{
+ // The cc_config flags are retrieved from cc_toolchain by rust rules.
+ "${cc_config.DeviceGlobalLldflags}",
+ "-B${cc_config.ClangBin}",
+ }))
}
func HostPrebuiltTag(config android.Config) string {
@@ -137,5 +145,5 @@
// BazelRustToolchainVars returns a string with
func BazelRustToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
+ return android.BazelToolchainVars(config, ExportedVars)
}
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 223baa4..8045591 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -10,6 +10,7 @@
"$TOP/build/soong/tests/persistent_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
"$TOP/build/soong/tests/stale_metrics_files_test.sh"
+"$TOP/build/soong/tests/symlink_forest_rerun_test.sh"
"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug
# The following tests build against the full source tree and don't rely on the
diff --git a/tests/symlink_forest_rerun_test.sh b/tests/symlink_forest_rerun_test.sh
new file mode 100755
index 0000000..74e779e
--- /dev/null
+++ b/tests/symlink_forest_rerun_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -eu
+
+set -o pipefail
+
+# Tests that symlink forest will replant if soong_build has changed
+# Any change to the build system should trigger a rerun
+
+source "$(dirname "$0")/lib.sh"
+
+function test_symlink_forest_reruns {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ }
+EOF
+
+ run_soong g
+
+ mtime=`cat out/soong/workspace/soong_build_mtime`
+ # rerun with no changes - ensure that it hasn't changed
+ run_soong g
+ newmtime=`cat out/soong/workspace/soong_build_mtime`
+ if [[ ! "$mtime" == "$mtime" ]]; then
+ fail "symlink forest reran when it shouldn't have"
+ fi
+
+ # change exit codes to force a soong_build rebuild.
+ sed -i 's/os.Exit(1)/os.Exit(2)/g' build/soong/bp2build/symlink_forest.go
+
+ run_soong g
+ newmtime=`cat out/soong/workspace/soong_build_mtime`
+ if [[ "$mtime" == "$newmtime" ]]; then
+ fail "symlink forest did not rerun when it should have"
+ fi
+
+}
+
+scan_and_run_tests