Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31c65d4f authored by Lokesh Gidra's avatar Lokesh Gidra
Browse files

Revert "use symlink for bundled APEX"

This reverts commit 58ab941c.

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
parent 58ab941c
Loading
Loading
Loading
Loading
+5 −32
Original line number Diff line number Diff line
@@ -52,40 +52,13 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
		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 {
		if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
			continue
		}

		linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform()

		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
		if !android.InList(fi.moduleName, moduleNames) {
			moduleNames = append(moduleNames, fi.moduleName)
		}

		fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
@@ -94,7 +67,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
		} else {
			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
		}
		fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
		// /apex/<apex_name>/{lib|framework|...}
		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
		if apexType == flattenedApex {
@@ -170,8 +143,8 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
		} else {
			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
			if a.primaryApexType && apexType == flattenedApex && fi.builtFile == a.manifestPbOut && len(postInstallCommands) > 0 {
				fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && "))
			if a.primaryApexType && fi.builtFile == a.manifestPbOut && len(a.compatSymlinks) > 0 {
				fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
			}
			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
		}
+12 −50
Original line number Diff line number Diff line
@@ -488,30 +488,6 @@ func (af *apexFile) Ok() bool {
	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 {
	android.ModuleBase
	android.DefaultableModuleBase
@@ -562,10 +538,6 @@ type apexBundle struct {
	// Suffix of module name in Android.mk
	// ".flattened", ".apex", ".zipapex", or ""
	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,
@@ -1169,8 +1141,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
						// of the original test module (`depName`, shared by all `test_per_src`
						// variations of that module).
						af.moduleName = filepath.Base(af.builtFile.String())
						// these are not considered transitive dep
						af.transitiveDep = false
						af.transitiveDep = true
						filesInfo = append(filesInfo, af)
						return true // track transitive dependencies
					}
@@ -1206,21 +1177,14 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	// remove duplicates in filesInfo
	removeDup := func(filesInfo []apexFile) []apexFile {
		encountered := make(map[string]apexFile)
		encountered := make(map[string]bool)
		result := []apexFile{}
		for _, f := range filesInfo {
			dest := filepath.Join(f.installDir, f.builtFile.Base())
			if e, ok := encountered[dest]; !ok {
				encountered[dest] = f
			} else {
				// 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
			}
			if !encountered[dest] {
				encountered[dest] = true
				result = append(result, f)
			}
		var result []apexFile
		for _, v := range encountered {
			result = append(result, v)
		}
		return result
	}
@@ -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.filesInfo = filesInfo

@@ -1262,14 +1232,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			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
	a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
+17 −127
Original line number Diff line number Diff line
@@ -91,10 +91,6 @@ func withBinder32bit(fs map[string][]byte, config android.Config) {
	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) {
	android.ClearApexDependency()

@@ -1535,67 +1531,45 @@ func TestHeaderLibsDependency(t *testing.T) {
	ensureContains(t, cFlags, "-Imy_include")
}

type fileInApex struct {
	path   string // path in apex
	isLink bool
}

func getFiles(t *testing.T, ctx *android.TestContext, moduleName string) []fileInApex {
func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
	t.Helper()
	apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Rule("apexRule")
	copyCmds := apexRule.Args["copy_commands"]
	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, "&&") {
		cmd = strings.TrimSpace(cmd)
		if cmd == "" {
			continue
		}
		terms := strings.Split(cmd, " ")
		var dst string
		var isLink bool
		switch terms[0] {
		case "mkdir":
		case "cp":
			if len(terms) != 3 {
				t.Fatal("copyCmds contains invalid cp command", cmd)
			}
			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 != "" {
			dst := terms[2]
			index := strings.Index(dst, imageApexDir)
			if index == -1 {
				t.Fatal("copyCmds should copy a file to image.apex/", cmd)
			}
			dstFile := dst[index+len(imageApexDir):]
			ret = append(ret, fileInApex{path: dstFile, isLink: isLink})
		}
	}
	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
			}
			addContent(dstFile)
		default:
			t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
		}
		surplus = append(surplus, file.path)
	}

	if len(surplus) > 0 {
@@ -3391,90 +3365,6 @@ func TestCarryRequiredModuleNames(t *testing.T) {
	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) {
	run := func() int {
		setUp()
+21 −27
Original line number Diff line number Diff line
@@ -245,41 +245,36 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {

	apexType := a.properties.ApexType
	suffix := apexType.suffix()
	var implicitInputs []android.Path
	unsignedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix+".unsigned")

	// TODO(jiyong): construct the copy rules using RuleBuilder
	var copyCommands []string
	for _, fi := range a.filesInfo {
		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)
		}
	filesToCopy := []android.Path{}
	for _, f := range a.filesInfo {
		filesToCopy = append(filesToCopy, f.builtFile)
	}

	// TODO(jiyong): use RuleBuilder
	var emitCommands []string
	imageContentFile := android.PathForModuleOut(ctx, "content.txt")
	copyCommands := []string{}
	emitCommands := []string{}
	imageContentFile := android.PathForModuleOut(ctx, a.Name()+"-content.txt")
	emitCommands = append(emitCommands, "echo ./apex_manifest.pb >> "+imageContentFile.String())
	if proptools.Bool(a.properties.Legacy_android10_support) {
		emitCommands = append(emitCommands, "echo ./apex_manifest.json >> "+imageContentFile.String())
	}
	for _, fi := range a.filesInfo {
		emitCommands = append(emitCommands, "echo './"+fi.Path()+"' >> "+imageContentFile.String())
	for i, src := range filesToCopy {
		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())

	implicitInputs := append(android.Paths(nil), filesToCopy...)
	implicitInputs = append(implicitInputs, a.manifestPbOut)

	if a.properties.Whitelisted_files != nil {
		ctx.Build(pctx, android.BuildParams{
			Rule:        emitApexContentRule,
@@ -401,7 +396,6 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
			optFlags = append(optFlags, "--do_not_check_keyname")
		}

		implicitInputs = append(implicitInputs, a.manifestPbOut)
		if proptools.Bool(a.properties.Legacy_android10_support) {
			implicitInputs = append(implicitInputs, a.manifestJsonOut)
			optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
@@ -519,7 +513,7 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
	if a.installable() {
		// For flattened APEX, do nothing but make sure that APEX manifest and apex_pubkey are also copied along
		// 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
		copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -528,7 +522,7 @@ func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
			Input:  a.public_key_file,
			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 {
			apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())