diff --git a/android/androidmk.go b/android/androidmk.go index 3487b287d..045cb59b3 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -58,7 +58,7 @@ type AndroidMkData struct { Extra []AndroidMkExtraFunc - preamble bytes.Buffer + Entries AndroidMkEntries } type AndroidMkExtraFunc func(w io.Writer, outputFile Path) @@ -483,7 +483,7 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprint.Module) { // Get the preamble content through AndroidMkEntries logic. - entries := AndroidMkEntries{ + data.Entries = AndroidMkEntries{ Class: data.Class, SubName: data.SubName, DistFiles: data.DistFiles, @@ -494,16 +494,12 @@ func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprin Host_required: data.Host_required, Target_required: data.Target_required, } - entries.fillInEntries(config, bpPath, mod) - - // preamble doesn't need the footer content. - entries.footer = bytes.Buffer{} - entries.write(&data.preamble) + data.Entries.fillInEntries(config, bpPath, mod) // copy entries back to data since it is used in Custom - data.Required = entries.Required - data.Host_required = entries.Host_required - data.Target_required = entries.Target_required + data.Required = data.Entries.Required + data.Host_required = data.Entries.Host_required + data.Target_required = data.Entries.Target_required } func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module, @@ -559,7 +555,9 @@ func WriteAndroidMkData(w io.Writer, data AndroidMkData) { return } - w.Write(data.preamble.Bytes()) + // write preamble via Entries + data.Entries.footer = bytes.Buffer{} + data.Entries.write(w) for _, extra := range data.Extra { extra(w, data.OutputFile.Path()) diff --git a/apex/androidmk.go b/apex/androidmk.go index 4dd14d856..759523896 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -33,14 +33,7 @@ func (a *apexBundle) AndroidMk() android.AndroidMkData { Disabled: true, } } - writers := []android.AndroidMkData{} - writers = append(writers, a.androidMkForType()) - 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) - } - }} + return a.androidMkForType() } func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string) []string { @@ -308,6 +301,20 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String()) fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix()) fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable()) + + // Because apex writes .mk with Custom(), we need to write manually some common properties + // which are available via data.Entries + commonProperties := []string{ + "LOCAL_INIT_RC", "LOCAL_VINTF_FRAGMENTS", + "LOCAL_PROPRIETARY_MODULE", "LOCAL_VENDOR_MODULE", "LOCAL_ODM_MODULE", "LOCAL_PRODUCT_MODULE", "LOCAL_SYSTEM_EXT_MODULE", + "LOCAL_MODULE_OWNER", + } + for _, name := range commonProperties { + if value, ok := data.Entries.EntryMap[name]; ok { + fmt.Fprintln(w, name+" := "+strings.Join(value, " ")) + } + } + if len(a.overridableProperties.Overrides) > 0 { fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(a.overridableProperties.Overrides, " ")) } diff --git a/apex/apex.go b/apex/apex.go index a9be1a8ae..d0c1a09d5 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1329,6 +1329,7 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { targets := ctx.MultiTargets() config := ctx.DeviceConfig() + imageVariation := a.getImageVariation(ctx) a.combineProperties(ctx) @@ -1348,13 +1349,13 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { Jni_libs: a.properties.Jni_libs, Binaries: nil, }, - target, a.getImageVariation(config)) + target, imageVariation) // Add native modules targetting both ABIs addDependenciesForNativeModules(ctx, a.properties.Multilib.Both, target, - a.getImageVariation(config)) + imageVariation) isPrimaryAbi := i == 0 if isPrimaryAbi { @@ -1367,13 +1368,13 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { Jni_libs: nil, Binaries: a.properties.Binaries, }, - target, a.getImageVariation(config)) + target, imageVariation) // Add native modules targetting the first ABI addDependenciesForNativeModules(ctx, a.properties.Multilib.First, target, - a.getImageVariation(config)) + imageVariation) } switch target.Arch.ArchType.Multilib { @@ -1382,24 +1383,24 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { addDependenciesForNativeModules(ctx, a.properties.Multilib.Lib32, target, - a.getImageVariation(config)) + imageVariation) addDependenciesForNativeModules(ctx, a.properties.Multilib.Prefer32, target, - a.getImageVariation(config)) + imageVariation) case "lib64": // Add native modules targetting 64-bit ABI addDependenciesForNativeModules(ctx, a.properties.Multilib.Lib64, target, - a.getImageVariation(config)) + imageVariation) if !has32BitTarget { addDependenciesForNativeModules(ctx, a.properties.Multilib.Prefer32, target, - a.getImageVariation(config)) + imageVariation) } } } @@ -1501,15 +1502,33 @@ func (a *apexBundle) testOnlyShouldSkipPayloadSign() bool { return proptools.Bool(a.properties.Test_only_unsigned_payload) } -func (a *apexBundle) getImageVariation(config android.DeviceConfig) string { +func (a *apexBundle) getImageVariation(ctx android.BottomUpMutatorContext) string { + deviceConfig := ctx.DeviceConfig() if a.vndkApex { - return cc.VendorVariationPrefix + a.vndkVersion(config) + return cc.VendorVariationPrefix + a.vndkVersion(deviceConfig) } - if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) { - return cc.VendorVariationPrefix + config.PlatformVndkVersion() - } else { - return android.CoreVariation + + var prefix string + var vndkVersion string + if deviceConfig.VndkVersion() != "" { + if proptools.Bool(a.properties.Use_vendor) { + prefix = cc.VendorVariationPrefix + vndkVersion = deviceConfig.PlatformVndkVersion() + } else if a.SocSpecific() || a.DeviceSpecific() { + prefix = cc.VendorVariationPrefix + vndkVersion = deviceConfig.VndkVersion() + } else if a.ProductSpecific() { + prefix = cc.ProductVariationPrefix + vndkVersion = deviceConfig.ProductVndkVersion() + } } + if vndkVersion == "current" { + vndkVersion = deviceConfig.PlatformVndkVersion() + } + if vndkVersion != "" { + return prefix + vndkVersion + } + return android.CoreVariation } func (a *apexBundle) EnableSanitizer(sanitizerName string) { @@ -1541,7 +1560,7 @@ func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext for _, target := range ctx.MultiTargets() { if target.Arch.ArchType.Multilib == "lib64" { ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ - {Mutator: "image", Variation: a.getImageVariation(ctx.DeviceConfig())}, + {Mutator: "image", Variation: a.getImageVariation(ctx)}, {Mutator: "link", Variation: "shared"}, {Mutator: "version", Variation: ""}, // "" is the non-stub variant }...), sharedLibTag, "libclang_rt.hwasan-aarch64-android") @@ -1785,6 +1804,12 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { return } + // Because APEXes targeting other than system/system_ext partitions + // can't set apex_available, we skip checks for these APEXes + if ctx.SocSpecific() || ctx.DeviceSpecific() || ctx.ProductSpecific() { + return + } + // Coverage build adds additional dependencies for the coverage-only runtime libraries. // Requiring them and their transitive depencies with apex_available is not right // because they just add noise. @@ -2099,7 +2124,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs) af.transitiveDep = true - if !a.Host() && !android.DirectlyInApex(ctx.ModuleName(), ctx.OtherModuleName(cc)) && (cc.IsStubs() || cc.HasStubsVariants()) { + if !a.Host() && !android.DirectlyInApex(ctx.ModuleName(), depName) && (cc.IsStubs() || cc.HasStubsVariants()) { // If the dependency is a stubs lib, don't include it in this APEX, // but make sure that the lib is installed on the device. // In case no APEX is having the lib, the lib is installed to the system @@ -2107,8 +2132,17 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // // Always include if we are a host-apex however since those won't have any // system libraries. - if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.BaseModuleName(), a.requiredDeps) { - a.requiredDeps = append(a.requiredDeps, cc.BaseModuleName()) + if !android.DirectlyInAnyApex(ctx, depName) { + // we need a module name for Make + name := cc.BaseModuleName() + cc.Properties.SubName + if proptools.Bool(a.properties.Use_vendor) { + // we don't use subName(.vendor) for a "use_vendor: true" apex + // which is supposed to be installed in /system + name = cc.BaseModuleName() + } + if !android.InList(name, a.requiredDeps) { + a.requiredDeps = append(a.requiredDeps, name) + } } requireNativeLibs = append(requireNativeLibs, af.Stem()) // Don't track further @@ -2203,6 +2237,12 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.installable() && !proptools.Bool(a.properties.Use_vendor) + // APEXes targeting other than system/system_ext partitions use vendor/product variants. + // So we can't link them to /system/lib libs which are core variants. + if a.SocSpecific() || a.DeviceSpecific() || a.ProductSpecific() { + a.linkToSystemLib = false + } + // 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) if a.Updatable() && a.properties.ApexType == imageApex { diff --git a/apex/apex_test.go b/apex/apex_test.go index f1638c3bc..befb81483 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -2105,7 +2105,7 @@ func TestUseVendor(t *testing.T) { ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_myapex/mylib2.so") } -func TestUseVendorRestriction(t *testing.T) { +func TestUseVendorNotAllowedForSystemApexes(t *testing.T) { testApexError(t, `module "myapex" .*: use_vendor: not allowed`, ` apex { name: "myapex", @@ -2161,6 +2161,141 @@ func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) { `) } +func TestVendorApex(t *testing.T) { + ctx, config := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + binaries: ["mybin"], + vendor: true, + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + cc_binary { + name: "mybin", + vendor: true, + shared_libs: ["libfoo"], + } + cc_library { + name: "libfoo", + proprietary: true, + } + `) + + ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "bin/mybin", + "lib64/libfoo.so", + // TODO(b/159195575): Add an option to use VNDK libs from VNDK APEX + "lib64/libc++.so", + }) + + apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, config, "", apexBundle) + name := apexBundle.BaseModuleName() + prefix := "TARGET_" + var builder strings.Builder + data.Custom(&builder, name, prefix, "", data) + androidMk := builder.String() + ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`) +} + +func TestAndroidMk_UseVendorRequired(t *testing.T) { + ctx, config := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + use_vendor: true, + native_shared_libs: ["mylib"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + vendor_available: true, + apex_available: ["myapex"], + } + `, func(fs map[string][]byte, config android.Config) { + setUseVendorAllowListForTest(config, []string{"myapex"}) + }) + + apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, config, "", apexBundle) + name := apexBundle.BaseModuleName() + prefix := "TARGET_" + var builder strings.Builder + data.Custom(&builder, name, prefix, "", data) + androidMk := builder.String() + ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += libc libm libdl\n") +} + +func TestAndroidMk_VendorApexRequired(t *testing.T) { + ctx, config := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + vendor: true, + native_shared_libs: ["mylib"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + vendor_available: true, + } + `) + + apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, config, "", apexBundle) + name := apexBundle.BaseModuleName() + prefix := "TARGET_" + var builder strings.Builder + data.Custom(&builder, name, prefix, "", data) + androidMk := builder.String() + ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += libc.vendor libm.vendor libdl.vendor\n") +} + +func TestAndroidMkWritesCommonProperties(t *testing.T) { + ctx, config := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + vintf_fragments: ["fragment.xml"], + init_rc: ["init.rc"], + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + cc_binary { + name: "mybin", + } + `) + + apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, config, "", apexBundle) + name := apexBundle.BaseModuleName() + prefix := "TARGET_" + var builder strings.Builder + data.Custom(&builder, name, prefix, "", data) + androidMk := builder.String() + ensureContains(t, androidMk, "LOCAL_VINTF_FRAGMENTS := fragment.xml\n") + ensureContains(t, androidMk, "LOCAL_INIT_RC := init.rc\n") +} + func TestStaticLinking(t *testing.T) { ctx, _ := testApex(t, ` apex {