Merge "Add support for sysprop description files to Java"
diff --git a/Android.bp b/Android.bp
index ac50166..bcf831d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -40,6 +40,7 @@
],
srcs: [
"android/androidmk.go",
+ "android/apex.go",
"android/api_levels.go",
"android/arch.go",
"android/config.go",
@@ -192,6 +193,9 @@
srcs: [
"genrule/genrule.go",
],
+ testSrcs: [
+ "genrule/genrule_test.go",
+ ],
pluginFor: ["soong_build"],
}
@@ -216,6 +220,7 @@
"blueprint-pathtools",
"soong",
"soong-android",
+ "soong-cc",
"soong-genrule",
"soong-java-config",
"soong-tradefed",
@@ -331,6 +336,23 @@
pluginFor: ["soong_build"],
}
+bootstrap_go_package {
+ name: "soong-apex",
+ pkgPath: "android/soong/apex",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-java",
+ ],
+ srcs: [
+ "apex/apex.go",
+ "apex/key.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
//
// Defaults to enable various configurations of host bionic
//
@@ -357,9 +379,19 @@
defaults: ["linux_bionic_supported"],
vendor_available: true,
recovery_available: true,
+
arch: {
arm: {
- instruction_set: "arm",
+ src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/arm-linux-androideabi/lib/libatomic.a",
+ },
+ arm64: {
+ src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/aarch64-linux-android/lib64/libatomic.a",
+ },
+ x86: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/lib/libatomic.a",
+ },
+ x86_64: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/lib64/libatomic.a",
},
},
}
@@ -369,9 +401,19 @@
defaults: ["linux_bionic_supported"],
vendor_available: true,
recovery_available: true,
+
arch: {
arm: {
- instruction_set: "arm",
+ src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
+ },
+ 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",
},
},
}
@@ -384,15 +426,31 @@
windows: {
enabled: true,
},
+ windows_x86: {
+ src: "prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib32/libwinpthread.a",
+ },
+ windows_x86_64: {
+ src: "prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib/libwinpthread.a",
+ },
},
}
toolchain_library {
name: "libgcov",
defaults: ["linux_bionic_supported"],
+
arch: {
arm: {
- instruction_set: "arm",
+ src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcov.a",
+ },
+ arm64: {
+ src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcov.a",
+ },
+ x86: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcov.a",
+ },
+ x86_64: {
+ src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcov.a",
},
},
}
@@ -424,7 +482,7 @@
}
cc_genrule {
- name: "host_bionic_linker_script",
+ name: "host_bionic_linker_flags",
host_supported: true,
device_supported: false,
target: {
@@ -439,7 +497,7 @@
},
},
tools: ["extract_linker"],
- cmd: "$(location) -T $(out) $(in)",
+ cmd: "$(location) -f $(out) $(in)",
srcs: [":linker"],
- out: ["linker.script"],
+ out: ["linker.flags"],
}
diff --git a/android/androidmk.go b/android/androidmk.go
index 5df4a85..7030523 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -215,7 +215,7 @@
}
- if amod.Arch().ArchType != ctx.Config().Targets[amod.Os().Class][0].Arch.ArchType {
+ if amod.Arch().ArchType != ctx.Config().Targets[amod.Os()][0].Arch.ArchType {
prefix = "2ND_" + prefix
}
}
diff --git a/android/apex.go b/android/apex.go
new file mode 100644
index 0000000..dae88ce
--- /dev/null
+++ b/android/apex.go
@@ -0,0 +1,102 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+// ApexModule is the interface that a module type is expected to implement if
+// the module has to be built differently depending on whether the module
+// is destined for an apex or not (installed to one of the regular partitions).
+//
+// Native shared libraries are one such module type; when it is built for an
+// APEX, it should depend only on stable interfaces such as NDK, stable AIDL,
+// or C APIs from other APEXs.
+//
+// A module implementing this interface will be mutated into multiple
+// variations by the apex mutator if it is directly or indirectly included
+// in one or more APEXs. Specifically, if a module is included in apex.foo and
+// apex.bar then three apex variants are created: platform, apex.foo and
+// apex.bar. The platform variant is for the regular partitions
+// (e.g., /system or /vendor, etc.) while the other two are for the APEXs,
+// respectively.
+type ApexModule interface {
+ Module
+ apexModuleBase() *ApexModuleBase
+
+ // Marks that this module should be built for the APEX of the specified name
+ BuildForApex(apexName string)
+
+ // Tests whether this module will be built for the platform or not (= APEXs)
+ IsForPlatform() bool
+
+ // Returns the name of APEX that this module will be built for. Empty string
+ // is returned when 'IsForPlatform() == true'. Note that a module can be
+ // included to multiple APEXs, in which case, the module is mutated into
+ // multiple modules each of which for an APEX. This method returns the
+ // name of the APEX that a variant module is for.
+ ApexName() string
+
+ // Tests if this module can have APEX variants. APEX variants are
+ // created only for the modules that returns true here. This is useful
+ // for not creating APEX variants for shared libraries such as NDK stubs.
+ CanHaveApexVariants() bool
+
+ // Tests if this module can be installed to APEX as a file. For example,
+ // this would return true for shared libs while return false for static
+ // libs.
+ IsInstallableToApex() bool
+}
+
+type ApexProperties struct {
+ ApexName string `blueprint:"mutated"`
+}
+
+// Provides default implementation for the ApexModule interface. APEX-aware
+// modules are expected to include this struct and call InitApexModule().
+type ApexModuleBase struct {
+ ApexProperties ApexProperties
+
+ canHaveApexVariants bool
+}
+
+func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
+ return m
+}
+
+func (m *ApexModuleBase) BuildForApex(apexName string) {
+ m.ApexProperties.ApexName = apexName
+}
+
+func (m *ApexModuleBase) IsForPlatform() bool {
+ return m.ApexProperties.ApexName == ""
+}
+
+func (m *ApexModuleBase) ApexName() string {
+ return m.ApexProperties.ApexName
+}
+
+func (m *ApexModuleBase) CanHaveApexVariants() bool {
+ return m.canHaveApexVariants
+}
+
+func (m *ApexModuleBase) IsInstallableToApex() bool {
+ // should be overriden if needed
+ return false
+}
+
+func InitApexModule(m ApexModule) {
+ base := m.apexModuleBase()
+ base.canHaveApexVariants = true
+
+ m.AddProperties(&base.ApexProperties)
+}
diff --git a/android/arch.go b/android/arch.go
index 57899cd..2543fca 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -194,7 +194,7 @@
NoOsType OsType
Linux = NewOsType("linux_glibc", Host, false)
Darwin = NewOsType("darwin", Host, false)
- LinuxBionic = NewOsType("linux_bionic", Host, true)
+ LinuxBionic = NewOsType("linux_bionic", Host, false)
Windows = NewOsType("windows", HostCross, true)
Android = NewOsType("android", Device, false)
@@ -288,6 +288,30 @@
return target.Os.String() + "_" + target.Arch.String()
}
+// archMutator splits a module into a variant for each Target requested by the module. Target selection
+// for a module is in three levels, OsClass, mulitlib, and then Target.
+// OsClass selection is determined by:
+// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
+// whether the module type can compile for host, device or both.
+// - The host_supported and device_supported properties on the module.
+// If host is supported for the module, the Host and HostCross OsClasses are are selected. If device is supported
+// for the module, the Device OsClass is selected.
+// Within each selected OsClass, the multilib selection is determined by:
+// - The compile_multilib property if it set (which may be overriden by target.android.compile_multlib or
+// target.host.compile_multilib).
+// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
+// Valid multilib values include:
+// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
+// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64,
+// but may be arm for a 32-bit only build or a build with TARGET_PREFER_32_BIT=true set.
+// "32": compile for only a single 32-bit Target supported by the OsClass.
+// "64": compile for only a single 64-bit Target supported by the OsClass.
+// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
+//
+// Once the list of Targets is determined, the module is split into a variant for each Target.
+//
+// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
+// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
func archMutator(mctx BottomUpMutatorContext) {
var module Module
var ok bool
@@ -295,57 +319,66 @@
return
}
- if !module.base().ArchSpecific() {
+ base := module.base()
+
+ if !base.ArchSpecific() {
return
}
- osClasses := module.base().OsClassSupported()
-
var moduleTargets []Target
+ moduleMultiTargets := make(map[int][]Target)
primaryModules := make(map[int]bool)
+ osClasses := base.OsClassSupported()
- for _, class := range osClasses {
- targets := mctx.Config().Targets[class]
- if len(targets) == 0 {
+ for _, os := range osTypeList {
+ supportedClass := false
+ for _, osClass := range osClasses {
+ if os.Class == osClass {
+ supportedClass = true
+ }
+ }
+ if !supportedClass {
continue
}
- var multilib string
- switch class {
- case Device:
- multilib = String(module.base().commonProperties.Target.Android.Compile_multilib)
- case Host, HostCross:
- multilib = String(module.base().commonProperties.Target.Host.Compile_multilib)
+
+ osTargets := mctx.Config().Targets[os]
+ if len(osTargets) == 0 {
+ continue
}
- if multilib == "" {
- multilib = String(module.base().commonProperties.Compile_multilib)
- }
- if multilib == "" {
- multilib = module.base().commonProperties.Default_multilib
- }
- var prefer32 bool
- switch class {
- case Device:
- prefer32 = mctx.Config().DevicePrefer32BitExecutables()
- case HostCross:
- // Windows builds always prefer 32-bit
- prefer32 = true
- }
+
// only the primary arch in the recovery partition
- if module.InstallInRecovery() {
- targets = []Target{mctx.Config().Targets[Device][0]}
+ if os == Android && module.InstallInRecovery() {
+ osTargets = []Target{osTargets[0]}
}
- targets, err := decodeMultilib(multilib, targets, prefer32)
+
+ prefer32 := false
+ if base.prefer32 != nil {
+ prefer32 = base.prefer32(mctx, base, os.Class)
+ }
+
+ multilib, extraMultilib := decodeMultilib(base, os.Class)
+ targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
if err != nil {
mctx.ModuleErrorf("%s", err.Error())
}
+
+ var multiTargets []Target
+ if extraMultilib != "" {
+ multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
+ if err != nil {
+ mctx.ModuleErrorf("%s", err.Error())
+ }
+ }
+
if len(targets) > 0 {
primaryModules[len(moduleTargets)] = true
+ moduleMultiTargets[len(moduleTargets)] = multiTargets
moduleTargets = append(moduleTargets, targets...)
}
}
if len(moduleTargets) == 0 {
- module.base().commonProperties.Enabled = boolPtr(false)
+ base.commonProperties.Enabled = boolPtr(false)
return
}
@@ -357,11 +390,37 @@
modules := mctx.CreateVariations(targetNames...)
for i, m := range modules {
- m.(Module).base().SetTarget(moduleTargets[i], primaryModules[i])
+ m.(Module).base().SetTarget(moduleTargets[i], moduleMultiTargets[i], primaryModules[i])
m.(Module).base().setArchProperties(mctx)
}
}
+func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
+ switch class {
+ case Device:
+ multilib = String(base.commonProperties.Target.Android.Compile_multilib)
+ case Host, HostCross:
+ multilib = String(base.commonProperties.Target.Host.Compile_multilib)
+ }
+ if multilib == "" {
+ multilib = String(base.commonProperties.Compile_multilib)
+ }
+ if multilib == "" {
+ multilib = base.commonProperties.Default_multilib
+ }
+
+ if base.commonProperties.UseTargetVariants {
+ return multilib, ""
+ } else {
+ // For app modules a single arch variant will be created per OS class which is expected to handle all the
+ // selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
+ if multilib == base.commonProperties.Default_multilib {
+ multilib = "first"
+ }
+ return base.commonProperties.Default_multilib, multilib
+ }
+}
+
func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
var fields []reflect.StructField
@@ -789,17 +848,17 @@
}
if (arch.ArchType == X86 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
(arch.ArchType == Arm &&
- hasX86AndroidArch(ctx.Config().Targets[Device])) {
+ hasX86AndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86"
prefix := "target.arm_on_x86"
a.appendProperties(ctx, genProps, targetProp, field, prefix)
}
if (arch.ArchType == X86_64 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Device]))) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android]))) ||
(arch.ArchType == Arm &&
- hasX8664AndroidArch(ctx.Config().Targets[Device])) {
+ hasX8664AndroidArch(ctx.Config().Targets[Android])) {
field := "Arm_on_x86_64"
prefix := "target.arm_on_x86_64"
a.appendProperties(ctx, genProps, targetProp, field, prefix)
@@ -824,10 +883,10 @@
}
// Convert the arch product variables into a list of targets for each os class structs
-func decodeTargetProductVariables(config *config) (map[OsClass][]Target, error) {
+func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
variables := config.productVariables
- targets := make(map[OsClass][]Target)
+ targets := make(map[OsType][]Target)
var targetErr error
addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi *[]string) {
@@ -841,7 +900,7 @@
return
}
- targets[os.Class] = append(targets[os.Class],
+ targets[os] = append(targets[os],
Target{
Os: os,
Arch: arch,
@@ -888,7 +947,7 @@
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
variables.DeviceSecondaryAbi)
- deviceArches := targets[Device]
+ deviceArches := targets[Android]
if deviceArches[0].Arch.ArchType.Multilib == deviceArches[1].Arch.ArchType.Multilib {
deviceArches[1].Arch.Native = false
}
@@ -962,6 +1021,7 @@
{"arm", "armv7-a-neon", "cortex-a72", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a73", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a75", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "denver", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
@@ -975,6 +1035,7 @@
{"arm64", "armv8-a", "exynos-m1", []string{"arm64-v8a"}},
{"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
+ {"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
{"mips", "mips32-fp", "", []string{"mips"}},
{"mips", "mips32r2-fp", "", []string{"mips"}},
{"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
@@ -1113,7 +1174,7 @@
}
// Use the module multilib setting to select one or more targets from a target list
-func decodeMultilib(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
+func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
buildTargets := []Target{}
switch multilib {
diff --git a/android/config.go b/android/config.go
index 3ef202b..0aee0e3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -90,7 +90,7 @@
ConfigFileName string
ProductVariablesFileName string
- Targets map[OsClass][]Target
+ Targets map[OsType][]Target
BuildOsVariant string
BuildOsCommonVariant string
@@ -230,17 +230,19 @@
testConfig := TestConfig(buildDir, env)
config := testConfig.config
- config.Targets = map[OsClass][]Target{
- Device: []Target{
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true}},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true}},
+ 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"}}},
},
- Host: []Target{
+ BuildOs: []Target{
{BuildOs, Arch{ArchType: X86_64}},
{BuildOs, Arch{ArchType: X86}},
},
}
+ config.BuildOsVariant = config.Targets[BuildOs][0].String()
+
return testConfig
}
@@ -302,16 +304,16 @@
}
if archConfig != nil {
- deviceTargets, err := decodeArchSettings(archConfig)
+ androidTargets, err := decodeArchSettings(archConfig)
if err != nil {
return Config{}, err
}
- targets[Device] = deviceTargets
+ targets[Android] = androidTargets
}
config.Targets = targets
- config.BuildOsVariant = targets[Host][0].String()
- config.BuildOsCommonVariant = getCommonTargets(targets[Host])[0].String()
+ config.BuildOsVariant = targets[BuildOs][0].String()
+ config.BuildOsCommonVariant = getCommonTargets(targets[BuildOs])[0].String()
if err := config.fromEnv(); err != nil {
return Config{}, err
@@ -576,12 +578,16 @@
return Bool(c.productVariables.Debuggable)
}
+func (c *config) DevicePrefer32BitApps() bool {
+ return Bool(c.productVariables.DevicePrefer32BitApps)
+}
+
func (c *config) DevicePrefer32BitExecutables() bool {
return Bool(c.productVariables.DevicePrefer32BitExecutables)
}
func (c *config) DevicePrimaryArchType() ArchType {
- return c.Targets[Device][0].Arch.ArchType
+ return c.Targets[Android][0].Arch.ArchType
}
func (c *config) SkipDeviceInstall() bool {
@@ -618,7 +624,7 @@
}
func (c *config) Android64() bool {
- for _, t := range c.Targets[Device] {
+ for _, t := range c.Targets[Android] {
if t.Arch.ArchType.Multilib == "lib64" {
return true
}
@@ -640,10 +646,6 @@
return c.targetOpenJDK9
}
-func (c *config) UseClangLld() bool {
- return Bool(c.productVariables.UseClangLld)
-}
-
func (c *config) ClangTidy() bool {
return Bool(c.productVariables.ClangTidy)
}
@@ -661,8 +663,8 @@
func (c *config) LibartImgDeviceBaseAddress() string {
archType := Common
- if len(c.Targets[Device]) > 0 {
- archType = c.Targets[Device][0].Arch.ArchType
+ if len(c.Targets[Android]) > 0 {
+ archType = c.Targets[Android][0].Arch.ArchType
}
switch archType {
default:
@@ -709,7 +711,7 @@
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
- for _, target := range c.config.Targets[Device] {
+ for _, target := range c.config.Targets[Android] {
arches = append(arches, target.Arch)
}
return arches
diff --git a/android/module.go b/android/module.go
index 92b11ed..556c73d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -58,6 +58,7 @@
type androidBaseContext interface {
Target() Target
TargetPrimary() bool
+ MultiTargets() []Target
Arch() Arch
Os() OsType
Host() bool
@@ -215,7 +216,8 @@
}
}
- Default_multilib string `blueprint:"mutated"`
+ UseTargetVariants bool `blueprint:"mutated"`
+ Default_multilib string `blueprint:"mutated"`
// whether this is a proprietary vendor module, and should be installed into /vendor
Proprietary *bool
@@ -264,8 +266,9 @@
Notice *string
// Set by TargetMutator
- CompileTarget Target `blueprint:"mutated"`
- CompilePrimary bool `blueprint:"mutated"`
+ CompileTarget Target `blueprint:"mutated"`
+ CompileMultiTargets []Target `blueprint:"mutated"`
+ CompilePrimary bool `blueprint:"mutated"`
// Set by InitAndroidModule
HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
@@ -362,6 +365,7 @@
base.commonProperties.HostOrDeviceSupported = hod
base.commonProperties.Default_multilib = string(defaultMultilib)
base.commonProperties.ArchSpecific = true
+ base.commonProperties.UseTargetVariants = true
switch hod {
case HostAndDeviceSupported, HostAndDeviceDefault:
@@ -371,6 +375,11 @@
InitArchModule(m)
}
+func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
+ InitAndroidArchModule(m, hod, defaultMultilib)
+ m.base().commonProperties.UseTargetVariants = false
+}
+
// A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's
@@ -442,6 +451,8 @@
// For tests
buildParams []BuildParams
+
+ prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
}
func (a *ModuleBase) AddProperties(props ...interface{}) {
@@ -456,6 +467,10 @@
return a.buildParams
}
+func (a *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) {
+ a.prefer32 = prefer32
+}
+
// Name returns the name of the module. It may be overridden by individual module types, for
// example prebuilts will prepend prebuilt_ to the name.
func (a *ModuleBase) Name() string {
@@ -471,8 +486,9 @@
return a
}
-func (a *ModuleBase) SetTarget(target Target, primary bool) {
+func (a *ModuleBase) SetTarget(target Target, multiTargets []Target, primary bool) {
a.commonProperties.CompileTarget = target
+ a.commonProperties.CompileMultiTargets = multiTargets
a.commonProperties.CompilePrimary = primary
}
@@ -484,6 +500,10 @@
return a.commonProperties.CompilePrimary
}
+func (a *ModuleBase) MultiTargets() []Target {
+ return a.commonProperties.CompileMultiTargets
+}
+
func (a *ModuleBase) Os() OsType {
return a.Target().Os
}
@@ -725,6 +745,7 @@
return androidBaseContextImpl{
target: a.commonProperties.CompileTarget,
targetPrimary: a.commonProperties.CompilePrimary,
+ multiTargets: a.commonProperties.CompileMultiTargets,
kind: determineModuleKind(a, ctx),
config: ctx.Config().(Config),
}
@@ -779,6 +800,7 @@
type androidBaseContextImpl struct {
target Target
+ multiTargets []Target
targetPrimary bool
debug bool
kind moduleKind
@@ -1016,6 +1038,10 @@
return a.targetPrimary
}
+func (a *androidBaseContextImpl) MultiTargets() []Target {
+ return a.multiTargets
+}
+
func (a *androidBaseContextImpl) Arch() Arch {
return a.target.Arch
}
@@ -1045,10 +1071,10 @@
}
func (a *androidBaseContextImpl) PrimaryArch() bool {
- if len(a.config.Targets[a.target.Os.Class]) <= 1 {
+ if len(a.config.Targets[a.target.Os]) <= 1 {
return true
}
- return a.target.Arch.ArchType == a.config.Targets[a.target.Os.Class][0].Arch.ArchType
+ return a.target.Arch.ArchType == a.config.Targets[a.target.Os][0].Arch.ArchType
}
func (a *androidBaseContextImpl) AConfig() Config {
diff --git a/android/neverallow.go b/android/neverallow.go
index a7f4f82..d3a2801 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -56,7 +56,9 @@
without("vendor", "true").
without("owner", "").
because("a VNDK module can never have an owner."),
- neverallow().notIn("libcore", "development", "external/conscrypt").with("no_standard_libs", "true"),
+ neverallow().
+ notIn("libcore", "development", "external/apache-harmony", "external/apache-xml", "external/bouncycastle", "external/conscrypt", "external/icu", "external/okhttp", "external/wycheproof").
+ with("no_standard_libs", "true"),
// TODO(b/67974785): always enforce the manifest
neverallow().
diff --git a/android/paths.go b/android/paths.go
index daaf857..b22e3c7 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -725,46 +725,6 @@
return PathForOutput(ctx, ".intermediates", path)
}
-// DistPath is a Path representing a file path rooted from the dist directory
-type DistPath struct {
- basePath
-}
-
-func (p DistPath) withRel(rel string) DistPath {
- p.basePath = p.basePath.withRel(rel)
- return p
-}
-
-var _ Path = DistPath{}
-
-// PathForDist joins the provided paths and returns a DistPath that is
-// validated to not escape the dist dir.
-// On error, it will return a usable, but invalid DistPath, and report a ModuleError.
-func PathForDist(ctx PathContext, pathComponents ...string) DistPath {
- path, err := validatePath(pathComponents...)
- if err != nil {
- reportPathError(ctx, err)
- }
- return DistPath{basePath{path, ctx.Config(), ""}}
-}
-
-func (p DistPath) writablePath() {}
-
-func (p DistPath) Valid() bool {
- return p.config.productVariables.DistDir != nil && *p.config.productVariables.DistDir != ""
-}
-
-func (p DistPath) String() string {
- if !p.Valid() {
- panic("Requesting an invalid path")
- }
- return filepath.Join(*p.config.productVariables.DistDir, p.path)
-}
-
-func (p DistPath) RelPathString() string {
- return p.path
-}
-
// ModuleSrcPath is a Path representing a file rooted from a module's local source dir
type ModuleSrcPath struct {
SourcePath
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index 046512f..fbc9de2 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -49,6 +49,7 @@
properties prebuiltEtcProperties
sourceFilePath Path
+ outputFilePath OutputPath
installDirPath OutputPath
additionalDependencies *Paths
}
@@ -84,9 +85,25 @@
p.additionalDependencies = &paths
}
+func (p *PrebuiltEtc) OutputFile() OutputPath {
+ return p.outputFilePath
+}
+
+func (p *PrebuiltEtc) SubDir() string {
+ return String(p.properties.Sub_dir)
+}
+
func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
+ p.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName()).OutputPath
p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
+
+ // This ensures that outputFilePath has the same name as this module.
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Output: p.outputFilePath,
+ Input: p.sourceFilePath,
+ })
}
func (p *PrebuiltEtc) AndroidMk() AndroidMkData {
@@ -101,7 +118,7 @@
fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
- fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.sourceFilePath.String())
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
if p.additionalDependencies != nil {
diff --git a/android/variable.go b/android/variable.go
index b478389..476171b 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -183,7 +183,6 @@
Eng *bool `json:",omitempty"`
Device_uses_hwc2 *bool `json:",omitempty"`
Treble_linker_namespaces *bool `json:",omitempty"`
- Sepolicy_split *bool `json:",omitempty"`
Enforce_vintf_manifest *bool `json:",omitempty"`
Pdk *bool `json:",omitempty"`
Uml *bool `json:",omitempty"`
@@ -202,8 +201,6 @@
ProductPath *string `json:",omitempty"`
ProductServicesPath *string `json:",omitempty"`
- UseClangLld *bool `json:",omitempty"`
-
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
@@ -211,6 +208,7 @@
CoveragePaths *[]string `json:",omitempty"`
CoverageExcludePaths *[]string `json:",omitempty"`
+ DevicePrefer32BitApps *bool `json:",omitempty"`
DevicePrefer32BitExecutables *bool `json:",omitempty"`
HostPrefer32BitExecutables *bool `json:",omitempty"`
@@ -228,7 +226,6 @@
Product_is_iot *bool `json:",omitempty"`
DeviceKernelHeaders []string `json:",omitempty"`
- DistDir *string `json:",omitempty"`
ExtraVndkVersions []string `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 1d50980..b3d5aec 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -51,6 +51,7 @@
"LOCAL_MODULE_HOST_OS": hostOs,
"LOCAL_SANITIZE": sanitize(""),
"LOCAL_SANITIZE_DIAG": sanitize("diag."),
+ "LOCAL_STRIP_MODULE": strip(),
"LOCAL_CFLAGS": cflags,
"LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
"LOCAL_PROGUARD_ENABLED": proguardEnabled,
@@ -81,7 +82,6 @@
map[string]string{
"LOCAL_MODULE": "name",
"LOCAL_CXX_STL": "stl",
- "LOCAL_STRIP_MODULE": "strip",
"LOCAL_MULTILIB": "compile_multilib",
"LOCAL_ARM_MODE_HACK": "instruction_set",
"LOCAL_SDK_VERSION": "sdk_version",
@@ -140,6 +140,7 @@
"LOCAL_DX_FLAGS": "dxflags",
"LOCAL_JAVA_LIBRARIES": "libs",
"LOCAL_STATIC_JAVA_LIBRARIES": "static_libs",
+ "LOCAL_JNI_SHARED_LIBRARIES": "jni_libs",
"LOCAL_AAPT_FLAGS": "aaptflags",
"LOCAL_PACKAGE_SPLITS": "package_splits",
"LOCAL_COMPATIBILITY_SUITE": "test_suites",
@@ -154,6 +155,7 @@
// java_library_static to android_library.
"LOCAL_SHARED_ANDROID_LIBRARIES": "android_libs",
"LOCAL_STATIC_ANDROID_LIBRARIES": "android_static_libs",
+ "LOCAL_ADDITIONAL_CERTIFICATES": "additional_certificates",
})
addStandardProperties(bpparser.BoolType,
@@ -461,6 +463,29 @@
}
}
+func strip() func(ctx variableAssignmentContext) error {
+ return func(ctx variableAssignmentContext) error {
+ val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.StringType)
+ if err != nil {
+ return err
+ }
+
+ if _, ok := val.(*bpparser.String); !ok {
+ return fmt.Errorf("unsupported strip expression")
+ }
+
+ bpTrue := &bpparser.Bool{
+ Value: true,
+ }
+ v := val.(*bpparser.String).Value
+ sub := (map[string]string{"false": "none", "true": "all", "keep_symbols": "keep_symbols"})[v]
+ if sub == "" {
+ return fmt.Errorf("unexpected strip option: %s", v)
+ }
+ return setVariable(ctx.file, false, ctx.prefix, "strip."+sub, bpTrue, true)
+ }
+}
+
func prebuiltClass(ctx variableAssignmentContext) error {
class := ctx.mkvalue.Value(ctx.file.scope)
if v, ok := prebuiltTypes[class]; ok {
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 80e7a75..0f6c5ac 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -692,6 +692,47 @@
}
`,
},
+ {
+ desc: "LOCAL_STRIP_MODULE",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest
+LOCAL_STRIP_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest2
+LOCAL_STRIP_MODULE := true
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libtest3
+LOCAL_STRIP_MODULE := keep_symbols
+include $(BUILD_SHARED_LIBRARY)
+`,
+ expected: `
+cc_library_shared {
+ name: "libtest",
+ strip: {
+ none: true,
+ }
+}
+
+cc_library_shared {
+ name: "libtest2",
+ strip: {
+ all: true,
+ }
+}
+
+cc_library_shared {
+ name: "libtest3",
+ strip: {
+ keep_symbols: true,
+ }
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/apex.go b/apex/apex.go
new file mode 100644
index 0000000..619ac33
--- /dev/null
+++ b/apex/apex.go
@@ -0,0 +1,413 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package apex
+
+import (
+ "fmt"
+ "io"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/java"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ pctx = android.NewPackageContext("android/apex")
+
+ // Create a canned fs config file where all files and directories are
+ // by default set to (uid/gid/mode) = (1000/1000/0644)
+ // TODO(b/113082813) make this configurable using config.fs syntax
+ generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
+ Command: `echo '/ 1000 1000 0644' > ${out} && ` +
+ `echo '/manifest.json 1000 1000 0644' >> ${out} && ` +
+ `echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
+ `echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0755"}' >> ${out}`,
+ Description: "fs_config ${out}",
+ }, "ro_paths", "exec_paths")
+
+ // TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
+ // against the binary policy using sefcontext_compiler -p <policy>.
+
+ // TODO(b/114327326): automate the generation of file_contexts
+ apexRule = pctx.StaticRule("apexRule", blueprint.RuleParams{
+ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
+ `(${copy_commands}) && ` +
+ `APEXER_TOOL_PATH=${tool_path} ` +
+ `${apexer} --verbose --force --manifest ${manifest} ` +
+ `--file_contexts ${file_contexts} ` +
+ `--canned_fs_config ${canned_fs_config} ` +
+ `--key ${key} ${image_dir} ${out} `,
+ CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
+ "${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
+ "${soong_zip}", "${zipalign}", "${aapt2}"},
+ Description: "APEX ${image_dir} => ${out}",
+ }, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key")
+)
+
+var apexSuffix = ".apex"
+
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+var (
+ sharedLibTag = dependencyTag{name: "sharedLib"}
+ executableTag = dependencyTag{name: "executable"}
+ javaLibTag = dependencyTag{name: "javaLib"}
+ prebuiltTag = dependencyTag{name: "prebuilt"}
+ keyTag = dependencyTag{name: "key"}
+)
+
+func init() {
+ pctx.Import("android/soong/common")
+ pctx.HostBinToolVariable("apexer", "apexer")
+ pctx.HostBinToolVariable("aapt2", "aapt2")
+ pctx.HostBinToolVariable("avbtool", "avbtool")
+ pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid")
+ pctx.HostBinToolVariable("merge_zips", "merge_zips")
+ pctx.HostBinToolVariable("mke2fs", "mke2fs")
+ pctx.HostBinToolVariable("resize2fs", "resize2fs")
+ pctx.HostBinToolVariable("sefcontext_compile", "sefcontext_compile")
+ pctx.HostBinToolVariable("soong_zip", "soong_zip")
+ pctx.HostBinToolVariable("zipalign", "zipalign")
+
+ android.RegisterModuleType("apex", apexBundleFactory)
+
+ android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_deps", apexDepsMutator)
+ ctx.BottomUp("apex", apexMutator)
+ })
+}
+
+// maps a module name to set of apex bundle names that the module should be built for
+func apexBundleNamesFor(config android.Config) map[string]map[string]bool {
+ return config.Once("apexBundleNames", func() interface{} {
+ return make(map[string]map[string]bool)
+ }).(map[string]map[string]bool)
+}
+
+// Mark the direct and transitive dependencies of apex bundles so that they
+// can be built for the apex bundles.
+func apexDepsMutator(mctx android.TopDownMutatorContext) {
+ if _, ok := mctx.Module().(*apexBundle); ok {
+ apexBundleName := mctx.Module().Name()
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
+ moduleName := am.Name()
+ bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]
+ if !ok {
+ bundleNames = make(map[string]bool)
+ apexBundleNamesFor(mctx.Config())[moduleName] = bundleNames
+ }
+ bundleNames[apexBundleName] = true
+ return true
+ } else {
+ return false
+ }
+ })
+ }
+}
+
+// Create apex variations if a module is included in APEX(s).
+func apexMutator(mctx android.BottomUpMutatorContext) {
+ if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
+ moduleName := am.Name()
+ if bundleNames, ok := apexBundleNamesFor(mctx.Config())[moduleName]; ok {
+ variations := []string{"platform"}
+ for bn := range bundleNames {
+ variations = append(variations, bn)
+ }
+ modules := mctx.CreateVariations(variations...)
+ for i, m := range modules {
+ if i == 0 {
+ continue // platform
+ }
+ m.(android.ApexModule).BuildForApex(variations[i])
+ }
+ }
+ } else if _, ok := mctx.Module().(*apexBundle); ok {
+ // apex bundle itself is mutated so that it and its modules have same
+ // apex variant.
+ apexBundleName := mctx.ModuleName()
+ mctx.CreateVariations(apexBundleName)
+ }
+}
+
+type apexBundleProperties struct {
+ // Json manifest file describing meta info of this APEX bundle. Default:
+ // "manifest.json"
+ Manifest *string
+
+ // File contexts file for setting security context to each file in this APEX bundle
+ // Default: "file_contexts".
+ File_contexts *string
+
+ // List of native shared libs that are embedded inside this APEX bundle
+ Native_shared_libs []string
+
+ // List of native executables that are embedded inside this APEX bundle
+ Binaries []string
+
+ // List of java libraries that are embedded inside this APEX bundle
+ Java_libs []string
+
+ // List of prebuilt files that are embedded inside this APEX bundle
+ Prebuilts []string
+
+ // Name of the apex_key module that provides the private key to sign APEX
+ Key *string
+}
+
+type apexBundle struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ properties apexBundleProperties
+
+ outputFile android.WritablePath
+ installDir android.OutputPath
+}
+
+func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+ for _, arch := range ctx.MultiTargets() {
+ // Use *FarVariation* to be able to depend on modules having
+ // conflicting variations with this module. This is required since
+ // arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+ // for native shared libs.
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: arch.String()},
+ {Mutator: "image", Variation: "core"},
+ {Mutator: "link", Variation: "shared"},
+ }, sharedLibTag, a.properties.Native_shared_libs...)
+
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: arch.String()},
+ {Mutator: "image", Variation: "core"},
+ }, executableTag, a.properties.Binaries...)
+ }
+
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: "android_common"},
+ }, javaLibTag, a.properties.Java_libs...)
+
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: "android_common"},
+ }, prebuiltTag, a.properties.Prebuilts...)
+
+ if String(a.properties.Key) == "" {
+ ctx.ModuleErrorf("key is missing")
+ return
+ }
+ ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
+}
+
+func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
+ // Decide the APEX-local directory by the multilib of the library
+ // In the future, we may query this to the module.
+ switch cc.Arch().ArchType.Multilib {
+ case "lib32":
+ dirInApex = "lib"
+ case "lib64":
+ dirInApex = "lib64"
+ }
+ if !cc.Arch().Native {
+ dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
+ }
+
+ fileToCopy = cc.OutputFile().Path()
+ return
+}
+
+func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
+ dirInApex = "bin"
+ fileToCopy = cc.OutputFile().Path()
+ return
+}
+
+func getCopyManifestForJavaLibrary(java *java.Library) (fileToCopy android.Path, dirInApex string) {
+ dirInApex = "javalib"
+ fileToCopy = java.Srcs()[0]
+ return
+}
+
+func getCopyManifestForPrebuiltEtc(prebuilt *android.PrebuiltEtc) (fileToCopy android.Path, dirInApex string) {
+ dirInApex = filepath.Join("etc", prebuilt.SubDir())
+ fileToCopy = prebuilt.OutputFile()
+ return
+}
+
+func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // files to copy -> dir in apex
+ copyManifest := make(map[android.Path]string)
+
+ var keyFile android.Path
+
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if _, ok := parent.(*apexBundle); ok {
+ // direct dependencies
+ depTag := ctx.OtherModuleDependencyTag(child)
+ depName := ctx.OtherModuleName(child)
+ switch depTag {
+ case sharedLibTag:
+ if cc, ok := child.(*cc.Module); ok {
+ fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+ copyManifest[fileToCopy] = dirInApex
+ return true
+ } else {
+ ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
+ }
+ case executableTag:
+ if cc, ok := child.(*cc.Module); ok {
+ fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
+ copyManifest[fileToCopy] = dirInApex
+ return true
+ } else {
+ ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
+ }
+ case javaLibTag:
+ if java, ok := child.(*java.Library); ok {
+ fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
+ copyManifest[fileToCopy] = dirInApex
+ return true
+ } else {
+ ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName)
+ }
+ case prebuiltTag:
+ if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
+ fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
+ copyManifest[fileToCopy] = dirInApex
+ return true
+ } else {
+ ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
+ }
+ case keyTag:
+ if key, ok := child.(*apexKey); ok {
+ keyFile = key.private_key_file
+ return false
+ } else {
+ ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
+ }
+ }
+ } else {
+ // indirect dependencies
+ if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
+ if cc, ok := child.(*cc.Module); ok {
+ fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+ copyManifest[fileToCopy] = dirInApex
+ return true
+ }
+ }
+ }
+ return false
+ })
+
+ // files and dirs that will be created in apex
+ var readOnlyPaths []string
+ var executablePaths []string // this also includes dirs
+ for fileToCopy, dirInApex := range copyManifest {
+ pathInApex := filepath.Join(dirInApex, fileToCopy.Base())
+ if dirInApex == "bin" {
+ executablePaths = append(executablePaths, pathInApex)
+ } else {
+ readOnlyPaths = append(readOnlyPaths, pathInApex)
+ }
+ if !android.InList(dirInApex, executablePaths) {
+ executablePaths = append(executablePaths, dirInApex)
+ }
+ }
+ sort.Strings(readOnlyPaths)
+ sort.Strings(executablePaths)
+ cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ Rule: generateFsConfig,
+ Output: cannedFsConfig,
+ Args: map[string]string{
+ "ro_paths": strings.Join(readOnlyPaths, " "),
+ "exec_paths": strings.Join(executablePaths, " "),
+ },
+ })
+
+ manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "manifest.json"))
+ fileContexts := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.File_contexts, "file_contexts"))
+
+ a.outputFile = android.PathForModuleOut(ctx, a.ModuleBase.Name()+apexSuffix)
+
+ filesToCopy := []android.Path{}
+ for file := range copyManifest {
+ filesToCopy = append(filesToCopy, file)
+ }
+ sort.Slice(filesToCopy, func(i, j int) bool {
+ return filesToCopy[i].String() < filesToCopy[j].String()
+ })
+
+ copyCommands := []string{}
+ for _, src := range filesToCopy {
+ dest := filepath.Join(copyManifest[src], src.Base())
+ dest_path := filepath.Join(android.PathForModuleOut(ctx, "image").String(), dest)
+ copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
+ copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
+ }
+ implicitInputs := append(android.Paths(nil), filesToCopy...)
+ implicitInputs = append(implicitInputs, cannedFsConfig, manifest, fileContexts, keyFile)
+ outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
+ prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
+ ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+ Rule: apexRule,
+ Implicits: implicitInputs,
+ Output: a.outputFile,
+ Args: map[string]string{
+ "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+ "image_dir": android.PathForModuleOut(ctx, "image").String(),
+ "copy_commands": strings.Join(copyCommands, " && "),
+ "manifest": manifest.String(),
+ "file_contexts": fileContexts.String(),
+ "canned_fs_config": cannedFsConfig.String(),
+ "key": keyFile.String(),
+ },
+ })
+
+ a.installDir = android.PathForModuleInstall(ctx, "apex")
+}
+
+func (a *apexBundle) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
+ fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+ fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+ fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
+ fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexSuffix)
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
+ fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
+ }}
+}
+
+func apexBundleFactory() android.Module {
+ module := &apexBundle{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
diff --git a/apex/key.go b/apex/key.go
new file mode 100644
index 0000000..ff348a8
--- /dev/null
+++ b/apex/key.go
@@ -0,0 +1,88 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package apex
+
+import (
+ "fmt"
+ "io"
+
+ "android/soong/android"
+ "github.com/google/blueprint/proptools"
+)
+
+var String = proptools.String
+
+func init() {
+ android.RegisterModuleType("apex_key", apexKeyFactory)
+}
+
+type apexKey struct {
+ android.ModuleBase
+
+ properties apexKeyProperties
+
+ public_key_file android.Path
+ private_key_file android.Path
+
+ keyName string
+}
+
+type apexKeyProperties struct {
+ // Path to the public key file in avbpubkey format. Installed to the device.
+ // Base name of the file is used as the ID for the key.
+ Public_key *string
+ // Path to the private key file in pem format. Used to sign APEXs.
+ Private_key *string
+}
+
+func apexKeyFactory() android.Module {
+ module := &apexKey{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ return module
+}
+
+func (m *apexKey) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
+ m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
+
+ pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
+ privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
+
+ if pubKeyName != privKeyName {
+ ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
+ m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
+ return
+ }
+ m.keyName = pubKeyName
+
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "etc/security/apex"), m.keyName, m.public_key_file)
+}
+
+func (m *apexKey) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(m.public_key_file),
+ Extra: []android.AndroidMkExtraFunc{
+ func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_OUT)/etc/security/apex")
+ fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.keyName)
+ },
+ },
+ }
+}
diff --git a/build_test.bash b/build_test.bash
index 4c43224..ee979e7 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -27,6 +27,10 @@
# that's detected in the Go code, which skips calculating the startup time.
export TRACE_BEGIN_SOONG=$(date +%s%N)
+# Remove BUILD_NUMBER so that incremental builds on build servers don't
+# re-read makefiles every time.
+unset BUILD_NUMBER
+
export TOP=$(cd $(dirname ${BASH_SOURCE[0]})/../..; PWD= /bin/pwd)
cd "${TOP}"
source "${TOP}/build/soong/scripts/microfactory.bash"
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5daacb7..324b5bc 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -51,7 +51,7 @@
}
func (c *Module) AndroidMk() android.AndroidMkData {
- if c.Properties.HideFromMake {
+ if c.Properties.HideFromMake || !c.IsForPlatform() {
return android.AndroidMkData{
Disabled: true,
}
diff --git a/cc/binary.go b/cc/binary.go
index 07d503b..15db2ad 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -15,6 +15,8 @@
package cc
import (
+ "github.com/google/blueprint"
+
"android/soong/android"
)
@@ -154,7 +156,8 @@
}
if ctx.Os() == android.LinuxBionic && !binary.static() {
- deps.LinkerScript = "host_bionic_linker_script"
+ deps.DynamicLinker = "linker"
+ deps.LinkerFlagsFile = "host_bionic_linker_flags"
}
}
@@ -244,14 +247,23 @@
switch ctx.Os() {
case android.Android:
flags.DynamicLinker = "/system/bin/linker"
+ if flags.Toolchain.Is64Bit() {
+ flags.DynamicLinker += "64"
+ }
case android.LinuxBionic:
flags.DynamicLinker = ""
default:
ctx.ModuleErrorf("unknown dynamic linker")
}
- if flags.Toolchain.Is64Bit() {
- flags.DynamicLinker += "64"
- }
+ }
+
+ if ctx.Os() == android.LinuxBionic {
+ // Use the dlwrap entry point, but keep _start around so
+ // that it can be used by host_bionic_inject
+ flags.LdFlags = append(flags.LdFlags,
+ "-Wl,--entry=__dlwrap__start",
+ "-Wl,--undefined=_start",
+ )
}
}
@@ -262,7 +274,6 @@
"-Wl,--gc-sections",
"-Wl,-z,nocopyreloc",
)
-
}
} else {
if binary.static() {
@@ -288,13 +299,15 @@
sharedLibs := deps.SharedLibs
sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
- if deps.LinkerScript.Valid() {
- flags.LdFlags = append(flags.LdFlags, "-Wl,-T,"+deps.LinkerScript.String())
- linkerDeps = append(linkerDeps, deps.LinkerScript.Path())
+ if deps.LinkerFlagsFile.Valid() {
+ flags.LdFlags = append(flags.LdFlags, "$$(cat "+deps.LinkerFlagsFile.String()+")")
+ linkerDeps = append(linkerDeps, deps.LinkerFlagsFile.Path())
}
if flags.DynamicLinker != "" {
- flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+ flags.LdFlags = append(flags.LdFlags, "-Wl,-dynamic-linker,"+flags.DynamicLinker)
+ } else if ctx.toolchain().Bionic() && !binary.static() {
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--no-dynamic-linker")
}
builderFlags := flagsToBuilderFlags(flags)
@@ -302,8 +315,7 @@
if binary.stripper.needsStrip(ctx) {
// b/80093681, GNU strip/objcopy bug.
// Use llvm-{strip,objcopy} when clang lld is used.
- builderFlags.stripUseLlvmStrip =
- flags.Clang && binary.baseLinker.useClangLld(ctx)
+ builderFlags.stripUseLlvmStrip = binary.baseLinker.useClangLld(ctx)
strippedOutputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
@@ -324,6 +336,17 @@
binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
}
+ if ctx.Os() == android.LinuxBionic && !binary.static() {
+ injectedOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "prelinker", fileName)
+
+ if !deps.DynamicLinker.Valid() {
+ panic("Non-static host bionic modules must have a dynamic linker")
+ }
+
+ binary.injectHostBionicLinkerSymbols(ctx, outputFile, deps.DynamicLinker.Path(), injectedOutputFile)
+ }
+
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
linkerDeps = append(linkerDeps, objs.tidyFiles...)
@@ -368,3 +391,26 @@
func (binary *binaryDecorator) hostToolPath() android.OptionalPath {
return binary.toolPath
}
+
+func init() {
+ pctx.HostBinToolVariable("hostBionicSymbolsInjectCmd", "host_bionic_inject")
+}
+
+var injectHostBionicSymbols = pctx.AndroidStaticRule("injectHostBionicSymbols",
+ blueprint.RuleParams{
+ Command: "$hostBionicSymbolsInjectCmd -i $in -l $linker -o $out",
+ CommandDeps: []string{"$hostBionicSymbolsInjectCmd"},
+ }, "linker")
+
+func (binary *binaryDecorator) injectHostBionicLinkerSymbols(ctx ModuleContext, in, linker android.Path, out android.WritablePath) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: injectHostBionicSymbols,
+ Description: "inject host bionic symbols",
+ Input: in,
+ Implicit: linker,
+ Output: out,
+ Args: map[string]string{
+ "linker": linker.String(),
+ },
+ })
+}
diff --git a/cc/builder.go b/cc/builder.go
index 58196f4..3d12538 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -127,17 +127,6 @@
Command: "rm -f $out && touch $out",
})
- _ = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
-
- copyGccLib = pctx.AndroidStaticRule("copyGccLib",
- blueprint.RuleParams{
- Depfile: "${out}.d",
- Deps: blueprint.DepsGCC,
- Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
- CommandDeps: []string{"$copyGccLibPath", "$ccCmd"},
- },
- "ccCmd", "cFlags", "libName")
-
_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
toc = pctx.AndroidStaticRule("toc",
@@ -180,7 +169,7 @@
// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
sAbiDump = pctx.AndroidStaticRule("sAbiDump",
blueprint.RuleParams{
- Command: "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem ${config.RSIncludePath}",
+ Command: "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
CommandDeps: []string{"$sAbiDumper"},
},
"cFlags", "exportDirs")
@@ -202,11 +191,8 @@
func(ctx android.PackageRuleContext) blueprint.RuleParams {
// TODO(b/78139997): Add -check-all-apis back
commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -o ${out} -new $in -old $referenceDump)"
- distAbiDiffDir := android.PathForDist(ctx, "abidiffs")
commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
- if distAbiDiffDir.Valid() {
- commandStr += " && (mkdir -p " + distAbiDiffDir.String() + " && cp ${out} " + distAbiDiffDir.String() + ")"
- }
+ commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiff/)"
commandStr += " && exit 1)"
return blueprint.RuleParams{
Command: commandStr,
@@ -253,7 +239,6 @@
aidlFlags string
rsFlags string
toolchain config.Toolchain
- clang bool
tidy bool
coverage bool
sAbiDump bool
@@ -301,7 +286,7 @@
objFiles := make(android.Paths, len(srcFiles))
var tidyFiles android.Paths
- if flags.tidy && flags.clang {
+ if flags.tidy {
tidyFiles = make(android.Paths, 0, len(srcFiles))
}
var coverageFiles android.Paths
@@ -344,19 +329,14 @@
}, " ")
var sAbiDumpFiles android.Paths
- if flags.sAbiDump && flags.clang {
+ if flags.sAbiDump {
sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
}
- if flags.clang {
- cflags += " ${config.NoOverrideClangGlobalCflags}"
- toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
- cppflags += " ${config.NoOverrideClangGlobalCflags}"
- toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
- } else {
- cflags += " ${config.NoOverrideGlobalCflags}"
- cppflags += " ${config.NoOverrideGlobalCflags}"
- }
+ cflags += " ${config.NoOverrideClangGlobalCflags}"
+ toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
+ cppflags += " ${config.NoOverrideClangGlobalCflags}"
+ toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
for i, srcFile := range srcFiles {
objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
@@ -396,23 +376,23 @@
var moduleCflags string
var moduleToolingCflags string
var ccCmd string
- tidy := flags.tidy && flags.clang
+ tidy := flags.tidy
coverage := flags.coverage
- dump := flags.sAbiDump && flags.clang
+ dump := flags.sAbiDump
switch srcFile.Ext() {
case ".S", ".s":
- ccCmd = "gcc"
+ ccCmd = "clang"
moduleCflags = asflags
tidy = false
coverage = false
dump = false
case ".c":
- ccCmd = "gcc"
+ ccCmd = "clang"
moduleCflags = cflags
moduleToolingCflags = toolingCflags
case ".cpp", ".cc", ".mm":
- ccCmd = "g++"
+ ccCmd = "clang++"
moduleCflags = cppflags
moduleToolingCflags = toolingCppflags
default:
@@ -420,24 +400,9 @@
continue
}
- if flags.clang {
- switch ccCmd {
- case "gcc":
- ccCmd = "clang"
- case "g++":
- ccCmd = "clang++"
- default:
- panic("unrecoginzied ccCmd")
- }
- }
-
ccDesc := ccCmd
- if flags.clang {
- ccCmd = "${config.ClangBin}/" + ccCmd
- } else {
- ccCmd = gccCmd(flags.toolchain, ccCmd)
- }
+ ccCmd = "${config.ClangBin}/" + ccCmd
var implicitOutputs android.WritablePaths
if coverage {
@@ -622,12 +587,7 @@
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
- var ldCmd string
- if flags.clang {
- ldCmd = "${config.ClangBin}/clang++"
- } else {
- ldCmd = gccCmd(flags.toolchain, "g++")
- }
+ ldCmd := "${config.ClangBin}/clang++"
var libFlagsList []string
@@ -788,12 +748,7 @@
func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
flags builderFlags, outputFile android.WritablePath) {
- var ldCmd string
- if flags.clang {
- ldCmd = "${config.ClangBin}/clang++"
- } else {
- ldCmd = gccCmd(flags.toolchain, "g++")
- }
+ ldCmd := "${config.ClangBin}/clang++"
ctx.Build(pctx, android.BuildParams{
Rule: partialLd,
@@ -880,21 +835,6 @@
return android.OptionalPath{}
}
-func CopyGccLib(ctx android.ModuleContext, libName string,
- flags builderFlags, outputFile android.WritablePath) {
-
- ctx.Build(pctx, android.BuildParams{
- Rule: copyGccLib,
- Description: "copy gcc library " + libName,
- Output: outputFile,
- Args: map[string]string{
- "ccCmd": gccCmd(flags.toolchain, "gcc"),
- "cFlags": flags.globalFlags,
- "libName": libName,
- },
- })
-}
-
func gccCmd(toolchain config.Toolchain, cmd string) string {
return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
}
diff --git a/cc/cc.go b/cc/cc.go
index d31a38a..8b68489 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -35,11 +35,11 @@
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("image", imageMutator).Parallel()
- ctx.BottomUp("link", linkageMutator).Parallel()
+ ctx.BottomUp("link", LinkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
- ctx.BottomUp("begin", beginMutator).Parallel()
+ ctx.BottomUp("begin", BeginMutator).Parallel()
})
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -83,7 +83,10 @@
ReexportGeneratedHeaders []string
CrtBegin, CrtEnd string
- LinkerScript string
+
+ // Used for host bionic
+ LinkerFlagsFile string
+ DynamicLinker string
}
type PathDeps struct {
@@ -108,7 +111,12 @@
// Paths to crt*.o files
CrtBegin, CrtEnd android.OptionalPath
- LinkerScript android.OptionalPath
+
+ // Path to the file container flags to use with the linker
+ LinkerFlagsFile android.OptionalPath
+
+ // Path to the dynamic linker binary
+ DynamicLinker android.OptionalPath
}
type Flags struct {
@@ -136,7 +144,6 @@
SystemIncludeFlags []string
Toolchain config.Toolchain
- Clang bool
Tidy bool
Coverage bool
SAbiDump bool
@@ -165,9 +172,6 @@
// Deprecated. true is the default, false is invalid.
Clang *bool `android:"arch_variant"`
- // Some internals still need GCC (toolchain_library)
- Gcc bool `blueprint:"mutated"`
-
// Minimum sdk version supported when compiling against the ndk
Sdk_version *string
@@ -220,7 +224,6 @@
type ModuleContextIntf interface {
static() bool
staticBinary() bool
- clang() bool
toolchain() config.Toolchain
useSdk() bool
sdkVersion() string
@@ -311,7 +314,8 @@
objDepTag = dependencyTag{name: "obj"}
crtBeginDepTag = dependencyTag{name: "crtbegin"}
crtEndDepTag = dependencyTag{name: "crtend"}
- linkerScriptDepTag = dependencyTag{name: "linker script"}
+ linkerFlagsDepTag = dependencyTag{name: "linker flags file"}
+ dynamicLinkerDepTag = dependencyTag{name: "dynamic linker"}
reuseObjTag = dependencyTag{name: "reuse objects"}
ndkStubDepTag = dependencyTag{name: "ndk stub", library: true}
ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true}
@@ -325,6 +329,7 @@
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.ApexModuleBase
Properties BaseProperties
VendorProperties VendorProperties
@@ -406,10 +411,23 @@
c.AddProperties(feature.props()...)
}
+ c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
+ switch class {
+ case android.Device:
+ return ctx.Config().DevicePrefer32BitExecutables()
+ case android.HostCross:
+ // Windows builds always prefer 32-bit
+ return true
+ default:
+ return false
+ }
+ })
android.InitAndroidArchModule(c, c.hod, c.multilib)
android.InitDefaultableModule(c)
+ android.InitApexModule(c)
+
return c
}
@@ -502,10 +520,6 @@
ctx BaseModuleContext
}
-func (ctx *moduleContextImpl) clang() bool {
- return ctx.mod.clang(ctx.ctx)
-}
-
func (ctx *moduleContextImpl) toolchain() config.Toolchain {
return ctx.mod.toolchain(ctx.ctx)
}
@@ -722,9 +736,12 @@
return
}
+ if c.Properties.Clang != nil && *c.Properties.Clang == false {
+ ctx.PropertyErrorf("clang", "false (GCC) is no longer supported")
+ }
+
flags := Flags{
Toolchain: c.toolchain(ctx),
- Clang: c.clang(ctx),
}
if c.compiler != nil {
flags = c.compiler.compilerFlags(ctx, flags, deps)
@@ -789,7 +806,7 @@
c.outputFile = android.OptionalPathForPath(outputFile)
}
- if c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() {
+ if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
c.installer.install(ctx, c.outputFile.Path())
if ctx.Failed() {
return
@@ -1054,8 +1071,11 @@
if deps.CrtEnd != "" {
actx.AddVariationDependencies(nil, crtEndDepTag, deps.CrtEnd)
}
- if deps.LinkerScript != "" {
- actx.AddDependency(c, linkerScriptDepTag, deps.LinkerScript)
+ if deps.LinkerFlagsFile != "" {
+ actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
+ }
+ if deps.DynamicLinker != "" {
+ actx.AddDependency(c, dynamicLinkerDepTag, deps.DynamicLinker)
}
version := ctx.sdkVersion()
@@ -1082,20 +1102,12 @@
}
}
-func beginMutator(ctx android.BottomUpMutatorContext) {
+func BeginMutator(ctx android.BottomUpMutatorContext) {
if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
c.beginMutator(ctx)
}
}
-func (c *Module) clang(ctx BaseModuleContext) bool {
- if c.Properties.Clang != nil && *c.Properties.Clang == false {
- ctx.PropertyErrorf("clang", "false (GCC) is no longer supported")
- }
-
- return !c.Properties.Gcc
-}
-
// Whether a module can link to another module, taking into
// account NDK linking.
func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag dependencyTag) {
@@ -1257,13 +1269,13 @@
} else {
ctx.ModuleErrorf("module %q is not a genrule", depName)
}
- case linkerScriptDepTag:
+ case linkerFlagsDepTag:
if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
files := genRule.GeneratedSourceFiles()
if len(files) == 1 {
- depPaths.LinkerScript = android.OptionalPathForPath(files[0])
+ depPaths.LinkerFlagsFile = android.OptionalPathForPath(files[0])
} else if len(files) > 1 {
- ctx.ModuleErrorf("module %q can only generate a single file if used for a linker script", depName)
+ ctx.ModuleErrorf("module %q can only generate a single file if used for a linker flag file", depName)
}
} else {
ctx.ModuleErrorf("module %q is not a genrule", depName)
@@ -1358,6 +1370,8 @@
depPaths.CrtBegin = linkFile
case crtEndDepTag:
depPaths.CrtEnd = linkFile
+ case dynamicLinkerDepTag:
+ depPaths.DynamicLinker = linkFile
}
switch depTag {
@@ -1514,12 +1528,24 @@
}
}
+// Overrides ApexModule.IsInstallabeToApex()
+// Only shared libraries are installable to APEX.
+func (c *Module) IsInstallableToApex() bool {
+ if shared, ok := c.linker.(interface {
+ shared() bool
+ }); ok {
+ return shared.shared()
+ }
+ return false
+}
+
//
// Defaults
//
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
+ android.ApexModuleBase
}
func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1561,6 +1587,7 @@
)
android.InitDefaultsModule(module)
+ android.InitApexModule(module)
return module
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3d5dfb1..ead89f6 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -56,17 +56,17 @@
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
- ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(ToolchainLibraryFactory))
ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
- ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
+ ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(ObjectFactory))
ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("image", imageMutator).Parallel()
- ctx.BottomUp("link", linkageMutator).Parallel()
+ ctx.BottomUp("link", LinkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel()
- ctx.BottomUp("begin", beginMutator).Parallel()
+ ctx.BottomUp("begin", BeginMutator).Parallel()
})
ctx.Register()
@@ -76,18 +76,49 @@
name: "libatomic",
vendor_available: true,
recovery_available: true,
+ src: "",
}
toolchain_library {
name: "libcompiler_rt-extras",
vendor_available: true,
recovery_available: true,
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-arm-android",
+ vendor_available: true,
+ recovery_available: true,
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-aarch64-android",
+ vendor_available: true,
+ recovery_available: true,
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-i686-android",
+ vendor_available: true,
+ recovery_available: true,
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-x86_64-android",
+ vendor_available: true,
+ recovery_available: true,
+ src: "",
}
toolchain_library {
name: "libgcc",
vendor_available: true,
recovery_available: true,
+ src: "",
}
cc_library {
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index a2f46cd..7b4f89b 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -18,7 +18,6 @@
"fmt"
"android/soong/android"
- "android/soong/cc/config"
"os"
"path"
"path/filepath"
@@ -150,18 +149,10 @@
f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", getAndroidSrcRootDirectory(ctx)))
- if ccModule.flags.Clang {
- pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
- f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
- f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))
- } else {
- toolchain := config.FindToolchain(ccModule.Os(), ccModule.Arch())
- root, _ := evalVariable(ctx, toolchain.GccRoot())
- triple, _ := evalVariable(ctx, toolchain.GccTriple())
- pathToCC := filepath.Join(root, "bin", triple+"-")
- f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "gcc"))
- f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "g++"))
- }
+ pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
+ f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
+ f.WriteString(fmt.Sprintf("set(CMAKE_CXX_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang++"))
+
// Add all sources to the project.
f.WriteString("list(APPEND\n")
f.WriteString(" SOURCE_FILES\n")
@@ -204,10 +195,11 @@
writeAllIncludeDirectories(c.systemHeaderSearchPath, f, true)
writeAllIncludeDirectories(c.headerSearchPath, f, false)
if cflags {
+ writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_C_FLAGS")
writeAllFlags(c.flags, f, "CMAKE_C_FLAGS")
}
-
if cppflags {
+ writeAllRelativeFilePathFlags(c.relativeFilePathFlags, f, "CMAKE_CXX_FLAGS")
writeAllFlags(c.flags, f, "CMAKE_CXX_FLAGS")
}
if c.sysroot != "" {
@@ -249,6 +241,17 @@
f.WriteString("list (APPEND SOURCE_FILES ${TMP_HEADERS})\n\n")
}
+type relativeFilePathFlagType struct {
+ flag string
+ relativeFilePath string
+}
+
+func writeAllRelativeFilePathFlags(relativeFilePathFlags []relativeFilePathFlagType, f *os.File, tag string) {
+ for _, flag := range relativeFilePathFlags {
+ f.WriteString(fmt.Sprintf("set(%s \"${%s} %s=%s\")\n", tag, tag, flag.flag, buildCMakePath(flag.relativeFilePath)))
+ }
+}
+
func writeAllFlags(flags []string, f *os.File, tag string) {
for _, flag := range flags {
f.WriteString(fmt.Sprintf("set(%s \"${%s} %s\")\n", tag, tag, flag))
@@ -263,6 +266,7 @@
systemHeaderSearchPath
flag
systemRoot
+ relativeFilePathFlag
)
type compilerParameters struct {
@@ -270,6 +274,8 @@
systemHeaderSearchPath []string
flags []string
sysroot string
+ // Must be in a=b/c/d format and can be split into "a" and "b/c/d"
+ relativeFilePathFlags []relativeFilePathFlagType
}
func makeCompilerParameters() compilerParameters {
@@ -294,6 +300,9 @@
if strings.HasPrefix(parameter, "--sysroot") {
return systemRoot
}
+ if strings.HasPrefix(parameter, "-fsanitize-blacklist") {
+ return relativeFilePathFlag
+ }
return flag
}
@@ -347,6 +356,16 @@
f.WriteString("# Found a system root path marker with no path")
}
i = i + 1
+ case relativeFilePathFlag:
+ flagComponents := strings.Split(param, "=")
+ if len(flagComponents) == 2 {
+ flagStruct := relativeFilePathFlagType{flag: flagComponents[0], relativeFilePath: flagComponents[1]}
+ compilerParameters.relativeFilePathFlags = append(compilerParameters.relativeFilePathFlags, flagStruct)
+ } else {
+ if outputDebugInfo {
+ f.WriteString(fmt.Sprintf("# Relative File Path Flag [%s] is not formatted as a=b/c/d \n", param))
+ }
+ }
}
}
return compilerParameters
diff --git a/cc/compdb.go b/cc/compdb.go
index a9c5b5e..acfc924 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -181,7 +181,7 @@
func evalAndSplitVariable(ctx android.SingletonContext, str string) ([]string, error) {
evaluated, err := ctx.Eval(pctx, str)
if err == nil {
- return strings.Split(evaluated, " "), nil
+ return strings.Fields(evaluated), nil
}
return []string{""}, err
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 5ef9e4e..68d8593 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -340,10 +340,7 @@
if flags.RequiredInstructionSet != "" {
instructionSet = flags.RequiredInstructionSet
}
- instructionSetFlags, err := tc.InstructionSetFlags(instructionSet)
- if flags.Clang {
- instructionSetFlags, err = tc.ClangInstructionSetFlags(instructionSet)
- }
+ instructionSetFlags, err := tc.ClangInstructionSetFlags(instructionSet)
if err != nil {
ctx.ModuleErrorf("%s", err)
}
@@ -353,24 +350,22 @@
// TODO: debug
flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Release.Cflags)...)
- if flags.Clang {
- CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
- CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+ CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+ CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
- flags.CFlags = config.ClangFilterUnknownCflags(flags.CFlags)
- flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Clang_cflags)...)
- flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Clang_asflags)...)
- flags.CppFlags = config.ClangFilterUnknownCflags(flags.CppFlags)
- flags.ConlyFlags = config.ClangFilterUnknownCflags(flags.ConlyFlags)
- flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags)
+ flags.CFlags = config.ClangFilterUnknownCflags(flags.CFlags)
+ flags.CFlags = append(flags.CFlags, esc(compiler.Properties.Clang_cflags)...)
+ flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+ flags.CppFlags = config.ClangFilterUnknownCflags(flags.CppFlags)
+ flags.ConlyFlags = config.ClangFilterUnknownCflags(flags.ConlyFlags)
+ flags.LdFlags = config.ClangFilterUnknownCflags(flags.LdFlags)
- target := "-target " + tc.ClangTriple()
- gccPrefix := "-B" + config.ToolPath(tc)
+ target := "-target " + tc.ClangTriple()
+ gccPrefix := "-B" + config.ToolPath(tc)
- flags.CFlags = append(flags.CFlags, target, gccPrefix)
- flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
- flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
- }
+ flags.CFlags = append(flags.CFlags, target, gccPrefix)
+ flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
+ flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
hod := "Host"
if ctx.Os().Class == android.Device {
@@ -381,25 +376,15 @@
flags.ConlyFlags = append([]string{"${config.CommonGlobalConlyflags}"}, flags.ConlyFlags...)
flags.CppFlags = append([]string{fmt.Sprintf("${config.%sGlobalCppflags}", hod)}, flags.CppFlags...)
- if flags.Clang {
- flags.AsFlags = append(flags.AsFlags, tc.ClangAsflags())
- flags.CppFlags = append([]string{"${config.CommonClangGlobalCppflags}"}, flags.CppFlags...)
- flags.GlobalFlags = append(flags.GlobalFlags,
- tc.ClangCflags(),
- "${config.CommonClangGlobalCflags}",
- fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
- } else {
- flags.CppFlags = append([]string{"${config.CommonGlobalCppflags}"}, flags.CppFlags...)
- flags.GlobalFlags = append(flags.GlobalFlags,
- tc.Cflags(),
- "${config.CommonGlobalCflags}",
- fmt.Sprintf("${config.%sGlobalCflags}", hod))
- }
+ flags.AsFlags = append(flags.AsFlags, tc.ClangAsflags())
+ flags.CppFlags = append([]string{"${config.CommonClangGlobalCppflags}"}, flags.CppFlags...)
+ flags.GlobalFlags = append(flags.GlobalFlags,
+ tc.ClangCflags(),
+ "${config.CommonClangGlobalCflags}",
+ fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
- if flags.Clang {
- if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
- flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...)
- }
+ if strings.HasPrefix(android.PathForModuleSrc(ctx).String(), "external/") {
+ flags.GlobalFlags = append([]string{"${config.ClangExternalCflags}"}, flags.GlobalFlags...)
}
if ctx.Device() {
@@ -412,19 +397,11 @@
flags.AsFlags = append(flags.AsFlags, "-D__ASSEMBLY__")
- if flags.Clang {
- flags.CppFlags = append(flags.CppFlags, tc.ClangCppflags())
- } else {
- flags.CppFlags = append(flags.CppFlags, tc.Cppflags())
- }
+ flags.CppFlags = append(flags.CppFlags, tc.ClangCppflags())
flags.YasmFlags = append(flags.YasmFlags, tc.YasmFlags())
- if flags.Clang {
- flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainClangCflags())
- } else {
- flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainCflags())
- }
+ flags.GlobalFlags = append(flags.GlobalFlags, tc.ToolchainClangCflags())
cStd := config.CStdVersion
if String(compiler.Properties.C_std) == "experimental" {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 12e9114..6a63828 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -48,7 +48,7 @@
arm64Cppflags = []string{}
- arm64CpuVariantCflags = map[string][]string{
+ arm64ClangCpuVariantCflags = map[string][]string{
"cortex-a53": []string{
"-mcpu=cortex-a53",
},
@@ -60,10 +60,13 @@
// core (cortex-a55) and is sensitive to ordering.
"-mcpu=cortex-a55",
},
+ "cortex-a76": []string{
+ // Use the cortex-a55 since it is similar to the little
+ // core (cortex-a55) and is sensitive to ordering.
+ "-mcpu=cortex-a55",
+ },
"kryo": []string{
- // Use the cortex-a57 cpu since some compilers
- // don't support a Kryo specific target yet.
- "-mcpu=cortex-a57",
+ "-mcpu=kryo",
},
"exynos-m1": []string{
"-mcpu=exynos-m1",
@@ -72,8 +75,6 @@
"-mcpu=exynos-m2",
},
}
-
- arm64ClangCpuVariantCflags = copyVariantFlags(arm64CpuVariantCflags)
)
const (
@@ -89,23 +90,19 @@
"cortex-a72",
"cortex-a73",
"cortex-a75",
+ "cortex-a76",
"kryo",
"exynos-m1",
"exynos-m2",
"denver64")
- // Clang supports specific Kryo targeting
- replaceFirst(arm64ClangCpuVariantCflags["kryo"], "-mcpu=cortex-a57", "-mcpu=kryo")
-
pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
pctx.SourcePathVariable("Arm64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
- pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
pctx.StaticVariable("Arm64Lldflags", strings.Join(arm64Lldflags, " "))
- pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
pctx.StaticVariable("Arm64IncludeFlags", bionicHeaders("arm64"))
pctx.StaticVariable("Arm64ClangCflags", strings.Join(ClangFilterUnknownCflags(arm64Cflags), " "))
@@ -116,45 +113,23 @@
pctx.StaticVariable("Arm64ClangArmv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
pctx.StaticVariable("Arm64ClangArmv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
- pctx.StaticVariable("Arm64CortexA53Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
pctx.StaticVariable("Arm64ClangCortexA53Cflags",
strings.Join(arm64ClangCpuVariantCflags["cortex-a53"], " "))
- pctx.StaticVariable("Arm64CortexA55Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
pctx.StaticVariable("Arm64ClangCortexA55Cflags",
strings.Join(arm64ClangCpuVariantCflags["cortex-a55"], " "))
- pctx.StaticVariable("Arm64KryoCflags",
- strings.Join(arm64CpuVariantCflags["kryo"], " "))
pctx.StaticVariable("Arm64ClangKryoCflags",
strings.Join(arm64ClangCpuVariantCflags["kryo"], " "))
- pctx.StaticVariable("Arm64ExynosM1Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
pctx.StaticVariable("Arm64ClangExynosM1Cflags",
strings.Join(arm64ClangCpuVariantCflags["exynos-m1"], " "))
- pctx.StaticVariable("Arm64ExynosM2Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
pctx.StaticVariable("Arm64ClangExynosM2Cflags",
strings.Join(arm64ClangCpuVariantCflags["exynos-m2"], " "))
}
var (
- arm64CpuVariantCflagsVar = map[string]string{
- "": "",
- "cortex-a53": "${config.Arm64CortexA53Cflags}",
- "cortex-a55": "${config.Arm64CortexA55Cflags}",
- "cortex-a72": "${config.Arm64CortexA53Cflags}",
- "cortex-a73": "${config.Arm64CortexA53Cflags}",
- "cortex-a75": "${config.Arm64CortexA55Cflags}",
- "kryo": "${config.Arm64KryoCflags}",
- "exynos-m1": "${config.Arm64ExynosM1Cflags}",
- "exynos-m2": "${config.Arm64ExynosM2Cflags}",
- }
-
arm64ClangArchVariantCflagsVar = map[string]string{
"armv8-a": "${config.Arm64ClangArmv8ACflags}",
"armv8-2a": "${config.Arm64ClangArmv82ACflags}",
@@ -167,6 +142,7 @@
"cortex-a72": "${config.Arm64ClangCortexA53Cflags}",
"cortex-a73": "${config.Arm64ClangCortexA53Cflags}",
"cortex-a75": "${config.Arm64ClangCortexA55Cflags}",
+ "cortex-a76": "${config.Arm64ClangCortexA55Cflags}",
"kryo": "${config.Arm64ClangKryoCflags}",
"exynos-m1": "${config.Arm64ClangExynosM1Cflags}",
"exynos-m2": "${config.Arm64ClangExynosM2Cflags}",
@@ -177,7 +153,7 @@
toolchain64Bit
ldflags string
- toolchainCflags string
+ lldflags string
toolchainClangCflags string
}
@@ -197,22 +173,6 @@
return arm64GccVersion
}
-func (t *toolchainArm64) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainArm64) Cflags() string {
- return "${config.Arm64Cflags}"
-}
-
-func (t *toolchainArm64) Cppflags() string {
- return "${config.Arm64Cppflags}"
-}
-
-func (t *toolchainArm64) Ldflags() string {
- return t.ldflags
-}
-
func (t *toolchainArm64) IncludeFlags() string {
return "${config.Arm64IncludeFlags}"
}
@@ -234,7 +194,7 @@
}
func (t *toolchainArm64) ClangLldflags() string {
- return "${config.Arm64Lldflags}"
+ return t.lldflags
}
func (t *toolchainArm64) ToolchainClangCflags() string {
@@ -272,7 +232,10 @@
"${config.Arm64Ldflags}",
extraLdflags,
}, " "),
- toolchainCflags: variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant),
+ lldflags: strings.Join([]string{
+ "${config.Arm64Lldflags}",
+ extraLdflags,
+ }, " "),
toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
}
}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index c1c2c7b..75f5962 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -50,7 +50,7 @@
"-Os",
}
- armArchVariantCflags = map[string][]string{
+ armClangArchVariantCflags = map[string][]string{
"armv7-a": []string{
"-march=armv7-a",
"-mfloat-abi=softfp",
@@ -68,7 +68,7 @@
},
}
- armCpuVariantCflags = map[string][]string{
+ armClangCpuVariantCflags = map[string][]string{
"cortex-a7": []string{
"-mcpu=cortex-a7",
"-mfpu=neon-vfpv4",
@@ -117,8 +117,17 @@
// better solution comes around. See Bug 27340895
"-D__ARM_FEATURE_LPAE=1",
},
+ "cortex-a76": []string{
+ "-mcpu=cortex-a55",
+ "-mfpu=neon-fp-armv8",
+ // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // don't advertise.
+ // TODO This is a hack and we need to add it for each processor that supports LPAE until some
+ // better solution comes around. See Bug 27340895
+ "-D__ARM_FEATURE_LPAE=1",
+ },
"krait": []string{
- "-mcpu=cortex-a15",
+ "-mcpu=krait",
"-mfpu=neon-vfpv4",
// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
// don't advertise.
@@ -138,9 +147,6 @@
"-D__ARM_FEATURE_LPAE=1",
},
}
-
- armClangCpuVariantCflags = copyVariantFlags(armCpuVariantCflags)
- armClangArchVariantCflags = copyVariantFlags(armArchVariantCflags)
)
const (
@@ -165,6 +171,7 @@
"cortex-a72",
"cortex-a73",
"cortex-a75",
+ "cortex-a76",
"krait",
"kryo",
"exynos-m1",
@@ -174,49 +181,15 @@
android.RegisterArchVariantFeatures(android.Arm, "armv7-a-neon", "neon")
android.RegisterArchVariantFeatures(android.Arm, "armv8-a", "neon")
- // Krait is not supported by GCC, but is supported by Clang, so
- // override the definitions when building modules with Clang.
- replaceFirst(armClangCpuVariantCflags["krait"], "-mcpu=cortex-a15", "-mcpu=krait")
-
- // The reason we use "-march=armv8-a+crc", instead of "-march=armv8-a", for
- // gcc is the latter would conflict with any specified/supported -mcpu!
- // All armv8-a cores supported by gcc 4.9 support crc, so it's safe
- // to add +crc. Besides, the use of gcc is only for legacy code.
- replaceFirst(armArchVariantCflags["armv8-a"], "-march=armv8-a", "-march=armv8-a+crc")
-
pctx.StaticVariable("armGccVersion", armGccVersion)
pctx.SourcePathVariable("ArmGccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
- pctx.StaticVariable("ArmToolchainCflags", strings.Join(armToolchainCflags, " "))
- pctx.StaticVariable("ArmCflags", strings.Join(armCflags, " "))
pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
pctx.StaticVariable("ArmLldflags", strings.Join(armLldflags, " "))
- pctx.StaticVariable("ArmCppflags", strings.Join(armCppflags, " "))
pctx.StaticVariable("ArmIncludeFlags", bionicHeaders("arm"))
- // Extended cflags
-
- // ARM vs. Thumb instruction set flags
- pctx.StaticVariable("ArmArmCflags", strings.Join(armArmCflags, " "))
- pctx.StaticVariable("ArmThumbCflags", strings.Join(armThumbCflags, " "))
-
- // Architecture variant cflags
- pctx.StaticVariable("ArmArmv7ACflags", strings.Join(armArchVariantCflags["armv7-a"], " "))
- pctx.StaticVariable("ArmArmv7ANeonCflags", strings.Join(armArchVariantCflags["armv7-a-neon"], " "))
- pctx.StaticVariable("ArmArmv8ACflags", strings.Join(armArchVariantCflags["armv8-a"], " "))
-
- // Cpu variant cflags
- pctx.StaticVariable("ArmGenericCflags", strings.Join(armCpuVariantCflags[""], " "))
- pctx.StaticVariable("ArmCortexA7Cflags", strings.Join(armCpuVariantCflags["cortex-a7"], " "))
- pctx.StaticVariable("ArmCortexA8Cflags", strings.Join(armCpuVariantCflags["cortex-a8"], " "))
- pctx.StaticVariable("ArmCortexA15Cflags", strings.Join(armCpuVariantCflags["cortex-a15"], " "))
- pctx.StaticVariable("ArmCortexA53Cflags", strings.Join(armCpuVariantCflags["cortex-a53"], " "))
- pctx.StaticVariable("ArmCortexA55Cflags", strings.Join(armCpuVariantCflags["cortex-a55"], " "))
- pctx.StaticVariable("ArmKraitCflags", strings.Join(armCpuVariantCflags["krait"], " "))
- pctx.StaticVariable("ArmKryoCflags", strings.Join(armCpuVariantCflags["kryo"], " "))
-
// Clang cflags
pctx.StaticVariable("ArmToolchainClangCflags", strings.Join(ClangFilterUnknownCflags(armToolchainCflags), " "))
pctx.StaticVariable("ArmClangCflags", strings.Join(ClangFilterUnknownCflags(armCflags), " "))
@@ -256,30 +229,6 @@
}
var (
- armArchVariantCflagsVar = map[string]string{
- "armv7-a": "${config.ArmArmv7ACflags}",
- "armv7-a-neon": "${config.ArmArmv7ANeonCflags}",
- "armv8-a": "${config.ArmArmv8ACflags}",
- }
-
- armCpuVariantCflagsVar = map[string]string{
- "": "${config.ArmGenericCflags}",
- "cortex-a7": "${config.ArmCortexA7Cflags}",
- "cortex-a8": "${config.ArmCortexA8Cflags}",
- "cortex-a15": "${config.ArmCortexA15Cflags}",
- "cortex-a53": "${config.ArmCortexA53Cflags}",
- "cortex-a53.a57": "${config.ArmCortexA53Cflags}",
- "cortex-a55": "${config.ArmCortexA55Cflags}",
- "cortex-a72": "${config.ArmCortexA53Cflags}",
- "cortex-a73": "${config.ArmCortexA53Cflags}",
- "cortex-a75": "${config.ArmCortexA55Cflags}",
- "krait": "${config.ArmKraitCflags}",
- "kryo": "${config.ArmKryoCflags}",
- "exynos-m1": "${config.ArmCortexA53Cflags}",
- "exynos-m2": "${config.ArmCortexA53Cflags}",
- "denver": "${config.ArmCortexA15Cflags}",
- }
-
armClangArchVariantCflagsVar = map[string]string{
"armv7-a": "${config.ArmClangArmv7ACflags}",
"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
@@ -307,9 +256,9 @@
type toolchainArm struct {
toolchain32Bit
- ldflags string
- lldflags string
- toolchainCflags, toolchainClangCflags string
+ ldflags string
+ lldflags string
+ toolchainClangCflags string
}
func (t *toolchainArm) Name() string {
@@ -328,37 +277,10 @@
return armGccVersion
}
-func (t *toolchainArm) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainArm) Cflags() string {
- return "${config.ArmCflags}"
-}
-
-func (t *toolchainArm) Cppflags() string {
- return "${config.ArmCppflags}"
-}
-
-func (t *toolchainArm) Ldflags() string {
- return t.ldflags
-}
-
func (t *toolchainArm) IncludeFlags() string {
return "${config.ArmIncludeFlags}"
}
-func (t *toolchainArm) InstructionSetFlags(isa string) (string, error) {
- switch isa {
- case "arm":
- return "${config.ArmArmCflags}", nil
- case "thumb", "":
- return "${config.ArmThumbCflags}", nil
- default:
- return t.toolchainBase.InstructionSetFlags(isa)
- }
-}
-
func (t *toolchainArm) ClangTriple() string {
// http://b/72619014 work around llvm LTO bug.
return "armv7a-linux-androideabi"
@@ -406,16 +328,11 @@
func armToolchainFactory(arch android.Arch) Toolchain {
var fixCortexA8 string
- toolchainCflags := make([]string, 2, 3)
toolchainClangCflags := make([]string, 2, 3)
- toolchainCflags[0] = "${config.ArmToolchainCflags}"
- toolchainCflags[1] = armArchVariantCflagsVar[arch.ArchVariant]
toolchainClangCflags[0] = "${config.ArmToolchainClangCflags}"
toolchainClangCflags[1] = armClangArchVariantCflagsVar[arch.ArchVariant]
- toolchainCflags = append(toolchainCflags,
- variantOrDefault(armCpuVariantCflagsVar, arch.CpuVariant))
toolchainClangCflags = append(toolchainClangCflags,
variantOrDefault(armClangCpuVariantCflagsVar, arch.CpuVariant))
@@ -437,7 +354,6 @@
}
return &toolchainArm{
- toolchainCflags: strings.Join(toolchainCflags, " "),
ldflags: strings.Join([]string{
"${config.ArmLdflags}",
fixCortexA8,
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 186d790..5c82604 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -92,17 +92,16 @@
"-Wl,-m,aarch64_elf64_le_vec",
})
-var ClangLibToolingUnknownCflags = []string{
- // Remove -flto and other flto dependent flags.
- "-flto*",
- "-fsanitize*",
- "-fwhole-program-vtables",
-}
+var ClangLibToolingUnknownCflags []string = nil
func init() {
pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
"-D__compiler_offsetof=__builtin_offsetof",
+ // Make implicit fallthrough an error in the future.
+ "-Wimplicit-fallthrough",
+ "-Wno-error=implicit-fallthrough",
+
// Help catch common 32/64-bit errors.
"-Werror=int-conversion",
@@ -175,16 +174,31 @@
// this new warning are fixed.
"-Wno-null-pointer-arithmetic",
+ // http://b/72330874 Disable -Wenum-compare until the instances detected by this new
+ // warning are fixed.
+ "-Wno-enum-compare",
+ "-Wno-enum-compare-switch",
+
// Disable c++98-specific warning since Android is not concerned with C++98
// compatibility.
"-Wno-c++98-compat-extra-semi",
+
+ // Disable this warning until we can fix all instances where it fails.
+ "-Wno-self-assign-overloaded",
+
+ // Disable this warning until we can fix all instances where it fails.
+ "-Wno-constant-logical-operand",
+
+ // Disable this warning because we don't care about behavior with older compilers.
+ "-Wno-return-std-move-in-c++11",
+
+ // Disable this warning until we can fix all instances where it fails.
+ "-Wno-dangling-field",
}, " "))
- // Extra cflags for projects under external/ directory to disable warnings that are infeasible
- // to fix in all the external projects and their upstream repos.
+ // Extra cflags for projects under external/ directory
pctx.StaticVariable("ClangExtraExternalCflags", strings.Join([]string{
- "-Wno-enum-compare",
- "-Wno-enum-compare-switch",
+ // TODO(yikong): Move -Wno flags here
}, " "))
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 000aab6..330cb10 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -15,7 +15,6 @@
package config
import (
- "fmt"
"runtime"
"strings"
@@ -126,8 +125,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r328903"
- ClangDefaultShortVersion = "7.0.2"
+ ClangDefaultVersion = "clang-r339409b"
+ ClangDefaultShortVersion = "8.0.2"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -146,19 +145,13 @@
commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
}
- pctx.StaticVariable("CommonGlobalCflags", strings.Join(commonGlobalCflags, " "))
pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " "))
- pctx.StaticVariable("DeviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " "))
pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " "))
pctx.StaticVariable("DeviceGlobalLldflags", strings.Join(deviceGlobalLldflags, " "))
- pctx.StaticVariable("HostGlobalCflags", strings.Join(hostGlobalCflags, " "))
pctx.StaticVariable("HostGlobalCppflags", strings.Join(hostGlobalCppflags, " "))
pctx.StaticVariable("HostGlobalLdflags", strings.Join(hostGlobalLdflags, " "))
pctx.StaticVariable("HostGlobalLldflags", strings.Join(hostGlobalLldflags, " "))
- pctx.StaticVariable("NoOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
-
- pctx.StaticVariable("CommonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
pctx.StaticVariable("CommonClangGlobalCflags",
strings.Join(append(ClangFilterUnknownCflags(commonGlobalCflags), "${ClangExtraCflags}"), " "))
@@ -256,10 +249,3 @@
"-isystem bionic/libc/kernel/android/uapi",
}, " ")
}
-
-func replaceFirst(slice []string, from, to string) {
- if slice[0] != from {
- panic(fmt.Errorf("Expected %q, found %q", from, to))
- }
- slice[0] = to
-}
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
index 0c4640b..561d8d6 100644
--- a/cc/config/mips64_device.go
+++ b/cc/config/mips64_device.go
@@ -69,9 +69,6 @@
pctx.SourcePathVariable("Mips64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
- pctx.StaticVariable("Mips64Cflags", strings.Join(mips64Cflags, " "))
- pctx.StaticVariable("Mips64Ldflags", strings.Join(mips64Ldflags, " "))
- pctx.StaticVariable("Mips64Cppflags", strings.Join(mips64Cppflags, " "))
pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips"))
// Clang cflags
@@ -83,7 +80,6 @@
// Architecture variant cflags
for variant, cflags := range mips64ArchVariantCflags {
- pctx.StaticVariable("Mips64"+variant+"VariantCflags", strings.Join(cflags, " "))
pctx.StaticVariable("Mips64"+variant+"VariantClangCflags",
strings.Join(ClangFilterUnknownCflags(cflags), " "))
}
@@ -91,8 +87,8 @@
type toolchainMips64 struct {
toolchain64Bit
- cflags, clangCflags string
- toolchainCflags, toolchainClangCflags string
+ clangCflags string
+ toolchainClangCflags string
}
func (t *toolchainMips64) Name() string {
@@ -111,22 +107,6 @@
return mips64GccVersion
}
-func (t *toolchainMips64) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainMips64) Cflags() string {
- return t.cflags
-}
-
-func (t *toolchainMips64) Cppflags() string {
- return "${config.Mips64Cppflags}"
-}
-
-func (t *toolchainMips64) Ldflags() string {
- return "${config.Mips64Ldflags}"
-}
-
func (t *toolchainMips64) IncludeFlags() string {
return "${config.Mips64IncludeFlags}"
}
@@ -166,9 +146,7 @@
func mips64ToolchainFactory(arch android.Arch) Toolchain {
return &toolchainMips64{
- cflags: "${config.Mips64Cflags}",
clangCflags: "${config.Mips64ClangCflags}",
- toolchainCflags: "${config.Mips64" + arch.ArchVariant + "VariantCflags}",
toolchainClangCflags: "${config.Mips64" + arch.ArchVariant + "VariantClangCflags}",
}
}
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
index eb44fd5..8cd35b3 100644
--- a/cc/config/mips_device.go
+++ b/cc/config/mips_device.go
@@ -111,9 +111,6 @@
"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
pctx.StaticVariable("MipsToolchainLdflags", strings.Join(mipsToolchainLdflags, " "))
- pctx.StaticVariable("MipsCflags", strings.Join(mipsCflags, " "))
- pctx.StaticVariable("MipsLdflags", strings.Join(mipsLdflags, " "))
- pctx.StaticVariable("MipsCppflags", strings.Join(mipsCppflags, " "))
pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips"))
// Clang cflags
@@ -125,7 +122,6 @@
// Architecture variant cflags
for variant, cflags := range mipsArchVariantCflags {
- pctx.StaticVariable("Mips"+variant+"VariantCflags", strings.Join(cflags, " "))
pctx.StaticVariable("Mips"+variant+"VariantClangCflags",
strings.Join(ClangFilterUnknownCflags(cflags), " "))
}
@@ -133,8 +129,8 @@
type toolchainMips struct {
toolchain32Bit
- cflags, clangCflags string
- toolchainCflags, toolchainClangCflags string
+ clangCflags string
+ toolchainClangCflags string
}
func (t *toolchainMips) Name() string {
@@ -153,26 +149,6 @@
return mipsGccVersion
}
-func (t *toolchainMips) ToolchainLdflags() string {
- return "${config.MipsToolchainLdflags}"
-}
-
-func (t *toolchainMips) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainMips) Cflags() string {
- return t.cflags
-}
-
-func (t *toolchainMips) Cppflags() string {
- return "${config.MipsCppflags}"
-}
-
-func (t *toolchainMips) Ldflags() string {
- return "${config.MipsLdflags}"
-}
-
func (t *toolchainMips) IncludeFlags() string {
return "${config.MipsIncludeFlags}"
}
@@ -216,9 +192,7 @@
func mipsToolchainFactory(arch android.Arch) Toolchain {
return &toolchainMips{
- cflags: "${config.MipsCflags}",
clangCflags: "${config.MipsClangCflags}",
- toolchainCflags: "${config.Mips" + arch.ArchVariant + "VariantCflags}",
toolchainClangCflags: "${config.Mips" + arch.ArchVariant + "VariantClangCflags}",
}
}
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index 2e49c16..dd52a0e 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -36,7 +36,6 @@
"performance*",
"-google-readability*",
"-google-runtime-references",
- "-performance-noexcept-move-constructor",
}, ",")
})
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 930b18f..d5e9d01 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -49,13 +49,7 @@
GccVersion() string
ToolPath() string
- ToolchainCflags() string
- ToolchainLdflags() string
- Cflags() string
- Cppflags() string
- Ldflags() string
IncludeFlags() string
- InstructionSetFlags(string) (string, error)
ClangTriple() string
ToolchainClangCflags() string
@@ -101,13 +95,6 @@
return triple
}
-func (toolchainBase) InstructionSetFlags(s string) (string, error) {
- if s != "" {
- return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
- }
- return "", nil
-}
-
func (toolchainBase) ClangInstructionSetFlags(s string) (string, error) {
if s != "" {
return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
@@ -115,14 +102,6 @@
return "", nil
}
-func (toolchainBase) ToolchainCflags() string {
- return ""
-}
-
-func (toolchainBase) ToolchainLdflags() string {
- return ""
-}
-
func (toolchainBase) ToolchainClangCflags() string {
return ""
}
@@ -183,18 +162,6 @@
return false
}
-func copyVariantFlags(m map[string][]string) map[string][]string {
- ret := make(map[string][]string, len(m))
- for k, v := range m {
- l := make([]string, len(m[k]))
- for i := range m[k] {
- l[i] = v[i]
- }
- ret[k] = l
- }
- return ret
-}
-
func variantOrDefault(variants map[string]string, choice string) string {
if ret, ok := variants[choice]; ok {
return ret
@@ -253,6 +220,10 @@
return LibclangRuntimeLibrary(t, "scudo")
}
+func ScudoMinimalRuntimeLibrary(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "scudo_minimal")
+}
+
func ToolPath(t Toolchain) string {
if p := t.ToolPath(); p != "" {
return p
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 5e2dc49..ff8a6da 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -125,10 +125,8 @@
pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
- pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
pctx.StaticVariable("X86_64Lldflags", strings.Join(x86_64Lldflags, " "))
- pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
pctx.StaticVariable("X86_64IncludeFlags", bionicHeaders("x86"))
// Clang cflags
@@ -144,7 +142,6 @@
// Architecture variant cflags
for variant, cflags := range x86_64ArchVariantCflags {
- pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
pctx.StaticVariable("X86_64"+variant+"VariantClangCflags",
strings.Join(ClangFilterUnknownCflags(cflags), " "))
}
@@ -152,7 +149,7 @@
type toolchainX86_64 struct {
toolchain64Bit
- toolchainCflags, toolchainClangCflags string
+ toolchainClangCflags string
}
func (t *toolchainX86_64) Name() string {
@@ -171,26 +168,6 @@
return x86_64GccVersion
}
-func (t *toolchainX86_64) ToolchainLdflags() string {
- return "${config.X86_64ToolchainLdflags}"
-}
-
-func (t *toolchainX86_64) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainX86_64) Cflags() string {
- return "${config.X86_64Cflags}"
-}
-
-func (t *toolchainX86_64) Cppflags() string {
- return "${config.X86_64Cppflags}"
-}
-
-func (t *toolchainX86_64) Ldflags() string {
- return "${config.X86_64Ldflags}"
-}
-
func (t *toolchainX86_64) IncludeFlags() string {
return "${config.X86_64IncludeFlags}"
}
@@ -232,23 +209,16 @@
}
func x86_64ToolchainFactory(arch android.Arch) Toolchain {
- toolchainCflags := []string{
- "${config.X86_64ToolchainCflags}",
- "${config.X86_64" + arch.ArchVariant + "VariantCflags}",
- }
-
toolchainClangCflags := []string{
"${config.X86_64ToolchainCflags}",
"${config.X86_64" + arch.ArchVariant + "VariantClangCflags}",
}
for _, feature := range arch.ArchFeatures {
- toolchainCflags = append(toolchainCflags, x86_64ArchFeatureCflags[feature]...)
toolchainClangCflags = append(toolchainClangCflags, x86_64ArchFeatureCflags[feature]...)
}
return &toolchainX86_64{
- toolchainCflags: strings.Join(toolchainCflags, " "),
toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
}
}
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 694137d..09632db 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -117,9 +117,6 @@
pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
- pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
- pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
-
pctx.StaticVariable("DarwinClangCflags", strings.Join(darwinClangCflags, " "))
pctx.StaticVariable("DarwinClangLdflags", strings.Join(darwinClangLdflags, " "))
pctx.StaticVariable("DarwinClangLldflags", strings.Join(darwinClangLldflags, " "))
@@ -182,18 +179,6 @@
return darwinGccVersion
}
-func (t *toolchainDarwin) Cflags() string {
- return "${config.DarwinCflags}"
-}
-
-func (t *toolchainDarwin) Cppflags() string {
- return ""
-}
-
-func (t *toolchainDarwin) Ldflags() string {
- return "${config.DarwinLdflags}"
-}
-
func (t *toolchainDarwin) IncludeFlags() string {
return ""
}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index ffdf8ea..fc0b1d8 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -149,10 +149,8 @@
pctx.StaticVariable("X86ToolchainCflags", "-m32")
pctx.StaticVariable("X86ToolchainLdflags", "-m32")
- pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
pctx.StaticVariable("X86Lldflags", strings.Join(x86Lldflags, " "))
- pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
pctx.StaticVariable("X86IncludeFlags", bionicHeaders("x86"))
// Clang cflags
@@ -168,7 +166,6 @@
// Architecture variant cflags
for variant, cflags := range x86ArchVariantCflags {
- pctx.StaticVariable("X86"+variant+"VariantCflags", strings.Join(cflags, " "))
pctx.StaticVariable("X86"+variant+"VariantClangCflags",
strings.Join(ClangFilterUnknownCflags(cflags), " "))
}
@@ -176,7 +173,7 @@
type toolchainX86 struct {
toolchain32Bit
- toolchainCflags, toolchainClangCflags string
+ toolchainClangCflags string
}
func (t *toolchainX86) Name() string {
@@ -195,26 +192,6 @@
return x86GccVersion
}
-func (t *toolchainX86) ToolchainLdflags() string {
- return "${config.X86ToolchainLdflags}"
-}
-
-func (t *toolchainX86) ToolchainCflags() string {
- return t.toolchainCflags
-}
-
-func (t *toolchainX86) Cflags() string {
- return "${config.X86Cflags}"
-}
-
-func (t *toolchainX86) Cppflags() string {
- return "${config.X86Cppflags}"
-}
-
-func (t *toolchainX86) Ldflags() string {
- return "${config.X86Ldflags}"
-}
-
func (t *toolchainX86) IncludeFlags() string {
return "${config.X86IncludeFlags}"
}
@@ -256,23 +233,16 @@
}
func x86ToolchainFactory(arch android.Arch) Toolchain {
- toolchainCflags := []string{
- "${config.X86ToolchainCflags}",
- "${config.X86" + arch.ArchVariant + "VariantCflags}",
- }
-
toolchainClangCflags := []string{
"${config.X86ToolchainCflags}",
"${config.X86" + arch.ArchVariant + "VariantClangCflags}",
}
for _, feature := range arch.ArchFeatures {
- toolchainCflags = append(toolchainCflags, x86ArchFeatureCflags[feature]...)
toolchainClangCflags = append(toolchainClangCflags, x86ArchFeatureCflags[feature]...)
}
return &toolchainX86{
- toolchainCflags: strings.Join(toolchainCflags, " "),
toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
}
}
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index a9fb1f6..5fb88e6 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -96,18 +96,6 @@
return "4.9"
}
-func (t *toolchainLinuxBionic) Cflags() string {
- return ""
-}
-
-func (t *toolchainLinuxBionic) Cppflags() string {
- return ""
-}
-
-func (t *toolchainLinuxBionic) Ldflags() string {
- return ""
-}
-
func (t *toolchainLinuxBionic) IncludeFlags() string {
return "${config.LinuxBionicIncludeFlags}"
}
@@ -151,6 +139,10 @@
return true
}
+func (toolchainLinuxBionic) LibclangRuntimeLibraryArch() string {
+ return "x86_64"
+}
+
var toolchainLinuxBionicSingleton Toolchain = &toolchainLinuxBionic{}
func linuxBionicToolchainFactory(arch android.Arch) Toolchain {
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 3965cd7..8da21b3 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -122,19 +122,10 @@
pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
- pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
- pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
-
pctx.StaticVariable("LinuxClangCflags", strings.Join(linuxClangCflags, " "))
pctx.StaticVariable("LinuxClangLdflags", strings.Join(linuxClangLdflags, " "))
pctx.StaticVariable("LinuxClangLldflags", strings.Join(linuxClangLldflags, " "))
- // Extended cflags
- pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
- pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
- pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
- pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
-
pctx.StaticVariable("LinuxX86ClangCflags",
strings.Join(ClangFilterUnknownCflags(linuxX86Cflags), " "))
pctx.StaticVariable("LinuxX8664ClangCflags",
@@ -182,26 +173,6 @@
return linuxGccVersion
}
-func (t *toolchainLinuxX86) Cflags() string {
- return "${config.LinuxCflags} ${config.LinuxX86Cflags}"
-}
-
-func (t *toolchainLinuxX8664) Cflags() string {
- return "${config.LinuxCflags} ${config.LinuxX8664Cflags}"
-}
-
-func (t *toolchainLinux) Cppflags() string {
- return ""
-}
-
-func (t *toolchainLinuxX86) Ldflags() string {
- return "${config.LinuxLdflags} ${config.LinuxX86Ldflags}"
-}
-
-func (t *toolchainLinuxX8664) Ldflags() string {
- return "${config.LinuxLdflags} ${config.LinuxX8664Ldflags}"
-}
-
func (t *toolchainLinux) IncludeFlags() string {
return ""
}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 65b9e6c..6300a1b 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -47,18 +47,11 @@
"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include",
}
- windowsClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3",
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/backward",
- }
+ windowsClangCppflags = []string{}
- windowsX86ClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}/32",
- }
+ windowsX86ClangCppflags = []string{}
- windowsX8664ClangCppflags = []string{
- "-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include/c++/4.8.3/${WindowsGccTriple}",
- }
+ windowsX8664ClangCppflags = []string{}
windowsLdflags = []string{
"--enable-stdcall-fixup",
@@ -80,24 +73,18 @@
"-m32",
"-Wl,--large-address-aware",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
- "-static-libgcc",
}
windowsX86ClangLdflags = append(ClangFilterUnknownCflags(windowsX86Ldflags), []string{
"-B${WindowsGccRoot}/${WindowsGccTriple}/bin",
"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/32",
"-B${WindowsGccRoot}/${WindowsGccTriple}/lib32",
- "-pthread",
- // Bug: http://b/109759970 - WAR until issue with ld.bfd's
- // inability to handle Clang-generated section names is fixed.
- "-Wl,--allow-multiple-definition",
}...)
windowsX86ClangLldflags = ClangFilterUnknownLldflags(windowsX86ClangLdflags)
windowsX8664Ldflags = []string{
"-m64",
"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
- "-static-libgcc",
"-Wl,--high-entropy-va",
}
windowsX8664ClangLdflags = append(ClangFilterUnknownCflags(windowsX8664Ldflags), []string{
@@ -105,10 +92,6 @@
"-B${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
"-L${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3",
"-B${WindowsGccRoot}/${WindowsGccTriple}/lib64",
- "-pthread",
- // Bug: http://b/109759970 - WAR until issue with ld.bfd's
- // inability to handle Clang-generated section names is fixed.
- "-Wl,--allow-multiple-definition",
}...)
windowsX8664ClangLldflags = ClangFilterUnknownLldflags(windowsX8664ClangLdflags)
@@ -140,19 +123,11 @@
pctx.StaticVariable("WindowsGccTriple", "x86_64-w64-mingw32")
- pctx.StaticVariable("WindowsCflags", strings.Join(windowsCflags, " "))
- pctx.StaticVariable("WindowsLdflags", strings.Join(windowsLdflags, " "))
-
pctx.StaticVariable("WindowsClangCflags", strings.Join(windowsClangCflags, " "))
pctx.StaticVariable("WindowsClangLdflags", strings.Join(windowsClangLdflags, " "))
pctx.StaticVariable("WindowsClangLldflags", strings.Join(windowsClangLldflags, " "))
pctx.StaticVariable("WindowsClangCppflags", strings.Join(windowsClangCppflags, " "))
- pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " "))
- pctx.StaticVariable("WindowsX8664Cflags", strings.Join(windowsX8664Cflags, " "))
- pctx.StaticVariable("WindowsX86Ldflags", strings.Join(windowsX86Ldflags, " "))
- pctx.StaticVariable("WindowsX8664Ldflags", strings.Join(windowsX8664Ldflags, " "))
-
pctx.StaticVariable("WindowsX86ClangCflags",
strings.Join(ClangFilterUnknownCflags(windowsX86Cflags), " "))
pctx.StaticVariable("WindowsX8664ClangCflags",
@@ -201,26 +176,6 @@
return windowsGccVersion
}
-func (t *toolchainWindowsX86) Cflags() string {
- return "${config.WindowsCflags} ${config.WindowsX86Cflags}"
-}
-
-func (t *toolchainWindowsX8664) Cflags() string {
- return "${config.WindowsCflags} ${config.WindowsX8664Cflags}"
-}
-
-func (t *toolchainWindows) Cppflags() string {
- return ""
-}
-
-func (t *toolchainWindowsX86) Ldflags() string {
- return "${config.WindowsLdflags} ${config.WindowsX86Ldflags}"
-}
-
-func (t *toolchainWindowsX8664) Ldflags() string {
- return "${config.WindowsLdflags} ${config.WindowsX8664Ldflags}"
-}
-
func (t *toolchainWindows) IncludeFlags() string {
return "${config.WindowsIncludeFlags}"
}
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 8c99bbf..c49d197 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -20,6 +20,7 @@
import logging
import os
import re
+import sys
ALL_ARCHITECTURES = (
@@ -107,22 +108,33 @@
return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
-def should_omit_version(name, tags, arch, api, vndk):
+def should_omit_version(version, arch, api, vndk):
"""Returns True if the version section should be ommitted.
We want to omit any sections that do not have any symbols we'll have in the
stub library. Sections that contain entirely future symbols or only symbols
for certain architectures.
"""
- if version_is_private(name):
+ if version_is_private(version.name):
return True
- if 'platform-only' in tags:
+ if 'platform-only' in version.tags:
return True
- if 'vndk' in tags and not vndk:
+ if 'vndk' in version.tags and not vndk:
return True
- if not symbol_in_arch(tags, arch):
+ if not symbol_in_arch(version.tags, arch):
return True
- if not symbol_in_api(tags, arch, api):
+ if not symbol_in_api(version.tags, arch, api):
+ return True
+ return False
+
+
+def should_omit_symbol(symbol, arch, api, vndk):
+ """Returns True if the symbol should be omitted."""
+ if not vndk and 'vndk' in symbol.tags:
+ return True
+ if not symbol_in_arch(symbol.tags, arch):
+ return True
+ if not symbol_in_api(symbol.tags, arch, api):
return True
return False
@@ -189,6 +201,15 @@
pass
+class MultiplyDefinedSymbolError(RuntimeError):
+ """A symbol name was multiply defined."""
+ def __init__(self, multiply_defined_symbols):
+ super(MultiplyDefinedSymbolError, self).__init__(
+ 'Version script contains multiple definitions for: {}'.format(
+ ', '.join(multiply_defined_symbols)))
+ self.multiply_defined_symbols = multiply_defined_symbols
+
+
class Version(object):
"""A version block of a symbol file."""
def __init__(self, name, base, tags, symbols):
@@ -221,9 +242,12 @@
class SymbolFileParser(object):
"""Parses NDK symbol files."""
- def __init__(self, input_file, api_map):
+ def __init__(self, input_file, api_map, arch, api, vndk):
self.input_file = input_file
self.api_map = api_map
+ self.arch = arch
+ self.api = api
+ self.vndk = vndk
self.current_line = None
def parse(self):
@@ -235,8 +259,36 @@
else:
raise ParseError(
'Unexpected contents at top level: ' + self.current_line)
+
+ self.check_no_duplicate_symbols(versions)
return versions
+ def check_no_duplicate_symbols(self, versions):
+ """Raises errors for multiply defined symbols.
+
+ This situation is the normal case when symbol versioning is actually
+ used, but this script doesn't currently handle that. The error message
+ will be a not necessarily obvious "error: redefition of 'foo'" from
+ stub.c, so it's better for us to catch this situation and raise a
+ better error.
+ """
+ symbol_names = set()
+ multiply_defined_symbols = set()
+ for version in versions:
+ if should_omit_version(version, self.arch, self.api, self.vndk):
+ continue
+
+ for symbol in version.symbols:
+ if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
+ continue
+
+ if symbol.name in symbol_names:
+ multiply_defined_symbols.add(symbol.name)
+ symbol_names.add(symbol.name)
+ if multiply_defined_symbols:
+ raise MultiplyDefinedSymbolError(
+ sorted(list(multiply_defined_symbols)))
+
def parse_version(self):
"""Parses a single version section and returns a Version object."""
name = self.current_line.split('{')[0].strip()
@@ -274,7 +326,8 @@
elif global_scope and not cpp_symbols:
symbols.append(self.parse_symbol())
else:
- # We're in a hidden scope or in 'extern "C++"' block. Ignore everything.
+ # We're in a hidden scope or in 'extern "C++"' block. Ignore
+ # everything.
pass
raise ParseError('Unexpected EOF in version block.')
@@ -324,20 +377,14 @@
def write_version(self, version):
"""Writes a single version block's data to the output files."""
- name = version.name
- tags = version.tags
- if should_omit_version(name, tags, self.arch, self.api, self.vndk):
+ if should_omit_version(version, self.arch, self.api, self.vndk):
return
- section_versioned = symbol_versioned_in_api(tags, self.api)
+ section_versioned = symbol_versioned_in_api(version.tags, self.api)
version_empty = True
pruned_symbols = []
for symbol in version.symbols:
- if not self.vndk and 'vndk' in symbol.tags:
- continue
- if not symbol_in_arch(symbol.tags, self.arch):
- continue
- if not symbol_in_api(symbol.tags, self.arch, self.api):
+ if should_omit_symbol(symbol, self.arch, self.api, self.vndk):
continue
if symbol_versioned_in_api(symbol.tags, self.api):
@@ -432,7 +479,11 @@
logging.basicConfig(level=verbose_map[verbosity])
with open(args.symbol_file) as symbol_file:
- versions = SymbolFileParser(symbol_file, api_map).parse()
+ try:
+ versions = SymbolFileParser(symbol_file, api_map, args.arch, api,
+ args.vndk).parse()
+ except MultiplyDefinedSymbolError as ex:
+ sys.exit('{}: error: {}'.format(args.symbol_file, ex))
with open(args.stub_src, 'w') as src_file:
with open(args.version_script, 'w') as version_file:
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index 42dc770..82a779c 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -26,7 +26,7 @@
if ctx.Device() {
f := &stub.libraryDecorator.flagExporter
for _, dir := range ctx.DeviceConfig().DeviceKernelHeaderDirs() {
- f.flags = append(f.flags, "-isystem"+dir)
+ f.flags = append(f.flags, "-isystem "+dir)
}
}
return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs)
diff --git a/cc/library.go b/cc/library.go
index 0e45af9..9eb3f47 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -274,11 +274,6 @@
if library.shared() {
libName := library.getLibName(ctx)
- // GCC for Android assumes that -shared means -Bsymbolic, use -Wl,-shared instead
- sharedFlag := "-Wl,-shared"
- if flags.Clang || ctx.Host() {
- sharedFlag = "-shared"
- }
var f []string
if ctx.toolchain().Bionic() {
f = append(f,
@@ -300,7 +295,7 @@
}
} else {
f = append(f,
- sharedFlag,
+ "-shared",
"-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
}
@@ -558,8 +553,7 @@
if library.stripper.needsStrip(ctx) {
// b/80093681, GNU strip/objcopy bug.
// Use llvm-{strip,objcopy} when clang lld is used.
- builderFlags.stripUseLlvmStrip =
- flags.Clang && library.baseLinker.useClangLld(ctx)
+ builderFlags.stripUseLlvmStrip = library.baseLinker.useClangLld(ctx)
strippedOutputFile := outputFile
outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
library.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
@@ -821,7 +815,7 @@
}
}
-func linkageMutator(mctx android.BottomUpMutatorContext) {
+func LinkageMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
if library, ok := m.linker.(libraryInterface); ok {
var modules []blueprint.Module
diff --git a/cc/linker.go b/cc/linker.go
index 9911b16..28f4747 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/cc/config"
"fmt"
"github.com/google/blueprint"
@@ -58,6 +59,9 @@
// don't link in libgcc.a
No_libgcc *bool
+ // don't link in libclang_rt.builtins-*.a
+ No_libcrt *bool
+
// Use clang lld instead of gnu ld.
Use_clang_lld *bool `android:"arch_variant"`
@@ -214,12 +218,17 @@
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs)
}
- if ctx.ModuleName() != "libcompiler_rt-extras" {
- deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras")
- }
-
if ctx.toolchain().Bionic() {
- // libgcc and libatomic have to be last on the command line
+ // Allow individual projects to opt out of libcrt,builtins
+ // b/117565638
+ if !Bool(linker.Properties.No_libcrt) {
+ // libclang_rt.builtins, libgcc and libatomic have to be last on the command line
+ // TODO: Also enable for libc and libm
+ if ctx.ModuleName() != "libc" && ctx.ModuleName() != "libm" {
+ 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, "libgcc")
@@ -280,7 +289,7 @@
if linker.Properties.Use_clang_lld != nil {
return Bool(linker.Properties.Use_clang_lld)
}
- return ctx.Config().UseClangLld()
+ return true
}
// ModuleContext extends BaseModuleContext
@@ -293,7 +302,7 @@
hod = "Device"
}
- if flags.Clang && linker.useClangLld(ctx) {
+ if linker.useClangLld(ctx) {
flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
if !BoolDefault(linker.MoreProperties.Pack_relocations, true) {
flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none")
@@ -310,12 +319,10 @@
flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
}
- if flags.Clang && linker.useClangLld(ctx) {
+ if linker.useClangLld(ctx) {
flags.LdFlags = append(flags.LdFlags, toolchain.ClangLldflags())
- } else if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
} else {
- flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags())
+ flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags())
}
if !ctx.toolchain().Bionic() {
@@ -362,11 +369,7 @@
flags.LdFlags = append(flags.LdFlags, "-Wl,--hash-style=both")
}
- if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
- } else {
- flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags())
- }
+ flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags())
if Bool(linker.Properties.Group_static_libs) {
flags.GroupStaticLibs = true
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index c23dfd4..32da059 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -144,17 +144,17 @@
timestampFiles = append(timestampFiles, stub.processHeaders(ctx, dir, genHeaderOutDir))
}
- includePrefix := "-I "
+ includePrefix := "-I"
if Bool(stub.Properties.Export_headers_as_system) {
includePrefix = "-isystem "
}
- stub.reexportFlags([]string{includePrefix + " " + genHeaderOutDir.String()})
+ stub.reexportFlags([]string{includePrefix + genHeaderOutDir.String()})
stub.reexportDeps(timestampFiles)
}
if Bool(stub.Properties.Export_headers_as_system) {
- stub.exportIncludes(ctx, "-isystem")
+ stub.exportIncludes(ctx, "-isystem ")
stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
}
diff --git a/cc/lto.go b/cc/lto.go
index fd2a869..52b9a34 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -76,7 +76,7 @@
if lto.Properties.Use_clang_lld != nil {
return Bool(lto.Properties.Use_clang_lld)
}
- return ctx.Config().UseClangLld()
+ return true
}
func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
diff --git a/cc/makevars.go b/cc/makevars.go
index b7fb575..32674a9 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -87,9 +87,7 @@
ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link")
ctx.Strict("CLANG_EXTERNAL_CFLAGS", "${config.ClangExternalCflags}")
- ctx.Strict("GLOBAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}")
- ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.ClangExtraNoOverrideCflags}")
- ctx.Strict("GLOBAL_CPPFLAGS_NO_OVERRIDE", "")
+ ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideClangGlobalCflags}")
ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " "))
@@ -128,6 +126,7 @@
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", strings.Join(asanLibs, " "))
ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " "))
+ ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ","))
ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " "))
ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " "))
@@ -173,13 +172,13 @@
sort.Strings(ndkMigratedLibs)
ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " "))
- hostTargets := ctx.Config().Targets[android.Host]
+ hostTargets := ctx.Config().Targets[android.BuildOs]
makeVarsToolchain(ctx, "", hostTargets[0])
if len(hostTargets) > 1 {
makeVarsToolchain(ctx, "2ND_", hostTargets[1])
}
- crossTargets := ctx.Config().Targets[android.HostCross]
+ crossTargets := ctx.Config().Targets[android.Windows]
if len(crossTargets) > 0 {
makeVarsToolchain(ctx, "", crossTargets[0])
if len(crossTargets) > 1 {
@@ -187,7 +186,7 @@
}
}
- deviceTargets := ctx.Config().Targets[android.Device]
+ deviceTargets := ctx.Config().Targets[android.Android]
makeVarsToolchain(ctx, "", deviceTargets[0])
if len(deviceTargets) > 1 {
makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
@@ -230,13 +229,13 @@
ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " "))
if target.Arch.ArchType == android.Arm {
- flags, err := toolchain.InstructionSetFlags("arm")
+ flags, err := toolchain.ClangInstructionSetFlags("arm")
if err != nil {
panic(err)
}
ctx.Strict(makePrefix+"arm_CFLAGS", flags)
- flags, err = toolchain.InstructionSetFlags("thumb")
+ flags, err = toolchain.ClangInstructionSetFlags("thumb")
if err != nil {
panic(err)
}
@@ -283,6 +282,7 @@
ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so"))
+ ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so"))
}
// This is used by external/gentoo/...
@@ -309,16 +309,14 @@
ctx.Strict(makePrefix+"OBJCOPY", gccCmd(toolchain, "objcopy"))
ctx.Strict(makePrefix+"LD", gccCmd(toolchain, "ld"))
ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
- ctx.Strict(makePrefix+"NDK_GCC_VERSION", toolchain.GccVersion())
ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain))
+ ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, ""))
}
if target.Os.Class == android.Host || target.Os.Class == android.HostCross {
ctx.Strict(makePrefix+"AVAILABLE_LIBRARIES", strings.Join(toolchain.AvailableLibraries(), " "))
}
- ctx.Strict(makePrefix+"TOOLCHAIN_ROOT", toolchain.GccRoot())
- ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, ""))
ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix())
ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix())
}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 1cd4829..cdf63d8 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -278,11 +278,7 @@
module.AddProperties(&module.properties)
- // Host module rather than device module because device module install steps
- // do not get run when embedded in make. We're not any of the existing
- // module types that can be exposed via the Android.mk exporter, so just use
- // a host module.
- android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
+ android.InitAndroidModule(module)
return module
}
@@ -362,11 +358,7 @@
module.AddProperties(&module.properties)
- // Host module rather than device module because device module install steps
- // do not get run when embedded in make. We're not any of the existing
- // module types that can be exposed via the Android.mk exporter, so just use
- // a host module.
- android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
+ android.InitAndroidModule(module)
return module
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2709a89..63d9f29 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -61,7 +61,7 @@
// These libraries have migrated over to the new ndk_library, which is added
// as a variation dependency via depsMutator.
ndkMigratedLibs = []string{}
- ndkMigratedLibsLock sync.Mutex // protects ndkMigratedLibs writes during parallel beginMutator
+ ndkMigratedLibsLock sync.Mutex // protects ndkMigratedLibs writes during parallel BeginMutator
)
// Creates a stub shared library based on the provided version file.
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 258d6bd..2a7e657 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -137,7 +137,7 @@
ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name")
}
- ndk.exportIncludes(ctx, "-isystem")
+ ndk.exportIncludes(ctx, "-isystem ")
libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
libExt := flags.Toolchain.ShlibSuffix()
diff --git a/cc/object.go b/cc/object.go
index 7c134ac..0010621 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -25,7 +25,7 @@
//
func init() {
- android.RegisterModuleType("cc_object", objectFactory)
+ android.RegisterModuleType("cc_object", ObjectFactory)
}
type objectLinker struct {
@@ -33,7 +33,7 @@
Properties ObjectLinkerProperties
}
-func objectFactory() android.Module {
+func ObjectFactory() android.Module {
module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
module.linker = &objectLinker{
baseLinker: NewBaseLinker(nil),
@@ -64,11 +64,7 @@
}
func (*objectLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- if flags.Clang {
- flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
- } else {
- flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainLdflags())
- }
+ flags.LdFlags = append(flags.LdFlags, ctx.toolchain().ToolchainClangLdflags())
return flags
}
diff --git a/cc/sabi.go b/cc/sabi.go
index 72a3c5c..4a86499 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -73,17 +73,6 @@
flags.ToolingCFlags = filterOutWithPrefix(flags.CFlags, config.ClangLibToolingUnknownCflags)
flags.ToolingCppFlags = filterOutWithPrefix(flags.CppFlags, config.ClangLibToolingUnknownCflags)
- // RSClang does not support recent mcpu option likes exynos-m2.
- // So we need overriding mcpu option when we want to use it.
- mappedArch := map[string]string{
- "exynos-m2": "cortex-a53",
- "cortex-a55": "cortex-a53",
- "cortex-a75": "cortex-a57",
- }
- if arch, ok := mappedArch[ctx.Arch().CpuVariant]; ok {
- flags.ToolingCFlags = append(flags.ToolingCFlags, "-mcpu="+arch)
- }
-
return flags
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b2fc63f..330a5e3 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -50,7 +50,9 @@
hwasanStaticLibsMutex sync.Mutex
intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
- minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer", "-fno-sanitize-recover=integer"}
+ minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
+ "-fno-sanitize-recover=integer,undefined"}
+ hwasanGlobalOptions = []string{"heap_history_size=4095"}
)
type sanitizerType int
@@ -164,17 +166,15 @@
var globalSanitizers []string
var globalSanitizersDiag []string
- if ctx.clang() {
- if ctx.Host() {
- if !ctx.Windows() {
- globalSanitizers = ctx.Config().SanitizeHost()
- }
- } else {
- arches := ctx.Config().SanitizeDeviceArch()
- if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
- globalSanitizers = ctx.Config().SanitizeDevice()
- globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
- }
+ if ctx.Host() {
+ if !ctx.Windows() {
+ globalSanitizers = ctx.Config().SanitizeHost()
+ }
+ } else {
+ arches := ctx.Config().SanitizeDeviceArch()
+ if len(arches) == 0 || inList(ctx.Arch().ArchType.Name, arches) {
+ globalSanitizers = ctx.Config().SanitizeDevice()
+ globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag()
}
}
@@ -369,10 +369,6 @@
return flags
}
- if !ctx.clang() {
- ctx.ModuleErrorf("Use of sanitizers requires clang")
- }
-
var sanitizers []string
var diagSanitizers []string
@@ -536,7 +532,11 @@
} else if Bool(sanitize.Properties.Sanitize.Thread) {
runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(ctx.toolchain())
} else if Bool(sanitize.Properties.Sanitize.Scudo) {
- runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
+ if len(diagSanitizers) == 0 && !sanitize.Properties.UbsanRuntimeDep {
+ runtimeLibrary = config.ScudoMinimalRuntimeLibrary(ctx.toolchain())
+ } else {
+ runtimeLibrary = config.ScudoRuntimeLibrary(ctx.toolchain())
+ }
} else if len(diagSanitizers) > 0 || sanitize.Properties.UbsanRuntimeDep {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(ctx.toolchain())
}
@@ -836,7 +836,6 @@
func enableMinimalRuntime(sanitize *sanitize) bool {
if !Bool(sanitize.Properties.Sanitize.Address) &&
!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
- !Bool(sanitize.Properties.Sanitize.Scudo) &&
(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
diff --git a/cc/stl.go b/cc/stl.go
index f44902e..8eee612 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -81,9 +81,9 @@
}
} else if ctx.Windows() {
switch s {
- case "libc++", "libc++_static", "libstdc++", "":
- // libc++ is not supported on mingw
- return "libstdc++"
+ case "libc++", "libc++_static", "":
+ // Only use static libc++ for Windows.
+ return "libc++_static"
case "none":
return ""
default:
@@ -177,6 +177,20 @@
} else {
flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...)
}
+ if ctx.Windows() {
+ // Use SjLj exceptions for 32-bit. libgcc_eh implements SjLj
+ // exception model for 32-bit.
+ if ctx.Arch().ArchType == android.X86 {
+ flags.CppFlags = append(flags.CppFlags, "-fsjlj-exceptions")
+ }
+ flags.CppFlags = append(flags.CppFlags,
+ // Disable visiblity annotations since we're using static
+ // libc++.
+ "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
+ "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
+ // Use Win32 threads in libc++.
+ "-D_LIBCPP_HAS_THREAD_API_WIN32")
+ }
} else {
if ctx.Arch().ArchType == android.Arm {
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a")
@@ -213,9 +227,10 @@
hostDynamicGccLibs = map[android.OsType][]string{
android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"},
android.Darwin: []string{"-lc", "-lSystem"},
- android.Windows: []string{"-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", "-lmsvcr110",
- "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lmingw32",
- "-lgcc", "-lmoldname", "-lmingwex", "-lmsvcrt"},
+ android.Windows: []string{"-Wl,--start-group", "-lmingw32", "-lgcc", "-lgcc_eh",
+ "-lmoldname", "-lmingwex", "-lmsvcr110", "-lmsvcrt", "-lpthread",
+ "-ladvapi32", "-lshell32", "-luser32", "-lkernel32", "-lpsapi",
+ "-Wl,--end-group"},
}
hostStaticGccLibs = map[android.OsType][]string{
android.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"},
diff --git a/cc/test.go b/cc/test.go
index 3fffffc..96049db 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -26,6 +26,9 @@
type TestProperties struct {
// if set, build against the gtest library. Defaults to true.
Gtest *bool
+
+ // if set, use the isolated gtest runner. Defaults to false.
+ Isolated *bool
}
type TestBinaryProperties struct {
@@ -168,6 +171,8 @@
if test.gtest() {
if ctx.useSdk() && ctx.Device() {
deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_c++", "libgtest_ndk_c++")
+ } else if BoolDefault(test.Properties.Isolated, false) {
+ deps.StaticLibs = append(deps.StaticLibs, "libgtest_isolated_main")
} else {
deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
}
diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py
index b20a5c7..3b5585a 100755
--- a/cc/test_gen_stub_libs.py
+++ b/cc/test_gen_stub_libs.py
@@ -15,7 +15,7 @@
# limitations under the License.
#
"""Tests for gen_stub_libs.py."""
-import cStringIO
+import io
import textwrap
import unittest
@@ -163,51 +163,106 @@
class OmitVersionTest(unittest.TestCase):
def test_omit_private(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo_PRIVATE', [], 'arm', 9, False))
- self.assertTrue(gsl.should_omit_version(
- 'foo_PLATFORM', [], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['platform-only'], 'arm', 9, False))
-
- def test_omit_vndk(self):
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['vndk'], 'arm', 9, False))
-
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, True))
- self.assertFalse(gsl.should_omit_version(
- 'foo', ['vndk'], 'arm', 9, True))
-
- def test_omit_arch(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
- self.assertFalse(gsl.should_omit_version(
- 'foo', ['arm'], 'arm', 9, False))
-
- self.assertTrue(gsl.should_omit_version(
- 'foo', ['x86'], 'arm', 9, False))
-
- def test_omit_api(self):
- self.assertFalse(gsl.should_omit_version('foo', [], 'arm', 9, False))
self.assertFalse(
- gsl.should_omit_version('foo', ['introduced=9'], 'arm', 9, False))
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
self.assertTrue(
- gsl.should_omit_version('foo', ['introduced=14'], 'arm', 9, False))
+ gsl.should_omit_version(
+ gsl.Version('foo_PRIVATE', None, [], []), 'arm', 9, False))
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo_PLATFORM', None, [], []), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['platform-only'], []), 'arm', 9,
+ False))
+
+ def test_omit_vndk(self):
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['vndk'], []), 'arm', 9, False))
+
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, True))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['vndk'], []), 'arm', 9, True))
+
+ def test_omit_arch(self):
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['arm'], []), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['x86'], []), 'arm', 9, False))
+
+ def test_omit_api(self):
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, [], []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['introduced=9'], []), 'arm', 9,
+ False))
+
+ self.assertTrue(
+ gsl.should_omit_version(
+ gsl.Version('foo', None, ['introduced=14'], []), 'arm', 9,
+ False))
+
+
+class OmitSymbolTest(unittest.TestCase):
+ def test_omit_vndk(self):
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['vndk']), 'arm', 9, False))
+
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, True))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['vndk']), 'arm', 9, True))
+
+ def test_omit_arch(self):
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['arm']), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['x86']), 'arm', 9, False))
+
+ def test_omit_api(self):
+ self.assertFalse(
+ gsl.should_omit_symbol(gsl.Symbol('foo', []), 'arm', 9, False))
+ self.assertFalse(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['introduced=9']), 'arm', 9, False))
+
+ self.assertTrue(
+ gsl.should_omit_symbol(
+ gsl.Symbol('foo', ['introduced=14']), 'arm', 9, False))
class SymbolFileParseTest(unittest.TestCase):
def test_next_line(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
foo
bar
# baz
qux
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
self.assertIsNone(parser.current_line)
self.assertEqual('foo', parser.next_line().strip())
@@ -223,7 +278,7 @@
self.assertEqual('', parser.current_line)
def test_parse_version(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 { # foo bar
baz;
qux; # woodly doodly
@@ -232,7 +287,7 @@
VERSION_2 {
} VERSION_1; # asdf
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
version = parser.parse_version()
@@ -253,31 +308,31 @@
self.assertEqual([], version.tags)
def test_parse_version_eof(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_unknown_scope_label(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo:
}
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_parse_symbol(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
foo;
bar; # baz qux
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
symbol = parser.parse_symbol()
@@ -290,47 +345,47 @@
self.assertEqual(['baz', 'qux'], symbol.tags)
def test_wildcard_symbol_global(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_wildcard_symbol_local(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
version = parser.parse_version()
self.assertEqual([], version.symbols)
def test_missing_semicolon(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
foo
};
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.next_line()
with self.assertRaises(gsl.ParseError):
parser.parse_version()
def test_parse_fails_invalid_input(self):
with self.assertRaises(gsl.ParseError):
- input_file = cStringIO.StringIO('foo')
- parser = gsl.SymbolFileParser(input_file, {})
+ input_file = io.StringIO('foo')
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
parser.parse()
def test_parse(self):
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
local:
hidden1;
@@ -347,7 +402,7 @@
qwerty;
} VERSION_1;
"""))
- parser = gsl.SymbolFileParser(input_file, {})
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
versions = parser.parse()
expected = [
@@ -368,8 +423,8 @@
def test_omit_version(self):
# Thorough testing of the cases involved here is handled by
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
version = gsl.Version('VERSION_PRIVATE', None, [], [
@@ -396,8 +451,8 @@
def test_omit_symbol(self):
# Thorough testing of the cases involved here is handled by
# SymbolPresenceTest.
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
version = gsl.Version('VERSION_1', None, [], [
@@ -422,8 +477,8 @@
self.assertEqual('', version_file.getvalue())
def test_write(self):
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
versions = [
@@ -475,7 +530,7 @@
'P': 9001,
}
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
global:
foo; # var
@@ -505,11 +560,11 @@
wobble;
} VERSION_4;
"""))
- parser = gsl.SymbolFileParser(input_file, api_map)
+ parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9, False)
versions = parser.parse()
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9, False)
generator.write(versions)
@@ -545,7 +600,7 @@
'Q': 9002,
}
- input_file = cStringIO.StringIO(textwrap.dedent("""\
+ input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
global:
foo; # introduced=O
@@ -555,11 +610,11 @@
*;
};
"""))
- parser = gsl.SymbolFileParser(input_file, api_map)
+ parser = gsl.SymbolFileParser(input_file, api_map, 'arm', 9001, False)
versions = parser.parse()
- src_file = cStringIO.StringIO()
- version_file = cStringIO.StringIO()
+ src_file = io.StringIO()
+ version_file = io.StringIO()
generator = gsl.Generator(src_file, version_file, 'arm', 9001, False)
generator.write(versions)
@@ -578,6 +633,38 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ def test_multiple_definition(self):
+ input_file = io.StringIO(textwrap.dedent("""\
+ VERSION_1 {
+ global:
+ foo;
+ foo;
+ bar;
+ baz;
+ qux; # arm
+ local:
+ *;
+ };
+
+ VERSION_2 {
+ global:
+ bar;
+ qux; # arm64
+ } VERSION_1;
+
+ VERSION_PRIVATE {
+ global:
+ baz;
+ } VERSION_2;
+
+ """))
+ parser = gsl.SymbolFileParser(input_file, {}, 'arm', 16, False)
+
+ with self.assertRaises(gsl.MultiplyDefinedSymbolError) as cm:
+ parser.parse()
+ self.assertEquals(['bar', 'foo'],
+ cm.exception.multiply_defined_symbols)
+
def main():
suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/cc/tidy.go b/cc/tidy.go
index 0a6b413..ddb445a 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -62,11 +62,6 @@
return flags
}
- // Clang-tidy requires clang
- if !flags.Clang {
- return flags
- }
-
flags.Tidy = true
// Add global WITH_TIDY_FLAGS and local tidy_flags.
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index 2b117b3..5811b01 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -23,11 +23,18 @@
//
func init() {
- android.RegisterModuleType("toolchain_library", toolchainLibraryFactory)
+ android.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
+}
+
+type toolchainLibraryProperties struct {
+ // the prebuilt toolchain library, as a path from the top of the source tree
+ Src *string `android:"arch_variant"`
}
type toolchainLibraryDecorator struct {
*libraryDecorator
+
+ Properties toolchainLibraryProperties
}
func (*toolchainLibraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -35,7 +42,13 @@
return deps
}
-func toolchainLibraryFactory() android.Module {
+func (library *toolchainLibraryDecorator) linkerProps() []interface{} {
+ var props []interface{}
+ props = append(props, library.libraryDecorator.linkerProps()...)
+ return append(props, &library.Properties)
+}
+
+func ToolchainLibraryFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
toolchainLibrary := &toolchainLibraryDecorator{
@@ -43,7 +56,6 @@
}
module.compiler = toolchainLibrary
module.linker = toolchainLibrary
- module.Properties.Gcc = true
module.stl = nil
module.sanitize = nil
module.installer = nil
@@ -58,16 +70,10 @@
func (library *toolchainLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- libName := ctx.ModuleName() + staticLibraryExtension
- outputFile := android.PathForModuleOut(ctx, libName)
-
- if flags.Clang {
- ctx.ModuleErrorf("toolchain_library must use GCC, not Clang")
+ if library.Properties.Src == nil {
+ ctx.PropertyErrorf("src", "No library source specified")
+ return android.PathForSource(ctx, "")
}
- CopyGccLib(ctx, libName, flagsToBuilderFlags(flags), outputFile)
-
- ctx.CheckbuildFile(outputFile)
-
- return outputFile
+ return android.PathForSource(ctx, *library.Properties.Src)
}
diff --git a/cc/util.go b/cc/util.go
index bab4d32..1412d54 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -78,7 +78,6 @@
sAbiFlags: strings.Join(in.SAbiFlags, " "),
yasmFlags: strings.Join(in.YasmFlags, " "),
toolchain: in.Toolchain,
- clang: in.Clang,
coverage: in.Coverage,
tidy: in.Tidy,
sAbiDump: in.SAbiDump,
diff --git a/cc/vndk.go b/cc/vndk.go
index 5a24a98..1a9b77a 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -15,6 +15,7 @@
package cc
import (
+ "errors"
"sort"
"strings"
"sync"
@@ -151,38 +152,42 @@
}
// Check the dependencies of VNDK shared libraries.
- if !vndkIsVndkDepAllowed(vndk, to.vndkdep) {
- ctx.ModuleErrorf("(%s) should not link to %q (%s)",
- vndk.typeName(), to.Name(), to.vndkdep.typeName())
+ if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil {
+ ctx.ModuleErrorf("(%s) should not link to %q (%s): %v",
+ vndk.typeName(), to.Name(), to.vndkdep.typeName(), err)
return
}
}
-func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) bool {
+func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error {
// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
if from.isVndkExt() {
if from.isVndkSp() {
- // VNDK-SP-Ext may depend on VNDK-SP, VNDK-SP-Ext, or vendor libs (excluding
- // VNDK and VNDK-Ext).
- return to.isVndkSp() || !to.isVndk()
+ if to.isVndk() && !to.isVndkSp() {
+ return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions")
+ }
+ return nil
}
// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
- return true
+ return nil
}
if from.isVndk() {
if to.isVndkExt() {
- // VNDK-core and VNDK-SP must not depend on VNDK extensions.
- return false
+ return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions")
}
if from.isVndkSp() {
- // VNDK-SP must only depend on VNDK-SP.
- return to.isVndkSp()
+ if !to.isVndkSp() {
+ return errors.New("VNDK-SP must only depend on VNDK-SP")
+ }
+ return nil
}
- // VNDK-core may depend on VNDK-core or VNDK-SP.
- return to.isVndk()
+ if !to.isVndk() {
+ return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP")
+ }
+ return nil
}
// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
- return true
+ return nil
}
var (
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index 3f24ab2..ea0bf4e 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -13,7 +13,7 @@
// limitations under the License.
// This tool extracts ELF LOAD segments from our linker binary, and produces an
-// assembly file and linker script which will embed those segments as sections
+// assembly file and linker flags which will embed those segments as sections
// in another binary.
package main
@@ -26,38 +26,15 @@
"io/ioutil"
"log"
"os"
- "text/template"
+ "strings"
)
-var linkerScriptTemplate = template.Must(template.New("linker_script").Parse(`
-ENTRY(__dlwrap__start)
-SECTIONS {
- __dlwrap_original_start = _start;
- /DISCARD/ : { *(.interp) }
-
-{{range .}}
- . = {{ printf "0x%x" .Vaddr }};
- {{.Name}} : { KEEP(*({{.Name}})) }
-{{end}}
-
- .text : { *(.text .text.*) }
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .data : { *(.data .data.* .gnu.linkonce.d.*) }
- .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) }
-}
-`))
-
-type LinkerSection struct {
- Name string
- Vaddr uint64
-}
-
func main() {
var asmPath string
- var scriptPath string
+ var flagsPath string
flag.StringVar(&asmPath, "s", "", "Path to save the assembly file")
- flag.StringVar(&scriptPath, "T", "", "Path to save the linker script")
+ flag.StringVar(&flagsPath, "f", "", "Path to save the linker flags")
flag.Parse()
f, err := os.Open(flag.Arg(0))
@@ -72,19 +49,21 @@
}
asm := &bytes.Buffer{}
-
- fmt.Fprintln(asm, ".globl __dlwrap_linker_entry")
- fmt.Fprintf(asm, ".set __dlwrap_linker_entry, 0x%x\n\n", ef.Entry)
-
baseLoadAddr := uint64(0x1000)
- sections := []LinkerSection{}
load := 0
+ linkFlags := []string{}
+
+ fmt.Fprintln(asm, ".globl __dlwrap_linker_offset")
+ fmt.Fprintf(asm, ".set __dlwrap_linker_offset, 0x%x\n", baseLoadAddr)
+
for _, prog := range ef.Progs {
if prog.Type != elf.PT_LOAD {
continue
}
sectionName := fmt.Sprintf(".linker.sect%d", load)
+ symName := fmt.Sprintf("__dlwrap_linker_sect%d", load)
+
flags := ""
if prog.Flags&elf.PF_W != 0 {
flags += "w"
@@ -94,10 +73,12 @@
}
fmt.Fprintf(asm, ".section %s, \"a%s\"\n", sectionName, flags)
- if load == 0 {
- fmt.Fprintln(asm, ".globl __dlwrap_linker_code_start")
- fmt.Fprintln(asm, "__dlwrap_linker_code_start:")
- }
+ fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName)
+
+ linkFlags = append(linkFlags,
+ fmt.Sprintf("-Wl,--undefined=%s", symName),
+ fmt.Sprintf("-Wl,--section-start=%s=0x%x",
+ sectionName, baseLoadAddr+prog.Vaddr))
buffer, _ := ioutil.ReadAll(prog.Open())
bytesToAsm(asm, buffer)
@@ -113,11 +94,6 @@
}
fmt.Fprintln(asm)
- sections = append(sections, LinkerSection{
- Name: sectionName,
- Vaddr: baseLoadAddr + prog.Vaddr,
- })
-
load += 1
}
@@ -127,13 +103,10 @@
}
}
- if scriptPath != "" {
- buf := &bytes.Buffer{}
- if err := linkerScriptTemplate.Execute(buf, sections); err != nil {
- log.Fatalf("Failed to create linker script: %v", err)
- }
- if err := ioutil.WriteFile(scriptPath, buf.Bytes(), 0777); err != nil {
- log.Fatalf("Unable to write %q: %v", scriptPath, err)
+ if flagsPath != "" {
+ flags := strings.Join(linkFlags, " ")
+ if err := ioutil.WriteFile(flagsPath, []byte(flags), 0777); err != nil {
+ log.Fatalf("Unable to write %q: %v", flagsPath, err)
}
}
}
diff --git a/cmd/symbol_inject/Android.bp b/cmd/host_bionic_inject/Android.bp
similarity index 63%
copy from cmd/symbol_inject/Android.bp
copy to cmd/host_bionic_inject/Android.bp
index a2ea12b..acce683 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/cmd/host_bionic_inject/Android.bp
@@ -13,20 +13,7 @@
// limitations under the License.
blueprint_go_binary {
- name: "symbol_inject",
- srcs: [
- "symbol_inject.go",
- "elf.go",
- "macho.go",
- "pe.go",
- ],
- testSrcs: [
- "elf_symboldata_test.go",
- "elf_test.go",
- "macho_symboldata_test.go",
- "macho_test.go",
- "pe_symboldata_test.go",
- "pe_test.go",
- "symbol_inject_test.go",
- ],
+ name: "host_bionic_inject",
+ deps: ["soong-symbol_inject"],
+ srcs: ["host_bionic_inject.go"],
}
diff --git a/cmd/host_bionic_inject/host_bionic_inject.go b/cmd/host_bionic_inject/host_bionic_inject.go
new file mode 100644
index 0000000..0dabbba
--- /dev/null
+++ b/cmd/host_bionic_inject/host_bionic_inject.go
@@ -0,0 +1,174 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Verifies a host bionic executable with an embedded linker, then injects
+// the address of the _start function for the linker_wrapper to use.
+package main
+
+import (
+ "debug/elf"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+
+ "android/soong/symbol_inject"
+)
+
+func main() {
+ var inputFile, linkerFile, outputFile string
+
+ flag.StringVar(&inputFile, "i", "", "Input file")
+ flag.StringVar(&linkerFile, "l", "", "Linker file")
+ flag.StringVar(&outputFile, "o", "", "Output file")
+ flag.Parse()
+
+ if inputFile == "" || linkerFile == "" || outputFile == "" || flag.NArg() != 0 {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ r, err := os.Open(inputFile)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(2)
+ }
+ defer r.Close()
+
+ file, err := symbol_inject.OpenFile(r)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(3)
+ }
+
+ linker, err := elf.Open(linkerFile)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(4)
+ }
+
+ start_addr, err := parseElf(r, linker)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(5)
+ }
+
+ w, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(6)
+ }
+ defer w.Close()
+
+ err = symbol_inject.InjectUint64Symbol(file, w, "__dlwrap_original_start", start_addr)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(7)
+ }
+}
+
+// Check the ELF file, and return the address to the _start function
+func parseElf(r io.ReaderAt, linker *elf.File) (uint64, error) {
+ file, err := elf.NewFile(r)
+ if err != nil {
+ return 0, err
+ }
+
+ symbols, err := file.Symbols()
+ if err != nil {
+ return 0, err
+ }
+
+ for _, prog := range file.Progs {
+ if prog.Type == elf.PT_INTERP {
+ return 0, fmt.Errorf("File should not have a PT_INTERP header")
+ }
+ }
+
+ if dlwrap_start, err := findSymbol(symbols, "__dlwrap__start"); err != nil {
+ return 0, err
+ } else if dlwrap_start.Value != file.Entry {
+ return 0, fmt.Errorf("Expected file entry(0x%x) to point to __dlwrap_start(0x%x)",
+ file.Entry, dlwrap_start.Value)
+ }
+
+ err = checkLinker(file, linker, symbols)
+ if err != nil {
+ return 0, err
+ }
+
+ start, err := findSymbol(symbols, "_start")
+ if err != nil {
+ return 0, fmt.Errorf("Failed to find _start symbol")
+ }
+ return start.Value, nil
+}
+
+func findSymbol(symbols []elf.Symbol, name string) (elf.Symbol, error) {
+ for _, sym := range symbols {
+ if sym.Name == name {
+ return sym, nil
+ }
+ }
+ return elf.Symbol{}, fmt.Errorf("Failed to find symbol %q", name)
+}
+
+// Check that all of the PT_LOAD segments have been embedded properly
+func checkLinker(file, linker *elf.File, fileSyms []elf.Symbol) error {
+ dlwrap_linker_offset, err := findSymbol(fileSyms, "__dlwrap_linker_offset")
+ if err != nil {
+ return err
+ }
+
+ for i, lprog := range linker.Progs {
+ if lprog.Type != elf.PT_LOAD {
+ continue
+ }
+
+ found := false
+ for j, prog := range file.Progs {
+ if prog.Type != elf.PT_LOAD {
+ continue
+ }
+
+ if lprog.Vaddr+dlwrap_linker_offset.Value != prog.Vaddr {
+ continue
+ }
+ found = true
+
+ if lprog.Memsz != prog.Memsz {
+ return fmt.Errorf("Linker prog %d (0x%x) memsz (0x%x) does not match (0x%x)",
+ i, lprog.Vaddr, lprog.Memsz, prog.Memsz)
+ }
+
+ // The linker shouldn't be using BSS, since only one
+ // BSS section is supported per ELF file.
+ if prog.Memsz != prog.Filesz {
+ return fmt.Errorf("Embedded prog %d (0x%x) memsz (0x%x) does not match filesz (0x%x)",
+ j, prog.Vaddr, prog.Memsz, prog.Filesz)
+ }
+
+ if lprog.Flags != prog.Flags {
+ return fmt.Errorf("Linker prog %d (0x%x) flags (%s) do not match (%s)",
+ i, lprog.Vaddr, lprog.Flags, prog.Flags)
+ }
+ }
+ if !found {
+ return fmt.Errorf("Linker prog %d (0x%x) not found at offset 0x%x",
+ i, lprog.Vaddr, dlwrap_linker_offset.Value)
+ }
+ }
+
+ return nil
+}
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index 4df4938..7a448ba 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -176,4 +176,12 @@
regexp.MustCompile(`Note: (Some input files|.*\.java) uses? unchecked or unsafe operations.`),
regexp.MustCompile(`Note: Recompile with -Xlint:unchecked for details.`),
regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
+
+ regexp.MustCompile(`javadoc: warning - The old Doclet and Taglet APIs in the packages`),
+ regexp.MustCompile(`com.sun.javadoc, com.sun.tools.doclets and their implementations`),
+ regexp.MustCompile(`are planned to be removed in a future JDK release. These`),
+ regexp.MustCompile(`components have been superseded by the new APIs in jdk.javadoc.doclet.`),
+ regexp.MustCompile(`Users are strongly recommended to migrate to the new APIs.`),
+
+ regexp.MustCompile(`javadoc: option --boot-class-path not allowed with target 1.9`),
}
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index d76793f..ad657e7 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -64,6 +64,17 @@
in: "\n",
out: "\n",
},
+ {
+ in: `
+javadoc: warning - The old Doclet and Taglet APIs in the packages
+com.sun.javadoc, com.sun.tools.doclets and their implementations
+are planned to be removed in a future JDK release. These
+components have been superseded by the new APIs in jdk.javadoc.doclet.
+Users are strongly recommended to migrate to the new APIs.
+javadoc: option --boot-class-path not allowed with target 1.9
+`,
+ out: "\n",
+ },
}
func TestJavacColorize(t *testing.T) {
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index f383de9..8e71a97 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -173,6 +173,10 @@
return ze.content.FileHeader.CRC32
}
+func (ze zipEntry) Size() uint64 {
+ return ze.content.FileHeader.UncompressedSize64
+}
+
func (ze zipEntry) WriteToZip(dest string, zw *zip.Writer) error {
return zw.CopyFrom(ze.content, dest)
}
@@ -195,6 +199,10 @@
return crc32.ChecksumIEEE(be.content)
}
+func (be bufferEntry) Size() uint64 {
+ return uint64(len(be.content))
+}
+
func (be bufferEntry) WriteToZip(dest string, zw *zip.Writer) error {
w, err := zw.CreateHeader(be.fh)
if err != nil {
@@ -215,6 +223,7 @@
String() string
IsDir() bool
CRC32() uint32
+ Size() uint64
WriteToZip(dest string, zw *zip.Writer) error
}
@@ -369,25 +378,27 @@
return fmt.Errorf("Directory/file mismatch at %v from %v and %v\n",
dest, existingSource, source)
}
+
if ignoreDuplicates {
continue
}
+
if emulateJar &&
file.Name == jar.ManifestFile || file.Name == jar.ModuleInfoClass {
// Skip manifest and module info files that are not from the first input file
continue
}
- if !source.IsDir() {
- if emulateJar {
- if existingSource.CRC32() != source.CRC32() {
- fmt.Fprintf(os.Stdout, "WARNING: Duplicate path %v found in %v and %v\n",
- dest, existingSource, source)
- }
- } else {
- return fmt.Errorf("Duplicate path %v found in %v and %v\n",
- dest, existingSource, source)
- }
+
+ if source.IsDir() {
+ continue
}
+
+ if existingSource.CRC32() == source.CRC32() && existingSource.Size() == source.Size() {
+ continue
+ }
+
+ return fmt.Errorf("Duplicate path %v found in %v and %v\n",
+ dest, existingSource, source)
}
}
}
diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go
index f91111f..19fa5ed 100644
--- a/cmd/merge_zips/merge_zips_test.go
+++ b/cmd/merge_zips/merge_zips_test.go
@@ -88,6 +88,14 @@
ignoreDuplicates: true,
},
{
+ name: "duplicates identical",
+ in: [][]testZipEntry{
+ {a},
+ {a},
+ },
+ out: []testZipEntry{a},
+ },
+ {
name: "sort",
in: [][]testZipEntry{
{be, bc, bDir, bbDir, bbb, A, metainfDir, manifestFile},
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index e8ea9b9..c4fb3d6 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -17,6 +17,7 @@
import (
"flag"
"fmt"
+ "io"
"log"
"os"
"path/filepath"
@@ -39,11 +40,15 @@
staticTime = time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
- excludes excludeArgs
+ excludes multiFlag
+ includes multiFlag
+ uncompress multiFlag
)
func init() {
flag.Var(&excludes, "x", "exclude a filespec from the output")
+ flag.Var(&includes, "X", "include a filespec in the output that was previously excluded")
+ flag.Var(&uncompress, "0", "convert a filespec to uncompressed in the output")
}
func main() {
@@ -93,7 +98,7 @@
}()
if err := zip2zip(&reader.Reader, writer, *sortGlobs, *sortJava, *setTime,
- flag.Args(), excludes); err != nil {
+ flag.Args(), excludes, includes, uncompress); err != nil {
log.Fatal(err)
}
@@ -101,11 +106,12 @@
type pair struct {
*zip.File
- newName string
+ newName string
+ uncompress bool
}
func zip2zip(reader *zip.Reader, writer *zip.Writer, sortOutput, sortJava, setTime bool,
- includes []string, excludes []string) error {
+ args []string, excludes, includes multiFlag, uncompresses []string) error {
matches := []pair{}
@@ -121,14 +127,14 @@
}
}
- for _, include := range includes {
+ for _, arg := range args {
// Reserve escaping for future implementation, so make sure no
// one is using \ and expecting a certain behavior.
- if strings.Contains(include, "\\") {
+ if strings.Contains(arg, "\\") {
return fmt.Errorf("\\ characters are not currently supported")
}
- input, output := includeSplit(include)
+ input, output := includeSplit(arg)
var includeMatches []pair
@@ -149,7 +155,7 @@
newName = output
}
}
- includeMatches = append(includeMatches, pair{file, newName})
+ includeMatches = append(includeMatches, pair{file, newName, false})
}
}
@@ -157,10 +163,10 @@
matches = append(matches, includeMatches...)
}
- if len(includes) == 0 {
+ if len(args) == 0 {
// implicitly match everything
for _, file := range reader.File {
- matches = append(matches, pair{file, file.Name})
+ matches = append(matches, pair{file, file.Name, false})
}
sortMatches(matches)
}
@@ -169,21 +175,18 @@
seen := make(map[string]*zip.File)
for _, match := range matches {
- // Filter out matches whose original file name matches an exclude filter
- excluded := false
- for _, exclude := range excludes {
- if excludeMatch, err := pathtools.Match(exclude, match.File.Name); err != nil {
+ // Filter out matches whose original file name matches an exclude filter, unless it also matches an
+ // include filter
+ if exclude, err := excludes.Match(match.File.Name); err != nil {
+ return err
+ } else if exclude {
+ if include, err := includes.Match(match.File.Name); err != nil {
return err
- } else if excludeMatch {
- excluded = true
- break
+ } else if !include {
+ continue
}
}
- if excluded {
- continue
- }
-
// Check for duplicate output names, ignoring ones that come from the same input zip entry.
if prev, exists := seen[match.newName]; exists {
if prev != match.File {
@@ -193,6 +196,15 @@
}
seen[match.newName] = match.File
+ for _, u := range uncompresses {
+ if uncompressMatch, err := pathtools.Match(u, match.newName); err != nil {
+ return err
+ } else if uncompressMatch {
+ match.uncompress = true
+ break
+ }
+ }
+
matchesAfterExcludes = append(matchesAfterExcludes, match)
}
@@ -200,8 +212,32 @@
if setTime {
match.File.SetModTime(staticTime)
}
- if err := writer.CopyFrom(match.File, match.newName); err != nil {
- return err
+ if match.uncompress && match.File.FileHeader.Method != zip.Store {
+ fh := match.File.FileHeader
+ fh.Name = match.newName
+ fh.Method = zip.Store
+ fh.CompressedSize64 = fh.UncompressedSize64
+
+ zw, err := writer.CreateHeaderAndroid(&fh)
+ if err != nil {
+ return err
+ }
+
+ zr, err := match.File.Open()
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(zw, zr)
+ zr.Close()
+ if err != nil {
+ return err
+ }
+ } else {
+ err := writer.CopyFrom(match.File, match.newName)
+ if err != nil {
+ return err
+ }
}
}
@@ -217,13 +253,27 @@
}
}
-type excludeArgs []string
+type multiFlag []string
-func (e *excludeArgs) String() string {
- return strings.Join(*e, " ")
+func (m *multiFlag) String() string {
+ return strings.Join(*m, " ")
}
-func (e *excludeArgs) Set(s string) error {
- *e = append(*e, s)
+func (m *multiFlag) Set(s string) error {
+ *m = append(*m, s)
return nil
}
+
+func (m *multiFlag) Match(s string) (bool, error) {
+ if m == nil {
+ return false, nil
+ }
+ for _, f := range *m {
+ if match, err := pathtools.Match(f, s); err != nil {
+ return false, err
+ } else if match {
+ return true, nil
+ }
+ }
+ return false, nil
+}
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index 212ab28..ae16494 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -26,13 +26,16 @@
var testCases = []struct {
name string
- inputFiles []string
- sortGlobs bool
- sortJava bool
- args []string
- excludes []string
+ inputFiles []string
+ sortGlobs bool
+ sortJava bool
+ args []string
+ excludes []string
+ includes []string
+ uncompresses []string
outputFiles []string
+ storedFiles []string
err error
}{
{
@@ -226,7 +229,7 @@
},
},
{
- name: "excludes with include",
+ name: "excludes with args",
inputFiles: []string{
"a/a",
@@ -240,6 +243,31 @@
},
},
{
+ name: "excludes over args",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: []string{"a/a"},
+ excludes: []string{"a/*"},
+
+ outputFiles: nil,
+ },
+ {
+ name: "excludes with includes",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ args: nil,
+ excludes: []string{"a/*"},
+ includes: []string{"a/b"},
+
+ outputFiles: []string{"a/b"},
+ },
+ {
name: "excludes with glob",
inputFiles: []string{
@@ -251,6 +279,79 @@
outputFiles: nil,
},
+ {
+ name: "uncompress one",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ uncompresses: []string{"a/a"},
+
+ outputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ storedFiles: []string{
+ "a/a",
+ },
+ },
+ {
+ name: "uncompress two",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ uncompresses: []string{"a/a", "a/b"},
+
+ outputFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ storedFiles: []string{
+ "a/a",
+ "a/b",
+ },
+ },
+ {
+ name: "uncompress glob",
+
+ inputFiles: []string{
+ "a/a",
+ "a/b",
+ "a/c.so",
+ "a/d.so",
+ },
+ uncompresses: []string{"a/*.so"},
+
+ outputFiles: []string{
+ "a/a",
+ "a/b",
+ "a/c.so",
+ "a/d.so",
+ },
+ storedFiles: []string{
+ "a/c.so",
+ "a/d.so",
+ },
+ },
+ {
+ name: "uncompress rename",
+
+ inputFiles: []string{
+ "a/a",
+ },
+ args: []string{"a/a:a/b"},
+ uncompresses: []string{"a/b"},
+
+ outputFiles: []string{
+ "a/b",
+ },
+ storedFiles: []string{
+ "a/b",
+ },
+ },
}
func errorString(e error) string {
@@ -282,7 +383,8 @@
}
outputWriter := zip.NewWriter(outputBuf)
- err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false, testCase.args, testCase.excludes)
+ err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false,
+ testCase.args, testCase.excludes, testCase.includes, testCase.uncompresses)
if errorString(testCase.err) != errorString(err) {
t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
}
@@ -294,15 +396,22 @@
t.Fatal(err)
}
var outputFiles []string
+ var storedFiles []string
if len(outputReader.File) > 0 {
outputFiles = make([]string, len(outputReader.File))
for i, file := range outputReader.File {
outputFiles[i] = file.Name
+ if file.Method == zip.Store {
+ storedFiles = append(storedFiles, file.Name)
+ }
}
}
if !reflect.DeepEqual(testCase.outputFiles, outputFiles) {
- t.Fatalf("Output file list does not match:\n got: %v\nwant: %v", outputFiles, testCase.outputFiles)
+ t.Fatalf("Output file list does not match:\nwant: %v\n got: %v", testCase.outputFiles, outputFiles)
+ }
+ if !reflect.DeepEqual(testCase.storedFiles, storedFiles) {
+ t.Fatalf("Stored file list does not match:\nwant: %v\n got: %v", testCase.storedFiles, storedFiles)
}
})
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e3823c5..2824e49 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -52,10 +52,9 @@
type hostToolDependencyTag struct {
blueprint.BaseDependencyTag
+ label string
}
-var hostToolDepTag hostToolDependencyTag
-
type generatorProperties struct {
// The command to run on one or more input files. Cmd supports substitution of a few variables
// (the actual substitution is implemented in GenerateAndroidBuildActions below)
@@ -63,7 +62,7 @@
// Available variables for substitution:
//
// $(location): the path to the first entry in tools or tool_files
- // $(location <label>): the path to the tool or tool_file with name <label>
+ // $(location <label>): the path to the tool, tool_file, input or output with name <label>
// $(in): one or more input files
// $(out): a single output file
// $(depfile): a file to which dependencies will be written, if the depfile property is set to true
@@ -102,8 +101,9 @@
taskGenerator taskFunc
- deps android.Paths
- rule blueprint.Rule
+ deps android.Paths
+ rule blueprint.Rule
+ rawCommand string
exportedIncludeDirs android.Paths
@@ -140,10 +140,14 @@
android.ExtractSourcesDeps(ctx, g.properties.Srcs)
android.ExtractSourcesDeps(ctx, g.properties.Tool_files)
if g, ok := ctx.Module().(*Module); ok {
- if len(g.properties.Tools) > 0 {
+ for _, tool := range g.properties.Tools {
+ tag := hostToolDependencyTag{label: tool}
+ if m := android.SrcIsModule(tool); m != "" {
+ tool = m
+ }
ctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "arch", Variation: ctx.Config().BuildOsVariant},
- }, hostToolDepTag, g.properties.Tools...)
+ }, tag, tool)
}
}
}
@@ -158,12 +162,25 @@
g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, ""))
}
- tools := map[string]android.Path{}
+ locationLabels := map[string][]string{}
+ firstLabel := ""
+
+ addLocationLabel := func(label string, paths []string) {
+ if firstLabel == "" {
+ firstLabel = label
+ }
+ if _, exists := locationLabels[label]; !exists {
+ locationLabels[label] = paths
+ } else {
+ ctx.ModuleErrorf("multiple labels for %q, %q and %q",
+ label, strings.Join(locationLabels[label], " "), strings.Join(paths, " "))
+ }
+ }
if len(g.properties.Tools) > 0 {
ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- switch ctx.OtherModuleDependencyTag(module) {
- case hostToolDepTag:
+ switch tag := ctx.OtherModuleDependencyTag(module).(type) {
+ case hostToolDependencyTag:
tool := ctx.OtherModuleName(module)
var path android.OptionalPath
@@ -191,11 +208,7 @@
if path.Valid() {
g.deps = append(g.deps, path.Path())
- if _, exists := tools[tool]; !exists {
- tools[tool] = path.Path()
- } else {
- ctx.ModuleErrorf("multiple tools for %q, %q and %q", tool, tools[tool], path.Path().String())
- }
+ addLocationLabel(tag.label, []string{path.Path().String()})
} else {
ctx.ModuleErrorf("host tool %q missing output file", tool)
}
@@ -207,21 +220,27 @@
return
}
- toolFiles := ctx.ExpandSources(g.properties.Tool_files, nil)
- for _, tool := range toolFiles {
- g.deps = append(g.deps, tool)
- if _, exists := tools[tool.Rel()]; !exists {
- tools[tool.Rel()] = tool
- } else {
- ctx.ModuleErrorf("multiple tools for %q, %q and %q", tool, tools[tool.Rel()], tool.Rel())
- }
+ for _, toolFile := range g.properties.Tool_files {
+ paths := ctx.ExpandSources([]string{toolFile}, nil)
+ g.deps = append(g.deps, paths...)
+ addLocationLabel(toolFile, paths.Strings())
+ }
+
+ var srcFiles android.Paths
+ for _, in := range g.properties.Srcs {
+ paths := ctx.ExpandSources([]string{in}, nil)
+ srcFiles = append(srcFiles, paths...)
+ addLocationLabel(in, paths.Strings())
+ }
+
+ task := g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles)
+
+ for _, out := range task.out {
+ addLocationLabel(out.Rel(), []string{filepath.Join("__SBOX_OUT_DIR__", out.Rel())})
}
referencedDepfile := false
- srcFiles := ctx.ExpandSources(g.properties.Srcs, nil)
- task := g.taskGenerator(ctx, String(g.properties.Cmd), srcFiles)
-
rawCommand, err := android.Expand(task.cmd, func(name string) (string, error) {
// report the error directly without returning an error to android.Expand to catch multiple errors in a
// single run
@@ -232,13 +251,17 @@
switch name {
case "location":
- if len(g.properties.Tools) == 0 && len(toolFiles) == 0 {
+ if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 {
return reportError("at least one `tools` or `tool_files` is required if $(location) is used")
- } else if len(g.properties.Tools) > 0 {
- return tools[g.properties.Tools[0]].String(), nil
- } else {
- return tools[toolFiles[0].Rel()].String(), nil
}
+ paths := locationLabels[firstLabel]
+ if len(paths) == 0 {
+ return reportError("default label %q has no files", firstLabel)
+ } else if len(paths) > 1 {
+ return reportError("default label %q has multiple files, use $(locations %s) to reference it",
+ firstLabel, firstLabel)
+ }
+ return locationLabels[firstLabel][0], nil
case "in":
return "${in}", nil
case "out":
@@ -254,13 +277,30 @@
default:
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
- if tool, ok := tools[label]; ok {
- return tool.String(), nil
+ if paths, ok := locationLabels[label]; ok {
+ if len(paths) == 0 {
+ return reportError("label %q has no files", label)
+ } else if len(paths) > 1 {
+ return reportError("label %q has multiple files, use $(locations %s) to reference it",
+ label, label)
+ }
+ return paths[0], nil
} else {
return reportError("unknown location label %q", label)
}
+ } else if strings.HasPrefix(name, "locations ") {
+ label := strings.TrimSpace(strings.TrimPrefix(name, "locations "))
+ if paths, ok := locationLabels[label]; ok {
+ if len(paths) == 0 {
+ return reportError("label %q has no files", label)
+ }
+ return strings.Join(paths, " "), nil
+ } else {
+ return reportError("unknown locations label %q", label)
+ }
+ } else {
+ return reportError("unknown variable '$(%s)'", name)
}
- return reportError("unknown variable '$(%s)'", name)
}
})
@@ -287,6 +327,7 @@
genDir := android.PathForModuleGen(ctx)
// Escape the command for the shell
rawCommand = "'" + strings.Replace(rawCommand, "'", `'\''`, -1) + "'"
+ g.rawCommand = rawCommand
sandboxCommand := fmt.Sprintf("$sboxCmd --sandbox-path %s --output-root %s -c %s %s $allouts",
sandboxPath, genDir, rawCommand, depfilePlaceholder)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
new file mode 100644
index 0000000..7e16ce1
--- /dev/null
+++ b/genrule/genrule_test.go
@@ -0,0 +1,489 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package genrule
+
+import (
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_java_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testContext(config android.Config, bp string,
+ fs map[string][]byte) *android.TestContext {
+
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
+ ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(GenRuleFactory))
+ ctx.RegisterModuleType("tool", android.ModuleFactoryAdaptor(toolFactory))
+ ctx.Register()
+
+ bp += `
+ tool {
+ name: "tool",
+ }
+
+ filegroup {
+ name: "tool_files",
+ srcs: [
+ "tool_file1",
+ "tool_file2",
+ ],
+ }
+
+ filegroup {
+ name: "1tool_file",
+ srcs: [
+ "tool_file1",
+ ],
+ }
+
+ filegroup {
+ name: "ins",
+ srcs: [
+ "in1",
+ "in2",
+ ],
+ }
+
+ filegroup {
+ name: "1in",
+ srcs: [
+ "in1",
+ ],
+ }
+
+ filegroup {
+ name: "empty",
+ }
+ `
+
+ mockFS := map[string][]byte{
+ "Android.bp": []byte(bp),
+ "tool": nil,
+ "tool_file1": nil,
+ "tool_file2": nil,
+ "in1": nil,
+ "in2": nil,
+ }
+
+ for k, v := range fs {
+ mockFS[k] = v
+ }
+
+ ctx.MockFileSystem(mockFS)
+
+ return ctx
+}
+
+func TestGenruleCmd(t *testing.T) {
+ testcases := []struct {
+ name string
+ prop string
+
+ err string
+ expect string
+ }{
+ {
+ name: "empty location tool",
+ prop: `
+ tools: ["tool"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ expect: "out/tool > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "empty location tool2",
+ prop: `
+ tools: [":tool"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ expect: "out/tool > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "empty location tool file",
+ prop: `
+ tool_files: ["tool_file1"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ expect: "tool_file1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "empty location tool file fg",
+ prop: `
+ tool_files: [":1tool_file"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ expect: "tool_file1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "empty location tool and tool file",
+ prop: `
+ tools: ["tool"],
+ tool_files: ["tool_file1"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ expect: "out/tool > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool",
+ prop: `
+ tools: ["tool"],
+ out: ["out"],
+ cmd: "$(location tool) > $(out)",
+ `,
+ expect: "out/tool > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool2",
+ prop: `
+ tools: [":tool"],
+ out: ["out"],
+ cmd: "$(location :tool) > $(out)",
+ `,
+ expect: "out/tool > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool file",
+ prop: `
+ tool_files: ["tool_file1"],
+ out: ["out"],
+ cmd: "$(location tool_file1) > $(out)",
+ `,
+ expect: "tool_file1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool file fg",
+ prop: `
+ tool_files: [":1tool_file"],
+ out: ["out"],
+ cmd: "$(location :1tool_file) > $(out)",
+ `,
+ expect: "tool_file1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "tool files",
+ prop: `
+ tool_files: [":tool_files"],
+ out: ["out"],
+ cmd: "$(locations :tool_files) > $(out)",
+ `,
+ expect: "tool_file1 tool_file2 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "in1",
+ prop: `
+ srcs: ["in1"],
+ out: ["out"],
+ cmd: "cat $(in) > $(out)",
+ `,
+ expect: "cat ${in} > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "in1 fg",
+ prop: `
+ srcs: [":1in"],
+ out: ["out"],
+ cmd: "cat $(in) > $(out)",
+ `,
+ expect: "cat ${in} > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "ins",
+ prop: `
+ srcs: ["in1", "in2"],
+ out: ["out"],
+ cmd: "cat $(in) > $(out)",
+ `,
+ expect: "cat ${in} > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "ins fg",
+ prop: `
+ srcs: [":ins"],
+ out: ["out"],
+ cmd: "cat $(in) > $(out)",
+ `,
+ expect: "cat ${in} > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "location in1",
+ prop: `
+ srcs: ["in1"],
+ out: ["out"],
+ cmd: "cat $(location in1) > $(out)",
+ `,
+ expect: "cat in1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "location in1 fg",
+ prop: `
+ srcs: [":1in"],
+ out: ["out"],
+ cmd: "cat $(location :1in) > $(out)",
+ `,
+ expect: "cat in1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "location ins",
+ prop: `
+ srcs: ["in1", "in2"],
+ out: ["out"],
+ cmd: "cat $(location in1) > $(out)",
+ `,
+ expect: "cat in1 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "location ins fg",
+ prop: `
+ srcs: [":ins"],
+ out: ["out"],
+ cmd: "cat $(locations :ins) > $(out)",
+ `,
+ expect: "cat in1 in2 > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "outs",
+ prop: `
+ out: ["out", "out2"],
+ cmd: "echo foo > $(out)",
+ `,
+ expect: "echo foo > __SBOX_OUT_FILES__",
+ },
+ {
+ name: "location out",
+ prop: `
+ out: ["out", "out2"],
+ cmd: "echo foo > $(location out2)",
+ `,
+ expect: "echo foo > __SBOX_OUT_DIR__/out2",
+ },
+ {
+ name: "depfile",
+ prop: `
+ out: ["out"],
+ depfile: true,
+ cmd: "echo foo > $(out) && touch $(depfile)",
+ `,
+ expect: "echo foo > __SBOX_OUT_FILES__ && touch __SBOX_DEPFILE__",
+ },
+ {
+ name: "gendir",
+ prop: `
+ out: ["out"],
+ cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
+ `,
+ expect: "echo foo > __SBOX_OUT_DIR__/foo && cp __SBOX_OUT_DIR__/foo __SBOX_OUT_FILES__",
+ },
+
+ {
+ name: "error empty location",
+ prop: `
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ err: "at least one `tools` or `tool_files` is required if $(location) is used",
+ },
+ {
+ name: "error empty location no files",
+ prop: `
+ tool_files: [":empty"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ err: `default label ":empty" has no files`,
+ },
+ {
+ name: "error empty location multiple files",
+ prop: `
+ tool_files: [":tool_files"],
+ out: ["out"],
+ cmd: "$(location) > $(out)",
+ `,
+ err: `default label ":tool_files" has multiple files`,
+ },
+ {
+ name: "error location",
+ prop: `
+ out: ["out"],
+ cmd: "echo foo > $(location missing)",
+ `,
+ err: `unknown location label "missing"`,
+ },
+ {
+ name: "error locations",
+ prop: `
+ out: ["out"],
+ cmd: "echo foo > $(locations missing)",
+ `,
+ err: `unknown locations label "missing"`,
+ },
+ {
+ name: "error location no files",
+ prop: `
+ out: ["out"],
+ srcs: [":empty"],
+ cmd: "echo $(location :empty) > $(out)",
+ `,
+ err: `label ":empty" has no files`,
+ },
+ {
+ name: "error locations no files",
+ prop: `
+ out: ["out"],
+ srcs: [":empty"],
+ cmd: "echo $(locations :empty) > $(out)",
+ `,
+ err: `label ":empty" has no files`,
+ },
+ {
+ name: "error location multiple files",
+ prop: `
+ out: ["out"],
+ srcs: [":ins"],
+ cmd: "echo $(location :ins) > $(out)",
+ `,
+ err: `label ":ins" has multiple files`,
+ },
+ {
+ name: "error variable",
+ prop: `
+ out: ["out"],
+ srcs: ["in1"],
+ cmd: "echo $(foo) > $(out)",
+ `,
+ err: `unknown variable '$(foo)'`,
+ },
+ {
+ name: "error depfile",
+ prop: `
+ out: ["out"],
+ cmd: "echo foo > $(out) && touch $(depfile)",
+ `,
+ err: "$(depfile) used without depfile property",
+ },
+ {
+ name: "error no depfile",
+ prop: `
+ out: ["out"],
+ depfile: true,
+ cmd: "echo foo > $(out)",
+ `,
+ err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
+ },
+ {
+ name: "error no out",
+ prop: `
+ cmd: "echo foo > $(out)",
+ `,
+ err: "must have at least one output file",
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ config := android.TestArchConfig(buildDir, nil)
+ bp := "genrule {\n"
+ bp += "name: \"gen\",\n"
+ bp += test.prop
+ bp += "}\n"
+
+ ctx := testContext(config, bp, nil)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ if errs == nil {
+ _, errs = ctx.PrepareBuildActions(config)
+ }
+ if errs == nil && test.err != "" {
+ t.Fatalf("want error %q, got no error", test.err)
+ } else if errs != nil && test.err == "" {
+ android.FailIfErrored(t, errs)
+ } else if test.err != "" {
+ if len(errs) != 1 {
+ t.Errorf("want 1 error, got %d errors:", len(errs))
+ for _, err := range errs {
+ t.Errorf(" %s", err.Error())
+ }
+ t.FailNow()
+ }
+ if !strings.Contains(errs[0].Error(), test.err) {
+ t.Fatalf("want %q, got %q", test.err, errs[0].Error())
+ }
+ return
+ }
+
+ gen := ctx.ModuleForTests("gen", "").Module().(*Module)
+ if gen.rawCommand != "'"+test.expect+"'" {
+ t.Errorf("want %q, got %q", test.expect, gen.rawCommand)
+ }
+ })
+ }
+
+}
+
+type testTool struct {
+ android.ModuleBase
+ outputFile android.Path
+}
+
+func toolFactory() android.Module {
+ module := &testTool{}
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+func (t *testTool) DepsMutator(ctx android.BottomUpMutatorContext) {}
+
+func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ t.outputFile = android.PathForTesting("out", ctx.ModuleName())
+}
+
+func (t *testTool) HostToolPath() android.OptionalPath {
+ return android.OptionalPathForPath(t.outputFile)
+}
+
+var _ HostToolProvider = (*testTool)(nil)
diff --git a/java/aapt2.go b/java/aapt2.go
index 70c7507..5553bfd 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -111,7 +111,8 @@
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
+ Command: `rm -rf $genDir && ` +
+ `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
`--output-text-symbols ${rTxt} $inFlags && ` +
`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
`${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
diff --git a/java/aar.go b/java/aar.go
index 29f5597..a06d191 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -250,6 +250,8 @@
}
switch ctx.OtherModuleDependencyTag(module) {
+ case instrumentationForTag:
+ // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case libTag, frameworkResTag:
if exportPackage != nil {
sharedLibs = append(sharedLibs, exportPackage)
@@ -359,7 +361,7 @@
module.androidLibraryProperties.BuildAAR = true
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ InitJavaModule(module, android.DeviceSupported)
return module
}
@@ -382,6 +384,7 @@
type AARImport struct {
android.ModuleBase
+ android.DefaultableModuleBase
prebuilt android.Prebuilt
properties AARImportProperties
@@ -555,6 +558,6 @@
module.AddProperties(&module.properties)
android.InitPrebuiltModule(module, &module.properties.Aars)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ InitJavaModule(module, android.DeviceSupported)
return module
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 313a144..359594c 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -243,6 +243,10 @@
if len(app.appProperties.Overrides) > 0 {
fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES := "+strings.Join(app.appProperties.Overrides, " "))
}
+
+ for _, jniLib := range app.installJniLibs {
+ fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), "+=", jniLib.name)
+ }
},
},
}
@@ -267,6 +271,21 @@
return data
}
+func (a *AndroidTestHelperApp) AndroidMk() android.AndroidMkData {
+ data := a.AndroidApp.AndroidMk()
+ data.Extra = append(data.Extra, func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_MODULE_TAGS := tests")
+ if len(a.appTestHelperAppProperties.Test_suites) > 0 {
+ fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
+ strings.Join(a.appTestHelperAppProperties.Test_suites, " "))
+ } else {
+ fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := null-suite")
+ }
+ })
+
+ return data
+}
+
func (a *AndroidLibrary) AndroidMk() android.AndroidMkData {
data := a.Library.AndroidMk()
diff --git a/java/app.go b/java/app.go
index f8bef1c..5d25dcf 100644
--- a/java/app.go
+++ b/java/app.go
@@ -19,26 +19,30 @@
import (
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/tradefed"
)
func init() {
android.RegisterModuleType("android_app", AndroidAppFactory)
android.RegisterModuleType("android_test", AndroidTestFactory)
+ android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
+ android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
}
// AndroidManifest.xml merging
// package splits
type appProperties struct {
- // path to a certificate, or the name of a certificate in the default
- // certificate directory, or blank to use the default product certificate
+ // 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
- // paths to extra certificates to sign the apk with
+ // Names of extra android_app_certificate modules to sign the apk with in the form ":module".
Additional_certificates []string
// If set, create package-export.apk, which other packages can
@@ -59,6 +63,11 @@
// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
// from PRODUCT_PACKAGES.
Overrides []string
+
+ // list of native libraries that will be provided in or alongside the resulting jar
+ Jni_libs []string `android:"arch_variant"`
+
+ EmbedJNI bool `blueprint:"mutated"`
}
type AndroidApp struct {
@@ -70,6 +79,8 @@
appProperties appProperties
extraLinkFlags []string
+
+ installJniLibs []jniLib
}
func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -92,9 +103,36 @@
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
+
if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
a.aapt.deps(ctx, sdkContext(a))
}
+
+ for _, jniTarget := range ctx.MultiTargets() {
+ variation := []blueprint.Variation{
+ {Mutator: "arch", Variation: jniTarget.String()},
+ {Mutator: "link", Variation: "shared"},
+ }
+ tag := &jniDependencyTag{
+ target: jniTarget,
+ }
+ ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+ }
+
+ cert := android.SrcIsModule(String(a.appProperties.Certificate))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
+
+ for _, cert := range a.appProperties.Additional_certificates {
+ cert = android.SrcIsModule(cert)
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ } else {
+ ctx.PropertyErrorf("additional_certificates",
+ `must be names of android_app_certificate modules in the form ":module"`)
+ }
+ }
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -150,35 +188,45 @@
a.Module.compile(ctx, a.aaptSrcJar)
}
- c := String(a.appProperties.Certificate)
- switch {
- case c == "":
- pem, key := ctx.Config().DefaultAppCertificate(ctx)
- a.certificate = certificate{pem, key}
- case strings.ContainsRune(c, '/'):
- a.certificate = certificate{
- android.PathForSource(ctx, c+".x509.pem"),
- android.PathForSource(ctx, c+".pk8"),
- }
- default:
- defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
- a.certificate = certificate{
- defaultDir.Join(ctx, c+".x509.pem"),
- defaultDir.Join(ctx, c+".pk8"),
- }
- }
-
- certificates := []certificate{a.certificate}
- for _, c := range a.appProperties.Additional_certificates {
- certificates = append(certificates, certificate{
- android.PathForSource(ctx, c+".x509.pem"),
- android.PathForSource(ctx, c+".pk8"),
- })
- }
-
packageFile := android.PathForModuleOut(ctx, "package.apk")
- CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)
+ var certificates []certificate
+
+ var jniJarFile android.WritablePath
+ jniLibs, certificateDeps := a.collectAppDeps(ctx)
+ if len(jniLibs) > 0 {
+ embedJni := ctx.Config().UnbundledBuild() || a.appProperties.EmbedJNI
+ if embedJni {
+ jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip")
+ TransformJniLibsToJar(ctx, jniJarFile, jniLibs)
+ } else {
+ a.installJniLibs = jniLibs
+ }
+ }
+
+ if ctx.Failed() {
+ return
+ }
+
+ cert := String(a.appProperties.Certificate)
+ 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"),
+ }
+ } else {
+ pem, key := ctx.Config().DefaultAppCertificate(ctx)
+ a.certificate = certificate{pem, key}
+ }
+
+ certificates = append([]certificate{a.certificate}, certificateDeps...)
+
+ CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, a.outputFile, certificates)
a.outputFile = packageFile
@@ -192,6 +240,42 @@
}
}
+func (a *AndroidApp) collectAppDeps(ctx android.ModuleContext) ([]jniLib, []certificate) {
+ var jniLibs []jniLib
+ var certificates []certificate
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ otherName := ctx.OtherModuleName(module)
+ tag := ctx.OtherModuleDependencyTag(module)
+
+ if jniTag, ok := tag.(*jniDependencyTag); ok {
+ if dep, ok := module.(*cc.Module); ok {
+ lib := dep.OutputFile()
+ if lib.Valid() {
+ jniLibs = append(jniLibs, jniLib{
+ name: ctx.OtherModuleName(module),
+ path: lib.Path(),
+ target: jniTag.target,
+ })
+ } else {
+ ctx.ModuleErrorf("dependency %q missing output file", otherName)
+ }
+ } else {
+ ctx.ModuleErrorf("jni_libs dependency %q must be a cc library", otherName)
+
+ }
+ } else if tag == certificateTag {
+ if dep, ok := module.(*AndroidAppCertificate); ok {
+ certificates = append(certificates, dep.certificate)
+ } else {
+ ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
+ }
+ }
+ })
+
+ return jniLibs, certificates
+}
+
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
@@ -208,7 +292,13 @@
&module.aaptProperties,
&module.appProperties)
- InitJavaModule(module, android.DeviceSupported)
+ module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
+ return class == android.Device && ctx.Config().DevicePrefer32BitApps()
+ })
+
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
return module
}
@@ -228,12 +318,6 @@
}
func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if String(a.appTestProperties.Instrumentation_for) != "" {
- a.AndroidApp.extraLinkFlags = append(a.AndroidApp.extraLinkFlags,
- "--rename-instrumentation-target-package",
- String(a.appTestProperties.Instrumentation_for))
- }
-
a.generateAndroidBuildActions(ctx)
a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath)
@@ -245,6 +329,12 @@
android.ExtractSourceDeps(ctx, a.testProperties.Test_config_template)
android.ExtractSourcesDeps(ctx, a.testProperties.Data)
a.AndroidApp.DepsMutator(ctx)
+ if a.appTestProperties.Instrumentation_for != nil {
+ // The android_app dependency listed in instrumentation_for needs to be added to the classpath for javac,
+ // but not added to the aapt2 link includes like a normal android_app or android_library dependency, so
+ // use instrumentationForTag instead of libTag.
+ ctx.AddVariationDependencies(nil, instrumentationForTag, String(a.appTestProperties.Instrumentation_for))
+ }
}
func AndroidTestFactory() android.Module {
@@ -254,6 +344,7 @@
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.appProperties.EmbedJNI = true
module.AddProperties(
&module.Module.properties,
@@ -264,6 +355,69 @@
&module.appTestProperties,
&module.testProperties)
- InitJavaModule(module, android.DeviceSupported)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
return module
}
+
+type appTestHelperAppProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+}
+
+type AndroidTestHelperApp struct {
+ AndroidApp
+
+ appTestHelperAppProperties appTestHelperAppProperties
+}
+
+func AndroidTestHelperAppFactory() android.Module {
+ module := &AndroidTestHelperApp{}
+
+ module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)
+
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.appProperties.EmbedJNI = true
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.deviceProperties,
+ &module.Module.protoProperties,
+ &module.aaptProperties,
+ &module.appProperties,
+ &module.appTestHelperAppProperties)
+
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+type AndroidAppCertificate struct {
+ android.ModuleBase
+ properties AndroidAppCertificateProperties
+ certificate certificate
+}
+
+type AndroidAppCertificateProperties struct {
+ // Name of the certificate files. Extensions .x509.pem and .pk8 will be added to the name.
+ Certificate *string
+}
+
+func AndroidAppCertificateFactory() android.Module {
+ module := &AndroidAppCertificate{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ return module
+}
+
+func (c *AndroidAppCertificate) DepsMutator(ctx android.BottomUpMutatorContext) {
+}
+
+func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ cert := String(c.properties.Certificate)
+ c.certificate = certificate{
+ android.PathForModuleSrc(ctx, cert+".x509.pem"),
+ android.PathForModuleSrc(ctx, cert+".pk8"),
+ }
+}
diff --git a/java/app_builder.go b/java/app_builder.go
index 954ca44..b9b5f43 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -19,9 +19,11 @@
// functions.
import (
+ "path/filepath"
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
)
@@ -61,16 +63,18 @@
})
func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- resJarFile, dexJarFile android.Path, certificates []certificate) {
-
- // TODO(ccross): JNI libs
+ resJarFile, jniJarFile, dexJarFile android.Path, certificates []certificate) {
unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
- inputs := android.Paths{resJarFile}
+ var inputs android.Paths
if dexJarFile != nil {
inputs = append(inputs, dexJarFile)
}
+ inputs = append(inputs, resJarFile)
+ if jniJarFile != nil {
+ inputs = append(inputs, jniJarFile)
+ }
ctx.Build(pctx, android.BuildParams{
Rule: combineApk,
@@ -103,10 +107,10 @@
`cp ${manifest} ${outDir}/AndroidManifest.xml && ` +
`cp ${classesJar} ${outDir}/classes.jar && ` +
`cp ${rTxt} ${outDir}/R.txt && ` +
- `${config.SoongZipCmd} -jar -o $out -C ${outDir} -D ${outDir} ${resArgs}`,
+ `${config.SoongZipCmd} -jar -o $out -C ${outDir} -D ${outDir}`,
CommandDeps: []string{"${config.SoongZipCmd}"},
},
- "manifest", "classesJar", "rTxt", "resArgs", "outDir")
+ "manifest", "classesJar", "rTxt", "outDir")
func BuildAAR(ctx android.ModuleContext, outputFile android.WritablePath,
classesJar, manifest, rTxt android.Path, res android.Paths) {
@@ -132,3 +136,37 @@
},
})
}
+
+func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.WritablePath,
+ jniLibs []jniLib) {
+
+ var deps android.Paths
+ jarArgs := []string{
+ "-j", // junk paths, they will be added back with -P arguments
+ }
+
+ if !ctx.Config().UnbundledBuild() {
+ jarArgs = append(jarArgs, "-L 0")
+ }
+
+ for _, j := range jniLibs {
+ deps = append(deps, j.path)
+ jarArgs = append(jarArgs,
+ "-P "+targetToJniDir(j.target),
+ "-f "+j.path.String())
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: zip,
+ Description: "zip jni libs",
+ Output: outputFile,
+ Implicits: deps,
+ Args: map[string]string{
+ "jarArgs": strings.Join(proptools.NinjaAndShellEscape(jarArgs), " "),
+ },
+ })
+}
+
+func targetToJniDir(target android.Target) string {
+ return filepath.Join("lib", target.Arch.Abi[0])
+}
diff --git a/java/app_test.go b/java/app_test.go
index c7c94ec..f6476dc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"fmt"
+ "path/filepath"
"reflect"
"sort"
"strings"
@@ -338,3 +339,118 @@
}
}
}
+
+func TestJNI(t *testing.T) {
+ ctx := testJava(t, `
+ toolchain_library {
+ name: "libcompiler_rt-extras",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libatomic",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libgcc",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-aarch64-android",
+ src: "",
+ }
+
+ toolchain_library {
+ name: "libclang_rt.builtins-arm-android",
+ src: "",
+ }
+
+ cc_object {
+ name: "crtbegin_so",
+ stl: "none",
+ }
+
+ cc_object {
+ name: "crtend_so",
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libjni",
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ android_test {
+ name: "test",
+ no_framework_libs: true,
+ jni_libs: ["libjni"],
+ }
+
+ android_test {
+ name: "test_first",
+ no_framework_libs: true,
+ compile_multilib: "first",
+ jni_libs: ["libjni"],
+ }
+
+ android_test {
+ name: "test_both",
+ no_framework_libs: true,
+ compile_multilib: "both",
+ jni_libs: ["libjni"],
+ }
+
+ android_test {
+ name: "test_32",
+ no_framework_libs: true,
+ compile_multilib: "32",
+ jni_libs: ["libjni"],
+ }
+
+ android_test {
+ name: "test_64",
+ no_framework_libs: true,
+ compile_multilib: "64",
+ jni_libs: ["libjni"],
+ }
+ `)
+
+ // check the existence of the internal modules
+ ctx.ModuleForTests("test", "android_common")
+ ctx.ModuleForTests("test_first", "android_common")
+ ctx.ModuleForTests("test_both", "android_common")
+ ctx.ModuleForTests("test_32", "android_common")
+ ctx.ModuleForTests("test_64", "android_common")
+
+ testCases := []struct {
+ name string
+ abis []string
+ }{
+ {"test", []string{"arm64-v8a"}},
+ {"test_first", []string{"arm64-v8a"}},
+ {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
+ {"test_32", []string{"armeabi-v7a"}},
+ {"test_64", []string{"arm64-v8a"}},
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ app := ctx.ModuleForTests(test.name, "android_common")
+ jniLibZip := app.Output("jnilibs.zip")
+ var abis []string
+ args := strings.Fields(jniLibZip.Args["jarArgs"])
+ for i := 0; i < len(args); i++ {
+ if args[i] == "-P" {
+ abis = append(abis, filepath.Base(args[i+1]))
+ i++
+ }
+ }
+ if !reflect.DeepEqual(abis, test.abis) {
+ t.Errorf("want abis %v, got %v", test.abis, abis)
+ }
+ })
+ }
+}
diff --git a/java/builder.go b/java/builder.go
index 48b5a7b..cefb916 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -109,6 +109,15 @@
},
"jarArgs")
+ zip = pctx.AndroidStaticRule("zip",
+ blueprint.RuleParams{
+ Command: `${config.SoongZipCmd} -o $out @$out.rsp`,
+ CommandDeps: []string{"${config.SoongZipCmd}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$jarArgs",
+ },
+ "jarArgs")
+
combineJar = pctx.AndroidStaticRule("combineJar",
blueprint.RuleParams{
Command: `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out $in`,
@@ -321,7 +330,7 @@
Output: outputFile,
Implicits: deps,
Args: map[string]string{
- "jarArgs": strings.Join(proptools.NinjaEscape(jarArgs), " "),
+ "jarArgs": strings.Join(proptools.NinjaAndShellEscape(jarArgs), " "),
},
})
}
@@ -390,6 +399,17 @@
})
}
+func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Description: "manifest",
+ Output: outputFile,
+ Args: map[string]string{
+ "content": "Main-Class: " + mainClass + "\n",
+ },
+ })
+}
+
type classpath []android.Path
func (x *classpath) FormJavaClassPath(optName string) string {
diff --git a/java/config/config.go b/java/config/config.go
index 3d27b70..d2a8c46 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -27,9 +27,9 @@
var (
pctx = android.NewPackageContext("android/soong/java/config")
- DefaultBootclasspathLibraries = []string{"core-oj", "core-libart", "core-simple"}
- DefaultSystemModules = "core-system-modules"
- DefaultLibraries = []string{"ext", "framework", "okhttp"}
+ DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"}
+ DefaultSystemModules = "core-platform-api-stubs-system-modules"
+ DefaultLibraries = []string{"ext", "framework"}
DefaultLambdaStubsLibrary = "core-lambda-stubs"
SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar"
diff --git a/java/dex.go b/java/dex.go
index 03316f6..625fb83 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -26,7 +26,7 @@
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`${config.D8Cmd} --output $outDir $d8Flags $in && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.D8Cmd}",
@@ -46,7 +46,7 @@
`-printmapping $outDict ` +
`$r8Flags && ` +
`touch "$outDict" && ` +
- `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.R8Cmd}",
@@ -157,6 +157,8 @@
if !Bool(opt.Obfuscate) {
r8Flags = append(r8Flags, "-dontobfuscate")
}
+ // TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
+ // dictionary of the app and move the app from libraryjars to injars.
return r8Flags, r8Deps
}
@@ -171,8 +173,6 @@
outDir := android.PathForModuleOut(ctx, "dex")
if useR8 {
- // TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
- // dictionary of the app and move the app from libraryjars to injars.
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
j.proguardDictionary = proguardDictionary
r8Flags, r8Deps := j.r8Flags(ctx, flags)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index bfe72f6..063f2c1 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -30,7 +30,7 @@
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
- `${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` +
+ `${config.SoongJavacWrapper} ${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` +
`$opts $bootclasspathArgs $classpathArgs $sourcepathArgs ` +
`-d $outDir -quiet && ` +
`${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` +
@@ -40,9 +40,10 @@
"${config.JavadocCmd}",
"${config.SoongZipCmd}",
},
- Rspfile: "$out.rsp",
- RspfileContent: "$in",
- Restat: true,
+ CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ Restat: true,
},
"outDir", "srcJarDir", "stubsDir", "srcJars", "opts",
"bootclasspathArgs", "classpathArgs", "sourcepathArgs", "docZip", "postDoclavaCmds")
@@ -1306,8 +1307,7 @@
}
flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath")
- flags.sourcepathArgs = "-sourcepath " + strings.Join(d.Javadoc.sourcepaths.Strings(), ":")
-
+ flags.sourcepathArgs = "-sourcepath \"" + strings.Join(d.Javadoc.sourcepaths.Strings(), ":") + "\""
return flags, nil
}
diff --git a/java/java.go b/java/java.go
index 7fd5344..d7068c6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -95,9 +95,6 @@
// list of java libraries that will be compiled into the resulting jar
Static_libs []string `android:"arch_variant"`
- // list of native libraries that will be provided in or alongside the resulting jar
- Jni_libs []string `android:"arch_variant"`
-
// manifest file to be included in resulting jar
Manifest *string
@@ -312,6 +309,9 @@
// list of extra progurad flag files
extraProguardFlagFiles android.Paths
+ // manifest file to use instead of properties.Manifest
+ overrideManifest android.OptionalPath
+
// list of SDK lib names that this java moudule is exporting
exportedSdkLibs []string
@@ -365,16 +365,23 @@
name string
}
+type jniDependencyTag struct {
+ blueprint.BaseDependencyTag
+ target android.Target
+}
+
var (
- staticLibTag = dependencyTag{name: "staticlib"}
- libTag = dependencyTag{name: "javalib"}
- annoTag = dependencyTag{name: "annotation processor"}
- bootClasspathTag = dependencyTag{name: "bootclasspath"}
- systemModulesTag = dependencyTag{name: "system modules"}
- frameworkResTag = dependencyTag{name: "framework-res"}
- frameworkApkTag = dependencyTag{name: "framework-apk"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
- proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ staticLibTag = dependencyTag{name: "staticlib"}
+ libTag = dependencyTag{name: "javalib"}
+ annoTag = dependencyTag{name: "annotation processor"}
+ bootClasspathTag = dependencyTag{name: "bootclasspath"}
+ systemModulesTag = dependencyTag{name: "system modules"}
+ frameworkResTag = dependencyTag{name: "framework-res"}
+ frameworkApkTag = dependencyTag{name: "framework-apk"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ certificateTag = dependencyTag{name: "certificate"}
+ instrumentationForTag = dependencyTag{name: "instrumentation_for"}
)
type sdkDep struct {
@@ -389,6 +396,12 @@
aidl android.Path
}
+type jniLib struct {
+ name string
+ path android.Path
+ target android.Target
+}
+
func (j *Module) shouldInstrument(ctx android.BaseContext) bool {
return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
}
@@ -597,6 +610,7 @@
ctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
}, annoTag, j.properties.Annotation_processors...)
+
android.ExtractSourcesDeps(ctx, j.properties.Srcs)
android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
@@ -787,6 +801,15 @@
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
+ if _, ok := tag.(*jniDependencyTag); ok {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+ if tag == certificateTag {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+
if to, ok := module.(*Library); ok {
switch tag {
case bootClasspathTag, libTag, staticLibTag:
@@ -798,7 +821,7 @@
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
- case libTag:
+ case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
@@ -892,7 +915,7 @@
ret = javaVersion
} else if ctx.Device() && sdk <= 23 {
ret = "1.7"
- } else if ctx.Device() && sdk <= 26 || !ctx.Config().TargetOpenJDK9() {
+ } else if ctx.Device() && sdk <= 28 || !ctx.Config().TargetOpenJDK9() {
ret = "1.8"
} else if ctx.Device() && sdkContext.sdkVersion() != "" && sdk == android.FutureApiLevel {
// TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
@@ -1174,8 +1197,8 @@
jars = append(jars, deps.staticJars...)
jars = append(jars, deps.staticResourceJars...)
- var manifest android.OptionalPath
- if j.properties.Manifest != nil {
+ manifest := j.overrideManifest
+ if !manifest.Valid() && j.properties.Manifest != nil {
manifest = android.OptionalPathForPath(ctx.ExpandSource(*j.properties.Manifest, "manifest"))
}
@@ -1493,7 +1516,6 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
InitJavaModule(module, android.HostAndDeviceSupported)
- android.InitDefaultableModule(module)
return module
}
@@ -1508,7 +1530,6 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
InitJavaModule(module, android.HostSupported)
- android.InitDefaultableModule(module)
return module
}
@@ -1519,6 +1540,9 @@
type binaryProperties struct {
// installable script to execute the resulting jar
Wrapper *string
+
+ // Name of the class containing main to be inserted into the manifest as Main-Class.
+ Main_class *string
}
type Binary struct {
@@ -1539,6 +1563,15 @@
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if ctx.Arch().ArchType == android.Common {
// Compile the jar
+ if j.binaryProperties.Main_class != nil {
+ if j.properties.Manifest != nil {
+ ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
+ }
+ manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
+ GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
+ j.overrideManifest = android.OptionalPathForPath(manifestFile)
+ }
+
j.Library.GenerateAndroidBuildActions(ctx)
} else {
// Handle the binary wrapper
@@ -1624,6 +1657,7 @@
type Import struct {
android.ModuleBase
+ android.DefaultableModuleBase
prebuilt android.Prebuilt
properties ImportProperties
@@ -1739,7 +1773,7 @@
// solution to get the Import name.
name := j.Name()
if strings.HasPrefix(name, removedPrefix) {
- name = strings.Trim(name, removedPrefix)
+ name = strings.TrimPrefix(name, removedPrefix)
}
return name
}
@@ -1752,7 +1786,7 @@
module.AddProperties(&module.properties)
android.InitPrebuiltModule(module, &module.properties.Jars)
- android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+ InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -1762,7 +1796,7 @@
module.AddProperties(&module.properties)
android.InitPrebuiltModule(module, &module.properties.Jars)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+ InitJavaModule(module, android.HostSupported)
return module
}
@@ -1792,6 +1826,13 @@
&CompilerProperties{},
&CompilerDeviceProperties{},
&android.ProtoProperties{},
+ &aaptProperties{},
+ &androidLibraryProperties{},
+ &appProperties{},
+ &appTestProperties{},
+ &ImportProperties{},
+ &AARImportProperties{},
+ &sdkLibraryProperties{},
)
android.InitDefaultsModule(module)
diff --git a/java/java_resources.go b/java/java_resources.go
index fdc1590..6c1fd39 100644
--- a/java/java_resources.go
+++ b/java/java_resources.go
@@ -19,6 +19,8 @@
"path/filepath"
"strings"
+ "github.com/google/blueprint/pathtools"
+
"android/soong/android"
)
@@ -64,7 +66,7 @@
if !strings.HasPrefix(path, dir.String()) {
panic(fmt.Errorf("path %q does not start with %q", path, dir))
}
- args = append(args, "-f", path)
+ args = append(args, "-f", pathtools.MatchEscape(path))
}
}
}
@@ -107,7 +109,7 @@
if i == 0 || dir != lastDir {
args = append(args, "-C", dir)
}
- args = append(args, "-f", path)
+ args = append(args, "-f", pathtools.MatchEscape(path))
lastDir = dir
}
diff --git a/java/java_test.go b/java/java_test.go
index 82accd5..86349fe 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -15,8 +15,6 @@
package java
import (
- "android/soong/android"
- "android/soong/genrule"
"fmt"
"io/ioutil"
"os"
@@ -27,6 +25,10 @@
"testing"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/genrule"
)
var buildDir string
@@ -73,6 +75,7 @@
ctx := android.NewTestArchContext()
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory))
ctx.RegisterModuleType("android_library", android.ModuleFactoryAdaptor(AndroidLibraryFactory))
+ ctx.RegisterModuleType("android_test", android.ModuleFactoryAdaptor(AndroidTestFactory))
ctx.RegisterModuleType("java_binary_host", android.ModuleFactoryAdaptor(BinaryHostFactory))
ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
ctx.RegisterModuleType("java_library_host", android.ModuleFactoryAdaptor(LibraryHostFactory))
@@ -95,20 +98,27 @@
ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
})
ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
+
+ // Register module types and mutators from cc needed for JNI testing
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+ ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+ ctx.BottomUp("begin", cc.BeginMutator).Parallel()
+ })
+
ctx.Register()
extraModules := []string{
- "core-oj",
- "core-libart",
"core-lambda-stubs",
- "core-simple",
"framework",
"ext",
- "okhttp",
"android_stubs_current",
"android_system_stubs_current",
"android_test_stubs_current",
"core.current.stubs",
+ "core.platform.api.stubs",
"kotlin-stdlib",
}
@@ -119,7 +129,7 @@
srcs: ["a.java"],
no_standard_libs: true,
sdk_version: "core_current",
- system_modules: "core-system-modules",
+ system_modules: "core-platform-api-stubs-system-modules",
}
`, extra)
}
@@ -133,6 +143,7 @@
systemModules := []string{
"core-system-modules",
+ "core-platform-api-stubs-system-modules",
"android_stubs_current_system_modules",
"android_system_stubs_current_system_modules",
"android_test_stubs_current_system_modules",
@@ -352,16 +363,16 @@
}{
{
name: "default",
- bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
- system: "core-system-modules",
- classpath: []string{"ext", "framework", "okhttp"},
+ bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+ system: "core-platform-api-stubs-system-modules",
+ classpath: []string{"ext", "framework"},
},
{
name: "blank sdk version",
properties: `sdk_version: "",`,
- bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
- system: "core-system-modules",
- classpath: []string{"ext", "framework", "okhttp"},
+ bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+ system: "core-platform-api-stubs-system-modules",
+ classpath: []string{"ext", "framework"},
},
{
@@ -418,8 +429,8 @@
{
name: "nostdlib system_modules",
- properties: `no_standard_libs: true, system_modules: "core-system-modules"`,
- system: "core-system-modules",
+ properties: `no_standard_libs: true, system_modules: "core-platform-api-stubs-system-modules"`,
+ system: "core-platform-api-stubs-system-modules",
bootclasspath: []string{`""`},
classpath: []string{},
},
@@ -1049,12 +1060,6 @@
name: "droiddoc-templates-sdk",
path: ".",
}
- java_library {
- name: "conscrypt",
- }
- java_library {
- name: "bouncycastle",
- }
java_sdk_library {
name: "foo",
srcs: ["a.java", "b.java"],
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 3e6908b..e513a59 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -128,6 +128,11 @@
// Defaults to "android.annotation".
Srcs_lib_whitelist_pkgs []string
+ // if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
+ // currently still used for documentation generation, and will be replaced by Dokka soon.
+ // Defaults to true.
+ Metalava_enabled *bool
+
// TODO: determines whether to create HTML doc or not
//Html_doc *bool
}
@@ -417,7 +422,6 @@
props := struct {
Name *string
Srcs []string
- Custom_template *string
Installable *bool
Srcs_lib *string
Srcs_lib_whitelist_dirs []string
@@ -436,11 +440,13 @@
Local_include_dirs []string
}
}{}
+ droiddocProps := struct {
+ Custom_template *string
+ }{}
props.Name = proptools.StringPtr(module.docsName(apiScope))
props.Srcs = append(props.Srcs, module.properties.Srcs...)
props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
- props.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
props.Installable = proptools.BoolPtr(false)
// A droiddoc module has only one Libs property and doesn't distinguish between
// shared libs and static libs. So we need to add both of these libs to Libs property.
@@ -449,10 +455,26 @@
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
- droiddocArgs := " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128" +
- " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
- " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, "-hidePackage ") +
- " " + android.JoinWithPrefix(module.properties.Droiddoc_options, "-") + " -nodocs"
+ if module.properties.Metalava_enabled == nil {
+ module.properties.Metalava_enabled = proptools.BoolPtr(true)
+ }
+
+ droiddocArgs := ""
+ if Bool(module.properties.Metalava_enabled) == true {
+ droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
+ " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
+ " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+ " --hide MissingPermission --hide BroadcastBehavior " +
+ "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+ "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+ } else {
+ droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
+ droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
+ " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
+ " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
+ " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
+ }
+
switch apiScope {
case apiScopeSystem:
droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
@@ -484,44 +506,52 @@
// check against the not-yet-release API
props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
- // any change is reported as error
- props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
- "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
- "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
- "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
// check against the latest released API
props.Check_api.Last_released.Api_file = proptools.StringPtr(
module.latestApiFilegroupName(apiScope))
props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
module.latestRemovedApiFilegroupName(apiScope))
- // backward incompatible changes are reported as error
- props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
- "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
- "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
- "-error 15 -error 16 -error 17 -error 18")
+ if Bool(module.properties.Metalava_enabled) == false {
+ // any change is reported as error
+ props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
+ "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
+ "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
+ "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
- // Include the part of the framework source. This is required for the case when
- // API class is extending from the framework class. In that case, doclava needs
- // to know whether the base class is hidden or not. Since that information is
- // encoded as @hide string in the comment, we need source files for the classes,
- // not the compiled ones.
- props.Srcs_lib = proptools.StringPtr("framework")
- props.Srcs_lib_whitelist_dirs = []string{"core/java"}
- // Add android.annotation package to give access to the framework-defined
- // annotations such as SystemApi, NonNull, etc.
- if module.properties.Srcs_lib_whitelist_pkgs != nil {
- props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
- } else {
- props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
+ // backward incompatible changes are reported as error
+ props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
+ "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
+ "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
+ "-error 15 -error 16 -error 17 -error 18")
+
+ // Include the part of the framework source. This is required for the case when
+ // API class is extending from the framework class. In that case, doclava needs
+ // to know whether the base class is hidden or not. Since that information is
+ // encoded as @hide string in the comment, we need source files for the classes,
+ // not the compiled ones.
+ props.Srcs_lib = proptools.StringPtr("framework")
+ props.Srcs_lib_whitelist_dirs = []string{"core/java"}
+
+ // Add android.annotation package to give access to the framework-defined
+ // annotations such as SystemApi, NonNull, etc.
+ if module.properties.Srcs_lib_whitelist_pkgs != nil {
+ props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
+ } else {
+ props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
+ }
}
// These libs are required by doclava to parse the framework sources add via
// Src_lib and Src_lib_whitelist_* properties just above.
// If we don't add them to the classpath, errors messages are generated by doclava,
// though they don't break the build.
- props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp", "framework")
+ props.Libs = append(props.Libs, "framework")
- mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
+ if Bool(module.properties.Metalava_enabled) == true {
+ mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
+ } else {
+ mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
+ }
}
// Creates the runtime library. This is not directly linkable from other modules.
@@ -691,7 +721,6 @@
module := &sdkLibrary{}
module.AddProperties(&module.properties)
module.AddProperties(&module.deviceProperties)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitDefaultableModule(module)
+ InitJavaModule(module, android.DeviceSupported)
return module
}
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index e686211..213401d 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -41,6 +41,7 @@
args = sys.argv[1:]
new_env = {}
+ runfiles_path = None
try:
runfiles_path = ExtractRunfiles()
@@ -82,7 +83,8 @@
except:
raise
finally:
- shutil.rmtree(runfiles_path, True)
+ if runfiles_path is not None:
+ shutil.rmtree(runfiles_path, True)
if __name__ == '__main__':
Main()
diff --git a/scripts/copygcclib.sh b/scripts/copygcclib.sh
deleted file mode 100755
index 28359fc..0000000
--- a/scripts/copygcclib.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash -e
-
-# Copyright 2017 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.
-
-OUT=$1
-shift
-LIBPATH=$($@ | sed -e "s|^$PWD/||")
-cp -f $LIBPATH $OUT
-echo "$OUT: $LIBPATH" > ${OUT}.d
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index b6fe34e..9256cb2 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -56,7 +56,9 @@
parser.add_argument('--library', dest='library', action='store_true',
help='manifest is for a static library')
parser.add_argument('--uses-library', dest='uses_libraries', action='append',
- help='specify additional <uses-library> tag to add')
+ help='specify additional <uses-library> tag to add. android:requred is set to true')
+ parser.add_argument('--optional-uses-library', dest='optional_uses_libraries', action='append',
+ help='specify additional <uses-library> tag to add. android:requred is set to false')
parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
help='manifest is for a package built against the platform')
parser.add_argument('input', help='input AndroidManifest.xml file')
@@ -179,18 +181,24 @@
if target_attr is None:
target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion')
if library:
- target_attr.value = '1'
+ # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but
+ # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it
+ # is empty. Set it to something low so that it will be overriden by the
+ # main manifest, but high enough that it doesn't cause implicit
+ # permissions grants.
+ target_attr.value = '15'
else:
target_attr.value = target_sdk_version
element.setAttributeNode(target_attr)
-def add_uses_libraries(doc, new_uses_libraries):
- """Add additional <uses-library> tags with android:required=true.
+def add_uses_libraries(doc, new_uses_libraries, required):
+ """Add additional <uses-library> tags
Args:
doc: The XML document. May be modified by this function.
new_uses_libraries: The names of libraries to be added by this function.
+ required: The value of android:required attribute. Can be true or false.
Raises:
RuntimeError: Invalid manifest
"""
@@ -222,7 +230,7 @@
ul = doc.createElement('uses-library')
ul.setAttributeNS(android_ns, 'android:name', name)
- ul.setAttributeNS(android_ns, 'android:required', 'true')
+ ul.setAttributeNS(android_ns, 'android:required', str(required).lower())
application.insertBefore(doc.createTextNode(indent), last)
application.insertBefore(ul, last)
@@ -280,7 +288,10 @@
raise_min_sdk_version(doc, args.min_sdk_version, args.target_sdk_version, args.library)
if args.uses_libraries:
- add_uses_libraries(doc, args.uses_libraries)
+ add_uses_libraries(doc, args.uses_libraries, True)
+
+ if args.optional_uses_libraries:
+ add_uses_libraries(doc, args.optional_uses_libraries, False)
if args.uses_non_sdk_api:
add_uses_non_sdk_api(doc)
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 66a2317..d1d401a 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -173,7 +173,7 @@
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='1')
+ expected = self.manifest_tmpl % self.uses_sdk(min='28', target='15')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assertEqual(output, expected)
@@ -189,7 +189,7 @@
"""Tests inserting targetSdkVersion when minSdkVersion does not exist."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='1')
+ expected = self.manifest_tmpl % self.uses_sdk(min='28', target='15')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assertEqual(output, expected)
diff --git a/scripts/strip.sh b/scripts/strip.sh
index bfc66ee..4634c18 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -54,7 +54,7 @@
# ${CROSS_COMPILE}strip --strip-all does not strip .ARM.attributes,
# so we tell llvm-strip to keep it too.
if [ ! -z "${use_llvm_strip}" ]; then
- "${CLANG_BIN}/llvm-strip" --strip-all -keep=.ARM.attributes "${infile}" "${outfile}.tmp"
+ "${CLANG_BIN}/llvm-strip" --strip-all -keep=.ARM.attributes "${infile}" -o "${outfile}.tmp"
else
"${CROSS_COMPILE}strip" --strip-all "${infile}" -o "${outfile}.tmp"
fi
@@ -75,7 +75,7 @@
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
local fail=
if [ ! -z "${use_llvm_strip}" ]; then
- "${CLANG_BIN}/llvm-strip" --strip-all -keep=.ARM.attributes -remove-section=.comment "${infile}" "${outfile}.tmp" || fail=true
+ "${CLANG_BIN}/llvm-strip" --strip-all -keep=.ARM.attributes -remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
else
"${CROSS_COMPILE}strip" --strip-all -R .comment "${infile}" -o "${outfile}.tmp" || fail=true
fi
@@ -98,6 +98,7 @@
else
"${CROSS_COMPILE}objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
fi
+ rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
else
cp -f "${infile}" "${outfile}.tmp"
fi
diff --git a/cmd/symbol_inject/Android.bp b/symbol_inject/Android.bp
similarity index 90%
rename from cmd/symbol_inject/Android.bp
rename to symbol_inject/Android.bp
index a2ea12b..8308043 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/symbol_inject/Android.bp
@@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-blueprint_go_binary {
- name: "symbol_inject",
+bootstrap_go_package {
+ name: "soong-symbol_inject",
+ pkgPath: "android/soong/symbol_inject",
srcs: [
"symbol_inject.go",
"elf.go",
diff --git a/cmd/symbol_inject/Android.bp b/symbol_inject/cmd/Android.bp
similarity index 71%
copy from cmd/symbol_inject/Android.bp
copy to symbol_inject/cmd/Android.bp
index a2ea12b..ee2f259 100644
--- a/cmd/symbol_inject/Android.bp
+++ b/symbol_inject/cmd/Android.bp
@@ -14,19 +14,8 @@
blueprint_go_binary {
name: "symbol_inject",
+ deps: ["soong-symbol_inject"],
srcs: [
"symbol_inject.go",
- "elf.go",
- "macho.go",
- "pe.go",
- ],
- testSrcs: [
- "elf_symboldata_test.go",
- "elf_test.go",
- "macho_symboldata_test.go",
- "macho_test.go",
- "pe_symboldata_test.go",
- "pe_test.go",
- "symbol_inject_test.go",
],
}
diff --git a/symbol_inject/cmd/symbol_inject.go b/symbol_inject/cmd/symbol_inject.go
new file mode 100644
index 0000000..1397b37
--- /dev/null
+++ b/symbol_inject/cmd/symbol_inject.go
@@ -0,0 +1,97 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+
+ "android/soong/symbol_inject"
+)
+
+var (
+ input = flag.String("i", "", "input file")
+ output = flag.String("o", "", "output file")
+ symbol = flag.String("s", "", "symbol to inject into")
+ from = flag.String("from", "", "optional existing value of the symbol for verification")
+ value = flag.String("v", "", "value to inject into symbol")
+
+ dump = flag.Bool("dump", false, "dump the symbol table for copying into a test")
+)
+
+func main() {
+ flag.Parse()
+
+ usageError := func(s string) {
+ fmt.Fprintln(os.Stderr, s)
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ if *input == "" {
+ usageError("-i is required")
+ }
+
+ if !*dump {
+ if *output == "" {
+ usageError("-o is required")
+ }
+
+ if *symbol == "" {
+ usageError("-s is required")
+ }
+
+ if *value == "" {
+ usageError("-v is required")
+ }
+ }
+
+ r, err := os.Open(*input)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(2)
+ }
+ defer r.Close()
+
+ if *dump {
+ err := symbol_inject.DumpSymbols(r)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(6)
+ }
+ return
+ }
+
+ w, err := os.OpenFile(*output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(3)
+ }
+ defer w.Close()
+
+ file, err := symbol_inject.OpenFile(r)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(4)
+ }
+
+ err = symbol_inject.InjectStringSymbol(file, w, *symbol, *value, *from)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Remove(*output)
+ os.Exit(5)
+ }
+}
diff --git a/cmd/symbol_inject/elf.go b/symbol_inject/elf.go
similarity index 99%
rename from cmd/symbol_inject/elf.go
rename to symbol_inject/elf.go
index d94877d..8742cbd 100644
--- a/cmd/symbol_inject/elf.go
+++ b/symbol_inject/elf.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/elf"
diff --git a/cmd/symbol_inject/elf_symboldata_test.go b/symbol_inject/elf_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/elf_symboldata_test.go
rename to symbol_inject/elf_symboldata_test.go
index 9ba7153..b2f1148 100644
--- a/cmd/symbol_inject/elf_symboldata_test.go
+++ b/symbol_inject/elf_symboldata_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import "debug/elf"
diff --git a/cmd/symbol_inject/elf_test.go b/symbol_inject/elf_test.go
similarity index 98%
rename from cmd/symbol_inject/elf_test.go
rename to symbol_inject/elf_test.go
index 30b46a5..aceee44 100644
--- a/cmd/symbol_inject/elf_test.go
+++ b/symbol_inject/elf_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"strconv"
diff --git a/cmd/symbol_inject/macho.go b/symbol_inject/macho.go
similarity index 98%
rename from cmd/symbol_inject/macho.go
rename to symbol_inject/macho.go
index be49f8b..6ee3f4f 100644
--- a/cmd/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/macho"
diff --git a/cmd/symbol_inject/macho_symboldata_test.go b/symbol_inject/macho_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/macho_symboldata_test.go
rename to symbol_inject/macho_symboldata_test.go
index 3100a81..7336a27 100644
--- a/cmd/symbol_inject/macho_symboldata_test.go
+++ b/symbol_inject/macho_symboldata_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/macho"
diff --git a/cmd/symbol_inject/macho_test.go b/symbol_inject/macho_test.go
similarity index 98%
rename from cmd/symbol_inject/macho_test.go
rename to symbol_inject/macho_test.go
index 7acab23..50df131 100644
--- a/cmd/symbol_inject/macho_test.go
+++ b/symbol_inject/macho_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/macho"
diff --git a/cmd/symbol_inject/pe.go b/symbol_inject/pe.go
similarity index 98%
rename from cmd/symbol_inject/pe.go
rename to symbol_inject/pe.go
index 12f35ee..58cf91a 100644
--- a/cmd/symbol_inject/pe.go
+++ b/symbol_inject/pe.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/pe"
diff --git a/cmd/symbol_inject/pe_symboldata_test.go b/symbol_inject/pe_symboldata_test.go
similarity index 99%
rename from cmd/symbol_inject/pe_symboldata_test.go
rename to symbol_inject/pe_symboldata_test.go
index edc1c97..5c0fd70 100644
--- a/cmd/symbol_inject/pe_symboldata_test.go
+++ b/symbol_inject/pe_symboldata_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/pe"
diff --git a/cmd/symbol_inject/pe_test.go b/symbol_inject/pe_test.go
similarity index 99%
rename from cmd/symbol_inject/pe_test.go
rename to symbol_inject/pe_test.go
index 21a0bc4..df7bac3 100644
--- a/cmd/symbol_inject/pe_test.go
+++ b/symbol_inject/pe_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"debug/pe"
diff --git a/cmd/symbol_inject/symbol_inject.go b/symbol_inject/symbol_inject.go
similarity index 70%
rename from cmd/symbol_inject/symbol_inject.go
rename to symbol_inject/symbol_inject.go
index d0f01c5..2a3d67e 100644
--- a/cmd/symbol_inject/symbol_inject.go
+++ b/symbol_inject/symbol_inject.go
@@ -12,25 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"bytes"
- "flag"
+ "encoding/binary"
"fmt"
"io"
"math"
- "os"
-)
-
-var (
- input = flag.String("i", "", "input file")
- output = flag.String("o", "", "output file")
- symbol = flag.String("s", "", "symbol to inject into")
- from = flag.String("from", "", "optional existing value of the symbol for verification")
- value = flag.String("v", "", "value to inject into symbol")
-
- dump = flag.Bool("dump", false, "dump the symbol table for copying into a test")
)
var maxUint64 uint64 = math.MaxUint64
@@ -39,71 +28,7 @@
error
}
-func main() {
- flag.Parse()
-
- usageError := func(s string) {
- fmt.Fprintln(os.Stderr, s)
- flag.Usage()
- os.Exit(1)
- }
-
- if *input == "" {
- usageError("-i is required")
- }
-
- if !*dump {
- if *output == "" {
- usageError("-o is required")
- }
-
- if *symbol == "" {
- usageError("-s is required")
- }
-
- if *value == "" {
- usageError("-v is required")
- }
- }
-
- r, err := os.Open(*input)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(2)
- }
- defer r.Close()
-
- if *dump {
- err := dumpSymbols(r)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(6)
- }
- return
- }
-
- w, err := os.OpenFile(*output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(3)
- }
- defer w.Close()
-
- file, err := openFile(r)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(4)
- }
-
- err = injectSymbol(file, w, *symbol, *value, *from)
- if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
- os.Remove(*output)
- os.Exit(5)
- }
-}
-
-func openFile(r io.ReaderAt) (*File, error) {
+func OpenFile(r io.ReaderAt) (*File, error) {
file, err := elfSymbolsFromFile(r)
if elfError, ok := err.(cantParseError); ok {
// Try as a mach-o file
@@ -126,7 +51,7 @@
return file, err
}
-func injectSymbol(file *File, w io.Writer, symbol, value, from string) error {
+func InjectStringSymbol(file *File, w io.Writer, symbol, value, from string) error {
offset, size, err := findSymbol(file, symbol)
if err != nil {
return err
@@ -151,13 +76,29 @@
}
}
- return copyAndInject(file.r, w, offset, size, value)
-}
-
-func copyAndInject(r io.ReaderAt, w io.Writer, offset, size uint64, value string) (err error) {
buf := make([]byte, size)
copy(buf, value)
+ return copyAndInject(file.r, w, offset, buf)
+}
+
+func InjectUint64Symbol(file *File, w io.Writer, symbol string, value uint64) error {
+ offset, size, err := findSymbol(file, symbol)
+ if err != nil {
+ return err
+ }
+
+ if size != 8 {
+ return fmt.Errorf("symbol %q is not a uint64, it is %d bytes long", symbol, size)
+ }
+
+ buf := make([]byte, 8)
+ binary.LittleEndian.PutUint64(buf, value)
+
+ return copyAndInject(file.r, w, offset, buf)
+}
+
+func copyAndInject(r io.ReaderAt, w io.Writer, offset uint64, buf []byte) (err error) {
// Copy the first bytes up to the symbol offset
_, err = io.Copy(w, io.NewSectionReader(r, 0, int64(offset)))
@@ -167,7 +108,7 @@
}
// Write the remainder of the file
- pos := int64(offset + size)
+ pos := int64(offset) + int64(len(buf))
if err == nil {
_, err = io.Copy(w, io.NewSectionReader(r, pos, 1<<63-1-pos))
}
@@ -239,7 +180,7 @@
Size uint64
}
-func dumpSymbols(r io.ReaderAt) error {
+func DumpSymbols(r io.ReaderAt) error {
err := dumpElfSymbols(r)
if elfError, ok := err.(cantParseError); ok {
// Try as a mach-o file
diff --git a/cmd/symbol_inject/symbol_inject_test.go b/symbol_inject/symbol_inject_test.go
similarity index 77%
rename from cmd/symbol_inject/symbol_inject_test.go
rename to symbol_inject/symbol_inject_test.go
index dbee39a..6607e65 100644
--- a/cmd/symbol_inject/symbol_inject_test.go
+++ b/symbol_inject/symbol_inject_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package symbol_inject
import (
"bytes"
@@ -23,32 +23,23 @@
func TestCopyAndInject(t *testing.T) {
s := "abcdefghijklmnopqrstuvwxyz"
testCases := []struct {
- offset, size uint64
- value string
- expected string
+ offset uint64
+ buf string
+ expected string
}{
{
offset: 0,
- size: 1,
- value: "A",
+ buf: "A",
expected: "Abcdefghijklmnopqrstuvwxyz",
},
{
offset: 1,
- size: 1,
- value: "B",
- expected: "aBcdefghijklmnopqrstuvwxyz",
- },
- {
- offset: 1,
- size: 1,
- value: "BCD",
+ buf: "B",
expected: "aBcdefghijklmnopqrstuvwxyz",
},
{
offset: 25,
- size: 1,
- value: "Z",
+ buf: "Z",
expected: "abcdefghijklmnopqrstuvwxyZ",
},
}
@@ -57,7 +48,7 @@
t.Run(strconv.Itoa(i), func(t *testing.T) {
in := bytes.NewReader([]byte(s))
out := &bytes.Buffer{}
- copyAndInject(in, out, testCase.offset, testCase.size, testCase.value)
+ copyAndInject(in, out, testCase.offset, []byte(testCase.buf))
if out.String() != testCase.expected {
t.Errorf("expected %s, got %s", testCase.expected, out.String())
diff --git a/ui/build/build.go b/ui/build/build.go
index 377481b..c902a0f 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -40,9 +40,10 @@
pool local_pool
depth = {{.Parallel}}
build _kati_always_build_: phony
-{{if .HasKatiSuffix}}include {{.KatiBuildNinjaFile}}
+{{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
+subninja {{.KatiPackageNinjaFile}}
{{end -}}
-include {{.SoongNinjaFile}}
+subninja {{.SoongNinjaFile}}
`))
func createCombinedBuildNinjaFile(ctx Context, config Config) {
@@ -180,6 +181,7 @@
genKatiSuffix(ctx, config)
runKatiCleanSpec(ctx, config)
runKatiBuild(ctx, config)
+ runKatiPackage(ctx, config)
ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
} else {
diff --git a/ui/build/config.go b/ui/build/config.go
index d470b96..840f505 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -34,6 +34,7 @@
arguments []string
goma bool
environ *Environment
+ distDir string
// From the arguments
parallel int
@@ -86,6 +87,12 @@
ret.environ.Set("OUT_DIR", outDir)
}
+ if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
+ ret.distDir = filepath.Clean(distDir)
+ } else {
+ ret.distDir = filepath.Join(ret.OutDir(), "dist")
+ }
+
ret.environ.Unset(
// We're already using it
"USE_SOONG_UI",
@@ -107,6 +114,9 @@
// We handle this above
"OUT_DIR_COMMON_BASE",
+ // This is handled above too, and set for individual commands later
+ "DIST_DIR",
+
// Variables that have caused problems in the past
"CDPATH",
"DISPLAY",
@@ -248,10 +258,10 @@
}
} else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
c.environ.Set(k, v)
+ } else if arg == "dist" {
+ c.dist = true
} else {
- if arg == "dist" {
- c.dist = true
- } else if arg == "checkbuild" {
+ if arg == "checkbuild" {
c.checkbuild = true
}
c.arguments = append(c.arguments, arg)
@@ -375,10 +385,7 @@
}
func (c *configImpl) DistDir() string {
- if distDir, ok := c.environ.Get("DIST_DIR"); ok {
- return filepath.Clean(distDir)
- }
- return filepath.Join(c.OutDir(), "dist")
+ return c.distDir
}
func (c *configImpl) NinjaArgs() []string {
@@ -505,6 +512,10 @@
return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
}
+func (c *configImpl) KatiPackageNinjaFile() string {
+ return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
+}
+
func (c *configImpl) SoongNinjaFile() string {
return filepath.Join(c.SoongOutDir(), "build.ninja")
}
@@ -532,6 +543,10 @@
return filepath.Join(c.ProductOut(), "previous_build_config.mk")
}
+func (c *configImpl) KatiPackageMkDir() string {
+ return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
+}
+
func (c *configImpl) hostOutRoot() string {
return filepath.Join(c.OutDir(), "host")
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index ffea841..ad57d02 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -32,8 +32,40 @@
//
// vars is the list of variables to read. The values will be put in the
// returned map.
+//
+// variables controlled by soong_ui directly are now returned without needing
+// to call into make, to retain compatibility.
func DumpMakeVars(ctx Context, config Config, goals, vars []string) (map[string]string, error) {
- return dumpMakeVars(ctx, config, goals, vars, false)
+ soongUiVars := map[string]func() string{
+ "OUT_DIR": func() string { return config.OutDir() },
+ "DIST_DIR": func() string { return config.DistDir() },
+ }
+
+ makeVars := make([]string, 0, len(vars))
+ for _, v := range vars {
+ if _, ok := soongUiVars[v]; !ok {
+ makeVars = append(makeVars, v)
+ }
+ }
+
+ var ret map[string]string
+ if len(makeVars) > 0 {
+ var err error
+ ret, err = dumpMakeVars(ctx, config, goals, makeVars, false)
+ if err != nil {
+ return ret, err
+ }
+ } else {
+ ret = make(map[string]string)
+ }
+
+ for _, v := range vars {
+ if f, ok := soongUiVars[v]; ok {
+ ret[v] = f()
+ }
+ }
+
+ return ret, nil
}
func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_vars bool) (map[string]string, error) {
@@ -48,7 +80,6 @@
"dump-many-vars",
"MAKECMDGOALS="+strings.Join(goals, " "))
cmd.Environment.Set("CALLED_FROM_SETUP", "true")
- cmd.Environment.Set("BUILD_SYSTEM", "build/make/core")
if write_soong_vars {
cmd.Environment.Set("WRITE_SOONG_VARIABLES", "true")
}
diff --git a/ui/build/environment.go b/ui/build/environment.go
index cbeeb4b..d8ff7f2 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -75,6 +75,17 @@
*e = out
}
+// Allow removes all keys that are not present in the input list
+func (e *Environment) Allow(keys ...string) {
+ out := (*e)[:0]
+ for _, env := range *e {
+ if key, _, ok := decodeKeyValue(env); ok && inList(key, keys) {
+ out = append(out, env)
+ }
+ }
+ *e = out
+}
+
// Environ returns the []string required for exec.Cmd.Env
func (e *Environment) Environ() []string {
return []string(*e)
diff --git a/ui/build/environment_test.go b/ui/build/environment_test.go
index 0294dac..37f500f 100644
--- a/ui/build/environment_test.go
+++ b/ui/build/environment_test.go
@@ -56,6 +56,15 @@
}
}
+func TestEnvAllow(t *testing.T) {
+ initial := &Environment{"TEST=1", "TEST2=0", "TEST3=2"}
+ initial.Allow("TEST3", "TEST")
+ got := initial.Environ()
+ if len(got) != 2 || got[0] != "TEST=1" || got[1] != "TEST3=2" {
+ t.Errorf("Expected [TEST=1 TEST3=2], got: %v", got)
+ }
+}
+
const testKatiEnvFileContents = `#!/bin/sh
# Generated by kati unknown
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 546fd1a..56e9a88 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -28,6 +28,7 @@
const katiBuildSuffix = ""
const katiCleanspecSuffix = "-cleanspec"
+const katiPackageSuffix = "-package"
// genKatiSuffix creates a suffix for kati-generated files so that we can cache
// them based on their inputs. So this should encode all common changes to Kati
@@ -59,7 +60,7 @@
}
}
-func runKati(ctx Context, config Config, extraSuffix string, args []string) {
+func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) {
executable := config.PrebuiltBuildTool("ckati")
args = append([]string{
"--ninja",
@@ -80,10 +81,6 @@
"--kati_stats",
}, args...)
- args = append(args,
- "SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
- "TARGET_DEVICE_DIR="+config.TargetDeviceDir())
-
cmd := Command(ctx, config, "ckati", executable, args...)
cmd.Sandbox = katiSandbox
pipe, err := cmd.StdoutPipe()
@@ -92,6 +89,8 @@
}
cmd.Stderr = cmd.Stdout
+ envFunc(cmd.Environment)
+
cmd.StartOrFatal()
status.KatiReader(ctx.Status.StartTool(), pipe)
cmd.WaitOrFatal()
@@ -103,7 +102,6 @@
args := []string{
"--writable", config.OutDir() + "/",
- "--writable", config.DistDir() + "/",
"-f", "build/make/core/main.mk",
}
@@ -125,9 +123,54 @@
args = append(args, config.KatiArgs()...)
- args = append(args, "SOONG_ANDROID_MK="+config.SoongAndroidMk())
+ args = append(args,
+ "SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
+ "SOONG_ANDROID_MK="+config.SoongAndroidMk(),
+ "TARGET_DEVICE_DIR="+config.TargetDeviceDir(),
+ "KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())
- runKati(ctx, config, katiBuildSuffix, args)
+ runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
+}
+
+func runKatiPackage(ctx Context, config Config) {
+ ctx.BeginTrace("kati package")
+ defer ctx.EndTrace()
+
+ args := []string{
+ "--writable", config.DistDir() + "/",
+ "--werror_writable",
+ "--werror_implicit_rules",
+ "--werror_overriding_commands",
+ "--werror_real_to_phony",
+ "--werror_phony_looks_real",
+ "-f", "build/make/packaging/main.mk",
+ "KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(),
+ }
+
+ runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) {
+ env.Allow([]string{
+ // Some generic basics
+ "LANG",
+ "LC_MESSAGES",
+ "PATH",
+ "PWD",
+ "TMPDIR",
+
+ // Tool configs
+ "JAVA_HOME",
+ "PYTHONDONTWRITEBYTECODE",
+
+ // Build configuration
+ "ANDROID_BUILD_SHELL",
+ "DIST_DIR",
+ "OUT_DIR",
+ }...)
+
+ if config.Dist() {
+ env.Set("DIST", "true")
+ env.Set("DIST_DIR", config.DistDir())
+ }
+ })
}
func runKatiCleanSpec(ctx Context, config Config) {
@@ -138,5 +181,7 @@
"--werror_implicit_rules",
"--werror_overriding_commands",
"-f", "build/make/core/cleanbuild.mk",
- })
+ "SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
+ "TARGET_DEVICE_DIR=" + config.TargetDeviceDir(),
+ }, func(env *Environment) {})
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 91cb475..c8f19d1 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -60,6 +60,8 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
+ cmd.Environment.Set("DIST_DIR", config.DistDir())
+
// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
// used in the past to specify extra ninja arguments.
if extra, ok := cmd.Environment.Get("NINJA_ARGS"); ok {
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 7886466..c4fcc20 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -39,6 +39,12 @@
Error: true,
}
+var Log = PathConfig{
+ Symlink: true,
+ Log: true,
+ Error: false,
+}
+
// The configuration used if the tool is not listed in the config below.
// Currently this will create the symlink, but log and error when it's used. In
// the future, I expect the symlink to be removed, and this will be equivalent
@@ -95,7 +101,6 @@
"ls": Allowed,
"lsof": Allowed,
"m4": Allowed,
- "make": Allowed,
"md5sum": Allowed,
"mkdir": Allowed,
"mktemp": Allowed,
@@ -104,7 +109,6 @@
"openssl": Allowed,
"paste": Allowed,
"patch": Allowed,
- "perl": Allowed,
"pgrep": Allowed,
"pkill": Allowed,
"ps": Allowed,
@@ -128,7 +132,6 @@
"sleep": Allowed,
"sort": Allowed,
"stat": Allowed,
- "sum": Allowed,
"tar": Allowed,
"tail": Allowed,
"tee": Allowed,
@@ -144,7 +147,6 @@
"which": Allowed,
"whoami": Allowed,
"xargs": Allowed,
- "xmllint": Allowed,
"xxd": Allowed,
"xz": Allowed,
"zip": Allowed,
diff --git a/ui/status/kati.go b/ui/status/kati.go
index 552a9e9..7c26d42 100644
--- a/ui/status/kati.go
+++ b/ui/status/kati.go
@@ -24,7 +24,7 @@
)
var katiError = regexp.MustCompile(`^(\033\[1m)?[^ ]+:[0-9]+: (\033\[31m)?error:`)
-var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including [^ ]+|initializing build system|finishing build rules|writing build rules) ...)$`)
+var katiIncludeRe = regexp.MustCompile(`^(\[(\d+)/(\d+)] )?((including [^ ]+|initializing (build|packaging) system|finishing (build|packaging) rules|writing (build|packaging) rules) ...)$`)
var katiLogRe = regexp.MustCompile(`^\*kati\*: `)
var katiNinjaMissing = regexp.MustCompile("^[^ ]+ is missing, regenerating...$")
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index 1125602..b4f75f7 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -136,6 +136,8 @@
compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
+ ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist")
+ symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them")
parallelJobs := flags.Int("parallel", runtime.NumCPU(), "number of parallel threads to use")
cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
@@ -197,9 +199,11 @@
NumParallelJobs: *parallelJobs,
NonDeflatedFiles: nonDeflatedFiles,
WriteIfChanged: *writeIfChanged,
+ StoreSymlinks: *symlinks,
+ IgnoreMissingFiles: *ignoreMissingFiles,
})
if err != nil {
- fmt.Fprintln(os.Stderr, err.Error())
+ fmt.Fprintln(os.Stderr, "error:", err.Error())
os.Exit(1)
}
}
diff --git a/zip/zip.go b/zip/zip.go
index e7de6f8..774966a 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -27,6 +27,7 @@
"sort"
"strings"
"sync"
+ "syscall"
"time"
"unicode"
@@ -163,6 +164,15 @@
return b.fileArgs
}
+type IncorrectRelativeRootError struct {
+ RelativeRoot string
+ Path string
+}
+
+func (x IncorrectRelativeRootError) Error() string {
+ return fmt.Sprintf("path %q is outside relative root %q", x.Path, x.RelativeRoot)
+}
+
type ZipWriter struct {
time time.Time
createdFiles map[string]string
@@ -178,7 +188,11 @@
compressorPool sync.Pool
compLevel int
- fs pathtools.FileSystem
+ followSymlinks pathtools.ShouldFollowSymlinks
+ ignoreMissingFiles bool
+
+ stderr io.Writer
+ fs pathtools.FileSystem
}
type zipEntry struct {
@@ -202,7 +216,11 @@
NumParallelJobs int
NonDeflatedFiles map[string]bool
WriteIfChanged bool
- Filesystem pathtools.FileSystem
+ StoreSymlinks bool
+ IgnoreMissingFiles bool
+
+ Stderr io.Writer
+ Filesystem pathtools.FileSystem
}
const NOQUOTE = '\x00'
@@ -253,27 +271,90 @@
args.AddDirectoryEntriesToZip = true
}
+ // Have Glob follow symlinks if they are not being stored as symlinks in the zip file.
+ followSymlinks := pathtools.ShouldFollowSymlinks(!args.StoreSymlinks)
+
z := &ZipWriter{
- time: jar.DefaultTime,
- createdDirs: make(map[string]string),
- createdFiles: make(map[string]string),
- directories: args.AddDirectoryEntriesToZip,
- compLevel: args.CompressionLevel,
- fs: args.Filesystem,
+ time: jar.DefaultTime,
+ createdDirs: make(map[string]string),
+ createdFiles: make(map[string]string),
+ directories: args.AddDirectoryEntriesToZip,
+ compLevel: args.CompressionLevel,
+ followSymlinks: followSymlinks,
+ ignoreMissingFiles: args.IgnoreMissingFiles,
+ stderr: args.Stderr,
+ fs: args.Filesystem,
}
if z.fs == nil {
z.fs = pathtools.OsFs
}
+ if z.stderr == nil {
+ z.stderr = os.Stderr
+ }
+
pathMappings := []pathMapping{}
noCompression := args.CompressionLevel == 0
for _, fa := range args.FileArgs {
- srcs := fa.SourceFiles
+ var srcs []string
+ for _, s := range fa.SourceFiles {
+ s = strings.TrimSpace(s)
+ if s == "" {
+ continue
+ }
+
+ globbed, _, err := z.fs.Glob(s, nil, followSymlinks)
+ if err != nil {
+ return err
+ }
+ if len(globbed) == 0 {
+ err := &os.PathError{
+ Op: "lstat",
+ Path: s,
+ Err: os.ErrNotExist,
+ }
+ if args.IgnoreMissingFiles {
+ fmt.Fprintln(args.Stderr, "warning:", err)
+ } else {
+ return err
+ }
+ }
+ srcs = append(srcs, globbed...)
+ }
if fa.GlobDir != "" {
- srcs = append(srcs, recursiveGlobFiles(fa.GlobDir)...)
+ if exists, isDir, err := z.fs.Exists(fa.GlobDir); err != nil {
+ return err
+ } else if !exists && !args.IgnoreMissingFiles {
+ err := &os.PathError{
+ Op: "lstat",
+ Path: fa.GlobDir,
+ Err: os.ErrNotExist,
+ }
+ if args.IgnoreMissingFiles {
+ fmt.Fprintln(args.Stderr, "warning:", err)
+ } else {
+ return err
+ }
+ } else if !isDir && !args.IgnoreMissingFiles {
+ err := &os.PathError{
+ Op: "lstat",
+ Path: fa.GlobDir,
+ Err: syscall.ENOTDIR,
+ }
+ if args.IgnoreMissingFiles {
+ fmt.Fprintln(args.Stderr, "warning:", err)
+ } else {
+ return err
+ }
+ }
+ globbed, _, err := z.fs.Glob(filepath.Join(fa.GlobDir, "**/*"), nil, followSymlinks)
+ if err != nil {
+ return err
+ }
+ srcs = append(srcs, globbed...)
}
for _, src := range srcs {
err := fillPathPairs(fa, src, &pathMappings, args.NonDeflatedFiles, noCompression)
@@ -328,11 +409,6 @@
func fillPathPairs(fa FileArg, src string, pathMappings *[]pathMapping,
nonDeflatedFiles map[string]bool, noCompression bool) error {
- src = strings.TrimSpace(src)
- if src == "" {
- return nil
- }
- src = filepath.Clean(src)
var dest string
if fa.JunkPaths {
@@ -343,6 +419,13 @@
if err != nil {
return err
}
+ if strings.HasPrefix(dest, "../") {
+ return IncorrectRelativeRootError{
+ Path: src,
+ RelativeRoot: fa.SourcePrefixToStrip,
+ }
+ }
+
}
dest = filepath.Join(fa.PathPrefixInZip, dest)
@@ -509,7 +592,19 @@
var fileSize int64
var executable bool
- if s, err := z.fs.Lstat(src); err != nil {
+ var s os.FileInfo
+ var err error
+ if z.followSymlinks {
+ s, err = z.fs.Stat(src)
+ } else {
+ s, err = z.fs.Lstat(src)
+ }
+
+ if err != nil {
+ if os.IsNotExist(err) && z.ignoreMissingFiles {
+ fmt.Fprintln(z.stderr, "warning:", err)
+ return nil
+ }
return err
} else if s.IsDir() {
if z.directories {
@@ -889,15 +984,3 @@
return nil
}
-
-func recursiveGlobFiles(path string) []string {
- var files []string
- filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
- if !info.IsDir() {
- files = append(files, path)
- }
- return nil
- })
-
- return files
-}
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 0c2105c..93c5f3d 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -98,13 +98,15 @@
func TestZip(t *testing.T) {
testCases := []struct {
- name string
- args *FileArgsBuilder
- compressionLevel int
- emulateJar bool
- nonDeflatedFiles map[string]bool
- dirEntries bool
- manifest string
+ name string
+ args *FileArgsBuilder
+ compressionLevel int
+ emulateJar bool
+ nonDeflatedFiles map[string]bool
+ dirEntries bool
+ manifest string
+ storeSymlinks bool
+ ignoreMissingFiles bool
files []zip.FileHeader
err error
@@ -130,6 +132,36 @@
},
},
{
+ name: "files glob",
+ args: fileArgsBuilder().
+ SourcePrefixToStrip("a").
+ File("a/**/*"),
+ compressionLevel: 9,
+ storeSymlinks: true,
+
+ files: []zip.FileHeader{
+ fh("a/a", fileA, zip.Deflate),
+ fh("a/b", fileB, zip.Deflate),
+ fhLink("a/c", "../../c"),
+ fhLink("a/d", "b"),
+ },
+ },
+ {
+ name: "dir",
+ args: fileArgsBuilder().
+ SourcePrefixToStrip("a").
+ Dir("a"),
+ compressionLevel: 9,
+ storeSymlinks: true,
+
+ files: []zip.FileHeader{
+ fh("a/a", fileA, zip.Deflate),
+ fh("a/b", fileB, zip.Deflate),
+ fhLink("a/c", "../../c"),
+ fhLink("a/d", "b"),
+ },
+ },
+ {
name: "stored files",
args: fileArgsBuilder().
File("a/a/a").
@@ -151,6 +183,7 @@
File("a/a/c").
File("a/a/d"),
compressionLevel: 9,
+ storeSymlinks: true,
files: []zip.FileHeader{
fh("a/a/a", fileA, zip.Deflate),
@@ -160,6 +193,23 @@
},
},
{
+ name: "follow symlinks",
+ args: fileArgsBuilder().
+ File("a/a/a").
+ File("a/a/b").
+ File("a/a/c").
+ File("a/a/d"),
+ compressionLevel: 9,
+ storeSymlinks: false,
+
+ files: []zip.FileHeader{
+ fh("a/a/a", fileA, zip.Deflate),
+ fh("a/a/b", fileB, zip.Deflate),
+ fh("a/a/c", fileC, zip.Deflate),
+ fh("a/a/d", fileB, zip.Deflate),
+ },
+ },
+ {
name: "list",
args: fileArgsBuilder().
List("l"),
@@ -289,6 +339,20 @@
fh("a/a/b", fileB, zip.Deflate),
},
},
+ {
+ name: "ignore missing files",
+ args: fileArgsBuilder().
+ File("a/a/a").
+ File("a/a/b").
+ File("missing"),
+ compressionLevel: 9,
+ ignoreMissingFiles: true,
+
+ files: []zip.FileHeader{
+ fh("a/a/a", fileA, zip.Deflate),
+ fh("a/a/b", fileB, zip.Deflate),
+ },
+ },
// errors
{
@@ -298,11 +362,24 @@
err: os.ErrNotExist,
},
{
+ name: "error missing dir",
+ args: fileArgsBuilder().
+ Dir("missing"),
+ err: os.ErrNotExist,
+ },
+ {
name: "error missing file in list",
args: fileArgsBuilder().
List("l2"),
err: os.ErrNotExist,
},
+ {
+ name: "error incorrect relative root",
+ args: fileArgsBuilder().
+ SourcePrefixToStrip("b").
+ File("a/a/a"),
+ err: IncorrectRelativeRootError{},
+ },
}
for _, test := range testCases {
@@ -318,7 +395,10 @@
args.AddDirectoryEntriesToZip = test.dirEntries
args.NonDeflatedFiles = test.nonDeflatedFiles
args.ManifestSourcePath = test.manifest
+ args.StoreSymlinks = test.storeSymlinks
+ args.IgnoreMissingFiles = test.ignoreMissingFiles
args.Filesystem = mockFs
+ args.Stderr = &bytes.Buffer{}
buf := &bytes.Buffer{}
err := ZipTo(args, buf)
@@ -330,6 +410,10 @@
if !os.IsNotExist(test.err) {
t.Fatalf("want error %v, got %v", test.err, err)
}
+ } else if _, wantRelativeRootErr := test.err.(IncorrectRelativeRootError); wantRelativeRootErr {
+ if _, gotRelativeRootErr := err.(IncorrectRelativeRootError); !gotRelativeRootErr {
+ t.Fatalf("want error %v, got %v", test.err, err)
+ }
} else {
t.Fatalf("want error %v, got %v", test.err, err)
}