Revert "use symlink for bundled APEX"

This reverts commit 58ab941c6c.

Reason for revert: art-com_android_runtime_host-linux_bionic and art-linux-bionic-zipapex builds failing (https://android-build.googleplex.com/builds/submitted/6131062/art-com_android_runtime_host-linux_bionic/latest/view/logs/build.log)

Bug: 144533348
Change-Id: I040af6887aea205a5d72a416fc8e6533dcfa08dd
This commit is contained in:
Lokesh Gidra 2020-01-13 23:57:34 +00:00
parent 58ab941c6c
commit 31c65d4fe4
4 changed files with 55 additions and 236 deletions

View file

@ -52,40 +52,13 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
return moduleNames return moduleNames
} }
var postInstallCommands []string
for _, fi := range a.filesInfo {
if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
linkTarget := filepath.Join("/system", fi.Path())
linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexName, fi.Path())
mkdirCmd := "mkdir -p " + filepath.Dir(linkPath)
linkCmd := "ln -s " + linkTarget + " " + linkPath
postInstallCommands = append(postInstallCommands, mkdirCmd, linkCmd)
}
}
postInstallCommands = append(postInstallCommands, a.compatSymlinks...)
for _, fi := range a.filesInfo { for _, fi := range a.filesInfo {
if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake { if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
continue continue
} }
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() if !android.InList(fi.moduleName, moduleNames) {
moduleNames = append(moduleNames, fi.moduleName)
var moduleName string
if linkToSystemLib {
moduleName = fi.moduleName
} else {
moduleName = fi.moduleName + "." + apexName + a.suffix
}
if !android.InList(moduleName, moduleNames) {
moduleNames = append(moduleNames, moduleName)
}
if linkToSystemLib {
// No need to copy the file since it's linked to the system file
continue
} }
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
@ -94,7 +67,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
} else { } else {
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
} }
fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName) fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
// /apex/<apex_name>/{lib|framework|...} // /apex/<apex_name>/{lib|framework|...}
pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir) pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
if apexType == flattenedApex { if apexType == flattenedApex {
@ -170,8 +143,8 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
} else { } else {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex // For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
if a.primaryApexType && apexType == flattenedApex && fi.builtFile == a.manifestPbOut && len(postInstallCommands) > 0 { if a.primaryApexType && fi.builtFile == a.manifestPbOut && len(a.compatSymlinks) > 0 {
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && ")) fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
} }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)") fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
} }

View file

