apex: Remove 'zip' apex support

zip apex is no longer supported.

Bug: 279835185
Test: m
Change-Id: I651b0dc4e0efe766f61e97b1e5dd263e0ab74102
This commit is contained in:
Jooyung Han 2023-08-23 11:11:43 +09:00
parent 15aed3b882
commit 06a8a1c384
6 changed files with 255 additions and 495 deletions

View file

@ -67,7 +67,7 @@ func (a *apexBundle) fullModuleName(apexBundleName string, linkToSystemLib bool,
if linkToSystemLib { if linkToSystemLib {
return fi.androidMkModuleName return fi.androidMkModuleName
} }
return fi.androidMkModuleName + "." + apexBundleName + a.suffix return fi.androidMkModuleName + "." + apexBundleName
} }
// androidMkForFiles generates Make definitions for the contents of an // androidMkForFiles generates Make definitions for the contents of an
@ -85,11 +85,6 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
// conflicts between two apexes with the same apexName. // conflicts between two apexes with the same apexName.
moduleNames := []string{} moduleNames := []string{}
// To avoid creating duplicate build rules, run this function only when primaryApexType is true
// to install symbol files in $(PRODUCT_OUT}/apex.
if !a.primaryApexType {
return moduleNames
}
for _, fi := range a.filesInfo { for _, fi := range a.filesInfo {
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
@ -237,7 +232,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st
} }
// m <module_name> will build <module_name>.<apex_name> as well. // m <module_name> will build <module_name>.<apex_name> as well.
if fi.androidMkModuleName != moduleName && a.primaryApexType { if fi.androidMkModuleName != moduleName {
fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName) fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName)
fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName) fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
} }
@ -266,19 +261,18 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
return android.AndroidMkData{ return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{} moduleNames := []string{}
apexType := a.properties.ApexType
if a.installable() { if a.installable() {
moduleNames = a.androidMkForFiles(w, name, moduleDir, data) moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
} }
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle") fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix) fmt.Fprintln(w, "LOCAL_MODULE :=", name)
data.Entries.WriteLicenseVariables(w) data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class? fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String()) fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.String())
stemSuffix := apexType.suffix() stemSuffix := imageApexSuffix
if a.isCompressed { if a.isCompressed {
stemSuffix = imageCapexSuffix stemSuffix = imageCapexSuffix
} }
@ -306,10 +300,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
a.writeRequiredModules(w, moduleNames) a.writeRequiredModules(w, moduleNames)
fmt.Fprintln(w, "include $(BUILD_PREBUILT)") fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
if apexType == imageApex {
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
}
android.AndroidMkEmitAssignList(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS", a.lintReports.Strings()) android.AndroidMkEmitAssignList(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS", a.lintReports.Strings())
if a.installedFilesFile != nil { if a.installedFilesFile != nil {

View file

@ -166,15 +166,7 @@ type apexBundleProperties struct {
// Should be only used in non-system apexes (e.g. vendor: true). Default is false. // Should be only used in non-system apexes (e.g. vendor: true). Default is false.
Use_vndk_as_stable *bool Use_vndk_as_stable *bool
// The type of APEX to build. Controls what the APEX payload is. Either 'image', 'zip' or // The type of filesystem to use. Either 'ext4', 'f2fs' or 'erofs'. Default 'ext4'.
// 'both'. When set to image, contents are stored in a filesystem image inside a zip
// container. When set to zip, contents are stored in a zip container directly. This type is
// mostly for host-side debugging. When set to both, the two types are both built. Default
// is 'image'.
Payload_type *string
// The type of filesystem to use when the payload_type is 'image'. Either 'ext4', 'f2fs'
// or 'erofs'. Default 'ext4'.
Payload_fs_type *string Payload_fs_type *string
// For telling the APEX to ignore special handling for system libraries such as bionic. // For telling the APEX to ignore special handling for system libraries such as bionic.
@ -216,9 +208,6 @@ type apexBundleProperties struct {
HideFromMake bool `blueprint:"mutated"` HideFromMake bool `blueprint:"mutated"`
// Internal package method for this APEX.
ApexType apexPackaging `blueprint:"mutated"`
// Name that dependencies can specify in their apex_available properties to refer to this module. // Name that dependencies can specify in their apex_available properties to refer to this module.
// If not specified, this defaults to Soong module name. This must be the name of a Soong module. // If not specified, this defaults to Soong module name. This must be the name of a Soong module.
Apex_available_name *string Apex_available_name *string
@ -421,13 +410,6 @@ type apexBundle struct {
testApex bool testApex bool
vndkApex bool vndkApex bool
// Tells whether this variant of the APEX bundle is the primary one or not. Only the primary
// one gets installed to the device.
primaryApexType bool
// Suffix of module name in Android.mk ".apex", ".zipapex", or ""
suffix string
// File system type of apex_payload.img // File system type of apex_payload.img
payloadFsType fsType payloadFsType fsType
@ -1353,88 +1335,26 @@ func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) {
} }
} }
// apexPackaging represents a specific packaging method for an APEX.
type apexPackaging int
const (
// imageApex is a packaging method where contents are included in a filesystem image which
// is then included in a zip container. This is the most typical way of packaging.
imageApex apexPackaging = iota
// zipApex is a packaging method where contents are directly included in the zip container.
// This is used for host-side testing - because the contents are easily accessible by
// unzipping the container.
// TODO(b/279835185) deprecate zipApex
zipApex
)
const ( const (
// File extensions of an APEX for different packaging methods // File extensions of an APEX for different packaging methods
imageApexSuffix = ".apex" imageApexSuffix = ".apex"
imageCapexSuffix = ".capex" imageCapexSuffix = ".capex"
zipApexSuffix = ".zipapex"
// variant names each of which is for a packaging method // variant names each of which is for a packaging method
imageApexType = "image" imageApexType = "image"
zipApexType = "zip"
ext4FsType = "ext4" ext4FsType = "ext4"
f2fsFsType = "f2fs" f2fsFsType = "f2fs"
erofsFsType = "erofs" erofsFsType = "erofs"
) )
// The suffix for the output "file", not the module
func (a apexPackaging) suffix() string {
switch a {
case imageApex:
return imageApexSuffix
case zipApex:
return zipApexSuffix
default:
panic(fmt.Errorf("unknown APEX type %d", a))
}
}
func (a apexPackaging) name() string {
switch a {
case imageApex:
return imageApexType
case zipApex:
return zipApexType
default:
panic(fmt.Errorf("unknown APEX type %d", a))
}
}
// apexPackagingMutator creates one or more variations each of which is for a packaging method. // apexPackagingMutator creates one or more variations each of which is for a packaging method.
func apexPackagingMutator(mctx android.BottomUpMutatorContext) { func apexPackagingMutator(mctx android.BottomUpMutatorContext) {
if !mctx.Module().Enabled() { if !mctx.Module().Enabled() {
return return
} }
if ab, ok := mctx.Module().(*apexBundle); ok { if _, ok := mctx.Module().(*apexBundle); ok {
var variants []string mctx.CreateLocalVariations(imageApexType)
switch proptools.StringDefault(ab.properties.Payload_type, "image") {
case "image":
variants = append(variants, imageApexType)
case "zip":
variants = append(variants, zipApexType)
case "both":
variants = append(variants, imageApexType, zipApexType)
default:
mctx.PropertyErrorf("payload_type", "%q is not one of \"image\", \"zip\", or \"both\".", *ab.properties.Payload_type)
return
}
modules := mctx.CreateLocalVariations(variants...)
for i, v := range variants {
switch v {
case imageApexType:
modules[i].(*apexBundle).properties.ApexType = imageApex
case zipApexType:
modules[i].(*apexBundle).properties.ApexType = zipApex
}
}
} else if _, ok := mctx.Module().(*OverrideApex); ok { } else if _, ok := mctx.Module().(*OverrideApex); ok {
// payload_type is forcibly overridden to "image" // payload_type is forcibly overridden to "image"
// TODO(jiyong): is this the right decision? // TODO(jiyong): is this the right decision?
@ -1945,7 +1865,7 @@ func (f fsType) string() string {
var _ android.MixedBuildBuildable = (*apexBundle)(nil) var _ android.MixedBuildBuildable = (*apexBundle)(nil)
func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool { func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
return a.properties.ApexType == imageApex return true
} }
func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) { func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) {
@ -1966,13 +1886,9 @@ func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
return return
} }
a.setApexTypeAndSuffix(ctx)
a.setPayloadFsType(ctx) a.setPayloadFsType(ctx)
a.setSystemLibLink(ctx) a.setSystemLibLink(ctx)
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
if a.properties.ApexType != zipApex {
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType)
}
bazelCtx := ctx.Config().BazelContext bazelCtx := ctx.Config().BazelContext
outputs, err := bazelCtx.GetApexInfo(a.GetBazelLabel(ctx, a), android.GetConfigKey(ctx)) outputs, err := bazelCtx.GetApexInfo(a.GetBazelLabel(ctx, a), android.GetConfigKey(ctx))
@ -2007,24 +1923,18 @@ func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
// part of a bundled build. // part of a bundled build.
a.makeModulesToInstall = append(a.makeModulesToInstall, outputs.MakeModulesToInstall...) a.makeModulesToInstall = append(a.makeModulesToInstall, outputs.MakeModulesToInstall...)
apexType := a.properties.ApexType a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
switch apexType { a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
case imageApex: a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile) // TODO(b/239084755): Generate the java api using.xml file from Bazel.
a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex)) a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs)) a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles))
// TODO(b/239084755): Generate the java api using.xml file from Bazel. installSuffix := imageApexSuffix
a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex)) if a.isCompressed {
a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles)) installSuffix = imageCapexSuffix
installSuffix := imageApexSuffix
if a.isCompressed {
installSuffix = imageCapexSuffix
}
a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
a.compatSymlinks.Paths()...)
default:
panic(fmt.Errorf("internal error: unexpected apex_type for the ProcessBazelQueryResponse: %v", a.properties.ApexType))
} }
a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
a.compatSymlinks.Paths()...)
// filesInfo in mixed mode must retrieve all information about the apex's // filesInfo in mixed mode must retrieve all information about the apex's
// contents completely from the Starlark providers. It should never rely on // contents completely from the Starlark providers. It should never rely on
@ -2065,9 +1975,7 @@ func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
} }
func (a *apexBundle) setCompression(ctx android.ModuleContext) { func (a *apexBundle) setCompression(ctx android.ModuleContext) {
if a.properties.ApexType != imageApex { if a.testOnlyShouldForceCompression() {
a.isCompressed = false
} else if a.testOnlyShouldForceCompression() {
a.isCompressed = true a.isCompressed = true
} else { } else {
a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable() a.isCompressed = ctx.Config().ApexCompressionEnabled() && a.isCompressable()
@ -2093,7 +2001,7 @@ func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) {
// We don't need the optimization for updatable APEXes, as it might give false signal // We don't need the optimization for updatable APEXes, as it might give false signal
// to the system health when the APEXes are still bundled (b/149805758). // to the system health when the APEXes are still bundled (b/149805758).
if !forced && updatable && a.properties.ApexType == imageApex { if !forced && updatable {
a.linkToSystemLib = false a.linkToSystemLib = false
} }
@ -2116,22 +2024,6 @@ func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) {
} }
} }
func (a *apexBundle) setApexTypeAndSuffix(ctx android.ModuleContext) {
// Set suffix and primaryApexType depending on the ApexType
switch a.properties.ApexType {
case imageApex:
a.suffix = ""
a.primaryApexType = true
case zipApex:
if proptools.String(a.properties.Payload_type) == "zip" {
a.suffix = ""
a.primaryApexType = true
} else {
a.suffix = zipApexSuffix
}
}
}
func (a *apexBundle) isCompressable() bool { func (a *apexBundle) isCompressable() bool {
return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex return proptools.BoolDefault(a.overridableProperties.Compressible, false) && !a.testApex
} }
@ -2621,12 +2513,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.installDir = android.PathForModuleInstall(ctx, "apex") a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = vctx.filesInfo a.filesInfo = vctx.filesInfo
a.setApexTypeAndSuffix(ctx)
a.setPayloadFsType(ctx) a.setPayloadFsType(ctx)
a.setSystemLibLink(ctx) a.setSystemLibLink(ctx)
if a.properties.ApexType != zipApex { a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType)
}
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
// 4) generate the build rules to create the APEX. This is done in builder.go. // 4) generate the build rules to create the APEX. This is done in builder.go.

