Loading apex/apex.go +233 −92 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ var ( `${apexer} --force --manifest ${manifest} ` + `--file_contexts ${file_contexts} ` + `--canned_fs_config ${canned_fs_config} ` + `--payload_type image ` + `--key ${key} ${image_dir} ${out} `, CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", Loading @@ -62,6 +63,17 @@ var ( Description: "APEX ${image_dir} => ${out}", }, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key") zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + `(${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}"}, Description: "ZipAPEX ${image_dir} => ${out}", }, "tool_path", "image_dir", "copy_commands", "manifest") apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule", blueprint.RuleParams{ Command: `${aapt2} convert --output-format proto $in -o $out`, Loading @@ -78,7 +90,11 @@ var ( }, "abi") ) var apexSuffix = ".apex" var imageApexSuffix = ".apex" var zipApexSuffix = ".zipapex" var imageApexType = "image" var zipApexType = "zip" type dependencyTag struct { blueprint.BaseDependencyTag Loading Loading @@ -199,6 +215,10 @@ type apexBundleProperties struct { // Name of the apex_key module that provides the private key to sign APEX Key *string // The type of APEX to build. Controls what the APEX payload is. Either // 'image', 'zip' or 'both'. Default: 'image'. Payload_type *string // The name of a certificate in the default certificate directory, blank to use the default product certificate, // or an android_app_certificate module name in the form ":module". Certificate *string Loading Loading @@ -246,6 +266,56 @@ const ( javaSharedLib ) type apexPackaging int const ( imageApex apexPackaging = iota zipApex both ) func (a apexPackaging) image() bool { switch a { case imageApex, both: return true } return false } func (a apexPackaging) zip() bool { switch a { case zipApex, both: return true } return false } func (a apexPackaging) suffix() string { switch a { case imageApex: return imageApexSuffix case zipApex: return zipApexSuffix case both: panic(fmt.Errorf("must be either zip or image")) default: panic(fmt.Errorf("unkonwn APEX type %d", a)) } } func (a apexPackaging) name() string { switch a { case imageApex: return imageApexType case zipApex: return zipApexType case both: panic(fmt.Errorf("must be either zip or image")) default: panic(fmt.Errorf("unkonwn APEX type %d", a)) } } func (class apexFileClass) NameInMake() string { switch class { case etc: Loading Loading @@ -275,8 +345,10 @@ type apexBundle struct { properties apexBundleProperties apexTypes apexPackaging bundleModuleFile android.WritablePath outputFile android.WritablePath outputFiles map[apexPackaging]android.WritablePath installDir android.OutputPath // list of files to be included in this apex Loading Loading @@ -425,6 +497,17 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { var keyFile android.Path var certificate java.Certificate if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" { a.apexTypes = imageApex } else if *a.properties.Payload_type == "zip" { a.apexTypes = zipApex } else if *a.properties.Payload_type == "both" { a.apexTypes = both } else { ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type) return } ctx.WalkDeps(func(child, parent android.Module) bool { if _, ok := parent.(*apexBundle); ok { // direct dependencies Loading Loading @@ -532,14 +615,20 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() a.installDir = android.PathForModuleInstall(ctx, "apex") a.filesInfo = filesInfo if a.apexTypes.zip() { a.buildUnflattenedApex(ctx, keyFile, certificate, zipApex) } if a.apexTypes.image() { if ctx.Config().FlattenApex() { a.buildFlattenedApex(ctx) } else { a.buildUnflattenedApex(ctx, keyFile, certificate) a.buildUnflattenedApex(ctx, keyFile, certificate, imageApex) } } } func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate) { func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate, apexType apexPackaging) { cert := String(a.properties.Certificate) if cert != "" && android.SrcIsModule(cert) == "" { defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) Loading @@ -552,7 +641,40 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and certificate = java.Certificate{pem, key} } // files and dirs that will be created in apex manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) 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) suffix := apexType.suffix() unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned") filesToCopy := []android.Path{} for _, f := range a.filesInfo { filesToCopy = append(filesToCopy, f.builtFile) } copyCommands := []string{} for i, src := range filesToCopy { dest := filepath.Join(a.filesInfo[i].installDir, src.Base()) 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) } implicitInputs := append(android.Paths(nil), filesToCopy...) implicitInputs = append(implicitInputs, manifest) outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") if apexType.image() { // files and dirs that will be created in APEX var readOnlyPaths []string var executablePaths []string // this also includes dirs for _, f := range a.filesInfo { Loading @@ -579,8 +701,6 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and }, }) manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName()) fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts" fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath) Loading @@ -590,32 +710,17 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and } fileContexts := fileContextsOptionalPath.Path() unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix+".unsigned") // Additional implicit inputs. implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, keyFile) filesToCopy := []android.Path{} for _, f := range a.filesInfo { filesToCopy = append(filesToCopy, f.builtFile) } copyCommands := []string{} for i, src := range filesToCopy { dest := filepath.Join(a.filesInfo[i].installDir, src.Base()) dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").String(), dest) copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path)) copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path) } implicitInputs := append(android.Paths(nil), filesToCopy...) implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile) outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") ctx.Build(pctx, android.BuildParams{ Rule: apexRule, Implicits: implicitInputs, Output: unsignedOutputFile, Description: "apex", Description: "apex (" + apexType.name() + ")", Args: map[string]string{ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "image_dir": android.PathForModuleOut(ctx, "image").String(), "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), "copy_commands": strings.Join(copyCommands, " && "), "manifest": manifest.String(), "file_contexts": fileContexts.String(), Loading @@ -624,14 +729,8 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and }, }) var abis []string for _, target := range ctx.MultiTargets() { abis = append(abis, target.Arch.Abi[0]) } abis = android.FirstUniqueStrings(abis) apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+apexSuffix) bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-base.zip") apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix) bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip") a.bundleModuleFile = bundleModuleFile ctx.Build(pctx, android.BuildParams{ Loading @@ -644,24 +743,41 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and ctx.Build(pctx, android.BuildParams{ Rule: apexBundleRule, Input: apexProtoFile, Output: bundleModuleFile, Output: a.bundleModuleFile, Description: "apex bundle module", Args: map[string]string{ "abi": strings.Join(abis, "."), }, }) } else { ctx.Build(pctx, android.BuildParams{ Rule: zipApexRule, Implicits: implicitInputs, Output: unsignedOutputFile, Description: "apex (" + apexType.name() + ")", Args: map[string]string{ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), "copy_commands": strings.Join(copyCommands, " && "), "manifest": manifest.String(), }, }) } a.outputFile = android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix) a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix) ctx.Build(pctx, android.BuildParams{ Rule: java.Signapk, Description: "signapk", Output: a.outputFile, Output: a.outputFiles[apexType], Input: unsignedOutputFile, Args: map[string]string{ "certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "), "flags": "-a 4096", //alignment }, }) // Install to $OUT/soong/{target,host}/.../apex ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType]) } func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { Loading @@ -677,7 +793,24 @@ func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { } func (a *apexBundle) AndroidMk() android.AndroidMkData { if a.flattened { writers := []android.AndroidMkData{} if a.apexTypes.image() { writers = append(writers, a.androidMkForType(imageApex)) } if a.apexTypes.zip() { writers = append(writers, a.androidMkForType(zipApex)) } return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { for _, data := range writers { data.Custom(w, name, prefix, moduleDir, data) } }} } func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData { // Only image APEXes can be flattened. if a.flattened && apexType.image() { return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { moduleNames := []string{} Loading Loading @@ -716,29 +849,37 @@ func (a *apexBundle) AndroidMk() android.AndroidMkData { } else { return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { // zip-apex is the less common type so have the name refer to the image-apex // only and use {name}.zip if you want the zip-apex if apexType == zipApex && a.apexTypes == both { name = name + ".zip" } fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name) 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.outputFiles[apexType].String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString())) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexType.suffix()) fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key)) fmt.Fprintln(w, "include $(BUILD_PREBUILT)") if apexType == imageApex { fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String()) } }} } } func apexBundleFactory() android.Module { module := &apexBundle{} module := &apexBundle{ outputFiles: map[apexPackaging]android.WritablePath{}, } module.AddProperties(&module.properties) module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { return class == android.Device && ctx.Config().DevicePrefer32BitExecutables() }) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) return module } apex/apex_test.go +57 −9 Original line number Diff line number Diff line Loading @@ -188,8 +188,56 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex") // Ensure that both direct and indirect deps are copied into apex ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image/lib64/mylib2.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") } func TestBasicZipApex(t *testing.T) { ctx := testApex(t, ` apex { name: "myapex", key: "myapex.key", payload_type: "zip", native_shared_libs: ["mylib"], } 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", } cc_library { name: "mylib2", srcs: ["mylib.cpp"], system_shared_libs: [], stl: "none", } `) zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").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_myapex") // Ensure that APEX variant is created for the indirect dep ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex") // 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) { Loading Loading @@ -239,13 +287,13 @@ func TestApexWithStubs(t *testing.T) { copyCmds := apexRule.Args["copy_commands"] // Ensure that direct non-stubs dep is always included ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") // Ensure that indirect stubs dep is not included ensureNotContains(t, copyCmds, "image/lib64/mylib2.so") ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") // Ensure that direct stubs dep is included ensureContains(t, copyCmds, "image/lib64/mylib3.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so") mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"] Loading Loading @@ -326,12 +374,12 @@ func TestApexWithSystemLibsStubs(t *testing.T) { copyCmds := apexRule.Args["copy_commands"] // Ensure that mylib, libm, libdl are included. ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image/lib64/libm.so") ensureContains(t, copyCmds, "image/lib64/libdl.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/libm.so") ensureContains(t, copyCmds, "image.apex/lib64/libdl.so") // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs) ensureNotContains(t, copyCmds, "image/lib64/libc.so") ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so") mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"] mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] Loading Loading
apex/apex.go +233 −92 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ var ( `${apexer} --force --manifest ${manifest} ` + `--file_contexts ${file_contexts} ` + `--canned_fs_config ${canned_fs_config} ` + `--payload_type image ` + `--key ${key} ${image_dir} ${out} `, CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", Loading @@ -62,6 +63,17 @@ var ( Description: "APEX ${image_dir} => ${out}", }, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key") zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + `(${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}"}, Description: "ZipAPEX ${image_dir} => ${out}", }, "tool_path", "image_dir", "copy_commands", "manifest") apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule", blueprint.RuleParams{ Command: `${aapt2} convert --output-format proto $in -o $out`, Loading @@ -78,7 +90,11 @@ var ( }, "abi") ) var apexSuffix = ".apex" var imageApexSuffix = ".apex" var zipApexSuffix = ".zipapex" var imageApexType = "image" var zipApexType = "zip" type dependencyTag struct { blueprint.BaseDependencyTag Loading Loading @@ -199,6 +215,10 @@ type apexBundleProperties struct { // Name of the apex_key module that provides the private key to sign APEX Key *string // The type of APEX to build. Controls what the APEX payload is. Either // 'image', 'zip' or 'both'. Default: 'image'. Payload_type *string // The name of a certificate in the default certificate directory, blank to use the default product certificate, // or an android_app_certificate module name in the form ":module". Certificate *string Loading Loading @@ -246,6 +266,56 @@ const ( javaSharedLib ) type apexPackaging int const ( imageApex apexPackaging = iota zipApex both ) func (a apexPackaging) image() bool { switch a { case imageApex, both: return true } return false } func (a apexPackaging) zip() bool { switch a { case zipApex, both: return true } return false } func (a apexPackaging) suffix() string { switch a { case imageApex: return imageApexSuffix case zipApex: return zipApexSuffix case both: panic(fmt.Errorf("must be either zip or image")) default: panic(fmt.Errorf("unkonwn APEX type %d", a)) } } func (a apexPackaging) name() string { switch a { case imageApex: return imageApexType case zipApex: return zipApexType case both: panic(fmt.Errorf("must be either zip or image")) default: panic(fmt.Errorf("unkonwn APEX type %d", a)) } } func (class apexFileClass) NameInMake() string { switch class { case etc: Loading Loading @@ -275,8 +345,10 @@ type apexBundle struct { properties apexBundleProperties apexTypes apexPackaging bundleModuleFile android.WritablePath outputFile android.WritablePath outputFiles map[apexPackaging]android.WritablePath installDir android.OutputPath // list of files to be included in this apex Loading Loading @@ -425,6 +497,17 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { var keyFile android.Path var certificate java.Certificate if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" { a.apexTypes = imageApex } else if *a.properties.Payload_type == "zip" { a.apexTypes = zipApex } else if *a.properties.Payload_type == "both" { a.apexTypes = both } else { ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type) return } ctx.WalkDeps(func(child, parent android.Module) bool { if _, ok := parent.(*apexBundle); ok { // direct dependencies Loading Loading @@ -532,14 +615,20 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() a.installDir = android.PathForModuleInstall(ctx, "apex") a.filesInfo = filesInfo if a.apexTypes.zip() { a.buildUnflattenedApex(ctx, keyFile, certificate, zipApex) } if a.apexTypes.image() { if ctx.Config().FlattenApex() { a.buildFlattenedApex(ctx) } else { a.buildUnflattenedApex(ctx, keyFile, certificate) a.buildUnflattenedApex(ctx, keyFile, certificate, imageApex) } } } func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate) { func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate, apexType apexPackaging) { cert := String(a.properties.Certificate) if cert != "" && android.SrcIsModule(cert) == "" { defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) Loading @@ -552,7 +641,40 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and certificate = java.Certificate{pem, key} } // files and dirs that will be created in apex manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) 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) suffix := apexType.suffix() unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned") filesToCopy := []android.Path{} for _, f := range a.filesInfo { filesToCopy = append(filesToCopy, f.builtFile) } copyCommands := []string{} for i, src := range filesToCopy { dest := filepath.Join(a.filesInfo[i].installDir, src.Base()) 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) } implicitInputs := append(android.Paths(nil), filesToCopy...) implicitInputs = append(implicitInputs, manifest) outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") if apexType.image() { // files and dirs that will be created in APEX var readOnlyPaths []string var executablePaths []string // this also includes dirs for _, f := range a.filesInfo { Loading @@ -579,8 +701,6 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and }, }) manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")) fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName()) fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts" fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath) Loading @@ -590,32 +710,17 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and } fileContexts := fileContextsOptionalPath.Path() unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix+".unsigned") // Additional implicit inputs. implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, keyFile) filesToCopy := []android.Path{} for _, f := range a.filesInfo { filesToCopy = append(filesToCopy, f.builtFile) } copyCommands := []string{} for i, src := range filesToCopy { dest := filepath.Join(a.filesInfo[i].installDir, src.Base()) dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").String(), dest) copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path)) copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path) } implicitInputs := append(android.Paths(nil), filesToCopy...) implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile) outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") ctx.Build(pctx, android.BuildParams{ Rule: apexRule, Implicits: implicitInputs, Output: unsignedOutputFile, Description: "apex", Description: "apex (" + apexType.name() + ")", Args: map[string]string{ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "image_dir": android.PathForModuleOut(ctx, "image").String(), "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), "copy_commands": strings.Join(copyCommands, " && "), "manifest": manifest.String(), "file_contexts": fileContexts.String(), Loading @@ -624,14 +729,8 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and }, }) var abis []string for _, target := range ctx.MultiTargets() { abis = append(abis, target.Arch.Abi[0]) } abis = android.FirstUniqueStrings(abis) apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+apexSuffix) bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-base.zip") apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix) bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip") a.bundleModuleFile = bundleModuleFile ctx.Build(pctx, android.BuildParams{ Loading @@ -644,24 +743,41 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile and ctx.Build(pctx, android.BuildParams{ Rule: apexBundleRule, Input: apexProtoFile, Output: bundleModuleFile, Output: a.bundleModuleFile, Description: "apex bundle module", Args: map[string]string{ "abi": strings.Join(abis, "."), }, }) } else { ctx.Build(pctx, android.BuildParams{ Rule: zipApexRule, Implicits: implicitInputs, Output: unsignedOutputFile, Description: "apex (" + apexType.name() + ")", Args: map[string]string{ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(), "copy_commands": strings.Join(copyCommands, " && "), "manifest": manifest.String(), }, }) } a.outputFile = android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix) a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix) ctx.Build(pctx, android.BuildParams{ Rule: java.Signapk, Description: "signapk", Output: a.outputFile, Output: a.outputFiles[apexType], Input: unsignedOutputFile, Args: map[string]string{ "certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "), "flags": "-a 4096", //alignment }, }) // Install to $OUT/soong/{target,host}/.../apex ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType]) } func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { Loading @@ -677,7 +793,24 @@ func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { } func (a *apexBundle) AndroidMk() android.AndroidMkData { if a.flattened { writers := []android.AndroidMkData{} if a.apexTypes.image() { writers = append(writers, a.androidMkForType(imageApex)) } if a.apexTypes.zip() { writers = append(writers, a.androidMkForType(zipApex)) } return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { for _, data := range writers { data.Custom(w, name, prefix, moduleDir, data) } }} } func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData { // Only image APEXes can be flattened. if a.flattened && apexType.image() { return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { moduleNames := []string{} Loading Loading @@ -716,29 +849,37 @@ func (a *apexBundle) AndroidMk() android.AndroidMkData { } else { return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { // zip-apex is the less common type so have the name refer to the image-apex // only and use {name}.zip if you want the zip-apex if apexType == zipApex && a.apexTypes == both { name = name + ".zip" } fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name) 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.outputFiles[apexType].String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString())) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexType.suffix()) fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key)) fmt.Fprintln(w, "include $(BUILD_PREBUILT)") if apexType == imageApex { fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String()) } }} } } func apexBundleFactory() android.Module { module := &apexBundle{} module := &apexBundle{ outputFiles: map[apexPackaging]android.WritablePath{}, } module.AddProperties(&module.properties) module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool { return class == android.Device && ctx.Config().DevicePrefer32BitExecutables() }) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) return module }
apex/apex_test.go +57 −9 Original line number Diff line number Diff line Loading @@ -188,8 +188,56 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex") // Ensure that both direct and indirect deps are copied into apex ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image/lib64/mylib2.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") } func TestBasicZipApex(t *testing.T) { ctx := testApex(t, ` apex { name: "myapex", key: "myapex.key", payload_type: "zip", native_shared_libs: ["mylib"], } 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", } cc_library { name: "mylib2", srcs: ["mylib.cpp"], system_shared_libs: [], stl: "none", } `) zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").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_myapex") // Ensure that APEX variant is created for the indirect dep ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex") // 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) { Loading Loading @@ -239,13 +287,13 @@ func TestApexWithStubs(t *testing.T) { copyCmds := apexRule.Args["copy_commands"] // Ensure that direct non-stubs dep is always included ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") // Ensure that indirect stubs dep is not included ensureNotContains(t, copyCmds, "image/lib64/mylib2.so") ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") // Ensure that direct stubs dep is included ensureContains(t, copyCmds, "image/lib64/mylib3.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so") mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"] Loading Loading @@ -326,12 +374,12 @@ func TestApexWithSystemLibsStubs(t *testing.T) { copyCmds := apexRule.Args["copy_commands"] // Ensure that mylib, libm, libdl are included. ensureContains(t, copyCmds, "image/lib64/mylib.so") ensureContains(t, copyCmds, "image/lib64/libm.so") ensureContains(t, copyCmds, "image/lib64/libdl.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/libm.so") ensureContains(t, copyCmds, "image.apex/lib64/libdl.so") // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs) ensureNotContains(t, copyCmds, "image/lib64/libc.so") ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so") mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"] mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] Loading