@ -488,30 +488,6 @@ func (af *apexFile) Ok() bool {
return af.builtFile != nil && af.builtFile.String() != "" return af.builtFile != nil && af.builtFile.String() != ""
} }
// Path() returns path of this apex file relative to the APEX root
func (af *apexFile) Path() string {
return filepath.Join(af.installDir, af.builtFile.Base())
}
// SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root
func (af *apexFile) SymlinkPaths() []string {
var ret []string
for _, symlink := range af.symlinks {
ret = append(ret, filepath.Join(af.installDir, symlink))
}
return ret
}
func (af *apexFile) AvailableToPlatform() bool {
if af.module == nil {
return false
}
if am, ok := af.module.(android.ApexModule); ok {
return am.AvailableFor(android.AvailableToPlatform)
}
return false
}
type apexBundle struct { type apexBundle struct {
android.ModuleBase android.ModuleBase
android.DefaultableModuleBase android.DefaultableModuleBase
@ -562,10 +538,6 @@ type apexBundle struct {
// Suffix of module name in Android.mk // Suffix of module name in Android.mk
// ".flattened", ".apex", ".zipapex", or "" // ".flattened", ".apex", ".zipapex", or ""
suffix string suffix string
// Whether to create symlink to the system file instead of having a file
// inside the apex or not
linkToSystemLib bool
} }
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@ -1169,8 +1141,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// of the original test module (`depName`, shared by all `test_per_src` // of the original test module (`depName`, shared by all `test_per_src`
// variations of that module). // variations of that module).
af.moduleName = filepath.Base(af.builtFile.String()) af.moduleName = filepath.Base(af.builtFile.String())
// these are not considered transitive dep af.transitiveDep = true
af.transitiveDep = false
filesInfo = append(filesInfo, af) filesInfo = append(filesInfo, af)
return true // track transitive dependencies return true // track transitive dependencies
} }
@ -1206,22 +1177,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// remove duplicates in filesInfo // remove duplicates in filesInfo
removeDup := func(filesInfo []apexFile) []apexFile { removeDup := func(filesInfo []apexFile) []apexFile {
encountered := make(map[string]apexFile) encountered := make(map[string]bool)
result := []apexFile{}
for _, f := range filesInfo { for _, f := range filesInfo {
dest := filepath.Join(f.installDir, f.builtFile.Base()) dest := filepath.Join(f.installDir, f.builtFile.Base())
if e, ok := encountered[dest]; !ok { if !encountered[dest] {
encountered[dest] = f encountered[dest] = true
} else { result = append(result, f)
// If a module is directly included and also transitively depended on
// consider it as directly included.
e.transitiveDep = e.transitiveDep && f.transitiveDep
encountered[dest] = e
} }
} }
var result []apexFile
for _, v := range encountered {
result = append(result, v)
}
return result return result
} }
filesInfo = removeDup(filesInfo) filesInfo = removeDup(filesInfo)
@ -1243,6 +1207,12 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} }
} }
// prepend the name of this APEX to the module names. These names will be the names of
// modules that will be defined if the APEX is flattened.
for i := range filesInfo {
filesInfo[i].moduleName = filesInfo[i].moduleName + "." + a.Name() + a.suffix
}
a.installDir = android.PathForModuleInstall(ctx, "apex") a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo a.filesInfo = filesInfo
@ -1262,14 +1232,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return return
} }
} }
// Optimization. If we are building bundled APEX, for the files that are gathered due to the
// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
// the same library in the system partition, thus effectively sharing the same libraries
// across the APEX boundary. For unbundled APEX, all the gathered files are actually placed
// in the APEX.
a.linkToSystemLib = !ctx.Config().UnbundledBuild() &&
a.installable() &&
!proptools.Bool(a.properties.Use_vendor)
// prepare apex_manifest.json // prepare apex_manifest.json
a.buildManifest(ctx, provideNativeLibs, requireNativeLibs) a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)

View file

