Merge "Soong: Add synopsis to ndk_prebuilt_* modules."
diff --git a/Android.bp b/Android.bp
index 6b59f04..afac2b5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -70,6 +70,7 @@
"android/testing.go",
"android/util.go",
"android/variable.go",
+ "android/visibility.go",
"android/vts_config.go",
"android/writedocs.go",
@@ -90,6 +91,7 @@
"android/rule_builder_test.go",
"android/util_test.go",
"android/variable_test.go",
+ "android/visibility_test.go",
"android/vts_config_test.go",
],
}
@@ -274,6 +276,7 @@
"java/plugin.go",
"java/prebuilt_apis.go",
"java/proto.go",
+ "java/robolectric.go",
"java/sdk.go",
"java/sdk_library.go",
"java/support_libraries.go",
@@ -441,6 +444,7 @@
defaults: ["linux_bionic_supported"],
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
arch: {
arm: {
@@ -463,6 +467,7 @@
defaults: ["linux_bionic_supported"],
vendor_available: true,
recovery_available: true,
+ native_bridge_supported: true,
arch: {
arm: {
@@ -481,6 +486,118 @@
}
toolchain_library {
+ name: "libgcc_stripped",
+ defaults: ["linux_bionic_supported"],
+ vendor_available: true,
+ recovery_available: true,
+ native_bridge_supported: true,
+
+ arch: {
+ arm: {
+ src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
+ strip: {
+ keep_symbols_list: [
+ // unwind-arm.o
+ "_Unwind_Complete",
+ "_Unwind_DeleteException",
+ "_Unwind_GetCFA",
+ "_Unwind_VRS_Get",
+ "_Unwind_VRS_Pop",
+ "_Unwind_VRS_Set",
+ "__aeabi_unwind_cpp_pr0",
+ "__aeabi_unwind_cpp_pr1",
+ "__aeabi_unwind_cpp_pr2",
+ "__gnu_Unwind_Backtrace",
+ "__gnu_Unwind_ForcedUnwind",
+ "__gnu_Unwind_RaiseException",
+ "__gnu_Unwind_Resume",
+ "__gnu_Unwind_Resume_or_Rethrow",
+
+ // libunwind.o
+ "_Unwind_Backtrace",
+ "_Unwind_ForcedUnwind",
+ "_Unwind_RaiseException",
+ "_Unwind_Resume",
+ "_Unwind_Resume_or_Rethrow",
+ "___Unwind_Backtrace",
+ "___Unwind_ForcedUnwind",
+ "___Unwind_RaiseException",
+ "___Unwind_Resume",
+ "___Unwind_Resume_or_Rethrow",
+ "__gnu_Unwind_Restore_VFP",
+ "__gnu_Unwind_Restore_VFP_D",
+ "__gnu_Unwind_Restore_VFP_D_16_to_31",
+ "__gnu_Unwind_Restore_WMMXC",
+ "__gnu_Unwind_Restore_WMMXD",
+ "__gnu_Unwind_Save_VFP",
+ "__gnu_Unwind_Save_VFP_D",
+ "__gnu_Unwind_Save_VFP_D_16_to_31",
+ "__gnu_Unwind_Save_WMMXC",
+ "__gnu_Unwind_Save_WMMXD",
+ "__restore_core_regs",
+ "restore_core_regs",
+
+ // pr-support.o
+ "_Unwind_GetDataRelBase",
+ "_Unwind_GetLanguageSpecificData",
+ "_Unwind_GetRegionStart",
+ "_Unwind_GetTextRelBase",
+ "__gnu_unwind_execute",
+ "__gnu_unwind_frame",
+ ],
+ use_gnu_strip: true,
+ },
+ },
+ arm64: {
+ src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
+ },
+ x86: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcc.a",
+
+ },
+ x86_64: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcc.a",
+ },
+ },
+ strip: {
+ keep_symbols_list: [
+ // unwind-dw2.o
+ "_Unwind_Backtrace",
+ "_Unwind_DeleteException",
+ "_Unwind_FindEnclosingFunction",
+ "_Unwind_ForcedUnwind",
+ "_Unwind_GetCFA",
+ "_Unwind_GetDataRelBase",
+ "_Unwind_GetGR",
+ "_Unwind_GetIP",
+ "_Unwind_GetIPInfo",
+ "_Unwind_GetLanguageSpecificData",
+ "_Unwind_GetRegionStart",
+ "_Unwind_GetTextRelBase",
+ "_Unwind_RaiseException",
+ "_Unwind_Resume",
+ "_Unwind_Resume_or_Rethrow",
+ "_Unwind_SetGR",
+ "_Unwind_SetIP",
+ "__frame_state_for",
+
+ // unwind-dw2-fde-dip.o
+ "_Unwind_Find_FDE",
+ "__deregister_frame",
+ "__deregister_frame_info",
+ "__deregister_frame_info_bases",
+ "__register_frame",
+ "__register_frame_info",
+ "__register_frame_info_bases",
+ "__register_frame_info_table",
+ "__register_frame_info_table_bases",
+ "__register_frame_table",
+ ],
+ use_gnu_strip: true,
+ },
+}
+
+toolchain_library {
name: "libwinpthread",
host_supported: true,
enabled: false,
diff --git a/README.md b/README.md
index 2957940..b0b61a8 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,30 @@
}
```
+### Packages
+
+The build is organized into packages where each package is a collection of related files and a
+specification of the dependencies among them in the form of modules.
+
+A package is defined as a directory containing a file named `Android.bp`, residing beneath the
+top-level directory in the build and its name is its path relative to the top-level directory. A
+package includes all files in its directory, plus all subdirectories beneath it, except those which
+themselves contain an `Android.bp` file.
+
+The modules in a package's `Android.bp` and included files are part of the module.
+
+For example, in the following directory tree (where `.../android/` is the top-level Android
+directory) there are two packages, `my/app`, and the subpackage `my/app/tests`. Note that
+`my/app/data` is not a package, but a directory belonging to package `my/app`.
+
+ .../android/my/app/Android.bp
+ .../android/my/app/app.cc
+ .../android/my/app/data/input.txt
+ .../android/my/app/tests/Android.bp
+ .../android/my/app/tests/test.cc
+
+This is based on the Bazel package concept.
+
### Name resolution
Soong provides the ability for modules in different directories to specify
@@ -139,6 +163,54 @@
built by the `m` command. After we have fully converted from Make to Soong, the
details of enabling namespaces could potentially change.
+### Visibility
+
+The `visibility` property on a module controls whether the module can be
+used by other packages. Modules are always visible to other modules declared
+in the same package. This is based on the Bazel visibility mechanism.
+
+If specified the `visibility` property must contain at least one rule.
+
+Each rule in the property must be in one of the following forms:
+* `["//visibility:public"]`: Anyone can use this module.
+* `["//visibility:private"]`: Only rules in the module's package (not its
+subpackages) can use this module.
+* `["//some/package:__pkg__", "//other/package:__pkg__"]`: Only modules in
+`some/package` and `other/package` (defined in `some/package/*.bp` and
+`other/package/*.bp`) have access to this module. Note that sub-packages do not
+have access to the rule; for example, `//some/package/foo:bar` or
+`//other/package/testing:bla` wouldn't have access. `__pkg__` is a special
+module and must be used verbatim. It represents all of the modules in the
+package.
+* `["//project:__subpackages__", "//other:__subpackages__"]`: Only modules in
+packages `project` or `other` or in one of their sub-packages have access to
+this module. For example, `//project:rule`, `//project/library:lib` or
+`//other/testing/internal:munge` are allowed to depend on this rule (but not
+`//independent:evil`)
+* `["//project"]`: This is shorthand for `["//project:__pkg__"]`
+* `[":__subpackages__"]`: This is shorthand for `["//project:__subpackages__"]`
+where `//project` is the module's package. e.g. using `[":__subpackages__"]` in
+`packages/apps/Settings/Android.bp` is equivalent to
+`//packages/apps/Settings:__subpackages__`.
+* `["//visibility:legacy_public"]`: The default visibility, behaves as
+`//visibility:public` for now. It is an error if it is used in a module.
+
+The visibility rules of `//visibility:public` and `//visibility:private` can
+not be combined with any other visibility specifications.
+
+Packages outside `vendor/` cannot make themselves visible to specific packages
+in `vendor/`, e.g. a module in `libcore` cannot declare that it is visible to
+say `vendor/google`, instead it must make itself visible to all packages within
+`vendor/` using `//vendor:__subpackages__`.
+
+If a module does not specify the `visibility` property the module is
+`//visibility:legacy_public`. Once the build has been completely switched over to
+soong it is possible that a global refactoring will be done to change this to
+`//visibility:private` at which point all modules that do not currently specify
+a `visibility` property will be updated to have
+`visibility = [//visibility:legacy_public]` added. It will then be the owner's
+responsibility to replace that with a more appropriate visibility.
+
### Formatter
Soong includes a canonical formatter for blueprint files, similar to
diff --git a/android/androidmk.go b/android/androidmk.go
index 2a3748e..2bbd452 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -28,6 +28,10 @@
"github.com/google/blueprint/bootstrap"
)
+var (
+ NativeBridgeSuffix = ".native_bridge"
+)
+
func init() {
RegisterSingletonType("androidmk", AndroidMkSingleton)
}
@@ -161,6 +165,10 @@
}
}
+ if amod.Target().NativeBridge {
+ a.SubName += NativeBridgeSuffix
+ }
+
fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
// Collect make variable assignment entries.
@@ -190,7 +198,22 @@
case Device:
// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
if archStr != "common" {
- a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
+ if amod.Target().NativeBridge {
+ // TODO: Unhardcode these rules.
+ guestArchStr := archStr
+ hostArchStr := ""
+ if guestArchStr == "arm" {
+ hostArchStr = "x86"
+ } else if guestArchStr == "arm64" {
+ hostArchStr = "x86_64"
+ }
+
+ if hostArchStr != "" {
+ a.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
+ }
+ } else {
+ a.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
+ }
}
a.AddStrings("LOCAL_INIT_RC", amod.commonProperties.Init_rc...)
diff --git a/android/arch.go b/android/arch.go
index 957a659..c68fe46 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -683,13 +683,25 @@
return NoOsType
}
+type NativeBridgeSupport bool
+
+const (
+ NativeBridgeDisabled NativeBridgeSupport = false
+ NativeBridgeEnabled NativeBridgeSupport = true
+)
+
type Target struct {
- Os OsType
- Arch Arch
+ Os OsType
+ Arch Arch
+ NativeBridge NativeBridgeSupport
}
func (target Target) String() string {
- return target.Os.String() + "_" + target.Arch.String()
+ variant := ""
+ if target.NativeBridge {
+ variant = "native_bridge_"
+ }
+ return target.Os.String() + "_" + variant + target.Arch.String()
}
// archMutator splits a module into a variant for each Target requested by the module. Target selection
@@ -750,6 +762,18 @@
continue
}
+ // Filter NativeBridge targets unless they are explicitly supported
+ if os == Android && !Bool(base.commonProperties.Native_bridge_supported) {
+ var targets []Target
+ for _, t := range osTargets {
+ if !t.NativeBridge {
+ targets = append(targets, t)
+ }
+ }
+
+ osTargets = targets
+ }
+
// only the primary arch in the recovery partition
if os == Android && module.InstallInRecovery() {
osTargets = []Target{osTargets[0]}
@@ -1378,7 +1402,8 @@
targets := make(map[OsType][]Target)
var targetErr error
- addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string) {
+ addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string,
+ nativeBridgeEnabled NativeBridgeSupport) {
if targetErr != nil {
return
}
@@ -1391,8 +1416,9 @@
targets[os] = append(targets[os],
Target{
- Os: os,
- Arch: arch,
+ Os: os,
+ Arch: arch,
+ NativeBridge: nativeBridgeEnabled,
})
}
@@ -1400,14 +1426,14 @@
return nil, fmt.Errorf("No host primary architecture set")
}
- addTarget(BuildOs, *variables.HostArch, nil, nil, nil)
+ addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled)
if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
- addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil)
+ addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled)
}
if Bool(config.Host_bionic) {
- addTarget(LinuxBionic, "x86_64", nil, nil, nil)
+ addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled)
}
if String(variables.CrossHost) != "" {
@@ -1420,10 +1446,10 @@
return nil, fmt.Errorf("No cross-host primary architecture set")
}
- addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil)
+ addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled)
if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
- addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil)
+ addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled)
}
}
@@ -1434,18 +1460,32 @@
}
addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
- variables.DeviceCpuVariant, variables.DeviceAbi)
+ variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled)
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
addTarget(Android, *variables.DeviceSecondaryArch,
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
- variables.DeviceSecondaryAbi)
+ variables.DeviceSecondaryAbi, NativeBridgeDisabled)
deviceArches := targets[Android]
if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
deviceArches[1].Arch.Native = false
}
}
+
+ if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
+ addTarget(Android, *variables.NativeBridgeArch,
+ variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
+ variables.NativeBridgeAbi, NativeBridgeEnabled)
+ }
+
+ if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
+ variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" {
+ addTarget(Android, *variables.NativeBridgeSecondaryArch,
+ variables.NativeBridgeSecondaryArchVariant,
+ variables.NativeBridgeSecondaryCpuVariant,
+ variables.NativeBridgeSecondaryAbi, NativeBridgeEnabled)
+ }
}
if targetErr != nil {
diff --git a/android/config.go b/android/config.go
index 25615b6..b142042 100644
--- a/android/config.go
+++ b/android/config.go
@@ -234,16 +234,36 @@
return Config{config}
}
+func TestArchConfigNativeBridge(buildDir string, env map[string]string) Config {
+ testConfig := TestConfig(buildDir, env)
+ config := testConfig.config
+
+ config.Targets = map[OsType][]Target{
+ Android: []Target{
+ {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
+ {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled},
+ },
+ BuildOs: []Target{
+ {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
+ {BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled},
+ },
+ }
+
+ return testConfig
+}
+
func TestArchConfigFuchsia(buildDir string, env map[string]string) Config {
testConfig := TestConfig(buildDir, env)
config := testConfig.config
config.Targets = map[OsType][]Target{
Fuchsia: []Target{
- {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}},
+ {Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}, NativeBridgeDisabled},
},
BuildOs: []Target{
- {BuildOs, Arch{ArchType: X86_64}},
+ {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
},
}
@@ -257,12 +277,12 @@
config.Targets = map[OsType][]Target{
Android: []Target{
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled},
},
BuildOs: []Target{
- {BuildOs, Arch{ArchType: X86_64}},
- {BuildOs, Arch{ArchType: X86}},
+ {BuildOs, Arch{ArchType: X86_64}, NativeBridgeDisabled},
+ {BuildOs, Arch{ArchType: X86}, NativeBridgeDisabled},
},
}
@@ -932,6 +952,10 @@
return c.config.productVariables.BoardPlatPrivateSepolicyDirs
}
+func (c *deviceConfig) SepolicyM4Defs() []string {
+ return c.config.productVariables.BoardSepolicyM4Defs
+}
+
func (c *deviceConfig) OverrideManifestPackageNameFor(name string) (manifestName string, overridden bool) {
return findOverrideValue(c.config.productVariables.ManifestPackageNameOverrides, name,
"invalid override rule %q in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES should be <module_name>:<manifest_name>")
@@ -1064,3 +1088,15 @@
func (c *deviceConfig) TargetFSConfigGen() []string {
return c.config.productVariables.TargetFSConfigGen
}
+
+func (c *config) ProductPublicSepolicyDirs() []string {
+ return c.productVariables.ProductPublicSepolicyDirs
+}
+
+func (c *config) ProductPrivateSepolicyDirs() []string {
+ return c.productVariables.ProductPrivateSepolicyDirs
+}
+
+func (c *config) ProductCompatibleProperty() bool {
+ return Bool(c.productVariables.ProductCompatibleProperty)
+}
diff --git a/android/module.go b/android/module.go
index b12f0c1..fb5c00a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -143,6 +143,7 @@
OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+ GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
@@ -210,6 +211,33 @@
// emit build rules for this module
Enabled *bool `android:"arch_variant"`
+ // Controls the visibility of this module to other modules. Allowable values are one or more of
+ // these formats:
+ //
+ // ["//visibility:public"]: Anyone can use this module.
+ // ["//visibility:private"]: Only rules in the module's package (not its subpackages) can use
+ // this module.
+ // ["//some/package:__pkg__", "//other/package:__pkg__"]: Only modules in some/package and
+ // other/package (defined in some/package/*.bp and other/package/*.bp) have access to
+ // this module. Note that sub-packages do not have access to the rule; for example,
+ // //some/package/foo:bar or //other/package/testing:bla wouldn't have access. __pkg__
+ // is a special module and must be used verbatim. It represents all of the modules in the
+ // package.
+ // ["//project:__subpackages__", "//other:__subpackages__"]: Only modules in packages project
+ // or other or in one of their sub-packages have access to this module. For example,
+ // //project:rule, //project/library:lib or //other/testing/internal:munge are allowed
+ // to depend on this rule (but not //independent:evil)
+ // ["//project"]: This is shorthand for ["//project:__pkg__"]
+ // [":__subpackages__"]: This is shorthand for ["//project:__subpackages__"] where
+ // //project is the module's package. e.g. using [":__subpackages__"] in
+ // packages/apps/Settings/Android.bp is equivalent to
+ // //packages/apps/Settings:__subpackages__.
+ // ["//visibility:legacy_public"]: The default visibility, behaves as //visibility:public
+ // for now. It is an error if it is used in a module.
+ // See https://android.googlesource.com/platform/build/soong/+/master/README.md#visibility for
+ // more details.
+ Visibility []string
+
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
@@ -262,6 +290,9 @@
// Whether this module is installed to recovery partition
Recovery *bool
+ // Whether this module is built for non-native architecures (also known as native bridge binary)
+ Native_bridge_supported *bool `android:"arch_variant"`
+
// init.rc files to be installed if this module is installed
Init_rc []string `android:"path"`
@@ -1066,6 +1097,18 @@
}
}
+func (a *androidModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
+ var deps []Module
+ a.VisitDirectDepsBlueprint(func(m blueprint.Module) {
+ if aModule, _ := m.(Module); aModule != nil {
+ if a.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+ deps = append(deps, aModule)
+ }
+ }
+ })
+ return deps
+}
+
func (a *androidModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
m, _ := a.getDirectDepInternal(name, tag)
return m
diff --git a/android/mutator.go b/android/mutator.go
index 5ce743a..45954d3 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -78,6 +78,7 @@
RegisterPrebuiltsPreArchMutators,
RegisterDefaultsPreArchMutators,
RegisterOverridePreArchMutators,
+ registerVisibilityRuleGatherer,
}
func registerArchMutator(ctx RegisterMutatorsContext) {
@@ -92,6 +93,7 @@
var postDeps = []RegisterMutatorFunc{
registerPathDepsMutator,
RegisterPrebuiltsPostDepsMutators,
+ registerVisibilityRuleEnforcer,
registerNeverallowMutator,
}
@@ -118,6 +120,7 @@
Module() Module
OtherModuleName(m blueprint.Module) string
+ OtherModuleDir(m blueprint.Module) string
OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
diff --git a/android/namespace.go b/android/namespace.go
index 50bdcba..78d7f3c 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -26,12 +26,6 @@
"github.com/google/blueprint"
)
-// This file implements namespaces
-const (
- namespacePrefix = "//"
- modulePrefix = ":"
-)
-
func init() {
RegisterModuleType("soong_namespace", NamespaceFactory)
}
@@ -215,11 +209,11 @@
// parses a fully-qualified path (like "//namespace_path:module_name") into a namespace name and a
// module name
func (r *NameResolver) parseFullyQualifiedName(name string) (namespaceName string, moduleName string, ok bool) {
- if !strings.HasPrefix(name, namespacePrefix) {
+ if !strings.HasPrefix(name, "//") {
return "", "", false
}
- name = strings.TrimPrefix(name, namespacePrefix)
- components := strings.Split(name, modulePrefix)
+ name = strings.TrimPrefix(name, "//")
+ components := strings.Split(name, ":")
if len(components) != 2 {
return "", "", false
}
diff --git a/android/neverallow.go b/android/neverallow.go
index fba43b3..9314483 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -97,32 +97,15 @@
"external/wycheproof",
}
- var coreModules = []string{
- "core-all",
- "core-oj",
- "core-libart",
- "okhttp",
- "bouncycastle",
- "conscrypt",
- "apache-xml",
- }
-
- // Core library constraints. Prevent targets adding dependencies on core
- // library internals, which could lead to compatibility issues with the ART
- // mainline module. They should use core.platform.api.stubs instead.
+ // Core library constraints. The no_standard_libs can only be used in core
+ // library projects. Access to core library targets is restricted using
+ // visibility rules.
rules := []*rule{
neverallow().
notIn(append(coreLibraryProjects, "development")...).
with("no_standard_libs", "true"),
}
- for _, m := range coreModules {
- r := neverallow().
- notIn(coreLibraryProjects...).
- with("libs", m).
- because("Only core libraries projects can depend on " + m)
- rules = append(rules, r)
- }
return rules
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index d55ca57..00c51ea 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -138,17 +138,6 @@
expectedError: "",
},
{
- name: "dependency on core-libart",
- fs: map[string][]byte{
- "Blueprints": []byte(`
- java_library {
- name: "needs_core_libart",
- libs: ["core-libart"],
- }`),
- },
- expectedError: "Only core libraries projects can depend on core-libart",
- },
- {
name: "java_device_for_host",
fs: map[string][]byte{
"Blueprints": []byte(`
diff --git a/android/paths.go b/android/paths.go
index 0f20b84..da387a8 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -967,7 +967,7 @@
// PathForVndkRefAbiDump returns an OptionalPath representing the path of the
// reference abi dump for the given module. This is not guaranteed to be valid.
func PathForVndkRefAbiDump(ctx ModuleContext, version, fileName string,
- isLlndk, isGzip bool) OptionalPath {
+ isLlndkOrNdk, isVndk, isGzip bool) OptionalPath {
arches := ctx.DeviceConfig().Arches()
if len(arches) == 0 {
@@ -980,10 +980,12 @@
}
var dirName string
- if isLlndk {
+ if isLlndkOrNdk {
dirName = "ndk"
- } else {
+ } else if isVndk {
dirName = "vndk"
+ } else {
+ dirName = "platform" // opt-in libs
}
binderBitness := ctx.DeviceConfig().BinderBitness()
diff --git a/android/prebuilt.go b/android/prebuilt.go
index df25a89..2556770 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -74,6 +74,10 @@
}
}
+func (p *Prebuilt) UsePrebuilt() bool {
+ return p.properties.UsePrebuilt
+}
+
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
p := module.Prebuilt()
module.AddProperties(&p.properties)
diff --git a/android/variable.go b/android/variable.go
index f3da66d..c500671 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -165,6 +165,16 @@
DeviceSecondaryCpuVariant *string `json:",omitempty"`
DeviceSecondaryAbi []string `json:",omitempty"`
+ NativeBridgeArch *string `json:",omitempty"`
+ NativeBridgeArchVariant *string `json:",omitempty"`
+ NativeBridgeCpuVariant *string `json:",omitempty"`
+ NativeBridgeAbi []string `json:",omitempty"`
+
+ NativeBridgeSecondaryArch *string `json:",omitempty"`
+ NativeBridgeSecondaryArchVariant *string `json:",omitempty"`
+ NativeBridgeSecondaryCpuVariant *string `json:",omitempty"`
+ NativeBridgeSecondaryAbi []string `json:",omitempty"`
+
HostArch *string `json:",omitempty"`
HostSecondaryArch *string `json:",omitempty"`
@@ -267,6 +277,7 @@
BoardOdmSepolicyDirs []string `json:",omitempty"`
BoardPlatPublicSepolicyDirs []string `json:",omitempty"`
BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
+ BoardSepolicyM4Defs []string `json:",omitempty"`
VendorVars map[string]map[string]string `json:",omitempty"`
@@ -288,6 +299,10 @@
ProductHiddenAPIStubsSystem []string `json:",omitempty"`
ProductHiddenAPIStubsTest []string `json:",omitempty"`
+ ProductPublicSepolicyDirs []string `json:",omitempty"`
+ ProductPrivateSepolicyDirs []string `json:",omitempty"`
+ ProductCompatibleProperty *bool `json:",omitempty"`
+
TargetFSConfigGen []string `json:",omitempty"`
}
diff --git a/android/visibility.go b/android/visibility.go
new file mode 100644
index 0000000..36b6f35
--- /dev/null
+++ b/android/visibility.go
@@ -0,0 +1,313 @@
+// Copyright 2019 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 android
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+ "sync"
+)
+
+// Enforces visibility rules between modules.
+//
+// Two stage process:
+// * First stage works bottom up to extract visibility information from the modules, parse it,
+// create visibilityRule structures and store them in a map keyed by the module's
+// qualifiedModuleName instance, i.e. //<pkg>:<name>. The map is stored in the context rather
+// than a global variable for testing. Each test has its own Config so they do not share a map
+// and so can be run in parallel.
+//
+// * Second stage works top down and iterates over all the deps for each module. If the dep is in
+// the same package then it is automatically visible. Otherwise, for each dep it first extracts
+// its visibilityRule from the config map. If one could not be found then it assumes that it is
+// publicly visible. Otherwise, it calls the visibility rule to check that the module can see
+// the dependency. If it cannot then an error is reported.
+//
+// TODO(b/130631145) - Make visibility work properly with prebuilts.
+// TODO(b/130796911) - Make visibility work properly with defaults.
+
+// Patterns for the values that can be specified in visibility property.
+const (
+ packagePattern = `//([^/:]+(?:/[^/:]+)*)`
+ namePattern = `:([^/:]+)`
+ visibilityRulePattern = `^(?:` + packagePattern + `)?(?:` + namePattern + `)?$`
+)
+
+var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern)
+
+// Qualified id for a module
+type qualifiedModuleName struct {
+ // The package (i.e. directory) in which the module is defined, without trailing /
+ pkg string
+
+ // The name of the module.
+ name string
+}
+
+func (q qualifiedModuleName) String() string {
+ return fmt.Sprintf("//%s:%s", q.pkg, q.name)
+}
+
+// A visibility rule is associated with a module and determines which other modules it is visible
+// to, i.e. which other modules can depend on the rule's module.
+type visibilityRule interface {
+ // Check to see whether this rules matches m.
+ // Returns true if it does, false otherwise.
+ matches(m qualifiedModuleName) bool
+
+ String() string
+}
+
+// A compositeRule is a visibility rule composed from other visibility rules.
+// This array will only be [] if all the rules are invalid and will behave as if visibility was
+// ["//visibility:private"].
+type compositeRule []visibilityRule
+
+// A compositeRule matches if and only if any of its rules matches.
+func (c compositeRule) matches(m qualifiedModuleName) bool {
+ for _, r := range c {
+ if r.matches(m) {
+ return true
+ }
+ }
+ return false
+}
+
+func (r compositeRule) String() string {
+ s := make([]string, 0, len(r))
+ for _, r := range r {
+ s = append(s, r.String())
+ }
+
+ return "[" + strings.Join(s, ", ") + "]"
+}
+
+// A packageRule is a visibility rule that matches modules in a specific package (i.e. directory).
+type packageRule struct {
+ pkg string
+}
+
+func (r packageRule) matches(m qualifiedModuleName) bool {
+ return m.pkg == r.pkg
+}
+
+func (r packageRule) String() string {
+ return fmt.Sprintf("//%s:__pkg__", r.pkg)
+}
+
+// A subpackagesRule is a visibility rule that matches modules in a specific package (i.e.
+// directory) or any of its subpackages (i.e. subdirectories).
+type subpackagesRule struct {
+ pkgPrefix string
+}
+
+func (r subpackagesRule) matches(m qualifiedModuleName) bool {
+ return isAncestor(r.pkgPrefix, m.pkg)
+}
+
+func isAncestor(p1 string, p2 string) bool {
+ return strings.HasPrefix(p2+"/", p1+"/")
+}
+
+func (r subpackagesRule) String() string {
+ return fmt.Sprintf("//%s:__subpackages__", r.pkgPrefix)
+}
+
+var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
+
+// The map from qualifiedModuleName to visibilityRule.
+func moduleToVisibilityRuleMap(ctx BaseModuleContext) *sync.Map {
+ return ctx.Config().Once(visibilityRuleMap, func() interface{} {
+ return &sync.Map{}
+ }).(*sync.Map)
+}
+
+// Visibility is not dependent on arch so this must be registered before the arch phase to avoid
+// having to process multiple variants for each module.
+func registerVisibilityRuleGatherer(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer).Parallel()
+}
+
+// This must be registered after the deps have been resolved.
+func registerVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
+ ctx.TopDown("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
+}
+
+// Gathers the visibility rules, parses the visibility properties, stores them in a map by
+// qualifiedModuleName for retrieval during enforcement.
+//
+// See ../README.md#Visibility for information on the format of the visibility rules.
+
+func visibilityRuleGatherer(ctx BottomUpMutatorContext) {
+ m, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+
+ qualified := createQualifiedModuleName(ctx)
+
+ visibility := m.base().commonProperties.Visibility
+ if visibility != nil {
+ rule := parseRules(ctx, qualified.pkg, visibility)
+ if rule != nil {
+ moduleToVisibilityRuleMap(ctx).Store(qualified, rule)
+ }
+ }
+}
+
+func parseRules(ctx BottomUpMutatorContext, currentPkg string, visibility []string) compositeRule {
+ ruleCount := len(visibility)
+ if ruleCount == 0 {
+ // This prohibits an empty list as its meaning is unclear, e.g. it could mean no visibility and
+ // it could mean public visibility. Requiring at least one rule makes the owner's intent
+ // clearer.
+ ctx.PropertyErrorf("visibility", "must contain at least one visibility rule")
+ return nil
+ }
+
+ rules := make(compositeRule, 0, ruleCount)
+ for _, v := range visibility {
+ ok, pkg, name := splitRule(ctx, v, currentPkg)
+ if !ok {
+ // Visibility rule is invalid so ignore it. Keep going rather than aborting straight away to
+ // ensure all the rules on this module are checked.
+ ctx.PropertyErrorf("visibility",
+ "invalid visibility pattern %q must match"+
+ " //<package>:<module>, //<package> or :<module>",
+ v)
+ continue
+ }
+
+ if pkg == "visibility" {
+ if ruleCount != 1 {
+ ctx.PropertyErrorf("visibility", "cannot mix %q with any other visibility rules", v)
+ continue
+ }
+ switch name {
+ case "private":
+ rules = append(rules, packageRule{currentPkg})
+ continue
+ case "public":
+ return nil
+ case "legacy_public":
+ ctx.PropertyErrorf("visibility", "//visibility:legacy_public must not be used")
+ return nil
+ default:
+ ctx.PropertyErrorf("visibility", "unrecognized visibility rule %q", v)
+ continue
+ }
+ }
+
+ // If the current directory is not in the vendor tree then there are some additional
+ // restrictions on the rules.
+ if !isAncestor("vendor", currentPkg) {
+ if !isAllowedFromOutsideVendor(pkg, name) {
+ ctx.PropertyErrorf("visibility",
+ "%q is not allowed. Packages outside //vendor cannot make themselves visible to specific"+
+ " targets within //vendor, they can only use //vendor:__subpackages__.", v)
+ continue
+ }
+ }
+
+ // Create the rule
+ var r visibilityRule
+ switch name {
+ case "__pkg__":
+ r = packageRule{pkg}
+ case "__subpackages__":
+ r = subpackagesRule{pkg}
+ default:
+ ctx.PropertyErrorf("visibility", "unrecognized visibility rule %q", v)
+ continue
+ }
+
+ rules = append(rules, r)
+ }
+
+ return rules
+}
+
+func isAllowedFromOutsideVendor(pkg string, name string) bool {
+ if pkg == "vendor" {
+ if name == "__subpackages__" {
+ return true
+ }
+ return false
+ }
+
+ return !isAncestor("vendor", pkg)
+}
+
+func splitRule(ctx BaseModuleContext, ruleExpression string, currentPkg string) (bool, string, string) {
+ // Make sure that the rule is of the correct format.
+ matches := visibilityRuleRegexp.FindStringSubmatch(ruleExpression)
+ if ruleExpression == "" || matches == nil {
+ return false, "", ""
+ }
+
+ // Extract the package and name.
+ pkg := matches[1]
+ name := matches[2]
+
+ // Normalize the short hands
+ if pkg == "" {
+ pkg = currentPkg
+ }
+ if name == "" {
+ name = "__pkg__"
+ }
+
+ return true, pkg, name
+}
+
+func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
+ _, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+
+ qualified := createQualifiedModuleName(ctx)
+
+ moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
+
+ // Visit all the dependencies making sure that this module has access to them all.
+ ctx.VisitDirectDeps(func(dep Module) {
+ depName := ctx.OtherModuleName(dep)
+ depDir := ctx.OtherModuleDir(dep)
+ depQualified := qualifiedModuleName{depDir, depName}
+
+ // Targets are always visible to other targets in their own package.
+ if depQualified.pkg == qualified.pkg {
+ return
+ }
+
+ rule, ok := moduleToVisibilityRule.Load(depQualified)
+ if ok {
+ if !rule.(compositeRule).matches(qualified) {
+ ctx.ModuleErrorf(
+ "depends on %s which is not visible to this module; %s is only visible to %s",
+ depQualified, depQualified, rule)
+ }
+ }
+ })
+}
+
+func createQualifiedModuleName(ctx BaseModuleContext) qualifiedModuleName {
+ moduleName := ctx.ModuleName()
+ dir := ctx.ModuleDir()
+ qualified := qualifiedModuleName{dir, moduleName}
+ return qualified
+}
diff --git a/android/visibility_test.go b/android/visibility_test.go
new file mode 100644
index 0000000..6809914
--- /dev/null
+++ b/android/visibility_test.go
@@ -0,0 +1,474 @@
+package android
+
+import (
+ "github.com/google/blueprint"
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+var visibilityTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+}{
+ {
+ name: "invalid visibility: empty list",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: [],
+ }`),
+ },
+ expectedErrors: []string{`visibility: must contain at least one visibility rule`},
+ },
+ {
+ name: "invalid visibility: empty rule",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: [""],
+ }`),
+ },
+ expectedErrors: []string{`visibility: invalid visibility pattern ""`},
+ },
+ {
+ name: "invalid visibility: unqualified",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["target"],
+ }`),
+ },
+ expectedErrors: []string{`visibility: invalid visibility pattern "target"`},
+ },
+ {
+ name: "invalid visibility: empty namespace",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//"],
+ }`),
+ },
+ expectedErrors: []string{`visibility: invalid visibility pattern "//"`},
+ },
+ {
+ name: "invalid visibility: empty module",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: [":"],
+ }`),
+ },
+ expectedErrors: []string{`visibility: invalid visibility pattern ":"`},
+ },
+ {
+ name: "invalid visibility: empty namespace and module",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//:"],
+ }`),
+ },
+ expectedErrors: []string{`visibility: invalid visibility pattern "//:"`},
+ },
+ {
+ name: "//visibility:unknown",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:unknown"],
+ }`),
+ },
+ expectedErrors: []string{`unrecognized visibility rule "//visibility:unknown"`},
+ },
+ {
+ name: "//visibility:public mixed",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:public", "//namespace"],
+ }
+
+ mock_library {
+ name: "libother",
+ visibility: ["//visibility:private", "//namespace"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libother" variant "android_common": visibility: cannot mix "//visibility:private"` +
+ ` with any other visibility rules`,
+ `module "libexample" variant "android_common": visibility: cannot mix` +
+ ` "//visibility:public" with any other visibility rules`,
+ },
+ },
+ {
+ name: "//visibility:legacy_public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:legacy_public"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libexample" variant "android_common": visibility: //visibility:legacy_public must` +
+ ` not be used`,
+ },
+ },
+ {
+ // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g.
+ // the current directory, a nested directory and a directory in a separate tree.
+ name: "//visibility:public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:public"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ },
+ {
+ // Verify that //visibility:public will allow the module to be referenced from anywhere, e.g.
+ // the current directory, a nested directory and a directory in a separate tree.
+ name: "//visibility:public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:public"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ },
+ {
+ // Verify that //visibility:private allows the module to be referenced from the current
+ // directory only.
+ name: "//visibility:private",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:private"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libnested" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+ },
+ },
+ {
+ // Verify that :__pkg__ allows the module to be referenced from the current directory only.
+ name: ":__pkg__",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: [":__pkg__"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libnested" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top:__pkg__\]`,
+ },
+ },
+ {
+ // Verify that //top/nested allows the module to be referenced from the current directory and
+ // the top/nested directory only, not a subdirectory of top/nested and not peak directory.
+ name: "//top/nested",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//top/nested"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "top/nested/again/Blueprints": []byte(`
+ mock_library {
+ name: "libnestedagain",
+ deps: ["libexample"],
+ }`),
+ "peak/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libother" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top/nested:__pkg__\]`,
+ `module "libnestedagain" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top/nested:__pkg__\]`,
+ },
+ },
+ {
+ // Verify that :__subpackages__ allows the module to be referenced from the current directory
+ // and sub directories but nowhere else.
+ name: ":__subpackages__",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: [":__subpackages__"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "peak/other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libother" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to \[//top:__subpackages__\]`,
+ },
+ },
+ {
+ // Verify that //top/nested:__subpackages__ allows the module to be referenced from the current
+ // directory and sub directories but nowhere else.
+ name: "//top/nested:__subpackages__",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//top/nested:__subpackages__", "//other"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "top/other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libother" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module; //top:libexample is only visible to` +
+ ` \[//top/nested:__subpackages__, //other:__pkg__\]`,
+ },
+ },
+ {
+ // Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from
+ // the current directory, top/nested and peak and all its subpackages.
+ name: `["//top/nested", "//peak:__subpackages__"]`,
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//top/nested", "//peak:__subpackages__"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "peak/other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ },
+ {
+ // Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__
+ name: `//vendor`,
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//vendor:__subpackages__"],
+ }
+
+ mock_library {
+ name: "libsamepackage",
+ visibility: ["//vendor/apps/AcmeSettings"],
+ }`),
+ "vendor/Blueprints": []byte(`
+ mock_library {
+ name: "libvendorexample",
+ deps: ["libexample"],
+ visibility: ["//vendor/nested"],
+ }`),
+ "vendor/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libvendornested",
+ deps: ["libexample", "libvendorexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libsamepackage" variant "android_common": visibility: "//vendor/apps/AcmeSettings"` +
+ ` is not allowed. Packages outside //vendor cannot make themselves visible to specific` +
+ ` targets within //vendor, they can only use //vendor:__subpackages__.`,
+ },
+ },
+}
+
+func TestVisibility(t *testing.T) {
+ buildDir, err := ioutil.TempDir("", "soong_neverallow_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(buildDir)
+
+ for _, test := range visibilityTests {
+ t.Run(test.name, func(t *testing.T) {
+ _, errs := testVisibility(buildDir, test.fs)
+
+ expectedErrors := test.expectedErrors
+ if expectedErrors == nil {
+ FailIfErrored(t, errs)
+ } else {
+ for _, expectedError := range expectedErrors {
+ FailIfNoMatchingErrors(t, expectedError, errs)
+ }
+ if len(errs) > len(expectedErrors) {
+ t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
+ for i, expectedError := range expectedErrors {
+ t.Errorf("expectedErrors[%d] = %s", i, expectedError)
+ }
+ for i, err := range errs {
+ t.Errorf("errs[%d] = %s", i, err)
+ }
+ }
+ }
+ })
+ }
+}
+
+func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) {
+
+ // Create a new config per test as visibility information is stored in the config.
+ config := TestArchConfig(buildDir, nil)
+
+ ctx := NewTestArchContext()
+ ctx.RegisterModuleType("mock_library", ModuleFactoryAdaptor(newMockLibraryModule))
+ ctx.PreDepsMutators(registerVisibilityRuleGatherer)
+ ctx.PostDepsMutators(registerVisibilityRuleEnforcer)
+ ctx.Register()
+
+ ctx.MockFileSystem(fs)
+
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}
+
+type mockLibraryProperties struct {
+ Deps []string
+}
+
+type mockLibraryModule struct {
+ ModuleBase
+ properties mockLibraryProperties
+}
+
+func newMockLibraryModule() Module {
+ m := &mockLibraryModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+ return m
+}
+
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+func (j *mockLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
+}
+
+func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/apex/apex.go b/apex/apex.go
index 509e0f2..68d0bc1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1184,8 +1184,11 @@
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
} else if fi.class == nativeSharedLib || fi.class == nativeExecutable {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
- if cc, ok := fi.module.(*cc.Module); ok && cc.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
+ if cc, ok := fi.module.(*cc.Module); ok {
+ if cc.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
+ }
+ cc.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
} else {
@@ -1373,11 +1376,15 @@
return android.Paths{p.outputApex}
}
+func (p *Prebuilt) InstallFilename() string {
+ return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix)
+}
+
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// TODO(jungjw): Check the key validity.
p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
p.installDir = android.PathForModuleInstall(ctx, "apex")
- p.installFilename = proptools.StringDefault(p.properties.Filename, ctx.ModuleName()+imageApexSuffix)
+ p.installFilename = p.InstallFilename()
if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index b0cd4be..5276ce4 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -93,6 +93,13 @@
}
toolchain_library {
+ name: "libgcc_stripped",
+ src: "",
+ vendor_available: true,
+ recovery_available: true,
+ }
+
+ toolchain_library {
name: "libclang_rt.builtins-aarch64-android",
src: "",
vendor_available: true,
diff --git a/apex/key.go b/apex/key.go
index 229d593..08cd45e 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "sort"
"strings"
"android/soong/android"
@@ -105,12 +106,31 @@
func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
s.output = android.PathForOutput(ctx, "apexkeys.txt")
- var filecontent strings.Builder
+ apexModulesMap := make(map[string]android.Module)
ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(android.Module); ok && !m.Enabled() {
- return
+ if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
+ apexModulesMap[m.Name()] = m
}
+ })
+ // Find prebuilts and let them override apexBundle if they are preferred
+ ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
+ m.Prebuilt().UsePrebuilt() {
+ apexModulesMap[m.BaseModuleName()] = m
+ }
+ })
+
+ // iterating over map does not give consistent ordering in golang
+ var moduleNames []string
+ for key, _ := range apexModulesMap {
+ moduleNames = append(moduleNames, key)
+ }
+ sort.Strings(moduleNames)
+
+ var filecontent strings.Builder
+ for _, key := range moduleNames {
+ module := apexModulesMap[key]
if m, ok := module.(*apexBundle); ok {
fmt.Fprintf(&filecontent,
"name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n",
@@ -119,8 +139,14 @@
m.private_key_file.String(),
m.container_certificate_file.String(),
m.container_private_key_file.String())
+ } else if m, ok := module.(*Prebuilt); ok {
+ fmt.Fprintf(&filecontent,
+ "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n",
+ m.InstallFilename(),
+ "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED")
}
- })
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: android.WriteFile,
Description: "apexkeys.txt",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 02806f9..79469ee 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -145,6 +145,16 @@
}
}
+func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
+ if library.sAbiOutputFile.Valid() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", library.sAbiOutputFile.String())
+ if library.sAbiDiff.Valid() && !library.static() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", library.sAbiDiff.String())
+ fmt.Fprintln(w, "HEADER_ABI_DIFFS +=", library.sAbiDiff.String())
+ }
+ }
+}
+
func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
if library.static() {
ret.Class = "STATIC_LIBRARIES"
@@ -169,14 +179,7 @@
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 := ")
- if library.sAbiOutputFile.Valid() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES += ", library.sAbiOutputFile.String())
- if library.sAbiDiff.Valid() && !library.static() {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES += ", library.sAbiDiff.String())
- fmt.Fprintln(w, "HEADER_ABI_DIFFS += ", library.sAbiDiff.String())
- }
- }
+ library.androidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
_, _, ext := splitFileExt(outputFile.Base())
diff --git a/cc/builder.go b/cc/builder.go
index 7b26d51..c99e461 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -255,6 +255,7 @@
groupStaticLibs bool
stripKeepSymbols bool
+ stripKeepSymbolsList string
stripKeepMiniDebugInfo bool
stripAddGnuDebuglink bool
stripUseGnuStrip bool
@@ -835,6 +836,9 @@
if flags.stripKeepSymbols {
args += " --keep-symbols"
}
+ if flags.stripKeepSymbolsList != "" {
+ args += " -k" + flags.stripKeepSymbolsList
+ }
if flags.stripUseGnuStrip {
args += " --use-gnu-strip"
}
diff --git a/cc/cc.go b/cc/cc.go
index bec39ca..bb24942 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -19,6 +19,7 @@
// is handled in builder.go
import (
+ "io"
"strconv"
"strings"
@@ -1803,6 +1804,8 @@
return libName + vendorPublicLibrarySuffix
} else if ccDep.inRecovery() && !ccDep.onlyInRecovery() {
return libName + recoverySuffix
+ } else if ccDep.Target().NativeBridge == android.NativeBridgeEnabled {
+ return libName + android.NativeBridgeSuffix
} else {
return libName
}
@@ -1966,6 +1969,14 @@
dpInfo.Srcs = append(dpInfo.Srcs, c.Srcs().Strings()...)
}
+func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
+ if c.linker != nil {
+ if library, ok := c.linker.(*libraryDecorator); ok {
+ library.androidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ }
+ }
+}
+
//
// Defaults
//
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 05d74b9..f3d5e60 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1833,13 +1833,13 @@
// Check the shared version of lib2.
variant := "android_arm64_armv8-a_core_shared"
module := ctx.ModuleForTests("lib2", variant).Module().(*Module)
- checkStaticLibs(t, []string{"lib1", "libclang_rt.builtins-aarch64-android", "libatomic", "libgcc"}, module)
+ checkStaticLibs(t, []string{"lib1", "libclang_rt.builtins-aarch64-android", "libatomic", "libgcc_stripped"}, module)
// Check the static version of lib2.
variant = "android_arm64_armv8-a_core_static"
module = ctx.ModuleForTests("lib2", variant).Module().(*Module)
// libc++_static is linked additionally.
- checkStaticLibs(t, []string{"lib1", "libc++_static", "libclang_rt.builtins-aarch64-android", "libatomic", "libgcc"}, module)
+ checkStaticLibs(t, []string{"lib1", "libc++_static", "libclang_rt.builtins-aarch64-android", "libatomic", "libgcc_stripped"}, module)
}
var compilerFlagsTestCases = []struct {
diff --git a/cc/installer.go b/cc/installer.go
index bd8f9e7..cb261b7 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -66,7 +66,7 @@
if ctx.toolchain().Is64Bit() && installer.dir64 != "" {
dir = installer.dir64
}
- if !ctx.Host() && !ctx.Arch().Native {
+ if (!ctx.Host() && !ctx.Arch().Native) || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
if installer.location == InstallInData && ctx.useVndk() {
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index 82a779c..c1da578 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -32,6 +32,11 @@
return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs)
}
+// kernel_headers retrieves the list of kernel headers directories from
+// TARGET_BOARD_KERNEL_HEADERS and TARGET_PRODUCT_KERNEL_HEADERS variables in
+// a makefile for compilation. See
+// https://android.googlesource.com/platform/build/+/master/core/config.mk
+// for more details on them.
func kernelHeadersFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
library.HeaderOnly()
diff --git a/cc/library.go b/cc/library.go
index 13972cc..1f79bec 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -15,6 +15,7 @@
package cc
import (
+ "io"
"path/filepath"
"regexp"
"sort"
@@ -96,6 +97,9 @@
// Properties for ABI compatibility checker
Header_abi_checker struct {
+ // Enable ABI checks (even if this is not an LLNDK/VNDK lib)
+ Enabled *bool
+
// Path to a symbol file that specifies the symbols to be included in the generated
// ABI dump file
Symbol_file *string `android:"path"`
@@ -421,6 +425,13 @@
return exportedIncludes
}
+func (library *libraryDecorator) shouldCreateVndkSourceAbiDump(ctx ModuleContext) bool {
+ if library.Properties.Header_abi_checker.Enabled != nil {
+ return Bool(library.Properties.Header_abi_checker.Enabled)
+ }
+ return ctx.shouldCreateVndkSourceAbiDump()
+}
+
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if library.buildStubs() {
objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
@@ -440,7 +451,7 @@
}
return Objects{}
}
- if ctx.shouldCreateVndkSourceAbiDump() || library.sabi.Properties.CreateSAbiDumps {
+ if library.shouldCreateVndkSourceAbiDump(ctx) || library.sabi.Properties.CreateSAbiDumps {
exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
var SourceAbiFlags []string
for _, dir := range exportIncludeDirs.Strings() {
@@ -487,6 +498,9 @@
// Sets whether a specific variant is static or shared
setStatic()
setShared()
+
+ // Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
+ androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
}
func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
@@ -769,10 +783,10 @@
}
func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
- isLlndk := inList(ctx.baseModuleName(), llndkLibraries) || inList(ctx.baseModuleName(), ndkMigratedLibs)
+ isLlndkOrNdk := inList(ctx.baseModuleName(), llndkLibraries) || inList(ctx.baseModuleName(), ndkMigratedLibs)
- refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isLlndk, false)
- refAbiDumpGzipFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isLlndk, true)
+ refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isLlndkOrNdk, ctx.isVndk(), false)
+ refAbiDumpGzipFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isLlndkOrNdk, ctx.isVndk(), true)
if refAbiDumpTextFile.Valid() {
if refAbiDumpGzipFile.Valid() {
@@ -790,7 +804,7 @@
}
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
- if len(objs.sAbiDumpFiles) > 0 && ctx.shouldCreateVndkSourceAbiDump() {
+ if len(objs.sAbiDumpFiles) > 0 && library.shouldCreateVndkSourceAbiDump(ctx) {
vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
if ver := ctx.DeviceConfig().VndkVersion(); ver != "" && ver != "current" {
vndkVersion = ver
diff --git a/cc/linker.go b/cc/linker.go
index e724df6..986a562 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -228,10 +228,10 @@
// libclang_rt.builtins, libgcc and libatomic have to be last on the command line
if !Bool(linker.Properties.No_libcrt) {
deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
- }
-
- deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
- if !Bool(linker.Properties.No_libgcc) {
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc_stripped")
+ } else if !Bool(linker.Properties.No_libgcc) {
+ deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic")
deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
}
diff --git a/cc/strip.go b/cc/strip.go
index 02397f4..7122585 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -15,15 +15,19 @@
package cc
import (
+ "strings"
+
"android/soong/android"
)
type StripProperties struct {
Strip struct {
- None *bool
- All *bool
- Keep_symbols *bool
- }
+ None *bool `android:"arch_variant"`
+ All *bool `android:"arch_variant"`
+ Keep_symbols *bool `android:"arch_variant"`
+ Keep_symbols_list []string `android:"arch_variant"`
+ Use_gnu_strip *bool `android:"arch_variant"`
+ } `android:"arch_variant"`
}
type stripper struct {
@@ -42,9 +46,14 @@
} else {
if Bool(stripper.StripProperties.Strip.Keep_symbols) {
flags.stripKeepSymbols = true
+ } else if len(stripper.StripProperties.Strip.Keep_symbols_list) > 0 {
+ flags.stripKeepSymbolsList = strings.Join(stripper.StripProperties.Strip.Keep_symbols_list, ",")
} else if !Bool(stripper.StripProperties.Strip.All) {
flags.stripKeepMiniDebugInfo = true
}
+ if Bool(stripper.StripProperties.Strip.Use_gnu_strip) {
+ flags.stripUseGnuStrip = true
+ }
if ctx.Config().Debuggable() && !flags.stripKeepMiniDebugInfo {
flags.stripAddGnuDebuglink = true
}
diff --git a/cc/testing.go b/cc/testing.go
index 2f41de1..8d76c2f 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -69,6 +69,13 @@
src: "",
}
+ toolchain_library {
+ name: "libgcc_stripped",
+ vendor_available: true,
+ recovery_available: true,
+ src: "",
+ }
+
cc_library {
name: "libc",
no_libgcc: true,
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 6494a26..b4c51ab 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -34,6 +34,8 @@
type toolchainLibraryDecorator struct {
*libraryDecorator
+ stripper
+
Properties toolchainLibraryProperties
}
@@ -45,7 +47,7 @@
func (library *toolchainLibraryDecorator) linkerProps() []interface{} {
var props []interface{}
props = append(props, library.libraryDecorator.linkerProps()...)
- return append(props, &library.Properties)
+ return append(props, &library.Properties, &library.stripper.StripProperties)
}
// toolchain_library is used internally by the build tool to link the specified
@@ -78,7 +80,17 @@
return android.PathForSource(ctx, "")
}
- return android.PathForSource(ctx, *library.Properties.Src)
+ srcPath := android.PathForSource(ctx, *library.Properties.Src)
+
+ if library.stripper.StripProperties.Strip.Keep_symbols_list != nil {
+ fileName := ctx.ModuleName() + staticLibraryExtension
+ outputFile := android.PathForModuleOut(ctx, fileName)
+ buildFlags := flagsToBuilderFlags(flags)
+ library.stripper.strip(ctx, srcPath, outputFile, buildFlags)
+ return outputFile
+ }
+
+ return srcPath
}
func (library *toolchainLibraryDecorator) nativeCoverage() bool {
diff --git a/cmd/diff_target_files/known_nondeterminism.whitelist b/cmd/diff_target_files/known_nondeterminism.whitelist
index 6d71403..a8ade49 100644
--- a/cmd/diff_target_files/known_nondeterminism.whitelist
+++ b/cmd/diff_target_files/known_nondeterminism.whitelist
@@ -3,8 +3,6 @@
[
{
"Paths": [
- // b/120039850
- "system/framework/oat/*/services.art"
]
}
]
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index f1fa0ff..3b77042 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -59,6 +59,7 @@
NeverAllowStripping bool // whether stripping should not be done - used as build time check to make sure dex files are always available
NoDebugInfo bool // don't generate debug info by default
+ DontResolveStartupStrings bool // don't resolve string literals loaded during application startup.
AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true)
NeverSystemServerDebugInfo bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false)
AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
@@ -301,6 +302,7 @@
GenerateDMFiles: false,
NeverAllowStripping: false,
NoDebugInfo: false,
+ DontResolveStartupStrings: false,
AlwaysSystemServerDebugInfo: false,
NeverSystemServerDebugInfo: false,
AlwaysOtherDebugInfo: false,
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 01ee15e..5b658d9 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -461,6 +461,9 @@
appImageInstallPath := pathtools.ReplaceExtension(odexInstallPath, "art")
cmd.FlagWithOutput("--app-image-file=", appImagePath).
FlagWithArg("--image-format=", "lz4")
+ if !global.DontResolveStartupStrings {
+ cmd.FlagWithArg("--resolve-startup-const-strings=", "true")
+ }
rule.Install(appImagePath, appImageInstallPath)
}
diff --git a/java/OWNERS b/java/OWNERS
index d68a5b0..16ef4d8 100644
--- a/java/OWNERS
+++ b/java/OWNERS
@@ -1 +1 @@
-per-file dexpreopt.go = ngeoffray@google.com,calin@google.com,mathieuc@google.com
+per-file dexpreopt*.go = ngeoffray@google.com,calin@google.com,mathieuc@google.com
diff --git a/java/aar.go b/java/aar.go
index c621276..5e1f88e 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -29,7 +29,7 @@
ExportedProguardFlagFiles() android.Paths
ExportedRRODirs() []rroDir
ExportedStaticPackages() android.Paths
- ExportedManifest() android.Path
+ ExportedManifests() android.Paths
}
func init() {
@@ -71,17 +71,19 @@
}
type aapt struct {
- aaptSrcJar android.Path
- exportPackage android.Path
- manifestPath android.Path
- proguardOptionsFile android.Path
- rroDirs []rroDir
- rTxt android.Path
- extraAaptPackagesFile android.Path
- isLibrary bool
- uncompressedJNI bool
- useEmbeddedDex bool
- usesNonSdkApis bool
+ aaptSrcJar android.Path
+ exportPackage android.Path
+ manifestPath android.Path
+ transitiveManifestPaths android.Paths
+ proguardOptionsFile android.Path
+ rroDirs []rroDir
+ rTxt android.Path
+ extraAaptPackagesFile android.Path
+ mergedManifestFile android.Path
+ isLibrary bool
+ useEmbeddedNativeLibs bool
+ useEmbeddedDex bool
+ usesNonSdkApis bool
splitNames []string
splits []split
@@ -103,8 +105,8 @@
return a.rroDirs
}
-func (a *aapt) ExportedManifest() android.Path {
- return a.manifestPath
+func (a *aapt) ExportedManifests() android.Paths {
+ return a.transitiveManifestPaths
}
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, manifestPath android.Path) (flags []string,
@@ -192,14 +194,28 @@
}
func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
- transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags := aaptLibs(ctx, sdkContext)
+ transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags := aaptLibs(ctx, sdkContext)
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := manifestMerger(ctx, manifestSrcPath, sdkContext, staticLibManifests, a.isLibrary,
- a.uncompressedJNI, a.useEmbeddedDex, a.usesNonSdkApis)
+ manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext,
+ a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex)
+
+ a.transitiveManifestPaths = append(android.Paths{manifestPath}, transitiveStaticLibManifests...)
+
+ if len(transitiveStaticLibManifests) > 0 {
+ a.mergedManifestFile = manifestMerger(ctx, manifestPath, transitiveStaticLibManifests, a.isLibrary)
+ if !a.isLibrary {
+ // Only use the merged manifest for applications. For libraries, the transitive closure of manifests
+ // will be propagated to the final application and merged there. The merged manifest for libraries is
+ // only passed to Make, which can't handle transitive dependencies.
+ manifestPath = a.mergedManifestFile
+ }
+ } else {
+ a.mergedManifestFile = manifestPath
+ }
linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
@@ -286,7 +302,7 @@
}
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, staticLibManifests android.Paths,
+func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
staticRRODirs []rroDir, deps android.Paths, flags []string) {
var sharedLibs android.Paths
@@ -314,7 +330,7 @@
if exportPackage != nil {
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
- staticLibManifests = append(staticLibManifests, aarDep.ExportedManifest())
+ transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
outer:
for _, d := range aarDep.ExportedRRODirs() {
@@ -341,8 +357,9 @@
}
transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
+ transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
- return transitiveStaticLibs, staticLibManifests, staticRRODirs, deps, flags
+ return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags
}
type AndroidLibrary struct {
@@ -498,8 +515,8 @@
return a.exportedStaticPackages
}
-func (a *AARImport) ExportedManifest() android.Path {
- return a.manifest
+func (a *AARImport) ExportedManifests() android.Paths {
+ return android.Paths{a.manifest}
}
func (a *AARImport) Prebuilt() *android.Prebuilt {
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 8dc3b47..7b378cd 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -36,13 +36,14 @@
var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
blueprint.RuleParams{
- Command: `${config.ManifestMergerCmd} --main $in $libs --out $out`,
+ Command: `${config.ManifestMergerCmd} $args --main $in $libs --out $out`,
CommandDeps: []string{"${config.ManifestMergerCmd}"},
},
- "libs")
+ "args", "libs")
-func manifestMerger(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
- staticLibManifests android.Paths, isLibrary, uncompressedJNI, useEmbeddedDex, usesNonSdkApis bool) android.Path {
+// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
+func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
+ isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex bool) android.Path {
var args []string
if isLibrary {
@@ -53,8 +54,8 @@
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
if minSdkVersion >= 23 {
- args = append(args, fmt.Sprintf("--extract-native-libs=%v", !uncompressedJNI))
- } else if uncompressedJNI {
+ args = append(args, fmt.Sprintf("--extract-native-libs=%v", !useEmbeddedNativeLibs))
+ } else if useEmbeddedNativeLibs {
ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
minSdkVersion)
}
@@ -79,35 +80,44 @@
deps = append(deps, apiFingerprint)
}
- // Inject minSdkVersion into the manifest
fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
ctx.Build(pctx, android.BuildParams{
- Rule: manifestFixerRule,
- Input: manifest,
- Implicits: deps,
- Output: fixedManifest,
+ Rule: manifestFixerRule,
+ Description: "fix manifest",
+ Input: manifest,
+ Implicits: deps,
+ Output: fixedManifest,
Args: map[string]string{
"minSdkVersion": sdkVersionOrDefault(ctx, sdkContext.minSdkVersion()),
"targetSdkVersion": targetSdkVersion,
"args": strings.Join(args, " "),
},
})
- manifest = fixedManifest
- // Merge static aar dependency manifests if necessary
- if len(staticLibManifests) > 0 {
- mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
- ctx.Build(pctx, android.BuildParams{
- Rule: manifestMergerRule,
- Input: manifest,
- Implicits: staticLibManifests,
- Output: mergedManifest,
- Args: map[string]string{
- "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "),
- },
- })
- manifest = mergedManifest
+ return fixedManifest
+}
+
+func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths,
+ isLibrary bool) android.Path {
+
+ var args string
+ if !isLibrary {
+ // Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests.
+ args = "--remove-tools-declarations"
}
- return manifest
+ mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: manifestMergerRule,
+ Description: "merge manifest",
+ Input: manifest,
+ Implicits: staticLibManifests,
+ Output: mergedManifest,
+ Args: map[string]string{
+ "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "),
+ "args": args,
+ },
+ })
+
+ return mergedManifest
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 304b1c4..5491b3e 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -47,6 +47,9 @@
if len(data.Target_required) > 0 {
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(data.Target_required, " "))
}
+ if r := library.deviceProperties.Target.Hostdex.Required; len(r) > 0 {
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(r, " "))
+ }
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
}
}
@@ -91,6 +94,10 @@
fmt.Fprintln(w, "LOCAL_ADDITIONAL_CHECKED_MODULE +=", strings.Join(library.additionalCheckedModules.Strings(), " "))
}
+ if library.proguardDictionary != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", library.proguardDictionary.String())
+ }
+
// Temporary hack: export sources used to compile framework.jar to Make
// to be used for droiddoc
// TODO(ccross): remove this once droiddoc is in soong
@@ -373,9 +380,6 @@
if a.aarFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_AAR :=", a.aarFile.String())
}
- if a.proguardDictionary != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", a.proguardDictionary.String())
- }
if a.Name() == "framework-res" {
fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
@@ -386,7 +390,7 @@
fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", a.exportPackage.String())
fmt.Fprintln(w, "LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=", a.extraAaptPackagesFile.String())
- fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", a.manifestPath.String())
+ fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", a.mergedManifestFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=",
strings.Join(a.exportedProguardFlagFiles.Strings(), " "))
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
@@ -586,6 +590,32 @@
}
}
+func (app *AndroidAppImport) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Class: "APPS",
+ OutputFile: android.OptionalPathForPath(app.outputFile),
+ Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
+ Extra: []android.AndroidMkExtraFunc{
+ func(w io.Writer, outputFile android.Path) {
+ if Bool(app.properties.Privileged) {
+ fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
+ }
+ if app.certificate != nil {
+ fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String())
+ } else {
+ fmt.Fprintln(w, "LOCAL_CERTIFICATE := PRESIGNED")
+ }
+ if len(app.properties.Overrides) > 0 {
+ fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES :=", strings.Join(app.properties.Overrides, " "))
+ }
+ if len(app.dexpreopter.builtInstalled) > 0 {
+ fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", app.dexpreopter.builtInstalled)
+ }
+ },
+ },
+ }
+}
+
func androidMkWriteTestData(data android.Paths, ret *android.AndroidMkData) {
var testFiles []string
for _, d := range data {
diff --git a/java/app.go b/java/app.go
index da8024f..4f0b7ac 100644
--- a/java/app.go
+++ b/java/app.go
@@ -34,6 +34,7 @@
android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
+ android.RegisterModuleType("android_app_import", AndroidAppImportFactory)
}
// AndroidManifest.xml merging
@@ -161,14 +162,14 @@
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.aapt.uncompressedJNI = a.shouldUncompressJNI(ctx)
+ a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
a.generateAndroidBuildActions(ctx)
}
-// shouldUncompressJNI returns true if the native libraries should be stored in the APK uncompressed and the
+// Returns true if the native libraries should be stored in the APK uncompressed and the
// extractNativeLibs application flag should be set to false in the manifest.
-func (a *AndroidApp) shouldUncompressJNI(ctx android.ModuleContext) bool {
+func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
minSdkVersion, err := sdkVersionToNumber(ctx, a.minSdkVersion())
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
@@ -294,7 +295,7 @@
a.appProperties.AlwaysPackageNativeLibs
if embedJni {
jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
- TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.shouldUncompressJNI(ctx))
+ TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx))
} else {
a.installJniLibs = jniLibs
}
@@ -302,37 +303,38 @@
return jniJarFile
}
-func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx android.ModuleContext) []Certificate {
- cert := a.getCertString(ctx)
- certModule := android.SrcIsModule(cert)
- if certModule != "" {
- a.certificate = certificateDeps[0]
- certificateDeps = certificateDeps[1:]
- } else if cert != "" {
- defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
- a.certificate = Certificate{
- defaultDir.Join(ctx, cert+".x509.pem"),
- defaultDir.Join(ctx, cert+".pk8"),
+// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
+// isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
+func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate {
+ if android.SrcIsModule(certPropValue) == "" {
+ var mainCert Certificate
+ if certPropValue != "" {
+ defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
+ mainCert = Certificate{
+ defaultDir.Join(ctx, certPropValue+".x509.pem"),
+ defaultDir.Join(ctx, certPropValue+".pk8"),
+ }
+ } else {
+ pem, key := ctx.Config().DefaultAppCertificate(ctx)
+ mainCert = Certificate{pem, key}
}
- } else {
- pem, key := ctx.Config().DefaultAppCertificate(ctx)
- a.certificate = Certificate{pem, key}
+ certificates = append([]Certificate{mainCert}, certificates...)
}
- if !a.Module.Platform() {
- certPath := a.certificate.Pem.String()
+ if !m.Platform() {
+ certPath := certificates[0].Pem.String()
systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
if strings.HasPrefix(certPath, systemCertPath) {
enforceSystemCert := ctx.Config().EnforceSystemCertificate()
whitelist := ctx.Config().EnforceSystemCertificateWhitelist()
- if enforceSystemCert && !inList(a.Module.Name(), whitelist) {
+ if enforceSystemCert && !inList(m.Name(), whitelist) {
ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
}
}
}
- return append([]Certificate{a.certificate}, certificateDeps...)
+ return certificates
}
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
@@ -346,25 +348,26 @@
dexJarFile := a.dexBuildActions(ctx)
- jniLibs, certificateDeps := a.collectAppDeps(ctx)
+ jniLibs, certificateDeps := collectAppDeps(ctx)
jniJarFile := a.jniBuildActions(jniLibs, ctx)
if ctx.Failed() {
return
}
- certificates := a.certificateBuildActions(certificateDeps, ctx)
+ certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx)
+ a.certificate = certificates[0]
// Build a final signed app package.
// TODO(jungjw): Consider changing this to installApkName.
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
- CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
+ CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
a.outputFile = packageFile
for _, split := range a.aapt.splits {
// Sign the split APKs
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
- CreateAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
}
@@ -390,7 +393,7 @@
}
}
-func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
+func collectAppDeps(ctx android.ModuleContext) ([]jniLib, []Certificate) {
var jniLibs []jniLib
var certificates []Certificate
@@ -412,7 +415,6 @@
}
} else {
ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
-
}
} else if tag == certificateTag {
if dep, ok := module.(*AndroidAppCertificate); ok {
@@ -487,6 +489,8 @@
a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
}
}
+ a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
+ a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
a.generateAndroidBuildActions(ctx)
a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
@@ -620,3 +624,135 @@
android.InitOverrideModule(m)
return m
}
+
+type AndroidAppImport struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ prebuilt android.Prebuilt
+
+ properties AndroidAppImportProperties
+
+ outputFile android.Path
+ certificate *Certificate
+
+ dexpreopter
+}
+
+type AndroidAppImportProperties struct {
+ // A prebuilt apk to import
+ Apk 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
+
+ // Set this flag to true if the prebuilt apk is already signed. The certificate property must not
+ // be set for presigned modules.
+ Presigned *bool
+
+ // Specifies that this app should be installed to the priv-app directory,
+ // where the system will grant it additional privileges not available to
+ // normal apps.
+ Privileged *bool
+
+ // Names of modules to be overridden. Listed modules can only be other binaries
+ // (in Make or Soong).
+ // This does not completely prevent installation of the overridden binaries, but if both
+ // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+ // from PRODUCT_PACKAGES.
+ Overrides []string
+}
+
+func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+ cert := android.SrcIsModule(String(a.properties.Certificate))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
+}
+
+func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
+ ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
+ rule := android.NewRuleBuilder()
+ rule.Command().
+ Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
+ Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+ FlagWithInput("-i ", inputPath).
+ FlagWithOutput("-o ", outputPath).
+ FlagWithArg("-0 ", "'lib/**/*.so'").
+ Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
+ rule.Build(pctx, ctx, "uncompress-embedded-jni-libs", "Uncompress embedded JIN libs")
+}
+
+func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if String(a.properties.Certificate) == "" && !Bool(a.properties.Presigned) {
+ ctx.PropertyErrorf("certificate", "No certificate specified for prebuilt")
+ }
+ if String(a.properties.Certificate) != "" && Bool(a.properties.Presigned) {
+ ctx.PropertyErrorf("certificate", "Certificate can't be specified for presigned modules")
+ }
+
+ _, certificates := collectAppDeps(ctx)
+
+ // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
+ // TODO: LOCAL_DPI_VARIANTS
+ // TODO: LOCAL_PACKAGE_SPLITS
+
+ srcApk := a.prebuilt.SingleSourcePath(ctx)
+
+ // TODO: Install or embed JNI libraries
+
+ // Uncompress JNI libraries in the apk
+ jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
+ a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
+
+ // TODO: Uncompress dex if applicable
+
+ installDir := android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
+ a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
+ a.dexpreopter.isInstallable = true
+ a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
+ dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+
+ // Sign or align the package
+ // TODO: Handle EXTERNAL
+ if !Bool(a.properties.Presigned) {
+ certificates = processMainCert(a.ModuleBase, *a.properties.Certificate, certificates, ctx)
+ if len(certificates) != 1 {
+ ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
+ }
+ a.certificate = &certificates[0]
+ signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
+ SignAppPackage(ctx, signed, dexOutput, certificates)
+ a.outputFile = signed
+ } else {
+ alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
+ TransformZipAlign(ctx, alignedApk, dexOutput)
+ a.outputFile = alignedApk
+ }
+
+ // TODO: Optionally compress the output apk.
+
+ ctx.InstallFile(installDir, a.BaseModuleName()+".apk", a.outputFile)
+
+ // TODO: androidmk converter jni libs
+}
+
+func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
+ return &a.prebuilt
+}
+
+func (a *AndroidAppImport) Name() string {
+ return a.prebuilt.Name(a.ModuleBase.Name())
+}
+
+// android_app_import imports a prebuilt apk with additional processing specified in the module.
+func AndroidAppImportFactory() android.Module {
+ module := &AndroidAppImport{}
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.dexpreoptProperties)
+
+ InitJavaModule(module, android.DeviceSupported)
+ android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk)
+
+ return module
+}
diff --git a/java/app_builder.go b/java/app_builder.go
index 5bacb67..82a390f 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -62,7 +62,7 @@
CommandDeps: []string{"${config.MergeZipsCmd}"},
})
-func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
+func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
@@ -83,6 +83,11 @@
Output: unsignedApk,
})
+ SignAppPackage(ctx, outputFile, unsignedApk, certificates)
+}
+
+func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) {
+
var certificateArgs []string
var deps android.Paths
for _, c := range certificates {
@@ -93,7 +98,7 @@
ctx.Build(pctx, android.BuildParams{
Rule: Signapk,
Description: "signapk",
- Output: outputFile,
+ Output: signedApk,
Input: unsignedApk,
Implicits: deps,
Args: map[string]string{
diff --git a/java/app_test.go b/java/app_test.go
index a084c9c..e4c6afe 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -968,3 +968,87 @@
}
}
}
+
+func TestAndroidAppImport(t *testing.T) {
+ ctx := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+
+ // Check cert signing flag.
+ signedApk := variant.Output("signed/foo.apk")
+ signingFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+}
+
+func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
+ ctx := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ dex_preopt: {
+ enabled: false,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs. They shouldn't exist.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
+ t.Errorf("dexpreopt shouldn't have run.")
+ }
+}
+
+func TestAndroidAppImport_Presigned(t *testing.T) {
+ ctx := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+ // Make sure stripping wasn't done.
+ stripRule := variant.Output("dexpreopt/foo.apk")
+ if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") {
+ t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command)
+ }
+
+ // Make sure signing was skipped and aligning was done instead.
+ if variant.MaybeOutput("signed/foo.apk").Rule != nil {
+ t.Errorf("signing rule shouldn't be included.")
+ }
+ if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
+ t.Errorf("can't find aligning rule")
+ }
+}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 9f40a6c..9c883e5 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -15,9 +15,12 @@
package java
import (
- "android/soong/android"
+ "fmt"
+ "io"
"github.com/google/blueprint"
+
+ "android/soong/android"
)
type DeviceHostConverter struct {
@@ -30,6 +33,9 @@
implementationJars android.Paths
implementationAndResourceJars android.Paths
resourceJars android.Paths
+
+ combinedHeaderJar android.Path
+ combinedImplementationJar android.Path
}
type DeviceHostConverterProperties struct {
@@ -98,6 +104,27 @@
ctx.PropertyErrorf("libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
}
})
+
+ jarName := ctx.ModuleName() + ".jar"
+
+ if len(d.implementationAndResourceJars) > 1 {
+ outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+ TransformJarsToJar(ctx, outputFile, "combine", d.implementationAndResourceJars,
+ android.OptionalPath{}, false, nil, nil)
+ d.combinedImplementationJar = outputFile
+ } else {
+ d.combinedImplementationJar = d.implementationAndResourceJars[0]
+ }
+
+ if len(d.headerJars) > 1 {
+ outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, outputFile, "turbine combine", d.headerJars,
+ android.OptionalPath{}, false, nil, nil)
+ d.combinedHeaderJar = outputFile
+ } else {
+ d.combinedHeaderJar = d.headerJars[0]
+ }
+
}
var _ Dependency = (*DeviceHostConverter)(nil)
@@ -129,3 +156,18 @@
func (d *DeviceHostConverter) ExportedSdkLibs() []string {
return nil
}
+
+func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Class: "JAVA_LIBRARIES",
+ OutputFile: android.OptionalPathForPath(d.combinedImplementationJar),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Extra: []android.AndroidMkExtraFunc{
+ func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", d.combinedHeaderJar.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", d.combinedImplementationJar.String())
+ },
+ },
+ }
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 9141f9e..08fd06e 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -22,11 +22,12 @@
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
- installPath android.OutputPath
- uncompressedDex bool
- isSDKLibrary bool
- isTest bool
- isInstallable bool
+ installPath android.OutputPath
+ uncompressedDex bool
+ isSDKLibrary bool
+ isTest bool
+ isInstallable bool
+ isPresignedPrebuilt bool
builtInstalled string
}
@@ -51,7 +52,7 @@
// If set, provides the path to profile relative to the Android.bp file. If not set,
// defaults to searching for a file that matches the name of this module in the default
// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
- Profile *string
+ Profile *string `android:"path"`
}
}
@@ -110,7 +111,9 @@
if len(archs) == 0 {
// assume this is a java library, dexpreopt for all arches for now
for _, target := range ctx.Config().Targets[android.Android] {
- archs = append(archs, target.Arch.ArchType)
+ if target.NativeBridge == android.NativeBridgeDisabled {
+ archs = append(archs, target.Arch.ArchType)
+ }
}
if inList(ctx.ModuleName(), global.SystemServerJars) && !d.isSDKLibrary {
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
@@ -177,6 +180,8 @@
NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
+ PresignedPrebuilt: d.isPresignedPrebuilt,
+
NoStripping: Bool(d.dexpreoptProperties.Dex_preopt.No_stripping),
StripInputPath: dexJarFile,
StripOutputPath: strippedDexJarFile.OutputPath,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index cb2ea9f..092a133 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -197,8 +197,10 @@
}
for _, target := range targets {
- files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
- allFiles = append(allFiles, files.Paths()...)
+ if target.NativeBridge == android.NativeBridgeDisabled {
+ files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ allFiles = append(allFiles, files.Paths()...)
+ }
}
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index b30bd00..a0b1ea5 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -138,21 +138,29 @@
global := dexpreoptGlobalConfig(ctx)
runtimeModules := global.RuntimeApexJars
+ nonFrameworkModules := concat(runtimeModules, global.ProductUpdatableBootModules)
+ frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
+ imageModules := concat(runtimeModules, frameworkModules)
- var runtimeBootLocations []string
+ var bootLocations []string
for _, m := range runtimeModules {
- runtimeBootLocations = append(runtimeBootLocations,
+ bootLocations = append(bootLocations,
filepath.Join("/apex/com.android.runtime/javalib", m+".jar"))
}
+ for _, m := range frameworkModules {
+ bootLocations = append(bootLocations,
+ filepath.Join("/system/framework", m+".jar"))
+ }
+
// The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
// the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy
// them there.
// TODO: use module dependencies instead
- var runtimeBootDexPaths android.WritablePaths
- for _, m := range runtimeModules {
- runtimeBootDexPaths = append(runtimeBootDexPaths,
+ var bootDexPaths android.WritablePaths
+ for _, m := range imageModules {
+ bootDexPaths = append(bootDexPaths,
android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars_input", m+".jar"))
}
@@ -167,9 +175,9 @@
return bootImageConfig{
name: "apex",
- modules: runtimeModules,
- dexLocations: runtimeBootLocations,
- dexPaths: runtimeBootDexPaths,
+ modules: imageModules,
+ dexLocations: bootLocations,
+ dexPaths: bootDexPaths,
dir: dir,
symbolsDir: symbolsDir,
images: images,
diff --git a/java/java.go b/java/java.go
index d6c759b..47dd957 100644
--- a/java/java.go
+++ b/java/java.go
@@ -221,6 +221,13 @@
// If true, export a copy of the module as a -hostdex module for host testing.
Hostdex *bool
+ Target struct {
+ Hostdex struct {
+ // Additional required dependencies to add to -hostdex modules.
+ Required []string
+ }
+ }
+
// If set to true, compile dex regardless of installable. Defaults to false.
Compile_dex *bool
@@ -1246,9 +1253,9 @@
// merge implementation jar with resources if necessary
implementationAndResourcesJar := outputFile
if j.resourceJar != nil {
- jars := android.Paths{implementationAndResourcesJar, j.resourceJar}
+ jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
- TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
false, nil, nil)
implementationAndResourcesJar = combinedJar
}
@@ -1632,6 +1639,9 @@
&module.Module.protoProperties,
&module.testHelperLibraryProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.Module.dexpreopter.isTest = true
+
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
diff --git a/java/java_test.go b/java/java_test.go
index 3fab43d..5335d78 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -63,6 +63,7 @@
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
ctx.RegisterModuleType("android_app_certificate", android.ModuleFactoryAdaptor(AndroidAppCertificateFactory))
+ ctx.RegisterModuleType("android_app_import", android.ModuleFactoryAdaptor(AndroidAppImportFactory))
ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory))
ctx.RegisterModuleType("android_test", android.ModuleFactoryAdaptor(AndroidTestFactory))
ctx.RegisterModuleType("android_test_helper_app", android.ModuleFactoryAdaptor(AndroidTestHelperAppFactory))
@@ -163,6 +164,8 @@
"prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
"prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`),
+ "prebuilts/apk/app.apk": nil,
+
// For framework-res, which is an implicit dependency for framework
"AndroidManifest.xml": nil,
"build/make/target/product/security/testkey": nil,
diff --git a/java/robolectric.go b/java/robolectric.go
new file mode 100644
index 0000000..26f1e9d
--- /dev/null
+++ b/java/robolectric.go
@@ -0,0 +1,110 @@
+// Copyright 2019 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 java
+
+import (
+ "fmt"
+ "io"
+ "strings"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
+}
+
+var robolectricDefaultLibs = []string{
+ "robolectric_android-all-stub",
+ "Robolectric_all-target",
+ "mockito-robolectric-prebuilt",
+ "truth-prebuilt",
+}
+
+type robolectricProperties struct {
+ // The name of the android_app module that the tests will run against.
+ Instrumentation_for *string
+
+ Test_options struct {
+ // Timeout in seconds when running the tests.
+ Timeout *string
+ }
+}
+
+type robolectricTest struct {
+ Library
+
+ robolectricProperties robolectricProperties
+
+ libs []string
+}
+
+func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ r.Library.DepsMutator(ctx)
+
+ if r.robolectricProperties.Instrumentation_for != nil {
+ ctx.AddVariationDependencies(nil, instrumentationForTag, String(r.robolectricProperties.Instrumentation_for))
+ } else {
+ ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
+ }
+
+ ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
+}
+
+func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ r.Library.GenerateAndroidBuildActions(ctx)
+
+ for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+ r.libs = append(r.libs, ctx.OtherModuleName(dep))
+ }
+}
+
+func (r *robolectricTest) AndroidMk() android.AndroidMkData {
+ data := r.Library.AndroidMk()
+
+ data.Custom = func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ android.WriteAndroidMkData(w, data)
+
+ fmt.Fprintln(w, "")
+ fmt.Fprintln(w, "include $(CLEAR_VARS)")
+ fmt.Fprintln(w, "LOCAL_MODULE := Run"+name)
+ fmt.Fprintln(w, "LOCAL_JAVA_LIBRARIES :=", name)
+ fmt.Fprintln(w, "LOCAL_JAVA_LIBRARIES += ", strings.Join(r.libs, " "))
+ fmt.Fprintln(w, "LOCAL_TEST_PACKAGE :=", String(r.robolectricProperties.Instrumentation_for))
+ if t := r.robolectricProperties.Test_options.Timeout; t != nil {
+ fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
+ }
+ fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+ }
+
+ return data
+}
+
+// An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
+// instead of on a device. It also generates a rule with the name of the module prefixed with "Run" that can be
+// used to run the tests. Running the tests with build rule will eventually be deprecated and replaced with atest.
+func RobolectricTestFactory() android.Module {
+ module := &robolectricTest{}
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.protoProperties,
+ &module.robolectricProperties)
+
+ module.Module.dexpreopter.isTest = true
+
+ InitJavaModule(module, android.DeviceSupported)
+ return module
+}
diff --git a/scripts/strip.sh b/scripts/strip.sh
index d536907..0f77da8 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -24,6 +24,7 @@
# -i ${file}: input file (required)
# -o ${file}: output file (required)
# -d ${file}: deps file (required)
+# -k symbols: Symbols to keep (optional)
# --add-gnu-debuglink
# --keep-mini-debug-info
# --keep-symbols
@@ -32,11 +33,11 @@
set -o pipefail
-OPTSTRING=d:i:o:-:
+OPTSTRING=d:i:o:k:-:
usage() {
cat <<EOF
-Usage: strip.sh [options] -i in-file -o out-file -d deps-file
+Usage: strip.sh [options] -k symbols -i in-file -o out-file -d deps-file
Options:
--add-gnu-debuglink Add a gnu-debuglink section to out-file
--keep-mini-debug-info Keep compressed debug info in out-file
@@ -71,6 +72,20 @@
fi
}
+do_strip_keep_symbol_list() {
+ if [ -z "${use_gnu_strip}" ]; then
+ echo "do_strip_keep_symbol_list does not work with llvm-objcopy"
+ echo "http://b/131631155"
+ usage
+ fi
+
+ echo "${symbols_to_keep}" | tr ',' '\n' > "${outfile}.symbolList"
+ KEEP_SYMBOLS="-w --strip-unneeded-symbol=* --keep-symbols="
+ KEEP_SYMBOLS+="${outfile}.symbolList"
+
+ "${CROSS_COMPILE}objcopy" "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
+}
+
do_strip_keep_mini_debug_info() {
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
local fail=
@@ -124,19 +139,21 @@
while getopts $OPTSTRING opt; do
case "$opt" in
- d) depsfile="${OPTARG}" ;;
- i) infile="${OPTARG}" ;;
- o) outfile="${OPTARG}" ;;
- -)
- case "${OPTARG}" in
- add-gnu-debuglink) add_gnu_debuglink=true ;;
- keep-mini-debug-info) keep_mini_debug_info=true ;;
- keep-symbols) keep_symbols=true ;;
- remove-build-id) remove_build_id=true ;;
- *) echo "Unknown option --${OPTARG}"; usage ;;
- esac;;
- ?) usage ;;
- *) echo "'${opt}' '${OPTARG}'"
+ d) depsfile="${OPTARG}" ;;
+ i) infile="${OPTARG}" ;;
+ o) outfile="${OPTARG}" ;;
+ k) symbols_to_keep="${OPTARG}" ;;
+ -)
+ case "${OPTARG}" in
+ add-gnu-debuglink) add_gnu_debuglink=true ;;
+ keep-mini-debug-info) keep_mini_debug_info=true ;;
+ keep-symbols) keep_symbols=true ;;
+ remove-build-id) remove_build_id=true ;;
+ use-gnu-strip) use_gnu_strip=true ;;
+ *) echo "Unknown option --${OPTARG}"; usage ;;
+ esac;;
+ ?) usage ;;
+ *) echo "'${opt}' '${OPTARG}'"
esac
done
@@ -160,6 +177,11 @@
usage
fi
+if [ ! -z "${symbols_to_keep}" -a ! -z "${keep_symbols}" ]; then
+ echo "--keep-symbols and -k cannot be used together"
+ usage
+fi
+
if [ ! -z "${add_gnu_debuglink}" -a ! -z "${keep_mini_debug_info}" ]; then
echo "--add-gnu-debuglink cannot be used with --keep-mini-debug-info"
usage
@@ -169,6 +191,8 @@
if [ ! -z "${keep_symbols}" ]; then
do_strip_keep_symbols
+elif [ ! -z "${symbols_to_keep}" ]; then
+ do_strip_keep_symbol_list
elif [ ! -z "${keep_mini_debug_info}" ]; then
do_strip_keep_mini_debug_info
else
diff --git a/ui/build/build.go b/ui/build/build.go
index 0ae06d6..59d1474 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -166,11 +166,13 @@
runMakeProductConfig(ctx, config)
}
- if inList("installclean", config.Arguments()) {
+ if inList("installclean", config.Arguments()) ||
+ inList("install-clean", config.Arguments()) {
installClean(ctx, config, what)
ctx.Println("Deleted images and staging directories.")
return
- } else if inList("dataclean", config.Arguments()) {
+ } else if inList("dataclean", config.Arguments()) ||
+ inList("data-clean", config.Arguments()) {
dataClean(ctx, config, what)
ctx.Println("Deleted data files.")
return
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index ed2d9ca..54006d2 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -74,13 +74,16 @@
}
var Configuration = map[string]PathConfig{
- "bash": Allowed,
- "bc": Allowed,
+ "bash": Allowed,
+ "bc": Allowed,
+ // We need bzip2 here even though we provide a bzip2 binary because
+ // GNU tar seems to avoid calling ours.
"bzip2": Allowed,
"date": Allowed,
"dd": Allowed,
"diff": Allowed,
"egrep": Allowed,
+ "expr": Allowed,
"find": Allowed,
"fuser": Allowed,
"getopt": Allowed,
@@ -104,7 +107,6 @@
"timeout": Allowed,
"tr": Allowed,
"unzip": Allowed,
- "xz": Allowed,
"zip": Allowed,
"zipinfo": Allowed,
@@ -134,7 +136,6 @@
"du": LinuxOnlyPrebuilt,
"echo": LinuxOnlyPrebuilt,
"env": LinuxOnlyPrebuilt,
- "expr": LinuxOnlyPrebuilt,
"head": LinuxOnlyPrebuilt,
"getconf": LinuxOnlyPrebuilt,
"hostname": LinuxOnlyPrebuilt,