Merge "delete redundant code"
diff --git a/Android.bp b/Android.bp
index 05972fd..8d0c1ea 100644
--- a/Android.bp
+++ b/Android.bp
@@ -366,6 +366,7 @@
"rust/prebuilt.go",
"rust/proc_macro.go",
"rust/rust.go",
+ "rust/test.go",
"rust/testing.go",
],
testSrcs: [
@@ -373,6 +374,7 @@
"rust/compiler_test.go",
"rust/library_test.go",
"rust/rust_test.go",
+ "rust/test_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/android/util.go b/android/util.go
index 71ded5e..81f481d 100644
--- a/android/util.go
+++ b/android/util.go
@@ -93,6 +93,20 @@
return s
}
+func SortedStringMapValues(m interface{}) []string {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Map {
+ panic(fmt.Sprintf("%#v is not a map", m))
+ }
+ keys := v.MapKeys()
+ s := make([]string, 0, len(keys))
+ for _, key := range keys {
+ s = append(s, v.MapIndex(key).String())
+ }
+ sort.Strings(s)
+ return s
+}
+
func IndexList(s string, list []string) int {
for i, l := range list {
if l == s {
@@ -352,3 +366,14 @@
}
return ret
}
+
+func CheckDuplicate(values []string) (duplicate string, found bool) {
+ seen := make(map[string]string)
+ for _, v := range values {
+ if duplicate, found = seen[v]; found {
+ return
+ }
+ seen[v] = v
+ }
+ return
+}
diff --git a/apex/apex.go b/apex/apex.go
index 4ad2680..4e6827f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -129,9 +129,11 @@
const (
imageApexSuffix = ".apex"
zipApexSuffix = ".zipapex"
+ flattenedSuffix = ".flattened"
- imageApexType = "image"
- zipApexType = "zip"
+ imageApexType = "image"
+ zipApexType = "zip"
+ flattenedApexType = "flattened"
vndkApexNamePrefix = "com.android.vndk.v"
)
@@ -316,13 +318,30 @@
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
if ab, ok := mctx.Module().(*apexBundle); ok {
- if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
- modules := mctx.CreateLocalVariations("", "flattened")
- modules[0].(*apexBundle).SetFlattened(false)
- modules[1].(*apexBundle).SetFlattened(true)
- } else {
- ab.SetFlattened(true)
- ab.SetFlattenedConfigValue()
+ var variants []string
+ switch proptools.StringDefault(ab.properties.Payload_type, "image") {
+ case "image":
+ variants = append(variants, imageApexType, flattenedApexType)
+ case "zip":
+ variants = append(variants, zipApexType)
+ case "both":
+ variants = append(variants, imageApexType, zipApexType, flattenedApexType)
+ default:
+ mctx.PropertyErrorf("type", "%q is not one of \"image\" or \"zip\".", *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
+ case flattenedApexType:
+ modules[i].(*apexBundle).properties.ApexType = flattenedApex
+ }
}
}
}
@@ -333,6 +352,34 @@
}
}
+var (
+ useVendorWhitelistKey = android.NewOnceKey("useVendorWhitelist")
+)
+
+// useVendorWhitelist returns the list of APEXes which are allowed to use_vendor.
+// When use_vendor is used, native modules are built with __ANDROID_VNDK__ and __ANDROID_APEX__,
+// which may cause compatibility issues. (e.g. libbinder)
+// Even though libbinder restricts its availability via 'apex_available' property and relies on
+// yet another macro __ANDROID_APEX_<NAME>__, we restrict usage of "use_vendor:" from other APEX modules
+// to avoid similar problems.
+func useVendorWhitelist(config android.Config) []string {
+ return config.Once(useVendorWhitelistKey, func() interface{} {
+ return []string{
+ // swcodec uses "vendor" variants for smaller size
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ }
+ }).([]string)
+}
+
+// setUseVendorWhitelistForTest overrides useVendorWhitelist and must be
+// called before the first call to useVendorWhitelist()
+func setUseVendorWhitelistForTest(config android.Config, whitelist []string) {
+ config.Once(useVendorWhitelistKey, func() interface{} {
+ return whitelist
+ })
+}
+
type apexNativeDependencies struct {
// List of native libraries
Native_shared_libs []string
@@ -438,13 +485,9 @@
// List of APKs to package inside APEX
Apps []string
- // To distinguish between flattened and non-flattened apex.
- // if set true, then output files are flattened.
- Flattened bool `blueprint:"mutated"`
-
- // if true, it means that TARGET_FLATTEN_APEX is true and
- // TARGET_BUILD_APPS is false
- FlattenedConfigValue bool `blueprint:"mutated"`
+ // package format of this apex variant; could be non-flattened, flattened, or zip.
+ // imageApex, zipApex or flattened
+ ApexType apexPackaging `blueprint:"mutated"`
// List of SDKs that are used to build this APEX. A reference to an SDK should be either
// `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
@@ -501,33 +544,16 @@
const (
imageApex apexPackaging = iota
zipApex
- both
+ flattenedApex
)
-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
-}
-
+// The suffix for the output "file", not the module
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("unknown APEX type %d", a))
}
@@ -539,8 +565,6 @@
return imageApexType
case zipApex:
return zipApexType
- case both:
- panic(fmt.Errorf("must be either zip or image"))
default:
panic(fmt.Errorf("unknown APEX type %d", a))
}
@@ -590,11 +614,8 @@
targetProperties apexTargetBundleProperties
vndkProperties apexVndkProperties
- apexTypes apexPackaging
-
bundleModuleFile android.WritablePath
- outputFiles map[apexPackaging]android.WritablePath
- flattenedOutput android.InstallPath
+ outputFile android.WritablePath
installDir android.InstallPath
prebuiltFileToDelete string
@@ -611,8 +632,9 @@
// list of module names that this APEX is depending on
externalDeps []string
- testApex bool
- vndkApex bool
+ testApex bool
+ vndkApex bool
+ primaryApexType bool
// intermediate path for apex_manifest.json
manifestOut android.WritablePath
@@ -622,6 +644,10 @@
// apex package itself(for unflattened build) or apex_manifest.json(for flattened build)
// so that compat symlinks are always installed regardless of TARGET_FLATTEN_APEX setting.
compatSymlinks []string
+
+ // Suffix of module name in Android.mk
+ // ".flattened", ".apex", ".zipapex", or ""
+ suffix string
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -661,6 +687,10 @@
}
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorWhitelist(ctx.Config())) {
+ ctx.PropertyErrorf("use_vendor", "not allowed to set use_vendor: true")
+ }
+
targets := ctx.MultiTargets()
config := ctx.DeviceConfig()
@@ -808,18 +838,7 @@
func (a *apexBundle) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
- if file, ok := a.outputFiles[imageApex]; ok {
- return android.Paths{file}, nil
- } else {
- return nil, nil
- }
- case ".flattened":
- if a.properties.Flattened {
- flattenedApexPath := a.flattenedOutput
- return android.Paths{flattenedApexPath}, nil
- } else {
- return nil, nil
- }
+ return android.Paths{a.outputFile}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -876,24 +895,6 @@
a.properties.HideFromMake = true
}
-func (a *apexBundle) SetFlattened(flattened bool) {
- a.properties.Flattened = flattened
-}
-
-func (a *apexBundle) SetFlattenedConfigValue() {
- a.properties.FlattenedConfigValue = true
-}
-
-// isFlattenedVariant returns true when the current module is the flattened
-// variant of an apex that has both a flattened and an unflattened variant.
-// It returns false when the current module is flattened but there is no
-// unflattened variant, which occurs when ctx.Config().FlattenedApex() returns
-// true. It can be used to avoid collisions between the install paths of the
-// flattened and unflattened variants.
-func (a *apexBundle) isFlattenedVariant() bool {
- return a.properties.Flattened && !a.properties.FlattenedConfigValue
-}
-
func getCopyManifestForNativeLibrary(ccMod *cc.Module, config android.Config, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
// Decide the APEX-local directory by the multilib of the library
// In the future, we may query this to the module.
@@ -1012,15 +1013,29 @@
func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filesInfo := []apexFile{}
- 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
+ buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
+ switch a.properties.ApexType {
+ case imageApex:
+ if buildFlattenedAsDefault {
+ a.suffix = imageApexSuffix
+ } else {
+ a.suffix = ""
+ a.primaryApexType = true
+ }
+ case zipApex:
+ if proptools.String(a.properties.Payload_type) == "zip" {
+ a.suffix = ""
+ a.primaryApexType = true
+ } else {
+ a.suffix = zipApexSuffix
+ }
+ case flattenedApex:
+ if buildFlattenedAsDefault {
+ a.suffix = ""
+ a.primaryApexType = true
+ } else {
+ a.suffix = flattenedSuffix
+ }
}
if len(a.properties.Tests) > 0 && !a.testApex {
@@ -1266,7 +1281,7 @@
// prepend the name of this APEX to the module names. These names will be the names of
// modules that will be defined if the APEX is flattened.
for i := range filesInfo {
- filesInfo[i].moduleName = filesInfo[i].moduleName + "." + ctx.ModuleName()
+ filesInfo[i].moduleName = filesInfo[i].moduleName + "." + ctx.ModuleName() + a.suffix
}
a.installDir = android.PathForModuleInstall(ctx, "apex")
@@ -1297,27 +1312,14 @@
},
})
- // Temporarily wrap the original `ctx` into a `flattenedApexContext` to have it
- // reply true to `InstallBypassMake()` (thus making the call
- // `android.PathForModuleInstall` below use `android.pathForInstallInMakeDir`
- // instead of `android.PathForOutput`) to return the correct path to the flattened
- // APEX (as its contents is installed by Make, not Soong).
- factx := flattenedApexContext{ctx}
- apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
- a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", apexName)
-
- if a.apexTypes.zip() {
- a.buildUnflattenedApex(ctx, zipApex)
- }
- if a.apexTypes.image() {
- // Build rule for unflattened APEX is created even when ctx.Config().FlattenApex()
- // is true. This is to support referencing APEX via ":<module_name>" syntax
- // in other modules. It is in AndroidMk where the selection of flattened
- // or unflattened APEX is made.
- a.buildUnflattenedApex(ctx, imageApex)
+ a.setCertificateAndPrivateKey(ctx)
+ if a.properties.ApexType == flattenedApex {
a.buildFlattenedApex(ctx)
+ } else {
+ a.buildUnflattenedApex(ctx)
}
+ apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
}
@@ -1343,18 +1345,7 @@
return android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)).HtmlGzOutput
}
-func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) {
- cert := String(a.properties.Certificate)
- if cert != "" && android.SrcIsModule(cert) == "" {
- defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
- a.container_certificate_file = defaultDir.Join(ctx, cert+".x509.pem")
- a.container_private_key_file = defaultDir.Join(ctx, cert+".pk8")
- } else if cert == "" {
- pem, key := ctx.Config().DefaultAppCertificate(ctx)
- a.container_certificate_file = pem
- a.container_private_key_file = key
- }
-
+func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
var abis []string
for _, target := range ctx.MultiTargets() {
if len(target.Arch.Abi) > 0 {
@@ -1364,6 +1355,7 @@
abis = android.FirstUniqueStrings(abis)
+ apexType := a.properties.ApexType
suffix := apexType.suffix()
unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned")
@@ -1424,7 +1416,7 @@
outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
- if apexType.image() {
+ if apexType == imageApex {
// files and dirs that will be created in APEX
var readOnlyPaths []string
var executablePaths []string // this also includes dirs
@@ -1570,11 +1562,11 @@
})
}
- a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix)
+ a.outputFile = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix)
ctx.Build(pctx, android.BuildParams{
Rule: java.Signapk,
Description: "signapk",
- Output: a.outputFiles[apexType],
+ Output: a.outputFile,
Input: unsignedOutputFile,
Implicits: []android.Path{
a.container_certificate_file,
@@ -1587,16 +1579,43 @@
})
// Install to $OUT/soong/{target,host}/.../apex
- if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) && !a.isFlattenedVariant() {
- ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType])
+ if a.installable() {
+ ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFile)
}
+ a.buildFilesInfo(ctx)
}
func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) {
+ // Temporarily wrap the original `ctx` into a `flattenedApexContext` to have it
+ // reply true to `InstallBypassMake()` (thus making the call
+ // `android.PathForModuleInstall` below use `android.pathForInstallInMakeDir`
+ // instead of `android.PathForOutput`) to return the correct path to the flattened
+ // APEX (as its contents is installed by Make, not Soong).
+ factx := flattenedApexContext{ctx}
+ apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+ a.outputFile = android.PathForModuleInstall(&factx, "apex", apexName)
+
+ a.buildFilesInfo(ctx)
+}
+
+func (a *apexBundle) setCertificateAndPrivateKey(ctx android.ModuleContext) {
+ cert := String(a.properties.Certificate)
+ if cert != "" && android.SrcIsModule(cert) == "" {
+ defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
+ a.container_certificate_file = defaultDir.Join(ctx, cert+".x509.pem")
+ a.container_private_key_file = defaultDir.Join(ctx, cert+".pk8")
+ } else if cert == "" {
+ pem, key := ctx.Config().DefaultAppCertificate(ctx)
+ a.container_certificate_file = pem
+ a.container_private_key_file = key
+ }
+}
+
+func (a *apexBundle) buildFilesInfo(ctx android.ModuleContext) {
if a.installable() {
// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
// with other ordinary files.
- a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, "apex_manifest.json." + ctx.ModuleName(), ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, "apex_manifest.json." + ctx.ModuleName() + a.suffix, ".", etc, nil, nil})
// rename to apex_pubkey
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -1605,9 +1624,9 @@
Input: a.public_key_file,
Output: copiedPubkey,
})
- a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, "apex_pubkey." + ctx.ModuleName(), ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, "apex_pubkey." + ctx.ModuleName() + a.suffix, ".", etc, nil, nil})
- if ctx.Config().FlattenApex() {
+ if a.properties.ApexType == flattenedApex {
apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
for _, fi := range a.filesInfo {
dir := filepath.Join("apex", apexName, fi.installDir)
@@ -1627,12 +1646,7 @@
}
}
writers := []android.AndroidMkData{}
- if a.apexTypes.image() {
- writers = append(writers, a.androidMkForType(imageApex))
- }
- if a.apexTypes.zip() {
- writers = append(writers, a.androidMkForType(zipApex))
- }
+ writers = append(writers, a.androidMkForType())
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
for _, data := range writers {
@@ -1641,36 +1655,35 @@
}}
}
-func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string, apexType apexPackaging) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string) []string {
moduleNames := []string{}
+ apexType := a.properties.ApexType
+ // To avoid creating duplicate build rules, run this function only when primaryApexType is true
+ // to install symbol files in $(PRODUCT_OUT}/apex.
+ // And if apexType is flattened, run this function to install files in $(PRODUCT_OUT}/system/apex.
+ if !a.primaryApexType && apexType != flattenedApex {
+ return moduleNames
+ }
for _, fi := range a.filesInfo {
if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
continue
}
- if a.properties.Flattened && !apexType.image() {
- continue
- }
-
- var suffix string
- if a.isFlattenedVariant() {
- suffix = ".flattened"
- }
if !android.InList(fi.moduleName, moduleNames) {
- moduleNames = append(moduleNames, fi.moduleName+suffix)
+ moduleNames = append(moduleNames, fi.moduleName)
}
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
- fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName+suffix)
+ fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
// /apex/<apex_name>/{lib|framework|...}
pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
- if a.properties.Flattened && apexType.image() {
+ if apexType == flattenedApex {
// /system/apex/<name>/{lib|framework|...}
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
apexName, fi.installDir))
- if !a.isFlattenedVariant() {
+ if a.primaryApexType {
fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
}
if len(fi.symlinks) > 0 {
@@ -1739,7 +1752,7 @@
} else {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
- if !a.isFlattenedVariant() && fi.builtFile.Base() == "apex_manifest.json" && len(a.compatSymlinks) > 0 {
+ if a.primaryApexType && fi.builtFile.Base() == "apex_manifest.json" && len(a.compatSymlinks) > 0 {
fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
}
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
@@ -1748,41 +1761,33 @@
return moduleNames
}
-func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData {
+func (a *apexBundle) androidMkForType() android.AndroidMkData {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{}
+ apexType := a.properties.ApexType
if a.installable() {
apexName := proptools.StringDefault(a.properties.Apex_name, name)
- moduleNames = a.androidMkForFiles(w, apexName, moduleDir, apexType)
+ moduleNames = a.androidMkForFiles(w, apexName, moduleDir)
}
- if a.isFlattenedVariant() {
- name = name + ".flattened"
- }
-
- if a.properties.Flattened && apexType.image() {
+ if apexType == flattenedApex {
// Only image APEXes can be flattened.
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
- fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+ fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
}
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
- fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): .KATI_IMPLICIT_OUTPUTS :=", a.flattenedOutput.String())
+ fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): .KATI_IMPLICIT_OUTPUTS :=", a.outputFile.String())
- } else if !a.isFlattenedVariant() {
- // 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"
- }
+ } else {
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
- fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+ fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
- fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
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())
@@ -1812,9 +1817,7 @@
}
func newApexBundle() *apexBundle {
- module := &apexBundle{
- outputFiles: map[apexPackaging]android.WritablePath{},
- }
+ module := &apexBundle{}
module.AddProperties(&module.properties)
module.AddProperties(&module.targetProperties)
module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ffbee86..77c1fb0 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -455,12 +455,12 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
optFlags := apexRule.Args["opt_flags"]
ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
// Ensure that the NOTICE output is being packaged as an asset.
- ensureContains(t, optFlags, "--assets_dir "+buildDir+"/.intermediates/myapex/android_common_myapex/NOTICE")
+ ensureContains(t, optFlags, "--assets_dir "+buildDir+"/.intermediates/myapex/android_common_myapex_image/NOTICE")
copyCmds := apexRule.Args["copy_commands"]
@@ -508,7 +508,7 @@
t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
}
- mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("mergeNoticesRule")
+ mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("mergeNoticesRule")
noticeInputs := mergeNoticesRule.Inputs.Strings()
if len(noticeInputs) != 2 {
t.Errorf("number of input notice files: expected = 2, actual = %q", len(noticeInputs))
@@ -548,7 +548,7 @@
}
`)
- zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule")
+ zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex_zip").Rule("zipApexRule")
copyCmds := zipApexRule.Args["copy_commands"]
// Ensure that main rule creates an output
@@ -617,7 +617,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -691,7 +691,7 @@
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -765,7 +765,7 @@
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -777,7 +777,7 @@
// Ensure that runtime_libs dep in included
ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.so")
@@ -818,16 +818,17 @@
name: "libbar",
symbol_file: "",
}
+ `, func(fs map[string][]byte, config android.Config) {
+ setUseVendorWhitelistForTest(config, []string{"myapex"})
+ })
- `)
-
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that LLNDK dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
// Ensure that LLNDK dep is required
@@ -904,7 +905,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that mylib, libm, libdl are included.
@@ -997,7 +998,7 @@
}
`)
- generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
+ generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
// Ensure that the subdirectories are all listed
@@ -1047,10 +1048,12 @@
vendor_available: true,
stl: "none",
}
- `)
+ `, func(fs map[string][]byte, config android.Config) {
+ setUseVendorWhitelistForTest(config, []string{"myapex"})
+ })
inputsList := []string{}
- for _, i := range ctx.ModuleForTests("myapex", "android_common_myapex").Module().BuildParamsForTests() {
+ for _, i := range ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().BuildParamsForTests() {
for _, implicit := range i.Implicits {
inputsList = append(inputsList, implicit.String())
}
@@ -1066,6 +1069,38 @@
ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib2.so")
}
+func TestUseVendorRestriction(t *testing.T) {
+ testApexError(t, `module "myapex" .*: use_vendor: not allowed`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ use_vendor: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ setUseVendorWhitelistForTest(config, []string{""})
+ })
+ // no error with whitelist
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ use_vendor: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ setUseVendorWhitelistForTest(config, []string{"myapex"})
+ })
+}
+
func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
testApexError(t, `dependency "mylib" of "myapex" missing variant:\n.*image:vendor`, `
apex {
@@ -1177,7 +1212,7 @@
}
// check the APK certs. It should be overridden to myapex.certificate.override
- certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"]
+ certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest_image").Rule("signapk").Args["certificates"]
if certs != "testkey.override.x509.pem testkey.override.pk8" {
t.Errorf("cert and private key %q are not %q", certs,
"testkey.override.509.pem testkey.override.pk8")
@@ -1212,24 +1247,21 @@
}
`)
- // non-APEX variant does not have __ANDROID__APEX__ defined
+ // non-APEX variant does not have __ANDROID_APEX(_NAME)__ defined
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
- // APEX variant has __ANDROID_APEX__=<apexname> defined
+ // APEX variant has __ANDROID_APEX(_NAME)__ defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
- // APEX variant has __ANDROID_APEX__=<apexname> defined
+ // APEX variant has __ANDROID_APEX(_NAME)__ defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"]
- ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
- ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
}
@@ -1284,7 +1316,7 @@
func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
t.Helper()
- apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName).Rule("apexRule")
+ apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
imageApexDir := "/image.apex/"
dstFiles := []string{}
@@ -1578,7 +1610,7 @@
}`)
assertApexName := func(expected, moduleName string) {
- bundle := ctx.ModuleForTests(moduleName, "android_common_"+moduleName).Module().(*apexBundle)
+ bundle := ctx.ModuleForTests(moduleName, "android_common_"+moduleName+"_image").Module().(*apexBundle)
actual := proptools.String(bundle.properties.Apex_name)
if !reflect.DeepEqual(actual, expected) {
t.Errorf("Got '%v', expected '%v'", actual, expected)
@@ -1793,25 +1825,25 @@
var apexManifestRule android.TestingBuildParams
var provideNativeLibs, requireNativeLibs []string
- apexManifestRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep_image").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListEmpty(t, requireNativeLibs)
- apexManifestRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep_image").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListContains(t, requireNativeLibs, "libfoo.so")
- apexManifestRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider_image").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libfoo.so")
ensureListEmpty(t, requireNativeLibs)
- apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained_image").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libfoo.so")
@@ -1833,7 +1865,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexManifestRule := module.Rule("apexManifestRule")
ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
apexRule := module.Rule("apexRule")
@@ -1862,7 +1894,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -1913,7 +1945,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -1997,7 +2029,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that main rule creates an output
@@ -2041,7 +2073,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
@@ -2071,7 +2103,7 @@
}
`)
- apex := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apex := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
expected := buildDir + "/target/product/test_device/product/apex"
actual := apex.installDir.String()
if actual != expected {
@@ -2215,7 +2247,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that test dep is copied into apex.
@@ -2227,7 +2259,7 @@
ensureContains(t, copyCmds, "image.apex/bin/test/mytest3")
// Ensure the module is correctly translated.
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, config, "", apexBundle)
name := apexBundle.BaseModuleName()
prefix := "TARGET_"
@@ -2281,11 +2313,11 @@
}
`)
- module1 := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module1 := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexRule1 := module1.Rule("apexRule")
copyCmds1 := apexRule1.Args["copy_commands"]
- module2 := ctx.ModuleForTests("commonapex", "android_common_commonapex")
+ module2 := ctx.ModuleForTests("commonapex", "android_common_commonapex_image")
apexRule2 := module2.Rule("apexRule")
copyCmds2 := apexRule2.Args["copy_commands"]
@@ -2356,7 +2388,9 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `)
+ `, func(fs map[string][]byte, config android.Config) {
+ setUseVendorWhitelistForTest(config, []string{"myapex"})
+ })
}
func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
@@ -2437,7 +2471,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -2482,7 +2516,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
diff --git a/cc/cc.go b/cc/cc.go
index f90f1e8..a312c49 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -745,17 +745,18 @@
func (c *Module) isLlndk(config android.Config) bool {
// Returns true for both LLNDK (public) and LLNDK-private libs.
- return inList(c.BaseModuleName(), *llndkLibraries(config))
+ return isLlndkLibrary(c.BaseModuleName(), config)
}
func (c *Module) isLlndkPublic(config android.Config) bool {
// Returns true only for LLNDK (public) libs.
- return c.isLlndk(config) && !c.isVndkPrivate(config)
+ name := c.BaseModuleName()
+ return isLlndkLibrary(name, config) && !isVndkPrivateLibrary(name, config)
}
func (c *Module) isVndkPrivate(config android.Config) bool {
// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
- return inList(c.BaseModuleName(), *vndkPrivateLibraries(config))
+ return isVndkPrivateLibrary(c.BaseModuleName(), config)
}
func (c *Module) IsVndk() bool {
@@ -853,6 +854,27 @@
return c.linker != nil && c.linker.nativeCoverage()
}
+func (c *Module) ExportedIncludeDirs() android.Paths {
+ if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
+ return flagsProducer.exportedDirs()
+ }
+ return []android.Path{}
+}
+
+func (c *Module) ExportedSystemIncludeDirs() android.Paths {
+ if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
+ return flagsProducer.exportedSystemDirs()
+ }
+ return []android.Path{}
+}
+
+func (c *Module) ExportedFlags() []string {
+ if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
+ return flagsProducer.exportedFlags()
+ }
+ return []string{}
+}
+
func isBionic(name string) bool {
switch name {
case "libc", "libm", "libdl", "linker":
@@ -1456,7 +1478,7 @@
}
// Split name#version into name and version
-func stubsLibNameAndVersion(name string) (string, string) {
+func StubsLibNameAndVersion(name string) (string, string) {
if sharp := strings.LastIndex(name, "#"); sharp != -1 && sharp != len(name)-1 {
version := name[sharp+1:]
libname := name[:sharp]
@@ -1496,21 +1518,20 @@
// The caller can then know to add the variantLibs dependencies differently from the
// nonvariantLibs
- llndkLibraries := llndkLibraries(actx.Config())
vendorPublicLibraries := vendorPublicLibraries(actx.Config())
rewriteNdkLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
variantLibs = []string{}
nonvariantLibs = []string{}
for _, entry := range list {
// strip #version suffix out
- name, _ := stubsLibNameAndVersion(entry)
+ name, _ := StubsLibNameAndVersion(entry)
if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
if !inList(name, ndkMigratedLibs) {
nonvariantLibs = append(nonvariantLibs, name+".ndk."+version)
} else {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
}
- } else if ctx.useVndk() && inList(name, *llndkLibraries) {
+ } else if ctx.useVndk() && isLlndkLibrary(name, ctx.Config()) {
nonvariantLibs = append(nonvariantLibs, name+llndkLibrarySuffix)
} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
vendorPublicLib := name + vendorPublicLibrarySuffix
@@ -1609,7 +1630,7 @@
// If the version is not specified, add dependency to the latest stubs library.
// The stubs library will be used when the depending module is built for APEX and
// the dependent module is not in the same APEX.
- latestVersion := latestStubsVersionFor(actx.Config(), name)
+ latestVersion := LatestStubsVersionFor(actx.Config(), name)
if version == "" && latestVersion != "" && versionVariantAvail {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "shared"},
@@ -1632,7 +1653,7 @@
lib = impl
}
- name, version := stubsLibNameAndVersion(lib)
+ name, version := StubsLibNameAndVersion(lib)
sharedLibNames = append(sharedLibNames, name)
addSharedLibDependencies(depTag, name, version)
@@ -1820,7 +1841,6 @@
// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
// or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
- llndkLibraries := llndkLibraries(ctx.Config())
check := func(child, parent android.Module) bool {
to, ok := child.(*Module)
if !ok {
@@ -1837,7 +1857,7 @@
return true
}
- if to.isVndkSp() || inList(child.Name(), *llndkLibraries) || Bool(to.VendorProperties.Double_loadable) {
+ if to.isVndkSp() || to.isLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) {
return false
}
@@ -1852,7 +1872,7 @@
}
if module, ok := ctx.Module().(*Module); ok {
if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
- if inList(ctx.ModuleName(), *llndkLibraries) || Bool(module.VendorProperties.Double_loadable) {
+ if module.isLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) {
ctx.WalkDeps(check)
}
}
@@ -1866,7 +1886,6 @@
directStaticDeps := []LinkableInterface{}
directSharedDeps := []LinkableInterface{}
- llndkLibraries := llndkLibraries(ctx.Config())
vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
reexportExporter := func(exporter exportedFlagsProducer) {
@@ -2138,7 +2157,7 @@
libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
libName = strings.TrimPrefix(libName, "prebuilt_")
- isLLndk := inList(libName, *llndkLibraries)
+ isLLndk := isLlndkLibrary(libName, ctx.Config())
isVendorPublicLib := inList(libName, *vendorPublicLibraries)
bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
@@ -2329,7 +2348,9 @@
if shared, ok := c.linker.(interface {
shared() bool
}); ok {
- return shared.shared()
+ // Stub libs and prebuilt libs in a versioned SDK are not
+ // installable to APEX even though they are shared libs.
+ return shared.shared() && !c.IsStubs() && c.ContainingSdk().Unversioned()
} else if _, ok := c.linker.(testPerSrc); ok {
return true
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 064b1a2..808968c 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -293,6 +293,7 @@
enabled: true,
},
nocrt: true,
+ stem: "libvndk-private",
}
cc_library {
@@ -303,6 +304,7 @@
support_system_process: true,
},
nocrt: true,
+ suffix: "-x",
}
cc_library {
@@ -313,6 +315,11 @@
support_system_process: true,
},
nocrt: true,
+ target: {
+ vendor: {
+ suffix: "-x",
+ },
+ },
}
`, config)
@@ -345,9 +352,9 @@
checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
- checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk_private.so"})
- checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk_private.so", "libvndk_sp_private.so"})
- checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp.so", "libvndk_sp_private.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so"})
+ checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so"})
checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", nil)
// merged & tagged & filtered-out(libclang_rt)
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
@@ -356,14 +363,27 @@
"LLNDK: libft2.so",
"LLNDK: libm.so",
"VNDK-SP: libc++.so",
- "VNDK-SP: libvndk_sp.so",
- "VNDK-SP: libvndk_sp_private.so",
+ "VNDK-SP: libvndk_sp-x.so",
+ "VNDK-SP: libvndk_sp_private-x.so",
+ "VNDK-core: libvndk-private.so",
"VNDK-core: libvndk.so",
- "VNDK-core: libvndk_private.so",
"VNDK-private: libft2.so",
- "VNDK-private: libvndk_private.so",
- "VNDK-private: libvndk_sp_private.so",
+ "VNDK-private: libvndk-private.so",
+ "VNDK-private: libvndk_sp_private-x.so",
})
+ checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{
+ "libc.so", "libdl.so", "libft2.so", "libm.so",
+ })
+ checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{
+ "libvndk-private.so", "libvndk.so",
+ })
+ checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{
+ "libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so",
+ })
+ checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{
+ "libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so",
+ })
+ checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{})
}
func TestVndkUsingCoreVariant(t *testing.T) {
@@ -405,7 +425,36 @@
`, config)
checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk2.so"})
- checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{"libvndk2.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{
+ "libc++.so", "libvndk2.so", "libvndk_sp.so",
+ })
+}
+
+func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
+ config := android.TestArchConfig(buildDir, nil)
+ config.TestProductVariables.DeviceVndkVersion = nil
+ config.TestProductVariables.Platform_vndk_version = nil
+
+ ctx := testCcWithConfig(t, `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `, config)
+
+ checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
+ "LLNDK: libc.so",
+ "LLNDK: libdl.so",
+ "LLNDK: libft2.so",
+ "LLNDK: libm.so",
+ "VNDK-SP: libc++.so",
+ "VNDK-core: libvndk.so",
+ "VNDK-private: libft2.so",
+ })
}
func TestVndkDepError(t *testing.T) {
@@ -1431,13 +1480,13 @@
symbol_file: "",
}`, config)
- assertArrayString(t, *vndkCoreLibraries(config),
+ assertMapKeys(t, vndkCoreLibraries(config),
[]string{"libvndk", "libvndkprivate"})
- assertArrayString(t, *vndkSpLibraries(config),
+ assertMapKeys(t, vndkSpLibraries(config),
[]string{"libc++", "libvndksp"})
- assertArrayString(t, *llndkLibraries(config),
+ assertMapKeys(t, llndkLibraries(config),
[]string{"libc", "libdl", "libft2", "libllndk", "libllndkprivate", "libm"})
- assertArrayString(t, *vndkPrivateLibraries(config),
+ assertMapKeys(t, vndkPrivateLibraries(config),
[]string{"libft2", "libllndkprivate", "libvndkprivate"})
vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
@@ -2419,6 +2468,11 @@
}
}
+func assertMapKeys(t *testing.T, m map[string]string, expected []string) {
+ t.Helper()
+ assertArrayString(t, android.SortedStringKeys(m), expected)
+}
+
func TestDefaults(t *testing.T) {
ctx := testCc(t, `
cc_defaults {
diff --git a/cc/compiler.go b/cc/compiler.go
index 438dee7..ff68101 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -320,8 +320,7 @@
}
if ctx.apexName() != "" {
- // TODO(b/142582178): remove the value for __ANDROID_APEX__
- flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__="+ctx.apexName())
+ flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__")
flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 2c3b973..577fa70 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -149,7 +149,7 @@
}
if fuzz.Properties.Fuzz_config != nil {
- configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.txt")
+ configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
Description: "fuzzer infrastructure configuration",
@@ -259,7 +259,7 @@
// The executable.
archDirs[archDir] = append(archDirs[archDir],
- fileToZip{ccModule.outputFile.Path(), ccModule.Name()})
+ fileToZip{ccModule.UnstrippedOutputFile(), ccModule.Name()})
// The corpora.
for _, corpusEntry := range fuzzModule.corpus {
diff --git a/cc/library.go b/cc/library.go
index 5a08879..8d90cd8 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -158,6 +158,10 @@
// listed in local_include_dirs.
Export_include_dirs []string `android:"arch_variant"`
+ // list of directories that will be added to the system include path
+ // using -isystem for this module and any module that links against this module.
+ Export_system_include_dirs []string `android:"arch_variant"`
+
Target struct {
Vendor struct {
// list of exported include directories, like
@@ -245,10 +249,13 @@
func (f *flagExporter) exportIncludes(ctx ModuleContext) {
f.dirs = append(f.dirs, f.exportedIncludes(ctx)...)
+ f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
}
func (f *flagExporter) exportIncludesAsSystem(ctx ModuleContext) {
+ // all dirs are force exported as system
f.systemDirs = append(f.systemDirs, f.exportedIncludes(ctx)...)
+ f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
}
func (f *flagExporter) reexportDirs(dirs ...android.Path) {
@@ -579,24 +586,28 @@
availableFor(string) bool
}
-func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
+func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
name := library.libName
if name == "" {
name = String(library.Properties.Stem)
if name == "" {
- name = ctx.baseModuleName()
+ name = baseModuleName
}
}
suffix := ""
- if ctx.useVndk() {
+ if useVndk {
suffix = String(library.Properties.Target.Vendor.Suffix)
}
if suffix == "" {
suffix = String(library.Properties.Suffix)
}
- name += suffix
+ return name + suffix
+}
+
+func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
+ name := library.getLibNameHelper(ctx.baseModuleName(), ctx.useVndk())
if ctx.isVndkExt() {
// vndk-ext lib should have the same name with original lib
@@ -1294,7 +1305,7 @@
var stubsVersionsLock sync.Mutex
-func latestStubsVersionFor(config android.Config, name string) string {
+func LatestStubsVersionFor(config android.Config, name string) string {
versions, ok := stubsVersionsFor(config)[name]
if ok && len(versions) > 0 {
// the versions are alreay sorted in ascending order
diff --git a/cc/makevars.go b/cc/makevars.go
index f9c58b9..e8cedf0 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -101,35 +101,6 @@
ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
- ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(*vndkCoreLibraries(ctx.Config()), " "))
- ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(*vndkSpLibraries(ctx.Config()), " "))
-
- // Make uses LLNDK_LIBRARIES to determine which libraries to install.
- // HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
- // Therefore, by removing the library here, we cause it to only be installed if libc
- // depends on it.
- installedLlndkLibraries := []string{}
-
- // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
- // they been moved to an apex.
- movedToApexLlndkLibraries := []string{}
- for _, lib := range *llndkLibraries(ctx.Config()) {
- if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
- continue
- }
- installedLlndkLibraries = append(installedLlndkLibraries, lib)
-
- // Skip bionic libs, they are handled in different manner
- if android.DirectlyInAnyApex(¬OnHostContext{}, lib) && !isBionic(lib) {
- movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
- }
- }
- ctx.Strict("LLNDK_LIBRARIES", strings.Join(installedLlndkLibraries, " "))
- ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
-
- ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(*vndkPrivateLibraries(ctx.Config()), " "))
- ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(*vndkUsingCoreVariantLibraries(ctx.Config()), " "))
-
// Filter vendor_public_library that are exported to make
exportedVendorPublicLibraries := []string{}
ctx.VisitAllModules(func(module android.Module) {
diff --git a/cc/sabi.go b/cc/sabi.go
index 8a9eff0..4760313 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -78,7 +78,7 @@
func sabiDepsMutator(mctx android.TopDownMutatorContext) {
if c, ok := mctx.Module().(*Module); ok &&
- ((c.IsVndk() && c.UseVndk()) || inList(c.Name(), *llndkLibraries(mctx.Config())) ||
+ ((c.IsVndk() && c.UseVndk()) || c.isLlndk(mctx.Config()) ||
(c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) {
mctx.VisitDirectDeps(func(m android.Module) {
tag := mctx.OtherModuleDependencyTag(m)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index e4c6b1c..a3b4e8e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -873,7 +873,7 @@
}
if mctx.Device() && runtimeLibrary != "" {
- if inList(runtimeLibrary, *llndkLibraries(mctx.Config())) && !c.static() && c.UseVndk() {
+ if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() {
runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
}
diff --git a/cc/test.go b/cc/test.go
index 0e66e28..5c49d6e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -173,7 +173,7 @@
if test, ok := m.linker.(testPerSrc); ok {
numTests := len(test.srcs())
if test.testPerSrc() && numTests > 0 {
- if duplicate, found := checkDuplicate(test.srcs()); found {
+ if duplicate, found := android.CheckDuplicate(test.srcs()); found {
mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
return
}
@@ -206,17 +206,6 @@
}
}
-func checkDuplicate(values []string) (duplicate string, found bool) {
- seen := make(map[string]string)
- for _, v := range values {
- if duplicate, found = seen[v]; found {
- return
- }
- seen[v] = v
- }
- return
-}
-
type testDecorator struct {
Properties TestProperties
linker *baseLinker
diff --git a/cc/vndk.go b/cc/vndk.go
index 47c3177..d6c2f6f 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -17,8 +17,8 @@
import (
"encoding/json"
"errors"
+ "fmt"
"path/filepath"
- "sort"
"strings"
"sync"
@@ -207,34 +207,44 @@
headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
)
-func vndkCoreLibraries(config android.Config) *[]string {
+func vndkCoreLibraries(config android.Config) map[string]string {
return config.Once(vndkCoreLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return make(map[string]string)
+ }).(map[string]string)
}
-func vndkSpLibraries(config android.Config) *[]string {
+func vndkSpLibraries(config android.Config) map[string]string {
return config.Once(vndkSpLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return make(map[string]string)
+ }).(map[string]string)
}
-func llndkLibraries(config android.Config) *[]string {
+func isLlndkLibrary(baseModuleName string, config android.Config) bool {
+ _, ok := llndkLibraries(config)[baseModuleName]
+ return ok
+}
+
+func llndkLibraries(config android.Config) map[string]string {
return config.Once(llndkLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return make(map[string]string)
+ }).(map[string]string)
}
-func vndkPrivateLibraries(config android.Config) *[]string {
+func isVndkPrivateLibrary(baseModuleName string, config android.Config) bool {
+ _, ok := vndkPrivateLibraries(config)[baseModuleName]
+ return ok
+}
+
+func vndkPrivateLibraries(config android.Config) map[string]string {
return config.Once(vndkPrivateLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return make(map[string]string)
+ }).(map[string]string)
}
-func vndkUsingCoreVariantLibraries(config android.Config) *[]string {
+func vndkUsingCoreVariantLibraries(config android.Config) map[string]string {
return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return make(map[string]string)
+ }).(map[string]string)
}
func modulePaths(config android.Config) map[string]string {
@@ -265,63 +275,44 @@
func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
lib := m.linker.(*llndkStubDecorator)
- name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
+ name := m.BaseModuleName()
+ filename := m.BaseModuleName() + ".so"
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
- llndkLibraries := llndkLibraries(mctx.Config())
- if !inList(name, *llndkLibraries) {
- *llndkLibraries = append(*llndkLibraries, name)
- sort.Strings(*llndkLibraries)
- }
+ llndkLibraries(mctx.Config())[name] = filename
if !Bool(lib.Properties.Vendor_available) {
- vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
- if !inList(name, *vndkPrivateLibraries) {
- *vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
- sort.Strings(*vndkPrivateLibraries)
- }
+ vndkPrivateLibraries(mctx.Config())[name] = filename
}
}
func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
- name := strings.TrimPrefix(m.Name(), "prebuilt_")
+ name := m.BaseModuleName()
+ filename, err := getVndkFileName(m)
+ if err != nil {
+ panic(err)
+ }
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
- modulePaths := modulePaths(mctx.Config())
+ modulePaths(mctx.Config())[name] = mctx.ModuleDir()
+
if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
m.Properties.MustUseVendorVariant = true
}
- if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
- vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
- if !inList(name, *vndkUsingCoreVariantLibraries) {
- *vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
- sort.Strings(*vndkUsingCoreVariantLibraries)
- }
+ if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant {
+ vndkUsingCoreVariantLibraries(mctx.Config())[name] = filename
}
+
if m.vndkdep.isVndkSp() {
- vndkSpLibraries := vndkSpLibraries(mctx.Config())
- if !inList(name, *vndkSpLibraries) {
- *vndkSpLibraries = append(*vndkSpLibraries, name)
- sort.Strings(*vndkSpLibraries)
- modulePaths[name] = mctx.ModuleDir()
- }
+ vndkSpLibraries(mctx.Config())[name] = filename
} else {
- vndkCoreLibraries := vndkCoreLibraries(mctx.Config())
- if !inList(name, *vndkCoreLibraries) {
- *vndkCoreLibraries = append(*vndkCoreLibraries, name)
- sort.Strings(*vndkCoreLibraries)
- modulePaths[name] = mctx.ModuleDir()
- }
+ vndkCoreLibraries(mctx.Config())[name] = filename
}
if !Bool(m.VendorProperties.Vendor_available) {
- vndkPrivateLibraries := vndkPrivateLibraries(mctx.Config())
- if !inList(name, *vndkPrivateLibraries) {
- *vndkPrivateLibraries = append(*vndkPrivateLibraries, name)
- sort.Strings(*vndkPrivateLibraries)
- }
+ vndkPrivateLibraries(mctx.Config())[name] = filename
}
}
@@ -395,9 +386,20 @@
return &vndkSnapshotSingleton{}
}
-type vndkSnapshotSingleton struct{}
+type vndkSnapshotSingleton struct {
+ installedLlndkLibraries []string
+ llnkdLibrariesFile android.Path
+ vndkSpLibrariesFile android.Path
+ vndkCoreLibrariesFile android.Path
+ vndkPrivateLibrariesFile android.Path
+ vndkCoreVariantLibrariesFile android.Path
+ vndkLibrariesFile android.Path
+}
func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // build these files even if PlatformVndkVersion or BoardVndkVersion is not set
+ c.buildVndkLibrariesTxtFiles(ctx)
+
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
if ctx.DeviceConfig().VndkVersion() != "current" {
return
@@ -411,8 +413,6 @@
return
}
- c.buildVndkLibrariesTxtFiles(ctx)
-
outputs := vndkSnapshotOutputs(ctx.Config())
snapshotDir := "vndk-snapshot"
@@ -481,9 +481,9 @@
}
}
- vndkCoreLibraries := vndkCoreLibraries(ctx.Config())
- vndkSpLibraries := vndkSpLibraries(ctx.Config())
- vndkPrivateLibraries := vndkPrivateLibraries(ctx.Config())
+ vndkCoreLibraries := android.SortedStringKeys(vndkCoreLibraries(ctx.Config()))
+ vndkSpLibraries := android.SortedStringKeys(vndkSpLibraries(ctx.Config()))
+ vndkPrivateLibraries := android.SortedStringKeys(vndkPrivateLibraries(ctx.Config()))
var generatedHeaders android.Paths
includeDirs := make(map[string]bool)
@@ -540,9 +540,9 @@
return nil, "", false
}
name := ctx.ModuleName(m)
- if inList(name, *vndkCoreLibraries) {
+ if inList(name, vndkCoreLibraries) {
return l, filepath.Join("shared", "vndk-core"), true
- } else if inList(name, *vndkSpLibraries) {
+ } else if inList(name, vndkSpLibraries) {
return l, filepath.Join("shared", "vndk-sp"), true
} else {
return nil, "", false
@@ -628,9 +628,9 @@
}
}
- installSnapshotFileFromContent(android.JoinWithSuffix(*vndkCoreLibraries, ".so", "\\n"),
+ installSnapshotFileFromContent(android.JoinWithSuffix(vndkCoreLibraries, ".so", "\\n"),
filepath.Join(configsDir, "vndkcore.libraries.txt"))
- installSnapshotFileFromContent(android.JoinWithSuffix(*vndkPrivateLibraries, ".so", "\\n"),
+ installSnapshotFileFromContent(android.JoinWithSuffix(vndkPrivateLibraries, ".so", "\\n"),
filepath.Join(configsDir, "vndkprivate.libraries.txt"))
var modulePathTxtBuilder strings.Builder
@@ -653,75 +653,60 @@
filepath.Join(configsDir, "module_paths.txt"))
}
-func installListFile(ctx android.SingletonContext, list []string, pathComponents ...string) android.OutputPath {
- out := android.PathForOutput(ctx, pathComponents...)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: out,
- Description: "Writing " + out.String(),
- Args: map[string]string{
- "content": strings.Join(list, "\\n"),
- },
- })
- return out
+func getVndkFileName(m *Module) (string, error) {
+ if library, ok := m.linker.(*libraryDecorator); ok {
+ return library.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+ }
+ if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
+ return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+ }
+ return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
}
func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
- var (
- llndk, vndkcore, vndksp, vndkprivate, vndkcorevariant, merged []string
- )
- vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- config := ctx.Config()
- ctx.VisitAllModules(func(m android.Module) {
- if !m.Enabled() {
- return
+ // Make uses LLNDK_LIBRARIES to determine which libraries to install.
+ // HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+ // Therefore, by removing the library here, we cause it to only be installed if libc
+ // depends on it.
+ installedLlndkLibraries := make(map[string]string)
+ for lib, filename := range llndkLibraries(ctx.Config()) {
+ if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
+ continue
}
- c, ok := m.(*Module)
- if !ok || c.Os().Class != android.Device {
- return
- }
- lib, ok := c.linker.(interface{ shared() bool })
- if !ok || !lib.shared() {
- return
- }
+ installedLlndkLibraries[lib] = filename
+ }
- if !c.OutputFile().Valid() {
- return
- }
+ installListFile := func(list []string, fileName string) android.Path {
+ out := android.PathForOutput(ctx, "vndk", fileName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: out,
+ Description: "Writing " + out.String(),
+ Args: map[string]string{
+ "content": strings.Join(list, "\\n"),
+ },
+ })
+ return out
+ }
- filename := c.OutputFile().Path().Base()
- if c.isLlndk(config) {
- llndk = append(llndk, filename)
- if c.isVndkPrivate(config) {
- vndkprivate = append(vndkprivate, filename)
- }
- } else if c.vndkVersion() == vndkVersion && c.IsVndk() && !c.isVndkExt() {
- if c.isVndkSp() {
- vndksp = append(vndksp, filename)
- } else {
- vndkcore = append(vndkcore, filename)
- }
- if c.isVndkPrivate(config) {
- vndkprivate = append(vndkprivate, filename)
- }
- if ctx.DeviceConfig().VndkUseCoreVariant() && !c.MustUseVendorVariant() {
- vndkcorevariant = append(vndkcorevariant, filename)
- }
- }
- })
- llndk = android.SortedUniqueStrings(llndk)
- vndkcore = android.SortedUniqueStrings(vndkcore)
- vndksp = android.SortedUniqueStrings(vndksp)
- vndkprivate = android.SortedUniqueStrings(vndkprivate)
- vndkcorevariant = android.SortedUniqueStrings(vndkcorevariant)
+ c.installedLlndkLibraries = android.SortedStringKeys(installedLlndkLibraries)
- installListFile(ctx, llndk, "vndk", "llndk.libraries.txt")
- installListFile(ctx, vndkcore, "vndk", "vndkcore.libraries.txt")
- installListFile(ctx, vndksp, "vndk", "vndksp.libraries.txt")
- installListFile(ctx, vndkprivate, "vndk", "vndkprivate.libraries.txt")
- installListFile(ctx, vndkcorevariant, "vndk", "vndkcorevariant.libraries.txt")
+ llndk := android.SortedStringMapValues(installedLlndkLibraries)
+ vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
+ vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
+ vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+ vndkcorevariant := android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
+
+ c.llnkdLibrariesFile = installListFile(llndk, "llndk.libraries.txt")
+ c.vndkCoreLibrariesFile = installListFile(vndkcore, "vndkcore.libraries.txt")
+ c.vndkSpLibrariesFile = installListFile(vndksp, "vndksp.libraries.txt")
+ c.vndkPrivateLibrariesFile = installListFile(vndkprivate, "vndkprivate.libraries.txt")
+ c.vndkCoreVariantLibrariesFile = installListFile(vndkcorevariant, "vndkcorevariant.libraries.txt")
// merged & tagged & filtered-out(libclang_rt)
+ // Since each target have different set of libclang_rt.* files,
+ // keep the common set of files in vndk.libraries.txt
+ var merged []string
filterOutLibClangRt := func(libList []string) (filtered []string) {
for _, lib := range libList {
if !strings.HasPrefix(lib, "libclang_rt.") {
@@ -734,6 +719,31 @@
merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+ c.vndkLibrariesFile = installListFile(merged, "vndk.libraries.txt")
+}
- installListFile(ctx, merged, "vndk", "vndk.libraries.txt")
+func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+ // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
+ // they been moved to an apex.
+ movedToApexLlndkLibraries := []string{}
+ for _, lib := range c.installedLlndkLibraries {
+ // Skip bionic libs, they are handled in different manner
+ if android.DirectlyInAnyApex(¬OnHostContext{}, lib) && !isBionic(lib) {
+ movedToApexLlndkLibraries = append(movedToApexLlndkLibraries, lib)
+ }
+ }
+ ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(movedToApexLlndkLibraries, " "))
+ ctx.Strict("LLNDK_LIBRARIES", strings.Join(c.installedLlndkLibraries, " "))
+ ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkCoreLibraries(ctx.Config())), " "))
+ ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(android.SortedStringKeys(vndkSpLibraries(ctx.Config())), " "))
+ ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(android.SortedStringKeys(vndkPrivateLibraries(ctx.Config())), " "))
+ ctx.Strict("VNDK_USING_CORE_VARIANT_LIBRARIES", strings.Join(android.SortedStringKeys(vndkUsingCoreVariantLibraries(ctx.Config())), " "))
+
+ ctx.Strict("LLNDK_LIBRARIES_FILE", c.llnkdLibrariesFile.String())
+ ctx.Strict("VNDKCORE_LIBRARIES_FILE", c.vndkCoreLibrariesFile.String())
+ ctx.Strict("VNDKSP_LIBRARIES_FILE", c.vndkSpLibrariesFile.String())
+ ctx.Strict("VNDKPRIVATE_LIBRARIES_FILE", c.vndkPrivateLibrariesFile.String())
+ ctx.Strict("VNDKCOREVARIANT_LIBRARIES_FILE", c.vndkCoreVariantLibrariesFile.String())
+
+ ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
}
diff --git a/rust/androidmk.go b/rust/androidmk.go
index f933cfb..49115f2 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -72,6 +72,8 @@
mod.subAndroidMk(&ret, mod.compiler)
+ ret.SubName += mod.Properties.SubName
+
return ret
}
@@ -85,6 +87,11 @@
})
}
+func (test *testBinaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
+ test.binaryDecorator.AndroidMk(ctx, ret)
+ ret.SubName = "_" + String(test.baseCompiler.Properties.Stem)
+}
+
func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ctx.subAndroidMk(ret, library.baseCompiler)
diff --git a/rust/binary_test.go b/rust/binary_test.go
index cd41fcf..ab2dae1 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -36,11 +36,20 @@
fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Output("fizz-buzz")
fizzBuzzDynamic := ctx.ModuleForTests("fizz-buzz-dynamic", "linux_glibc_x86_64").Output("fizz-buzz-dynamic")
- if !strings.Contains(fizzBuzzDynamic.Args["rustcFlags"], "prefer-dynamic") {
- t.Errorf("missing prefer-dynamic flag, rustcFlags: %#v", fizzBuzzDynamic.Args["rustcFlags"])
+ // Do not compile binary modules with the --test flag.
+ flags := fizzBuzzDynamic.Args["rustcFlags"]
+ if strings.Contains(flags, "--test") {
+ t.Errorf("extra --test flag, rustcFlags: %#v", flags)
+ }
+ if !strings.Contains(flags, "prefer-dynamic") {
+ t.Errorf("missing prefer-dynamic flag, rustcFlags: %#v", flags)
}
- if strings.Contains(fizzBuzz.Args["rustcFlags"], "prefer-dynamic") {
- t.Errorf("unexpected prefer-dynamic flag, rustcFlags: %#v", fizzBuzz.Args["rustcFlags"])
+ flags = fizzBuzz.Args["rustcFlags"]
+ if strings.Contains(flags, "--test") {
+ t.Errorf("extra --test flag, rustcFlags: %#v", flags)
+ }
+ if strings.Contains(flags, "prefer-dynamic") {
+ t.Errorf("unexpected prefer-dynamic flag, rustcFlags: %#v", flags)
}
}
diff --git a/rust/rust.go b/rust/rust.go
index ce81b91..ec3b590 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -39,6 +39,7 @@
android.RegisterModuleType("rust_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
+ ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
})
pctx.Import("android/soong/rust/config")
}
@@ -58,6 +59,7 @@
AndroidMkProcMacroLibs []string
AndroidMkSharedLibs []string
AndroidMkStaticLibs []string
+ SubName string `blueprint:"mutated"`
}
type Module struct {
@@ -495,9 +497,10 @@
}
var (
- rlibDepTag = dependencyTag{name: "rlibTag", library: true}
- dylibDepTag = dependencyTag{name: "dylib", library: true}
- procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
+ rlibDepTag = dependencyTag{name: "rlibTag", library: true}
+ dylibDepTag = dependencyTag{name: "dylib", library: true}
+ procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
+ testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
)
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
diff --git a/rust/test.go b/rust/test.go
new file mode 100644
index 0000000..816e3c7
--- /dev/null
+++ b/rust/test.go
@@ -0,0 +1,116 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+)
+
+// A test module is a binary module with extra --test compiler flag
+// and different default installation directory.
+// In golang, inheriance is written as a component.
+type testBinaryDecorator struct {
+ *binaryDecorator
+}
+
+func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testBinaryDecorator) {
+ module := newModule(hod, android.MultilibFirst)
+
+ test := &testBinaryDecorator{
+ binaryDecorator: &binaryDecorator{
+ // TODO(chh): set up dir64?
+ baseCompiler: NewBaseCompiler("testcases", ""),
+ },
+ }
+
+ module.compiler = test
+
+ return module, test
+}
+
+func (test *testBinaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
+ flags = test.binaryDecorator.compilerFlags(ctx, flags)
+ flags.RustFlags = append(flags.RustFlags, "--test")
+ return flags
+}
+
+func init() {
+ // Rust tests are binary files built with --test.
+ android.RegisterModuleType("rust_test", RustTestFactory)
+ android.RegisterModuleType("rust_test_host", RustTestHostFactory)
+}
+
+func RustTestFactory() android.Module {
+ module, _ := NewRustTest(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+func RustTestHostFactory() android.Module {
+ module, _ := NewRustTest(android.HostSupported)
+ return module.Init()
+}
+
+func (test *testBinaryDecorator) testPerSrc() bool {
+ return true
+}
+
+func (test *testBinaryDecorator) srcs() []string {
+ return test.Properties.Srcs
+}
+
+func (test *testBinaryDecorator) setSrc(name, src string) {
+ test.Properties.Srcs = []string{src}
+ test.baseCompiler.Properties.Stem = StringPtr(name)
+}
+
+func (test *testBinaryDecorator) unsetSrc() {
+ test.Properties.Srcs = nil
+ test.baseCompiler.Properties.Stem = StringPtr("")
+}
+
+type testPerSrc interface {
+ testPerSrc() bool
+ srcs() []string
+ setSrc(string, string)
+ unsetSrc()
+}
+
+var _ testPerSrc = (*testBinaryDecorator)(nil)
+
+func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*Module); ok {
+ if test, ok := m.compiler.(testPerSrc); ok {
+ numTests := len(test.srcs())
+ if test.testPerSrc() && numTests > 0 {
+ if duplicate, found := android.CheckDuplicate(test.srcs()); found {
+ mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
+ return
+ }
+ testNames := make([]string, numTests)
+ for i, src := range test.srcs() {
+ testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
+ }
+ // TODO(chh): Add an "all tests" variation like cc/test.go?
+ tests := mctx.CreateLocalVariations(testNames...)
+ for i, src := range test.srcs() {
+ tests[i].(*Module).compiler.(testPerSrc).setSrc(testNames[i], src)
+ }
+ }
+ }
+ }
+}
diff --git a/rust/test_test.go b/rust/test_test.go
new file mode 100644
index 0000000..aa4c3c8
--- /dev/null
+++ b/rust/test_test.go
@@ -0,0 +1,43 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package rust
+
+import (
+ "strings"
+ "testing"
+)
+
+// Check if rust_test_host accepts multiple source files and applies --test flag.
+func TestRustTest(t *testing.T) {
+ ctx := testRust(t, `
+ rust_test_host {
+ name: "my_test",
+ srcs: ["foo.rs", "src/bar.rs"],
+ relative_install_path: "rust/my-test",
+ }`)
+
+ for _, name := range []string{"foo", "bar"} {
+ testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64_"+name)
+ testingBuildParams := testingModule.Output(name)
+ rustcFlags := testingBuildParams.Args["rustcFlags"]
+ if !strings.Contains(rustcFlags, "--test") {
+ t.Errorf("%v missing --test flag, rustcFlags: %#v", name, rustcFlags)
+ }
+ outPath := "/my_test/linux_glibc_x86_64_" + name + "/" + name
+ if !strings.Contains(testingBuildParams.Output.String(), outPath) {
+ t.Errorf("wrong output: %v expect: %v", testingBuildParams.Output, outPath)
+ }
+ }
+}
diff --git a/rust/testing.go b/rust/testing.go
index cd63084..24defa6 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -168,6 +168,8 @@
ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
ctx.RegisterModuleType("rust_binary", android.ModuleFactoryAdaptor(RustBinaryFactory))
ctx.RegisterModuleType("rust_binary_host", android.ModuleFactoryAdaptor(RustBinaryHostFactory))
+ ctx.RegisterModuleType("rust_test", android.ModuleFactoryAdaptor(RustTestFactory))
+ ctx.RegisterModuleType("rust_test_host", android.ModuleFactoryAdaptor(RustTestHostFactory))
ctx.RegisterModuleType("rust_library", android.ModuleFactoryAdaptor(RustLibraryFactory))
ctx.RegisterModuleType("rust_library_host", android.ModuleFactoryAdaptor(RustLibraryHostFactory))
ctx.RegisterModuleType("rust_library_host_rlib", android.ModuleFactoryAdaptor(RustLibraryRlibHostFactory))
@@ -190,6 +192,7 @@
// rust mutators
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
+ ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
})
bp = bp + GatherRequiredDepsForTest()
diff --git a/sdk/sdk.go b/sdk/sdk.go
index d189043..002fb5d 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -24,6 +24,7 @@
// This package doesn't depend on the apex package, but import it to make its mutators to be
// registered before mutators in this package. See RegisterPostDepsMutators for more details.
_ "android/soong/apex"
+ "android/soong/cc"
)
func init() {
@@ -148,10 +149,17 @@
targets := mctx.MultiTargets()
for _, target := range targets {
- mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: "core"},
- {Mutator: "link", Variation: "shared"},
- }...), sdkMemberDepTag, m.properties.Native_shared_libs...)
+ for _, lib := range m.properties.Native_shared_libs {
+ name, version := cc.StubsLibNameAndVersion(lib)
+ if version == "" {
+ version = cc.LatestStubsVersionFor(mctx.Config(), name)
+ }
+ mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "image", Variation: "core"},
+ {Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: version},
+ }...), sdkMemberDepTag, name)
+ }
}
}
}
diff --git a/sdk/update.go b/sdk/update.go
index 5235c9e..ce60827 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -24,6 +24,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/java"
)
@@ -32,21 +33,31 @@
// generatedFile abstracts operations for writing contents into a file and emit a build rule
// for the file.
type generatedFile struct {
- path android.OutputPath
- content strings.Builder
+ path android.OutputPath
+ content strings.Builder
+ indentLevel int
}
func newGeneratedFile(ctx android.ModuleContext, name string) *generatedFile {
return &generatedFile{
- path: android.PathForModuleOut(ctx, name).OutputPath,
+ path: android.PathForModuleOut(ctx, name).OutputPath,
+ indentLevel: 0,
}
}
+func (gf *generatedFile) indent() {
+ gf.indentLevel++
+}
+
+func (gf *generatedFile) dedent() {
+ gf.indentLevel--
+}
+
func (gf *generatedFile) printfln(format string, args ...interface{}) {
// ninja consumes newline characters in rspfile_content. Prevent it by
// escaping the backslash in the newline character. The extra backshash
// is removed when the rspfile is written to the actual script file
- fmt.Fprintf(&(gf.content), format+"\\n", args...)
+ fmt.Fprintf(&(gf.content), strings.Repeat(" ", gf.indentLevel)+format+"\\n", args...)
}
func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
@@ -61,34 +72,187 @@
rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base())
}
-func (s *sdk) javaMemberNames(ctx android.ModuleContext) []string {
- result := []string{}
+func (s *sdk) javaLibs(ctx android.ModuleContext) []*java.Library {
+ result := []*java.Library{}
ctx.VisitDirectDeps(func(m android.Module) {
- if _, ok := m.(*java.Library); ok {
- result = append(result, m.Name())
+ if j, ok := m.(*java.Library); ok {
+ result = append(result, j)
}
})
return result
}
-// buildAndroidBp creates the blueprint file that defines prebuilt modules for each of
-// the SDK members, and the sdk_snapshot module for the specified version
-func (s *sdk) buildAndroidBp(ctx android.ModuleContext, version string) android.OutputPath {
- bp := newGeneratedFile(ctx, "blueprint-"+version+".sh")
+// archSpecificNativeLibInfo represents an arch-specific variant of a native lib
+type archSpecificNativeLibInfo struct {
+ name string
+ archType string
+ exportedIncludeDirs android.Paths
+ exportedSystemIncludeDirs android.Paths
+ exportedFlags []string
+ outputFile android.Path
+}
- makePrebuiltName := func(name string) string {
- return ctx.ModuleName() + "_" + name + string(android.SdkVersionSeparator) + version
+func (lib *archSpecificNativeLibInfo) signature() string {
+ return fmt.Sprintf("%v %v %v %v",
+ lib.name,
+ lib.exportedIncludeDirs.Strings(),
+ lib.exportedSystemIncludeDirs.Strings(),
+ lib.exportedFlags)
+}
+
+// nativeLibInfo represents a collection of arch-specific modules having the same name
+type nativeLibInfo struct {
+ name string
+ archVariants []archSpecificNativeLibInfo
+ // hasArchSpecificFlags is set to true if modules for each architecture all have the same
+ // include dirs, flags, etc, in which case only those of the first arch is selected.
+ hasArchSpecificFlags bool
+}
+
+// nativeMemberInfos collects all cc.Modules that are member of an SDK.
+func (s *sdk) nativeMemberInfos(ctx android.ModuleContext) []*nativeLibInfo {
+ infoMap := make(map[string]*nativeLibInfo)
+
+ // Collect cc.Modules
+ ctx.VisitDirectDeps(func(m android.Module) {
+ ccModule, ok := m.(*cc.Module)
+ if !ok {
+ return
+ }
+ depName := ctx.OtherModuleName(m)
+
+ if _, ok := infoMap[depName]; !ok {
+ infoMap[depName] = &nativeLibInfo{name: depName}
+ }
+
+ info := infoMap[depName]
+ info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{
+ name: ccModule.BaseModuleName(),
+ archType: ccModule.Target().Arch.ArchType.String(),
+ exportedIncludeDirs: ccModule.ExportedIncludeDirs(),
+ exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
+ exportedFlags: ccModule.ExportedFlags(),
+ outputFile: ccModule.OutputFile().Path(),
+ })
+ })
+
+ // Determine if include dirs and flags for each module are different across arch-specific
+ // modules or not. And set hasArchSpecificFlags accordingly
+ for _, info := range infoMap {
+ // by default, include paths and flags are assumed to be the same across arches
+ info.hasArchSpecificFlags = false
+ oldSignature := ""
+ for _, av := range info.archVariants {
+ newSignature := av.signature()
+ if oldSignature == "" {
+ oldSignature = newSignature
+ }
+ if oldSignature != newSignature {
+ info.hasArchSpecificFlags = true
+ break
+ }
+ }
}
- javaLibs := s.javaMemberNames(ctx)
- for _, name := range javaLibs {
- prebuiltName := makePrebuiltName(name)
- jar := filepath.Join("java", name, "stub.jar")
+ var list []*nativeLibInfo
+ for _, v := range infoMap {
+ list = append(list, v)
+ }
+ return list
+}
+// SDK directory structure
+// <sdk_root>/
+// Android.bp : definition of a 'sdk' module is here. This is a hand-made one.
+// <api_ver>/ : below this directory are all auto-generated
+// Android.bp : definition of 'sdk_snapshot' module is here
+// aidl/
+// frameworks/base/core/..../IFoo.aidl : an exported AIDL file
+// java/
+// java/<module_name>/stub.jar : a stub jar for a java library 'module_name'
+// include/
+// bionic/libc/include/stdlib.h : an exported header file
+// include_gen/
+// com/android/.../IFoo.h : a generated header file
+// <arch>/include/ : arch-specific exported headers
+// <arch>/include_gen/ : arch-specific generated headers
+// <arch>/lib/
+// libFoo.so : a stub library
+
+const (
+ aidlIncludeDir = "aidl"
+ javaStubDir = "java"
+ javaStubFile = "stub.jar"
+ nativeIncludeDir = "include"
+ nativeGeneratedIncludeDir = "include_gen"
+ nativeStubDir = "lib"
+ nativeStubFileSuffix = ".so"
+)
+
+// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
+func javaStubFilePathFor(javaLib *java.Library) string {
+ return filepath.Join(javaStubDir, javaLib.Name(), javaStubFile)
+}
+
+// path to the stub file of a native shared library. Relative to <sdk_root>/<api_dir>
+func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string {
+ return filepath.Join(lib.archType,
+ nativeStubDir, lib.name+nativeStubFileSuffix)
+}
+
+// paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
+func nativeIncludeDirPathsFor(ctx android.ModuleContext, lib archSpecificNativeLibInfo,
+ systemInclude bool, archSpecific bool) []string {
+ var result []string
+ buildDir := ctx.Config().BuildDir()
+ var includeDirs []android.Path
+ if !systemInclude {
+ includeDirs = lib.exportedIncludeDirs
+ } else {
+ includeDirs = lib.exportedSystemIncludeDirs
+ }
+ for _, dir := range includeDirs {
+ var path string
+ if gen := strings.HasPrefix(dir.String(), buildDir); gen {
+ path = filepath.Join(nativeGeneratedIncludeDir, dir.Rel())
+ } else {
+ path = filepath.Join(nativeIncludeDir, dir.String())
+ }
+ if archSpecific {
+ path = filepath.Join(lib.archType, path)
+ }
+ result = append(result, path)
+ }
+ return result
+}
+
+// A name that uniquely identifies an prebuilt SDK member for a version of SDK snapshot
+// This isn't visible to users, so could be changed in future.
+func versionedSdkMemberName(ctx android.ModuleContext, memberName string, version string) string {
+ return ctx.ModuleName() + "_" + memberName + string(android.SdkVersionSeparator) + version
+}
+
+// arm64, arm, x86, x86_64, etc.
+func archTypeOf(module android.Module) string {
+ return module.Target().Arch.ArchType.String()
+}
+
+// buildAndroidBp creates the blueprint file that defines prebuilt modules for each of
+// the SDK members, and the entire sdk_snapshot module for the specified version
+func (s *sdk) buildAndroidBp(ctx android.ModuleContext, version string) android.OutputPath {
+ bp := newGeneratedFile(ctx, "blueprint-"+version+".bp")
+ bp.printfln("// This is auto-generated. DO NOT EDIT.")
+ bp.printfln("")
+
+ javaLibModules := s.javaLibs(ctx)
+ for _, m := range javaLibModules {
+ name := m.Name()
bp.printfln("java_import {")
- bp.printfln(" name: %q,", prebuiltName)
- bp.printfln(" jars: [%q],", jar)
- bp.printfln(" sdk_member_name: %q,", name)
+ bp.indent()
+ bp.printfln("name: %q,", versionedSdkMemberName(ctx, name, version))
+ bp.printfln("sdk_member_name: %q,", name)
+ bp.printfln("jars: [%q],", javaStubFilePathFor(m))
+ bp.dedent()
bp.printfln("}")
bp.printfln("")
@@ -96,25 +260,92 @@
// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
// so that this module does not eclipse the unversioned module if it exists.
bp.printfln("java_import {")
- bp.printfln(" name: %q,", name)
- bp.printfln(" jars: [%q],", jar)
- bp.printfln(" prefer: false,")
+ bp.indent()
+ bp.printfln("name: %q,", name)
+ bp.printfln("jars: [%q],", javaStubFilePathFor(m))
+ bp.printfln("prefer: false,")
+ bp.dedent()
bp.printfln("}")
bp.printfln("")
-
}
- // TODO(jiyong): emit cc_prebuilt_library_shared for the native libs
+ nativeLibInfos := s.nativeMemberInfos(ctx)
+ for _, info := range nativeLibInfos {
+ bp.printfln("cc_prebuilt_library_shared {")
+ bp.indent()
+ bp.printfln("name: %q,", versionedSdkMemberName(ctx, info.name, version))
+ bp.printfln("sdk_member_name: %q,", info.name)
+
+ // a function for emitting include dirs
+ printExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, systemInclude bool) {
+ includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
+ if len(includeDirs) == 0 {
+ return
+ }
+ if !systemInclude {
+ bp.printfln("export_include_dirs: [")
+ } else {
+ bp.printfln("export_system_include_dirs: [")
+ }
+ bp.indent()
+ for _, dir := range includeDirs {
+ bp.printfln("%q,", dir)
+ }
+ bp.dedent()
+ bp.printfln("],")
+ }
+
+ if !info.hasArchSpecificFlags {
+ printExportedDirsForNativeLibs(info.archVariants[0], false /*systemInclude*/)
+ printExportedDirsForNativeLibs(info.archVariants[0], true /*systemInclude*/)
+ }
+
+ bp.printfln("arch: {")
+ bp.indent()
+ for _, av := range info.archVariants {
+ bp.printfln("%s: {", av.archType)
+ bp.indent()
+ bp.printfln("srcs: [%q],", nativeStubFilePathFor(av))
+ if info.hasArchSpecificFlags {
+ // export_* properties are added inside the arch: {<arch>: {...}} block
+ printExportedDirsForNativeLibs(av, false /*systemInclude*/)
+ printExportedDirsForNativeLibs(av, true /*systemInclude*/)
+ }
+ bp.dedent()
+ bp.printfln("},") // <arch>
+ }
+ bp.dedent()
+ bp.printfln("},") // arch
+ bp.printfln("stl: \"none\",")
+ bp.printfln("system_shared_libs: [],")
+ bp.dedent()
+ bp.printfln("}") // cc_prebuilt_library_shared
+ bp.printfln("")
+ }
bp.printfln("sdk_snapshot {")
- bp.printfln(" name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+version)
- bp.printfln(" java_libs: [")
- for _, n := range javaLibs {
- bp.printfln(" %q,", makePrebuiltName(n))
+ bp.indent()
+ bp.printfln("name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+version)
+ if len(javaLibModules) > 0 {
+ bp.printfln("java_libs: [")
+ bp.indent()
+ for _, m := range javaLibModules {
+ bp.printfln("%q,", versionedSdkMemberName(ctx, m.Name(), version))
+ }
+ bp.dedent()
+ bp.printfln("],") // java_libs
}
- bp.printfln(" ],")
- // TODO(jiyong): emit native_shared_libs
- bp.printfln("}")
+ if len(nativeLibInfos) > 0 {
+ bp.printfln("native_shared_libs: [")
+ bp.indent()
+ for _, info := range nativeLibInfos {
+ bp.printfln("%q,", versionedSdkMemberName(ctx, info.name, version))
+ }
+ bp.dedent()
+ bp.printfln("],") // native_shared_libs
+ }
+ bp.dedent()
+ bp.printfln("}") // sdk_snapshot
bp.printfln("")
bp.build(pctx, ctx, nil)
@@ -123,46 +354,104 @@
func (s *sdk) buildScript(ctx android.ModuleContext, version string) android.OutputPath {
sh := newGeneratedFile(ctx, "update_prebuilt-"+version+".sh")
+ buildDir := ctx.Config().BuildDir()
- snapshotRoot := filepath.Join(ctx.ModuleDir(), version)
- aidlIncludeDir := filepath.Join(snapshotRoot, "aidl")
- javaStubsDir := filepath.Join(snapshotRoot, "java")
+ snapshotPath := func(paths ...string) string {
+ return filepath.Join(ctx.ModuleDir(), version, filepath.Join(paths...))
+ }
+ // TODO(jiyong) instead of creating script, create a zip file having the Android.bp, the headers,
+ // and the stubs and put it to the dist directory. The dist'ed zip file then would be downloaded,
+ // unzipped and then uploaded to gerrit again.
sh.printfln("#!/bin/bash")
- sh.printfln("echo Updating snapshot of %s in %s", ctx.ModuleName(), snapshotRoot)
+ sh.printfln("echo Updating snapshot of %s in %s", ctx.ModuleName(), snapshotPath())
sh.printfln("pushd $ANDROID_BUILD_TOP > /dev/null")
- sh.printfln("rm -rf %s", snapshotRoot)
- sh.printfln("mkdir -p %s", aidlIncludeDir)
- sh.printfln("mkdir -p %s", javaStubsDir)
- // TODO(jiyong): mkdir the 'native' dir
+ sh.printfln("mkdir -p %s", snapshotPath(aidlIncludeDir))
+ sh.printfln("mkdir -p %s", snapshotPath(javaStubDir))
+ sh.printfln("mkdir -p %s", snapshotPath(nativeIncludeDir))
+ sh.printfln("mkdir -p %s", snapshotPath(nativeGeneratedIncludeDir))
+ for _, target := range ctx.MultiTargets() {
+ arch := target.Arch.ArchType.String()
+ sh.printfln("mkdir -p %s", snapshotPath(arch, nativeStubDir))
+ sh.printfln("mkdir -p %s", snapshotPath(arch, nativeIncludeDir))
+ sh.printfln("mkdir -p %s", snapshotPath(arch, nativeGeneratedIncludeDir))
+ }
var implicits android.Paths
- ctx.VisitDirectDeps(func(m android.Module) {
- if javaLib, ok := m.(*java.Library); ok {
- headerJars := javaLib.HeaderJars()
- if len(headerJars) != 1 {
- panic(fmt.Errorf("there must be only one header jar from %q", m.Name()))
- }
- implicits = append(implicits, headerJars...)
-
- exportedAidlIncludeDirs := javaLib.AidlIncludeDirs()
- for _, dir := range exportedAidlIncludeDirs {
- // Using tar to copy with the directory structure
- // TODO(jiyong): copy parcelable declarations only
- sh.printfln("find %s -name \"*.aidl\" | tar cf - -T - | (cd %s; tar xf -)",
- dir.String(), aidlIncludeDir)
- }
-
- copiedHeaderJar := filepath.Join(javaStubsDir, m.Name(), "stub.jar")
- sh.printfln("mkdir -p $(dirname %s) && cp %s %s",
- copiedHeaderJar, headerJars[0].String(), copiedHeaderJar)
+ for _, m := range s.javaLibs(ctx) {
+ headerJars := m.HeaderJars()
+ if len(headerJars) != 1 {
+ panic(fmt.Errorf("there must be only one header jar from %q", m.Name()))
}
- // TODO(jiyong): emit the commands for copying the headers and stub libraries for native libs
- })
+ implicits = append(implicits, headerJars...)
+
+ exportedAidlIncludeDirs := m.AidlIncludeDirs()
+ for _, dir := range exportedAidlIncludeDirs {
+ // Using tar to copy with the directory structure
+ // TODO(jiyong): copy parcelable declarations only
+ sh.printfln("find %s -name \"*.aidl\" | tar cf - -T - | (cd %s; tar xf -)",
+ dir.String(), snapshotPath(aidlIncludeDir))
+ }
+
+ copyTarget := snapshotPath(javaStubFilePathFor(m))
+ sh.printfln("mkdir -p %s && cp %s %s",
+ filepath.Dir(copyTarget), headerJars[0].String(), copyTarget)
+ }
+
+ nativeLibInfos := s.nativeMemberInfos(ctx)
+ for _, info := range nativeLibInfos {
+
+ // a function for emitting include dirs
+ printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
+ includeDirs := lib.exportedIncludeDirs
+ includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...)
+ if len(includeDirs) == 0 {
+ return
+ }
+ for _, dir := range includeDirs {
+ gen := strings.HasPrefix(dir.String(), buildDir)
+ targetDir := nativeIncludeDir
+ if gen {
+ targetDir = nativeGeneratedIncludeDir
+ }
+ if info.hasArchSpecificFlags {
+ targetDir = filepath.Join(lib.archType, targetDir)
+ }
+ targetDir = snapshotPath(targetDir)
+
+ sourceDirRoot := "."
+ sourceDirRel := dir.String()
+ if gen {
+ // ex) out/soong/.intermediate/foo/bar/gen/aidl
+ sourceDirRoot = strings.TrimSuffix(dir.String(), dir.Rel())
+ sourceDirRel = dir.Rel()
+ }
+ // TODO(jiyong) copy headers having other suffixes
+ sh.printfln("(cd %s; find %s -name \"*.h\" | tar cf - -T - ) | (cd %s; tar xf -)",
+ sourceDirRoot, sourceDirRel, targetDir)
+ }
+ }
+
+ if !info.hasArchSpecificFlags {
+ printExportedDirCopyCommandsForNativeLibs(info.archVariants[0])
+ }
+
+ // for each architecture
+ for _, av := range info.archVariants {
+ stub := av.outputFile
+ implicits = append(implicits, stub)
+ copiedStub := snapshotPath(nativeStubFilePathFor(av))
+ sh.printfln("cp %s %s", stub.String(), copiedStub)
+
+ if info.hasArchSpecificFlags {
+ printExportedDirCopyCommandsForNativeLibs(av)
+ }
+ }
+ }
bp := s.buildAndroidBp(ctx, version)
implicits = append(implicits, bp)
- sh.printfln("cp %s %s", bp.String(), filepath.Join(snapshotRoot, "Android.bp"))
+ sh.printfln("cp %s %s", bp.String(), snapshotPath("Android.bp"))
sh.printfln("popd > /dev/null")
sh.printfln("rm -- \"$0\"") // self deleting so that stale script is not used
@@ -218,8 +507,8 @@
fmt.Fprintln(w, "$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)")
fmt.Fprintln(w, " touch $@")
fmt.Fprintln(w, " echo ##################################################")
- fmt.Fprintln(w, " echo To update current SDK: execute", s.updateScript.String())
- fmt.Fprintln(w, " echo To freeze current SDK: execute", s.freezeScript.String())
+ fmt.Fprintln(w, " echo To update current SDK: execute", filepath.Join("\\$$ANDROID_BUILD_TOP", s.updateScript.String()))
+ fmt.Fprintln(w, " echo To freeze current SDK: execute", filepath.Join("\\$$ANDROID_BUILD_TOP", s.freezeScript.String()))
fmt.Fprintln(w, " echo ##################################################")
},
},