@ -91,10 +91,6 @@ func withBinder32bit(fs map[string][]byte, config android.Config) {
config.TestProductVariables.Binder32bit = proptools.BoolPtr(true) config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
} }
func withUnbundledBuild(fs map[string][]byte, config android.Config) {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) { func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
android.ClearApexDependency() android.ClearApexDependency()
@ -1535,68 +1531,46 @@ func TestHeaderLibsDependency(t *testing.T) {
ensureContains(t, cFlags, "-Imy_include") ensureContains(t, cFlags, "-Imy_include")
} }
type fileInApex struct { func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
path string // path in apex
isLink bool
}
func getFiles(t *testing.T, ctx *android.TestContext, moduleName string) []fileInApex {
t.Helper() t.Helper()
apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Rule("apexRule") apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"] copyCmds := apexRule.Args["copy_commands"]
imageApexDir := "/image.apex/" imageApexDir := "/image.apex/"
var ret []fileInApex var failed bool
var surplus []string
filesMatched := make(map[string]bool)
addContent := func(content string) {
for _, expected := range files {
if matched, _ := path.Match(expected, content); matched {
filesMatched[expected] = true
return
}
}
surplus = append(surplus, content)
}
for _, cmd := range strings.Split(copyCmds, "&&") { for _, cmd := range strings.Split(copyCmds, "&&") {
cmd = strings.TrimSpace(cmd) cmd = strings.TrimSpace(cmd)
if cmd == "" { if cmd == "" {
continue continue
} }
terms := strings.Split(cmd, " ") terms := strings.Split(cmd, " ")
var dst string
var isLink bool
switch terms[0] { switch terms[0] {
case "mkdir": case "mkdir":
case "cp": case "cp":
if len(terms) != 3 { if len(terms) != 3 {
t.Fatal("copyCmds contains invalid cp command", cmd) t.Fatal("copyCmds contains invalid cp command", cmd)
} }
dst = terms[2] dst := terms[2]
isLink = false
case "ln":
if len(terms) != 3 && len(terms) != 4 {
// ln LINK TARGET or ln -s LINK TARGET
t.Fatal("copyCmds contains invalid ln command", cmd)
}
dst = terms[len(terms)-1]
isLink = true
default:
t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
}
if dst != "" {
index := strings.Index(dst, imageApexDir) index := strings.Index(dst, imageApexDir)
if index == -1 { if index == -1 {
t.Fatal("copyCmds should copy a file to image.apex/", cmd) t.Fatal("copyCmds should copy a file to image.apex/", cmd)
} }
dstFile := dst[index+len(imageApexDir):] dstFile := dst[index+len(imageApexDir):]
ret = append(ret, fileInApex{path: dstFile, isLink: isLink}) addContent(dstFile)
default:
t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
} }
} }
return ret
}
func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
var failed bool
var surplus []string
filesMatched := make(map[string]bool)
for _, file := range getFiles(t, ctx, moduleName) {
for _, expected := range files {
if matched, _ := path.Match(expected, file.path); matched {
filesMatched[expected] = true
return
}
}
surplus = append(surplus, file.path)
}
if len(surplus) > 0 { if len(surplus) > 0 {
sort.Strings(surplus) sort.Strings(surplus)
@ -3391,90 +3365,6 @@ func TestCarryRequiredModuleNames(t *testing.T) {
ensureContains(t, androidMk, "LOCAL_TARGET_REQUIRED_MODULES += e f\n") ensureContains(t, androidMk, "LOCAL_TARGET_REQUIRED_MODULES += e f\n")
} }
func TestSymlinksFromApexToSystem(t *testing.T) {
bp := `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
shared_libs: ["myotherlib"],
system_shared_libs: [],
stl: "none",
}
cc_library {
name: "myotherlib",
srcs: ["mylib.cpp"],
system_shared_libs: [],
stl: "none",
}
java_library {
name: "myjar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
libs: ["myotherjar"],
compile_dex: true,
}
java_library {
name: "myotherjar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
}
`
ensureRealfileExists := func(t *testing.T, files []fileInApex, file string) {
for _, f := range files {
if f.path == file {
if f.isLink {
t.Errorf("%q is not a real file", file)
}
return
}
}
t.Errorf("%q is not found", file)
}
ensureSymlinkExists := func(t *testing.T, files []fileInApex, file string) {
for _, f := range files {
if f.path == file {
if !f.isLink {
t.Errorf("%q is not a symlink", file)
}
return
}
}
t.Errorf("%q is not found", file)
}
ctx, _ := testApex(t, bp, withUnbundledBuild)
files := getFiles(t, ctx, "myapex")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
ensureRealfileExists(t, files, "lib64/myotherlib.so")
ctx, _ = testApex(t, bp)
files = getFiles(t, ctx, "myapex")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
ensureSymlinkExists(t, files, "lib64/myotherlib.so") // this is symlink
}
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
run := func() int { run := func() int {
setUp() setUp()

View file

@ -245,41 +245,36 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
apexType := a.properties.ApexType apexType := a.properties.ApexType
suffix := apexType.suffix() suffix := apexType.suffix()
var implicitInputs []android.Path
unsignedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix+".unsigned") unsignedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix+".unsigned")
// TODO(jiyong): construct the copy rules using RuleBuilder filesToCopy := []android.Path{}
var copyCommands []string for _, f := range a.filesInfo {
for _, fi := range a.filesInfo { filesToCopy = append(filesToCopy, f.builtFile)
destPath := android.PathForModuleOut(ctx, "image"+suffix, fi.Path()).String()
copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(destPath))
if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
pathOnDevice := filepath.Join("/system", fi.Path())
copyCommands = append(copyCommands, "ln -s "+pathOnDevice+" "+destPath)
} else {
copyCommands = append(copyCommands, "cp "+fi.builtFile.String()+" "+destPath)
implicitInputs = append(implicitInputs, fi.builtFile)
}
// create additional symlinks pointing the file inside the APEX
for _, symlinkPath := range fi.SymlinkPaths() {
symlinkDest := android.PathForModuleOut(ctx, "image"+suffix, symlinkPath).String()
copyCommands = append(copyCommands, "ln -s "+filepath.Base(destPath)+" "+symlinkDest)
}
} }
// TODO(jiyong): use RuleBuilder copyCommands := []string{}
var emitCommands []string emitCommands := []string{}
imageContentFile := android.PathForModuleOut(ctx, "content.txt") imageContentFile := android.PathForModuleOut(ctx, a.Name()+"-content.txt")
emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String()) emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
if proptools.Bool(a.properties.Legacy_android10_support) { if proptools.Bool(a.properties.Legacy_android10_support) {
emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String()) emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
} }
for _, fi := range a.filesInfo { for i, src := range filesToCopy {
emitCommands = append(emitCommands, "echo './"+fi.Path()+"' >> "+imageContentFile.String()) dest := filepath.Join(a.filesInfo[i].installDir, src.Base())
emitCommands = append(emitCommands, "echo './"+dest+"' >> "+imageContentFile.String())
dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
for _, sym := range a.filesInfo[i].symlinks {
symlinkDest := filepath.Join(filepath.Dir(dest_path), sym)
copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest)
}
} }
emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String()) emitCommands = append(emitCommands, "sort -o "+imageContentFile.String()+" "+imageContentFile.String())
implicitInputs := append(android.Paths(nil), filesToCopy...)
implicitInputs = append(implicitInputs, a.manifestPbOut)
if a.properties.Whitelisted_files != nil { if a.properties.Whitelisted_files != nil {
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: emitApexContentRule, Rule: emitApexContentRule,
@ -401,7 +396,6 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
optFlags = append(optFlags, "--do_not_check_keyname") optFlags = append(optFlags, "--do_not_check_keyname")
} }
implicitInputs = append(implicitInputs, a.manifestPbOut)
if proptools.Bool(a.properties.Legacy_android10_support) { if proptools.Bool(a.properties.Legacy_android10_support) {
implicitInputs = append(implicitInputs, a.manifestJsonOut) implicitInputs = append(implicitInputs, a.manifestJsonOut)
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String()) optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
@ -519,7 +513,7 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
if a.installable() { if a.installable() {
// For flattened APEX, do nothing but make sure that APEX manifest and apex_pubkey are also copied along // For flattened APEX, do nothing but make sure that APEX manifest and apex_pubkey are also copied along
// with other ordinary files. // with other ordinary files.
a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb", ".", etc, nil)) a.filesInfo = append(a.filesInfo, newApexFile(ctx, a.manifestPbOut, "apex_manifest.pb."+a.Name()+a.suffix, ".", etc, nil))
// rename to apex_pubkey // rename to apex_pubkey
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey") copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@ -528,7 +522,7 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
Input: a.public_key_file, Input: a.public_key_file,
Output: copiedPubkey, Output: copiedPubkey,
}) })
a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil)) a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey."+a.Name()+a.suffix, ".", etc, nil))
if a.properties.ApexType == flattenedApex { if a.properties.ApexType == flattenedApex {
apexName := proptools.StringDefault(a.properties.Apex_name, a.Name()) apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())