diff options
author | 2025-02-13 12:45:35 -0800 | |
---|---|---|
committer | 2025-02-13 12:55:10 -0800 | |
commit | e3845057836c42e197c117815088dfac0fe38d2c (patch) | |
tree | 144b9539bb4950cd4eb44815d1604b7ca74f750b | |
parent | c0a00df42e8f63caa3070c80a1e40db22bc574cc (diff) |
Make soong-only builds adb-sync compatible
Historically, the build has put the staging directories for partitions
in out/target/product. But in soong-only builds, the main staging
directory is in the out/soong/.intermediates path for the filesystem
modules, and then later also replicated in out/target/product for
backwards compatibility with tools like adb sync.
However, adb sync determines which files to push by if they have
a different timestamp than on device. Since the device images were
built using a different staging directory than the one adb sync is
looking at, the have different timestamps, and adb sync syncs all files
on the device the first time it's run.
To work around this, ensure the files in both staging directories
have the same timestamp by preserving the timestamp from their
source file with the `cp -p` flag.
This cl only does that change for real files right now, not symlinks.
We could also do it for symlinks in the future, but they're more
complicated and I didn't want to deal with that right now. This means
the first adb sync will resync all symlinks on the device, but there
are relatively few of them and they're small so it's not that big of
an issue.
Long term, we should rewrite adb sync to not depend on staging
directories. If it looks at the actual module intermediates files,
it will see a more consistent timestamp.
Bug: 396466053
Test: Manually ran m sync workflows. Also testing togging soong-only on and off and rebuilding
Change-Id: Ia0076a2f8e58404c5c3a0bf0d33b09b6846e95bd
-rw-r--r-- | android/module_context.go | 13 | ||||
-rw-r--r-- | android/packaging.go | 10 | ||||
-rw-r--r-- | filesystem/android_device_product_out.go | 6 | ||||
-rw-r--r-- | filesystem/filesystem.go | 4 |
4 files changed, 28 insertions, 5 deletions
diff --git a/android/module_context.go b/android/module_context.go index 45a8e5c7a..706ead766 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -713,6 +713,17 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat implicitDeps = append(implicitDeps, extraZip.zip) } + var cpFlags = "-f" + + // If this is a device file, copy while preserving timestamps. This is to support + // adb sync in soong-only builds. Because soong-only builds have 2 different staging + // directories, the out/target/product one and the out/soong/.intermediates one, + // we need to ensure the files in them have the same timestamps so that adb sync doesn't + // update the files on device. + if strings.Contains(fullInstallPath.String(), "target/product") { + cpFlags += " -p" + } + m.Build(pctx, BuildParams{ Rule: rule, Description: "install " + fullInstallPath.Base(), @@ -722,7 +733,7 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat OrderOnly: orderOnlyDeps, Args: map[string]string{ "extraCmds": extraCmds, - "cpFlags": "-f", + "cpFlags": cpFlags, }, }) } diff --git a/android/packaging.go b/android/packaging.go index d216c0c18..551fd4c3f 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -598,12 +598,12 @@ func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]Packa func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) { dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec) dirsToSpecs[dir] = specs - return p.CopySpecsToDirs(ctx, builder, dirsToSpecs) + return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false) } // CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec // entries into corresponding directories. -func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) { +func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) { empty := true for _, specs := range dirsToSpecs { if len(specs) > 0 { @@ -637,7 +637,11 @@ func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, builder.Command().Textf("mkdir -p %s", destDir) } if ps.symlinkTarget == "" { - builder.Command().Text("cp").Input(ps.srcPath).Text(destPath) + cmd := builder.Command().Text("cp") + if preserveTimestamps { + cmd.Flag("-p") + } + cmd.Input(ps.srcPath).Text(destPath) } else { builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath) } diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go index 2c8cad6c0..7d37f1ee7 100644 --- a/filesystem/android_device_product_out.go +++ b/filesystem/android_device_product_out.go @@ -73,6 +73,12 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont Rule: android.CpWithBash, Input: fip.SourcePath, Output: fip.FullInstallPath, + Args: map[string]string{ + // Preserve timestamps for adb sync, so that this installed file's + // timestamp matches the timestamp in the filesystem's intermediate + // staging dir + "cpFlags": "-p", + }, }) } else { ctx.Build(pctx, android.BuildParams{ diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 0381951ca..979dba5a1 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -868,7 +868,9 @@ func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *andr dirsToSpecs[rootDir] = rootDirSpecs dirsToSpecs[rebasedDir] = rebasedDirSpecs - return f.CopySpecsToDirs(ctx, builder, dirsToSpecs) + // Preserve timestamps for adb sync, so that this staging dir file matches the timestamp in the + // out/target/product staging directory. + return f.CopySpecsToDirs(ctx, builder, dirsToSpecs, true) } func (f *filesystem) rootDirString() string { |