View file

@ -819,57 +819,6 @@ func TestFileContexts(t *testing.T) {
} }
} }
func TestBasicZipApex(t *testing.T) {
ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
payload_type: "zip",
native_shared_libs: ["mylib"],
updatable: false,
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
shared_libs: ["mylib2"],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
}
cc_library {
name: "mylib2",
srcs: ["mylib.cpp"],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
}
`)
zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex_zip").Rule("zipApexRule")
copyCmds := zipApexRule.Args["copy_commands"]
// Ensure that main rule creates an output
ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
// Ensure that APEX variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that APEX variant is created for the indirect dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
}
func TestApexWithStubs(t *testing.T) { func TestApexWithStubs(t *testing.T) {
ctx := testApex(t, ` ctx := testApex(t, `
apex { apex {
@ -3657,10 +3606,6 @@ func getFiles(t *testing.T, ctx *android.TestContext, moduleName, variant string
module := ctx.ModuleForTests(moduleName, variant) module := ctx.ModuleForTests(moduleName, variant)
apexRule := module.MaybeRule("apexRule") apexRule := module.MaybeRule("apexRule")
apexDir := "/image.apex/" apexDir := "/image.apex/"
if apexRule.Rule == nil {
apexRule = module.Rule("zipApexRule")
apexDir = "/image.zipapex/"
}
copyCmds := apexRule.Args["copy_commands"] copyCmds := apexRule.Args["copy_commands"]
var ret []fileInApex var ret []fileInApex
for _, cmd := range strings.Split(copyCmds, "&&") { for _, cmd := range strings.Split(copyCmds, "&&") {
@ -9554,28 +9499,6 @@ func TestPrebuiltStubLibDep(t *testing.T) {
} }
} }
func TestHostApexInHostOnlyBuild(t *testing.T) {
testApex(t, `
apex {
name: "myapex",
host_supported: true,
key: "myapex.key",
updatable: false,
payload_type: "zip",
}
apex_key {
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
`,
android.FixtureModifyConfig(func(config android.Config) {
// We may not have device targets in all builds, e.g. in
// prebuilts/build-tools/build-prebuilts.sh
config.Targets[android.Android] = []android.Target{}
}))
}
func TestApexJavaCoverage(t *testing.T) { func TestApexJavaCoverage(t *testing.T) {
bp := ` bp := `
apex { apex {

View file

@ -179,19 +179,6 @@ var (
}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key",
"opt_flags", "manifest", "libs_to_trim") "opt_flags", "manifest", "libs_to_trim")
zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
`(. ${out}.copy_commands) && ` +
`APEXER_TOOL_PATH=${tool_path} ` +
`${apexer} --force --manifest ${manifest} ` +
`--payload_type zip ` +
`${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
Rspfile: "${out}.copy_commands",
RspfileContent: "${copy_commands}",
Description: "ZipAPEX ${image_dir} => ${out}",
}, "tool_path", "image_dir", "copy_commands", "manifest")
apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule", apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
blueprint.RuleParams{ blueprint.RuleParams{
Command: `${aapt2} convert --output-format proto $in -o $out`, Command: `${aapt2} convert --output-format proto $in -o $out`,
@ -369,21 +356,16 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Output
// even though VNDK APEX is supposed to be installed on /system. (See com.android.vndk.current.on_vendor) // even though VNDK APEX is supposed to be installed on /system. (See com.android.vndk.current.on_vendor)
forceLabel = "u:object_r:vendor_apex_metadata_file:s0" forceLabel = "u:object_r:vendor_apex_metadata_file:s0"
} }
switch a.properties.ApexType { // remove old file
case imageApex: rule.Command().Text("rm").FlagWithOutput("-f ", output)
// remove old file // copy file_contexts
rule.Command().Text("rm").FlagWithOutput("-f ", output) rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
// copy file_contexts // new line
rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output) rule.Command().Text("echo").Text(">>").Output(output)
// new line if !useFileContextsAsIs {
rule.Command().Text("echo").Text(">>").Output(output) // force-label /apex_manifest.pb and /
if !useFileContextsAsIs { rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(forceLabel).Text(">>").Output(output)
// force-label /apex_manifest.pb and / rule.Command().Text("echo").Text("/").Text(forceLabel).Text(">>").Output(output)
rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(forceLabel).Text(">>").Output(output)
rule.Command().Text("echo").Text("/").Text(forceLabel).Text(">>").Output(output)
}
default:
panic(fmt.Errorf("unsupported type %v", a.properties.ApexType))
} }
rule.Build("file_contexts."+a.Name(), "Generate file_contexts") rule.Build("file_contexts."+a.Name(), "Generate file_contexts")
@ -464,8 +446,7 @@ func markManifestTestOnly(ctx android.ModuleContext, androidManifestFile android
// buildApex creates build rules to build an APEX using apexer. // buildApex creates build rules to build an APEX using apexer.
func (a *apexBundle) buildApex(ctx android.ModuleContext) { func (a *apexBundle) buildApex(ctx android.ModuleContext) {
apexType := a.properties.ApexType suffix := imageApexSuffix
suffix := apexType.suffix()
apexName := a.BaseModuleName() apexName := a.BaseModuleName()
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
@ -604,263 +585,247 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
outHostBinDir := ctx.Config().HostToolPath(ctx, "").String() outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
if apexType == imageApex { ////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
cannedFsConfig := a.buildCannedFsConfig(ctx)
implicitInputs = append(implicitInputs, cannedFsConfig)
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files // Step 3: Prepare option flags for apexer and invoke it to create an unsigned APEX.
// in this APEX. The file will be used by apexer in later steps. // TODO(jiyong): use the RuleBuilder
cannedFsConfig := a.buildCannedFsConfig(ctx) optFlags := []string{}
implicitInputs = append(implicitInputs, cannedFsConfig)
//////////////////////////////////////////////////////////////////////////////////// fileContexts := a.buildFileContexts(ctx)
// Step 3: Prepare option flags for apexer and invoke it to create an unsigned APEX. implicitInputs = append(implicitInputs, fileContexts)
// TODO(jiyong): use the RuleBuilder
optFlags := []string{}
fileContexts := a.buildFileContexts(ctx) implicitInputs = append(implicitInputs, a.privateKeyFile, a.publicKeyFile)
implicitInputs = append(implicitInputs, fileContexts) optFlags = append(optFlags, "--pubkey "+a.publicKeyFile.String())
implicitInputs = append(implicitInputs, a.privateKeyFile, a.publicKeyFile) manifestPackageName := a.getOverrideManifestPackageName(ctx)
optFlags = append(optFlags, "--pubkey "+a.publicKeyFile.String()) if manifestPackageName != "" {
optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName)
}
manifestPackageName := a.getOverrideManifestPackageName(ctx) if a.properties.AndroidManifest != nil {
if manifestPackageName != "" { androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest))
optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName)
if a.testApex {
androidManifestFile = markManifestTestOnly(ctx, androidManifestFile)
} }
if a.properties.AndroidManifest != nil { implicitInputs = append(implicitInputs, androidManifestFile)
androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest)) optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
} else if a.testApex {
optFlags = append(optFlags, "--test_only")
}
if a.testApex { // Determine target/min sdk version from the context
androidManifestFile = markManifestTestOnly(ctx, androidManifestFile) // TODO(jiyong): make this as a function
} moduleMinSdkVersion := a.minSdkVersion(ctx)
minSdkVersion := moduleMinSdkVersion.String()
implicitInputs = append(implicitInputs, androidManifestFile) // bundletool doesn't understand what "current" is. We need to transform it to
optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) // codename
} else if a.testApex { if moduleMinSdkVersion.IsCurrent() || moduleMinSdkVersion.IsNone() {
optFlags = append(optFlags, "--test_only") minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
}
// Determine target/min sdk version from the context
// TODO(jiyong): make this as a function
moduleMinSdkVersion := a.minSdkVersion(ctx)
minSdkVersion := moduleMinSdkVersion.String()
// bundletool doesn't understand what "current" is. We need to transform it to
// codename
if moduleMinSdkVersion.IsCurrent() || moduleMinSdkVersion.IsNone() {
minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
if java.UseApiFingerprint(ctx) {
minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
}
}
// apex module doesn't have a concept of target_sdk_version, hence for the time
// being targetSdkVersion == default targetSdkVersion of the branch.
targetSdkVersion := strconv.Itoa(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt())
if java.UseApiFingerprint(ctx) { if java.UseApiFingerprint(ctx) {
targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String()) minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx)) implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
} }
optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion) }
optFlags = append(optFlags, "--min_sdk_version "+minSdkVersion) // apex module doesn't have a concept of target_sdk_version, hence for the time
// being targetSdkVersion == default targetSdkVersion of the branch.
targetSdkVersion := strconv.Itoa(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt())
if a.overridableProperties.Logging_parent != "" { if java.UseApiFingerprint(ctx) {
optFlags = append(optFlags, "--logging_parent ", a.overridableProperties.Logging_parent) targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String())
} implicitInputs = append(implicitInputs, java.ApiFingerprintPath(ctx))
}
optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion)
optFlags = append(optFlags, "--min_sdk_version "+minSdkVersion)
// Create a NOTICE file, and embed it as an asset file in the APEX. if a.overridableProperties.Logging_parent != "" {
htmlGzNotice := android.PathForModuleOut(ctx, "NOTICE.html.gz") optFlags = append(optFlags, "--logging_parent ", a.overridableProperties.Logging_parent)
android.BuildNoticeHtmlOutputFromLicenseMetadata( }
ctx, htmlGzNotice, "", "",
[]string{
android.PathForModuleInstall(ctx).String() + "/",
android.PathForModuleInPartitionInstall(ctx, "apex").String() + "/",
})
noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("cp").
Input(htmlGzNotice).
Output(noticeAssetPath)
builder.Build("notice_dir", "Building notice dir")
implicitInputs = append(implicitInputs, noticeAssetPath)
optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeAssetPath.String()))
// Apexes which are supposed to be installed in builtin dirs(/system, etc) // Create a NOTICE file, and embed it as an asset file in the APEX.
// don't need hashtree for activation. Therefore, by removing hashtree from htmlGzNotice := android.PathForModuleOut(ctx, "NOTICE.html.gz")
// apex bundle (filesystem image in it, to be specific), we can save storage. android.BuildNoticeHtmlOutputFromLicenseMetadata(
needHashTree := moduleMinSdkVersion.LessThanOrEqualTo(android.SdkVersion_Android10) || ctx, htmlGzNotice, "", "",
a.shouldGenerateHashtree() []string{
if ctx.Config().ApexCompressionEnabled() && a.isCompressable() { android.PathForModuleInstall(ctx).String() + "/",
needHashTree = true android.PathForModuleInPartitionInstall(ctx, "apex").String() + "/",
}
if !needHashTree {
optFlags = append(optFlags, "--no_hashtree")
}
if a.testOnlyShouldSkipPayloadSign() {
optFlags = append(optFlags, "--unsigned_payload")
}
if moduleMinSdkVersion == android.SdkVersion_Android10 {
implicitInputs = append(implicitInputs, a.manifestJsonOut)
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
}
optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string())
if a.dynamic_common_lib_apex() {
ctx.Build(pctx, android.BuildParams{
Rule: DCLAApexRule,
Implicits: implicitInputs,
Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")",
Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
},
})
} else if ctx.Config().ApexTrimEnabled() && len(a.libs_to_trim(ctx)) > 0 {
ctx.Build(pctx, android.BuildParams{
Rule: TrimmedApexRule,
Implicits: implicitInputs,
Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")",
Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
"libs_to_trim": strings.Join(a.libs_to_trim(ctx), ","),
},
})
} else {
ctx.Build(pctx, android.BuildParams{
Rule: apexRule,
Implicits: implicitInputs,
Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")",
Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
},
})
}
// TODO(jiyong): make the two rules below as separate functions
apexProtoFile := android.PathForModuleOut(ctx, a.Name()+".pb"+suffix)
bundleModuleFile := android.PathForModuleOut(ctx, a.Name()+suffix+"-base.zip")
a.bundleModuleFile = bundleModuleFile
ctx.Build(pctx, android.BuildParams{
Rule: apexProtoConvertRule,
Input: unsignedOutputFile,
Output: apexProtoFile,
Description: "apex proto convert",
}) })
noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("cp").
Input(htmlGzNotice).
Output(noticeAssetPath)
builder.Build("notice_dir", "Building notice dir")
implicitInputs = append(implicitInputs, noticeAssetPath)
optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeAssetPath.String()))
implicitInputs = append(implicitInputs, unsignedOutputFile) // Apexes which are supposed to be installed in builtin dirs(/system, etc)
// don't need hashtree for activation. Therefore, by removing hashtree from
// apex bundle (filesystem image in it, to be specific), we can save storage.
needHashTree := moduleMinSdkVersion.LessThanOrEqualTo(android.SdkVersion_Android10) ||
a.shouldGenerateHashtree()
if ctx.Config().ApexCompressionEnabled() && a.isCompressable() {
needHashTree = true
}
if !needHashTree {
optFlags = append(optFlags, "--no_hashtree")
}
// Run coverage analysis if a.testOnlyShouldSkipPayloadSign() {
apisUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.txt") optFlags = append(optFlags, "--unsigned_payload")
}
if moduleMinSdkVersion == android.SdkVersion_Android10 {
implicitInputs = append(implicitInputs, a.manifestJsonOut)
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
}
optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string())
if a.dynamic_common_lib_apex() {
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: generateAPIsUsedbyApexRule, Rule: DCLAApexRule,
Implicits: implicitInputs,
Description: "coverage",
Output: apisUsedbyOutputFile,
Args: map[string]string{
"image_dir": imageDir.String(),
"readelf": "${config.ClangBin}/llvm-readelf",
},
})
a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
var nativeLibNames []string
for _, f := range a.filesInfo {
if f.class == nativeSharedLib {
nativeLibNames = append(nativeLibNames, f.stem())
}
}
apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
Output(apisBackedbyOutputFile).
Flags(nativeLibNames)
rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
var javaLibOrApkPath []android.Path
for _, f := range a.filesInfo {
if f.class == javaSharedLib || f.class == app {
javaLibOrApkPath = append(javaLibOrApkPath, f.builtFile)
}
}
javaApiUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.xml")
javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
javaUsedByRule.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
BuiltTool("dexdeps").
Output(javaApiUsedbyOutputFile).
Inputs(javaLibOrApkPath)
javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
bundleConfig := a.buildBundleConfig(ctx)
var abis []string
for _, target := range ctx.MultiTargets() {
if len(target.Arch.Abi) > 0 {
abis = append(abis, target.Arch.Abi[0])
}
}
abis = android.FirstUniqueStrings(abis)
ctx.Build(pctx, android.BuildParams{
Rule: apexBundleRule,
Input: apexProtoFile,
Implicit: bundleConfig,
Output: a.bundleModuleFile,
Description: "apex bundle module",
Args: map[string]string{
"abi": strings.Join(abis, "."),
"config": bundleConfig.String(),
},
})
} else { // zipApex
ctx.Build(pctx, android.BuildParams{
Rule: zipApexRule,
Implicits: implicitInputs, Implicits: implicitInputs,
Output: unsignedOutputFile, Output: unsignedOutputFile,
Description: "apex (" + apexType.name() + ")", Description: "apex",
Args: map[string]string{ Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(), "image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "), "copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(), "manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
},
})
} else if ctx.Config().ApexTrimEnabled() && len(a.libs_to_trim(ctx)) > 0 {
ctx.Build(pctx, android.BuildParams{
Rule: TrimmedApexRule,
Implicits: implicitInputs,
Output: unsignedOutputFile,
Description: "apex",
Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
"libs_to_trim": strings.Join(a.libs_to_trim(ctx), ","),
},
})
} else {
ctx.Build(pctx, android.BuildParams{
Rule: apexRule,
Implicits: implicitInputs,
Output: unsignedOutputFile,
Description: "apex",
Args: map[string]string{
"tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
"image_dir": imageDir.String(),
"copy_commands": strings.Join(copyCommands, " && "),
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
"key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
}, },
}) })
} }
// TODO(jiyong): make the two rules below as separate functions
apexProtoFile := android.PathForModuleOut(ctx, a.Name()+".pb"+suffix)
bundleModuleFile := android.PathForModuleOut(ctx, a.Name()+suffix+"-base.zip")
a.bundleModuleFile = bundleModuleFile
ctx.Build(pctx, android.BuildParams{
Rule: apexProtoConvertRule,
Input: unsignedOutputFile,
Output: apexProtoFile,
Description: "apex proto convert",
})
implicitInputs = append(implicitInputs, unsignedOutputFile)
// Run coverage analysis
apisUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.txt")
ctx.Build(pctx, android.BuildParams{
Rule: generateAPIsUsedbyApexRule,
Implicits: implicitInputs,
Description: "coverage",
Output: apisUsedbyOutputFile,
Args: map[string]string{
"image_dir": imageDir.String(),
"readelf": "${config.ClangBin}/llvm-readelf",
},
})
a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
var nativeLibNames []string
for _, f := range a.filesInfo {
if f.class == nativeSharedLib {
nativeLibNames = append(nativeLibNames, f.stem())
}
}
apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
rb := android.NewRuleBuilder(pctx, ctx)
rb.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
Output(apisBackedbyOutputFile).
Flags(nativeLibNames)
rb.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
var javaLibOrApkPath []android.Path
for _, f := range a.filesInfo {
if f.class == javaSharedLib || f.class == app {
javaLibOrApkPath = append(javaLibOrApkPath, f.builtFile)
}
}
javaApiUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.xml")
javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
javaUsedByRule.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
BuiltTool("dexdeps").
Output(javaApiUsedbyOutputFile).
Inputs(javaLibOrApkPath)
javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
bundleConfig := a.buildBundleConfig(ctx)
var abis []string
for _, target := range ctx.MultiTargets() {
if len(target.Arch.Abi) > 0 {
abis = append(abis, target.Arch.Abi[0])
}
}
abis = android.FirstUniqueStrings(abis)
ctx.Build(pctx, android.BuildParams{
Rule: apexBundleRule,
Input: apexProtoFile,
Implicit: bundleConfig,
Output: a.bundleModuleFile,
Description: "apex bundle module",
Args: map[string]string{
"abi": strings.Join(abis, "."),
"config": bundleConfig.String(),
},
})
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
// Step 4: Sign the APEX using signapk // Step 4: Sign the APEX using signapk
signedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix) signedOutputFile := android.PathForModuleOut(ctx, a.Name()+suffix)
@ -987,10 +952,6 @@ func (a *apexBundle) getOverrideManifestPackageName(ctx android.ModuleContext) s
} }
func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
if !a.primaryApexType {
return
}
if a.properties.IsCoverageVariant { if a.properties.IsCoverageVariant {
// Otherwise, we will have duplicated rules for coverage and // Otherwise, we will have duplicated rules for coverage and
// non-coverage variants of the same APEX // non-coverage variants of the same APEX

View file

@ -781,10 +781,10 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.initApexFilesForAndroidMk(ctx) p.initApexFilesForAndroidMk(ctx)
// in case that prebuilt_apex replaces source apex (using prefer: prop) // in case that prebuilt_apex replaces source apex (using prefer: prop)
p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx, true) p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx)
// or that prebuilt_apex overrides other apexes (using overrides: prop) // or that prebuilt_apex overrides other apexes (using overrides: prop)
for _, overridden := range p.prebuiltCommonProperties.Overrides { for _, overridden := range p.prebuiltCommonProperties.Overrides {
p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
} }
if p.installable() { if p.installable() {
@ -1006,10 +1006,10 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} }
// in case that apex_set replaces source apex (using prefer: prop) // in case that apex_set replaces source apex (using prefer: prop)
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, true) a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
// or that apex_set overrides other apexes (using overrides: prop) // or that apex_set overrides other apexes (using overrides: prop)
for _, overridden := range a.prebuiltCommonProperties.Overrides { for _, overridden := range a.prebuiltCommonProperties.Overrides {
a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
} }
} }

View file

@ -112,14 +112,10 @@ func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
} }
// name is module.BaseModuleName() which is used as LOCAL_MODULE_NAME and also LOCAL_OVERRIDES_* // name is module.BaseModuleName() which is used as LOCAL_MODULE_NAME and also LOCAL_OVERRIDES_*
func makeCompatSymlinks(name string, ctx android.ModuleContext, primaryApex bool) (symlinks android.InstallPaths) { func makeCompatSymlinks(name string, ctx android.ModuleContext) (symlinks android.InstallPaths) {
// small helper to add symlink commands // small helper to add symlink commands
addSymlink := func(target string, dir android.InstallPath, linkName string) { addSymlink := func(target string, dir android.InstallPath, linkName string) {
if primaryApex { symlinks = append(symlinks, ctx.InstallAbsoluteSymlink(dir, linkName, target))
symlinks = append(symlinks, ctx.InstallAbsoluteSymlink(dir, linkName, target))
} else {
symlinks = append(symlinks, dir.Join(ctx, linkName))
}
} }
// TODO(b/142911355): [VNDK APEX] Fix hard-coded references to /system/lib/vndk // TODO(b/142911355): [VNDK APEX] Fix hard-coded references to /system/lib/vndk