Merge "Add support for exclude_srcs in genrule"
diff --git a/Android.bp b/Android.bp
index ef42c84..76f6798 100644
--- a/Android.bp
+++ b/Android.bp
@@ -145,6 +145,7 @@
"cc/util.go",
"cc/vndk.go",
"cc/vndk_prebuilt.go",
+ "cc/xom.go",
"cc/cmakelists.go",
"cc/compdb.go",
@@ -352,6 +353,9 @@
"apex/apex.go",
"apex/key.go",
],
+ testSrcs: [
+ "apex/apex_test.go",
+ ],
pluginFor: ["soong_build"],
}
@@ -435,7 +439,7 @@
src: "prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib/libwinpthread.a",
},
},
- notice: "../../prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/licenses/mingw-w64-svn-r5861/mingw-w64-libraries/winpthreads/COPYING",
+ notice: ":mingw-libwinpthread-notice",
}
toolchain_library {
diff --git a/android/androidmk.go b/android/androidmk.go
index 493ba97..18b26d9 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -40,6 +40,7 @@
type AndroidMkData struct {
Class string
SubName string
+ DistFile OptionalPath
OutputFile OptionalPath
Disabled bool
Include string
@@ -220,6 +221,45 @@
}
}
+ if len(amod.commonProperties.Dist.Targets) > 0 {
+ distFile := data.DistFile
+ if !distFile.Valid() {
+ distFile = data.OutputFile
+ }
+ if distFile.Valid() {
+ dest := filepath.Base(distFile.String())
+
+ if amod.commonProperties.Dist.Dest != nil {
+ var err error
+ dest, err = validateSafePath(*amod.commonProperties.Dist.Dest)
+ if err != nil {
+ // This was checked in ModuleBase.GenerateBuildActions
+ panic(err)
+ }
+ }
+
+ if amod.commonProperties.Dist.Suffix != nil {
+ ext := filepath.Ext(dest)
+ suffix := *amod.commonProperties.Dist.Suffix
+ dest = strings.TrimSuffix(dest, ext) + suffix + ext
+ }
+
+ if amod.commonProperties.Dist.Dir != nil {
+ var err error
+ dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest)
+ if err != nil {
+ // This was checked in ModuleBase.GenerateBuildActions
+ panic(err)
+ }
+ }
+
+ goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
+ fmt.Fprintln(&data.preamble, ".PHONY:", goals)
+ fmt.Fprintf(&data.preamble, "$(call dist-for-goals,%s,%s:%s)\n",
+ goals, distFile.String(), dest)
+ }
+ }
+
fmt.Fprintln(&data.preamble, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(&data.preamble, "LOCAL_PATH :=", filepath.Dir(ctx.BlueprintFile(mod)))
fmt.Fprintln(&data.preamble, "LOCAL_MODULE :=", name+data.SubName)
@@ -277,8 +317,8 @@
}
}
- if amod.commonProperties.Notice != nil {
- fmt.Fprintln(&data.preamble, "LOCAL_NOTICE_FILE :=", "$(LOCAL_PATH)/"+*amod.commonProperties.Notice)
+ if amod.noticeFile != nil {
+ fmt.Fprintln(&data.preamble, "LOCAL_NOTICE_FILE :=", amod.noticeFile.String())
}
if host {
diff --git a/android/apex.go b/android/apex.go
index dae88ce..3a191cf 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -14,6 +14,8 @@
package android
+import "sync"
+
// ApexModule is the interface that a module type is expected to implement if
// the module has to be built differently depending on whether the module
// is destined for an apex or not (installed to one of the regular partitions).
@@ -94,6 +96,68 @@
return false
}
+// This structure maps a module name to the set of APEX bundle names that the module
+// should be built for. Examples:
+//
+// ...["foo"]["bar"] == true: module foo is directly depended on by APEX bar
+// ...["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
+// ...["foo"]["bar"] doesn't exist: foo is not built for APEX bar
+// ...["foo"] doesn't exist: foo is not built for any APEX
+func apexBundleNamesMap(config Config) map[string]map[string]bool {
+ return config.Once("apexBundleNames", func() interface{} {
+ return make(map[string]map[string]bool)
+ }).(map[string]map[string]bool)
+}
+
+var bundleNamesMapMutex sync.Mutex
+
+// Mark that a module named moduleName should be built for an apex named bundleName
+// directDep should be set to true if the module is a direct dependency of the apex.
+func BuildModuleForApexBundle(ctx BaseModuleContext, moduleName string, bundleName string, directDep bool) {
+ bundleNamesMapMutex.Lock()
+ defer bundleNamesMapMutex.Unlock()
+ bundleNames, ok := apexBundleNamesMap(ctx.Config())[moduleName]
+ if !ok {
+ bundleNames = make(map[string]bool)
+ apexBundleNamesMap(ctx.Config())[moduleName] = bundleNames
+ }
+ bundleNames[bundleName] = bundleNames[bundleName] || directDep
+}
+
+// Returns the list of apex bundle names that the module named moduleName
+// should be built for.
+func GetApexBundlesForModule(ctx BaseModuleContext, moduleName string) map[string]bool {
+ bundleNamesMapMutex.Lock()
+ defer bundleNamesMapMutex.Unlock()
+ return apexBundleNamesMap(ctx.Config())[moduleName]
+}
+
+// Tests if moduleName is directly depended on by bundleName (i.e. referenced in
+// native_shared_libs, etc.)
+func DirectlyInApex(config Config, bundleName string, moduleName string) bool {
+ bundleNamesMapMutex.Lock()
+ defer bundleNamesMapMutex.Unlock()
+ if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
+ return bundleNames[bundleName]
+ }
+ return false
+}
+
+// Tests if moduleName is directly depended on by any APEX. If this returns true,
+// that means the module is part of the platform.
+func DirectlyInAnyApex(config Config, moduleName string) bool {
+ bundleNamesMapMutex.Lock()
+ defer bundleNamesMapMutex.Unlock()
+ if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
+ for bn := range bundleNames {
+ if bundleNames[bn] {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func InitApexModule(m ApexModule) {
base := m.apexModuleBase()
base.canHaveApexVariants = true
diff --git a/android/arch.go b/android/arch.go
index 7fe1b18..bee09b0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1080,20 +1080,20 @@
{"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
- {"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
{"arm64", "armv8-a", "cortex-a53", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "cortex-a72", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "cortex-a73", []string{"arm64-v8a"}},
- {"arm64", "armv8-a", "denver64", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "kryo", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
+ {"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
{"mips", "mips32-fp", "", []string{"mips"}},
{"mips", "mips32r2-fp", "", []string{"mips"}},
{"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
diff --git a/android/config.go b/android/config.go
index 50c1413..54c9da8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -482,7 +482,7 @@
}
func (c *config) MinSupportedSdkVersion() int {
- return 14
+ return 16
}
func (c *config) DefaultAppTargetSdkInt() int {
@@ -581,6 +581,10 @@
return Bool(c.productVariables.Debuggable)
}
+func (c *config) Eng() bool {
+ return Bool(c.productVariables.Eng)
+}
+
func (c *config) DevicePrefer32BitApps() bool {
return Bool(c.productVariables.DevicePrefer32BitApps)
}
@@ -626,6 +630,14 @@
}
}
+func (c *config) EnableXOM() bool {
+ if c.productVariables.EnableXOM == nil {
+ return false
+ } else {
+ return Bool(c.productVariables.EnableXOM)
+ }
+}
+
func (c *config) Android64() bool {
for _, t := range c.Targets[Android] {
if t.Arch.ArchType.Multilib == "lib64" {
@@ -863,6 +875,13 @@
return PrefixInList(path, *c.productVariables.CFIIncludePaths)
}
+func (c *config) XOMDisabledForPath(path string) bool {
+ if c.productVariables.XOMExcludePaths == nil {
+ return false
+ }
+ return PrefixInList(path, *c.productVariables.XOMExcludePaths)
+}
+
func (c *config) VendorConfig(name string) VendorConfig {
return vendorConfig(c.productVariables.VendorVars[name])
}
@@ -885,6 +904,10 @@
return Bool(c.productVariables.Ndk_abis)
}
+func (c *config) ExcludeDraftNdkApis() bool {
+ return Bool(c.productVariables.Exclude_draft_ndk_apis)
+}
+
func (c *config) FlattenApex() bool {
return Bool(c.productVariables.FlattenApex)
}
diff --git a/android/module.go b/android/module.go
index bf49ca2..dc0c856 100644
--- a/android/module.go
+++ b/android/module.go
@@ -265,6 +265,24 @@
// relative path to a file to include in the list of notices for the device
Notice *string
+ Dist struct {
+ // copy the output of this module to the $DIST_DIR when `dist` is specified on the
+ // command line and any of these targets are also on the command line, or otherwise
+ // built
+ Targets []string `android:"arch_variant"`
+
+ // The name of the output artifact. This defaults to the basename of the output of
+ // the module.
+ Dest *string `android:"arch_variant"`
+
+ // The directory within the dist directory to store the artifact. Defaults to the
+ // top level directory ("").
+ Dir *string `android:"arch_variant"`
+
+ // A suffix to add to the artifact file name (before any extension).
+ Suffix *string `android:"arch_variant"`
+ } `android:"arch_variant"`
+
// Set by TargetMutator
CompileTarget Target `blueprint:"mutated"`
CompileMultiTargets []Target `blueprint:"mutated"`
@@ -441,6 +459,7 @@
noAddressSanitizer bool
installFiles Paths
checkbuildFiles Paths
+ noticeFile Path
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -781,6 +800,25 @@
}
ctx.Variable(pctx, "moduleDescSuffix", s)
+ // Some common property checks for properties that will be used later in androidmk.go
+ if a.commonProperties.Dist.Dest != nil {
+ _, err := validateSafePath(*a.commonProperties.Dist.Dest)
+ if err != nil {
+ ctx.PropertyErrorf("dist.dest", "%s", err.Error())
+ }
+ }
+ if a.commonProperties.Dist.Dir != nil {
+ _, err := validateSafePath(*a.commonProperties.Dist.Dir)
+ if err != nil {
+ ctx.PropertyErrorf("dist.dir", "%s", err.Error())
+ }
+ }
+ if a.commonProperties.Dist.Suffix != nil {
+ if strings.Contains(*a.commonProperties.Dist.Suffix, "/") {
+ ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.")
+ }
+ }
+
if a.Enabled() {
a.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
@@ -789,6 +827,11 @@
a.installFiles = append(a.installFiles, ctx.installFiles...)
a.checkbuildFiles = append(a.checkbuildFiles, ctx.checkbuildFiles...)
+
+ if a.commonProperties.Notice != nil {
+ // For filegroup-based notice file references.
+ a.noticeFile = ctx.ExpandSource(*a.commonProperties.Notice, "notice")
+ }
}
if a == ctx.FinalModule().(Module).base() {
@@ -1310,6 +1353,13 @@
srcFiles := ctx.ExpandSourcesSubDir([]string{srcFile}, nil, "")
if len(srcFiles) == 1 {
return srcFiles[0]
+ } else if len(srcFiles) == 0 {
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{srcFile})
+ } else {
+ ctx.PropertyErrorf(prop, "%s path %s does not exist", prop, srcFile)
+ }
+ return nil
} else {
ctx.PropertyErrorf(prop, "module providing %s must produce exactly one file", prop)
return nil
diff --git a/android/mutator.go b/android/mutator.go
index b9c44e8..b77c2f0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -207,6 +207,11 @@
func depsMutator(ctx BottomUpMutatorContext) {
if m, ok := ctx.Module().(Module); ok && m.Enabled() {
m.DepsMutator(ctx)
+
+ // For filegroup-based notice file references.
+ if m.base().commonProperties.Notice != nil {
+ ExtractSourceDeps(ctx, m.base().commonProperties.Notice)
+ }
}
}
diff --git a/android/variable.go b/android/variable.go
index 2763bf2..f496008 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -54,17 +54,19 @@
Cflags []string
}
- Device_uses_hwc2 struct {
- Cflags []string
- }
-
Override_rs_driver struct {
Cflags []string
}
// Product_is_iot is true for Android Things devices.
Product_is_iot struct {
- Cflags []string
+ Cflags []string
+ Enabled bool
+ Exclude_srcs []string
+ Init_rc []string
+ Shared_libs []string
+ Srcs []string
+ Static_libs []string
}
// treble_linker_namespaces is true when the system/vendor linker namespace separation is
@@ -184,7 +186,6 @@
UseGoma *bool `json:",omitempty"`
Debuggable *bool `json:",omitempty"`
Eng *bool `json:",omitempty"`
- Device_uses_hwc2 *bool `json:",omitempty"`
Treble_linker_namespaces *bool `json:",omitempty"`
Enforce_vintf_manifest *bool `json:",omitempty"`
Pdk *bool `json:",omitempty"`
@@ -205,6 +206,9 @@
CFIExcludePaths *[]string `json:",omitempty"`
CFIIncludePaths *[]string `json:",omitempty"`
+ EnableXOM *bool `json:",omitempty"`
+ XOMExcludePaths *[]string `json:",omitempty"`
+
VendorPath *string `json:",omitempty"`
OdmPath *string `json:",omitempty"`
ProductPath *string `json:",omitempty"`
@@ -249,7 +253,8 @@
VendorVars map[string]map[string]string `json:",omitempty"`
- Ndk_abis *bool `json:",omitempty"`
+ Ndk_abis *bool `json:",omitempty"`
+ Exclude_draft_ndk_apis *bool `json:",omitempty"`
FlattenApex *bool `json:",omitempty"`
}
diff --git a/apex/apex.go b/apex/apex.go
index 33143d6..f412d86 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -38,7 +38,7 @@
// TODO(b/113082813) make this configurable using config.fs syntax
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
Command: `echo '/ 1000 1000 0755' > ${out} && ` +
- `echo '/manifest.json 1000 1000 0644' >> ${out} && ` +
+ `echo '/apex_manifest.json 1000 1000 0644' >> ${out} && ` +
`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0755"}' >> ${out}`,
Description: "fs_config ${out}",
@@ -52,9 +52,10 @@
Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
`(${copy_commands}) && ` +
`APEXER_TOOL_PATH=${tool_path} ` +
- `${apexer} --verbose --force --manifest ${manifest} ` +
+ `${apexer} --force --manifest ${manifest} ` +
`--file_contexts ${file_contexts} ` +
`--canned_fs_config ${canned_fs_config} ` +
+ `--payload_type image ` +
`--key ${key} ${image_dir} ${out} `,
CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
"${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
@@ -62,6 +63,17 @@
Description: "APEX ${image_dir} => ${out}",
}, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key")
+ zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
+ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
+ `(${copy_commands}) && ` +
+ `APEXER_TOOL_PATH=${tool_path} ` +
+ `${apexer} --force --manifest ${manifest} ` +
+ `--payload_type zip ` +
+ `${image_dir} ${out} `,
+ CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
+ Description: "ZipAPEX ${image_dir} => ${out}",
+ }, "tool_path", "image_dir", "copy_commands", "manifest")
+
apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
blueprint.RuleParams{
Command: `${aapt2} convert --output-format proto $in -o $out`,
@@ -69,13 +81,20 @@
})
apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{
- Command: `${zip2zip} -i $in -o $out image.img:apex/${abi}.img manifest.json:root/manifest.json AndroidManifest.xml:manifest/AndroidManifest.xml`,
+ Command: `${zip2zip} -i $in -o $out ` +
+ `apex_payload.img:apex/${abi}.img ` +
+ `apex_manifest.json:root/apex_manifest.json ` +
+ `AndroidManifest.xml:manifest/AndroidManifest.xml`,
CommandDeps: []string{"${zip2zip}"},
Description: "app bundle",
}, "abi")
)
-var apexSuffix = ".apex"
+var imageApexSuffix = ".apex"
+var zipApexSuffix = ".zipapex"
+
+var imageApexType = "image"
+var zipApexType = "zip"
type dependencyTag struct {
blueprint.BaseDependencyTag
@@ -117,7 +136,7 @@
pctx.HostBinToolVariable("zip2zip", "zip2zip")
pctx.HostBinToolVariable("zipalign", "zipalign")
- android.RegisterModuleType("apex", apexBundleFactory)
+ android.RegisterModuleType("apex", ApexBundleFactory)
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_deps", apexDepsMutator)
@@ -125,13 +144,6 @@
})
}
-// maps a module name to set of apex bundle names that the module should be built for
-func apexBundleNamesFor(config android.Config) map[string]map[string]bool {
- return config.Once("apexBundleNames", func() interface{} {
- return make(map[string]map[string]bool)
- }).(map[string]map[string]bool)
-}
-
// Mark the direct and transitive dependencies of apex bundles so that they
// can be built for the apex bundles.
func apexDepsMutator(mctx android.TopDownMutatorContext) {
@@ -140,12 +152,9 @@
mctx.WalkDeps(func(child, parent android.Module) bool {
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
moduleName := mctx.OtherModuleName(am) + "-" + am.Target().String()
- bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]
- if !ok {
- bundleNames = make(map[string]bool)
- apexBundleNamesFor(mctx.Config())[moduleName] = bundleNames
- }
- bundleNames[apexBundleName] = true
+ // If the parent is apexBundle, this child is directly depended.
+ _, directDep := parent.(*apexBundle)
+ android.BuildModuleForApexBundle(mctx, moduleName, apexBundleName, directDep)
return true
} else {
return false
@@ -158,7 +167,8 @@
func apexMutator(mctx android.BottomUpMutatorContext) {
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
moduleName := mctx.ModuleName() + "-" + am.Target().String()
- if bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]; ok {
+ bundleNames := android.GetApexBundlesForModule(mctx, moduleName)
+ if len(bundleNames) > 0 {
variations := []string{"platform"}
for bn := range bundleNames {
variations = append(variations, bn)
@@ -181,7 +191,7 @@
type apexBundleProperties struct {
// Json manifest file describing meta info of this APEX bundle. Default:
- // "manifest.json"
+ // "apex_manifest.json"
Manifest *string
// Determines the file contexts file for setting security context to each file in this APEX bundle.
@@ -205,6 +215,10 @@
// Name of the apex_key module that provides the private key to sign APEX
Key *string
+ // The type of APEX to build. Controls what the APEX payload is. Either
+ // 'image', 'zip' or 'both'. Default: 'image'.
+ Payload_type *string
+
// The name of a certificate in the default certificate directory, blank to use the default product certificate,
// or an android_app_certificate module name in the form ":module".
Certificate *string
@@ -252,6 +266,56 @@
javaSharedLib
)
+type apexPackaging int
+
+const (
+ imageApex apexPackaging = iota
+ zipApex
+ both
+)
+
+func (a apexPackaging) image() bool {
+ switch a {
+ case imageApex, both:
+ return true
+ }
+ return false
+}
+
+func (a apexPackaging) zip() bool {
+ switch a {
+ case zipApex, both:
+ return true
+ }
+ return false
+}
+
+func (a apexPackaging) suffix() string {
+ switch a {
+ case imageApex:
+ return imageApexSuffix
+ case zipApex:
+ return zipApexSuffix
+ case both:
+ panic(fmt.Errorf("must be either zip or image"))
+ default:
+ panic(fmt.Errorf("unkonwn APEX type %d", a))
+ }
+}
+
+func (a apexPackaging) name() string {
+ switch a {
+ case imageApex:
+ return imageApexType
+ case zipApex:
+ return zipApexType
+ case both:
+ panic(fmt.Errorf("must be either zip or image"))
+ default:
+ panic(fmt.Errorf("unkonwn APEX type %d", a))
+ }
+}
+
func (class apexFileClass) NameInMake() string {
switch class {
case etc:
@@ -281,8 +345,10 @@
properties apexBundleProperties
+ apexTypes apexPackaging
+
bundleModuleFile android.WritablePath
- outputFile android.WritablePath
+ outputFiles map[apexPackaging]android.WritablePath
installDir android.OutputPath
// list of files to be included in this apex
@@ -301,6 +367,7 @@
{Mutator: "arch", Variation: arch},
{Mutator: "image", Variation: "core"},
{Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: ""}, // "" is the non-stub variant
}, sharedLibTag, native_shared_libs...)
ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -390,6 +457,10 @@
}
}
+func (a *apexBundle) Srcs() android.Paths {
+ return android.Paths{a.outputFiles[imageApex]}
+}
+
func getCopyManifestForNativeLibrary(cc *cc.Module) (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.
@@ -431,6 +502,17 @@
var keyFile android.Path
var certificate java.Certificate
+ if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" {
+ a.apexTypes = imageApex
+ } else if *a.properties.Payload_type == "zip" {
+ a.apexTypes = zipApex
+ } else if *a.properties.Payload_type == "both" {
+ a.apexTypes = both
+ } else {
+ ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type)
+ return
+ }
+
ctx.WalkDeps(func(child, parent android.Module) bool {
if _, ok := parent.(*apexBundle); ok {
// direct dependencies
@@ -492,6 +574,9 @@
// indirect dependencies
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
if cc, ok := child.(*cc.Module); ok {
+ if cc.IsStubs() || cc.HasStubsVariants() {
+ return false
+ }
depName := ctx.OtherModuleName(child)
fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib})
@@ -535,14 +620,20 @@
a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
- if ctx.Config().FlattenApex() {
- a.buildFlattenedApex(ctx)
- } else {
- a.buildUnflattenedApex(ctx, keyFile, certificate)
+
+ if a.apexTypes.zip() {
+ a.buildUnflattenedApex(ctx, keyFile, certificate, zipApex)
+ }
+ if a.apexTypes.image() {
+ if ctx.Config().FlattenApex() {
+ a.buildFlattenedApex(ctx)
+ } else {
+ a.buildUnflattenedApex(ctx, keyFile, certificate, imageApex)
+ }
}
}
-func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate) {
+func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path, certificate java.Certificate, apexType apexPackaging) {
cert := String(a.properties.Certificate)
if cert != "" && android.SrcIsModule(cert) == "" {
defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
@@ -555,45 +646,19 @@
certificate = java.Certificate{pem, key}
}
- // files and dirs that will be created in apex
- var readOnlyPaths []string
- var executablePaths []string // this also includes dirs
- for _, f := range a.filesInfo {
- pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
- if f.installDir == "bin" {
- executablePaths = append(executablePaths, pathInApex)
- } else {
- readOnlyPaths = append(readOnlyPaths, pathInApex)
- }
- if !android.InList(f.installDir, executablePaths) {
- executablePaths = append(executablePaths, f.installDir)
+ manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+
+ var abis []string
+ for _, target := range ctx.MultiTargets() {
+ if len(target.Arch.Abi) > 0 {
+ abis = append(abis, target.Arch.Abi[0])
}
}
- sort.Strings(readOnlyPaths)
- sort.Strings(executablePaths)
- cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
- ctx.Build(pctx, android.BuildParams{
- Rule: generateFsConfig,
- Output: cannedFsConfig,
- Description: "generate fs config",
- Args: map[string]string{
- "ro_paths": strings.Join(readOnlyPaths, " "),
- "exec_paths": strings.Join(executablePaths, " "),
- },
- })
- manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
+ abis = android.FirstUniqueStrings(abis)
- fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
- fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts"
- fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath)
- if !fileContextsOptionalPath.Valid() {
- ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath)
- return
- }
- fileContexts := fileContextsOptionalPath.Path()
-
- unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix+".unsigned")
+ suffix := apexType.suffix()
+ unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned")
filesToCopy := []android.Path{}
for _, f := range a.filesInfo {
@@ -603,74 +668,134 @@
copyCommands := []string{}
for i, src := range filesToCopy {
dest := filepath.Join(a.filesInfo[i].installDir, src.Base())
- dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").String(), dest)
+ dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
}
implicitInputs := append(android.Paths(nil), filesToCopy...)
- implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile)
+ implicitInputs = append(implicitInputs, manifest)
+
outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
- ctx.Build(pctx, android.BuildParams{
- Rule: apexRule,
- Implicits: implicitInputs,
- Output: unsignedOutputFile,
- Description: "apex",
- Args: map[string]string{
- "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
- "image_dir": android.PathForModuleOut(ctx, "image").String(),
- "copy_commands": strings.Join(copyCommands, " && "),
- "manifest": manifest.String(),
- "file_contexts": fileContexts.String(),
- "canned_fs_config": cannedFsConfig.String(),
- "key": keyFile.String(),
- },
- })
- var abis []string
- for _, target := range ctx.MultiTargets() {
- abis = append(abis, target.Arch.Abi[0])
+ if apexType.image() {
+ // files and dirs that will be created in APEX
+ var readOnlyPaths []string
+ var executablePaths []string // this also includes dirs
+ for _, f := range a.filesInfo {
+ pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
+ if f.installDir == "bin" {
+ executablePaths = append(executablePaths, pathInApex)
+ } else {
+ readOnlyPaths = append(readOnlyPaths, pathInApex)
+ }
+ dir := f.installDir
+ for !android.InList(dir, executablePaths) && dir != "" {
+ executablePaths = append(executablePaths, dir)
+ dir, _ = filepath.Split(dir) // move up to the parent
+ if len(dir) > 0 {
+ // remove trailing slash
+ dir = dir[:len(dir)-1]
+ }
+ }
+ }
+ sort.Strings(readOnlyPaths)
+ sort.Strings(executablePaths)
+ cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateFsConfig,
+ Output: cannedFsConfig,
+ Description: "generate fs config",
+ Args: map[string]string{
+ "ro_paths": strings.Join(readOnlyPaths, " "),
+ "exec_paths": strings.Join(executablePaths, " "),
+ },
+ })
+
+ fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
+ fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts"
+ fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath)
+ if !fileContextsOptionalPath.Valid() {
+ ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath)
+ return
+ }
+ fileContexts := fileContextsOptionalPath.Path()
+
+ // Additional implicit inputs.
+ implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, keyFile)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexRule,
+ Implicits: implicitInputs,
+ Output: unsignedOutputFile,
+ Description: "apex (" + apexType.name() + ")",
+ Args: map[string]string{
+ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+ "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
+ "copy_commands": strings.Join(copyCommands, " && "),
+ "manifest": manifest.String(),
+ "file_contexts": fileContexts.String(),
+ "canned_fs_config": cannedFsConfig.String(),
+ "key": keyFile.String(),
+ },
+ })
+
+ apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix)
+ bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip")
+ a.bundleModuleFile = bundleModuleFile
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexProtoConvertRule,
+ Input: unsignedOutputFile,
+ Output: apexProtoFile,
+ Description: "apex proto convert",
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexBundleRule,
+ Input: apexProtoFile,
+ Output: a.bundleModuleFile,
+ Description: "apex bundle module",
+ Args: map[string]string{
+ "abi": strings.Join(abis, "."),
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: zipApexRule,
+ Implicits: implicitInputs,
+ Output: unsignedOutputFile,
+ Description: "apex (" + apexType.name() + ")",
+ Args: map[string]string{
+ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+ "image_dir": android.PathForModuleOut(ctx, "image"+suffix).String(),
+ "copy_commands": strings.Join(copyCommands, " && "),
+ "manifest": manifest.String(),
+ },
+ })
}
- abis = android.FirstUniqueStrings(abis)
- apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+apexSuffix)
- bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-base.zip")
- a.bundleModuleFile = bundleModuleFile
-
- ctx.Build(pctx, android.BuildParams{
- Rule: apexProtoConvertRule,
- Input: unsignedOutputFile,
- Output: apexProtoFile,
- Description: "apex proto convert",
- })
-
- ctx.Build(pctx, android.BuildParams{
- Rule: apexBundleRule,
- Input: apexProtoFile,
- Output: bundleModuleFile,
- Description: "apex bundle module",
- Args: map[string]string{
- "abi": strings.Join(abis, "."),
- },
- })
-
- a.outputFile = android.PathForModuleOut(ctx, ctx.ModuleName()+apexSuffix)
+ a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix)
ctx.Build(pctx, android.BuildParams{
Rule: java.Signapk,
Description: "signapk",
- Output: a.outputFile,
+ Output: a.outputFiles[apexType],
Input: unsignedOutputFile,
Args: map[string]string{
"certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "),
+ "flags": "-a 4096", //alignment
},
})
+
+ // Install to $OUT/soong/{target,host}/.../apex
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType])
}
func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) {
- // For flattened APEX, do nothing but make sure that manifest.json file is also copied along
+ // For flattened APEX, do nothing but make sure that apex_manifest.json file is also copied along
// with other ordinary files.
- manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
- a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".manifest.json", android.Common, ".", etc})
+ manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+ a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc})
for _, fi := range a.filesInfo {
dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
@@ -679,7 +804,24 @@
}
func (a *apexBundle) AndroidMk() android.AndroidMkData {
- if a.flattened {
+ writers := []android.AndroidMkData{}
+ if a.apexTypes.image() {
+ writers = append(writers, a.androidMkForType(imageApex))
+ }
+ if a.apexTypes.zip() {
+ writers = append(writers, a.androidMkForType(zipApex))
+ }
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ for _, data := range writers {
+ data.Custom(w, name, prefix, moduleDir, data)
+ }
+ }}
+}
+
+func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData {
+ // Only image APEXes can be flattened.
+ if a.flattened && apexType.image() {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{}
@@ -718,29 +860,37 @@
} else {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ // zip-apex is the less common type so have the name refer to the image-apex
+ // only and use {name}.zip if you want the zip-apex
+ if apexType == zipApex && a.apexTypes == both {
+ name = name + ".zip"
+ }
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
- fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
- fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix)
+ fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexType.suffix())
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
- fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
+ if apexType == imageApex {
+ fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
+ }
}}
}
}
-func apexBundleFactory() android.Module {
- module := &apexBundle{}
+func ApexBundleFactory() android.Module {
+ module := &apexBundle{
+ outputFiles: map[apexPackaging]android.WritablePath{},
+ }
module.AddProperties(&module.properties)
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase,
- class android.OsClass) bool {
+ module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
})
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
new file mode 100644
index 0000000..c01c40a
--- /dev/null
+++ b/apex/apex_test.go
@@ -0,0 +1,457 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// 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 apex
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+)
+
+func testApex(t *testing.T, bp string) *android.TestContext {
+ config, buildDir := setup(t)
+ defer teardown(buildDir)
+
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(ApexBundleFactory))
+ ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
+
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_deps", apexDepsMutator)
+ ctx.BottomUp("apex", apexMutator)
+ })
+
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+ ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
+ ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+ ctx.RegisterModuleType("prebuilt_etc", android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory))
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+ ctx.BottomUp("version", cc.VersionMutator).Parallel()
+ ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+ })
+
+ ctx.Register()
+
+ bp = bp + `
+ toolchain_library {
+ name: "libcompiler_rt-extras",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libatomic",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libgcc",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-aarch64-android",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-arm-android",
+ src: "",
+ }
+
+ cc_object {
+ name: "crtbegin_so",
+ stl: "none",
+ }
+
+ cc_object {
+ name: "crtend_so",
+ stl: "none",
+ }
+
+ `
+
+ ctx.MockFileSystem(map[string][]byte{
+ "Android.bp": []byte(bp),
+ "testkey.avbpubkey": nil,
+ "testkey.pem": nil,
+ "build/target/product/security": nil,
+ "apex_manifest.json": nil,
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+ "mylib.cpp": nil,
+ "myprebuilt": nil,
+ })
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ return ctx
+}
+
+func setup(t *testing.T) (config android.Config, buildDir string) {
+ buildDir, err := ioutil.TempDir("", "soong_apex_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ config = android.TestArchConfig(buildDir, nil)
+
+ return
+}
+
+func teardown(buildDir string) {
+ os.RemoveAll(buildDir)
+}
+
+// ensure that 'result' contains 'expected'
+func ensureContains(t *testing.T, result string, expected string) {
+ if !strings.Contains(result, expected) {
+ t.Errorf("%q is not found in %q", expected, result)
+ }
+}
+
+// ensures that 'result' does not contain 'notExpected'
+func ensureNotContains(t *testing.T, result string, notExpected string) {
+ if strings.Contains(result, notExpected) {
+ t.Errorf("%q is found in %q", notExpected, result)
+ }
+}
+
+func ensureListContains(t *testing.T, result []string, expected string) {
+ if !android.InList(expected, result) {
+ t.Errorf("%q is not found in %v", expected, result)
+ }
+}
+
+func ensureListNotContains(t *testing.T, result []string, notExpected string) {
+ if android.InList(notExpected, result) {
+ t.Errorf("%q is found in %v", notExpected, result)
+ }
+}
+
+// Minimal test
+func TestBasicApex(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that main rule creates an output
+ ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+ // Ensure that apex variant is created for the direct dep
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+
+ // Ensure that apex variant is created for the indirect dep
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+
+ // Ensure that both direct and indirect deps are copied into apex
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+}
+
+func TestBasicZipApex(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ payload_type: "zip",
+ native_shared_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("zipApexRule")
+ copyCmds := zipApexRule.Args["copy_commands"]
+
+ // Ensure that main rule creates an output
+ ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
+
+ // Ensure that APEX variant is created for the direct dep
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+
+ // Ensure that APEX variant is created for the indirect dep
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+
+ // Ensure that both direct and indirect deps are copied into apex
+ ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
+}
+
+func TestApexWithStubs(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "mylib3"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2", "mylib3"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["1", "2", "3"],
+ },
+ }
+
+ cc_library {
+ name: "mylib3",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib4"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["10", "11", "12"],
+ },
+ }
+
+ cc_library {
+ name: "mylib4",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that direct non-stubs dep is always included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+
+ // Ensure that indirect stubs dep is not included
+ ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+
+ // Ensure that direct stubs dep is included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
+
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+
+ // Ensure that mylib is linking with the latest version of stubs for mylib2
+ ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3_myapex/mylib2.so")
+ // ... and not linking to the non-stub (impl) variant of mylib2
+ ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_myapex/mylib2.so")
+
+ // Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
+ ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
+ // .. and not linking to the stubs variant of mylib3
+ ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
+}
+
+func TestApexWithSystemLibsStubs(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libdl#27"],
+ stl: "none",
+ }
+
+ cc_library_shared {
+ name: "mylib_shared",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libdl#27"],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libc",
+ no_libgcc: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
+ }
+
+ cc_library {
+ name: "libm",
+ no_libgcc: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
+ }
+
+ cc_library {
+ name: "libdl",
+ no_libgcc: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["27", "28", "29"],
+ },
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that mylib, libm, libdl are included.
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
+
+ // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
+
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+ mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
+
+ // For dependency to libc
+ // Ensure that mylib is linking with the latest version of stubs
+ ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29_myapex/libc.so")
+ // ... and not linking to the non-stub (impl) variant
+ ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_myapex/libc.so")
+ // ... Cflags from stub is correctly exported to mylib
+ ensureContains(t, mylibCFlags, "__LIBC_API__=29")
+ ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
+
+ // For dependency to libm
+ // Ensure that mylib is linking with the non-stub (impl) variant
+ ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
+ // ... and not linking to the stub variant
+ ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29_myapex/libm.so")
+ // ... and is not compiling with the stub
+ ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
+ ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
+
+ // For dependency to libdl
+ // Ensure that mylib is linking with the specified version of stubs
+ ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27_myapex/libdl.so")
+ // ... and not linking to the other versions of stubs
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28_myapex/libdl.so")
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29_myapex/libdl.so")
+ // ... and not linking to the non-stub (impl) variant
+ ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
+ // ... Cflags from stub is correctly exported to mylib
+ ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
+ ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
+}
+
+func TestFilesInSubDir(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ prebuilts: ["myetc"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_etc {
+ name: "myetc",
+ src: "myprebuilt",
+ sub_dir: "foo/bar",
+ }
+ `)
+
+ generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
+ dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
+
+ // Ensure that etc, etc/foo, and etc/foo/bar are all listed
+ ensureListContains(t, dirs, "etc")
+ ensureListContains(t, dirs, "etc/foo")
+ ensureListContains(t, dirs, "etc/foo/bar")
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5e38973..f5e04bb 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -151,6 +151,7 @@
ret.Class = "HEADER_LIBRARIES"
}
+ ret.DistFile = library.distFile
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
library.androidMkWriteExportedFlags(w)
fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES := ")
@@ -194,6 +195,7 @@
ctx.subAndroidMk(ret, binary.baseInstaller)
ret.Class = "EXECUTABLES"
+ ret.DistFile = binary.distFile
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
if len(binary.symlinks) > 0 {
diff --git a/cc/binary.go b/cc/binary.go
index 15db2ad..6923f2b 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -88,6 +88,9 @@
// Output archive of gcno coverage information
coverageOutputFile android.OptionalPath
+
+ // Location of the file that should be copied to dist dir when requested
+ distFile android.OptionalPath
}
var _ linker = (*binaryDecorator)(nil)
@@ -330,10 +333,23 @@
flagsToBuilderFlags(flags), afterPrefixSymbols)
}
- if Bool(binary.baseLinker.Properties.Use_version_lib) && ctx.Host() {
- versionedOutputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
- binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ if Bool(binary.baseLinker.Properties.Use_version_lib) {
+ if ctx.Host() {
+ versionedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+ binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ } else {
+ versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+ binary.distFile = android.OptionalPathForPath(versionedOutputFile)
+
+ if binary.stripper.needsStrip(ctx) {
+ out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
+ binary.distFile = android.OptionalPathForPath(out)
+ binary.stripper.strip(ctx, versionedOutputFile, out, builderFlags)
+ }
+
+ binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ }
}
if ctx.Os() == android.LinuxBionic && !binary.static() {
diff --git a/cc/cc.go b/cc/cc.go
index ed65aa6..b8cbf26 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -39,7 +39,7 @@
ctx.BottomUp("vndk", vndkMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
- ctx.BottomUp("version", versionMutator).Parallel()
+ ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
})
@@ -53,6 +53,9 @@
ctx.TopDown("cfi_deps", sanitizerDepsMutator(cfi))
ctx.BottomUp("cfi", sanitizerMutator(cfi)).Parallel()
+ ctx.TopDown("scs_deps", sanitizerDepsMutator(scs))
+ ctx.BottomUp("scs", sanitizerMutator(scs)).Parallel()
+
ctx.TopDown("tsan_deps", sanitizerDepsMutator(tsan))
ctx.BottomUp("tsan", sanitizerMutator(tsan)).Parallel()
@@ -244,6 +247,8 @@
baseModuleName() string
getVndkExtendsModuleName() string
isPgoCompile() bool
+ useClangLld(actx ModuleContext) bool
+ isApex() bool
}
type ModuleContext interface {
@@ -284,6 +289,7 @@
linkerDeps(ctx DepsContext, deps Deps) Deps
linkerFlags(ctx ModuleContext, flags Flags) Flags
linkerProps() []interface{}
+ useClangLld(actx ModuleContext) bool
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
appendLdflags([]string)
@@ -303,6 +309,8 @@
library bool
reexportFlags bool
+
+ explicitlyVersioned bool
}
var (
@@ -357,6 +365,7 @@
vndkdep *vndkdep
lto *lto
pgo *pgo
+ xom *xom
androidMkSharedLibDeps []string
@@ -414,6 +423,9 @@
if c.pgo != nil {
c.AddProperties(c.pgo.props()...)
}
+ if c.xom != nil {
+ c.AddProperties(c.xom.props()...)
+ }
for _, feature := range c.features {
c.AddProperties(feature.props()...)
}
@@ -502,6 +514,20 @@
return c.ModuleBase.InstallInRecovery()
}
+func (c *Module) IsStubs() bool {
+ if library, ok := c.linker.(*libraryDecorator); ok {
+ return library.buildStubs()
+ }
+ return false
+}
+
+func (c *Module) HasStubsVariants() bool {
+ if library, ok := c.linker.(*libraryDecorator); ok {
+ return len(library.Properties.Stubs.Versions) > 0
+ }
+ return false
+}
+
type baseModuleContext struct {
android.BaseContext
moduleContextImpl
@@ -628,6 +654,10 @@
return ""
}
+func (ctx *moduleContextImpl) useClangLld(actx ModuleContext) bool {
+ return ctx.mod.linker.useClangLld(actx)
+}
+
func (ctx *moduleContextImpl) baseModuleName() string {
return ctx.mod.ModuleBase.BaseModuleName()
}
@@ -636,6 +666,11 @@
return ctx.mod.getVndkExtendsModuleName()
}
+// Tests if this module is built for APEX
+func (ctx *moduleContextImpl) isApex() bool {
+ return ctx.mod.ApexName() != ""
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -655,6 +690,7 @@
module.vndkdep = &vndkdep{}
module.lto = <o{}
module.pgo = &pgo{}
+ module.xom = &xom{}
return module
}
@@ -771,6 +807,9 @@
if c.pgo != nil {
flags = c.pgo.flags(ctx, flags)
}
+ if c.xom != nil {
+ flags = c.xom.flags(ctx, flags)
+ }
for _, feature := range c.features {
flags = feature.flags(ctx, flags)
}
@@ -1064,6 +1103,30 @@
{Mutator: "link", Variation: "static"},
}, lateStaticDepTag, deps.LateStaticLibs...)
+ addSharedLibDependencies := func(depTag dependencyTag, name string, version string) {
+ var variations []blueprint.Variation
+ variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
+ versionVariantAvail := ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery()
+ if version != "" && versionVariantAvail {
+ // Version is explicitly specified. i.e. libFoo#30
+ variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
+ depTag.explicitlyVersioned = true
+ }
+ actx.AddVariationDependencies(variations, depTag, name)
+
+ // 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)
+ if version == "" && latestVersion != "" && versionVariantAvail {
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: latestVersion},
+ }, depTag, name)
+ // Note that depTag.explicitlyVersioned is false in this case.
+ }
+ }
+
// shared lib names without the #version suffix
var sharedLibNames []string
@@ -1074,29 +1137,17 @@
if inList(lib, deps.ReexportSharedLibHeaders) {
depTag = sharedExportDepTag
}
- var variations []blueprint.Variation
- variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
- if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
- variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
- }
- actx.AddVariationDependencies(variations, depTag, name)
+ addSharedLibDependencies(depTag, name, version)
}
for _, lib := range deps.LateSharedLibs {
- name, version := stubsLibNameAndVersion(lib)
- if inList(name, sharedLibNames) {
+ if inList(lib, sharedLibNames) {
// This is to handle the case that some of the late shared libs (libc, libdl, libm, ...)
// are added also to SharedLibs with version (e.g., libc#10). If not skipped, we will be
// linking against both the stubs lib and the non-stubs lib at the same time.
continue
}
- depTag := lateSharedDepTag
- var variations []blueprint.Variation
- variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
- if version != "" && ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery() {
- variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
- }
- actx.AddVariationDependencies(variations, depTag, name)
+ addSharedLibDependencies(lateSharedDepTag, lib, "")
}
actx.AddVariationDependencies([]blueprint.Variation{
@@ -1272,7 +1323,8 @@
}
depIsDoubleLoadable := Bool(to.VendorProperties.Double_loadable)
if !depIsLlndk && !depIsVndkSp && !depIsDoubleLoadable && depIsVndk {
- ctx.ModuleErrorf("links VNDK library %q that isn't double_loadable.",
+ ctx.ModuleErrorf("links VNDK library %q that isn't double loadable (not also LL-NDK, "+
+ "VNDK-SP, or explicitly marked as 'double_loadable').",
ctx.OtherModuleName(to))
}
}
@@ -1354,7 +1406,53 @@
return
}
}
+
+ // Extract explicitlyVersioned field from the depTag and reset it inside the struct.
+ // Otherwise, sharedDepTag and lateSharedDepTag with explicitlyVersioned set to true
+ // won't be matched to sharedDepTag and lateSharedDepTag.
+ explicitlyVersioned := false
+ if t, ok := depTag.(dependencyTag); ok {
+ explicitlyVersioned = t.explicitlyVersioned
+ t.explicitlyVersioned = false
+ depTag = t
+ }
+
if t, ok := depTag.(dependencyTag); ok && t.library {
+ if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok {
+ depIsStubs := dependentLibrary.buildStubs()
+ depHasStubs := ccDep.HasStubsVariants()
+ depNameWithTarget := depName + "-" + ccDep.Target().String()
+ depInSameApex := android.DirectlyInApex(ctx.Config(), c.ApexName(), depNameWithTarget)
+ depInPlatform := !android.DirectlyInAnyApex(ctx.Config(), depNameWithTarget)
+
+ var useThisDep bool
+ if depIsStubs && explicitlyVersioned {
+ // Always respect dependency to the versioned stubs (i.e. libX#10)
+ useThisDep = true
+ } else if !depHasStubs {
+ // Use non-stub variant if that is the only choice
+ // (i.e. depending on a lib without stubs.version property)
+ useThisDep = true
+ } else if c.IsForPlatform() {
+ // If not building for APEX, use stubs only when it is from
+ // an APEX (and not from platform)
+ useThisDep = (depInPlatform != depIsStubs)
+ if c.inRecovery() {
+ // However, for recovery modules, since there is no APEX there,
+ // always link to non-stub variant
+ useThisDep = !depIsStubs
+ }
+ } else {
+ // If building for APEX, use stubs only when it is not from
+ // the same APEX
+ useThisDep = (depInSameApex != depIsStubs)
+ }
+
+ if !useThisDep {
+ return // stop processing this dep
+ }
+ }
+
if i, ok := ccDep.linker.(exportedFlagsProducer); ok {
flags := i.exportedFlags()
deps := i.exportedFlagsDeps()
@@ -1638,6 +1736,7 @@
&VndkProperties{},
<OProperties{},
&PgoProperties{},
+ &XomProperties{},
&android.ProtoProperties{},
)
@@ -1738,6 +1837,7 @@
// Sanity check
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
+ productSpecific := mctx.ProductSpecific()
if m.VendorProperties.Vendor_available != nil && vendorSpecific {
mctx.PropertyErrorf("vendor_available",
@@ -1747,6 +1847,11 @@
if vndkdep := m.vndkdep; vndkdep != nil {
if vndkdep.isVndk() {
+ if productSpecific {
+ mctx.PropertyErrorf("product_specific",
+ "product_specific must not be true when `vndk: {enabled: true}`")
+ return
+ }
if vendorSpecific {
if !vndkdep.isVndkExt() {
mctx.PropertyErrorf("vndk",
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3e78ec7..e368fb3 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -66,7 +66,7 @@
ctx.BottomUp("image", imageMutator).Parallel()
ctx.BottomUp("link", LinkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel()
- ctx.BottomUp("version", versionMutator).Parallel()
+ ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
})
ctx.Register()
@@ -492,6 +492,21 @@
`)
}
+func TestVndkMustNotBeProductSpecific(t *testing.T) {
+ // Check whether an error is emitted when a vndk lib has 'product_specific: true'.
+ testCcError(t, "product_specific must not be true when `vndk: {enabled: true}`", `
+ cc_library {
+ name: "libvndk",
+ product_specific: true, // Cause error
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `)
+}
+
func TestVndkExt(t *testing.T) {
// This test checks the VNDK-Ext properties.
ctx := testCc(t, `
diff --git a/cc/compiler.go b/cc/compiler.go
index 5ac5d79..63d2ade 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -75,6 +75,10 @@
// be added to the include path using -I
Local_include_dirs []string `android:"arch_variant,variant_prepend"`
+ // Add the directory containing the Android.bp file to the list of include
+ // directories. Defaults to true.
+ Include_build_directory *bool
+
// list of generated sources to compile. These are the names of gensrcs or
// genrule modules.
Generated_sources []string `android:"arch_variant"`
@@ -288,8 +292,11 @@
flags.YasmFlags = append(flags.YasmFlags, f)
}
- flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
- flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
+ if compiler.Properties.Include_build_directory == nil ||
+ *compiler.Properties.Include_build_directory {
+ flags.GlobalFlags = append(flags.GlobalFlags, "-I"+android.PathForModuleSrc(ctx).String())
+ flags.YasmFlags = append(flags.YasmFlags, "-I"+android.PathForModuleSrc(ctx).String())
+ }
if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
@@ -299,6 +306,7 @@
}
if ctx.useSdk() {
+ // TODO: Switch to --sysroot.
// The NDK headers are installed to a common sysroot. While a more
// typical Soong approach would be to only make the headers for the
// library you're using available, we're trying to emulate the NDK
@@ -307,6 +315,7 @@
"-isystem "+getCurrentIncludePath(ctx).String(),
"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
+ // TODO: Migrate to API suffixed triple?
// Traditionally this has come from android/api-level.h, but with the
// libc headers unified it must be set by the build system since we
// don't have per-API level copies of that header now.
@@ -316,14 +325,6 @@
}
flags.GlobalFlags = append(flags.GlobalFlags,
"-D__ANDROID_API__="+version)
-
- // Until the full NDK has been migrated to using ndk_headers, we still
- // need to add the legacy sysroot includes to get the full set of
- // headers.
- legacyIncludes := fmt.Sprintf(
- "prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
- ctx.sdkVersion(), ctx.Arch().ArchType.String())
- flags.SystemIncludeFlags = append(flags.SystemIncludeFlags, "-isystem "+legacyIncludes)
}
if ctx.useVndk() {
@@ -420,9 +421,6 @@
cppStd = config.CppStdVersion
case "experimental":
cppStd = config.ExperimentalCppStdVersion
- case "c++17", "gnu++17":
- // Map c++17 and gnu++17 to their 1z equivalents, until 17 is finalized.
- cppStd = strings.Replace(String(compiler.Properties.Cpp_std), "17", "1z", 1)
}
if compiler.Properties.Gnu_extensions != nil && *compiler.Properties.Gnu_extensions == false {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 6a63828..f98e1be 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -68,6 +68,10 @@
"kryo": []string{
"-mcpu=kryo",
},
+ "kryo385": []string{
+ // Use cortex-a53 because kryo385 is not supported in GCC/clang.
+ "-mcpu=cortex-a53",
+ },
"exynos-m1": []string{
"-mcpu=exynos-m1",
},
@@ -92,9 +96,9 @@
"cortex-a75",
"cortex-a76",
"kryo",
+ "kryo385",
"exynos-m1",
- "exynos-m2",
- "denver64")
+ "exynos-m2")
pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
@@ -144,6 +148,7 @@
"cortex-a75": "${config.Arm64ClangCortexA55Cflags}",
"cortex-a76": "${config.Arm64ClangCortexA55Cflags}",
"kryo": "${config.Arm64ClangKryoCflags}",
+ "kryo385": "${config.Arm64ClangCortexA53Cflags}",
"exynos-m1": "${config.Arm64ClangExynosM1Cflags}",
"exynos-m2": "${config.Arm64ClangExynosM2Cflags}",
}
@@ -220,10 +225,7 @@
var extraLdflags string
switch arch.CpuVariant {
- case "cortex-a53", "cortex-a72", "cortex-a73", "kryo", "exynos-m1", "exynos-m2",
- // This variant might not need the workaround but leave it
- // in the list since it has had the workaround on before.
- "denver64":
+ case "cortex-a53", "cortex-a72", "cortex-a73", "kryo", "exynos-m1", "exynos-m2":
extraLdflags = "-Wl,--fix-cortex-a53-843419"
}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index d759125..60bb91a 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -151,6 +151,15 @@
// better solution comes around. See Bug 27340895
"-D__ARM_FEATURE_LPAE=1",
},
+ "kryo385": []string{
+ // Use cortex-a53 because kryo385 is not supported in GCC/clang.
+ "-mcpu=cortex-a53",
+ // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // don't advertise.
+ // TODO This is a hack and we need to add it for each processor that supports LPAE until some
+ // better solution comes around. See Bug 27340895
+ "-D__ARM_FEATURE_LPAE=1",
+ },
}
)
@@ -180,9 +189,9 @@
"cortex-a76",
"krait",
"kryo",
+ "kryo385",
"exynos-m1",
- "exynos-m2",
- "denver")
+ "exynos-m2")
android.RegisterArchVariantFeatures(android.Arm, "armv7-a-neon", "neon")
android.RegisterArchVariantFeatures(android.Arm, "armv8-a", "neon")
@@ -242,7 +251,7 @@
"armv7-a": "${config.ArmClangArmv7ACflags}",
"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
"armv8-a": "${config.ArmClangArmv8ACflags}",
- "armv8-2a": "${config.ArmClangArmv82ACflags}",
+ "armv8-2a": "${config.ArmClangArmv82ACflags}",
}
armClangCpuVariantCflagsVar = map[string]string{
@@ -258,9 +267,9 @@
"cortex-a75": "${config.ArmClangCortexA55Cflags}",
"krait": "${config.ArmClangKraitCflags}",
"kryo": "${config.ArmClangKryoCflags}",
+ "kryo385": "${config.ArmClangCortexA53Cflags}",
"exynos-m1": "${config.ArmClangCortexA53Cflags}",
"exynos-m2": "${config.ArmClangCortexA53Cflags}",
- "denver": "${config.ArmClangCortexA15Cflags}",
}
)
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 0f22034..c070bf2 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -91,7 +91,7 @@
"-Wl,-m,aarch64_elf64_le_vec",
})
-var ClangLibToolingUnknownCflags []string = nil
+var ClangLibToolingUnknownCflags = sorted([]string{})
func init() {
pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
@@ -120,14 +120,10 @@
// color codes if it is not running in a terminal.
"-fcolor-diagnostics",
- // http://b/29823425 Disable -Wexpansion-to-defined for Clang update to r271374
- "-Wno-expansion-to-defined",
-
// http://b/68236239 Allow 0/NULL instead of using nullptr everywhere.
"-Wno-zero-as-null-pointer-constant",
// Warnings from clang-7.0
- "-Wno-deprecated-register",
"-Wno-sign-compare",
// Warnings from clang-8.0
@@ -184,17 +180,8 @@
// compatibility.
"-Wno-c++98-compat-extra-semi",
- // Disable this warning until we can fix all instances where it fails.
- "-Wno-self-assign-overloaded",
-
- // Disable this warning until we can fix all instances where it fails.
- "-Wno-constant-logical-operand",
-
// Disable this warning because we don't care about behavior with older compilers.
"-Wno-return-std-move-in-c++11",
-
- // Disable this warning until we can fix all instances where it fails.
- "-Wno-dangling-field",
}, " "))
// Extra cflags for projects under external/ directory
diff --git a/cc/config/global.go b/cc/config/global.go
index e2377e3..13ad27c 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -87,8 +87,6 @@
deviceGlobalLldflags = append(ClangFilterUnknownLldflags(deviceGlobalLdflags),
[]string{
- "-Wl,--pack-dyn-relocs=android+relr",
- "-Wl,--use-android-relr-tags",
"-fuse-ld=lld",
}...)
@@ -114,16 +112,16 @@
}
CStdVersion = "gnu99"
- CppStdVersion = "gnu++14"
+ CppStdVersion = "gnu++17"
ExperimentalCStdVersion = "gnu11"
- ExperimentalCppStdVersion = "gnu++1z"
+ ExperimentalCppStdVersion = "gnu++2a"
NdkMaxPrebuiltVersionInt = 27
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r344140b"
- ClangDefaultShortVersion = "8.0.4"
+ ClangDefaultVersion = "clang-r346389b"
+ ClangDefaultShortVersion = "8.0.6"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 6300a1b..dfdd40c 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -33,9 +33,9 @@
// Use C99-compliant printf functions (%zd).
"-D__USE_MINGW_ANSI_STDIO=1",
- // Admit to using >= Vista. Both are needed because of <_mingw.h>.
- "-D_WIN32_WINNT=0x0600",
- "-DWINVER=0x0600",
+ // Admit to using >= Windows 7. Both are needed because of <_mingw.h>.
+ "-D_WIN32_WINNT=0x0601",
+ "-DWINVER=0x0601",
// Get 64-bit off_t and related functions.
"-D_FILE_OFFSET_BITS=64",
@@ -140,6 +140,9 @@
pctx.StaticVariable("WindowsX8664ClangCppflags", strings.Join(windowsX8664ClangCppflags, " "))
pctx.StaticVariable("WindowsIncludeFlags", strings.Join(windowsIncludeFlags, " "))
+ // Yasm flags
+ pctx.StaticVariable("WindowsX86YasmFlags", "-f win32 -m x86")
+ pctx.StaticVariable("WindowsX8664YasmFlags", "-f win64 -m amd64")
}
type toolchainWindows struct {
@@ -228,6 +231,14 @@
return "${config.WindowsClangLldflags} ${config.WindowsX8664ClangLldflags}"
}
+func (t *toolchainWindowsX86) YasmFlags() string {
+ return "${config.WindowsX86YasmFlags}"
+}
+
+func (t *toolchainWindowsX8664) YasmFlags() string {
+ return "${config.WindowsX8664YasmFlags}"
+}
+
func (t *toolchainWindows) ShlibSuffix() string {
return ".dll"
}
diff --git a/cc/libbuildversion/libbuildversion.cpp b/cc/libbuildversion/libbuildversion.cpp
index d80d587..5242025 100644
--- a/cc/libbuildversion/libbuildversion.cpp
+++ b/cc/libbuildversion/libbuildversion.cpp
@@ -23,9 +23,19 @@
namespace android {
namespace build {
+#define PLACEHOLDER "SOONG BUILD NUMBER PLACEHOLDER"
+
+extern "C" {
+ char soong_build_number[128] = PLACEHOLDER;
+}
+
#ifdef __ANDROID__
std::string GetBuildNumber() {
+ if (strcmp(PLACEHOLDER, soong_build_number) != 0) {
+ return soong_build_number;
+ }
+
const prop_info* pi = __system_property_find("ro.build.version.incremental");
if (pi == nullptr) return "";
@@ -42,10 +52,6 @@
#else
-extern "C" {
- char soong_build_number[128] = "SOONG BUILD NUMBER PLACEHOLDER";
-}
-
std::string GetBuildNumber() {
return soong_build_number;
}
diff --git a/cc/libbuildversion/tests/Android.bp b/cc/libbuildversion/tests/Android.bp
index a18bc6c..b3b2061 100644
--- a/cc/libbuildversion/tests/Android.bp
+++ b/cc/libbuildversion/tests/Android.bp
@@ -2,10 +2,53 @@
name: "build_version_test_defaults",
use_version_lib: true,
host_supported: true,
+ dist: {
+ targets: ["test_build_version_test"],
+ },
target: {
+ android_arm: {
+ dist: {
+ dir: "android/arm",
+ },
+ },
+ android_arm64: {
+ dist: {
+ dir: "android/arm64",
+ },
+ },
+ android_x86: {
+ dist: {
+ dir: "android/x86",
+ },
+ },
+ android_x86_64: {
+ dist: {
+ dir: "android/x86_64",
+ },
+ },
+ darwin: {
+ dist: {
+ dir: "host/",
+ },
+ },
+ linux_glibc_x86: {
+ dist: {
+ dir: "host32/",
+ },
+ },
+ linux_glibc_x86_64: {
+ dist: {
+ dir: "host/",
+ },
+ },
windows: {
enabled: true,
},
+ windows_x86_64: {
+ dist: {
+ dest: "win64/build_ver_test.exe",
+ },
+ },
},
}
@@ -20,6 +63,11 @@
not_windows: {
shared_libs: ["libbuild_version_test"],
},
+ host: {
+ dist: {
+ suffix: "_host",
+ },
+ },
},
}
diff --git a/cc/library.go b/cc/library.go
index abaa6c4..bd43043 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -16,6 +16,8 @@
import (
"regexp"
+ "sort"
+ "strconv"
"strings"
"sync"
@@ -32,19 +34,21 @@
Srcs []string `android:"arch_variant"`
Cflags []string `android:"arch_variant"`
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
} `android:"arch_variant"`
Shared struct {
Srcs []string `android:"arch_variant"`
Cflags []string `android:"arch_variant"`
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
} `android:"arch_variant"`
// local file name to pass to the linker as -unexported_symbols_list
@@ -267,6 +271,9 @@
// Location of the linked, unstripped library for shared libraries
unstrippedOutputFile android.Path
+ // Location of the file that should be copied to dist dir when requested
+ distFile android.OptionalPath
+
versionScriptPath android.ModuleGenPath
// Decorated interafaces
@@ -408,11 +415,11 @@
buildFlags := flagsToBuilderFlags(flags)
if library.static() {
- srcs := android.PathsForModuleSrc(ctx, library.Properties.Static.Srcs)
+ srcs := ctx.ExpandSources(library.Properties.Static.Srcs, nil)
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceStaticLibrary,
srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
} else if library.shared() {
- srcs := android.PathsForModuleSrc(ctx, library.Properties.Shared.Srcs)
+ srcs := ctx.ExpandSources(library.Properties.Shared.Srcs, nil)
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceSharedLibrary,
srcs, library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
}
@@ -484,7 +491,29 @@
}
}
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+ if library.static() {
+ android.ExtractSourcesDeps(ctx, library.Properties.Static.Srcs)
+ } else if library.shared() {
+ android.ExtractSourcesDeps(ctx, library.Properties.Shared.Srcs)
+ }
+
+ return deps
+}
+
func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
+ if library.static() {
+ if library.Properties.Static.System_shared_libs != nil {
+ library.baseLinker.Properties.System_shared_libs = library.Properties.Static.System_shared_libs
+ }
+ } else if library.shared() {
+ if library.Properties.Shared.System_shared_libs != nil {
+ library.baseLinker.Properties.System_shared_libs = library.Properties.Shared.System_shared_libs
+ }
+ }
+
deps = library.baseLinker.linkerDeps(ctx, deps)
if library.static() {
@@ -542,10 +571,16 @@
outputFile := android.PathForModuleOut(ctx, fileName)
builderFlags := flagsToBuilderFlags(flags)
- if Bool(library.baseLinker.Properties.Use_version_lib) && ctx.Host() {
- versionedOutputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
- library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ if Bool(library.baseLinker.Properties.Use_version_lib) {
+ if ctx.Host() {
+ versionedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+ library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ } else {
+ versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+ library.distFile = android.OptionalPathForPath(versionedOutputFile)
+ library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ }
}
TransformObjToStaticLib(ctx, library.objects.objFiles, builderFlags, outputFile, objs.tidyFiles)
@@ -619,10 +654,23 @@
library.unstrippedOutputFile = outputFile
- if Bool(library.baseLinker.Properties.Use_version_lib) && ctx.Host() {
- versionedOutputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
- library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ if Bool(library.baseLinker.Properties.Use_version_lib) {
+ if ctx.Host() {
+ versionedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
+ library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ } else {
+ versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
+ library.distFile = android.OptionalPathForPath(versionedOutputFile)
+
+ if library.stripper.needsStrip(ctx) {
+ out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
+ library.distFile = android.OptionalPathForPath(out)
+ library.stripper.strip(ctx, versionedOutputFile, out, builderFlags)
+ }
+
+ library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
+ }
}
sharedLibs := deps.SharedLibs
@@ -899,8 +947,19 @@
func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Module) {
if staticCompiler, ok := static.compiler.(*libraryDecorator); ok {
sharedCompiler := shared.compiler.(*libraryDecorator)
+
+ // Check libraries in addition to cflags, since libraries may be exporting different
+ // include directories.
if len(staticCompiler.Properties.Static.Cflags) == 0 &&
- len(sharedCompiler.Properties.Shared.Cflags) == 0 {
+ len(sharedCompiler.Properties.Shared.Cflags) == 0 &&
+ len(staticCompiler.Properties.Static.Whole_static_libs) == 0 &&
+ len(sharedCompiler.Properties.Shared.Whole_static_libs) == 0 &&
+ len(staticCompiler.Properties.Static.Static_libs) == 0 &&
+ len(sharedCompiler.Properties.Shared.Static_libs) == 0 &&
+ len(staticCompiler.Properties.Static.Shared_libs) == 0 &&
+ len(sharedCompiler.Properties.Shared.Shared_libs) == 0 &&
+ staticCompiler.Properties.Static.System_shared_libs == nil &&
+ sharedCompiler.Properties.Shared.System_shared_libs == nil {
mctx.AddInterVariantDependency(reuseObjTag, shared, static)
sharedCompiler.baseCompiler.Properties.OriginalSrcs =
@@ -936,30 +995,68 @@
}
}
+// maps a module name to the list of stubs versions available for the module
+func stubsVersionsFor(config android.Config) map[string][]string {
+ return config.Once("stubVersions", func() interface{} {
+ return make(map[string][]string)
+ }).(map[string][]string)
+}
+
+var stubsVersionsLock sync.Mutex
+
+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
+ return versions[len(versions)-1]
+ }
+ return ""
+}
+
// Version mutator splits a module into the mandatory non-stubs variant
-// (which is named "impl") and zero or more stubs variants.
-func versionMutator(mctx android.BottomUpMutatorContext) {
+// (which is unnamed) and zero or more stubs variants.
+func VersionMutator(mctx android.BottomUpMutatorContext) {
if mctx.Os() != android.Android {
return
}
if m, ok := mctx.Module().(*Module); ok && !m.inRecovery() && m.linker != nil {
- if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() {
- versions := []string{""}
+ if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() &&
+ len(library.Properties.Stubs.Versions) > 0 {
+ versions := []string{}
for _, v := range library.Properties.Stubs.Versions {
+ if _, err := strconv.Atoi(v); err != nil {
+ mctx.PropertyErrorf("versions", "%q is not a number", v)
+ }
versions = append(versions, v)
}
+ sort.Slice(versions, func(i, j int) bool {
+ left, _ := strconv.Atoi(versions[i])
+ right, _ := strconv.Atoi(versions[j])
+ return left < right
+ })
+
+ // save the list of versions for later use
+ copiedVersions := make([]string, len(versions))
+ copy(copiedVersions, versions)
+ stubsVersionsLock.Lock()
+ defer stubsVersionsLock.Unlock()
+ stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = copiedVersions
+
+ // "" is for the non-stubs variant
+ versions = append(versions, "")
+
modules := mctx.CreateVariations(versions...)
for i, m := range modules {
l := m.(*Module).linker.(*libraryDecorator)
- if i == 0 {
- l.MutatedProperties.BuildStubs = false
- continue
+ if versions[i] != "" {
+ l.MutatedProperties.BuildStubs = true
+ l.MutatedProperties.StubsVersion = versions[i]
+ m.(*Module).Properties.HideFromMake = true
+ m.(*Module).sanitize = nil
+ m.(*Module).stl = nil
+ m.(*Module).Properties.PreventInstall = true
}
- // Mark that this variant is for stubs.
- l.MutatedProperties.BuildStubs = true
- l.MutatedProperties.StubsVersion = versions[i]
- m.(*Module).Properties.HideFromMake = true
}
} else {
mctx.CreateVariations("")
diff --git a/cc/linker.go b/cc/linker.go
index 3053609..854dfc5 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -18,6 +18,7 @@
"android/soong/android"
"android/soong/cc/config"
"fmt"
+ "strconv"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -48,7 +49,7 @@
// list of system libraries that will be dynamically linked to
// shared library and executable modules. If unset, generally defaults to libc,
// libm, and libdl. Set to [] to prevent linking against the defaults.
- System_shared_libs []string
+ System_shared_libs []string `android:"arch_variant"`
// allow the module to contain undefined symbols. By default,
// modules cannot contain undefined symbols that are not satisified by their immediate
@@ -236,35 +237,34 @@
deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
}
- if !ctx.static() {
- systemSharedLibs := linker.Properties.System_shared_libs
- if systemSharedLibs == nil {
- systemSharedLibs = []string{"libc", "libm", "libdl"}
- }
-
- if inList("libdl", deps.SharedLibs) {
- // If system_shared_libs has libc but not libdl, make sure shared_libs does not
- // have libdl to avoid loading libdl before libc.
- if inList("libc", systemSharedLibs) {
- if !inList("libdl", systemSharedLibs) {
- ctx.PropertyErrorf("shared_libs",
- "libdl must be in system_shared_libs, not shared_libs")
- }
- _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
- }
- }
-
- // If libc and libdl are both in system_shared_libs make sure libd comes after libc
- // to avoid loading libdl before libc.
- if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
- indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
- ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
- }
-
- deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
- } else if ctx.useSdk() || ctx.useVndk() {
- deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
+ var systemSharedLibs []string
+ if !ctx.useSdk() && !ctx.useVndk() {
+ systemSharedLibs = linker.Properties.System_shared_libs
}
+ if systemSharedLibs == nil {
+ systemSharedLibs = []string{"libc", "libm", "libdl"}
+ }
+
+ if inList("libdl", deps.SharedLibs) {
+ // If system_shared_libs has libc but not libdl, make sure shared_libs does not
+ // have libdl to avoid loading libdl before libc.
+ if inList("libc", systemSharedLibs) {
+ if !inList("libdl", systemSharedLibs) {
+ ctx.PropertyErrorf("shared_libs",
+ "libdl must be in system_shared_libs, not shared_libs")
+ }
+ _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
+ }
+ }
+
+ // If libc and libdl are both in system_shared_libs make sure libdl comes after libc
+ // to avoid loading libdl before libc.
+ if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
+ indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+ ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
+ }
+
+ deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
}
if ctx.Windows() {
@@ -298,6 +298,23 @@
return true
}
+// Check whether the SDK version is not older than the specific one
+func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool {
+ if ctx.sdkVersion() == "current" {
+ return true
+ }
+ parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion())
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version",
+ "Invalid sdk_version value (must be int or current): %q",
+ ctx.sdkVersion())
+ }
+ if parsedSdkVersion < SdkVersion {
+ return false
+ }
+ return true
+}
+
// ModuleContext extends BaseModuleContext
// BaseModuleContext should know if LLD is used?
func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -312,6 +329,13 @@
flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
if !BoolDefault(linker.Properties.Pack_relocations, true) {
flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none")
+ } else if ctx.Device() {
+ // The SHT_RELR relocations is only supported by API level >= 28.
+ // Do not turn this on if older version NDK is used.
+ if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=android+relr")
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--use-android-relr-tags")
+ }
}
} else {
flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 8177ff1..504a6a0 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -77,6 +77,11 @@
// Path to the NOTICE file associated with the headers.
License *string
+
+ // True if this API is not yet ready to be shipped in the NDK. It will be
+ // available in the platform for testing, but will be excluded from the
+ // sysroot provided to the NDK proper.
+ Draft bool
}
type headerModule struct {
@@ -182,6 +187,11 @@
// Path to the NOTICE file associated with the headers.
License *string
+
+ // True if this API is not yet ready to be shipped in the NDK. It will be
+ // available in the platform for testing, but will be excluded from the
+ // sysroot provided to the NDK proper.
+ Draft bool
}
// Like ndk_headers, but preprocesses the headers with the bionic versioner:
@@ -309,6 +319,11 @@
// Path to the NOTICE file associated with the headers.
License *string
+
+ // True if this API is not yet ready to be shipped in the NDK. It will be
+ // available in the platform for testing, but will be excluded from the
+ // sysroot provided to the NDK proper.
+ Draft bool
}
type preprocessedHeadersModule struct {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 63d9f29..53fe314 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -91,6 +91,11 @@
// Private property for use by the mutator that splits per-API level.
ApiLevel string `blueprint:"mutated"`
+
+ // True if this API is not yet ready to be shipped in the NDK. It will be
+ // available in the platform for testing, but will be excluded from the
+ // sysroot provided to the NDK proper.
+ Draft bool
}
type stubDecorator struct {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 80b5c6a..9265bff 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -104,22 +104,38 @@
}
if m, ok := module.(*headerModule); ok {
+ if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+ return
+ }
+
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*versionedHeaderModule); ok {
+ if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+ return
+ }
+
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*preprocessedHeadersModule); ok {
+ if ctx.Config().ExcludeDraftNdkApis() && m.properties.Draft {
+ return
+ }
+
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*Module); ok {
if installer, ok := m.installer.(*stubDecorator); ok {
+ if ctx.Config().ExcludeDraftNdkApis() &&
+ installer.properties.Draft {
+ return
+ }
installPaths = append(installPaths, installer.installPath)
}
diff --git a/cc/rs.go b/cc/rs.go
index 7c9f5d3..5421b92 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -16,13 +16,22 @@
import (
"android/soong/android"
+ "path/filepath"
+ "runtime"
"strings"
"github.com/google/blueprint"
)
func init() {
- pctx.HostBinToolVariable("rsCmd", "llvm-rs-cc")
+ pctx.VariableFunc("rsCmd", func(ctx android.PackageVarContext) string {
+ if ctx.Config().UnbundledBuild() {
+ // Use RenderScript prebuilts for unbundled builds but not PDK builds
+ return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin/llvm-rs-cc")
+ } else {
+ return pctx.HostBinToolPath(ctx, "llvm-rs-cc").String()
+ }
+ })
}
var rsCppCmdLine = strings.Replace(`
diff --git a/cc/sanitize.go b/cc/sanitize.go
index cd3b3e9..5db6bdf 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -36,7 +36,7 @@
asanLdflags = []string{"-Wl,-u,__asan_preinit"}
asanLibs = []string{"libasan"}
- hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than="}
+ hwasanCflags = []string{"-mllvm", "-hwasan-with-ifunc=0", "-fno-omit-frame-pointer", "-Wno-frame-larger-than=", "-mllvm", "-hwasan-create-frame-descriptions=0"}
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
"-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
@@ -49,8 +49,14 @@
cfiStaticLibsMutex sync.Mutex
hwasanStaticLibsMutex sync.Mutex
- intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
- minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
+ intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
+
+ // Pass -Xclang before -fsanitize-minimal-runtime to work around a driver
+ // check which rejects -fsanitize-minimal-runtime together with
+ // -fsanitize=shadow-call-stack even though this combination of flags
+ // is valid.
+ // TODO(pcc): Remove the -Xclang once LLVM r346526 is rolled into the compiler.
+ minimalRuntimeFlags = []string{"-Xclang", "-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
hwasanGlobalOptions = []string{"heap_history_size=4095"}
)
@@ -71,6 +77,7 @@
tsan
intOverflow
cfi
+ scs
)
func (t sanitizerType) String() string {
@@ -85,6 +92,8 @@
return "intOverflow"
case cfi:
return "cfi"
+ case scs:
+ return "scs"
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -109,6 +118,7 @@
Cfi *bool `android:"arch_variant"`
Integer_overflow *bool `android:"arch_variant"`
Scudo *bool `android:"arch_variant"`
+ Scs *bool `android:"arch_variant"`
// Sanitizers to run in the diagnostic mode (as opposed to the release mode).
// Replaces abort() on error with a human-readable error message.
@@ -118,6 +128,7 @@
Cfi *bool `android:"arch_variant"`
Integer_overflow *bool `android:"arch_variant"`
Misc_undefined []string `android:"arch_variant"`
+ No_recover []string
}
// value to pass to -fsanitize-recover=
@@ -276,6 +287,14 @@
s.Hwaddress = nil
}
+ // SCS is only implemented on AArch64.
+ // We also disable SCS if ASAN, TSAN or HWASAN are enabled because Clang considers
+ // them to be incompatible, although they are in fact compatible.
+ // TODO(pcc): Remove these checks once r347282 is rolled into the compiler.
+ if ctx.Arch().ArchType != android.Arm64 || Bool(s.Address) || Bool(s.Thread) || Bool(s.Hwaddress) {
+ s.Scs = nil
+ }
+
// Also disable CFI if ASAN is enabled.
if Bool(s.Address) || Bool(s.Hwaddress) {
s.Cfi = nil
@@ -299,7 +318,8 @@
}
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
- if ctx.inRecovery() {
+ // Keep libc instrumented so that recovery can run hwasan-instrumented code if necessary.
+ if ctx.inRecovery() && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") {
s.Hwaddress = nil
}
@@ -322,7 +342,7 @@
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
- Bool(s.Scudo) || Bool(s.Hwaddress)) {
+ Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
sanitize.Properties.SanitizerEnabled = true
}
@@ -357,6 +377,22 @@
return deps
}
+func toDisableImplicitIntegerChange(flags []string) bool {
+ // Returns true if any flag is fsanitize*integer, and there is
+ // no explicit flag about sanitize=implicit-integer-sign-change.
+ for _, f := range flags {
+ if strings.Contains(f, "sanitize=implicit-integer-sign-change") {
+ return false
+ }
+ }
+ for _, f := range flags {
+ if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
+ return true
+ }
+ }
+ return false
+}
+
func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
@@ -490,6 +526,10 @@
sanitizers = append(sanitizers, "scudo")
}
+ if Bool(sanitize.Properties.Sanitize.Scs) {
+ sanitizers = append(sanitizers, "shadow-call-stack")
+ }
+
if len(sanitizers) > 0 {
sanitizeArg := "-fsanitize=" + strings.Join(sanitizers, ",")
@@ -510,6 +550,10 @@
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
}
}
+ // http://b/119329758, Android core does not boot up with this sanitizer yet.
+ if toDisableImplicitIntegerChange(flags.CFlags) {
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
+ }
}
if len(diagSanitizers) > 0 {
@@ -522,6 +566,11 @@
strings.Join(sanitize.Properties.Sanitize.Recover, ","))
}
+ if sanitize.Properties.Sanitize.Diag.No_recover != nil {
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover="+
+ strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
+ }
+
// Link a runtime library if needed.
runtimeLibrary := ""
if Bool(sanitize.Properties.Sanitize.Address) {
@@ -553,9 +602,12 @@
sanitize.runtimeLibrary = runtimeLibrary
// When linking against VNDK, use the vendor variant of the runtime lib
- sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
if ctx.useVndk() {
sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + vendorSuffix
+ } else if ctx.inRecovery() {
+ sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary + recoverySuffix
+ } else {
+ sanitize.androidMkRuntimeLibrary = sanitize.runtimeLibrary
}
}
@@ -583,6 +635,9 @@
if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Hwaddress) {
ret.SubName += ".hwasan"
}
+ if ret.Class == "STATIC_LIBRARIES" && Bool(sanitize.Properties.Sanitize.Scs) {
+ ret.SubName += ".scs"
+ }
}
func (sanitize *sanitize) inSanitizerDir() bool {
@@ -601,6 +656,8 @@
return sanitize.Properties.Sanitize.Integer_overflow
case cfi:
return sanitize.Properties.Sanitize.Cfi
+ case scs:
+ return sanitize.Properties.Sanitize.Scs
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -610,7 +667,8 @@
return !sanitize.isSanitizerEnabled(asan) &&
!sanitize.isSanitizerEnabled(hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
- !sanitize.isSanitizerEnabled(cfi)
+ !sanitize.isSanitizerEnabled(cfi) &&
+ !sanitize.isSanitizerEnabled(scs)
}
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
@@ -634,6 +692,8 @@
sanitize.Properties.Sanitize.Integer_overflow = boolPtr(b)
case cfi:
sanitize.Properties.Sanitize.Cfi = boolPtr(b)
+ case scs:
+ sanitize.Properties.Sanitize.Scs = boolPtr(b)
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -683,7 +743,7 @@
if d, ok := child.(*Module); ok && d.sanitize != nil &&
!Bool(d.sanitize.Properties.Sanitize.Never) &&
!d.sanitize.isSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == hwasan {
+ if t == cfi || t == hwasan || t == scs {
if d.static() {
d.sanitize.Properties.SanitizeDep = true
}
@@ -779,6 +839,19 @@
modules[1].(*Module).Properties.PreventInstall = true
modules[1].(*Module).Properties.HideFromMake = true
}
+ } else if t == scs {
+ // We don't currently link any static libraries built with make into
+ // libraries built with SCS, so we don't need logic for propagating
+ // SCSness of dependencies into make.
+ if !c.static() {
+ if isSanitizerEnabled {
+ modules[0].(*Module).Properties.PreventInstall = true
+ modules[0].(*Module).Properties.HideFromMake = true
+ } else {
+ modules[1].(*Module).Properties.PreventInstall = true
+ modules[1].(*Module).Properties.HideFromMake = true
+ }
+ }
} else if t == hwasan {
if mctx.Device() {
// CFI and HWASAN are currently mutually exclusive so disable
diff --git a/cc/stl.go b/cc/stl.go
index 8eee612..4870870 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"fmt"
+ "strconv"
)
func getNdkStlFamily(m *Module) string {
@@ -110,6 +111,26 @@
}()
}
+func needsLibAndroidSupport(ctx BaseModuleContext) bool {
+ versionStr, err := normalizeNdkApiLevel(ctx, ctx.sdkVersion(), ctx.Arch())
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version", err.Error())
+ }
+
+ if versionStr == "current" {
+ return false
+ }
+
+ version, err := strconv.Atoi(versionStr)
+ if err != nil {
+ panic(fmt.Sprintf(
+ "invalid API level returned from normalizeNdkApiLevel: %q",
+ versionStr))
+ }
+
+ return version < 21
+}
+
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
switch stl.Properties.SelectedStl {
case "libstdc++":
@@ -141,7 +162,9 @@
} else {
deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
}
- deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
+ if needsLibAndroidSupport(ctx) {
+ deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
+ }
if ctx.Arch().ArchType == android.Arm {
deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
}
@@ -228,7 +251,7 @@
android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
android.Darwin: []string{"-lc", "-lSystem"},
android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
- "-lmoldname", "-lmingwex", "-lmsvcr110", "-lmsvcrt", "-lpthread",
+ "-lmoldname", "-lmingwex", "-lmsvcrt", "-lucrt", "-lpthread",
"-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
"-Wl,--end-group"},
}
diff --git a/cc/tidy.go b/cc/tidy.go
index ddb445a..6bac846 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -108,6 +108,12 @@
if len(tidy.Properties.Tidy_checks) > 0 {
tidyChecks = tidyChecks + "," + strings.Join(esc(tidy.Properties.Tidy_checks), ",")
}
+ if ctx.Windows() {
+ // https://b.corp.google.com/issues/120614316
+ // mingw32 has cert-dcl16-c warning in NO_ERROR,
+ // which is used in many Android files.
+ tidyChecks = tidyChecks + ",-cert-dcl16-c"
+ }
flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
return flags
diff --git a/cc/xom.go b/cc/xom.go
new file mode 100644
index 0000000..182069f
--- /dev/null
+++ b/cc/xom.go
@@ -0,0 +1,76 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// 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 cc
+
+import (
+ "android/soong/android"
+)
+
+type XomProperties struct {
+ Xom *bool
+}
+
+type xom struct {
+ Properties XomProperties
+}
+
+func (xom *xom) props() []interface{} {
+ return []interface{}{&xom.Properties}
+}
+
+func (xom *xom) begin(ctx BaseModuleContext) {}
+
+func (xom *xom) deps(ctx BaseModuleContext, deps Deps) Deps {
+ return deps
+}
+
+func (xom *xom) flags(ctx ModuleContext, flags Flags) Flags {
+ disableXom := false
+
+ if !ctx.Config().EnableXOM() || ctx.Config().XOMDisabledForPath(ctx.ModuleDir()) {
+ disableXom = true
+ }
+
+ if xom.Properties.Xom != nil && !*xom.Properties.Xom {
+ return flags
+ }
+
+ // If any static dependencies have XOM disabled, we should disable XOM in this module,
+ // the assumption being if it's been explicitly disabled then there's probably incompatible
+ // code in the library which may get pulled in.
+ if !ctx.static() && !disableXom {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ cc, ok := m.(*Module)
+ if !ok || cc.xom == nil || !cc.static() {
+ return
+ }
+ if cc.xom.Properties.Xom != nil && !*cc.xom.Properties.Xom {
+ disableXom = true
+ return
+ }
+ })
+ }
+
+ // Enable execute-only if none of the dependencies disable it,
+ // also if it's explicitly set true (allows overriding dependencies disabling it).
+ if !disableXom || (xom.Properties.Xom != nil && *xom.Properties.Xom) {
+ // XOM is only supported on AArch64 when using lld.
+ if ctx.Arch().ArchType == android.Arm64 && ctx.useClangLld(ctx) {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-execute-only")
+ }
+ }
+
+ return flags
+}
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index 8e71a97..c21da44 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -19,6 +19,7 @@
"flag"
"fmt"
"hash/crc32"
+ "io"
"io/ioutil"
"log"
"os"
@@ -66,6 +67,7 @@
manifest = flag.String("m", "", "manifest file to insert in jar")
pyMain = flag.String("pm", "", "__main__.py file to insert in par")
entrypoint = flag.String("e", "", "par entrypoint file to insert in par")
+ prefix = flag.String("prefix", "", "A file to prefix to the zip file")
ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
)
@@ -77,7 +79,7 @@
func main() {
flag.Usage = func() {
- fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] [-pm __main__.py] output [inputs...]")
+ fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [--prefix script] [-e entrypoint] [-pm __main__.py] output [inputs...]")
flag.PrintDefaults()
}
@@ -99,6 +101,19 @@
log.Fatal(err)
}
defer output.Close()
+
+ var offset int64
+ if *prefix != "" {
+ prefixFile, err := os.Open(*prefix)
+ if err != nil {
+ log.Fatal(err)
+ }
+ offset, err = io.Copy(output, prefixFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
writer := zip.NewWriter(output)
defer func() {
err := writer.Close()
@@ -106,6 +121,7 @@
log.Fatal(err)
}
}()
+ writer.SetOffset(offset)
// make readers
readers := []namedZipReader{}
diff --git a/java/app_builder.go b/java/app_builder.go
index b0983bd..28fc4c4 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -32,10 +32,10 @@
Signapk = pctx.AndroidStaticRule("signapk",
blueprint.RuleParams{
Command: `${config.JavaCmd} -Djava.library.path=$$(dirname $signapkJniLibrary) ` +
- `-jar $signapkCmd $certificates $in $out`,
+ `-jar $signapkCmd $flags $certificates $in $out`,
CommandDeps: []string{"$signapkCmd", "$signapkJniLibrary"},
},
- "certificates")
+ "flags", "certificates")
androidManifestMerger = pctx.AndroidStaticRule("androidManifestMerger",
blueprint.RuleParams{
diff --git a/java/dex.go b/java/dex.go
index 5cec325..a6d486a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -160,6 +160,11 @@
// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
// dictionary of the app and move the app from libraryjars to injars.
+ // Don't strip out debug information for eng builds.
+ if ctx.Config().Eng() {
+ r8Flags = append(r8Flags, "--debug")
+ }
+
return r8Flags, r8Deps
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 9dadb30..8e0a62a 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -360,6 +360,9 @@
// a list of top-level directories containing Java stub files to merge show/hide annotations from.
Merge_inclusion_annotations_dirs []string
+ // a file containing a list of classes to do nullability validation for.
+ Validate_nullability_from_list *string
+
// a file containing expected warnings produced by validation of nullability annotations.
Check_nullability_warnings *string
@@ -623,7 +626,7 @@
case libTag:
switch dep := module.(type) {
case Dependency:
- deps.classpath = append(deps.classpath, dep.ImplementationJars()...)
+ deps.classpath = append(deps.classpath, dep.HeaderJars()...)
case SdkLibraryDependency:
sdkVersion := j.sdkVersion()
linkType := javaSdk
@@ -1126,9 +1129,9 @@
Inputs: d.Javadoc.srcFiles,
Implicits: implicits,
Args: map[string]string{
- "outDir": android.PathForModuleOut(ctx, "out").String(),
- "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
- "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
+ "outDir": android.PathForModuleOut(ctx, "dokka-out").String(),
+ "srcJarDir": android.PathForModuleOut(ctx, "dokka-srcjars").String(),
+ "stubsDir": android.PathForModuleOut(ctx, "dokka-stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"classpathArgs": classpathArgs,
"opts": opts,
@@ -1302,6 +1305,9 @@
}
}
+ if String(d.properties.Validate_nullability_from_list) != "" {
+ android.ExtractSourceDeps(ctx, d.properties.Validate_nullability_from_list)
+ }
if String(d.properties.Check_nullability_warnings) != "" {
android.ExtractSourceDeps(ctx, d.properties.Check_nullability_warnings)
}
@@ -1411,7 +1417,9 @@
var flags string
if Bool(d.properties.Annotations_enabled) {
flags += " --include-annotations"
- validatingNullability := strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs")
+ validatingNullability :=
+ strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") ||
+ String(d.properties.Validate_nullability_from_list) != ""
migratingNullability := String(d.properties.Previous_api) != ""
if !(migratingNullability || validatingNullability) {
ctx.PropertyErrorf("previous_api",
@@ -1422,6 +1430,9 @@
*implicits = append(*implicits, previousApi)
flags += " --migrate-nullness " + previousApi.String()
}
+ if s := String(d.properties.Validate_nullability_from_list); s != "" {
+ flags += " --validate-nullability-from-list " + ctx.ExpandSource(s, "validate_nullability_from_list").String()
+ }
if validatingNullability {
d.nullabilityWarningsFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_nullability_warnings.txt")
*implicitOutputs = append(*implicitOutputs, d.nullabilityWarningsFile)
@@ -1574,7 +1585,7 @@
Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
implicits...),
Args: map[string]string{
- "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
+ "srcJarDir": android.PathForModuleOut(ctx, "apicheck-srcjars").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"javaVersion": javaVersion,
"bootclasspathArgs": bootclasspathArgs,
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e513a59..fdbf19d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -229,19 +229,19 @@
// Create dist rules to install the stubs libs to the dist dir
if len(module.publicApiStubsPath) == 1 {
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.publicApiStubsPath.Strings()[0]+
+ module.publicApiStubsImplPath.Strings()[0]+
":"+path.Join("apistubs", owner, "public",
module.BaseModuleName()+".jar")+")")
}
if len(module.systemApiStubsPath) == 1 {
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.systemApiStubsPath.Strings()[0]+
+ module.systemApiStubsImplPath.Strings()[0]+
":"+path.Join("apistubs", owner, "system",
module.BaseModuleName()+".jar")+")")
}
if len(module.testApiStubsPath) == 1 {
fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.testApiStubsPath.Strings()[0]+
+ module.testApiStubsImplPath.Strings()[0]+
":"+path.Join("apistubs", owner, "test",
module.BaseModuleName()+".jar")+")")
}
@@ -541,11 +541,6 @@
props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
}
}
- // These libs are required by doclava to parse the framework sources add via
- // Src_lib and Src_lib_whitelist_* properties just above.
- // If we don't add them to the classpath, errors messages are generated by doclava,
- // though they don't break the build.
- props.Libs = append(props.Libs, "framework")
if Bool(module.properties.Metalava_enabled) == true {
mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
diff --git a/python/builder.go b/python/builder.go
index 11a792a..cbbe56e 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -45,20 +45,24 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
- `$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
- `chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
+ `echo "#!/usr/bin/env python" >${out}.prefix &&` +
+ `$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` +
+ `chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
CommandDeps: []string{"$mergeParCmd"},
},
- "interp", "main", "template", "stub", "mergedZip", "srcsZips")
+ "interp", "main", "template", "stub", "srcsZips")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
- Command: `echo '$main' > $entryPoint &&` +
- `$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
- `chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
+ // `echo -n` to trim the newline, since the python code just wants the name.
+ // /bin/sh (used by ninja) on Mac turns off posix mode, and stops supporting -n.
+ // Explicitly use bash instead.
+ Command: `/bin/bash -c "echo -n '$main' > $entryPoint" &&` +
+ `$mergeParCmd -p --prefix $launcher -e $entryPoint $out $srcsZips && ` +
+ `chmod +x $out && (rm -f $entryPoint)`,
CommandDeps: []string{"$mergeParCmd"},
},
- "main", "entryPoint", "mergedZip", "srcsZips", "launcher")
+ "main", "entryPoint", "srcsZips", "launcher")
)
func init() {
@@ -73,9 +77,6 @@
launcherPath android.OptionalPath, interpreter, main, binName string,
srcsZips android.Paths) android.Path {
- // .intermediate output path for merged zip file.
- mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
-
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
@@ -96,12 +97,11 @@
Output: binFile,
Implicits: implicits,
Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(main, "/", `\/`, -1),
- "template": template.String(),
- "stub": stub,
- "mergedZip": mergedZip.String(),
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
+ "interp": strings.Replace(interpreter, "/", `\/`, -1),
+ "main": strings.Replace(main, "/", `\/`, -1),
+ "template": template.String(),
+ "stub": stub,
+ "srcsZips": strings.Join(srcsZips.Strings(), " "),
},
})
} else if launcherPath.Valid() {
@@ -117,9 +117,8 @@
Output: binFile,
Implicits: implicits,
Args: map[string]string{
- "main": main,
+ "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
"entryPoint": entryPoint,
- "mergedZip": mergedZip.String(),
"srcsZips": strings.Join(srcsZips.Strings(), " "),
"launcher": launcherPath.String(),
},
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 81f8564..947458a 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -48,7 +48,8 @@
"Malloc_not_svelte": false,
"Safestack": false,
- "Ndk_abis": true
+ "Ndk_abis": true,
+ "Exclude_draft_ndk_apis": true
}
EOF
m --skip-make ${SOONG_OUT}/ndk.timestamp
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 07925df..64f49cb 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -61,7 +61,7 @@
help='specify additional <uses-library> tag to add. android:requred is set to false')
parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
help='manifest is for a package built against the platform')
- parser.add_argument('--prefer-integrity', type=bool, dest='prefer_integrity',
+ parser.add_argument('--prefer-integrity', dest='prefer_integrity', action='store_true',
help=('specify if the app prefers strict integrity. Should not be conflict if ' +
'already declared in the manifest.'))
parser.add_argument('input', help='input AndroidManifest.xml file')
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index d48ce58..e2e4368 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -75,18 +75,14 @@
var Configuration = map[string]PathConfig{
"awk": Allowed,
- "basename": Allowed,
"bash": Allowed,
"bc": Allowed,
"bzip2": Allowed,
"chmod": Allowed,
- "cmp": Allowed,
"cp": Allowed,
- "cut": Allowed,
"date": Allowed,
"dd": Allowed,
"diff": Allowed,
- "dirname": Allowed,
"du": Allowed,
"echo": Allowed,
"egrep": Allowed,
@@ -98,7 +94,6 @@
"git": Allowed,
"grep": Allowed,
"gzip": Allowed,
- "head": Allowed,
"hexdump": Allowed,
"hostname": Allowed,
"jar": Allowed,
@@ -109,28 +104,22 @@
"lsof": Allowed,
"m4": Allowed,
"md5sum": Allowed,
- "mkdir": Allowed,
"mktemp": Allowed,
"mv": Allowed,
- "od": Allowed,
"openssl": Allowed,
- "paste": Allowed,
"patch": Allowed,
"pgrep": Allowed,
"pkill": Allowed,
"ps": Allowed,
"pstree": Allowed,
- "pwd": Allowed,
"python": Allowed,
"python2.7": Allowed,
"python3": Allowed,
"readlink": Allowed,
"realpath": Allowed,
"rm": Allowed,
- "rmdir": Allowed,
"rsync": Allowed,
"sed": Allowed,
- "setsid": Allowed,
"sh": Allowed,
"sha1sum": Allowed,
"sha256sum": Allowed,
@@ -138,18 +127,12 @@
"sort": Allowed,
"stat": Allowed,
"tar": Allowed,
- "tail": Allowed,
- "tee": Allowed,
"timeout": Allowed,
- "todos": Allowed,
- "touch": Allowed,
"tr": Allowed,
- "unix2dos": Allowed,
"unzip": Allowed,
"wc": Allowed,
"which": Allowed,
"xargs": Allowed,
- "xxd": Allowed,
"xz": Allowed,
"zip": Allowed,
"zipinfo": Allowed,
@@ -169,15 +152,31 @@
"pkg-config": Forbidden,
// On linux we'll use the toybox version of these instead
- "cat": Toybox,
- "comm": Toybox,
- "env": Toybox,
- "id": Toybox,
- "sleep": Toybox,
- "true": Toybox,
- "uname": Toybox,
- "uniq": Toybox,
- "whoami": Toybox,
+ "basename": Toybox,
+ "cat": Toybox,
+ "cmp": Toybox,
+ "comm": Toybox,
+ "cut": Toybox,
+ "dirname": Toybox,
+ "env": Toybox,
+ "head": Toybox,
+ "id": Toybox,
+ "mkdir": Toybox,
+ "od": Toybox,
+ "paste": Toybox,
+ "pwd": Toybox,
+ "rmdir": Toybox,
+ "setsid": Toybox,
+ "sleep": Toybox,
+ "tail": Toybox,
+ "tee": Toybox,
+ "touch": Toybox,
+ "true": Toybox,
+ "uname": Toybox,
+ "uniq": Toybox,
+ "unix2dos": Toybox,
+ "whoami": Toybox,
+ "xxd": Toybox,
}
func init() {