Merge "Fix soong crashing when there's no baseline file" into rvc-dev am: 8b9273d99e
Change-Id: Ibd30b9ef0800d98bd242d0c39c343d9a646242af
diff --git a/Android.bp b/Android.bp
index a81676f..a9eceb2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,6 +39,7 @@
"soong-android-soongconfig",
"soong-env",
"soong-shared",
+ "soong-ui-metrics_proto",
],
srcs: [
"android/androidmk.go",
@@ -54,6 +55,7 @@
"android/hooks.go",
"android/image.go",
"android/makevars.go",
+ "android/metrics.go",
"android/module.go",
"android/mutator.go",
"android/namespace.go",
@@ -142,8 +144,6 @@
"cc/config/arm_device.go",
"cc/config/arm64_device.go",
"cc/config/arm64_fuchsia_device.go",
- "cc/config/mips_device.go",
- "cc/config/mips64_device.go",
"cc/config/x86_device.go",
"cc/config/x86_64_device.go",
"cc/config/x86_64_fuchsia_device.go",
@@ -349,6 +349,7 @@
deps: [
"blueprint-proptools",
"soong-android",
+ "soong-remoteexec",
],
srcs: [
"java/config/config.go",
@@ -644,7 +645,8 @@
arch: {
arm: {
src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
- repack_objects_to_keep: ["unwind-arm.o", "libunwind.o", "pr-support.o"],
+ repack_objects_to_keep: [],
+ enabled: false,
},
arm64: {
src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
diff --git a/OWNERS b/OWNERS
index 4ae045d..e1db459 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,4 @@
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
per-file tidy.go = srhines@google.com, chh@google.com
per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
+per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
diff --git a/android/androidmk.go b/android/androidmk.go
index 6ba68af..d579e30 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -244,8 +244,8 @@
}
}
- if amod.noticeFile.Valid() {
- a.SetString("LOCAL_NOTICE_FILE", amod.noticeFile.String())
+ if len(amod.noticeFiles) > 0 {
+ a.SetString("LOCAL_NOTICE_FILE", strings.Join(amod.noticeFiles.Strings(), " "))
}
if host {
diff --git a/android/apex.go b/android/apex.go
index c7410a1..f9350d1 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -32,6 +32,7 @@
ApexName string
MinSdkVersion int
+ Updatable bool
}
// Extracted from ApexModule to make it easier to define custom subsets of the
@@ -115,6 +116,9 @@
// it returns 9 as string
ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
+ // Tests if the module comes from an updatable APEX.
+ Updatable() bool
+
// List of APEXes that this module tests. The module has access to
// the private part of the listed APEXes even when it is not included in the
// APEXes.
@@ -259,6 +263,10 @@
}
}
+func (m *ApexModuleBase) Updatable() bool {
+ return m.ApexProperties.Info.Updatable
+}
+
type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
diff --git a/android/arch.go b/android/arch.go
index e440486..08c0256 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -33,8 +33,6 @@
Arm = newArch("arm", "lib32")
Arm64 = newArch("arm64", "lib64")
- Mips = newArch("mips", "lib32")
- Mips64 = newArch("mips64", "lib64")
X86 = newArch("x86", "lib32")
X86_64 = newArch("x86_64", "lib64")
@@ -46,8 +44,6 @@
var archTypeMap = map[string]ArchType{
"arm": Arm,
"arm64": Arm64,
- "mips": Mips,
- "mips64": Mips64,
"x86": X86,
"x86_64": X86_64,
}
@@ -64,12 +60,6 @@
arm64: {
// Host or device variants with arm64 architecture
},
- mips: {
- // Host or device variants with mips architecture
- },
- mips64: {
- // Host or device variants with mips64 architecture
- },
x86: {
// Host or device variants with x86 architecture
},
@@ -145,18 +135,6 @@
"exynos-m1",
"exynos-m2",
},
- Mips: {
- "mips32_fp",
- "mips32r2_fp",
- "mips32r2_fp_xburst",
- "mips32r2dsp_fp",
- "mips32r2dspr2_fp",
- "mips32r6",
- },
- Mips64: {
- "mips64r2",
- "mips64r6",
- },
X86: {
"amberlake",
"atom",
@@ -193,15 +171,6 @@
Arm: {
"neon",
},
- Mips: {
- "dspr2",
- "rev6",
- "msa",
- },
- Mips64: {
- "rev6",
- "msa",
- },
X86: {
"ssse3",
"sse4",
@@ -239,19 +208,6 @@
"neon",
},
},
- Mips: {
- "mips32r2dspr2_fp": {
- "dspr2",
- },
- "mips32r6": {
- "rev6",
- },
- },
- Mips64: {
- "mips64r6": {
- "rev6",
- },
- },
X86: {
"amberlake": {
"ssse3",
@@ -616,7 +572,7 @@
LinuxBionic: []ArchType{X86_64},
Darwin: []ArchType{X86_64},
Windows: []ArchType{X86, X86_64},
- Android: []ArchType{Arm, Arm64, Mips, Mips64, X86, X86_64},
+ Android: []ArchType{Arm, Arm64, X86, X86_64},
Fuchsia: []ArchType{Arm64, X86_64},
}
)
@@ -1656,15 +1612,6 @@
{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
- {"mips", "mips32-fp", "", []string{"mips"}},
- {"mips", "mips32r2-fp", "", []string{"mips"}},
- {"mips", "mips32r2-fp-xburst", "", []string{"mips"}},
- //{"mips", "mips32r6", "", []string{"mips"}},
- {"mips", "mips32r2dsp-fp", "", []string{"mips"}},
- {"mips", "mips32r2dspr2-fp", "", []string{"mips"}},
- // mips64r2 is mismatching 64r2 and 64r6 libraries during linking to libgcc
- //{"mips64", "mips64r2", "", []string{"mips64"}},
- {"mips64", "mips64r6", "", []string{"mips64"}},
{"x86", "", "", []string{"x86"}},
{"x86", "atom", "", []string{"x86"}},
{"x86", "haswell", "", []string{"x86"}},
diff --git a/android/config.go b/android/config.go
index bf52c45..c297b05 100644
--- a/android/config.go
+++ b/android/config.go
@@ -847,16 +847,7 @@
}
func (c *config) LibartImgDeviceBaseAddress() string {
- archType := Common
- if len(c.Targets[Android]) > 0 {
- archType = c.Targets[Android][0].Arch.ArchType
- }
- switch archType {
- default:
- return "0x70000000"
- case Mips, Mips64:
- return "0x5C000000"
- }
+ return "0x70000000"
}
func (c *config) ArtUseReadBarrier() bool {
diff --git a/android/metrics.go b/android/metrics.go
new file mode 100644
index 0000000..b7aee54
--- /dev/null
+++ b/android/metrics.go
@@ -0,0 +1,87 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "io/ioutil"
+ "runtime"
+
+ "github.com/golang/protobuf/proto"
+
+ soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
+)
+
+var soongMetricsOnceKey = NewOnceKey("soong metrics")
+
+type SoongMetrics struct {
+ Modules int
+ Variants int
+}
+
+func ReadSoongMetrics(config Config) SoongMetrics {
+ return config.Get(soongMetricsOnceKey).(SoongMetrics)
+}
+
+func init() {
+ RegisterSingletonType("soong_metrics", soongMetricsSingletonFactory)
+}
+
+func soongMetricsSingletonFactory() Singleton { return soongMetricsSingleton{} }
+
+type soongMetricsSingleton struct{}
+
+func (soongMetricsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ metrics := SoongMetrics{}
+ ctx.VisitAllModules(func(m Module) {
+ if ctx.PrimaryModule(m) == m {
+ metrics.Modules++
+ }
+ metrics.Variants++
+ })
+ ctx.Config().Once(soongMetricsOnceKey, func() interface{} {
+ return metrics
+ })
+}
+
+func collectMetrics(config Config) *soong_metrics_proto.SoongBuildMetrics {
+ metrics := &soong_metrics_proto.SoongBuildMetrics{}
+
+ soongMetrics := ReadSoongMetrics(config)
+ metrics.Modules = proto.Uint32(uint32(soongMetrics.Modules))
+ metrics.Variants = proto.Uint32(uint32(soongMetrics.Variants))
+
+ memStats := runtime.MemStats{}
+ runtime.ReadMemStats(&memStats)
+ metrics.MaxHeapSize = proto.Uint64(memStats.HeapSys)
+ metrics.TotalAllocCount = proto.Uint64(memStats.Mallocs)
+ metrics.TotalAllocSize = proto.Uint64(memStats.TotalAlloc)
+
+ return metrics
+}
+
+func WriteMetrics(config Config, metricsFile string) error {
+ metrics := collectMetrics(config)
+
+ buf, err := proto.Marshal(metrics)
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(absolutePath(metricsFile), buf, 0666)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/android/module.go b/android/module.go
index d9e655a..02b2c89 100644
--- a/android/module.go
+++ b/android/module.go
@@ -182,6 +182,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
RequiredModuleNames() []string
HostRequiredModuleNames() []string
@@ -224,12 +225,13 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
SkipInstall()
IsSkipInstall() bool
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
- NoticeFile() OptionalPath
+ NoticeFiles() Paths
AddProperties(props ...interface{})
GetProperties() []interface{}
@@ -253,6 +255,8 @@
RequiredModuleNames() []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
+
+ filesToInstall() InstallPaths
}
// Qualified id for a module
@@ -706,9 +710,9 @@
primaryVisibilityProperty visibilityProperty
noAddressSanitizer bool
- installFiles Paths
+ installFiles InstallPaths
checkbuildFiles Paths
- noticeFile OptionalPath
+ noticeFiles Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -955,22 +959,20 @@
return m.commonProperties.NamespaceExportedToMake
}
-func (m *ModuleBase) computeInstallDeps(
- ctx blueprint.ModuleContext) Paths {
+func (m *ModuleBase) computeInstallDeps(ctx blueprint.ModuleContext) InstallPaths {
- result := Paths{}
+ var result InstallPaths
// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
- ctx.VisitDepsDepthFirstIf(isFileInstaller,
- func(m blueprint.Module) {
- fileInstaller := m.(fileInstaller)
- files := fileInstaller.filesToInstall()
- result = append(result, files...)
- })
+ ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
+ if a, ok := m.(Module); ok {
+ result = append(result, a.filesToInstall()...)
+ }
+ })
return result
}
-func (m *ModuleBase) filesToInstall() Paths {
+func (m *ModuleBase) filesToInstall() InstallPaths {
return m.installFiles
}
@@ -1006,12 +1008,16 @@
return false
}
+func (m *ModuleBase) InstallForceOS() *OsType {
+ return nil
+}
+
func (m *ModuleBase) Owner() string {
return String(m.commonProperties.Owner)
}
-func (m *ModuleBase) NoticeFile() OptionalPath {
- return m.noticeFile
+func (m *ModuleBase) NoticeFiles() Paths {
+ return m.noticeFiles
}
func (m *ModuleBase) setImageVariation(variant string) {
@@ -1064,8 +1070,8 @@
}
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
- allInstalledFiles := Paths{}
- allCheckbuildFiles := Paths{}
+ var allInstalledFiles InstallPaths
+ var allCheckbuildFiles Paths
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
@@ -1084,7 +1090,7 @@
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
Output: name,
- Implicits: allInstalledFiles,
+ Implicits: allInstalledFiles.Paths(),
Default: !ctx.Config().EmbeddedInMake(),
})
deps = append(deps, name)
@@ -1270,12 +1276,25 @@
}
})
- notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
+ m.noticeFiles = make([]Path, 0)
+ optPath := OptionalPath{}
+ notice := proptools.StringDefault(m.commonProperties.Notice, "")
if module := SrcIsModule(notice); module != "" {
- m.noticeFile = ctx.ExpandOptionalSource(¬ice, "notice")
- } else {
+ optPath = ctx.ExpandOptionalSource(¬ice, "notice")
+ } else if notice != "" {
noticePath := filepath.Join(ctx.ModuleDir(), notice)
- m.noticeFile = ExistentPathForSource(ctx, noticePath)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ }
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ } else {
+ for _, notice = range []string{"LICENSE", "LICENCE", "NOTICE"} {
+ noticePath := filepath.Join(ctx.ModuleDir(), notice)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ }
+ }
}
m.module.GenerateAndroidBuildActions(ctx)
@@ -1420,8 +1439,8 @@
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
- installDeps Paths
- installFiles Paths
+ installDeps InstallPaths
+ installFiles InstallPaths
checkbuildFiles Paths
module Module
@@ -1841,6 +1860,10 @@
return m.module.InstallBypassMake()
}
+func (m *moduleContext) InstallForceOS() *OsType {
+ return m.module.InstallForceOS()
+}
+
func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
if m.module.base().commonProperties.SkipInstall {
return true
@@ -1884,7 +1907,7 @@
if !m.skipInstall(fullInstallPath) {
- deps = append(deps, m.installDeps...)
+ deps = append(deps, m.installDeps.Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -1965,20 +1988,6 @@
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
-type fileInstaller interface {
- filesToInstall() Paths
-}
-
-func isFileInstaller(m blueprint.Module) bool {
- _, ok := m.(fileInstaller)
- return ok
-}
-
-func isAndroidModule(m blueprint.Module) bool {
- _, ok := m.(Module)
- return ok
-}
-
func findStringInSlice(str string, slice []string) int {
for i, s := range slice {
if s == str {
diff --git a/android/notices.go b/android/notices.go
index bf273b5..07cf3e4 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -22,7 +22,7 @@
func init() {
pctx.SourcePathVariable("merge_notices", "build/soong/scripts/mergenotice.py")
- pctx.SourcePathVariable("generate_notice", "build/make/tools/generate-notice-files.py")
+ pctx.SourcePathVariable("generate_notice", "build/soong/scripts/generate-notice-files.py")
pctx.HostBinToolVariable("minigzip", "minigzip")
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index 5a43ea9..0de356e 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -232,30 +232,10 @@
}, argNames...)
}
-// RBEExperimentalFlag indicates which flag should be set for the AndroidRemoteStaticRule
-// to use RBE.
-type RBEExperimentalFlag int
-
-const (
- // RBE_NOT_EXPERIMENTAL indicates the rule should use RBE in every build that has
- // UseRBE set.
- RBE_NOT_EXPERIMENTAL RBEExperimentalFlag = iota
- // RBE_JAVAC indicates the rule should use RBE only if the RBE_JAVAC variable is
- // set in an RBE enabled build.
- RBE_JAVAC
- // RBE_R8 indicates the rule should use RBE only if the RBE_R8 variable is set in
- // an RBE enabled build.
- RBE_R8
- // RBE_D8 indicates the rule should use RBE only if the RBE_D8 variable is set in
- // an RBE enabled build.
- RBE_D8
-)
-
// RemoteRuleSupports configures rules with whether they have Goma and/or RBE support.
type RemoteRuleSupports struct {
- Goma bool
- RBE bool
- RBEFlag RBEExperimentalFlag
+ Goma bool
+ RBE bool
}
// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
@@ -277,18 +257,6 @@
params.Pool = localPool
}
- if ctx.Config().UseRBE() && supports.RBE {
- if supports.RBEFlag == RBE_JAVAC && !ctx.Config().UseRBEJAVAC() {
- params.Pool = localPool
- }
- if supports.RBEFlag == RBE_R8 && !ctx.Config().UseRBER8() {
- params.Pool = localPool
- }
- if supports.RBEFlag == RBE_D8 && !ctx.Config().UseRBED8() {
- params.Pool = localPool
- }
- }
-
return params, nil
}, argNames...)
}
diff --git a/android/paths.go b/android/paths.go
index 0edda38..8bb9a96 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -53,6 +53,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
}
var _ ModuleInstallPathContext = ModuleContext(nil)
@@ -469,6 +470,14 @@
// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each. It
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func FirstUniquePaths(list Paths) Paths {
+ // 128 was chosen based on BenchmarkFirstUniquePaths results.
+ if len(list) > 128 {
+ return firstUniquePathsMap(list)
+ }
+ return firstUniquePathsList(list)
+}
+
+func firstUniquePathsList(list Paths) Paths {
k := 0
outer:
for i := 0; i < len(list); i++ {
@@ -483,6 +492,20 @@
return list[:k]
}
+func firstUniquePathsMap(list Paths) Paths {
+ k := 0
+ seen := make(map[Path]bool, len(list))
+ for i := 0; i < len(list); i++ {
+ if seen[list[i]] {
+ continue
+ }
+ seen[list[i]] = true
+ list[k] = list[i]
+ k++
+ }
+ return list[:k]
+}
+
// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each. It
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
func LastUniquePaths(list Paths) Paths {
@@ -1205,22 +1228,40 @@
// PathForModuleInstall returns a Path representing the install path for the
// module appended with paths...
func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
+ os := ctx.Os()
+ if forceOS := ctx.InstallForceOS(); forceOS != nil {
+ os = *forceOS
+ }
+ partition := modulePartition(ctx, os)
+
+ ret := pathForInstall(ctx, os, partition, ctx.Debug(), pathComponents...)
+
+ if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
+ ret = ret.ToMakePath()
+ }
+
+ return ret
+}
+
+func pathForInstall(ctx PathContext, os OsType, partition string, debug bool,
+ pathComponents ...string) InstallPath {
+
var outPaths []string
- if ctx.Device() {
- partition := modulePartition(ctx)
+
+ if os.Class == Device {
outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
} else {
- switch ctx.Os() {
+ switch os {
case Linux:
- outPaths = []string{"host", "linux-x86"}
+ outPaths = []string{"host", "linux-x86", partition}
case LinuxBionic:
// TODO: should this be a separate top level, or shared with linux-x86?
- outPaths = []string{"host", "linux_bionic-x86"}
+ outPaths = []string{"host", "linux_bionic-x86", partition}
default:
- outPaths = []string{"host", ctx.Os().String() + "-x86"}
+ outPaths = []string{"host", os.String() + "-x86", partition}
}
}
- if ctx.Debug() {
+ if debug {
outPaths = append([]string{"debug"}, outPaths...)
}
outPaths = append(outPaths, pathComponents...)
@@ -1231,9 +1272,6 @@
}
ret := InstallPath{basePath{path, ctx.Config(), ""}, ""}
- if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
- ret = ret.ToMakePath()
- }
return ret
}
@@ -1261,47 +1299,76 @@
return "/" + rel
}
-func modulePartition(ctx ModuleInstallPathContext) string {
+func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
var partition string
- if ctx.InstallInData() {
- partition = "data"
- } else if ctx.InstallInTestcases() {
+ if ctx.InstallInTestcases() {
+ // "testcases" install directory can be used for host or device modules.
partition = "testcases"
- } else if ctx.InstallInRamdisk() {
- if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
- partition = "recovery/root/first_stage_ramdisk"
+ } else if os.Class == Device {
+ if ctx.InstallInData() {
+ partition = "data"
+ } else if ctx.InstallInRamdisk() {
+ if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
+ partition = "recovery/root/first_stage_ramdisk"
+ } else {
+ partition = "ramdisk"
+ }
+ if !ctx.InstallInRoot() {
+ partition += "/system"
+ }
+ } else if ctx.InstallInRecovery() {
+ if ctx.InstallInRoot() {
+ partition = "recovery/root"
+ } else {
+ // the layout of recovery partion is the same as that of system partition
+ partition = "recovery/root/system"
+ }
+ } else if ctx.SocSpecific() {
+ partition = ctx.DeviceConfig().VendorPath()
+ } else if ctx.DeviceSpecific() {
+ partition = ctx.DeviceConfig().OdmPath()
+ } else if ctx.ProductSpecific() {
+ partition = ctx.DeviceConfig().ProductPath()
+ } else if ctx.SystemExtSpecific() {
+ partition = ctx.DeviceConfig().SystemExtPath()
+ } else if ctx.InstallInRoot() {
+ partition = "root"
} else {
- partition = "ramdisk"
+ partition = "system"
}
- if !ctx.InstallInRoot() {
- partition += "/system"
+ if ctx.InstallInSanitizerDir() {
+ partition = "data/asan/" + partition
}
- } else if ctx.InstallInRecovery() {
- if ctx.InstallInRoot() {
- partition = "recovery/root"
- } else {
- // the layout of recovery partion is the same as that of system partition
- partition = "recovery/root/system"
- }
- } else if ctx.SocSpecific() {
- partition = ctx.DeviceConfig().VendorPath()
- } else if ctx.DeviceSpecific() {
- partition = ctx.DeviceConfig().OdmPath()
- } else if ctx.ProductSpecific() {
- partition = ctx.DeviceConfig().ProductPath()
- } else if ctx.SystemExtSpecific() {
- partition = ctx.DeviceConfig().SystemExtPath()
- } else if ctx.InstallInRoot() {
- partition = "root"
- } else {
- partition = "system"
- }
- if ctx.InstallInSanitizerDir() {
- partition = "data/asan/" + partition
}
return partition
}
+type InstallPaths []InstallPath
+
+// Paths returns the InstallPaths as a Paths
+func (p InstallPaths) Paths() Paths {
+ if p == nil {
+ return nil
+ }
+ ret := make(Paths, len(p))
+ for i, path := range p {
+ ret[i] = path
+ }
+ return ret
+}
+
+// Strings returns the string forms of the install paths.
+func (p InstallPaths) Strings() []string {
+ if p == nil {
+ return nil
+ }
+ ret := make([]string, len(p))
+ for i, path := range p {
+ ret[i] = path.String()
+ }
+ return ret
+}
+
// validateSafePath validates a path that we trust (may contain ninja variables).
// Ensures that each path component does not attempt to leave its component.
func validateSafePath(pathComponents ...string) (string, error) {
diff --git a/android/paths_test.go b/android/paths_test.go
index 7a32026..9b45d3f 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -18,6 +18,7 @@
"errors"
"fmt"
"reflect"
+ "strconv"
"strings"
"testing"
@@ -205,6 +206,7 @@
inRamdisk bool
inRecovery bool
inRoot bool
+ forceOS *OsType
}
func (m moduleInstallPathContextImpl) Config() Config {
@@ -241,6 +243,10 @@
return false
}
+func (m moduleInstallPathContextImpl) InstallForceOS() *OsType {
+ return m.forceOS
+}
+
func pathTestConfig(buildDir string) Config {
return TestConfig(buildDir, nil, "", nil)
}
@@ -598,6 +604,40 @@
},
in: []string{"nativetest", "my_test"},
out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ }, {
+ name: "device testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "target/product/test_device/testcases/my_test/my_test_bin",
+ }, {
+ name: "host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: hostTarget.Os,
+ target: hostTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
+ }, {
+ name: "forced host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ forceOS: &Linux,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
},
}
@@ -1216,3 +1256,51 @@
// out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
// boot.art oat/arm/boot.vdex
}
+
+func BenchmarkFirstUniquePaths(b *testing.B) {
+ implementations := []struct {
+ name string
+ f func(Paths) Paths
+ }{
+ {
+ name: "list",
+ f: firstUniquePathsList,
+ },
+ {
+ name: "map",
+ f: firstUniquePathsMap,
+ },
+ }
+ const maxSize = 1024
+ uniquePaths := make(Paths, maxSize)
+ for i := range uniquePaths {
+ uniquePaths[i] = PathForTesting(strconv.Itoa(i))
+ }
+ samePath := make(Paths, maxSize)
+ for i := range samePath {
+ samePath[i] = uniquePaths[0]
+ }
+
+ f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
+ for i := 0; i < b.N; i++ {
+ b.ReportAllocs()
+ paths = append(Paths(nil), paths...)
+ imp(paths)
+ }
+ }
+
+ for n := 1; n <= maxSize; n <<= 1 {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ for _, implementation := range implementations {
+ b.Run(implementation.name, func(b *testing.B) {
+ b.Run("same", func(b *testing.B) {
+ f(b, implementation.f, samePath[:n])
+ })
+ b.Run("unique", func(b *testing.B) {
+ f(b, implementation.f, uniquePaths[:n])
+ })
+ })
+ }
+ })
+ }
+}
diff --git a/android/sdk.go b/android/sdk.go
index 2fdaf35..6f62f55 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -313,10 +313,11 @@
// SdkAware and be added with an SdkMemberTypeDependencyTag tag.
HasTransitiveSdkMembers() bool
- // Add dependencies from the SDK module to all the variants the member
- // contributes to the SDK. The exact set of variants required is determined
- // by the SDK and its properties. The dependencies must be added with the
- // supplied tag.
+ // Add dependencies from the SDK module to all the module variants the member
+ // type contributes to the SDK. `names` is the list of module names given in
+ // the member type property (as returned by SdkPropertyName()) in the SDK
+ // module. The exact set of variants required is determined by the SDK and its
+ // properties. The dependencies must be added with the supplied tag.
//
// The BottomUpMutatorContext provided is for the SDK module.
AddDependencies(mctx BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string)
diff --git a/android/util.go b/android/util.go
index ade851e..e74b64e 100644
--- a/android/util.go
+++ b/android/util.go
@@ -193,6 +193,14 @@
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
func FirstUniqueStrings(list []string) []string {
+ // 128 was chosen based on BenchmarkFirstUniqueStrings results.
+ if len(list) > 128 {
+ return firstUniqueStringsMap(list)
+ }
+ return firstUniqueStringsList(list)
+}
+
+func firstUniqueStringsList(list []string) []string {
k := 0
outer:
for i := 0; i < len(list); i++ {
@@ -207,6 +215,20 @@
return list[:k]
}
+func firstUniqueStringsMap(list []string) []string {
+ k := 0
+ seen := make(map[string]bool, len(list))
+ for i := 0; i < len(list); i++ {
+ if seen[list[i]] {
+ continue
+ }
+ seen[list[i]] = true
+ list[k] = list[i]
+ k++
+ }
+ return list[:k]
+}
+
// LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
func LastUniqueStrings(list []string) []string {
diff --git a/android/util_test.go b/android/util_test.go
index 1f9ca36..25b52ca 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "strconv"
"testing"
)
@@ -59,15 +60,25 @@
}
func TestFirstUniqueStrings(t *testing.T) {
- for _, testCase := range firstUniqueStringsTestCases {
- out := FirstUniqueStrings(testCase.in)
- if !reflect.DeepEqual(out, testCase.out) {
+ f := func(t *testing.T, imp func([]string) []string, in, want []string) {
+ t.Helper()
+ out := imp(in)
+ if !reflect.DeepEqual(out, want) {
t.Errorf("incorrect output:")
- t.Errorf(" input: %#v", testCase.in)
- t.Errorf(" expected: %#v", testCase.out)
+ t.Errorf(" input: %#v", in)
+ t.Errorf(" expected: %#v", want)
t.Errorf(" got: %#v", out)
}
}
+
+ for _, testCase := range firstUniqueStringsTestCases {
+ t.Run("list", func(t *testing.T) {
+ f(t, firstUniqueStringsList, testCase.in, testCase.out)
+ })
+ t.Run("map", func(t *testing.T) {
+ f(t, firstUniqueStringsMap, testCase.in, testCase.out)
+ })
+ }
}
var lastUniqueStringsTestCases = []struct {
@@ -568,3 +579,51 @@
})
}
}
+
+func BenchmarkFirstUniqueStrings(b *testing.B) {
+ implementations := []struct {
+ name string
+ f func([]string) []string
+ }{
+ {
+ name: "list",
+ f: firstUniqueStringsList,
+ },
+ {
+ name: "map",
+ f: firstUniqueStringsMap,
+ },
+ }
+ const maxSize = 1024
+ uniqueStrings := make([]string, maxSize)
+ for i := range uniqueStrings {
+ uniqueStrings[i] = strconv.Itoa(i)
+ }
+ sameString := make([]string, maxSize)
+ for i := range sameString {
+ sameString[i] = uniqueStrings[0]
+ }
+
+ f := func(b *testing.B, imp func([]string) []string, s []string) {
+ for i := 0; i < b.N; i++ {
+ b.ReportAllocs()
+ s = append([]string(nil), s...)
+ imp(s)
+ }
+ }
+
+ for n := 1; n <= maxSize; n <<= 1 {
+ b.Run(strconv.Itoa(n), func(b *testing.B) {
+ for _, implementation := range implementations {
+ b.Run(implementation.name, func(b *testing.B) {
+ b.Run("same", func(b *testing.B) {
+ f(b, implementation.f, sameString[:n])
+ })
+ b.Run("unique", func(b *testing.B) {
+ f(b, implementation.f, uniqueStrings[:n])
+ })
+ })
+ }
+ })
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index 118e107..3c08405 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -49,6 +49,14 @@
Exclude_static_libs []string `android:"arch_variant"`
} `android:"arch_variant"`
+ Malloc_zero_contents struct {
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+
+ Malloc_pattern_fill_contents struct {
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+
Safestack struct {
Cflags []string `android:"arch_variant"`
} `android:"arch_variant"`
@@ -95,6 +103,9 @@
Sanitize struct {
Address *bool
}
+ Optimize struct {
+ Enabled *bool
+ }
}
Pdk struct {
@@ -207,6 +218,8 @@
Unbundled_build *bool `json:",omitempty"`
Unbundled_build_sdks_from_source *bool `json:",omitempty"`
Malloc_not_svelte *bool `json:",omitempty"`
+ Malloc_zero_contents *bool `json:",omitempty"`
+ Malloc_pattern_fill_contents *bool `json:",omitempty"`
Safestack *bool `json:",omitempty"`
HostStaticBinaries *bool `json:",omitempty"`
Binder32bit *bool `json:",omitempty"`
@@ -373,8 +386,10 @@
AAPTCharacteristics: stringPtr("nosdcard"),
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
- Malloc_not_svelte: boolPtr(true),
- Safestack: boolPtr(false),
+ Malloc_not_svelte: boolPtr(true),
+ Malloc_zero_contents: boolPtr(false),
+ Malloc_pattern_fill_contents: boolPtr(false),
+ Safestack: boolPtr(false),
}
if runtime.GOOS == "linux" {
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 8860984..f863f8d 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -383,11 +383,15 @@
if err != nil {
return err
}
- if val.(*bpparser.Bool).Value {
+ boolValue, ok := val.(*bpparser.Bool)
+ if !ok {
+ return fmt.Errorf("value should evaluate to boolean literal")
+ }
+ if boolValue.Value {
thirtyTwo := &bpparser.String{
Value: "32",
}
- setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
+ return setVariable(ctx.file, false, ctx.prefix, "compile_multilib", thirtyTwo, true)
}
return nil
}
@@ -825,8 +829,6 @@
var propertyPrefixes = []struct{ mk, bp string }{
{"arm", "arch.arm"},
{"arm64", "arch.arm64"},
- {"mips", "arch.mips"},
- {"mips64", "arch.mips64"},
{"x86", "arch.x86"},
{"x86_64", "arch.x86_64"},
{"32", "multilib.lib32"},
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 7e1a72c..3e1d486 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1341,6 +1341,25 @@
}
`,
},
+ {
+ desc: "undefined_boolean_var",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= a.cpp
+LOCAL_MODULE:= test
+LOCAL_32_BIT_ONLY := $(FLAG)
+include $(BUILD_EXECUTABLE)
+`,
+ expected: `
+cc_binary {
+ name: "test",
+ srcs: ["a.cpp"],
+ // ANDROIDMK TRANSLATION ERROR: value should evaluate to boolean literal
+ // LOCAL_32_BIT_ONLY := $(FLAG)
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 2303efe..db1048e 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -121,8 +121,8 @@
fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
}
- if fi.module != nil && fi.module.NoticeFile().Valid() {
- fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", fi.module.NoticeFile().Path().String())
+ if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
+ fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
}
} else {
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
diff --git a/apex/apex.go b/apex/apex.go
index 6a0c4c1..84c24b5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -53,6 +53,7 @@
var (
sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
+ jniLibTag = dependencyTag{name: "jniLib", payload: true}
executableTag = dependencyTag{name: "executable", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
prebuiltTag = dependencyTag{name: "prebuilt", payload: true}
@@ -61,6 +62,7 @@
certificateTag = dependencyTag{name: "certificate"}
usesTag = dependencyTag{name: "uses"}
androidAppTag = dependencyTag{name: "androidApp", payload: true}
+ rroTag = dependencyTag{name: "rro", payload: true}
apexAvailWl = makeApexAvailableWhitelist()
inverseApexAvailWl = invertApexWhiteList(apexAvailWl)
@@ -764,6 +766,7 @@
apexBundles = []android.ApexInfo{{
ApexName: mctx.ModuleName(),
MinSdkVersion: a.minSdkVersion(mctx),
+ Updatable: proptools.Bool(a.properties.Updatable),
}}
directDep = true
} else if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -964,10 +967,13 @@
})
}
-type apexNativeDependencies struct {
+type ApexNativeDependencies struct {
// List of native libraries
Native_shared_libs []string
+ // List of JNI libraries
+ Jni_libs []string
+
// List of native executables
Binaries []string
@@ -977,19 +983,19 @@
type apexMultilibProperties struct {
// Native dependencies whose compile_multilib is "first"
- First apexNativeDependencies
+ First ApexNativeDependencies
// Native dependencies whose compile_multilib is "both"
- Both apexNativeDependencies
+ Both ApexNativeDependencies
// Native dependencies whose compile_multilib is "prefer32"
- Prefer32 apexNativeDependencies
+ Prefer32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "32"
- Lib32 apexNativeDependencies
+ Lib32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "64"
- Lib64 apexNativeDependencies
+ Lib64 ApexNativeDependencies
}
type apexBundleProperties struct {
@@ -1011,11 +1017,7 @@
// Default: /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
- // List of native shared libs that are embedded inside this APEX bundle
- Native_shared_libs []string
-
- // List of executables that are embedded inside this APEX bundle
- Binaries []string
+ ApexNativeDependencies
// List of java libraries that are embedded inside this APEX bundle
Java_libs []string
@@ -1023,9 +1025,6 @@
// List of prebuilt files that are embedded inside this APEX bundle
Prebuilts []string
- // List of tests that are embedded inside this APEX bundle
- Tests []string
-
// Name of the apex_key module that provides the private key to sign APEX
Key *string
@@ -1092,7 +1091,7 @@
// Default is false.
Updatable *bool
- // The minimum SDK version that this apex must be compatible with.
+ // The minimum SDK version that this apex must be compatibile with.
Min_sdk_version *string
}
@@ -1124,6 +1123,9 @@
// List of APKs to package inside APEX
Apps []string
+ // List of runtime resource overlays (RROs) inside APEX
+ Rros []string
+
// Names of modules to be overridden. Listed modules can only be other binaries
// (in Make or Soong).
// This does not completely prevent installation of the overridden binaries, but if both
@@ -1229,6 +1231,8 @@
jacocoReportClassesFile android.Path // only for javalibs and apps
certificate java.Certificate // only for apps
overriddenPackageName string // only for apps
+
+ isJniLib bool
}
func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
@@ -1347,7 +1351,7 @@
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
- native_shared_libs []string, binaries []string, tests []string,
+ nativeModules ApexNativeDependencies,
target android.Target, imageVariation string) {
// Use *FarVariation* to be able to depend on modules having
// conflicting variations with this module. This is required since
@@ -1357,16 +1361,22 @@
{Mutator: "image", Variation: imageVariation},
{Mutator: "link", Variation: "shared"},
{Mutator: "version", Variation: ""}, // "" is the non-stub variant
- }...), sharedLibTag, native_shared_libs...)
+ }...), sharedLibTag, nativeModules.Native_shared_libs...)
+
+ ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "image", Variation: imageVariation},
+ {Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: ""}, // "" is the non-stub variant
+ }...), jniLibTag, nativeModules.Jni_libs...)
ctx.AddFarVariationDependencies(append(target.Variations(),
blueprint.Variation{Mutator: "image", Variation: imageVariation}),
- executableTag, binaries...)
+ executableTag, nativeModules.Binaries...)
ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: imageVariation},
{Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, tests...)
+ }...), testTag, nativeModules.Tests...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -1399,41 +1409,39 @@
}
}
for i, target := range targets {
- // When multilib.* is omitted for native_shared_libs, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "link", Variation: "shared"},
- }...), sharedLibTag, a.properties.Native_shared_libs...)
-
- // When multilib.* is omitted for tests, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, a.properties.Tests...)
+ // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
+ // multilib.both
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: a.properties.Native_shared_libs,
+ Tests: a.properties.Tests,
+ Jni_libs: a.properties.Jni_libs,
+ Binaries: nil,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting both ABIs
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Both.Native_shared_libs,
- a.properties.Multilib.Both.Binaries,
- a.properties.Multilib.Both.Tests,
+ a.properties.Multilib.Both,
target,
a.getImageVariation(config))
isPrimaryAbi := i == 0
if isPrimaryAbi {
// When multilib.* is omitted for binaries, it implies
- // multilib.first.
- ctx.AddFarVariationDependencies(append(target.Variations(),
- blueprint.Variation{Mutator: "image", Variation: a.getImageVariation(config)}),
- executableTag, a.properties.Binaries...)
+ // multilib.first
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: nil,
+ Tests: nil,
+ Jni_libs: nil,
+ Binaries: a.properties.Binaries,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting the first ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.First.Native_shared_libs,
- a.properties.Multilib.First.Binaries,
- a.properties.Multilib.First.Tests,
+ a.properties.Multilib.First,
target,
a.getImageVariation(config))
}
@@ -1442,32 +1450,24 @@
case "lib32":
// Add native modules targetting 32-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib32.Native_shared_libs,
- a.properties.Multilib.Lib32.Binaries,
- a.properties.Multilib.Lib32.Tests,
+ a.properties.Multilib.Lib32,
target,
a.getImageVariation(config))
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
case "lib64":
// Add native modules targetting 64-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib64.Native_shared_libs,
- a.properties.Multilib.Lib64.Binaries,
- a.properties.Multilib.Lib64.Tests,
+ a.properties.Multilib.Lib64,
target,
a.getImageVariation(config))
if !has32BitTarget {
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
}
@@ -1476,8 +1476,8 @@
for _, sanitizer := range ctx.Config().SanitizeDevice() {
if sanitizer == "hwaddress" {
addDependenciesForNativeModules(ctx,
- []string{"libclang_rt.hwasan-aarch64-android"},
- nil, nil, target, a.getImageVariation(config))
+ ApexNativeDependencies{[]string{"libclang_rt.hwasan-aarch64-android"}, nil, nil, nil},
+ target, a.getImageVariation(config))
break
}
}
@@ -1536,6 +1536,8 @@
func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
androidAppTag, a.overridableProperties.Apps...)
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ rroTag, a.overridableProperties.Rros...)
}
func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
@@ -1640,10 +1642,10 @@
case "lib64":
dirInApex = "lib64"
}
- dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
}
+ dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
// Special case for Bionic libs and other libs installed with them. This is
// to prevent those libs from being included in the search path
@@ -1663,10 +1665,11 @@
}
func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
- dirInApex := filepath.Join("bin", cc.RelativeInstallPath())
+ dirInApex := "bin"
if cc.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
}
+ dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
fileToCopy := cc.OutputFile().Path()
af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
af.symlinks = cc.Symlinks()
@@ -1752,6 +1755,21 @@
return af
}
+func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
+ rroDir := "overlay"
+ dirInApex := filepath.Join(rroDir, rro.Theme())
+ fileToCopy := rro.OutputFile()
+ af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro)
+ af.certificate = rro.Certificate()
+
+ if a, ok := rro.(interface {
+ OverriddenManifestPackageName() string
+ }); ok {
+ af.overriddenPackageName = a.OverriddenManifestPackageName()
+ }
+ return af
+}
+
// Context "decorator", overriding the InstallBypassMake method to always reply `true`.
type flattenedApexContext struct {
android.ModuleContext
@@ -1983,16 +2001,23 @@
depName := ctx.OtherModuleName(child)
if _, isDirectDep := parent.(*apexBundle); isDirectDep {
switch depTag {
- case sharedLibTag:
+ case sharedLibTag, jniLibTag:
+ isJniLib := depTag == jniLibTag
if c, ok := child.(*cc.Module); ok {
// bootstrap bionic libs are treated as provided by system
if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
provideNativeLibs = append(provideNativeLibs, c.OutputFile().Path().Base())
}
- filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, c, handleSpecialLibs))
+ fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs)
+ fi.isJniLib = isJniLib
+ filesInfo = append(filesInfo, fi)
return true // track transitive dependencies
} else {
- ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
+ propertyName := "native_shared_libs"
+ if isJniLib {
+ propertyName = "jni_libs"
+ }
+ ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
}
case executableTag:
if cc, ok := child.(*cc.Module); ok {
@@ -2038,6 +2063,12 @@
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
+ case rroTag:
+ if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
+ filesInfo = append(filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
+ } else {
+ ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
+ }
case prebuiltTag:
if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2618db3..dea7a08 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -88,6 +88,24 @@
}
}
+// withNativeBridgeTargets sets configuration with targets including:
+// - X86_64 (primary)
+// - X86 (secondary)
+// - Arm64 on X86_64 (native bridge)
+// - Arm on X86 (native bridge)
+func withNativeBridgeEnabled(fs map[string][]byte, config android.Config) {
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
+ NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
+ NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
+ }
+}
+
func withManifestPackageNameOverrides(specs []string) testCustomizer {
return func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.ManifestPackageNameOverrides = specs
@@ -235,6 +253,14 @@
os.RemoveAll(buildDir)
}
+// ensure that 'result' equals 'expected'
+func ensureEquals(t *testing.T, result string, expected string) {
+ t.Helper()
+ if result != expected {
+ t.Errorf("%q != %q", expected, result)
+ }
+}
+
// ensure that 'result' contains 'expected'
func ensureContains(t *testing.T, result string, expected string) {
t.Helper()
@@ -495,6 +521,7 @@
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
apps: ["AppFoo"],
+ rros: ["rro"],
}
prebuilt_etc {
@@ -535,12 +562,19 @@
system_modules: "none",
apex_available: [ "myapex" ],
}
+
+ runtime_resource_overlay {
+ name: "rro",
+ theme: "blue",
+ }
+
`)
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"etc/myetc",
"javalib/myjar.jar",
"lib64/mylib.so",
"app/AppFoo/AppFoo.apk",
+ "overlay/blue/rro.apk",
})
}
@@ -1439,6 +1473,64 @@
ensureListContains(t, dirs, "bin/foo/bar")
}
+func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ multilib: {
+ both: {
+ native_shared_libs: ["mylib"],
+ binaries: ["mybin"],
+ },
+ },
+ compile_multilib: "both",
+ native_bridge_supported: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ relative_install_path: "foo/bar",
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ native_bridge_supported: true,
+ }
+
+ cc_binary {
+ name: "mybin",
+ relative_install_path: "foo/bar",
+ system_shared_libs: [],
+ static_executable: true,
+ stl: "none",
+ apex_available: [ "myapex" ],
+ native_bridge_supported: true,
+ compile_multilib: "both", // default is "first" for binary
+ multilib: {
+ lib64: {
+ suffix: "64",
+ },
+ },
+ }
+ `, withNativeBridgeEnabled)
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "bin/foo/bar/mybin",
+ "bin/foo/bar/mybin64",
+ "bin/arm/foo/bar/mybin",
+ "bin/arm64/foo/bar/mybin64",
+ "lib/foo/bar/mylib.so",
+ "lib/arm/foo/bar/mylib.so",
+ "lib64/foo/bar/mylib.so",
+ "lib64/arm64/foo/bar/mylib.so",
+ })
+}
+
func TestUseVendor(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -2312,15 +2404,7 @@
stl: "none",
apex_available: [ "myapex" ],
}
- `+vndkLibrariesTxtFiles("current"),
- withTargets(map[android.OsType][]android.Target{
- android.Android: []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm64", NativeBridgeRelativePath: "x86_64"},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "arm", NativeBridgeRelativePath: "x86"},
- },
- }))
+ `+vndkLibrariesTxtFiles("current"), withNativeBridgeEnabled)
ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
"lib/libvndk.so",
@@ -2415,7 +2499,8 @@
withBinder32bit,
withTargets(map[android.OsType][]android.Target{
android.Android: []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
},
}),
)
@@ -3405,6 +3490,7 @@
dex_preopt: {
enabled: false,
},
+ apex_available: ["myapex"],
}
android_app_import {
@@ -3416,6 +3502,7 @@
enabled: false,
},
filename: "AwesomePrebuiltAppFooPriv.apk",
+ apex_available: ["myapex"],
}
`)
@@ -3457,6 +3544,7 @@
filename: "AppFooPrebuilt.apk",
presigned: true,
prefer: true,
+ apex_available: ["myapex"],
}
`, withFiles(map[string][]byte{
"AppFooPrebuilt.apk": nil,
@@ -4152,6 +4240,47 @@
ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
}
+func TestApexWithJniLibs(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+ `)
+
+ rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
+ // Notice mylib2.so (transitive dep) is not added as a jni_lib
+ ensureEquals(t, rule.Args["opt"], "-a jniLibs mylib.so")
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "lib64/mylib.so",
+ "lib64/mylib2.so",
+ })
+}
+
func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -4173,6 +4302,29 @@
}
}
+func TestApexWithJniLibs_Errors(t *testing.T) {
+ testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["xxx"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_etc {
+ name: "xxx",
+ src: "xxx",
+ }
+ `, withFiles(map[string][]byte{
+ "xxx": nil,
+ }))
+}
+
func TestAppBundle(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -4213,6 +4365,13 @@
"system/sepolicy/apex/some-updatable-apex-file_contexts",
],
}
+
+ filegroup {
+ name: "some-non-updatable-apex-file_contexts",
+ srcs: [
+ "system/sepolicy/apex/some-non-updatable-apex-file_contexts",
+ ],
+ }
`
bp += cc.GatherRequiredDepsForTest(android.Android)
bp += java.GatherRequiredDepsForTest()
@@ -4225,6 +4384,7 @@
"apex_manifest.json": nil,
"AndroidManifest.xml": nil,
"system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
+ "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
"system/sepolicy/apex/com.android.art.something-file_contexts": nil,
"framework/aidl/a.aidl": nil,
}
@@ -4295,6 +4455,14 @@
}
java_library {
+ name: "some-non-updatable-apex-lib",
+ srcs: ["a.java"],
+ apex_available: [
+ "some-non-updatable-apex",
+ ],
+ }
+
+ java_library {
name: "some-platform-lib",
srcs: ["a.java"],
installable: true,
@@ -4313,16 +4481,30 @@
name: "some-updatable-apex",
key: "some-updatable-apex.key",
java_libs: ["some-updatable-apex-lib"],
+ updatable: true,
+ min_sdk_version: "current",
+ }
+
+ apex {
+ name: "some-non-updatable-apex",
+ key: "some-non-updatable-apex.key",
+ java_libs: ["some-non-updatable-apex-lib"],
}
apex_key {
name: "some-updatable-apex.key",
}
+ apex_key {
+ name: "some-non-updatable-apex.key",
+ }
+
apex {
name: "com.android.art.something",
key: "com.android.art.something.key",
java_libs: ["some-art-lib"],
+ updatable: true,
+ min_sdk_version: "current",
}
apex_key {
@@ -4353,6 +4535,13 @@
}
testNoUpdatableJarsInBootImage(t, error, bp, transform)
+ // non-updatable jar from some other apex in the ART boot image => error
+ error = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.ArtApexJars = []string{"some-non-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
// updatable jar from some other apex in the framework boot image => error
error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
transform = func(config *dexpreopt.GlobalConfig) {
@@ -4360,6 +4549,12 @@
}
testNoUpdatableJarsInBootImage(t, error, bp, transform)
+ // non-updatable jar from some other apex in the framework boot image => ok
+ transform = func(config *dexpreopt.GlobalConfig) {
+ config.BootJars = []string{"some-non-updatable-apex-lib"}
+ }
+ testNoUpdatableJarsInBootImage(t, "", bp, transform)
+
// nonexistent jar in the ART boot image => error
error = "failed to find a dex jar path for module 'nonexistent'"
transform = func(config *dexpreopt.GlobalConfig) {
@@ -4375,7 +4570,7 @@
testNoUpdatableJarsInBootImage(t, error, bp, transform)
// platform jar in the ART boot image => error
- error = "module 'some-platform-lib' is part of the platform and not allowed in the ART boot image"
+ error = "module 'some-platform-lib' is not allowed in the ART boot image"
transform = func(config *dexpreopt.GlobalConfig) {
config.ArtApexJars = []string{"some-platform-lib"}
}
diff --git a/apex/builder.go b/apex/builder.go
index 0d7e801..52aa51f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -185,6 +185,17 @@
optCommands = append(optCommands, "-v name "+*a.properties.Apex_name)
}
+ // collect jniLibs. Notice that a.filesInfo is already sorted
+ var jniLibs []string
+ for _, fi := range a.filesInfo {
+ if fi.isJniLib {
+ jniLibs = append(jniLibs, fi.builtFile.Base())
+ }
+ }
+ if len(jniLibs) > 0 {
+ optCommands = append(optCommands, "-a jniLibs "+strings.Join(jniLibs, " "))
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: apexManifestRule,
Input: manifestSrc,
@@ -225,10 +236,8 @@
return false
}
- notice := to.NoticeFile()
- if notice.Valid() {
- noticeFiles = append(noticeFiles, notice.Path())
- }
+ notices := to.NoticeFiles()
+ noticeFiles = append(noticeFiles, notices...)
return true
})
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 59d1502..4cdfb31 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -60,6 +60,10 @@
func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cflags := []string{
"-nostdlibinc",
+
+ // Make paths in deps files relative
+ "-no-canonical-prefixes",
+
"-O2",
"-isystem bionic/libc/include",
"-isystem bionic/libc/kernel/uapi",
diff --git a/build_kzip.bash b/build_kzip.bash
index 008030f..0018ea9 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -19,16 +19,20 @@
# The extraction might fail for some source files, so run with -k and then check that
# sufficiently many files were generated.
declare -r out="${OUT_DIR:-out}"
+
# Build extraction files for C++ and Java. Build `merge_zips` which we use later.
build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
-#Build extraction file for Go files in build/soong directory.
+
+# Build extraction file for Go the files in build/{blueprint,soong} directories.
declare -r abspath_out=$(realpath "${out}")
declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
declare -r go_root=$(realpath prebuilts/go/linux-x86)
+declare -r vnames_path=$(realpath build/soong/vnames.go.json)
+declare -r source_root=$PWD
for dir in blueprint soong; do
(cd "build/$dir";
- "$go_extractor" --goroot="$go_root" --rules=vnames.go.json --canonicalize_package_corpus \
- --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
+ KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+ --canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
)
done
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5438b14..671adb5 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -92,6 +92,9 @@
if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
entries.AddStrings("LOCAL_WHOLE_STATIC_LIBRARIES", c.Properties.AndroidMkWholeStaticLibs...)
}
+ if len(c.Properties.AndroidMkHeaderLibs) > 0 {
+ entries.AddStrings("LOCAL_HEADER_LIBRARIES", c.Properties.AndroidMkHeaderLibs...)
+ }
entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
if c.UseVndk() {
entries.SetBool("LOCAL_USE_VNDK", true)
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 9b3235c..1d9cc54 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -18,6 +18,7 @@
"path/filepath"
"android/soong/android"
+
"github.com/google/blueprint"
)
@@ -137,7 +138,9 @@
propertySet.AddPropertyWithTag("shared_libs", p.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
- if len(p.SystemSharedLibs) > 0 {
+ // SystemSharedLibs needs to be propagated if it's a list, even if it's empty,
+ // so check for non-nil instead of nonzero length.
+ if p.SystemSharedLibs != nil {
propertySet.AddPropertyWithTag("system_shared_libs", p.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
}
diff --git a/cc/builder.go b/cc/builder.go
index d8e90b6..2bedd9c 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -38,13 +38,6 @@
)
var (
- abiCheckAllowFlags = []string{
- "-allow-unreferenced-changes",
- "-allow-unreferenced-elf-symbol-changes",
- }
-)
-
-var (
pctx = android.NewPackageContext("android/soong/cc")
cc = pctx.AndroidRemoteStaticRule("cc", android.RemoteRuleSupports{Goma: true, RBE: true},
@@ -65,7 +58,7 @@
ld, ldRE = remoteexec.StaticRules(pctx, "ld",
blueprint.RuleParams{
- Command: "$ldCmd ${crtBegin} @${out}.rsp " +
+ Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " +
"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
CommandDeps: []string{"$ldCmd"},
Rspfile: "${out}.rsp",
@@ -73,28 +66,29 @@
// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
Restat: true,
},
- &remoteexec.REParams{Labels: map[string]string{"type": "link", "tool": "clang"},
+ &remoteexec.REParams{
+ Labels: map[string]string{"type": "link", "tool": "clang"},
ExecStrategy: "${config.RECXXLinksExecStrategy}",
Inputs: []string{"${out}.rsp"},
RSPFile: "${out}.rsp",
- OutputFiles: []string{"${out}"},
+ OutputFiles: []string{"${out}", "$implicitOutputs"},
ToolchainInputs: []string{"$ldCmd"},
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
- }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, nil)
+ }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitOutputs"})
partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
blueprint.RuleParams{
// Without -no-pie, clang 7.0 adds -pie to link Android files,
// but -r and -pie cannot be used together.
- Command: "$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
+ Command: "$reTemplate$ldCmd -fuse-ld=lld -nostdlib -no-pie -Wl,-r ${in} -o ${out} ${ldFlags}",
CommandDeps: []string{"$ldCmd"},
}, &remoteexec.REParams{
Labels: map[string]string{"type": "link", "tool": "clang"},
ExecStrategy: "${config.RECXXLinksExecStrategy}", Inputs: []string{"$inCommaList"},
- OutputFiles: []string{"${out}"},
+ OutputFiles: []string{"${out}", "$implicitOutputs"},
ToolchainInputs: []string{"$ldCmd"},
Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
- }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList"})
+ }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList", "implicitOutputs"})
ar = pctx.AndroidStaticRule("ar",
blueprint.RuleParams{
@@ -199,12 +193,18 @@
_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
- sAbiDump = pctx.AndroidStaticRule("sAbiDump",
+ sAbiDump, sAbiDumpRE = remoteexec.StaticRules(pctx, "sAbiDump",
blueprint.RuleParams{
- Command: "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
+ Command: "rm -f $out && $reTemplate$sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
CommandDeps: []string{"$sAbiDumper"},
- },
- "cFlags", "exportDirs")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
+ ExecStrategy: "${config.REAbiDumperExecStrategy}",
+ Platform: map[string]string{
+ remoteexec.PoolKey: "${config.RECXXPool}",
+ "InputRootAbsolutePath": android.AbsSrcDirForExistingUseCases(),
+ },
+ }, []string{"cFlags", "exportDirs"}, nil)
_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
@@ -221,8 +221,7 @@
sAbiDiff = pctx.RuleFunc("sAbiDiff",
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})"
+ commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'"
commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
commandStr += " && exit 1)"
@@ -231,7 +230,7 @@
CommandDeps: []string{"$sAbiDiffer"},
}
},
- "allowFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
+ "extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
blueprint.RuleParams{
@@ -567,8 +566,12 @@
sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
+ dumpRule := sAbiDump
+ if ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") {
+ dumpRule = sAbiDumpRE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: sAbiDump,
+ Rule: dumpRule,
Description: "header-abi-dumper " + srcFile.Rel(),
Output: sAbiDumpFile,
Input: srcFile,
@@ -672,8 +675,17 @@
}
rule := ld
+ args := map[string]string{
+ "ldCmd": ldCmd,
+ "crtBegin": crtBegin.String(),
+ "libFlags": strings.Join(libFlagsList, " "),
+ "extraLibFlags": flags.extraLibFlags,
+ "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
+ "crtEnd": crtEnd.String(),
+ }
if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
rule = ldRE
+ args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
@@ -683,14 +695,7 @@
ImplicitOutputs: implicitOutputs,
Inputs: objFiles,
Implicits: deps,
- Args: map[string]string{
- "ldCmd": ldCmd,
- "crtBegin": crtBegin.String(),
- "libFlags": strings.Join(libFlagsList, " "),
- "extraLibFlags": flags.extraLibFlags,
- "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
- "crtEnd": crtEnd.String(),
- },
+ Args: args,
})
}
@@ -742,27 +747,36 @@
}
func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName, exportedHeaderFlags string, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
+ baseName, exportedHeaderFlags string, checkAllApis, isLlndk, isNdk, isVndkExt bool) android.OptionalPath {
outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
createReferenceDumpFlags := ""
- localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
- if exportedHeaderFlags == "" {
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
+ var extraFlags []string
+ if checkAllApis {
+ extraFlags = append(extraFlags, "-check-all-apis")
+ } else {
+ extraFlags = append(extraFlags,
+ "-allow-unreferenced-changes",
+ "-allow-unreferenced-elf-symbol-changes")
}
+
+ if exportedHeaderFlags == "" {
+ extraFlags = append(extraFlags, "-advice-only")
+ }
+
if isLlndk || isNdk {
createReferenceDumpFlags = "--llndk"
if isLlndk {
// TODO(b/130324828): "-consider-opaque-types-different" should apply to
// both LLNDK and NDK shared libs. However, a known issue in header-abi-diff
// breaks libaaudio. Remove the if-guard after the issue is fixed.
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-consider-opaque-types-different")
+ extraFlags = append(extraFlags, "-consider-opaque-types-different")
}
}
if isVndkExt {
- localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
+ extraFlags = append(extraFlags, "-allow-extensions")
}
ctx.Build(pctx, android.BuildParams{
@@ -775,7 +789,7 @@
"referenceDump": referenceDump.String(),
"libName": libName,
"arch": ctx.Arch().ArchType.Name,
- "allowFlags": strings.Join(localAbiCheckAllowFlags, " "),
+ "extraFlags": strings.Join(extraFlags, " "),
"createReferenceDumpFlags": createReferenceDumpFlags,
},
})
diff --git a/cc/cc.go b/cc/cc.go
index b237935..082816e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -223,6 +223,7 @@
AndroidMkStaticLibs []string `blueprint:"mutated"`
AndroidMkRuntimeLibs []string `blueprint:"mutated"`
AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
+ AndroidMkHeaderLibs []string `blueprint:"mutated"`
HideFromMake bool `blueprint:"mutated"`
PreventInstall bool `blueprint:"mutated"`
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
@@ -396,7 +397,7 @@
type specifiedDeps struct {
sharedLibs []string
- systemSharedLibs []string
+ systemSharedLibs []string // Note nil and [] are semantically distinct.
}
type installer interface {
@@ -1198,6 +1199,11 @@
return false
}
+ // Coverage builds have extra symbols.
+ if ctx.mod.isCoverageVariant() {
+ return false
+ }
+
if ctx.ctx.Fuchsia() {
return false
}
@@ -2601,6 +2607,9 @@
case wholeStaticDepTag:
c.Properties.AndroidMkWholeStaticLibs = append(
c.Properties.AndroidMkWholeStaticLibs, makeLibName(depName))
+ case headerDepTag:
+ c.Properties.AndroidMkHeaderLibs = append(
+ c.Properties.AndroidMkHeaderLibs, makeLibName(depName))
}
})
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 19aedd9..5575baa 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -37,10 +37,8 @@
}
arm64Ldflags = []string{
- "-Wl,-m,aarch64_elf64_le_vec",
"-Wl,--hash-style=gnu",
"-Wl,-z,separate-code",
- "-fuse-ld=gold",
"-Wl,--icf=safe",
}
diff --git a/cc/config/clang.go b/cc/config/clang.go
index d849906..24dc6b9 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -48,8 +48,10 @@
"-Wunused-but-set-parameter",
"-Wunused-but-set-variable",
"-fdiagnostics-color",
+ // http://b/153759688
+ "-fuse-init-array",
- // arm + arm64 + mips + mips64
+ // arm + arm64
"-fgcse-after-reload",
"-frerun-cse-after-loop",
"-frename-registers",
@@ -68,11 +70,6 @@
"-fno-tree-copy-prop",
"-fno-tree-loop-optimize",
- // mips + mips64
- "-msynci",
- "-mno-synci",
- "-mno-fused-madd",
-
// x86 + x86_64
"-finline-limit=300",
"-fno-inline-functions-called-once",
@@ -85,10 +82,8 @@
// Ldflags that should be filtered out when linking with clang lld
var ClangUnknownLldflags = sorted([]string{
- "-fuse-ld=gold",
"-Wl,--fix-cortex-a8",
"-Wl,--no-fix-cortex-a8",
- "-Wl,-m,aarch64_elf64_le_vec",
})
var ClangLibToolingUnknownCflags = sorted([]string{})
@@ -120,9 +115,6 @@
// color codes if it is not running in a terminal.
"-fcolor-diagnostics",
- // http://b/68236239 Allow 0/NULL instead of using nullptr everywhere.
- "-Wno-zero-as-null-pointer-constant",
-
// Warnings from clang-7.0
"-Wno-sign-compare",
@@ -173,6 +165,17 @@
"-Wno-int-in-bool-context", // http://b/148287349
"-Wno-sizeof-array-div", // http://b/148815709
"-Wno-tautological-overlap-compare", // http://b/148815696
+ // New warnings to be fixed after clang-r383902.
+ "-Wno-deprecated-copy", // http://b/153746672
+ "-Wno-range-loop-construct", // http://b/153747076
+ "-Wno-misleading-indentation", // http://b/153746954
+ "-Wno-zero-as-null-pointer-constant", // http://b/68236239
+ "-Wno-deprecated-anon-enum-enum-conversion", // http://b/153746485
+ "-Wno-deprecated-enum-enum-conversion", // http://b/153746563
+ "-Wno-string-compare", // http://b/153764102
+ "-Wno-enum-enum-conversion", // http://b/154138986
+ "-Wno-enum-float-conversion", // http://b/154255917
+ "-Wno-pessimizing-move", // http://b/154270751
}, " "))
// Extra cflags for external third-party projects to disable warnings that
diff --git a/cc/config/global.go b/cc/config/global.go
index d85ac5f..923dd29 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -128,8 +128,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r377782d"
- ClangDefaultShortVersion = "10.0.6"
+ ClangDefaultVersion = "clang-r383902"
+ ClangDefaultShortVersion = "11.0.1"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -257,8 +257,10 @@
return ""
})
- pctx.VariableFunc("RECXXLinksPool", envOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
- pctx.VariableFunc("RECXXLinksExecStrategy", envOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RECXXPool", remoteexec.EnvOverrideFunc("RBE_CXX_POOL", remoteexec.DefaultPool))
+ pctx.VariableFunc("RECXXLinksPool", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
+ pctx.VariableFunc("RECXXLinksExecStrategy", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REAbiDumperExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
deleted file mode 100644
index c2af951..0000000
--- a/cc/config/mips64_device.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2015 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 config
-
-import (
- "strings"
-
- "android/soong/android"
-)
-
-var (
- mips64Cflags = []string{
- "-Umips",
-
- // Help catch common 32/64-bit errors.
- "-Werror=implicit-function-declaration",
- }
-
- mips64ClangCflags = append(mips64Cflags, []string{
- "-fintegrated-as",
- }...)
-
- mips64Cppflags = []string{}
-
- mips64Ldflags = []string{
- "-Wl,--allow-shlib-undefined",
- }
-
- mips64ArchVariantCflags = map[string][]string{
- "mips64r2": []string{
- "-mips64r2",
- "-msynci",
- },
- "mips64r6": []string{
- "-mips64r6",
- "-msynci",
- },
- }
-)
-
-const (
- mips64GccVersion = "4.9"
-)
-
-func init() {
- pctx.StaticVariable("mips64GccVersion", mips64GccVersion)
-
- pctx.SourcePathVariable("Mips64GccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
-
- pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips"))
-
- // Clang cflags
- pctx.StaticVariable("Mips64ClangCflags", strings.Join(ClangFilterUnknownCflags(mips64ClangCflags), " "))
- pctx.StaticVariable("Mips64ClangLdflags", strings.Join(ClangFilterUnknownCflags(mips64Ldflags), " "))
- pctx.StaticVariable("Mips64ClangCppflags", strings.Join(ClangFilterUnknownCflags(mips64Cppflags), " "))
-
- // Extended cflags
-
- // Architecture variant cflags
- for variant, cflags := range mips64ArchVariantCflags {
- pctx.StaticVariable("Mips64"+variant+"VariantClangCflags",
- strings.Join(ClangFilterUnknownCflags(cflags), " "))
- }
-}
-
-type toolchainMips64 struct {
- toolchain64Bit
- clangCflags string
- toolchainClangCflags string
-}
-
-func (t *toolchainMips64) Name() string {
- return "mips64"
-}
-
-func (t *toolchainMips64) GccRoot() string {
- return "${config.Mips64GccRoot}"
-}
-
-func (t *toolchainMips64) GccTriple() string {
- return "mips64el-linux-android"
-}
-
-func (t *toolchainMips64) GccVersion() string {
- return mips64GccVersion
-}
-
-func (t *toolchainMips64) IncludeFlags() string {
- return "${config.Mips64IncludeFlags}"
-}
-
-func (t *toolchainMips64) ClangTriple() string {
- return t.GccTriple()
-}
-
-func (t *toolchainMips64) ToolchainClangCflags() string {
- return t.toolchainClangCflags
-}
-
-func (t *toolchainMips64) ClangAsflags() string {
- return "-fno-integrated-as"
-}
-
-func (t *toolchainMips64) ClangCflags() string {
- return t.clangCflags
-}
-
-func (t *toolchainMips64) ClangCppflags() string {
- return "${config.Mips64ClangCppflags}"
-}
-
-func (t *toolchainMips64) ClangLdflags() string {
- return "${config.Mips64ClangLdflags}"
-}
-
-func (t *toolchainMips64) ClangLldflags() string {
- // TODO: define and use Mips64ClangLldflags
- return "${config.Mips64ClangLdflags}"
-}
-
-func (toolchainMips64) LibclangRuntimeLibraryArch() string {
- return "mips64"
-}
-
-func mips64ToolchainFactory(arch android.Arch) Toolchain {
- return &toolchainMips64{
- clangCflags: "${config.Mips64ClangCflags}",
- toolchainClangCflags: "${config.Mips64" + arch.ArchVariant + "VariantClangCflags}",
- }
-}
-
-func init() {
- registerToolchainFactory(android.Android, android.Mips64, mips64ToolchainFactory)
-}
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
deleted file mode 100644
index ddbc41b..0000000
--- a/cc/config/mips_device.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2015 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 config
-
-import (
- "strings"
-
- "android/soong/android"
-)
-
-var (
- mipsCflags = []string{
- "-fomit-frame-pointer",
- "-Umips",
- }
-
- mipsClangCflags = append(mipsCflags, []string{
- "-fPIC",
- "-fintegrated-as",
- }...)
-
- mipsCppflags = []string{}
-
- mipsLdflags = []string{
- "-Wl,--allow-shlib-undefined",
- }
-
- mipsToolchainLdflags = []string{
- "-Wl,-melf32ltsmip",
- }
-
- mipsArchVariantCflags = map[string][]string{
- "mips32-fp": []string{
- "-mips32",
- "-mfp32",
- "-modd-spreg",
- "-mno-synci",
- },
- "mips32r2-fp": []string{
- "-mips32r2",
- "-mfp32",
- "-modd-spreg",
- "-msynci",
- },
- "mips32r2-fp-xburst": []string{
- "-mips32r2",
- "-mfp32",
- "-modd-spreg",
- "-mno-fused-madd",
- "-mno-synci",
- },
- "mips32r2dsp-fp": []string{
- "-mips32r2",
- "-mfp32",
- "-modd-spreg",
- "-mdsp",
- "-msynci",
- },
- "mips32r2dspr2-fp": []string{
- "-mips32r2",
- "-mfp32",
- "-modd-spreg",
- "-mdspr2",
- "-msynci",
- },
- "mips32r6": []string{
- "-mips32r6",
- "-mfp64",
- "-mno-odd-spreg",
- "-msynci",
- },
- }
-)
-
-const (
- mipsGccVersion = "4.9"
-)
-
-func init() {
- pctx.StaticVariable("mipsGccVersion", mipsGccVersion)
-
- pctx.SourcePathVariable("MipsGccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
-
- pctx.StaticVariable("MipsToolchainLdflags", strings.Join(mipsToolchainLdflags, " "))
- pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips"))
-
- // Clang cflags
- pctx.StaticVariable("MipsClangCflags", strings.Join(ClangFilterUnknownCflags(mipsClangCflags), " "))
- pctx.StaticVariable("MipsClangLdflags", strings.Join(ClangFilterUnknownCflags(mipsLdflags), " "))
- pctx.StaticVariable("MipsClangCppflags", strings.Join(ClangFilterUnknownCflags(mipsCppflags), " "))
-
- // Extended cflags
-
- // Architecture variant cflags
- for variant, cflags := range mipsArchVariantCflags {
- pctx.StaticVariable("Mips"+variant+"VariantClangCflags",
- strings.Join(ClangFilterUnknownCflags(cflags), " "))
- }
-}
-
-type toolchainMips struct {
- toolchain32Bit
- clangCflags string
- toolchainClangCflags string
-}
-
-func (t *toolchainMips) Name() string {
- return "mips"
-}
-
-func (t *toolchainMips) GccRoot() string {
- return "${config.MipsGccRoot}"
-}
-
-func (t *toolchainMips) GccTriple() string {
- return "mips64el-linux-android"
-}
-
-func (t *toolchainMips) GccVersion() string {
- return mipsGccVersion
-}
-
-func (t *toolchainMips) IncludeFlags() string {
- return "${config.MipsIncludeFlags}"
-}
-
-func (t *toolchainMips) ClangTriple() string {
- return "mipsel-linux-android"
-}
-
-func (t *toolchainMips) ToolchainClangLdflags() string {
- return "${config.MipsToolchainLdflags}"
-}
-
-func (t *toolchainMips) ToolchainClangCflags() string {
- return t.toolchainClangCflags
-}
-
-func (t *toolchainMips) ClangAsflags() string {
- return "-fPIC -fno-integrated-as"
-}
-
-func (t *toolchainMips) ClangCflags() string {
- return t.clangCflags
-}
-
-func (t *toolchainMips) ClangCppflags() string {
- return "${config.MipsClangCppflags}"
-}
-
-func (t *toolchainMips) ClangLdflags() string {
- return "${config.MipsClangLdflags}"
-}
-
-func (t *toolchainMips) ClangLldflags() string {
- // TODO: define and use MipsClangLldflags
- return "${config.MipsClangLdflags}"
-}
-
-func (toolchainMips) LibclangRuntimeLibraryArch() string {
- return "mips"
-}
-
-func mipsToolchainFactory(arch android.Arch) Toolchain {
- return &toolchainMips{
- clangCflags: "${config.MipsClangCflags}",
- toolchainClangCflags: "${config.Mips" + arch.ArchVariant + "VariantClangCflags}",
- }
-}
-
-func init() {
- registerToolchainFactory(android.Android, android.Mips, mipsToolchainFactory)
-}
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index dd52a0e..4ac9e58 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -30,10 +30,12 @@
}
return strings.Join([]string{
"-*",
+ "bugprone*",
"clang-diagnostic-unused-command-line-argument",
"google*",
"misc-macro-parentheses",
"performance*",
+ "-bugprone-narrowing-conversions",
"-google-readability*",
"-google-runtime-references",
}, ",")
diff --git a/cc/fuzz.go b/cc/fuzz.go
index ee24300..948595b 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -126,7 +126,7 @@
func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
var fringe []android.Module
- seen := make(map[android.Module]bool)
+ seen := make(map[string]bool)
// Enumerate the first level of dependencies, as we discard all non-library
// modules in the BFS loop below.
@@ -140,15 +140,15 @@
for i := 0; i < len(fringe); i++ {
module := fringe[i]
- if seen[module] {
+ if seen[module.Name()] {
continue
}
- seen[module] = true
+ seen[module.Name()] = true
ccModule := module.(*Module)
sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
ctx.VisitDirectDeps(module, func(dep android.Module) {
- if isValidSharedDependency(dep) && !seen[dep] {
+ if isValidSharedDependency(dep) && !seen[dep.Name()] {
fringe = append(fringe, dep)
}
})
@@ -198,6 +198,11 @@
return installLocation
}
+// Get the device-only shared library symbols install directory.
+func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string {
+ return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base())
+}
+
func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
@@ -250,13 +255,13 @@
}
// Grab the list of required shared libraries.
- seen := make(map[android.Module]bool)
+ seen := make(map[string]bool)
var sharedLibraries android.Paths
ctx.WalkDeps(func(child, parent android.Module) bool {
- if seen[child] {
+ if seen[child.Name()] {
return false
}
- seen[child] = true
+ seen[child.Name()] = true
if isValidSharedDependency(child) {
sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
@@ -269,6 +274,12 @@
fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
sharedLibraryInstallLocation(
lib, ctx.Host(), ctx.Arch().ArchType.String()))
+
+ // Also add the dependency on the shared library symbols dir.
+ if !ctx.Host() {
+ fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+ sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String()))
+ }
}
}
@@ -355,10 +366,10 @@
return
}
- // Discard vendor-NDK-linked + ramdisk + recovery modules, they're duplicates of
+ // Discard ramdisk + recovery modules, they're duplicates of
// fuzz targets we're going to package anyway.
if !ccModule.Enabled() || ccModule.Properties.PreventInstall ||
- ccModule.UseVndk() || ccModule.InRamdisk() || ccModule.InRecovery() {
+ ccModule.InRamdisk() || ccModule.InRecovery() {
return
}
@@ -367,8 +378,6 @@
return
}
- s.fuzzTargets[module.Name()] = true
-
hostOrTargetString := "target"
if ccModule.Host() {
hostOrTargetString = "host"
@@ -421,12 +430,24 @@
continue
}
sharedLibraryInstalled[installDestination] = true
+
// Escape all the variables, as the install destination here will be called
// via. $(eval) in Make.
installDestination = strings.ReplaceAll(
installDestination, "$", "$$")
s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
library.String()+":"+installDestination)
+
+ // Ensure that on device, the library is also reinstalled to the /symbols/
+ // dir. Symbolized DSO's are always installed to the device when fuzzing, but
+ // we want symbolization tools (like `stack`) to be able to find the symbols
+ // in $ANDROID_PRODUCT_OUT/symbols automagically.
+ if !ccModule.Host() {
+ symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
+ symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
+ s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
+ library.String()+":"+symbolsInstallDestination)
+ }
}
// The executable.
@@ -458,6 +479,17 @@
builder.Build(pctx, ctx, "create-"+fuzzZip.String(),
"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
+ // Don't add modules to 'make haiku' that are set to not be exported to the
+ // fuzzing infrastructure.
+ if config := fuzzModule.Properties.Fuzz_config; config != nil {
+ if ccModule.Host() && !BoolDefault(config.Fuzz_on_haiku_host, true) {
+ return
+ } else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
+ return
+ }
+ }
+
+ s.fuzzTargets[module.Name()] = true
archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
})
diff --git a/cc/gen_stub_libs.py b/cc/gen_stub_libs.py
index 0de703c..7deb804 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/gen_stub_libs.py
@@ -26,8 +26,6 @@
ALL_ARCHITECTURES = (
'arm',
'arm64',
- 'mips',
- 'mips64',
'x86',
'x86_64',
)
diff --git a/cc/library.go b/cc/library.go
index ce814b1..ecea2ea 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -102,6 +102,10 @@
// Symbol tags that should be ignored from the symbol file
Exclude_symbol_tags []string
+
+ // Run checks on all APIs (in addition to the ones referred by
+ // one of exported ELF symbols.)
+ Check_all_apis *bool
}
// Order symbols in .bss section by their sizes. Only useful for shared libraries.
@@ -376,7 +380,7 @@
useCoreVariant bool
checkSameCoreVariant bool
- // Decorated interafaces
+ // Decorated interfaces
*baseCompiler
*baseLinker
*baseInstaller
@@ -749,10 +753,12 @@
func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
if library.static() {
+ // Compare with nil because an empty list needs to be propagated.
if library.StaticProperties.Static.System_shared_libs != nil {
library.baseLinker.Properties.System_shared_libs = library.StaticProperties.Static.System_shared_libs
}
} else if library.shared() {
+ // Compare with nil because an empty list needs to be propagated.
if library.SharedProperties.Shared.System_shared_libs != nil {
library.baseLinker.Properties.System_shared_libs = library.SharedProperties.Shared.System_shared_libs
}
@@ -828,10 +834,21 @@
}
specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...)
- specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
+
+ // Must distinguish nil and [] in system_shared_libs - ensure that [] in
+ // either input list doesn't come out as nil.
+ if specifiedDeps.systemSharedLibs == nil {
+ specifiedDeps.systemSharedLibs = properties.System_shared_libs
+ } else {
+ specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
+ }
specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
- specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
+ if len(specifiedDeps.systemSharedLibs) > 0 {
+ // Skip this if systemSharedLibs is either nil or [], to ensure they are
+ // retained.
+ specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
+ }
return specifiedDeps
}
@@ -1059,7 +1076,9 @@
refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
if refAbiDumpFile != nil {
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- refAbiDumpFile, fileName, exportedHeaderFlags, ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
+ refAbiDumpFile, fileName, exportedHeaderFlags,
+ Bool(library.Properties.Header_abi_checker.Check_all_apis),
+ ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
}
}
}
@@ -1384,6 +1403,8 @@
len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 &&
len(staticCompiler.StaticProperties.Static.Shared_libs) == 0 &&
len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 &&
+ // Compare System_shared_libs properties with nil because empty lists are
+ // semantically significant for them.
staticCompiler.StaticProperties.Static.System_shared_libs == nil &&
sharedCompiler.SharedProperties.Shared.System_shared_libs == nil {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 88cf7af..b7ab390 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -29,7 +29,7 @@
SupportsSdk: true,
},
prebuiltModuleType: "cc_prebuilt_library_headers",
- linkTypes: nil,
+ noOutputFiles: true,
}
func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 566bdce..953e85f 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -18,6 +18,7 @@
"path/filepath"
"android/soong/android"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -63,7 +64,10 @@
prebuiltModuleType string
- // The set of link types supported, set of "static", "shared".
+ noOutputFiles bool // True if there are no srcs files.
+
+ // The set of link types supported. A set of "static", "shared", or nil to
+ // skip link type variations.
linkTypes []string
}
@@ -208,7 +212,9 @@
outputProperties.AddPropertyWithTag("shared_libs", libInfo.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
- if len(libInfo.SystemSharedLibs) > 0 {
+ // SystemSharedLibs needs to be propagated if it's a list, even if it's empty,
+ // so check for non-nil instead of nonzero length.
+ if libInfo.SystemSharedLibs != nil {
outputProperties.AddPropertyWithTag("system_shared_libs", libInfo.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
@@ -263,6 +269,11 @@
for property, dirs := range includeDirs {
outputProperties.AddProperty(property, dirs)
}
+
+ if len(libInfo.StubsVersion) > 0 {
+ stubsSet := outputProperties.AddPropertySet("stubs")
+ stubsSet.AddProperty("versions", []string{libInfo.StubsVersion})
+ }
}
const (
@@ -323,11 +334,16 @@
// This field is exported as its contents may not be arch specific.
SharedLibs []string
- // The set of system shared libraries
+ // The set of system shared libraries. Note nil and [] are semantically
+ // distinct - see BaseLinkerProperties.System_shared_libs.
//
// This field is exported as its contents may not be arch specific.
SystemSharedLibs []string
+ // The specific stubs version for the lib variant, or empty string if stubs
+ // are not in use.
+ StubsVersion string
+
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
@@ -337,7 +353,7 @@
// If the library has some link types then it produces an output binary file, otherwise it
// is header only.
- if p.memberType.linkTypes != nil {
+ if !p.memberType.noOutputFiles {
p.outputFile = ccModule.OutputFile().Path()
}
@@ -359,10 +375,17 @@
specifiedDeps := specifiedDeps{}
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
- p.SharedLibs = specifiedDeps.sharedLibs
+ if !ccModule.HasStubsVariants() {
+ // Propagate dynamic dependencies for implementation libs, but not stubs.
+ p.SharedLibs = specifiedDeps.sharedLibs
+ }
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
+
+ if ccModule.HasStubsVariants() {
+ p.StubsVersion = ccModule.StubsVersion()
+ }
}
func (p *nativeLibInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/cc/linker.go b/cc/linker.go
index 9b2c1e7..57a0c01 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -449,11 +449,10 @@
}
}
- if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) {
+ if ctx.useSdk() {
// The bionic linker now has support gnu style hashes (which are much faster!), but shipping
// to older devices requires the old style hash. Fortunately, we can build with both and
// it'll work anywhere.
- // This is not currently supported on MIPS architectures.
flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
}
@@ -503,7 +502,15 @@
func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
- specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
+
+ // Must distinguish nil and [] in system_shared_libs - ensure that [] in
+ // either input list doesn't come out as nil.
+ if specifiedDeps.systemSharedLibs == nil {
+ specifiedDeps.systemSharedLibs = linker.Properties.System_shared_libs
+ } else {
+ specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
+ }
+
return specifiedDeps
}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 5744bb2..60f931d 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -17,7 +17,6 @@
import (
"fmt"
"path/filepath"
- "strings"
"github.com/google/blueprint"
@@ -131,14 +130,6 @@
m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
- // When generating NDK prebuilts, skip installing MIPS headers,
- // but keep them when doing regular platform build.
- // Ndk_abis property is only set to true with build/soong/scripts/build-ndk-prebuilts.sh
- // TODO: Revert this once MIPS is supported in NDK again.
- if ctx.Config().NdkAbis() && strings.Contains(ctx.ModuleName(), "mips") {
- return
- }
-
srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
for _, header := range srcFiles {
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 119ca40..1597b88 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -135,8 +135,6 @@
firstArchVersions := map[android.ArchType]int{
android.Arm: minVersion,
android.Arm64: 21,
- android.Mips: minVersion,
- android.Mips64: 21,
android.X86: minVersion,
android.X86_64: 21,
}
diff --git a/cc/object.go b/cc/object.go
index ad31d09..19decec 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -26,6 +26,16 @@
func init() {
android.RegisterModuleType("cc_object", ObjectFactory)
+ android.RegisterSdkMemberType(ccObjectSdkMemberType)
+}
+
+var ccObjectSdkMemberType = &librarySdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "native_objects",
+ SupportsSdk: true,
+ },
+ prebuiltModuleType: "cc_prebuilt_object",
+ linkTypes: nil,
}
type objectLinker struct {
@@ -47,12 +57,18 @@
Linker_script *string `android:"path,arch_variant"`
}
+func newObject() *Module {
+ module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
+ module.sanitize = &sanitize{}
+ module.stl = &stl{}
+ return module
+}
+
// cc_object runs the compiler without running the linker. It is rarely
// necessary, but sometimes used to generate .s files from .c files to use as
// input to a cc_genrule module.
func ObjectFactory() android.Module {
- module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth)
- module.sanitize = &sanitize{}
+ module := newObject()
module.linker = &objectLinker{
baseLinker: NewBaseLinker(module.sanitize),
}
@@ -61,7 +77,7 @@
// Clang's address-significance tables are incompatible with ld -r.
module.compiler.appendCflags([]string{"-fno-addrsig"})
- module.stl = &stl{}
+ module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType}
return module.Init()
}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 3dbd3e3..ac990f3 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -26,6 +26,7 @@
ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
+ ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
}
@@ -42,6 +43,11 @@
// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined
// symbols, etc), default true.
Check_elf_files *bool
+
+ // Optionally provide an import library if this is a Windows PE DLL prebuilt.
+ // This is needed only if this library is linked by other modules in build time.
+ // Only makes sense for the Windows target.
+ Windows_import_lib *string `android:"path,arch_variant"`
}
type prebuiltLinker struct {
@@ -108,9 +114,16 @@
in := android.PathForModuleSrc(ctx, srcs[0])
+ if p.static() {
+ return in
+ }
+
if p.shared() {
p.unstrippedOutputFile = in
libName := p.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
+ outputFile := android.PathForModuleOut(ctx, libName)
+ var implicits android.Paths
+
if p.needsStrip(ctx) {
stripped := android.PathForModuleOut(ctx, "stripped", libName)
p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
@@ -121,10 +134,41 @@
// depending on a table of contents file instead of the library itself.
tocFile := android.PathForModuleOut(ctx, libName+".toc")
p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
- }
+ TransformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
- return in
+ if ctx.Windows() && p.properties.Windows_import_lib != nil {
+ // Consumers of this library actually links to the import library in build
+ // time and dynamically links to the DLL in run time. i.e.
+ // a.exe <-- static link --> foo.lib <-- dynamic link --> foo.dll
+ importLibSrc := android.PathForModuleSrc(ctx, String(p.properties.Windows_import_lib))
+ importLibName := p.libraryDecorator.getLibName(ctx) + ".lib"
+ importLibOutputFile := android.PathForModuleOut(ctx, importLibName)
+ implicits = append(implicits, importLibOutputFile)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Description: "prebuilt import library",
+ Input: importLibSrc,
+ Output: importLibOutputFile,
+ Args: map[string]string{
+ "cpFlags": "-L",
+ },
+ })
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Description: "prebuilt shared library",
+ Implicits: implicits,
+ Input: in,
+ Output: outputFile,
+ Args: map[string]string{
+ "cpFlags": "-L",
+ },
+ })
+
+ return outputFile
+ }
}
return nil
@@ -222,6 +266,50 @@
return module, library
}
+type prebuiltObjectProperties struct {
+ Srcs []string `android:"path,arch_variant"`
+}
+
+type prebuiltObjectLinker struct {
+ android.Prebuilt
+ objectLinker
+
+ properties prebuiltObjectProperties
+}
+
+func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
+ return &p.Prebuilt
+}
+
+var _ prebuiltLinkerInterface = (*prebuiltObjectLinker)(nil)
+
+func (p *prebuiltObjectLinker) link(ctx ModuleContext,
+ flags Flags, deps PathDeps, objs Objects) android.Path {
+ if len(p.properties.Srcs) > 0 {
+ return p.Prebuilt.SingleSourcePath(ctx)
+ }
+ return nil
+}
+
+func newPrebuiltObject() *Module {
+ module := newObject()
+ prebuilt := &prebuiltObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+ module.AddProperties(&prebuilt.properties)
+ android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+ android.InitSdkAwareModule(module)
+ return module
+}
+
+func prebuiltObjectFactory() android.Module {
+ module := newPrebuiltObject()
+ return module.Init()
+}
+
type prebuiltBinaryLinker struct {
*binaryDecorator
prebuiltLinker
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 0eca97f..adb44bd 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -22,6 +22,25 @@
"github.com/google/blueprint"
)
+func testPrebuilt(t *testing.T, bp string, fs map[string][]byte) *android.TestContext {
+ config := TestConfig(buildDir, android.Android, nil, bp, fs)
+ ctx := CreateTestContext()
+
+ // Enable androidmk support.
+ // * Register the singleton
+ // * Configure that we are inside make
+ // * Add CommonOS to ensure that androidmk processing works.
+ android.RegisterAndroidMkBuildComponents(ctx)
+ android.SetInMakeForTests(config)
+
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+ return ctx
+}
+
func TestPrebuilt(t *testing.T) {
bp := `
cc_library {
@@ -73,9 +92,26 @@
srcs: ["libf.so"],
},
}
+
+ cc_object {
+ name: "crtx",
+ }
+
+ cc_prebuilt_object {
+ name: "crtx",
+ srcs: ["crtx.o"],
+ }
`
- ctx := testPrebuilt(t, bp)
+ ctx := testPrebuilt(t, bp, map[string][]byte{
+ "liba.so": nil,
+ "libb.a": nil,
+ "libd.so": nil,
+ "libe.a": nil,
+ "libf.a": nil,
+ "libf.so": nil,
+ "crtx.o": nil,
+ })
// Verify that all the modules exist and that their dependencies were connected correctly
liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
@@ -84,6 +120,7 @@
libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
+ crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
@@ -91,6 +128,7 @@
prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
+ prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
hasDep := func(m android.Module, wantDep android.Module) bool {
t.Helper()
@@ -126,33 +164,10 @@
if !hasDep(libfShared, prebuiltLibfShared) {
t.Errorf("libf shared missing dependency on prebuilt_libf")
}
-}
-func testPrebuilt(t *testing.T, bp string) *android.TestContext {
- fs := map[string][]byte{
- "liba.so": nil,
- "libb.a": nil,
- "libd.so": nil,
- "libe.a": nil,
- "libf.a": nil,
- "libf.so": nil,
+ if !hasDep(crtx, prebuiltCrtx) {
+ t.Errorf("crtx missing dependency on prebuilt_crtx")
}
- config := TestConfig(buildDir, android.Android, nil, bp, fs)
- ctx := CreateTestContext()
-
- // Enable androidmk support.
- // * Register the singleton
- // * Configure that we are inside make
- // * Add CommonOS to ensure that androidmk processing works.
- android.RegisterAndroidMkBuildComponents(ctx)
- android.SetInMakeForTests(config)
-
- ctx.Register(config)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return ctx
}
func TestPrebuiltLibraryShared(t *testing.T) {
@@ -164,10 +179,12 @@
none: true,
},
}
- `)
+ `, map[string][]byte{
+ "libf.so": nil,
+ })
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
- assertString(t, shared.OutputFile().String(), "libf.so")
+ assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
}
func TestPrebuiltLibraryStatic(t *testing.T) {
@@ -176,10 +193,12 @@
name: "libtest",
srcs: ["libf.a"],
}
- `)
+ `, map[string][]byte{
+ "libf.a": nil,
+ })
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
- assertString(t, static.OutputFile().String(), "libf.a")
+ assertString(t, static.OutputFile().Path().Base(), "libf.a")
}
func TestPrebuiltLibrary(t *testing.T) {
@@ -196,11 +215,59 @@
none: true,
},
}
- `)
+ `, map[string][]byte{
+ "libf.a": nil,
+ "libf.so": nil,
+ })
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
- assertString(t, shared.OutputFile().String(), "libf.so")
+ assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
- assertString(t, static.OutputFile().String(), "libf.a")
+ assertString(t, static.OutputFile().Path().Base(), "libf.a")
+}
+
+func TestPrebuiltLibraryStem(t *testing.T) {
+ ctx := testPrebuilt(t, `
+ cc_prebuilt_library {
+ name: "libfoo",
+ stem: "libbar",
+ static: {
+ srcs: ["libfoo.a"],
+ },
+ shared: {
+ srcs: ["libfoo.so"],
+ },
+ strip: {
+ none: true,
+ },
+ }
+ `, map[string][]byte{
+ "libfoo.a": nil,
+ "libfoo.so": nil,
+ })
+
+ static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
+ assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
+
+ shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
+}
+
+func TestPrebuiltLibrarySharedStem(t *testing.T) {
+ ctx := testPrebuilt(t, `
+ cc_prebuilt_library_shared {
+ name: "libfoo",
+ stem: "libbar",
+ srcs: ["libfoo.so"],
+ strip: {
+ none: true,
+ },
+ }
+ `, map[string][]byte{
+ "libfoo.so": nil,
+ })
+
+ shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f12edc6..d32efda 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -307,8 +307,8 @@
}
}
- // CFI needs gold linker, and mips toolchain does not have one.
- if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 {
+ // Is CFI actually enabled?
+ if !ctx.Config().EnableCFI() {
s.Cfi = nil
s.Diag.Cfi = nil
}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 26e7c8d..4012def 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -81,6 +81,17 @@
return outPath
}
+func combineNotices(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: paths,
+ Output: outPath,
+ Description: "combine notices for " + out,
+ })
+ return outPath
+}
+
func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
outPath := android.PathForOutput(ctx, out)
ctx.Build(pctx, android.BuildParams{
diff --git a/cc/stl.go b/cc/stl.go
index 34ff30c..4e74c7f 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -239,11 +239,6 @@
flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++")
flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
if ctx.Windows() {
- if stl.Properties.SelectedStl == "libc++_static" {
- // These are transitively needed by libc++_static.
- flags.extraLibFlags = append(flags.extraLibFlags,
- "-lmsvcrt", "-lucrt")
- }
// Use SjLj exceptions for 32-bit. libgcc_eh implements SjLj
// exception model for 32-bit.
if ctx.Arch().ArchType == android.X86 {
diff --git a/cc/tidy.go b/cc/tidy.go
index cfb5b68..364e56c 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -121,6 +121,12 @@
// many local projects enable cert-* checks, which
// trigger bugprone-reserved-identifier.
tidyChecks = tidyChecks + ",-bugprone-reserved-identifier*,-cert-dcl51-cpp,-cert-dcl37-c"
+ // http://b/153757728
+ tidyChecks = tidyChecks + ",-readability-qualified-auto"
+ // http://b/155034563
+ tidyChecks = tidyChecks + ",-bugprone-signed-char-misuse"
+ // http://b/155034972
+ tidyChecks = tidyChecks + ",-bugprone-branch-clone"
flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
if len(tidy.Properties.Tidy_checks_as_errors) > 0 {
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index c79a653..5801fc7 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -658,14 +658,14 @@
headers = append(headers, l.snapshotHeaders()...)
}
- if m.NoticeFile().Valid() {
+ if len(m.NoticeFiles()) > 0 {
noticeName := ctx.ModuleName(m) + ".txt"
noticeOut := filepath.Join(noticeDir, noticeName)
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, m.NoticeFile().Path(), noticeOut))
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), noticeOut))
}
}
})
diff --git a/cc/vndk.go b/cc/vndk.go
index 8eab8ba..dbe1f3b 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -660,13 +660,13 @@
moduleNames[stem] = ctx.ModuleName(m)
modulePaths[stem] = ctx.ModuleDir(m)
- if m.NoticeFile().Valid() {
+ if len(m.NoticeFiles()) > 0 {
noticeName := stem + ".txt"
// skip already copied notice file
if _, ok := noticeBuilt[noticeName]; !ok {
noticeBuilt[noticeName] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, m.NoticeFile().Path(), filepath.Join(noticeDir, noticeName)))
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
}
}
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index 2536a53..6b79823 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -17,9 +17,11 @@
deps: [
"blueprint",
"blueprint-bootstrap",
+ "golang-protobuf-proto",
"soong",
"soong-android",
"soong-env",
+ "soong-ui-metrics_proto",
],
srcs: [
"main.go",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 30381e0..bd1a9ed 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -131,4 +131,15 @@
os.Exit(1)
}
}
+
+ // TODO(ccross): make this a command line argument. Requires plumbing through blueprint
+ // to affect the command line of the primary builder.
+ if docFile == "" {
+ metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
+ err = android.WriteMetrics(configuration, metricsFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
+ os.Exit(1)
+ }
+ }
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index db61fba..1d94f02 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -173,6 +173,7 @@
stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
stat.AddOutput(status.NewCriticalPath(log))
+ stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
diff --git a/cuj/cuj.go b/cuj/cuj.go
index c7ff8ff..3333012 100644
--- a/cuj/cuj.go
+++ b/cuj/cuj.go
@@ -33,8 +33,9 @@
)
type Test struct {
- name string
- args []string
+ name string
+ args []string
+ before func() error
results TestResults
}
@@ -119,6 +120,15 @@
t.results.metrics = met
}
+// Touch the Intent.java file to cause a rebuild of the frameworks to monitor the
+// incremental build speed as mentioned b/152046247. Intent.java file was chosen
+// as it is a key component of the framework and is often modified.
+func touchIntentFile() error {
+ const intentFileName = "frameworks/base/core/java/android/content/Intent.java"
+ currentTime := time.Now().Local()
+ return os.Chtimes(intentFileName, currentTime, currentTime)
+}
+
func main() {
outDir := os.Getenv("OUT_DIR")
if outDir == "" {
@@ -170,6 +180,36 @@
name: "framework_rebuild_twice",
args: []string{"framework"},
},
+ {
+ // Scenario major_inc_build (b/152046247): tracking build speed of major incremental build.
+ name: "major_inc_build_droid",
+ args: []string{"droid"},
+ },
+ {
+ name: "major_inc_build_framework_minus_apex_after_droid_build",
+ args: []string{"framework-minus-apex"},
+ before: touchIntentFile,
+ },
+ {
+ name: "major_inc_build_framework_after_droid_build",
+ args: []string{"framework"},
+ before: touchIntentFile,
+ },
+ {
+ name: "major_inc_build_sync_after_droid_build",
+ args: []string{"sync"},
+ before: touchIntentFile,
+ },
+ {
+ name: "major_inc_build_droid_rebuild",
+ args: []string{"droid"},
+ before: touchIntentFile,
+ },
+ {
+ name: "major_inc_build_update_api_after_droid_rebuild",
+ args: []string{"update-api"},
+ before: touchIntentFile,
+ },
}
cujMetrics := metrics.NewCriticalUserJourneysMetrics()
@@ -178,6 +218,12 @@
for i, t := range tests {
logsSubDir := fmt.Sprintf("%02d_%s", i, t.name)
logsDir := filepath.Join(cujDir, "logs", logsSubDir)
+ if t.before != nil {
+ if err := t.before(); err != nil {
+ fmt.Printf("error running before function on test %q: %v\n", t.name, err)
+ break
+ }
+ }
t.Run(logsDir)
if t.results.err != nil {
fmt.Printf("error running test %q: %s\n", t.name, t.results.err)
diff --git a/doc.go b/doc.go
index 543c460..299fd2b 100644
--- a/doc.go
+++ b/doc.go
@@ -46,8 +46,8 @@
//
// Target architecture
// The target architecture is the preferred architecture supported by the selected
-// device. It is most commonly 32-bit arm, but may also be 64-bit arm, 32-bit or
-// 64-bit x86, or mips.
+// device. It is most commonly 32-bit arm, but may also be 64-bit arm, 32-bit
+// x86, or 64-bit x86.
//
// Secondary architecture
// The secondary architecture specifies the architecture to compile a second copy
diff --git a/docs/map_files.md b/docs/map_files.md
new file mode 100644
index 0000000..9fc0d14
--- /dev/null
+++ b/docs/map_files.md
@@ -0,0 +1,174 @@
+# Native API Map Files
+
+Native APIs such as those exposed by the NDK, LL-NDK, or APEX are described by
+map.txt files. These files are [linker version scripts] with comments that are
+semantically meaningful to [gen_stub_libs.py]. For an example of a map file, see
+[libc.map.txt].
+
+[gen_stub_libs.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/gen_stub_libs.py
+[libc.map.txt]: https://cs.android.com/android/platform/superproject/+/master:bionic/libc/libc.map.txt
+[linker version scripts]: https://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html
+
+## Basic format
+
+A linker version script defines at least one alphanumeric "version" definition,
+each of which contain a list of symbols. For example:
+
+```txt
+MY_API_R { # introduced=R
+ global:
+ api_foo;
+ api_bar;
+ local:
+ *;
+};
+
+MY_API_S { # introduced=S
+ global:
+ api_baz;
+} MY_API_R;
+```
+
+Comments on the same line as either a version definition or a symbol name have
+meaning. If you need to add any comments that should not be interpreted by the
+stub generator, keep them on their own line. For a list of supported comments,
+see the "Tags" section.
+
+Here, `api_foo` and `api_bar` are exposed in the generated stubs with the
+`MY_API_R` version and `api_baz` is exposed with the `MY_API_S` version. No
+other symbols are defined as public by this API. `MY_API_S` inherits all symbols
+defined by `MY_API_R`.
+
+When generating NDK API stubs from this version script, the stub library for R
+will define `api_foo` and `api_bar`. The stub library for S will define all
+three APIs.
+
+Note that, with few exceptions (see "Special version names" below), the name of
+the version has no inherent meaning.
+
+These map files can (and should) also be used as version scripts for building
+the implementation library rather than just defining the stub interface by using
+the `version_script` property of `cc_library`. This has the effect of limiting
+symbol visibility of the library to expose only the interface named by the map
+file. Without this, APIs that you have not explicitly exposed will still be
+available to users via `dlsym`. Note: All comments are ignored in this case. Any
+symbol named in any `global:` group will be visible.
+
+## Special version names
+
+Version names that end with `_PRIVATE` or `_PLATFORM` will not be exposed in any
+stubs, but will be exposed in the implementation library. Using either of these
+naming schemes is equivalent to marking the version with the `platform-only`
+tag. See the docs for `platform-only` for more information.
+
+## Tags
+
+Comments on the same line as a version definition or a symbol name are
+interpreted by the stub generator. Multiple space-delimited tags may be used on
+the same line. The supported tags are:
+
+### apex
+
+Indicates that the version or symbol is to be exposed in the APEX stubs rather
+than the NDK. May be used in combination with `llndk` if the symbol is exposed
+to both APEX and the LL-NDK.
+
+### future
+
+Indicates that the version or symbol is first introduced in the "future" API
+level. This is an abitrarily high API level used to define APIs that have not
+yet been added to a specific release.
+
+### introduced
+
+Indicates the version in which an API was first introduced. For example,
+`introduced=21` specifies that the API was first added (or first made public) in
+API level 21. This tag can be applied to either a version definition or an
+individual symbol. If applied to a version, all symbols contained in the version
+will have the tag applied. An `introduced` tag on a symbol overrides the value
+set for the version, if both are defined.
+
+Note: The map file alone does not contain all the information needed to
+determine which API level an API was added in. The `first_version` property of
+`ndk_library` will dictate which API levels stubs are generated for. If the
+module sets `first_version: "21"`, no symbols were introduced before API 21.
+
+Codenames can (and typically should) be used when defining new APIs. This allows
+the actual number of the API level to remain vague during development of that
+release. For example, `introduced=S` can be used to define APIs added in S. Any
+code name known to the build system can be used. For a list of versions known to
+the build system, see `out/soong/api_levels.json` (if not present, run `m
+out/soong/api_levels.json` to generate it).
+
+Architecture-specific variants of this tag exist:
+
+* `introduced-arm=VERSION`
+* `introduced-arm64=VERSION`
+* `introduced-x86=VERSION`
+* `introduced-x86_64=VERSION`
+
+The architecture-specific tag will take precedence over the architecture-generic
+tag when generating stubs for that architecture if both are present. If the
+symbol is defined with only architecture-specific tags, it will not be present
+for architectures that are not named.
+
+Note: The architecture-specific tags should, in general, not be used. These are
+primarily needed for APIs that were wrongly inconsistently exposed by libc/libm
+in old versions of Android before the stubs were well maintained. Think hard
+before using an architecture-specific tag for a new API.
+
+### llndk
+
+Indicates that the version or symbol is to be exposed in the LL-NDK stubs rather
+than the NDK. May be used in combination with `apex` if the symbol is exposed to
+both APEX and the LL-NDK.
+
+### platform-only
+
+Indicates that the version or symbol is public in the implementation library but
+should not be exposed in the stub library. Developers can still access them via
+`dlsym`, but they will not be exposed in the stubs so it should at least be
+clear to the developer that they are up to no good.
+
+The typical use for this tag is for exposing an API to the platform that is not
+for use by the NDK, LL-NDK, or APEX. It is preferable to keep such APIs in an
+entirely separate library to protect them from access via `dlsym`, but this is
+not always possible.
+
+### var
+
+Used to define a public global variable. By default all symbols are exposed as
+functions. In the uncommon situation of exposing a global variable, the `var`
+tag may be used.
+
+### versioned=VERSION
+
+Behaves similarly to `introduced` but defines the first version that the stub
+library should apply symbol versioning. For example:
+
+```txt
+R { # introduced=R
+ global:
+ foo;
+ bar; # versioned=S
+ local:
+ *;
+};
+```
+
+The stub library for R will contain symbols for both `foo` and `bar`, but only
+`foo` will include a versioned symbol `foo@R`. The stub library for S will
+contain both symbols, as well as the versioned symbols `foo@R` and `bar@R`.
+
+This tag is not commonly needed and is only used to hide symbol versioning
+mistakes that shipped as part of the platform.
+
+Note: Like `introduced`, the map file does not tell the whole story. The
+`ndk_library` Soong module may define a `unversioned_until` property that sets
+the default for the entire map file.
+
+### weak
+
+Indicates that the symbol should be [weak] in the stub library.
+
+[weak]: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
diff --git a/java/androidmk.go b/java/androidmk.go
index 6f24f34..2c29192 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -626,6 +626,11 @@
}
func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
+ if !a.IsForPlatform() {
+ // The non-platform variant is placed inside APEX. No reason to
+ // make it available to Make.
+ return nil
+ }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "APPS",
OutputFile: android.OptionalPathForPath(a.outputFile),
diff --git a/java/app.go b/java/app.go
index 0c94e23..2fd397a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -459,16 +459,20 @@
return false
}
- path := child.(android.Module).NoticeFile()
- if path.Valid() {
- noticePathSet[path.Path()] = true
+ paths := child.(android.Module).NoticeFiles()
+ if len(paths) > 0 {
+ for _, path := range paths {
+ noticePathSet[path] = true
+ }
}
return true
})
// If the app has one, add it too.
- if a.NoticeFile().Valid() {
- noticePathSet[a.NoticeFile().Path()] = true
+ if len(a.NoticeFiles()) > 0 {
+ for _, path := range a.NoticeFiles() {
+ noticePathSet[path] = true
+ }
}
if len(noticePathSet) == 0 {
@@ -759,6 +763,7 @@
}
type appTestProperties struct {
+ // The name of the android_app module that the tests will run against.
Instrumentation_for *string
// if specified, the instrumentation target package name in the manifest is overwritten by it.
@@ -1018,6 +1023,7 @@
type AndroidAppImport struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.ApexModuleBase
prebuilt android.Prebuilt
properties AndroidAppImportProperties
@@ -1255,7 +1261,9 @@
// TODO: Optionally compress the output apk.
- a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ if a.IsForPlatform() {
+ a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ }
// TODO: androidmk converter jni libs
}
@@ -1306,6 +1314,13 @@
return Bool(a.properties.Privileged)
}
+func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ // android_app_import might have extra dependencies via uses_libs property.
+ // Don't track the dependency as we don't automatically add those libraries
+ // to the classpath. It should be explicitly added to java_libs property of APEX
+ return false
+}
+
func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
@@ -1352,6 +1367,7 @@
module.processVariants(ctx)
})
+ android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
@@ -1389,6 +1405,7 @@
module.processVariants(ctx)
})
+ android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
@@ -1441,6 +1458,15 @@
Overrides []string
}
+// RuntimeResourceOverlayModule interface is used by the apex package to gather information from
+// a RuntimeResourceOverlay module.
+type RuntimeResourceOverlayModule interface {
+ android.Module
+ OutputFile() android.Path
+ Certificate() Certificate
+ Theme() string
+}
+
func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
sdkDep := decodeSdkDep(ctx, sdkContext(r))
if sdkDep.hasFrameworkLibs() {
@@ -1507,6 +1533,18 @@
return r.sdkVersion()
}
+func (r *RuntimeResourceOverlay) Certificate() Certificate {
+ return r.certificate
+}
+
+func (r *RuntimeResourceOverlay) OutputFile() android.Path {
+ return r.outputFile
+}
+
+func (r *RuntimeResourceOverlay) Theme() string {
+ return String(r.properties.Theme)
+}
+
// runtime_resource_overlay generates a resource-only apk file that can overlay application and
// system resources at run time.
func RuntimeResourceOverlayFactory() android.Module {
diff --git a/java/builder.go b/java/builder.go
index ad9afee..3a4a10d 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -38,12 +39,13 @@
// this, all java rules write into separate directories and then are combined into a .jar file
// (if the rule produces .class files) or a .srcjar file (if the rule produces .java files).
// .srcjar files are unzipped into a temporary directory when compiled with javac.
- javac = pctx.AndroidRemoteStaticRule("javac", android.RemoteRuleSupports{Goma: true, RBE: true, RBEFlag: android.RBE_JAVAC},
+ // TODO(b/143658984): goma can't handle the --system argument to javac.
+ javac, javacRE = remoteexec.StaticRules(pctx, "javac",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
- `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ` +
+ `${config.SoongJavacWrapper} $reTemplate${config.JavacCmd} ` +
`${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
@@ -58,9 +60,12 @@
CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
Rspfile: "$out.rsp",
RspfileContent: "$in",
- },
- "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
- "outDir", "annoDir", "javaVersion")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
+ "outDir", "annoDir", "javaVersion"}, nil)
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
@@ -187,6 +192,7 @@
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
+ pctx.Import("android/soong/remoteexec")
}
type javaBuilderFlags struct {
@@ -397,8 +403,12 @@
outDir = filepath.Join(shardDir, outDir)
annoDir = filepath.Join(shardDir, annoDir)
}
+ rule := javac
+ if ctx.Config().IsEnvTrue("RBE_JAVAC") {
+ rule = javacRE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: javac,
+ Rule: rule,
Description: desc,
Output: outputFile,
Inputs: srcFiles,
diff --git a/java/config/config.go b/java/config/config.go
index 487dc04..ceec9a8 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -22,6 +22,7 @@
_ "github.com/google/blueprint/bootstrap"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -139,30 +140,16 @@
pctx.HostJavaToolVariable("MetalavaJar", "metalava.jar")
pctx.HostJavaToolVariable("DokkaJar", "dokka.jar")
pctx.HostJavaToolVariable("JetifierJar", "jetifier.jar")
+ pctx.HostJavaToolVariable("R8Jar", "r8-compat-proguard.jar")
+ pctx.HostJavaToolVariable("D8Jar", "d8.jar")
pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen")
- pctx.VariableFunc("JavacWrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("JAVAC_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
-
- pctx.VariableFunc("R8Wrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("R8_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
-
- pctx.VariableFunc("D8Wrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("D8_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
+ pctx.VariableFunc("REJavaPool", remoteexec.EnvOverrideFunc("RBE_JAVA_POOL", "java16"))
+ pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar")
diff --git a/java/dex.go b/java/dex.go
index 6afdb6d..27ec6ee 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -20,12 +20,13 @@
"github.com/google/blueprint"
"android/soong/android"
+ "android/soong/remoteexec"
)
-var d8 = pctx.AndroidRemoteStaticRule("d8", android.RemoteRuleSupports{RBE: true, RBEFlag: android.RBE_D8},
+var d8, d8RE = remoteexec.StaticRules(pctx, "d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.D8Wrapper}${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
+ `$reTemplate${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
`${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
@@ -33,14 +34,19 @@
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
- },
- "outDir", "d8Flags", "zipFlags")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "d8"},
+ Inputs: []string{"${config.D8Jar}"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"outDir", "d8Flags", "zipFlags"}, nil)
-var r8 = pctx.AndroidRemoteStaticRule("r8", android.RemoteRuleSupports{RBE: true, RBEFlag: android.RBE_R8},
+var r8, r8RE = remoteexec.StaticRules(pctx, "r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && ` +
- `${config.R8Wrapper}${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
+ `$reTemplate${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
`--force-proguard-compatibility ` +
`--no-data-resources ` +
`-printmapping $outDict ` +
@@ -53,8 +59,13 @@
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
- },
- "outDir", "outDict", "r8Flags", "zipFlags")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "r8"},
+ Inputs: []string{"$implicits", "${config.R8Jar}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"})
func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
flags := j.deviceProperties.Dxflags
@@ -185,24 +196,34 @@
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
j.proguardDictionary = proguardDictionary
r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ rule := r8
+ args := map[string]string{
+ "r8Flags": strings.Join(r8Flags, " "),
+ "zipFlags": zipFlags,
+ "outDict": j.proguardDictionary.String(),
+ "outDir": outDir.String(),
+ }
+ if ctx.Config().IsEnvTrue("RBE_R8") {
+ rule = r8RE
+ args["implicits"] = strings.Join(r8Deps.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: r8,
+ Rule: rule,
Description: "r8",
Output: javalibJar,
ImplicitOutput: proguardDictionary,
Input: classesJar,
Implicits: r8Deps,
- Args: map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
- "zipFlags": zipFlags,
- "outDict": j.proguardDictionary.String(),
- "outDir": outDir.String(),
- },
+ Args: args,
})
} else {
d8Flags, d8Deps := j.d8Flags(ctx, flags)
+ rule := d8
+ if ctx.Config().IsEnvTrue("RBE_D8") {
+ rule = d8RE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: d8,
+ Rule: rule,
Description: "d8",
Output: javalibJar,
Input: classesJar,
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 28a2c8a..4725b07 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -131,7 +131,8 @@
global := dexpreopt.GetGlobalConfig(ctx)
bootImage := defaultBootImageConfig(ctx)
dexFiles := bootImage.dexPathsDeps.Paths()
- dexLocations := bootImage.dexLocationsDeps
+ // The dex locations for all Android variants are identical.
+ dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
if global.UseArtImage {
bootImage = artBootImageConfig(ctx)
}
@@ -159,6 +160,8 @@
images = append(images, variant.images)
imagesDeps = append(imagesDeps, variant.imagesDeps)
}
+ // The image locations for all Android variants are identical.
+ imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
@@ -202,7 +205,7 @@
Archs: archs,
DexPreoptImages: images,
DexPreoptImagesDeps: imagesDeps,
- DexPreoptImageLocations: bootImage.imageLocations,
+ DexPreoptImageLocations: imageLocations,
PreoptBootClassPathDexFiles: dexFiles,
PreoptBootClassPathDexLocations: dexLocations,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 1b26667..c3825cb 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -29,29 +29,10 @@
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
-// The image "location" is a symbolic path that with multiarchitecture
-// support doesn't really exist on the device. Typically it is
-// /system/framework/boot.art and should be the same for all supported
-// architectures on the device. The concrete architecture specific
-// content actually ends up in a "filename" that contains an
-// architecture specific directory name such as arm, arm64, mips,
-// mips64, x86, x86_64.
-//
-// Here are some example values for an x86_64 / x86 configuration:
-//
-// bootImages["x86_64"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art"
-// dexpreopt.PathToLocation(bootImages["x86_64"], "x86_64") = "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art"
-//
-// bootImages["x86"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86/boot.art"
-// dexpreopt.PathToLocation(bootImages["x86"])= "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art"
-//
-// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools
-// will then reconstruct the real path, so the rules must have a dependency on the real path.
-
// Target-independent description of pre-compiled boot image.
type bootImageConfig struct {
- // Whether this image is an extension.
- extension bool
+ // If this image is an extension, the image that it extends.
+ extends *bootImageConfig
// Image name (used in directory names and ninja rule names).
name string
@@ -71,17 +52,10 @@
// The names of jars that constitute this image.
modules []string
- // The "locations" of jars.
- dexLocations []string // for this image
- dexLocationsDeps []string // for the dependency images and in this image
-
// File paths to jars.
dexPaths android.WritablePaths // for this image
dexPathsDeps android.WritablePaths // for the dependency images and in this image
- // The "locations" of the dependency images and in this image.
- imageLocations []string
-
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
@@ -99,6 +73,10 @@
// Target for which the image is generated.
target android.Target
+ // The "locations" of jars.
+ dexLocations []string // for this image
+ dexLocationsDeps []string // for the dependency images and in this image
+
// Paths to image files.
images android.OutputPath // first image file
imagesDeps android.OutputPaths // all files
@@ -121,13 +99,23 @@
return nil
}
+// Return any (the first) variant which is for the device (as opposed to for the host)
+func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant {
+ for _, variant := range image.variants {
+ if variant.target.Os == android.Android {
+ return variant
+ }
+ }
+ return nil
+}
+
func (image bootImageConfig) moduleName(idx int) string {
// Dexpreopt on the boot class path produces multiple files. The first dex file
// is converted into 'name'.art (to match the legacy assumption that 'name'.art
// exists), and the rest are converted to 'name'-<jar>.art.
m := image.modules[idx]
name := image.stem
- if idx != 0 || image.extension {
+ if idx != 0 || image.extends != nil {
name += "-" + stemOf(m)
}
return name
@@ -152,6 +140,24 @@
return ret
}
+// The image "location" is a symbolic path that, with multiarchitecture support, doesn't really
+// exist on the device. Typically it is /apex/com.android.art/javalib/boot.art and should be the
+// same for all supported architectures on the device. The concrete architecture specific files
+// actually end up in architecture-specific sub-directory such as arm, arm64, x86, or x86_64.
+//
+// For example a physical file
+// "/apex/com.android.art/javalib/x86/boot.art" has "image location"
+// "/apex/com.android.art/javalib/boot.art" (which is not an actual file).
+//
+// The location is passed as an argument to the ART tools like dex2oat instead of the real path.
+// ART tools will then reconstruct the architecture-specific real path.
+func (image *bootImageVariant) imageLocations() (imageLocations []string) {
+ if image.extends != nil {
+ imageLocations = image.extends.getVariant(image.target).imageLocations()
+ }
+ return append(imageLocations, dexpreopt.PathToLocation(image.images, image.target.Arch.ArchType))
+}
+
func concat(lists ...[]string) []string {
var size int
for _, l := range lists {
@@ -181,11 +187,6 @@
return true
}
- if len(ctx.Config().Targets[android.Android]) == 0 {
- // Host-only build
- return true
- }
-
return false
}
@@ -204,7 +205,10 @@
// Include dexpreopt files for the primary boot image.
files := map[android.ArchType]android.OutputPaths{}
for _, variant := range artBootImageConfig(ctx).variants {
- files[variant.target.Arch.ArchType] = variant.imagesDeps
+ // We also generate boot images for host (for testing), but we don't need those in the apex.
+ if variant.target.Os == android.Android {
+ files[variant.target.Arch.ArchType] = variant.imagesDeps
+ }
}
return files
}
@@ -264,27 +268,28 @@
// Check that this module satisfies constraints for a particular boot image.
apex, isApexModule := module.(android.ApexModule)
+ fromUpdatableApex := isApexModule && apex.Updatable()
if image.name == artBootImageName {
if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
- // ok, found the jar in the ART apex
- } else if isApexModule && !apex.IsForPlatform() {
- // this jar is part of an updatable apex other than ART, fail immediately
- ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
+ // ok: found the jar in the ART apex
} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
- // this is a special "hostdex" variant, skip it and resume search
+ // exception (skip and continue): special "hostdex" platform variant
return -1, nil
} else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- // this is Jacoco platform variant for a coverage build, skip it and resume search
+ // exception (skip and continue): Jacoco platform variant for a coverage build
return -1, nil
+ } else if fromUpdatableApex {
+ // error: this jar is part of an updatable apex other than ART
+ ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
} else {
- // this (installable) jar is part of the platform, fail immediately
- ctx.Errorf("module '%s' is part of the platform and not allowed in the ART boot image", name)
+ // error: this jar is part of the platform or a non-updatable apex
+ ctx.Errorf("module '%s' is not allowed in the ART boot image", name)
}
} else if image.name == frameworkBootImageName {
- if !isApexModule || apex.IsForPlatform() {
- // ok, this jar is part of the platform
+ if !fromUpdatableApex {
+ // ok: this jar is part of the platform or a non-updatable apex
} else {
- // this jar is part of an updatable apex, fail immediately
+ // error: this jar is part of an updatable apex
ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
}
} else {
@@ -362,9 +367,10 @@
global := dexpreopt.GetGlobalConfig(ctx)
arch := image.target.Arch.ArchType
- symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
+ os := image.target.Os.String() // We need to distinguish host-x86 and device-x86.
+ symbolsDir := image.symbolsDir.Join(ctx, os, image.installSubdir, arch.String())
symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
- outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
+ outputDir := image.dir.Join(ctx, os, image.installSubdir, arch.String())
outputPath := outputDir.Join(ctx, image.stem+".oat")
oatLocation := dexpreopt.PathToLocation(outputPath, arch)
imagePath := outputPath.ReplaceExtension(ctx, "art")
@@ -410,7 +416,7 @@
cmd.FlagWithInput("--dirty-image-objects=", global.DirtyImageObjects.Path())
}
- if image.extension {
+ if image.extends != nil {
artImage := image.primaryImages
cmd.
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
@@ -432,13 +438,18 @@
FlagWithArg("--oat-location=", oatLocation).
FlagWithArg("--image=", imagePath.String()).
FlagWithArg("--instruction-set=", arch.String()).
- FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
- FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
FlagWithArg("--android-root=", global.EmptyDirectory).
FlagWithArg("--no-inline-from=", "core-oj.jar").
Flag("--force-determinism").
Flag("--abort-on-hard-verifier-error")
+ // Use the default variant/features for host builds.
+ // The map below contains only device CPU info (which might be x86 on some devices).
+ if image.target.Os == android.Android {
+ cmd.FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch])
+ cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
+ }
+
if global.BootFlags != "" {
cmd.Flag(global.BootFlags)
}
@@ -450,7 +461,6 @@
cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
installDir := filepath.Join("/", image.installSubdir, arch.String())
- vdexInstallDir := filepath.Join("/", image.installSubdir)
var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls
@@ -469,11 +479,10 @@
cmd.ImplicitOutput(vdex)
zipFiles = append(zipFiles, vdex)
- // The vdex files are identical between architectures, install them to a shared location. The Make rules will
- // only use the install rules for one architecture, and will create symlinks into the architecture-specific
- // directories.
+ // Note that the vdex files are identical between architectures.
+ // Make rules will create symlinks to share them between architectures.
vdexInstalls = append(vdexInstalls,
- android.RuleBuilderInstall{vdex, filepath.Join(vdexInstallDir, vdex.Base())})
+ android.RuleBuilderInstall{vdex, filepath.Join(installDir, vdex.Base())})
}
for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") {
@@ -484,7 +493,7 @@
android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
}
- rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String())
+ rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
// save output and installed files for makevars
image.installs = rule.Installs()
@@ -534,7 +543,7 @@
Tool(globalSoong.Profman).
FlagWithInput("--create-profile-from=", bootImageProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.dexLocationsDeps).
+ FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.prof")
@@ -585,7 +594,7 @@
Flag("--generate-boot-profile").
FlagWithInput("--create-profile-from=", bootFrameworkProfile).
FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.dexLocationsDeps).
+ FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile)
rule.Install(profile, "/system/etc/boot-image.bprof")
@@ -657,27 +666,32 @@
var allPhonies android.Paths
for _, image := range image.variants {
arch := image.target.Arch.ArchType
+ suffix := arch.String()
+ // Host and target might both use x86 arch. We need to ensure the names are unique.
+ if image.target.Os.Class == android.Host {
+ suffix = "host-" + suffix
+ }
// Create a rule to call oatdump.
- output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
+ output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder()
rule.Command().
// TODO: for now, use the debug version for better error reporting
BuiltTool(ctx, "oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()).
+ FlagWithArg("--image=", strings.Join(image.imageLocations(), ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
- rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+ rule.Build(pctx, ctx, "dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
// Create a phony rule that depends on the output file and prints the path.
- phony := android.PathForPhony(ctx, "dump-oat-boot-"+arch.String())
+ phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
rule = android.NewRuleBuilder()
rule.Command().
Implicit(output).
ImplicitOutput(phony).
Text("echo").FlagWithArg("Output in ", output.String())
- rule.Build(pctx, ctx, "phony-dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
+ rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
allPhonies = append(allPhonies, phony)
}
@@ -715,21 +729,25 @@
if image != nil {
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPathsDeps.Strings(), " "))
- ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocationsDeps, " "))
+ ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.getAnyAndroidVariant().dexLocationsDeps, " "))
var imageNames []string
for _, current := range append(d.otherImages, image) {
imageNames = append(imageNames, current.name)
- for _, current := range current.variants {
- sfx := current.name + "_" + current.target.Arch.ArchType.String()
- ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String())
- ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String())
- ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " "))
- ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs.String())
- ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls.String())
+ for _, variant := range current.variants {
+ suffix := ""
+ if variant.target.Os.Class == android.Host {
+ suffix = "_host"
+ }
+ sfx := variant.name + suffix + "_" + variant.target.Arch.ArchType.String()
+ ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, variant.vdexInstalls.String())
+ ctx.Strict("DEXPREOPT_IMAGE_"+sfx, variant.images.String())
+ ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(variant.imagesDeps.Strings(), " "))
+ ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
+ ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
}
-
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":"))
+ imageLocations := current.getAnyAndroidVariant().imageLocations()
+ ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(imageLocations, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index e7b3c3b..127c201 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -62,7 +62,7 @@
bootArt := dexpreoptBootJars.Output("boot-foo.art")
expectedInputs := []string{
- "dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
+ "dex_artjars/android/apex/com.android.art/javalib/arm64/boot.art",
"dex_bootjars_input/foo.jar",
"dex_bootjars_input/bar.jar",
"dex_bootjars_input/baz.jar",
@@ -81,23 +81,23 @@
}
expectedOutputs := []string{
- "dex_bootjars/system/framework/arm64/boot.invocation",
+ "dex_bootjars/android/system/framework/arm64/boot.invocation",
- "dex_bootjars/system/framework/arm64/boot-foo.art",
- "dex_bootjars/system/framework/arm64/boot-bar.art",
- "dex_bootjars/system/framework/arm64/boot-baz.art",
+ "dex_bootjars/android/system/framework/arm64/boot-foo.art",
+ "dex_bootjars/android/system/framework/arm64/boot-bar.art",
+ "dex_bootjars/android/system/framework/arm64/boot-baz.art",
- "dex_bootjars/system/framework/arm64/boot-foo.oat",
- "dex_bootjars/system/framework/arm64/boot-bar.oat",
- "dex_bootjars/system/framework/arm64/boot-baz.oat",
+ "dex_bootjars/android/system/framework/arm64/boot-foo.oat",
+ "dex_bootjars/android/system/framework/arm64/boot-bar.oat",
+ "dex_bootjars/android/system/framework/arm64/boot-baz.oat",
- "dex_bootjars/system/framework/arm64/boot-foo.vdex",
- "dex_bootjars/system/framework/arm64/boot-bar.vdex",
- "dex_bootjars/system/framework/arm64/boot-baz.vdex",
+ "dex_bootjars/android/system/framework/arm64/boot-foo.vdex",
+ "dex_bootjars/android/system/framework/arm64/boot-bar.vdex",
+ "dex_bootjars/android/system/framework/arm64/boot-baz.vdex",
- "dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
- "dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
- "dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
+ "dex_bootjars_unstripped/android/system/framework/arm64/boot-foo.oat",
+ "dex_bootjars_unstripped/android/system/framework/arm64/boot-bar.oat",
+ "dex_bootjars_unstripped/android/system/framework/arm64/boot-baz.oat",
}
for i := range expectedOutputs {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index f8356d1..066694c 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -61,6 +61,10 @@
targets = append(targets, target)
}
}
+ // We may also need the images on host in order to run host-based tests.
+ for _, target := range ctx.Config().Targets[android.BuildOs] {
+ targets = append(targets, target)
+ }
return targets
}
@@ -75,6 +79,14 @@
return moduleName
}
+func getDexLocation(ctx android.PathContext, target android.Target, subdir string, name string) string {
+ if target.Os.Class == android.Host {
+ return filepath.Join(ctx.Config().Getenv("OUT_DIR"), "host", ctx.Config().PrebuiltOS(), subdir, name)
+ } else {
+ return filepath.Join("/", subdir, name)
+ }
+}
+
var (
bootImageConfigKey = android.NewOnceKey("bootImageConfig")
artBootImageName = "art"
@@ -100,36 +112,23 @@
artSubdir := "apex/com.android.art/javalib"
frameworkSubdir := "system/framework"
- var artLocations, frameworkLocations []string
- for _, m := range artModules {
- artLocations = append(artLocations, filepath.Join("/"+artSubdir, stemOf(m)+".jar"))
- }
- for _, m := range frameworkModules {
- frameworkLocations = append(frameworkLocations, filepath.Join("/"+frameworkSubdir, stemOf(m)+".jar"))
- }
-
// ART config for the primary boot image in the ART apex.
// It includes the Core Libraries.
artCfg := bootImageConfig{
- extension: false,
- name: artBootImageName,
- stem: "boot",
- installSubdir: artSubdir,
- modules: artModules,
- dexLocations: artLocations,
- dexLocationsDeps: artLocations,
+ name: artBootImageName,
+ stem: "boot",
+ installSubdir: artSubdir,
+ modules: artModules,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
- extension: true,
- name: frameworkBootImageName,
- stem: "boot",
- installSubdir: frameworkSubdir,
- modules: frameworkModules,
- dexLocations: frameworkLocations,
- dexLocationsDeps: append(artLocations, frameworkLocations...),
+ extends: &artCfg,
+ name: frameworkBootImageName,
+ stem: "boot",
+ installSubdir: frameworkSubdir,
+ modules: frameworkModules,
}
configs := map[string]*bootImageConfig{
@@ -145,8 +144,6 @@
// expands to <stem>.art for primary image and <stem>-<1st module>.art for extension
imageName := c.firstModuleNameOrStem() + ".art"
- c.imageLocations = []string{c.dir.Join(ctx, c.installSubdir, imageName).String()}
-
// The path to bootclasspath dex files needs to be known at module
// GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled.
// Set up known paths for them, the singleton rules will copy them there.
@@ -160,13 +157,17 @@
// Create target-specific variants.
for _, target := range targets {
arch := target.Arch.ArchType
- imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
+ imageDir := c.dir.Join(ctx, target.Os.String(), c.installSubdir, arch.String())
variant := &bootImageVariant{
bootImageConfig: c,
target: target,
images: imageDir.Join(ctx, imageName),
imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
}
+ for _, m := range c.modules {
+ variant.dexLocations = append(variant.dexLocations, getDexLocation(ctx, target, c.installSubdir, stemOf(m)+".jar"))
+ }
+ variant.dexLocationsDeps = variant.dexLocations
c.variants = append(c.variants, variant)
}
@@ -177,8 +178,8 @@
frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
for i := range targets {
frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images
+ frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...)
}
- frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
return configs
}).(map[string]*bootImageConfig)
@@ -202,7 +203,7 @@
updatableBootclasspath[i] = dexpreopt.GetJarLocationFromApexJarPair(p)
}
- bootclasspath := append(copyOf(image.dexLocationsDeps), updatableBootclasspath...)
+ bootclasspath := append(copyOf(image.getAnyAndroidVariant().dexLocationsDeps), updatableBootclasspath...)
return bootclasspath
})
}
@@ -217,7 +218,7 @@
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
- ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).dexLocationsDeps, ":"))
+ ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":"))
ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules, ":"))
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 1e950c1..eba7766 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -331,10 +331,18 @@
apiToCheck.Removed_api_file = nil
}
+// Used by xsd_config
type ApiFilePath interface {
ApiFilePath() android.Path
}
+// Provider of information about API stubs, used by java_sdk_library.
+type ApiStubsProvider interface {
+ ApiFilePath
+ RemovedApiFilePath() android.Path
+ StubsSrcJar() android.Path
+}
+
//
// Javadoc
//
@@ -1180,6 +1188,14 @@
return d.apiFilePath
}
+func (d *Droidstubs) RemovedApiFilePath() android.Path {
+ return d.removedApiFile
+}
+
+func (d *Droidstubs) StubsSrcJar() android.Path {
+ return d.stubsSrcJar
+}
+
func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
diff --git a/java/java.go b/java/java.go
index 5d77807..f6fe76e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2364,6 +2364,12 @@
// set the name of the output
Stem *string
+
+ Aidl struct {
+ // directories that should be added as include directories for any aidl sources of modules
+ // that depend on this module, as well as to aidl for this module.
+ Export_include_dirs []string
+ }
}
type Import struct {
@@ -2377,6 +2383,7 @@
combinedClasspathFile android.Path
exportedSdkLibs []string
+ exportAidlIncludeDirs android.Paths
}
func (j *Import) sdkVersion() sdkSpec {
@@ -2450,6 +2457,8 @@
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
jarName, outputFile)
}
+
+ j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
}
var _ Dependency = (*Import)(nil)
@@ -2484,7 +2493,7 @@
}
func (j *Import) AidlIncludeDirs() android.Paths {
- return nil
+ return j.exportAidlIncludeDirs
}
func (j *Import) ExportedSdkLibs() []string {
diff --git a/java/java_test.go b/java/java_test.go
index 6d972be..e8a1a7c 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1491,3 +1491,27 @@
t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
}
}
+
+func TestAidlExportIncludeDirsFromImports(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["aidl/foo/IFoo.aidl"],
+ libs: ["bar"],
+ }
+
+ java_import {
+ name: "bar",
+ jars: ["a.jar"],
+ aidl: {
+ export_include_dirs: ["aidl/bar"],
+ },
+ }
+ `)
+
+ aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ expectedAidlFlag := "-Iaidl/bar"
+ if !strings.Contains(aidlCommand, expectedAidlFlag) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+ }
+}
diff --git a/java/sdk.go b/java/sdk.go
index be5e512..65c0904 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -304,6 +304,28 @@
}
}
+func (s sdkSpec) validateSystemSdk(ctx android.EarlyModuleContext) bool {
+ // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
+ // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
+ // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
+ if s.kind != sdkSystem || !s.version.isNumbered() {
+ return true
+ }
+ allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
+ if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
+ systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
+ if len(systemSdkVersions) > 0 {
+ allowedVersions = systemSdkVersions
+ }
+ }
+ if len(allowedVersions) > 0 && !android.InList(s.version.String(), allowedVersions) {
+ ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
+ s.raw, allowedVersions)
+ return false
+ }
+ return true
+}
+
func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep {
sdkVersion := sdkContext.sdkVersion()
if !sdkVersion.valid() {
@@ -314,6 +336,9 @@
if ctx.Config().IsPdkBuild() {
sdkVersion = sdkVersion.forPdkBuild(ctx)
}
+ if !sdkVersion.validateSystemSdk(ctx) {
+ return sdkDep{}
+ }
if sdkVersion.usePrebuilt(ctx) {
dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), sdkVersion.kind.String())
@@ -361,21 +386,6 @@
}
}
- // Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
- // or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
- if sdkVersion.kind == sdkSystem && sdkVersion.version.isNumbered() {
- allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
- if ctx.DeviceSpecific() || ctx.SocSpecific() {
- if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
- allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
- }
- }
- if len(allowed_versions) > 0 && !android.InList(sdkVersion.version.String(), allowed_versions) {
- ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
- sdkVersion.raw, allowed_versions)
- }
- }
-
switch sdkVersion.kind {
case sdkPrivate:
return sdkDep{
diff --git a/java/sdk_library.go b/java/sdk_library.go
index fa26795..9e3ad5b 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -231,9 +231,11 @@
}
type scopePaths struct {
- stubsHeaderPath android.Paths
- stubsImplPath android.Paths
- apiFilePath android.Path
+ stubsHeaderPath android.Paths
+ stubsImplPath android.Paths
+ currentApiFilePath android.Path
+ removedApiFilePath android.Path
+ stubsSrcJar android.Path
}
// Common code between sdk library and sdk library import
@@ -320,11 +322,13 @@
scopePaths.stubsImplPath = lib.ImplementationJars()
}
}
- if doc, ok := to.(ApiFilePath); ok {
+ if doc, ok := to.(ApiStubsProvider); ok {
if scopeTag, ok := tag.(scopeDependencyTag); ok {
apiScope := scopeTag.apiScope
scopePaths := module.getScopePaths(apiScope)
- scopePaths.apiFilePath = doc.ApiFilePath()
+ scopePaths.currentApiFilePath = doc.ApiFilePath()
+ scopePaths.removedApiFilePath = doc.RemovedApiFilePath()
+ scopePaths.stubsSrcJar = doc.StubsSrcJar()
} else {
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
}
@@ -805,6 +809,15 @@
// List of shared java libs that this module has dependencies to
Libs []string
+
+ // The stub sources.
+ Stub_srcs []string `android:"path"`
+
+ // The current.txt
+ Current_api string `android:"path"`
+
+ // The removed.txt
+ Removed_api string `android:"path"`
}
type sdkLibraryImportProperties struct {
@@ -906,6 +919,8 @@
}
module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
+
+ module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
}
javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -950,6 +965,16 @@
mctx.CreateModule(ImportFactory, &props)
}
+func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.LoadHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ props := struct {
+ Name *string
+ Srcs []string
+ }{}
+ props.Name = proptools.StringPtr(apiScope.docsModuleName(module.BaseModuleName()))
+ props.Srcs = scopeProperties.Stub_srcs
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
+}
+
func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
for apiScope, scopeProperties := range module.scopeProperties {
if len(scopeProperties.Jars) == 0 {
@@ -1148,11 +1173,17 @@
// Additional libraries that the exported stubs libraries depend upon.
Libs []string
+
+ // The Java stubs source files.
+ Stub_srcs []string
}
type scopeProperties struct {
- Jars android.Paths
- SdkVersion string
+ Jars android.Paths
+ StubsSrcJar android.Path
+ CurrentApiFile android.Path
+ RemovedApiFile android.Path
+ SdkVersion string
}
func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -1166,6 +1197,9 @@
properties := scopeProperties{}
properties.Jars = jars
properties.SdkVersion = apiScope.sdkVersion
+ properties.StubsSrcJar = paths.stubsSrcJar
+ properties.CurrentApiFile = paths.currentApiFilePath
+ properties.RemovedApiFile = paths.removedApiFilePath
s.Scopes[apiScope] = properties
}
}
@@ -1178,14 +1212,34 @@
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.name)
+ scopeDir := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name)
+
var jars []string
for _, p := range properties.Jars {
- dest := filepath.Join("sdk_library", s.OsPrefix(), apiScope.name, ctx.Name()+"-stubs.jar")
+ dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar")
ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
jars = append(jars, dest)
}
scopeSet.AddProperty("jars", jars)
+ // Merge the stubs source jar into the snapshot zip so that when it is unpacked
+ // the source files are also unpacked.
+ snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
+ ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
+ scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
+
+ if properties.CurrentApiFile != nil {
+ currentApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".txt")
+ ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
+ scopeSet.AddProperty("current_api", currentApiSnapshotPath)
+ }
+
+ if properties.RemovedApiFile != nil {
+ removedApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"-removed.txt")
+ ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, removedApiSnapshotPath)
+ scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
+ }
+
if properties.SdkVersion != "" {
scopeSet.AddProperty("sdk_version", properties.SdkVersion)
}
diff --git a/java/testing.go b/java/testing.go
index 28c1a26..6929bb7 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -50,6 +50,8 @@
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
"framework/aidl/a.aidl": nil,
+ "aidl/foo/IFoo.aidl": nil,
+ "aidl/bar/IBar.aidl": nil,
"assets_a/a": nil,
"assets_b/b": nil,
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index d43dc6c..860db55 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -148,8 +148,20 @@
// locally executable rule and the second rule is a remotely executable rule.
func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
ruleParamsRE := ruleParams
- ruleParamsRE.Command = reParams.Template() + ruleParamsRE.Command
+ ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
+ ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
}
+
+// EnvOverrideFunc retrieves a variable func that evaluates to the value of the given environment
+// variable if set, otherwise the given default.
+func EnvOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string {
+ return func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv(envVar); override != "" {
+ return override
+ }
+ return defaultVal
+ }
+}
diff --git a/rust/builder.go b/rust/builder.go
index 27eeec2..2d5e602 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -108,8 +108,8 @@
}
// TODO once we have static libraries in the host prebuilt .bp, this
// should be unconditionally added.
- if !ctx.Host() {
- // If we're on a device build, do not use an implicit sysroot
+ if !(ctx.Host() && ctx.TargetPrimary()) {
+ // If we're not targeting the host primary arch, do not use an implicit sysroot
rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
}
// Collect linker flags
diff --git a/rust/compiler.go b/rust/compiler.go
index 4593165..7499776 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -183,8 +183,8 @@
if !Bool(compiler.Properties.No_stdlibs) {
for _, stdlib := range config.Stdlibs {
- // If we're building for host, use the compiler's stdlibs
- if ctx.Host() {
+ // If we're building for the primary host target, use the compiler's stdlibs
+ if ctx.Host() && ctx.TargetPrimary() {
stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
}
@@ -192,9 +192,12 @@
// static linking is the default, if one of our static
// dependencies uses a dynamic library, we need to dynamically
// link the stdlib as well.
- if (len(deps.Dylibs) > 0) || (!ctx.Host()) {
+ if (len(deps.Dylibs) > 0) || ctx.Device() {
// Dynamically linked stdlib
deps.Dylibs = append(deps.Dylibs, stdlib)
+ } else if ctx.Host() && !ctx.TargetPrimary() {
+ // Otherwise use the static in-tree stdlib for host secondary arch
+ deps.Rlibs = append(deps.Rlibs, stdlib+".static")
}
}
}
@@ -222,7 +225,10 @@
if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
dir = compiler.dir64
}
- if !ctx.Host() || ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
+ }
+ if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
return android.PathForModuleInstall(ctx, dir, compiler.subDir,
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index bbf9f8d..bcde757 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -74,3 +74,33 @@
host_supported: true,
}`)
}
+
+func TestInstallDir(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_dylib {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }
+ rust_binary {
+ name: "fizzbuzz",
+ srcs: ["foo.rs"],
+ }`)
+
+ install_path_lib64 := ctx.ModuleForTests("libfoo",
+ "android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
+ install_path_lib32 := ctx.ModuleForTests("libfoo",
+ "android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
+ install_path_bin := ctx.ModuleForTests("fizzbuzz",
+ "android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String()
+
+ if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") {
+ t.Fatalf("unexpected install path for 64-bit library: %#v", install_path_lib64)
+ }
+ if !strings.HasSuffix(install_path_lib32, "system/lib/libfoo.dylib.so") {
+ t.Fatalf("unexpected install path for 32-bit library: %#v", install_path_lib32)
+ }
+ if !strings.HasSuffix(install_path_bin, "system/bin/fizzbuzz") {
+ t.Fatalf("unexpected install path for binary: %#v", install_path_bin)
+ }
+}
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 60796d8..180fd8b 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -27,7 +27,6 @@
"-Wl,--icf=safe",
"-Wl,-z,max-page-size=4096",
- "-Wl,--execute-only",
"-Wl,-z,separate-code",
}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
index aedb42b..ac2580b 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -50,7 +50,7 @@
}
type toolchainArm struct {
- toolchain64Bit
+ toolchain32Bit
toolchainRustFlags string
}
diff --git a/rust/config/global.go b/rust/config/global.go
index 690d83e..c0bd0f2 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.40.0"
+ RustDefaultVersion = "1.42.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/rust/library.go b/rust/library.go
index 0cf2dd0..87e816d 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -281,7 +281,7 @@
}
func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
- module := newModule(hod, android.MultilibFirst)
+ module := newModule(hod, android.MultilibBoth)
library := &libraryDecorator{
MutatedProperties: LibraryMutatedProperties{
@@ -318,6 +318,8 @@
if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
deps = library.baseCompiler.bionicDeps(ctx, deps)
+ deps.CrtBegin = "crtbegin_so"
+ deps.CrtEnd = "crtend_so"
}
return deps
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 020581d..32eddc1 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -215,25 +215,6 @@
srcs: ["foo.rs"],
crate_name: "bar",
}
- // Make a dummy libstd to let resolution go through
- rust_library_dylib {
- name: "libstd",
- crate_name: "std",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
- rust_library_dylib {
- name: "libterm",
- crate_name: "term",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
- rust_library_dylib {
- name: "libtest",
- crate_name: "test",
- srcs: ["foo.rs"],
- no_stdlibs: true,
- }
rust_proc_macro {
name: "libpm",
rlibs: ["libbar"],
@@ -259,7 +240,7 @@
rust_binary {
name: "fizz-buzz",
srcs: ["foo.rs"],
- no_stdlibs: true,
+ no_stdlibs: true,
}`)
module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
@@ -267,3 +248,16 @@
t.Errorf("no_stdlibs did not suppress dependency on libstd")
}
}
+
+// Test that libraries provide both 32-bit and 64-bit variants.
+func TestMultilib(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_rlib {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib")
+ _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib")
+}
diff --git a/rust/testing.go b/rust/testing.go
index f9adec8..aad4ffe 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -22,51 +22,11 @@
func GatherRequiredDepsForTest() string {
bp := `
rust_prebuilt_dylib {
- name: "libarena_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libfmt_macros_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libgraphviz_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libserialize_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
name: "libstd_x86_64-unknown-linux-gnu",
srcs: [""],
host_supported: true,
}
rust_prebuilt_dylib {
- name: "libsyntax_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libsyntax_ext_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libsyntax_pos_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
- name: "libterm_x86_64-unknown-linux-gnu",
- srcs: [""],
- host_supported: true,
- }
- rust_prebuilt_dylib {
name: "libtest_x86_64-unknown-linux-gnu",
srcs: [""],
host_supported: true,
@@ -81,6 +41,36 @@
nocrt: true,
system_shared_libs: [],
}
+ rust_library_dylib {
+ name: "libstd",
+ crate_name: "std",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ host_supported: true,
+ }
+ rust_library_rlib {
+ name: "libstd.static",
+ crate_name: "std",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ host_supported: true,
+ }
+ rust_library_dylib {
+ name: "libtest",
+ crate_name: "test",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ host_supported: true,
+
+ }
+ rust_library_rlib {
+ name: "libtest.static",
+ crate_name: "test",
+ srcs: ["foo.rs"],
+ no_stdlibs: true,
+ host_supported: true,
+ }
+
` + cc.GatherRequiredDepsForTest(android.NoOsType)
return bp
}
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 076b3f5..dd0966f 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -1 +1,3 @@
per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com
+per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
+per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index 7e3a82c..eef6149 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -50,6 +50,7 @@
mkdir -p ${SOONG_OUT}
SOONG_VARS=${SOONG_OUT}/soong.variables
+# We enable bionic linux builds as ART also needs prebuilts for it.
cat > ${SOONG_VARS}.new << EOF
{
"Platform_sdk_version": ${PLATFORM_SDK_VERSION},
@@ -58,6 +59,9 @@
"DeviceName": "generic_arm64",
"HostArch": "x86_64",
+ "HostSecondaryArch": "x86",
+ "CrossHost": "linux_bionic",
+ "CrossHostArch": "x86_64",
"Aml_abis": true,
"UseGoma": ${USE_GOMA}
@@ -72,4 +76,7 @@
mv ${SOONG_VARS}.new ${SOONG_VARS}
fi
-m --skip-make "$@"
+# We use force building LLVM components flag (even though we actually don't
+# compile them) because we don't have bionic host prebuilts
+# for them.
+FORCE_BUILD_LLVM_COMPONENTS=true m --skip-make "$@"
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
new file mode 100755
index 0000000..fc91c3d
--- /dev/null
+++ b/scripts/build-mainline-modules.sh
@@ -0,0 +1,64 @@
+#!/bin/bash -ex
+
+# Non exhaustive list of modules where we want prebuilts. More can be added as
+# needed.
+MAINLINE_MODULES=(
+ com.android.art.debug
+ com.android.art.release
+ com.android.art.testing
+ com.android.conscrypt
+ com.android.runtime
+ com.android.tzdata
+ com.android.i18n
+)
+
+# List of SDKs and module exports we know of.
+MODULES_SDK_AND_EXPORTS=(
+ art-module-sdk
+ art-module-test-exports
+ conscrypt-module-sdk
+ conscrypt-module-test-exports
+ conscrypt-module-host-exports
+)
+
+# We want to create apex modules for all supported architectures.
+PRODUCTS=(
+ aosp_arm
+ aosp_arm64
+ aosp_x86
+ aosp_x86_64
+)
+
+if [ ! -e "build/make/core/Makefile" ]; then
+ echo "$0 must be run from the top of the tree"
+ exit 1
+fi
+
+OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
+DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
+
+for product in "${PRODUCTS[@]}"; do
+ build/soong/soong_ui.bash --make-mode $@ \
+ TARGET_PRODUCT=${product} \
+ ${MAINLINE_MODULES[@]}
+
+ PRODUCT_OUT=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT=${product} get_build_var PRODUCT_OUT)
+ TARGET_ARCH=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT=${product} get_build_var TARGET_ARCH)
+ rm -rf ${DIST_DIR}/${TARGET_ARCH}/
+ mkdir -p ${DIST_DIR}/${TARGET_ARCH}/
+ for module in "${MAINLINE_MODULES[@]}"; do
+ cp ${PWD}/${PRODUCT_OUT}/system/apex/${module}.apex ${DIST_DIR}/${TARGET_ARCH}/
+ done
+done
+
+
+# Create multi-archs SDKs in a different out directory. The multi-arch script
+# uses soong directly and therefore needs its own directory that doesn't clash
+# with make.
+export OUT_DIR=${OUT_DIR}/aml/
+for sdk in "${MODULES_SDK_AND_EXPORTS[@]}"; do
+ build/soong/scripts/build-aml-prebuilts.sh ${sdk}
+done
+
+rm -rf ${DIST_DIR}/mainline-sdks
+cp -R ${OUT_DIR}/soong/mainline-sdks ${DIST_DIR}
diff --git a/scripts/build_broken_logs.go b/scripts/build_broken_logs.go
index 8021e55..82ba749 100644
--- a/scripts/build_broken_logs.go
+++ b/scripts/build_broken_logs.go
@@ -54,11 +54,13 @@
DefaultDeprecated
)
-var buildBrokenSettings = []struct {
+type Setting struct {
name string
behavior BuildBrokenBehavior
warnings []string
-}{
+}
+
+var buildBrokenSettings = []Setting{
{
name: "BUILD_BROKEN_DUP_RULES",
behavior: DefaultFalse,
@@ -68,6 +70,19 @@
name: "BUILD_BROKEN_USES_NETWORK",
behavior: DefaultDeprecated,
},
+ {
+ name: "BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
+ behavior: DefaultTrue,
+ warnings: []string{
+ "COPY_HEADERS has been deprecated",
+ "COPY_HEADERS is deprecated",
+ },
+ },
+}
+
+type Branch struct {
+ Settings []Setting
+ Logs []ProductLog
}
type ProductBranch struct {
@@ -82,35 +97,48 @@
}
type Log struct {
- BuildBroken []*bool
- HasBroken []bool
+ WarningModuleTypes []string
+ ErrorModuleTypes []string
+
+ BuildBroken map[string]*bool
+ HasBroken map[string]int
}
func Merge(l, l2 Log) Log {
- if len(l.BuildBroken) == 0 {
- l.BuildBroken = make([]*bool, len(buildBrokenSettings))
+ if l.BuildBroken == nil {
+ l.BuildBroken = map[string]*bool{}
}
- if len(l.HasBroken) == 0 {
- l.HasBroken = make([]bool, len(buildBrokenSettings))
+ if l.HasBroken == nil {
+ l.HasBroken = map[string]int{}
}
- if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) {
- panic("mis-matched logs")
- }
-
- for i, v := range l.BuildBroken {
+ for n, v := range l.BuildBroken {
if v == nil {
- l.BuildBroken[i] = l2.BuildBroken[i]
+ l.BuildBroken[n] = l2.BuildBroken[n]
}
}
- for i := range l.HasBroken {
- l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i]
+ for n, v := range l2.BuildBroken {
+ if _, ok := l.BuildBroken[n]; !ok {
+ l.BuildBroken[n] = v
+ }
+ }
+
+ for n := range l.HasBroken {
+ if l.HasBroken[n] < l2.HasBroken[n] {
+ l.HasBroken[n] = l2.HasBroken[n]
+ }
+ }
+ for n := range l2.HasBroken {
+ if _, ok := l.HasBroken[n]; !ok {
+ l.HasBroken[n] = l2.HasBroken[n]
+ }
}
return l
}
-func PrintResults(products []ProductLog) {
+func PrintResults(branch Branch) {
+ products := branch.Logs
devices := map[string]Log{}
deviceNames := []string{}
@@ -124,39 +152,48 @@
sort.Strings(deviceNames)
- for i, setting := range buildBrokenSettings {
+ for _, setting := range branch.Settings {
printed := false
+ n := setting.name
for _, device := range deviceNames {
log := devices[device]
if setting.behavior == DefaultTrue {
- if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false {
- if log.HasBroken[i] {
+ if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false {
+ if log.HasBroken[n] > 0 {
printed = true
- fmt.Printf(" %s needs to set %s := true\n", device, setting.name)
+ plural := ""
+ if log.HasBroken[n] > 1 {
+ plural = "s"
+ }
+ fmt.Printf(" %s needs to set %s := true (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural)
}
- } else if !log.HasBroken[i] {
+ } else if log.HasBroken[n] == 0 {
printed = true
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
}
} else if setting.behavior == DefaultFalse {
- if log.BuildBroken[i] == nil {
+ if log.BuildBroken[n] == nil {
// Nothing to be done
- } else if *log.BuildBroken[i] == false {
+ } else if *log.BuildBroken[n] == false {
printed = true
fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name)
- } else if !log.HasBroken[i] {
+ } else if log.HasBroken[n] == 0 {
printed = true
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
}
} else if setting.behavior == DefaultDeprecated {
- if log.BuildBroken[i] != nil {
+ if log.BuildBroken[n] != nil {
printed = true
- if log.HasBroken[i] {
- fmt.Printf(" %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i])
+ if log.HasBroken[n] > 0 {
+ plural := ""
+ if log.HasBroken[n] > 1 {
+ plural = "s"
+ }
+ fmt.Printf(" %s sets %s := %v, which is deprecated, but has %d failure%s\n", device, setting.name, *log.BuildBroken[n], log.HasBroken[n], plural)
} else {
- fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i])
+ fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n])
}
}
}
@@ -168,17 +205,45 @@
}
}
-func ParseBranch(name string) []ProductLog {
+func ParseBranch(name string) Branch {
products, err := filepath.Glob(filepath.Join(name, "*"))
if err != nil {
log.Fatal(err)
}
- ret := []ProductLog{}
+ ret := Branch{Logs: []ProductLog{}}
for _, product := range products {
product = filepath.Base(product)
- ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product}))
+ ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product}))
+ }
+
+ ret.Settings = append(ret.Settings, buildBrokenSettings...)
+ if len(ret.Logs) > 0 {
+ for _, mtype := range ret.Logs[0].WarningModuleTypes {
+ if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
+ continue
+ }
+ ret.Settings = append(ret.Settings, Setting{
+ name: "BUILD_BROKEN_USES_" + mtype,
+ behavior: DefaultTrue,
+ warnings: []string{mtype + " has been deprecated"},
+ })
+ }
+ for _, mtype := range ret.Logs[0].ErrorModuleTypes {
+ if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
+ continue
+ }
+ ret.Settings = append(ret.Settings, Setting{
+ name: "BUILD_BROKEN_USES_" + mtype,
+ behavior: DefaultFalse,
+ warnings: []string{mtype + " has been deprecated"},
+ })
+ }
+ }
+
+ for _, productLog := range ret.Logs {
+ ScanProduct(ret.Settings, productLog)
}
return ret
}
@@ -192,15 +257,15 @@
ret := ProductLog{
ProductBranch: p,
Log: Log{
- BuildBroken: make([]*bool, len(buildBrokenSettings)),
- HasBroken: make([]bool, len(buildBrokenSettings)),
+ BuildBroken: map[string]*bool{},
+ HasBroken: map[string]int{},
},
}
lines := strings.Split(string(soongLog), "\n")
for _, line := range lines {
fields := strings.Split(line, " ")
- if len(fields) != 5 {
+ if len(fields) < 5 {
continue
}
@@ -208,30 +273,35 @@
ret.Device = fields[4]
}
+ if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" {
+ ret.WarningModuleTypes = fields[4:]
+ }
+ if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" {
+ ret.ErrorModuleTypes = fields[4:]
+ }
+
if strings.HasPrefix(fields[3], "BUILD_BROKEN_") {
- for i, setting := range buildBrokenSettings {
- if setting.name == fields[3] {
- ret.BuildBroken[i] = ParseBoolPtr(fields[4])
- }
- }
+ ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4])
}
}
- stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log"))
+ return ret
+}
+
+func ScanProduct(settings []Setting, l ProductLog) {
+ stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log"))
if err != nil {
log.Fatal(err)
}
stdStr := string(stdLog)
- for i, setting := range buildBrokenSettings {
+ for _, setting := range settings {
for _, warning := range setting.warnings {
if strings.Contains(stdStr, warning) {
- ret.HasBroken[i] = true
+ l.HasBroken[setting.name] += strings.Count(stdStr, warning)
}
}
}
-
- return ret
}
func ParseBoolPtr(str string) *bool {
diff --git a/scripts/generate-notice-files.py b/scripts/generate-notice-files.py
new file mode 100755
index 0000000..49011b2
--- /dev/null
+++ b/scripts/generate-notice-files.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2012 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.
+"""
+Usage: generate-notice-files --text-output [plain text output file] \
+ --html-output [html output file] \
+ --xml-output [xml output file] \
+ -t [file title] -s [directory of notices]
+
+Generate the Android notice files, including both text and html files.
+
+-h to display this usage message and exit.
+"""
+from collections import defaultdict
+import argparse
+import hashlib
+import itertools
+import os
+import os.path
+import re
+import sys
+
+MD5_BLOCKSIZE = 1024 * 1024
+HTML_ESCAPE_TABLE = {
+ "&": "&",
+ '"': """,
+ "'": "'",
+ ">": ">",
+ "<": "<",
+ }
+
+def hexify(s):
+ return ("%02x"*len(s)) % tuple(map(ord, s))
+
+def md5sum(filename):
+ """Calculate an MD5 of the file given by FILENAME,
+ and return hex digest as a string.
+ Output should be compatible with md5sum command"""
+
+ f = open(filename, "rb")
+ sum = hashlib.md5()
+ while 1:
+ block = f.read(MD5_BLOCKSIZE)
+ if not block:
+ break
+ sum.update(block)
+ f.close()
+ return hexify(sum.digest())
+
+
+def html_escape(text):
+ """Produce entities within text."""
+ return "".join(HTML_ESCAPE_TABLE.get(c,c) for c in text)
+
+HTML_OUTPUT_CSS="""
+<style type="text/css">
+body { padding: 0; font-family: sans-serif; }
+.same-license { background-color: #eeeeee; border-top: 20px solid white; padding: 10px; }
+.label { font-weight: bold; }
+.file-list { margin-left: 1em; color: blue; }
+</style>
+"""
+
+def combine_notice_files_html(file_hash, input_dir, output_filename):
+ """Combine notice files in FILE_HASH and output a HTML version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+
+ # Set up a filename to row id table (anchors inside tables don't work in
+ # most browsers, but href's to table row ids do)
+ id_table = {}
+ id_count = 0
+ for value in file_hash:
+ for filename in value:
+ id_table[filename] = id_count
+ id_count += 1
+
+ # Open the output file, and output the header pieces
+ output_file = open(output_filename, "wb")
+
+ print >> output_file, "<html><head>"
+ print >> output_file, HTML_OUTPUT_CSS
+ print >> output_file, '</head><body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">'
+
+ # Output our table of contents
+ print >> output_file, '<div class="toc">'
+ print >> output_file, "<ul>"
+
+ # Flatten the list of lists into a single list of filenames
+ sorted_filenames = sorted(itertools.chain.from_iterable(file_hash))
+
+ # Print out a nice table of contents
+ for filename in sorted_filenames:
+ stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, '<li><a href="#id%d">%s</a></li>' % (id_table.get(filename), stripped_filename)
+
+ print >> output_file, "</ul>"
+ print >> output_file, "</div><!-- table of contents -->"
+ # Output the individual notice file lists
+ print >>output_file, '<table cellpadding="0" cellspacing="0" border="0">'
+ for value in file_hash:
+ print >> output_file, '<tr id="id%d"><td class="same-license">' % id_table.get(value[0])
+ print >> output_file, '<div class="label">Notices for file(s):</div>'
+ print >> output_file, '<div class="file-list">'
+ for filename in value:
+ print >> output_file, "%s <br/>" % (SRC_DIR_STRIP_RE.sub(r"\1", filename))
+ print >> output_file, "</div><!-- file-list -->"
+ print >> output_file
+ print >> output_file, '<pre class="license-text">'
+ print >> output_file, html_escape(open(value[0]).read())
+ print >> output_file, "</pre><!-- license-text -->"
+ print >> output_file, "</td></tr><!-- same-license -->"
+ print >> output_file
+ print >> output_file
+ print >> output_file
+
+ # Finish off the file output
+ print >> output_file, "</table>"
+ print >> output_file, "</body></html>"
+ output_file.close()
+
+def combine_notice_files_text(file_hash, input_dir, output_filename, file_title):
+ """Combine notice files in FILE_HASH and output a text version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+ output_file = open(output_filename, "wb")
+ print >> output_file, file_title
+ for value in file_hash:
+ print >> output_file, "============================================================"
+ print >> output_file, "Notices for file(s):"
+ for filename in value:
+ print >> output_file, SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, "------------------------------------------------------------"
+ print >> output_file, open(value[0]).read()
+ output_file.close()
+
+def combine_notice_files_xml(files_with_same_hash, input_dir, output_filename):
+ """Combine notice files in FILE_HASH and output a XML version to OUTPUT_FILENAME."""
+
+ SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt")
+
+ # Set up a filename to row id table (anchors inside tables don't work in
+ # most browsers, but href's to table row ids do)
+ id_table = {}
+ for file_key in files_with_same_hash.keys():
+ for filename in files_with_same_hash[file_key]:
+ id_table[filename] = file_key
+
+ # Open the output file, and output the header pieces
+ output_file = open(output_filename, "wb")
+
+ print >> output_file, '<?xml version="1.0" encoding="utf-8"?>'
+ print >> output_file, "<licenses>"
+
+ # Flatten the list of lists into a single list of filenames
+ sorted_filenames = sorted(id_table.keys())
+
+ # Print out a nice table of contents
+ for filename in sorted_filenames:
+ stripped_filename = SRC_DIR_STRIP_RE.sub(r"\1", filename)
+ print >> output_file, '<file-name contentId="%s">%s</file-name>' % (id_table.get(filename), stripped_filename)
+
+ print >> output_file
+ print >> output_file
+
+ processed_file_keys = []
+ # Output the individual notice file lists
+ for filename in sorted_filenames:
+ file_key = id_table.get(filename)
+ if file_key in processed_file_keys:
+ continue
+ processed_file_keys.append(file_key)
+
+ print >> output_file, '<file-content contentId="%s"><![CDATA[%s]]></file-content>' % (file_key, html_escape(open(filename).read()))
+ print >> output_file
+
+ # Finish off the file output
+ print >> output_file, "</licenses>"
+ output_file.close()
+
+def get_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--text-output', required=True,
+ help='The text output file path.')
+ parser.add_argument(
+ '--html-output',
+ help='The html output file path.')
+ parser.add_argument(
+ '--xml-output',
+ help='The xml output file path.')
+ parser.add_argument(
+ '-t', '--title', required=True,
+ help='The file title.')
+ parser.add_argument(
+ '-s', '--source-dir', required=True,
+ help='The directory containing notices.')
+ parser.add_argument(
+ '-i', '--included-subdirs', action='append',
+ help='The sub directories which should be included.')
+ parser.add_argument(
+ '-e', '--excluded-subdirs', action='append',
+ help='The sub directories which should be excluded.')
+ return parser.parse_args()
+
+def main(argv):
+ args = get_args()
+
+ txt_output_file = args.text_output
+ html_output_file = args.html_output
+ xml_output_file = args.xml_output
+ file_title = args.title
+ included_subdirs = []
+ excluded_subdirs = []
+ if args.included_subdirs is not None:
+ included_subdirs = args.included_subdirs
+ if args.excluded_subdirs is not None:
+ excluded_subdirs = args.excluded_subdirs
+
+ # Find all the notice files and md5 them
+ input_dir = os.path.normpath(args.source_dir)
+ files_with_same_hash = defaultdict(list)
+ for root, dir, files in os.walk(input_dir):
+ for file in files:
+ matched = True
+ if len(included_subdirs) > 0:
+ matched = False
+ for subdir in included_subdirs:
+ if (root == (input_dir + '/' + subdir) or
+ root.startswith(input_dir + '/' + subdir + '/')):
+ matched = True
+ break
+ elif len(excluded_subdirs) > 0:
+ for subdir in excluded_subdirs:
+ if (root == (input_dir + '/' + subdir) or
+ root.startswith(input_dir + '/' + subdir + '/')):
+ matched = False
+ break
+ if matched and file.endswith(".txt"):
+ filename = os.path.join(root, file)
+ file_md5sum = md5sum(filename)
+ files_with_same_hash[file_md5sum].append(filename)
+
+ filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())]
+
+ combine_notice_files_text(filesets, input_dir, txt_output_file, file_title)
+
+ if html_output_file is not None:
+ combine_notice_files_html(filesets, input_dir, html_output_file)
+
+ if xml_output_file is not None:
+ combine_notice_files_xml(files_with_same_hash, input_dir, xml_output_file)
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/scripts/jsonmodify.py b/scripts/jsonmodify.py
index 4b2c3c2..ba1109e 100755
--- a/scripts/jsonmodify.py
+++ b/scripts/jsonmodify.py
@@ -112,9 +112,10 @@
if args.out:
with open(args.out, "w") as f:
- json.dump(obj, f, indent=2)
+ json.dump(obj, f, indent=2, separators=(',', ': '))
+ f.write('\n')
else:
- print(json.dumps(obj, indent=2))
+ print(json.dumps(obj, indent=2, separators=(',', ': ')))
if __name__ == '__main__':
diff --git a/scripts/mergenotice.py b/scripts/mergenotice.py
index 407ae8c..fe99073 100755
--- a/scripts/mergenotice.py
+++ b/scripts/mergenotice.py
@@ -16,7 +16,7 @@
#
"""
Merges input notice files to the output file while ignoring duplicated files
-This script shouldn't be confused with build/make/tools/generate-notice-files.py
+This script shouldn't be confused with build/soong/scripts/generate-notice-files.py
which is responsible for creating the final notice file for all artifacts
installed. This script has rather limited scope; it is meant to create a merged
notice file for a set of modules that are packaged together, e.g. in an APEX.
diff --git a/scripts/reverse-deps.sh b/scripts/reverse-deps.sh
new file mode 100755
index 0000000..02b7dcb
--- /dev/null
+++ b/scripts/reverse-deps.sh
@@ -0,0 +1,246 @@
+#!/bin/bash
+
+set -eu
+
+# Copyright 2020 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.
+
+# Tool to evaluate the transitive closure of the ninja dependency graph of the
+# files and targets depending on a given target.
+#
+# i.e. the list of things that could change after changing a target.
+
+readonly me=$(basename "${0}")
+
+readonly usage="usage: ${me} {options} target [target...]
+
+Evaluate the reverse transitive closure of ninja targets depending on one or
+more targets.
+
+Options:
+
+ -(no)quiet Suppresses progress output to stderr and interactive
+ alias -(no)q prompts. By default, when stderr is a tty, progress gets
+ reported to stderr; when both stderr and stdin are tty,
+ the script asks user whether to delete intermediate files.
+ When suppressed or not prompted, script always deletes the
+ temporary / intermediate files.
+ -sep=<delim> Use 'delim' as output field separator between notice
+ checksum and notice filename in notice output.
+ e.g. sep='\t'
+ (Default space)
+ -csv Shorthand for -sep=','
+
+At minimum, before running this script, you must first run:
+$ source build/envsetup.sh
+$ lunch
+$ m nothing
+to setup the build environment, choose a target platform, and build the ninja
+dependency graph.
+"
+
+function die() { echo -e "${*}" >&2; exit 2; }
+
+# Reads one input target per line from stdin; outputs (isnotice target) tuples.
+#
+# output target is a ninja target that the input target depends on
+# isnotice in {0,1} with 1 for output targets believed to be license or notice
+#
+# only argument is the dependency depth indicator
+function getDeps() {
+ (tr '\n' '\0' | xargs -0 "${ninja_bin}" -f "${ninja_file}" -t query) \
+ | awk -v depth="${1}" '
+ BEGIN {
+ inoutput = 0
+ }
+ $0 ~ /^\S\S*:$/ {
+ inoutput = 0
+ }
+ inoutput != 0 {
+ print gensub(/^\s*/, "", "g")" "depth
+ }
+ $1 == "outputs:" {
+ inoutput = 1
+ }
+ '
+}
+
+
+if [ -z "${ANDROID_BUILD_TOP}" ]; then
+ die "${me}: Run 'lunch' to configure the build environment"
+fi
+
+if [ -z "${TARGET_PRODUCT}" ]; then
+ die "${me}: Run 'lunch' to configure the build environment"
+fi
+
+ninja_file="${ANDROID_BUILD_TOP}/out/combined-${TARGET_PRODUCT}.ninja"
+if [ ! -f "${ninja_file}" ]; then
+ die "${me}: Run 'm nothing' to build the dependency graph"
+fi
+
+ninja_bin="${ANDROID_BUILD_TOP}/prebuilts/build-tools/linux-x86/bin/ninja"
+if [ ! -x "${ninja_bin}" ]; then
+ die "${me}: Cannot find ninja executable expected at ${ninja_bin}"
+fi
+
+
+# parse the command-line
+
+declare -a targets # one or more targets to evaluate
+
+quiet=false # whether to suppress progress
+
+sep=" " # output separator between depth and target
+
+use_stdin=false # whether to read targets from stdin i.e. target -
+
+while [ $# -gt 0 ]; do
+ case "${1:-}" in
+ -)
+ use_stdin=true
+ ;;
+ -*)
+ flag=$(expr "${1}" : '^-*\(.*\)$')
+ case "${flag:-}" in
+ q) ;&
+ quiet)
+ quiet=true;;
+ noq) ;&
+ noquiet)
+ quiet=false;;
+ csv)
+ sep=",";;
+ sep)
+ sep="${2?"${usage}"}"; shift;;
+ sep=*)
+ sep=$(expr "${flag}" : '^sep=\(.*\)$';;
+ *)
+ die "Unknown flag ${1}"
+ ;;
+ esac
+ ;;
+ *)
+ targets+=("${1:-}")
+ ;;
+ esac
+ shift
+done
+
+if [ ! -v targets[0] ] && ! ${use_stdin}; then
+ die "${usage}\n\nNo target specified."
+fi
+
+# showProgress when stderr is a tty
+if [ -t 2 ] && ! ${quiet}; then
+ showProgress=true
+else
+ showProgress=false
+fi
+
+# interactive when both stderr and stdin are tty
+if ${showProgress} && [ -t 0 ]; then
+ interactive=true
+else
+ interactive=false
+fi
+
+
+readonly tmpFiles=$(mktemp -d "${TMPDIR}.tdeps.XXXXXXXXX")
+if [ -z "${tmpFiles}" ]; then
+ die "${me}: unable to create temporary directory"
+fi
+
+# The deps files contain unique (isnotice target) tuples where
+# isnotice in {0,1} with 1 when ninja target `target` is a license or notice.
+readonly oldDeps="${tmpFiles}/old"
+readonly newDeps="${tmpFiles}/new"
+readonly allDeps="${tmpFiles}/all"
+
+if ${use_stdin}; then # start deps by reading 1 target per line from stdin
+ awk '
+ NF > 0 {
+ print gensub(/\s*$/, "", "g", gensub(/^\s*/, "", "g"))" "0
+ }
+ ' >"${newDeps}"
+else # start with no deps by clearing file
+ : >"${newDeps}"
+fi
+
+# extend deps by appending targets from command-line
+for idx in "${!targets[*]}"; do
+ echo "${targets[${idx}]} 0" >>"${newDeps}"
+done
+
+# remove duplicates and start with new, old and all the same
+sort -u <"${newDeps}" >"${allDeps}"
+cp "${allDeps}" "${newDeps}"
+cp "${allDeps}" "${oldDeps}"
+
+# report depth of dependenciens when showProgress
+depth=0
+
+while [ $(wc -l < "${newDeps}") -gt 0 ]; do
+ if ${showProgress}; then
+ echo "depth ${depth} has "$(wc -l < "${newDeps}")" targets" >&2
+ fi
+ depth=$(expr ${depth} + 1)
+ ( # recalculate dependencies by combining unique inputs of new deps w. old
+ cut -d\ -f1 "${newDeps}" | getDeps "${depth}"
+ cat "${oldDeps}"
+ ) | sort -n | awk '
+ BEGIN {
+ prev = ""
+ }
+ {
+ depth = $NF
+ $NF = ""
+ gsub(/\s*$/, "")
+ if ($0 != prev) {
+ print gensub(/\s*$/, "", "g")" "depth
+ }
+ prev = $0
+ }
+ ' >"${allDeps}"
+ # recalculate new dependencies as net additions to old dependencies
+ set +e
+ diff "${oldDeps}" "${allDeps}" --old-line-format='' \
+ --new-line-format='%L' --unchanged-line-format='' > "${newDeps}"
+ set -e
+ # recalculate old dependencies for next iteration
+ cp "${allDeps}" "${oldDeps}"
+done
+
+# found all deps -- clean up last iteration of old and new
+rm -f "${oldDeps}"
+rm -f "${newDeps}"
+
+if ${showProgress}; then
+ echo $(wc -l < "${allDeps}")" targets" >&2
+fi
+
+awk -v sep="${sep}" '{
+ depth = $NF
+ $NF = ""
+ gsub(/\s*$/, "")
+ print depth sep $0
+}' "${allDeps}" | sort -n
+
+if ${interactive}; then
+ echo -n "$(date '+%F %-k:%M:%S') Delete ${tmpFiles} ? [n] " >&2
+ read answer
+ case "${answer}" in [yY]*) rm -fr "${tmpFiles}";; esac
+else
+ rm -fr "${tmpFiles}"
+fi
diff --git a/scripts/transitive-deps.sh b/scripts/transitive-deps.sh
new file mode 100755
index 0000000..c6f8b76
--- /dev/null
+++ b/scripts/transitive-deps.sh
@@ -0,0 +1,491 @@
+#!/bin/bash
+
+set -eu
+
+# Copyright 2020 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.
+
+# Tool to evaluate the transitive closure of the ninja dependency graph of the
+# files and targets a given target depends on.
+#
+# i.e. the list of things that, if changed, could cause a change to a target.
+
+readonly me=$(basename "${0}")
+
+readonly usage="usage: ${me} {options} target [target...]
+
+Evaluate the transitive closure of files and ninja targets that one or more
+targets depend on.
+
+Dependency Options:
+
+ -(no)order_deps Whether to include order-only dependencies. (Default false)
+ -(no)implicit Whether to include implicit dependencies. (Default true)
+ -(no)explicit Whether to include regular / explicit deps. (Default true)
+
+ -nofollow Unanchored regular expression. Matching paths and targets
+ always get reported. Their dependencies do not get reported
+ unless first encountered in a 'container' file type.
+ Multiple allowed and combined using '|'.
+ e.g. -nofollow='*.so' not -nofollow='.so$'
+ -nofollow='*.so|*.dex' or -nofollow='*.so' -nofollow='.dex'
+ (Defaults to no matches)
+ -container Unanchored regular expression. Matching file extensions get
+ treated as 'container' files for -nofollow option.
+ Multiple allowed and combines using '|'
+ (Default 'apex|apk|zip|jar|tar|tgz')
+
+Output Options:
+
+ -(no)quiet Suppresses progress output to stderr and interactive
+ alias -(no)q prompts. By default, when stderr is a tty, progress gets
+ reported to stderr; when both stderr and stdin are tty,
+ the script asks user whether to delete intermediate files.
+ When suppressed or not prompted, script always deletes the
+ temporary / intermediate files.
+ -sep=<delim> Use 'delim' as output field separator between notice
+ checksum and notice filename in notice output.
+ e.g. sep='\t'
+ (Default space)
+ -csv Shorthand for -sep=','
+ -directories=<f> Output directory names of dependencies to 'f'.
+ alias -d User '/dev/stdout' to send directories to stdout. Defaults
+ to no directory output.
+ -notices=<file> Output license and notice file paths to 'file'.
+ alias -n Use '/dev/stdout' to send notices to stdout. Defaults to no
+ license/notice output.
+ -projects=<file> Output git project names to 'file'. Use '/dev/stdout' to
+ alias -p send projects to stdout. Defaults to no project output.
+ -targets=<fils> Output target dependencies to 'file'. Use '/dev/stdout' to
+ alias -t send targets to stdout.
+ When no directory, notice, project or target output options
+ given, defaults to stdout. Otherwise, defaults to no target
+ output.
+
+At minimum, before running this script, you must first run:
+$ source build/envsetup.sh
+$ lunch
+$ m nothing
+to setup the build environment, choose a target platform, and build the ninja
+dependency graph.
+"
+
+function die() { echo -e "${*}" >&2; exit 2; }
+
+# Reads one input target per line from stdin; outputs (isnotice target) tuples.
+#
+# output target is a ninja target that the input target depends on
+# isnotice in {0,1} with 1 for output targets believed to be license or notice
+function getDeps() {
+ (tr '\n' '\0' | xargs -0 -r "${ninja_bin}" -f "${ninja_file}" -t query) \
+ | awk -v include_order="${include_order_deps}" \
+ -v include_implicit="${include_implicit_deps}" \
+ -v include_explicit="${include_deps}" \
+ -v containers="${container_types}" \
+ '
+ BEGIN {
+ ininput = 0
+ isnotice = 0
+ currFileName = ""
+ currExt = ""
+ }
+ $1 == "outputs:" {
+ ininput = 0
+ }
+ ininput == 0 && $0 ~ /^\S\S*:$/ {
+ isnotice = ($0 ~ /.*NOTICE.*[.]txt:$/)
+ currFileName = gensub(/^.*[/]([^/]*)[:]$/, "\\1", "g")
+ currExt = gensub(/^.*[.]([^./]*)[:]$/, "\\1", "g")
+ }
+ ininput != 0 && $1 !~ /^[|][|]?/ {
+ if (include_explicit == "true") {
+ fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g")
+ print ( \
+ (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \
+ || $0 ~ /NOTICE|LICEN[CS]E/ \
+ || $0 ~ /(notice|licen[cs]e)[.]txt/ \
+ )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g")
+ }
+ }
+ ininput != 0 && $1 == "|" {
+ if (include_implicit == "true") {
+ fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g")
+ $1 = ""
+ print ( \
+ (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \
+ || $0 ~ /NOTICE|LICEN[CS]E/ \
+ || $0 ~ /(notice|licen[cs]e)[.]txt/ \
+ )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g")
+ }
+ }
+ ininput != 0 && $1 == "||" {
+ if (include_order == "true") {
+ fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g")
+ $1 = ""
+ print ( \
+ (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \
+ || $0 ~ /NOTICE|LICEN[CS]E/ \
+ || $0 ~ /(notice|licen[cs]e)[.]txt/ \
+ )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g")
+ }
+ }
+ $1 == "input:" {
+ ininput = 1
+ }
+ '
+}
+
+# Reads one input directory per line from stdin; outputs unique git projects.
+function getProjects() {
+ while read d; do
+ while [ "${d}" != '.' ] && [ "${d}" != '/' ]; do
+ if [ -d "${d}/.git/" ]; then
+ echo "${d}"
+ break
+ fi
+ d=$(dirname "${d}")
+ done
+ done | sort -u
+}
+
+
+if [ -z "${ANDROID_BUILD_TOP}" ]; then
+ die "${me}: Run 'lunch' to configure the build environment"
+fi
+
+if [ -z "${TARGET_PRODUCT}" ]; then
+ die "${me}: Run 'lunch' to configure the build environment"
+fi
+
+readonly ninja_file="${ANDROID_BUILD_TOP}/out/combined-${TARGET_PRODUCT}.ninja"
+if [ ! -f "${ninja_file}" ]; then
+ die "${me}: Run 'm nothing' to build the dependency graph"
+fi
+
+readonly ninja_bin="${ANDROID_BUILD_TOP}/prebuilts/build-tools/linux-x86/bin/ninja"
+if [ ! -x "${ninja_bin}" ]; then
+ die "${me}: Cannot find ninja executable expected at ${ninja_bin}"
+fi
+
+
+# parse the command-line
+
+declare -a targets # one or more targets to evaluate
+
+include_order_deps=false # whether to trace through || "order dependencies"
+include_implicit_deps=true # whether to trace through | "implicit deps"
+include_deps=true # whether to trace through regular explicit deps
+quiet=false # whether to suppress progress
+
+projects_out='' # where to output the list of projects
+directories_out='' # where to output the list of directories
+targets_out='' # where to output the list of targets/source files
+notices_out='' # where to output the list of license/notice files
+
+sep=" " # separator between md5sum and notice filename
+
+nofollow='' # regularexp must fully match targets to skip
+
+container_types='' # regularexp must full match file extension
+ # defaults to 'apex|apk|zip|jar|tar|tgz' below.
+
+use_stdin=false # whether to read targets from stdin i.e. target -
+
+while [ $# -gt 0 ]; do
+ case "${1:-}" in
+ -)
+ use_stdin=true
+ ;;
+ -*)
+ flag=$(expr "${1}" : '^-*\(.*\)$')
+ case "${flag:-}" in
+ order_deps)
+ include_order_deps=true;;
+ noorder_deps)
+ include_order_deps=false;;
+ implicit)
+ include_implicit_deps=true;;
+ noimplicit)
+ include_implicit_deps=false;;
+ explicit)
+ include_deps=true;;
+ noexplicit)
+ include_deps=false;;
+ csv)
+ sep=",";;
+ sep)
+ sep="${2?"${usage}"}"; shift;;
+ sep=)
+ sep=$(expr "${flag}" : '^sep=\(.*\)$');;
+ q) ;&
+ quiet)
+ quiet=true;;
+ noq) ;&
+ noquiet)
+ quiet=false;;
+ nofollow)
+ case "${nofollow}" in
+ '')
+ nofollow="${2?"${usage}"}";;
+ *)
+ nofollow="${nofollow}|${2?"${usage}"}";;
+ esac
+ shift
+ ;;
+ nofollow=*)
+ case "${nofollow}" in
+ '')
+ nofollow=$(expr "${flag}" : '^nofollow=\(.*\)$');;
+ *)
+ nofollow="${nofollow}|"$(expr "${flag}" : '^nofollow=\(.*\)$');;
+ esac
+ ;;
+ container)
+ container_types="${container_types}|${2?"${usage}"}";;
+ container=*)
+ container_types="${container_types}|"$(expr "${flag}" : '^container=\(.*\)$');;
+ p) ;&
+ projects)
+ projects_out="${2?"${usage}"}"; shift;;
+ p=*) ;&
+ projects=*)
+ projects_out=$(expr "${flag}" : '^.*=\(.*\)$');;
+ d) ;&
+ directores)
+ directories_out="${2?"${usage}"}"; shift;;
+ d=*) ;&
+ directories=*)
+ directories_out=$(expr "${flag}" : '^.*=\(.*\)$');;
+ t) ;&
+ targets)
+ targets_out="${2?"${usage}"}"; shift;;
+ t=*) ;&
+ targets=)
+ targets_out=$(expr "${flag}" : '^.*=\(.*\)$');;
+ n) ;&
+ notices)
+ notices_out="${2?"${usage}"}"; shift;;
+ n=*) ;&
+ notices=)
+ notices_out=$(expr "${flag}" : '^.*=\(.*\)$');;
+ *)
+ die "Unknown flag ${1}";;
+ esac
+ ;;
+ *)
+ targets+=("${1:-}")
+ ;;
+ esac
+ shift
+done
+
+
+# fail fast if command-line arguments are invalid
+
+if [ ! -v targets[0] ] && ! ${use_stdin}; then
+ die "${usage}\n\nNo target specified."
+fi
+
+if [ -z "${projects_out}" ] \
+ && [ -z "${directories_out}" ] \
+ && [ -z "${targets_out}" ] \
+ && [ -z "${notices_out}" ]
+then
+ targets_out='/dev/stdout'
+fi
+
+if [ -z "${container_types}" ]; then
+ container_types='apex|apk|zip|jar|tar|tgz'
+fi
+
+# showProgress when stderr is a tty
+if [ -t 2 ] && ! ${quiet}; then
+ showProgress=true
+else
+ showProgress=false
+fi
+
+# interactive when both stderr and stdin are tty
+if ${showProgress} && [ -t 0 ]; then
+ interactive=true
+else
+ interactive=false
+fi
+
+
+readonly tmpFiles=$(mktemp -d "${TMPDIR}.tdeps.XXXXXXXXX")
+if [ -z "${tmpFiles}" ]; then
+ die "${me}: unable to create temporary directory"
+fi
+
+# The deps files contain unique (isnotice target) tuples where
+# isnotice in {0,1} with 1 when ninja target 'target' is a license or notice.
+readonly oldDeps="${tmpFiles}/old"
+readonly newDeps="${tmpFiles}/new"
+readonly allDeps="${tmpFiles}/all"
+
+if ${use_stdin}; then # start deps by reading 1 target per line from stdin
+ awk '
+ NF > 0 {
+ print ( \
+ $0 ~ /NOTICE|LICEN[CS]E/ \
+ || $0 ~ /(notice|licen[cs]e)[.]txt/ \
+ )" "gensub(/\s*$/, "", "g", gensub(/^\s*/, "", "g"))
+ }
+ ' > "${newDeps}"
+else # start with no deps by clearing file
+ : > "${newDeps}"
+fi
+
+# extend deps by appending targets from command-line
+for idx in "${!targets[*]}"; do
+ isnotice='0'
+ case "${targets[${idx}]}" in
+ *NOTICE*) ;&
+ *LICEN[CS]E*) ;&
+ *notice.txt) ;&
+ *licen[cs]e.txt)
+ isnotice='1';;
+ esac
+ echo "${isnotice} 1 ${targets[${idx}]}" >> "${newDeps}"
+done
+
+# remove duplicates and start with new, old and all the same
+sort -u < "${newDeps}" > "${allDeps}"
+cp "${allDeps}" "${newDeps}"
+cp "${allDeps}" "${oldDeps}"
+
+# report depth of dependenciens when showProgress
+depth=0
+
+# 1st iteration always unfiltered
+filter='cat'
+while [ $(wc -l < "${newDeps}") -gt 0 ]; do
+ if ${showProgress}; then
+ echo "depth ${depth} has "$(wc -l < "${newDeps}")" targets" >&2
+ depth=$(expr ${depth} + 1)
+ fi
+ ( # recalculate dependencies by combining unique inputs of new deps w. old
+ set +e
+ sh -c "${filter}" < "${newDeps}" | cut -d\ -f3- | getDeps
+ set -e
+ cat "${oldDeps}"
+ ) | sort -u > "${allDeps}"
+ # recalculate new dependencies as net additions to old dependencies
+ set +e
+ diff "${oldDeps}" "${allDeps}" --old-line-format='' --new-line-format='%L' \
+ --unchanged-line-format='' > "${newDeps}"
+ set -e
+ # apply filters on subsequent iterations
+ case "${nofollow}" in
+ '')
+ filter='cat';;
+ *)
+ filter="egrep -v '^[01] 0 (${nofollow})$'"
+ ;;
+ esac
+ # recalculate old dependencies for next iteration
+ cp "${allDeps}" "${oldDeps}"
+done
+
+# found all deps -- clean up last iteration of old and new
+rm -f "${oldDeps}"
+rm -f "${newDeps}"
+
+if ${showProgress}; then
+ echo $(wc -l < "${allDeps}")" targets" >&2
+fi
+
+if [ -n "${targets_out}" ]; then
+ cut -d\ -f3- "${allDeps}" | sort -u > "${targets_out}"
+fi
+
+if [ -n "${directories_out}" ] \
+ || [ -n "${projects_out}" ] \
+ || [ -n "${notices_out}" ]
+then
+ readonly allDirs="${tmpFiles}/dirs"
+ (
+ cut -d\ -f3- "${allDeps}" | tr '\n' '\0' | xargs -0 dirname
+ ) | sort -u > "${allDirs}"
+ if ${showProgress}; then
+ echo $(wc -l < "${allDirs}")" directories" >&2
+ fi
+
+ case "${directories_out}" in
+ '') : do nothing;;
+ *)
+ cat "${allDirs}" > "${directories_out}"
+ ;;
+ esac
+fi
+
+if [ -n "${projects_out}" ] \
+ || [ -n "${notices_out}" ]
+then
+ readonly allProj="${tmpFiles}/projects"
+ set +e
+ egrep -v '^out[/]' "${allDirs}" | getProjects > "${allProj}"
+ set -e
+ if ${showProgress}; then
+ echo $(wc -l < "${allProj}")" projects" >&2
+ fi
+
+ case "${projects_out}" in
+ '') : do nothing;;
+ *)
+ cat "${allProj}" > "${projects_out}"
+ ;;
+ esac
+fi
+
+case "${notices_out}" in
+ '') : do nothing;;
+ *)
+ readonly allNotice="${tmpFiles}/notices"
+ set +e
+ egrep '^1' "${allDeps}" | cut -d\ -f3- | egrep -v '^out/' > "${allNotice}"
+ set -e
+ cat "${allProj}" | while read proj; do
+ for f in LICENSE LICENCE NOTICE license.txt notice.txt; do
+ if [ -f "${proj}/${f}" ]; then
+ echo "${proj}/${f}"
+ fi
+ done
+ done >> "${allNotice}"
+ if ${showProgress}; then
+ echo $(cat "${allNotice}" | sort -u | wc -l)" notice targets" >&2
+ fi
+ readonly hashedNotice="${tmpFiles}/hashednotices"
+ ( # md5sum outputs checksum space indicator(space or *) filename newline
+ set +e
+ sort -u "${allNotice}" | tr '\n' '\0' | xargs -0 -r md5sum 2>/dev/null
+ set -e
+ # use sed to replace space and indicator with separator
+ ) > "${hashedNotice}"
+ if ${showProgress}; then
+ echo $(cut -d\ -f2- "${hashedNotice}" | sort -u | wc -l)" notice files" >&2
+ echo $(cut -d\ -f1 "${hashedNotice}" | sort -u | wc -l)" distinct notices" >&2
+ fi
+ sed 's/^\([^ ]*\) [* ]/\1'"${sep}"'/g' "${hashedNotice}" | sort > "${notices_out}"
+ ;;
+esac
+
+if ${interactive}; then
+ echo -n "$(date '+%F %-k:%M:%S') Delete ${tmpFiles} ? [n] " >&2
+ read answer
+ case "${answer}" in [yY]*) rm -fr "${tmpFiles}";; esac
+else
+ rm -fr "${tmpFiles}"
+fi
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 0a4e16d..733f7ac 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -32,6 +32,7 @@
"arm64/include/Arm64Test.h": nil,
"libfoo.so": nil,
"aidl/foo/bar/Test.aidl": nil,
+ "some/where/stubslib.map.txt": nil,
}
return testSdkWithFs(t, bp, fs)
}
@@ -48,7 +49,6 @@
cc_library_shared {
name: "sdkmember",
srcs: ["Test.cpp"],
- system_shared_libs: [],
stl: "none",
}
`)
@@ -178,13 +178,11 @@
cc_library_host_shared {
name: "sdkshared",
- system_shared_libs: [],
stl: "none",
}
cc_library_host_static {
name: "sdkstatic",
- system_shared_libs: [],
stl: "none",
}
`)
@@ -201,30 +199,83 @@
cc_library_shared {
name: "sdkshared",
- system_shared_libs: [],
stl: "none",
}
cc_library_static {
name: "sdkstatic",
- system_shared_libs: [],
stl: "none",
}
cc_library {
name: "sdkboth1",
- system_shared_libs: [],
stl: "none",
}
cc_library {
name: "sdkboth2",
- system_shared_libs: [],
stl: "none",
}
`)
}
+func TestSnapshotWithObject(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_objects: ["crtobj"],
+ }
+
+ cc_object {
+ name: "crtobj",
+ stl: "none",
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_object {
+ name: "mysdk_crtobj@current",
+ sdk_member_name: "crtobj",
+ stl: "none",
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/crtobj.o"],
+ },
+ arm: {
+ srcs: ["arm/lib/crtobj.o"],
+ },
+ },
+}
+
+cc_prebuilt_object {
+ name: "crtobj",
+ prefer: false,
+ stl: "none",
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/crtobj.o"],
+ },
+ arm: {
+ srcs: ["arm/lib/crtobj.o"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ native_objects: ["mysdk_crtobj@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/crtobj/android_arm64_armv8-a/crtobj.o -> arm64/lib/crtobj.o
+.intermediates/crtobj/android_arm_armv7-a-neon/crtobj.o -> arm/lib/crtobj.o
+`),
+ )
+}
+
func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
@@ -238,7 +289,6 @@
"Test.cpp",
],
export_include_dirs: ["include"],
- system_shared_libs: [],
stl: "none",
}
@@ -248,7 +298,6 @@
"Test.cpp",
],
export_include_dirs: ["include"],
- system_shared_libs: [],
stl: "none",
}
`)
@@ -285,7 +334,6 @@
export_system_include_dirs: ["arm64/include"],
},
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -353,7 +401,6 @@
"Test.cpp",
],
compile_multilib: "both",
- system_shared_libs: [],
stl: "none",
}
`)
@@ -428,7 +475,6 @@
"Test.cpp",
],
compile_multilib: "both",
- system_shared_libs: [],
stl: "none",
target: {
windows: {
@@ -529,7 +575,6 @@
aidl: {
export_aidl_headers: true,
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -616,7 +661,6 @@
srcs: [
"Test.cpp",
],
- system_shared_libs: [],
stl: "none",
}
@@ -657,7 +701,6 @@
},
},
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -807,7 +850,6 @@
aidl: {
export_aidl_headers: true,
},
- system_shared_libs: [],
stl: "none",
sdk_version: "minimum",
}
@@ -903,7 +945,6 @@
srcs: [
"Test.cpp",
],
- system_shared_libs: [],
stl: "none",
target: {
windows: {
@@ -993,7 +1034,6 @@
aidl: {
export_aidl_headers: true,
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1080,7 +1120,6 @@
aidl: {
export_aidl_headers: true,
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1162,7 +1201,6 @@
"Test.cpp",
],
export_include_dirs: ["include"],
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1265,7 +1303,6 @@
aidl: {
export_aidl_headers: true,
},
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1336,7 +1373,6 @@
cc_library_headers {
name: "mynativeheaders",
export_include_dirs: ["include"],
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1387,7 +1423,6 @@
device_supported: false,
host_supported: true,
export_include_dirs: ["include"],
- system_shared_libs: [],
stl: "none",
}
`)
@@ -1441,7 +1476,6 @@
cc_library_headers {
name: "mynativeheaders",
host_supported: true,
- system_shared_libs: [],
stl: "none",
export_system_include_dirs: ["include"],
target: {
@@ -1504,3 +1538,270 @@
`),
)
}
+
+func TestSystemSharedLibPropagation(t *testing.T) {
+ // b/145598135 - Generating host snapshots for anything other than linux is not supported.
+ SkipIfNotLinux(t)
+
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["sslnil", "sslempty", "sslnonempty"],
+ }
+
+ cc_library {
+ name: "sslnil",
+ host_supported: true,
+ }
+
+ cc_library {
+ name: "sslempty",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "sslnonempty",
+ system_shared_libs: ["sslnil"],
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_sslnil@current",
+ sdk_member_name: "sslnil",
+ installable: false,
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslnil.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslnil.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "sslnil",
+ prefer: false,
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslnil.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslnil.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "mysdk_sslempty@current",
+ sdk_member_name: "sslempty",
+ installable: false,
+ system_shared_libs: [],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslempty.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "sslempty",
+ prefer: false,
+ system_shared_libs: [],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslempty.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "mysdk_sslnonempty@current",
+ sdk_member_name: "sslnonempty",
+ installable: false,
+ system_shared_libs: ["mysdk_sslnil@current"],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslnonempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslnonempty.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "sslnonempty",
+ prefer: false,
+ system_shared_libs: ["sslnil"],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/sslnonempty.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/sslnonempty.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ native_shared_libs: [
+ "mysdk_sslnil@current",
+ "mysdk_sslempty@current",
+ "mysdk_sslnonempty@current",
+ ],
+}
+`))
+
+ result = testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ host_supported: true,
+ native_shared_libs: ["sslvariants"],
+ }
+
+ cc_library {
+ name: "sslvariants",
+ host_supported: true,
+ target: {
+ android: {
+ system_shared_libs: [],
+ },
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_sslvariants@current",
+ sdk_member_name: "sslvariants",
+ host_supported: true,
+ installable: false,
+ target: {
+ android: {
+ system_shared_libs: [],
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/sslvariants.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/sslvariants.so"],
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
+ },
+ linux_glibc_x86: {
+ srcs: ["linux_glibc/x86/lib/sslvariants.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "sslvariants",
+ prefer: false,
+ host_supported: true,
+ target: {
+ android: {
+ system_shared_libs: [],
+ },
+ android_arm64: {
+ srcs: ["android/arm64/lib/sslvariants.so"],
+ },
+ android_arm: {
+ srcs: ["android/arm/lib/sslvariants.so"],
+ },
+ linux_glibc_x86_64: {
+ srcs: ["linux_glibc/x86_64/lib/sslvariants.so"],
+ },
+ linux_glibc_x86: {
+ srcs: ["linux_glibc/x86/lib/sslvariants.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ host_supported: true,
+ native_shared_libs: ["mysdk_sslvariants@current"],
+}
+`))
+}
+
+func TestStubsLibrary(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["stubslib"],
+ }
+
+ cc_library {
+ name: "internaldep",
+ }
+
+ cc_library {
+ name: "stubslib",
+ shared_libs: ["internaldep"],
+ stubs: {
+ symbol_file: "some/where/stubslib.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mysdk_stubslib@current",
+ sdk_member_name: "stubslib",
+ installable: false,
+ stubs: {
+ versions: ["3"],
+ },
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/stubslib.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/stubslib.so"],
+ },
+ },
+}
+
+cc_prebuilt_library_shared {
+ name: "stubslib",
+ prefer: false,
+ stubs: {
+ versions: ["3"],
+ },
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/stubslib.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/stubslib.so"],
+ },
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ native_shared_libs: ["mysdk_stubslib@current"],
+}
+`))
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index a844a53..788d016 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -624,7 +624,7 @@
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -678,7 +678,7 @@
}
`),
checkAllCopyRules(""),
- checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
+ checkMergeZips(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
)
}
@@ -997,14 +997,23 @@
apex_available: ["//apex_available:anyapex"],
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ current_api: "sdk_library/test/myjavalib.txt",
+ removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
},
}
@@ -1015,14 +1024,23 @@
apex_available: ["//apex_available:anyapex"],
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
+ current_api: "sdk_library/system/myjavalib.txt",
+ removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
+ current_api: "sdk_library/test/myjavalib.txt",
+ removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
},
}
@@ -1034,8 +1052,18 @@
`),
checkAllCopyRules(`
.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
.intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
.intermediates/myjavalib.stubs.test/android_common/javac/myjavalib.stubs.test.jar -> sdk_library/test/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib-removed.txt
`),
+ checkMergeZips(
+ ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+ ".intermediates/mysdk/common_os/tmp/sdk_library/system/myjavalib_stub_sources.zip",
+ ".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip"),
)
}
diff --git a/sdk/testing.go b/sdk/testing.go
index 570ea0f..9e27201 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -339,14 +339,15 @@
}
}
-// Check that the specified path is in the list of zips to merge with the intermediate zip.
-func checkMergeZip(expected string) snapshotBuildInfoChecker {
+// Check that the specified paths match the list of zips to merge with the intermediate zip.
+func checkMergeZips(expected ...string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
info.r.t.Helper()
if info.intermediateZip == "" {
info.r.t.Errorf("No intermediate zip file was created")
}
- ensureListContains(info.r.t, info.mergeZips, expected)
+
+ info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips)
}
}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 14fab68..0932873 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -18,6 +18,7 @@
"fmt"
"io"
"path"
+ "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -161,8 +162,21 @@
var (
pctx = android.NewPackageContext("android/soong/sysprop")
syspropCcTag = dependencyTag{name: "syspropCc"}
+
+ syspropLibrariesKey = android.NewOnceKey("syspropLibraries")
+ syspropLibrariesLock sync.Mutex
)
+func syspropLibraries(config android.Config) *[]string {
+ return config.Once(syspropLibrariesKey, func() interface{} {
+ return &[]string{}
+ }).(*[]string)
+}
+
+func SyspropLibraries(config android.Config) []string {
+ return append([]string{}, *syspropLibraries(config)...)
+}
+
func init() {
android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
}
@@ -202,6 +216,10 @@
return proptools.Bool(m.properties.Public_stub)
}
+func (m *syspropLibrary) CurrentSyspropApiFile() android.Path {
+ return m.currentApiFile
+}
+
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
baseModuleName := m.BaseModuleName()
@@ -475,6 +493,12 @@
Stem: proptools.StringPtr(m.BaseModuleName()),
})
}
+
+ syspropLibrariesLock.Lock()
+ defer syspropLibrariesLock.Unlock()
+
+ libraries := syspropLibraries(ctx.Config())
+ *libraries = append(*libraries, ctx.ModuleName())
}
func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/ui/build/build.go b/ui/build/build.go
index f3feac2..1122733 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -53,7 +53,6 @@
{{end -}}
pool highmem_pool
depth = {{.HighmemParallel}}
-build _kati_always_build_: phony
{{if .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
subninja {{.KatiPackageNinjaFile}}
{{end -}}
diff --git a/ui/build/config.go b/ui/build/config.go
index 5b9d10a..7fcc471 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -517,6 +517,9 @@
ctx.Fatalln("Unknown option:", arg)
}
} else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
+ if k == "OUT_DIR" {
+ ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
+ }
c.environ.Set(k, v)
} else if arg == "dist" {
c.dist = true
@@ -611,10 +614,6 @@
product = "aosp_arm"
case "arm64":
product = "aosm_arm64"
- case "mips":
- product = "aosp_mips"
- case "mips64":
- product = "aosp_mips64"
case "x86":
product = "aosp_x86"
case "x86_64":
@@ -787,48 +786,6 @@
return false
}
-func (c *configImpl) UseRBEJAVAC() bool {
- if !c.UseRBE() {
- return false
- }
-
- if v, ok := c.environ.Get("RBE_JAVAC"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return true
- }
- }
- return false
-}
-
-func (c *configImpl) UseRBER8() bool {
- if !c.UseRBE() {
- return false
- }
-
- if v, ok := c.environ.Get("RBE_R8"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return true
- }
- }
- return false
-}
-
-func (c *configImpl) UseRBED8() bool {
- if !c.UseRBE() {
- return false
- }
-
- if v, ok := c.environ.Get("RBE_D8"); ok {
- v = strings.TrimSpace(v)
- if v != "" && v != "false" {
- return true
- }
- }
- return false
-}
-
func (c *configImpl) StartRBE() bool {
if !c.UseRBE() {
return false
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a3234e3..a559330 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -229,8 +229,6 @@
"DEFAULT_ERROR_BUILD_MODULE_TYPES",
"BUILD_BROKEN_PREBUILT_ELF_FILES",
"BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW",
- "BUILD_BROKEN_USES_BUILD_AUX_EXECUTABLE",
- "BUILD_BROKEN_USES_BUILD_AUX_STATIC_LIBRARY",
"BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
"BUILD_BROKEN_USES_BUILD_EXECUTABLE",
"BUILD_BROKEN_USES_BUILD_FUZZ_TEST",
@@ -238,17 +236,12 @@
"BUILD_BROKEN_USES_BUILD_HOST_DALVIK_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_EXECUTABLE",
- "BUILD_BROKEN_USES_BUILD_HOST_FUZZ_TEST",
"BUILD_BROKEN_USES_BUILD_HOST_JAVA_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_NATIVE_TEST",
"BUILD_BROKEN_USES_BUILD_HOST_PREBUILT",
"BUILD_BROKEN_USES_BUILD_HOST_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_HOST_STATIC_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_STATIC_TEST_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_HOST_TEST_CONFIG",
"BUILD_BROKEN_USES_BUILD_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_MULTI_PREBUILT",
- "BUILD_BROKEN_USES_BUILD_NATIVE_BENCHMARK",
"BUILD_BROKEN_USES_BUILD_NATIVE_TEST",
"BUILD_BROKEN_USES_BUILD_NOTICE_FILE",
"BUILD_BROKEN_USES_BUILD_PACKAGE",
@@ -258,8 +251,6 @@
"BUILD_BROKEN_USES_BUILD_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_STATIC_TEST_LIBRARY",
- "BUILD_BROKEN_USES_BUILD_TARGET_TEST_CONFIG",
}, exportEnvVars...), BannerVars...)
make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
diff --git a/ui/build/exec.go b/ui/build/exec.go
index e435c53..053bbae 100644
--- a/ui/build/exec.go
+++ b/ui/build/exec.go
@@ -19,6 +19,8 @@
"io"
"os/exec"
"strings"
+ "syscall"
+ "time"
)
// Cmd is a wrapper of os/exec.Cmd that integrates with the build context for
@@ -33,6 +35,8 @@
ctx Context
config Config
name string
+
+ started time.Time
}
func Command(ctx Context, config Config, name string, executable string, args ...string) *Cmd {
@@ -57,7 +61,20 @@
c.wrapSandbox()
}
- c.ctx.Verboseln(c.Path, c.Args)
+ c.ctx.Verbosef("%q executing %q %v\n", c.name, c.Path, c.Args)
+ c.started = time.Now()
+}
+
+func (c *Cmd) report() {
+ if c.Cmd.ProcessState != nil {
+ rusage := c.Cmd.ProcessState.SysUsage().(*syscall.Rusage)
+ c.ctx.Verbosef("%q finished with exit code %d (%s real, %s user, %s system, %dMB maxrss)",
+ c.name, c.Cmd.ProcessState.ExitCode(),
+ time.Since(c.started).Round(time.Millisecond),
+ c.Cmd.ProcessState.UserTime().Round(time.Millisecond),
+ c.Cmd.ProcessState.SystemTime().Round(time.Millisecond),
+ rusage.Maxrss/1024)
+ }
}
func (c *Cmd) Start() error {
@@ -68,21 +85,30 @@
func (c *Cmd) Run() error {
c.prepare()
err := c.Cmd.Run()
+ c.report()
return err
}
func (c *Cmd) Output() ([]byte, error) {
c.prepare()
bytes, err := c.Cmd.Output()
+ c.report()
return bytes, err
}
func (c *Cmd) CombinedOutput() ([]byte, error) {
c.prepare()
bytes, err := c.Cmd.CombinedOutput()
+ c.report()
return bytes, err
}
+func (c *Cmd) Wait() error {
+ err := c.Cmd.Wait()
+ c.report()
+ return err
+}
+
// StartOrFatal is equivalent to Start, but handles the error with a call to ctx.Fatal
func (c *Cmd) StartOrFatal() {
if err := c.Start(); err != nil {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index a845c5b..2eb7850 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -67,6 +67,7 @@
"--ninja_dir=" + config.OutDir(),
"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
"--no_ninja_prelude",
+ "--use_ninja_phony_output",
"--regen",
"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
"--detect_android_echo",
@@ -104,17 +105,20 @@
envFunc(cmd.Environment)
if _, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok {
- u, err := user.Current()
- if err != nil {
- ctx.Println("Failed to get current user")
+ username := "unknown"
+ if u, err := user.Current(); err == nil {
+ username = u.Username
+ } else {
+ ctx.Println("Failed to get current user:", err)
}
- cmd.Environment.Set("BUILD_USERNAME", u.Username)
+ cmd.Environment.Set("BUILD_USERNAME", username)
}
if _, ok := cmd.Environment.Get("BUILD_HOSTNAME"); !ok {
hostname, err := os.Hostname()
if err != nil {
- ctx.Println("Failed to read hostname")
+ ctx.Println("Failed to read hostname:", err)
+ hostname = "unknown"
}
cmd.Environment.Set("BUILD_HOSTNAME", hostname)
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 4fc1f01..1b13e5d 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -58,6 +58,7 @@
args = append(args, "-f", config.CombinedNinjaFile())
args = append(args,
+ "-o", "usesphonyoutputs=yes",
"-w", "dupbuild=err",
"-w", "missingdepfile=err")
@@ -128,6 +129,16 @@
"GOMA_USE_LOCAL",
// RBE client
+ "RBE_compare",
+ "RBE_exec_root",
+ "RBE_exec_strategy",
+ "RBE_invocation_id",
+ "RBE_log_dir",
+ "RBE_platform",
+ "RBE_remote_accept_cache",
+ "RBE_remote_update_cache",
+ "RBE_server_address",
+ // TODO: remove old FLAG_ variables.
"FLAG_compare",
"FLAG_exec_root",
"FLAG_exec_strategy",
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 2de772b..98eb028 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -19,6 +19,7 @@
"os"
"os/exec"
"os/user"
+ "path/filepath"
"strings"
"sync"
)
@@ -54,6 +55,9 @@
working bool
group string
+ srcDir string
+ outDir string
+ distDir string
}
func (c *Cmd) sandboxSupported() bool {
@@ -72,15 +76,45 @@
sandboxConfig.group = "nobody"
}
- cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
+ // These directories will be bind mounted
+ // so we need full non-symlink paths
+ sandboxConfig.srcDir = absPath(c.ctx, ".")
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.srcDir); err == nil {
+ sandboxConfig.srcDir = absPath(c.ctx, derefPath)
+ }
+ sandboxConfig.outDir = absPath(c.ctx, c.config.OutDir())
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.outDir); err == nil {
+ sandboxConfig.outDir = absPath(c.ctx, derefPath)
+ }
+ sandboxConfig.distDir = absPath(c.ctx, c.config.DistDir())
+ if derefPath, err := filepath.EvalSymlinks(sandboxConfig.distDir); err == nil {
+ sandboxConfig.distDir = absPath(c.ctx, derefPath)
+ }
+
+ sandboxArgs := []string{
"-H", "android-build",
"-e",
"-u", "nobody",
"-g", sandboxConfig.group,
- "-B", "/",
+ "-R", "/",
+ "-B", sandboxConfig.srcDir,
+ "-B", "/tmp",
+ "-B", sandboxConfig.outDir,
+ }
+
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B",
+ sandboxConfig.distDir)
+ }
+
+ sandboxArgs = append(sandboxArgs,
"--disable_clone_newcgroup",
"--",
"/bin/bash", "-c", `if [ $(hostname) == "android-build" ]; then echo "Android" "Success"; else echo Failure; fi`)
+
+ cmd := exec.CommandContext(c.ctx.Context, nsjailPath, sandboxArgs...)
+
cmd.Env = c.config.Environment().Environ()
c.ctx.Verboseln(cmd.Args)
@@ -144,8 +178,17 @@
"--rlimit_fsize", "soft",
"--rlimit_nofile", "soft",
- // For now, just map everything. Eventually we should limit this, especially to make most things readonly.
- "-B", "/",
+ // For now, just map everything. Make most things readonly.
+ "-R", "/",
+
+ // Mount source are read-write
+ "-B", sandboxConfig.srcDir,
+
+ //Mount out dir as read-write
+ "-B", sandboxConfig.outDir,
+
+ // Mount a writable tmp dir
+ "-B", "/tmp",
// Disable newcgroup for now, since it may require newer kernels
// TODO: try out cgroups
@@ -155,6 +198,11 @@
"-q",
}
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir)
+ }
+
if c.Sandbox.AllowBuildBrokenUsesNetwork && c.config.BuildBrokenUsesNetwork() {
c.ctx.Printf("AllowBuildBrokenUsesNetwork: %v", c.Sandbox.AllowBuildBrokenUsesNetwork)
c.ctx.Printf("BuildBrokenUsesNetwork: %v", c.config.BuildBrokenUsesNetwork())
diff --git a/ui/build/soong.go b/ui/build/soong.go
index afbc073..2fbf381 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,11 +15,15 @@
package build
import (
+ "io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
+ soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
+
+ "github.com/golang/protobuf/proto"
"github.com/google/blueprint/microfactory"
"android/soong/ui/metrics"
@@ -115,7 +119,11 @@
cmd := Command(ctx, config, "soong "+name,
config.PrebuiltBuildTool("ninja"),
"-d", "keepdepfile",
+ "-o", "usesphonyoutputs=yes",
+ "-o", "preremoveoutputs=yes",
"-w", "dupbuild=err",
+ "-w", "outputdir=err",
+ "-w", "missingoutfile=err",
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
@@ -126,4 +134,35 @@
ninja("minibootstrap", ".minibootstrap/build.ninja")
ninja("bootstrap", ".bootstrap/build.ninja")
+
+ soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
+ logSoongBuildMetrics(ctx, soongBuildMetrics)
+
+ if ctx.Metrics != nil {
+ ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
+ }
+}
+
+func loadSoongBuildMetrics(ctx Context, config Config) *soong_metrics_proto.SoongBuildMetrics {
+ soongBuildMetricsFile := filepath.Join(config.OutDir(), "soong", "soong_build_metrics.pb")
+ buf, err := ioutil.ReadFile(soongBuildMetricsFile)
+ if err != nil {
+ ctx.Fatalf("Failed to load %s: %s", soongBuildMetricsFile, err)
+ }
+ soongBuildMetrics := &soong_metrics_proto.SoongBuildMetrics{}
+ err = proto.Unmarshal(buf, soongBuildMetrics)
+ if err != nil {
+ ctx.Fatalf("Failed to unmarshal %s: %s", soongBuildMetricsFile, err)
+ }
+ return soongBuildMetrics
+}
+
+func logSoongBuildMetrics(ctx Context, metrics *soong_metrics_proto.SoongBuildMetrics) {
+ ctx.Verbosef("soong_build metrics:")
+ ctx.Verbosef(" modules: %v", metrics.GetModules())
+ ctx.Verbosef(" variants: %v", metrics.GetVariants())
+ ctx.Verbosef(" max heap size: %v MB", metrics.GetMaxHeapSize()/1e6)
+ ctx.Verbosef(" total allocation count: %v", metrics.GetTotalAllocCount())
+ ctx.Verbosef(" total allocation size: %v MB", metrics.GetTotalAllocSize()/1e6)
+
}
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 5109465..4ff9483 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -50,10 +50,10 @@
// Get a list of leaf nodes in the dependency graph from ninja
executable := config.PrebuiltBuildTool("ninja")
- args := []string{}
- args = append(args, config.NinjaArgs()...)
- args = append(args, "-f", config.CombinedNinjaFile())
- args = append(args, "-t", "targets", "rule")
+ common_args := []string{}
+ common_args = append(common_args, config.NinjaArgs()...)
+ common_args = append(common_args, "-f", config.CombinedNinjaFile())
+ args := append(common_args, "-t", "targets", "rule")
cmd := Command(ctx, config, "ninja", executable, args...)
stdout, err := cmd.StdoutPipe()
@@ -96,9 +96,31 @@
sb := &strings.Builder{}
title := "Dependencies in out found with no rule to create them:"
fmt.Fprintln(sb, title)
- for _, dep := range danglingRulesList {
- fmt.Fprintln(sb, " ", dep)
+
+ report_lines := 1
+ for i, dep := range danglingRulesList {
+ if report_lines > 20 {
+ fmt.Fprintf(sb, " ... and %d more\n", len(danglingRulesList)-i)
+ break
+ }
+ // It's helpful to see the reverse dependencies. ninja -t query is the
+ // best tool we got for that. Its output starts with the dependency
+ // itself.
+ query_cmd := Command(ctx, config, "ninja", executable,
+ append(common_args, "-t", "query", dep)...)
+ query_stdout, err := query_cmd.StdoutPipe()
+ if err != nil {
+ ctx.Fatal(err)
+ }
+ query_cmd.StartOrFatal()
+ scanner := bufio.NewScanner(query_stdout)
+ for scanner.Scan() {
+ report_lines++
+ fmt.Fprintln(sb, " ", scanner.Text())
+ }
+ query_cmd.WaitOrFatal()
}
+
ts.FinishAction(status.ActionResult{
Action: action,
Error: fmt.Errorf(title),
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 529639d..3596e10 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -17,6 +17,7 @@
pkgPath: "android/soong/ui/metrics",
deps: [
"golang-protobuf-proto",
+ "soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
"soong-ui-tracer",
],
@@ -35,3 +36,11 @@
],
}
+bootstrap_go_package {
+ name: "soong-ui-metrics_upload_proto",
+ pkgPath: "android/soong/ui/metrics/upload_proto",
+ deps: ["golang-protobuf-proto"],
+ srcs: [
+ "upload_proto/upload.pb.go",
+ ],
+}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 8254e4a..3e76d37 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -145,6 +145,10 @@
return writeMessageToFile(&m.metrics, outputPath)
}
+func (m *Metrics) SetSoongBuildMetrics(metrics *soong_metrics_proto.SoongBuildMetrics) {
+ m.metrics.SoongBuildMetrics = metrics
+}
+
type CriticalUserJourneysMetrics struct {
cujs soong_metrics_proto.CriticalUserJourneysMetrics
}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 3986d0e..a39d1a8 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -197,10 +197,11 @@
// The metrics for calling Ninja.
NinjaRuns []*PerfInfo `protobuf:"bytes,20,rep,name=ninja_runs,json=ninjaRuns" json:"ninja_runs,omitempty"`
// The metrics for the whole build
- Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
- XXX_NoUnkeyedLiteral struct{} `json:"-"`
- XXX_unrecognized []byte `json:"-"`
- XXX_sizecache int32 `json:"-"`
+ Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"`
+ SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
func (m *MetricsBase) Reset() { *m = MetricsBase{} }
@@ -380,6 +381,13 @@
return nil
}
+func (m *MetricsBase) GetSoongBuildMetrics() *SoongBuildMetrics {
+ if m != nil {
+ return m.SoongBuildMetrics
+ }
+ return nil
+}
+
type PerfInfo struct {
// The description for the phase/action/part while the tool running.
Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
@@ -607,6 +615,82 @@
return nil
}
+type SoongBuildMetrics struct {
+ // The number of modules handled by soong_build.
+ Modules *uint32 `protobuf:"varint,1,opt,name=modules" json:"modules,omitempty"`
+ // The total number of variants handled by soong_build.
+ Variants *uint32 `protobuf:"varint,2,opt,name=variants" json:"variants,omitempty"`
+ // The total number of allocations in soong_build.
+ TotalAllocCount *uint64 `protobuf:"varint,3,opt,name=total_alloc_count,json=totalAllocCount" json:"total_alloc_count,omitempty"`
+ // The total size of allocations in soong_build in bytes.
+ TotalAllocSize *uint64 `protobuf:"varint,4,opt,name=total_alloc_size,json=totalAllocSize" json:"total_alloc_size,omitempty"`
+ // The approximate maximum size of the heap in soong_build in bytes.
+ MaxHeapSize *uint64 `protobuf:"varint,5,opt,name=max_heap_size,json=maxHeapSize" json:"max_heap_size,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SoongBuildMetrics) Reset() { *m = SoongBuildMetrics{} }
+func (m *SoongBuildMetrics) String() string { return proto.CompactTextString(m) }
+func (*SoongBuildMetrics) ProtoMessage() {}
+func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
+ return fileDescriptor_6039342a2ba47b72, []int{5}
+}
+
+func (m *SoongBuildMetrics) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SoongBuildMetrics.Unmarshal(m, b)
+}
+func (m *SoongBuildMetrics) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SoongBuildMetrics.Marshal(b, m, deterministic)
+}
+func (m *SoongBuildMetrics) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SoongBuildMetrics.Merge(m, src)
+}
+func (m *SoongBuildMetrics) XXX_Size() int {
+ return xxx_messageInfo_SoongBuildMetrics.Size(m)
+}
+func (m *SoongBuildMetrics) XXX_DiscardUnknown() {
+ xxx_messageInfo_SoongBuildMetrics.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoongBuildMetrics proto.InternalMessageInfo
+
+func (m *SoongBuildMetrics) GetModules() uint32 {
+ if m != nil && m.Modules != nil {
+ return *m.Modules
+ }
+ return 0
+}
+
+func (m *SoongBuildMetrics) GetVariants() uint32 {
+ if m != nil && m.Variants != nil {
+ return *m.Variants
+ }
+ return 0
+}
+
+func (m *SoongBuildMetrics) GetTotalAllocCount() uint64 {
+ if m != nil && m.TotalAllocCount != nil {
+ return *m.TotalAllocCount
+ }
+ return 0
+}
+
+func (m *SoongBuildMetrics) GetTotalAllocSize() uint64 {
+ if m != nil && m.TotalAllocSize != nil {
+ return *m.TotalAllocSize
+ }
+ return 0
+}
+
+func (m *SoongBuildMetrics) GetMaxHeapSize() uint64 {
+ if m != nil && m.MaxHeapSize != nil {
+ return *m.MaxHeapSize
+ }
+ return 0
+}
+
func init() {
proto.RegisterEnum("soong_build_metrics.MetricsBase_BuildVariant", MetricsBase_BuildVariant_name, MetricsBase_BuildVariant_value)
proto.RegisterEnum("soong_build_metrics.MetricsBase_Arch", MetricsBase_Arch_name, MetricsBase_Arch_value)
@@ -616,63 +700,72 @@
proto.RegisterType((*ModuleTypeInfo)(nil), "soong_build_metrics.ModuleTypeInfo")
proto.RegisterType((*CriticalUserJourneyMetrics)(nil), "soong_build_metrics.CriticalUserJourneyMetrics")
proto.RegisterType((*CriticalUserJourneysMetrics)(nil), "soong_build_metrics.CriticalUserJourneysMetrics")
+ proto.RegisterType((*SoongBuildMetrics)(nil), "soong_build_metrics.SoongBuildMetrics")
}
func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) }
var fileDescriptor_6039342a2ba47b72 = []byte{
- // 847 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdd, 0x6e, 0xdb, 0x36,
- 0x14, 0xae, 0x12, 0x25, 0xb6, 0x8e, 0x62, 0x57, 0x65, 0x52, 0x54, 0x5d, 0x11, 0xcc, 0x10, 0xd6,
- 0x21, 0x17, 0xab, 0x5b, 0x78, 0x45, 0x50, 0x18, 0xc5, 0x80, 0xc4, 0x31, 0x8a, 0x2e, 0xb0, 0x5d,
- 0x28, 0x71, 0x57, 0x6c, 0x17, 0x02, 0x23, 0xd1, 0x8d, 0x3a, 0x4b, 0x14, 0x48, 0xaa, 0x98, 0x1f,
- 0x62, 0x0f, 0xb9, 0x8b, 0xbd, 0xc7, 0xc0, 0x43, 0xc9, 0x51, 0x00, 0x0f, 0x09, 0x7a, 0x47, 0x9d,
- 0xef, 0x87, 0xdf, 0xa1, 0xc4, 0x23, 0xe8, 0x64, 0x4c, 0x89, 0x34, 0x96, 0xfd, 0x42, 0x70, 0xc5,
- 0xc9, 0xbe, 0xe4, 0x3c, 0xff, 0x1c, 0x5d, 0x95, 0xe9, 0x32, 0x89, 0x2a, 0x28, 0xf8, 0xc7, 0x01,
- 0x77, 0x62, 0xd6, 0xa7, 0x54, 0x32, 0xf2, 0x0a, 0x0e, 0x0c, 0x21, 0xa1, 0x8a, 0x45, 0x2a, 0xcd,
- 0x98, 0x54, 0x34, 0x2b, 0x7c, 0xab, 0x67, 0x1d, 0x6d, 0x87, 0x04, 0xb1, 0x33, 0xaa, 0xd8, 0x65,
- 0x8d, 0x90, 0xa7, 0xd0, 0x36, 0x8a, 0x34, 0xf1, 0xb7, 0x7a, 0xd6, 0x91, 0x13, 0xb6, 0xf0, 0xf9,
- 0x7d, 0x42, 0x86, 0xf0, 0xb4, 0x58, 0x52, 0xb5, 0xe0, 0x22, 0x8b, 0xbe, 0x32, 0x21, 0x53, 0x9e,
- 0x47, 0x31, 0x4f, 0x58, 0x4e, 0x33, 0xe6, 0x6f, 0x23, 0xf7, 0x49, 0x4d, 0xf8, 0x68, 0xf0, 0x51,
- 0x05, 0x93, 0xe7, 0xd0, 0x55, 0x54, 0x7c, 0x66, 0x2a, 0x2a, 0x04, 0x4f, 0xca, 0x58, 0xf9, 0x36,
- 0x0a, 0x3a, 0xa6, 0xfa, 0xc1, 0x14, 0x49, 0x02, 0x07, 0x15, 0xcd, 0x84, 0xf8, 0x4a, 0x45, 0x4a,
- 0x73, 0xe5, 0xef, 0xf4, 0xac, 0xa3, 0xee, 0xe0, 0x45, 0x7f, 0x43, 0xcf, 0xfd, 0x46, 0xbf, 0xfd,
- 0x53, 0x8d, 0x7c, 0x34, 0xa2, 0xe1, 0xf6, 0x78, 0xfa, 0x2e, 0x24, 0xc6, 0xaf, 0x09, 0x90, 0x19,
- 0xb8, 0xd5, 0x2e, 0x54, 0xc4, 0xd7, 0xfe, 0x2e, 0x9a, 0x3f, 0xbf, 0xd3, 0xfc, 0x44, 0xc4, 0xd7,
- 0xc3, 0xd6, 0x7c, 0x7a, 0x3e, 0x9d, 0xfd, 0x36, 0x0d, 0xc1, 0x58, 0xe8, 0x22, 0xe9, 0xc3, 0x7e,
- 0xc3, 0x70, 0x9d, 0xba, 0x85, 0x2d, 0x3e, 0xba, 0x21, 0xd6, 0x01, 0x7e, 0x82, 0x2a, 0x56, 0x14,
- 0x17, 0xe5, 0x9a, 0xde, 0x46, 0xba, 0x67, 0x90, 0x51, 0x51, 0xd6, 0xec, 0x73, 0x70, 0xae, 0xb9,
- 0xac, 0xc2, 0x3a, 0xdf, 0x14, 0xb6, 0xad, 0x0d, 0x30, 0x6a, 0x08, 0x1d, 0x34, 0x1b, 0xe4, 0x89,
- 0x31, 0x84, 0x6f, 0x32, 0x74, 0xb5, 0xc9, 0x20, 0x4f, 0xd0, 0xf3, 0x09, 0xb4, 0xd0, 0x93, 0x4b,
- 0xdf, 0xc5, 0x1e, 0x76, 0xf5, 0xe3, 0x4c, 0x92, 0xa0, 0xda, 0x8c, 0xcb, 0x88, 0xfd, 0xa5, 0x04,
- 0xf5, 0xf7, 0x10, 0x76, 0x0d, 0x3c, 0xd6, 0xa5, 0x35, 0x27, 0x16, 0x5c, 0x4a, 0x6d, 0xd1, 0xb9,
- 0xe1, 0x8c, 0x74, 0x6d, 0x26, 0xc9, 0x8f, 0xf0, 0xb0, 0xc1, 0xc1, 0xd8, 0x5d, 0xf3, 0xf9, 0xac,
- 0x59, 0x18, 0xe4, 0x05, 0xec, 0x37, 0x78, 0xeb, 0x16, 0x1f, 0x9a, 0x83, 0x5d, 0x73, 0x1b, 0xb9,
- 0x79, 0xa9, 0xa2, 0x24, 0x15, 0xbe, 0x67, 0x72, 0xf3, 0x52, 0x9d, 0xa5, 0x82, 0xfc, 0x02, 0xae,
- 0x64, 0xaa, 0x2c, 0x22, 0xc5, 0xf9, 0x52, 0xfa, 0x8f, 0x7a, 0xdb, 0x47, 0xee, 0xe0, 0x70, 0xe3,
- 0x11, 0x7d, 0x60, 0x62, 0xf1, 0x3e, 0x5f, 0xf0, 0x10, 0x50, 0x71, 0xa9, 0x05, 0x64, 0x08, 0xce,
- 0x9f, 0x54, 0xa5, 0x91, 0x28, 0x73, 0xe9, 0x93, 0xfb, 0xa8, 0xdb, 0x9a, 0x1f, 0x96, 0xb9, 0x24,
- 0x6f, 0x01, 0x0c, 0x13, 0xc5, 0xfb, 0xf7, 0x11, 0x3b, 0x88, 0xd6, 0xea, 0x3c, 0xcd, 0xbf, 0x50,
- 0xa3, 0x3e, 0xb8, 0x97, 0x1a, 0x05, 0xa8, 0xfe, 0x19, 0x76, 0x14, 0x57, 0x74, 0xe9, 0x3f, 0xee,
- 0x59, 0x77, 0x0b, 0x0d, 0x37, 0x78, 0x05, 0x7b, 0xb7, 0x6e, 0x57, 0x1b, 0xec, 0xf9, 0xc5, 0x38,
- 0xf4, 0x1e, 0x90, 0x0e, 0x38, 0x7a, 0x75, 0x36, 0x3e, 0x9d, 0xbf, 0xf3, 0x2c, 0xd2, 0x02, 0x7d,
- 0x23, 0xbd, 0xad, 0xe0, 0x2d, 0xd8, 0x78, 0xfe, 0x2e, 0xd4, 0xdf, 0x93, 0xf7, 0x40, 0xa3, 0x27,
- 0xe1, 0xc4, 0xb3, 0x88, 0x03, 0x3b, 0x27, 0xe1, 0xe4, 0xf8, 0xb5, 0xb7, 0xa5, 0x6b, 0x9f, 0xde,
- 0x1c, 0x7b, 0xdb, 0x04, 0x60, 0xf7, 0xd3, 0x9b, 0xe3, 0xe8, 0xf8, 0xb5, 0x67, 0x07, 0x7f, 0x5b,
- 0xd0, 0xae, 0x33, 0x10, 0x02, 0x76, 0xc2, 0x64, 0x8c, 0x03, 0xcd, 0x09, 0x71, 0xad, 0x6b, 0x38,
- 0x92, 0xcc, 0xf8, 0xc2, 0x35, 0x39, 0x04, 0x90, 0x8a, 0x0a, 0x85, 0x33, 0x10, 0x87, 0x95, 0x1d,
- 0x3a, 0x58, 0xd1, 0xa3, 0x8f, 0x3c, 0x03, 0x47, 0x30, 0xba, 0x34, 0xa8, 0x8d, 0x68, 0x5b, 0x17,
- 0x10, 0x3c, 0x04, 0xc8, 0x58, 0xc6, 0xc5, 0x2a, 0x2a, 0x25, 0xc3, 0x51, 0x64, 0x87, 0x8e, 0xa9,
- 0xcc, 0x25, 0x0b, 0xfe, 0xb5, 0xa0, 0x3b, 0xe1, 0x49, 0xb9, 0x64, 0x97, 0xab, 0x82, 0x61, 0xaa,
- 0x3f, 0x60, 0xcf, 0x9c, 0x99, 0x5c, 0x49, 0xc5, 0x32, 0x4c, 0xd7, 0x1d, 0xbc, 0xdc, 0x7c, 0xc7,
- 0x6e, 0x49, 0xcd, 0x04, 0xbb, 0x40, 0x59, 0xe3, 0xb6, 0x5d, 0xdd, 0x54, 0xc9, 0xf7, 0xe0, 0x66,
- 0xa8, 0x89, 0xd4, 0xaa, 0xa8, 0xbb, 0x84, 0x6c, 0x6d, 0x43, 0x7e, 0x80, 0x6e, 0x5e, 0x66, 0x11,
- 0x5f, 0x44, 0xa6, 0x28, 0xb1, 0xdf, 0x4e, 0xb8, 0x97, 0x97, 0xd9, 0x6c, 0x61, 0xf6, 0x93, 0xc1,
- 0x4b, 0x70, 0x1b, 0x7b, 0xdd, 0x7e, 0x17, 0x0e, 0xec, 0x5c, 0xcc, 0x66, 0x53, 0xfd, 0xd2, 0xda,
- 0x60, 0x4f, 0x4e, 0xce, 0xc7, 0xde, 0x56, 0xb0, 0x84, 0xef, 0x46, 0x22, 0x55, 0x69, 0x4c, 0x97,
- 0x73, 0xc9, 0xc4, 0xaf, 0xbc, 0x14, 0x39, 0x5b, 0x55, 0x23, 0x62, 0x7d, 0xe8, 0x56, 0xe3, 0xd0,
- 0x87, 0xd0, 0xaa, 0xba, 0xc4, 0x94, 0xee, 0xa0, 0x77, 0xd7, 0x94, 0x09, 0x6b, 0x41, 0x70, 0x05,
- 0xcf, 0x36, 0xec, 0x26, 0xeb, 0xed, 0x46, 0x60, 0xc7, 0xe5, 0x17, 0xe9, 0x5b, 0xf8, 0x85, 0x6f,
- 0x3e, 0xd9, 0xff, 0x4f, 0x1b, 0xa2, 0xf8, 0xf4, 0xf1, 0xef, 0xd5, 0x4f, 0xb4, 0x52, 0x44, 0xf8,
- 0x67, 0xfd, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xbd, 0xe2, 0xb1, 0x69, 0x07, 0x00, 0x00,
+ // 962 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xef, 0x4e, 0xdc, 0x46,
+ 0x10, 0x8f, 0xe1, 0xe0, 0xce, 0x63, 0xee, 0x30, 0x0b, 0x69, 0x9c, 0x44, 0xa8, 0x27, 0xab, 0x89,
+ 0x50, 0xd5, 0x90, 0x88, 0x46, 0x28, 0x42, 0x51, 0x25, 0x38, 0x50, 0x9a, 0x22, 0xb8, 0xc8, 0xfc,
+ 0x69, 0xd4, 0x7e, 0x58, 0x2d, 0xf6, 0x12, 0x9c, 0xda, 0x5e, 0x6b, 0x77, 0x1d, 0x41, 0xde, 0xa1,
+ 0x0f, 0xd4, 0xcf, 0x7d, 0x96, 0xbe, 0x47, 0xb5, 0xb3, 0xf6, 0x61, 0xda, 0x8b, 0x40, 0xf9, 0x66,
+ 0xcf, 0xef, 0xcf, 0xce, 0xac, 0x67, 0xe6, 0x0e, 0xfa, 0x39, 0xd7, 0x32, 0x8d, 0xd5, 0x7a, 0x29,
+ 0x85, 0x16, 0x64, 0x59, 0x09, 0x51, 0x7c, 0xa0, 0x67, 0x55, 0x9a, 0x25, 0xb4, 0x86, 0xc2, 0xbf,
+ 0x00, 0xbc, 0x03, 0xfb, 0xbc, 0xc3, 0x14, 0x27, 0x2f, 0x60, 0xc5, 0x12, 0x12, 0xa6, 0x39, 0xd5,
+ 0x69, 0xce, 0x95, 0x66, 0x79, 0x19, 0x38, 0x43, 0x67, 0x6d, 0x36, 0x22, 0x88, 0xed, 0x32, 0xcd,
+ 0x8f, 0x1b, 0x84, 0x3c, 0x84, 0x9e, 0x55, 0xa4, 0x49, 0x30, 0x33, 0x74, 0xd6, 0xdc, 0xa8, 0x8b,
+ 0xef, 0x6f, 0x13, 0xb2, 0x05, 0x0f, 0xcb, 0x8c, 0xe9, 0x73, 0x21, 0x73, 0xfa, 0x89, 0x4b, 0x95,
+ 0x8a, 0x82, 0xc6, 0x22, 0xe1, 0x05, 0xcb, 0x79, 0x30, 0x8b, 0xdc, 0x07, 0x0d, 0xe1, 0xd4, 0xe2,
+ 0xa3, 0x1a, 0x26, 0x4f, 0x60, 0xa0, 0x99, 0xfc, 0xc0, 0x35, 0x2d, 0xa5, 0x48, 0xaa, 0x58, 0x07,
+ 0x1d, 0x14, 0xf4, 0x6d, 0xf4, 0x9d, 0x0d, 0x92, 0x04, 0x56, 0x6a, 0x9a, 0x4d, 0xe2, 0x13, 0x93,
+ 0x29, 0x2b, 0x74, 0x30, 0x37, 0x74, 0xd6, 0x06, 0x1b, 0xcf, 0xd6, 0xa7, 0xd4, 0xbc, 0xde, 0xaa,
+ 0x77, 0x7d, 0xc7, 0x20, 0xa7, 0x56, 0xb4, 0x35, 0xbb, 0x77, 0xf8, 0x26, 0x22, 0xd6, 0xaf, 0x0d,
+ 0x90, 0x31, 0x78, 0xf5, 0x29, 0x4c, 0xc6, 0x17, 0xc1, 0x3c, 0x9a, 0x3f, 0xb9, 0xd5, 0x7c, 0x5b,
+ 0xc6, 0x17, 0x5b, 0xdd, 0x93, 0xc3, 0xfd, 0xc3, 0xf1, 0xaf, 0x87, 0x11, 0x58, 0x0b, 0x13, 0x24,
+ 0xeb, 0xb0, 0xdc, 0x32, 0x9c, 0x64, 0xdd, 0xc5, 0x12, 0x97, 0xae, 0x89, 0x4d, 0x02, 0x3f, 0x40,
+ 0x9d, 0x16, 0x8d, 0xcb, 0x6a, 0x42, 0xef, 0x21, 0xdd, 0xb7, 0xc8, 0xa8, 0xac, 0x1a, 0xf6, 0x3e,
+ 0xb8, 0x17, 0x42, 0xd5, 0xc9, 0xba, 0x5f, 0x95, 0x6c, 0xcf, 0x18, 0x60, 0xaa, 0x11, 0xf4, 0xd1,
+ 0x6c, 0xa3, 0x48, 0xac, 0x21, 0x7c, 0x95, 0xa1, 0x67, 0x4c, 0x36, 0x8a, 0x04, 0x3d, 0x1f, 0x40,
+ 0x17, 0x3d, 0x85, 0x0a, 0x3c, 0xac, 0x61, 0xde, 0xbc, 0x8e, 0x15, 0x09, 0xeb, 0xc3, 0x84, 0xa2,
+ 0xfc, 0x52, 0x4b, 0x16, 0x2c, 0x20, 0xec, 0x59, 0x78, 0xcf, 0x84, 0x26, 0x9c, 0x58, 0x0a, 0xa5,
+ 0x8c, 0x45, 0xff, 0x9a, 0x33, 0x32, 0xb1, 0xb1, 0x22, 0x4f, 0x61, 0xb1, 0xc5, 0xc1, 0xb4, 0x07,
+ 0xb6, 0x7d, 0x26, 0x2c, 0x4c, 0xe4, 0x19, 0x2c, 0xb7, 0x78, 0x93, 0x12, 0x17, 0xed, 0xc5, 0x4e,
+ 0xb8, 0xad, 0xbc, 0x45, 0xa5, 0x69, 0x92, 0xca, 0xc0, 0xb7, 0x79, 0x8b, 0x4a, 0xef, 0xa6, 0x92,
+ 0xfc, 0x04, 0x9e, 0xe2, 0xba, 0x2a, 0xa9, 0x16, 0x22, 0x53, 0xc1, 0xd2, 0x70, 0x76, 0xcd, 0xdb,
+ 0x58, 0x9d, 0x7a, 0x45, 0xef, 0xb8, 0x3c, 0x7f, 0x5b, 0x9c, 0x8b, 0x08, 0x50, 0x71, 0x6c, 0x04,
+ 0x64, 0x0b, 0xdc, 0x3f, 0x98, 0x4e, 0xa9, 0xac, 0x0a, 0x15, 0x90, 0xbb, 0xa8, 0x7b, 0x86, 0x1f,
+ 0x55, 0x85, 0x22, 0xaf, 0x01, 0x2c, 0x13, 0xc5, 0xcb, 0x77, 0x11, 0xbb, 0x88, 0x36, 0xea, 0x22,
+ 0x2d, 0x3e, 0x32, 0xab, 0x5e, 0xb9, 0x93, 0x1a, 0x05, 0xa8, 0xfe, 0x11, 0xe6, 0xb4, 0xd0, 0x2c,
+ 0x0b, 0xee, 0x0f, 0x9d, 0xdb, 0x85, 0x96, 0x4b, 0x4e, 0x61, 0xda, 0x2a, 0x0a, 0xbe, 0x41, 0x8b,
+ 0xa7, 0x53, 0x2d, 0x8e, 0x4c, 0x0c, 0x47, 0xb2, 0xee, 0xb0, 0x68, 0x49, 0xfd, 0x37, 0x14, 0xbe,
+ 0x80, 0x85, 0x1b, 0x53, 0xdb, 0x83, 0xce, 0xc9, 0xd1, 0x5e, 0xe4, 0xdf, 0x23, 0x7d, 0x70, 0xcd,
+ 0xd3, 0xee, 0xde, 0xce, 0xc9, 0x1b, 0xdf, 0x21, 0x5d, 0x30, 0x93, 0xee, 0xcf, 0x84, 0xaf, 0xa1,
+ 0x83, 0xdf, 0xd5, 0x83, 0xa6, 0x4f, 0xfd, 0x7b, 0x06, 0xdd, 0x8e, 0x0e, 0x7c, 0x87, 0xb8, 0x30,
+ 0xb7, 0x1d, 0x1d, 0x6c, 0xbe, 0xf4, 0x67, 0x4c, 0xec, 0xfd, 0xab, 0x4d, 0x7f, 0x96, 0x00, 0xcc,
+ 0xbf, 0x7f, 0xb5, 0x49, 0x37, 0x5f, 0xfa, 0x9d, 0xf0, 0x4f, 0x07, 0x7a, 0x4d, 0x6d, 0x84, 0x40,
+ 0x27, 0xe1, 0x2a, 0xc6, 0x45, 0xe9, 0x46, 0xf8, 0x6c, 0x62, 0xb8, 0xea, 0xec, 0x5a, 0xc4, 0x67,
+ 0xb2, 0x0a, 0xa0, 0x34, 0x93, 0x1a, 0x77, 0x2b, 0x2e, 0xc1, 0x4e, 0xe4, 0x62, 0xc4, 0xac, 0x54,
+ 0xf2, 0x18, 0x5c, 0xc9, 0x59, 0x66, 0xd1, 0x0e, 0xa2, 0x3d, 0x13, 0x40, 0x70, 0x15, 0x20, 0xe7,
+ 0xb9, 0x90, 0x57, 0xb4, 0x52, 0x1c, 0x57, 0x5c, 0x27, 0x72, 0x6d, 0xe4, 0x44, 0xf1, 0xf0, 0x1f,
+ 0x07, 0x06, 0x07, 0x22, 0xa9, 0x32, 0x7e, 0x7c, 0x55, 0x72, 0xcc, 0xea, 0x77, 0x58, 0xb0, 0x17,
+ 0xa9, 0xae, 0x94, 0xe6, 0x39, 0x66, 0x37, 0xd8, 0x78, 0x3e, 0x7d, 0x76, 0x6f, 0x48, 0xed, 0x66,
+ 0x3c, 0x42, 0x59, 0x6b, 0x8a, 0xcf, 0xae, 0xa3, 0xe4, 0x5b, 0xf0, 0x72, 0xd4, 0x50, 0x7d, 0x55,
+ 0x36, 0x55, 0x42, 0x3e, 0xb1, 0x21, 0xdf, 0xc1, 0xa0, 0xa8, 0x72, 0x2a, 0xce, 0xa9, 0x0d, 0x2a,
+ 0xac, 0xb7, 0x1f, 0x2d, 0x14, 0x55, 0x3e, 0x3e, 0xb7, 0xe7, 0xa9, 0xf0, 0x39, 0x78, 0xad, 0xb3,
+ 0x6e, 0x7e, 0x0b, 0x17, 0xe6, 0x8e, 0xc6, 0xe3, 0x43, 0xf3, 0xd1, 0x7a, 0xd0, 0x39, 0xd8, 0xde,
+ 0xdf, 0xf3, 0x67, 0xc2, 0x0c, 0x1e, 0x8d, 0x64, 0xaa, 0xd3, 0x98, 0x65, 0x27, 0x8a, 0xcb, 0x5f,
+ 0x44, 0x25, 0x0b, 0x7e, 0x55, 0x77, 0xc1, 0xe4, 0xd2, 0x9d, 0xd6, 0xa5, 0x6f, 0x41, 0xb7, 0xe9,
+ 0xb2, 0x19, 0xec, 0xb2, 0xe1, 0x6d, 0xdb, 0x2b, 0x6a, 0x04, 0xe1, 0x19, 0x3c, 0x9e, 0x72, 0x9a,
+ 0x6a, 0x8e, 0x1b, 0x41, 0x27, 0xae, 0x3e, 0xaa, 0xc0, 0xc1, 0xc9, 0x99, 0x7e, 0xb3, 0x5f, 0xce,
+ 0x36, 0x42, 0x71, 0xf8, 0xb7, 0x03, 0x4b, 0xff, 0x6b, 0x71, 0x12, 0x40, 0xb7, 0xb9, 0x37, 0x07,
+ 0xef, 0xad, 0x79, 0x25, 0x8f, 0xa0, 0x57, 0xff, 0x06, 0xd8, 0x82, 0xfa, 0xd1, 0xe4, 0x9d, 0x7c,
+ 0x0f, 0x4b, 0x38, 0x66, 0x94, 0x65, 0x99, 0x88, 0x69, 0x2c, 0xaa, 0x42, 0xd7, 0x7d, 0xb6, 0x88,
+ 0xc0, 0xb6, 0x89, 0x8f, 0x4c, 0x98, 0xac, 0x81, 0xdf, 0xe6, 0xaa, 0xf4, 0x73, 0xd3, 0x74, 0x83,
+ 0x6b, 0xea, 0x51, 0xfa, 0x99, 0x9b, 0xa5, 0x9b, 0xb3, 0x4b, 0x7a, 0xc1, 0x59, 0x69, 0x69, 0xb6,
+ 0xfb, 0xbc, 0x9c, 0x5d, 0xfe, 0xcc, 0x59, 0x69, 0x38, 0x3b, 0xf7, 0x7f, 0xab, 0xe7, 0xba, 0xae,
+ 0x9b, 0xe2, 0xff, 0x8e, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x2a, 0x36, 0xe3, 0x87, 0x08,
+ 0x00, 0x00,
}
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 194aa6b..50810eb 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -92,6 +92,8 @@
// The metrics for the whole build
optional PerfInfo total = 21;
+
+ optional SoongBuildMetrics soong_build_metrics = 22;
}
message PerfInfo {
@@ -140,4 +142,21 @@
message CriticalUserJourneysMetrics {
// A set of metrics from a run of the critical user journey tests.
repeated CriticalUserJourneyMetrics cujs = 1;
+}
+
+message SoongBuildMetrics {
+ // The number of modules handled by soong_build.
+ optional uint32 modules = 1;
+
+ // The total number of variants handled by soong_build.
+ optional uint32 variants = 2;
+
+ // The total number of allocations in soong_build.
+ optional uint64 total_alloc_count = 3;
+
+ // The total size of allocations in soong_build in bytes.
+ optional uint64 total_alloc_size = 4;
+
+ // The approximate maximum size of the heap in soong_build in bytes.
+ optional uint64 max_heap_size = 5;
}
\ No newline at end of file
diff --git a/ui/metrics/upload_proto/regen.sh b/ui/metrics/upload_proto/regen.sh
new file mode 100755
index 0000000..4521df7
--- /dev/null
+++ b/ui/metrics/upload_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of upload.proto file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. upload.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/upload_proto/upload.pb.go b/ui/metrics/upload_proto/upload.pb.go
new file mode 100644
index 0000000..1b1e5e8
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.pb.go
@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: upload.proto
+
+package soong_metrics_upload_proto
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Upload struct {
+ // The timestamp in milliseconds that the build was created.
+ CreationTimestampMs *uint64 `protobuf:"varint,1,opt,name=creation_timestamp_ms,json=creationTimestampMs" json:"creation_timestamp_ms,omitempty"`
+ // The timestamp in milliseconds when the build was completed.
+ CompletionTimestampMs *uint64 `protobuf:"varint,2,opt,name=completion_timestamp_ms,json=completionTimestampMs" json:"completion_timestamp_ms,omitempty"`
+ // The branch name.
+ BranchName *string `protobuf:"bytes,3,opt,name=branch_name,json=branchName" json:"branch_name,omitempty"`
+ // The target name.
+ TargetName *string `protobuf:"bytes,4,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // A list of metrics filepaths to upload.
+ MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Upload) Reset() { *m = Upload{} }
+func (m *Upload) String() string { return proto.CompactTextString(m) }
+func (*Upload) ProtoMessage() {}
+func (*Upload) Descriptor() ([]byte, []int) {
+ return fileDescriptor_91b94b655bd2a7e5, []int{0}
+}
+
+func (m *Upload) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Upload.Unmarshal(m, b)
+}
+func (m *Upload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Upload.Marshal(b, m, deterministic)
+}
+func (m *Upload) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Upload.Merge(m, src)
+}
+func (m *Upload) XXX_Size() int {
+ return xxx_messageInfo_Upload.Size(m)
+}
+func (m *Upload) XXX_DiscardUnknown() {
+ xxx_messageInfo_Upload.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Upload proto.InternalMessageInfo
+
+func (m *Upload) GetCreationTimestampMs() uint64 {
+ if m != nil && m.CreationTimestampMs != nil {
+ return *m.CreationTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetCompletionTimestampMs() uint64 {
+ if m != nil && m.CompletionTimestampMs != nil {
+ return *m.CompletionTimestampMs
+ }
+ return 0
+}
+
+func (m *Upload) GetBranchName() string {
+ if m != nil && m.BranchName != nil {
+ return *m.BranchName
+ }
+ return ""
+}
+
+func (m *Upload) GetTargetName() string {
+ if m != nil && m.TargetName != nil {
+ return *m.TargetName
+ }
+ return ""
+}
+
+func (m *Upload) GetMetricsFiles() []string {
+ if m != nil {
+ return m.MetricsFiles
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Upload)(nil), "soong_metrics_upload.Upload")
+}
+
+func init() {
+ proto.RegisterFile("upload.proto", fileDescriptor_91b94b655bd2a7e5)
+}
+
+var fileDescriptor_91b94b655bd2a7e5 = []byte{
+ // 201 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2d, 0xc8, 0xc9,
+ 0x4f, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x29, 0xce, 0xcf, 0xcf, 0x4b, 0x8f,
+ 0xcf, 0x4d, 0x2d, 0x29, 0xca, 0x4c, 0x2e, 0x8e, 0x87, 0xc8, 0x29, 0xdd, 0x66, 0xe4, 0x62, 0x0b,
+ 0x05, 0x33, 0x85, 0x8c, 0xb8, 0x44, 0x93, 0x8b, 0x52, 0x13, 0x4b, 0x32, 0xf3, 0xf3, 0xe2, 0x4b,
+ 0x32, 0x73, 0x53, 0x8b, 0x4b, 0x12, 0x73, 0x0b, 0xe2, 0x73, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35,
+ 0x58, 0x82, 0x84, 0x61, 0x92, 0x21, 0x30, 0x39, 0xdf, 0x62, 0x21, 0x33, 0x2e, 0xf1, 0xe4, 0xfc,
+ 0xdc, 0x82, 0x9c, 0x54, 0x4c, 0x5d, 0x4c, 0x60, 0x5d, 0xa2, 0x08, 0x69, 0x64, 0x7d, 0xf2, 0x5c,
+ 0xdc, 0x49, 0x45, 0x89, 0x79, 0xc9, 0x19, 0xf1, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0xcc, 0x0a, 0x8c,
+ 0x1a, 0x9c, 0x41, 0x5c, 0x10, 0x21, 0xbf, 0xc4, 0xdc, 0x54, 0x90, 0x82, 0x92, 0xc4, 0xa2, 0xf4,
+ 0xd4, 0x12, 0x88, 0x02, 0x16, 0x88, 0x02, 0x88, 0x10, 0x58, 0x81, 0x32, 0x17, 0x2f, 0xcc, 0x2b,
+ 0x69, 0x99, 0x39, 0xa9, 0xc5, 0x12, 0xac, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x3c, 0x50, 0x41, 0x37,
+ 0x90, 0x98, 0x93, 0x4c, 0x94, 0x14, 0x36, 0x5f, 0xc7, 0x83, 0x43, 0x04, 0x10, 0x00, 0x00, 0xff,
+ 0xff, 0xe2, 0x01, 0x74, 0x65, 0x20, 0x01, 0x00, 0x00,
+}
diff --git a/ui/metrics/upload_proto/upload.proto b/ui/metrics/upload_proto/upload.proto
new file mode 100644
index 0000000..7a9f080
--- /dev/null
+++ b/ui/metrics/upload_proto/upload.proto
@@ -0,0 +1,35 @@
+// Copyright 2020 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.
+
+syntax = "proto2";
+
+package soong_metrics_upload;
+option go_package = "soong_metrics_upload_proto";
+
+message Upload {
+ // The timestamp in milliseconds that the build was created.
+ optional uint64 creation_timestamp_ms = 1;
+
+ // The timestamp in milliseconds when the build was completed.
+ optional uint64 completion_timestamp_ms = 2;
+
+ // The branch name.
+ optional string branch_name = 3;
+
+ // The target name.
+ optional string target_name = 4;
+
+ // A list of metrics filepaths to upload.
+ repeated string metrics_files = 5;
+}
diff --git a/ui/status/Android.bp b/ui/status/Android.bp
index ec929b3..19e5a2a 100644
--- a/ui/status/Android.bp
+++ b/ui/status/Android.bp
@@ -20,6 +20,7 @@
"soong-ui-logger",
"soong-ui-status-ninja_frontend",
"soong-ui-status-build_error_proto",
+ "soong-ui-status-build_progress_proto",
],
srcs: [
"critical_path.go",
@@ -53,3 +54,12 @@
"build_error_proto/build_error.pb.go",
],
}
+
+bootstrap_go_package {
+ name: "soong-ui-status-build_progress_proto",
+ pkgPath: "android/soong/ui/status/build_progress_proto",
+ deps: ["golang-protobuf-proto"],
+ srcs: [
+ "build_progress_proto/build_progress.pb.go",
+ ],
+}
diff --git a/ui/status/build_progress_proto/build_progress.pb.go b/ui/status/build_progress_proto/build_progress.pb.go
new file mode 100644
index 0000000..f63c157
--- /dev/null
+++ b/ui/status/build_progress_proto/build_progress.pb.go
@@ -0,0 +1,115 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: build_progress.proto
+
+package soong_build_progress_proto
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type BuildProgress struct {
+ // Total number of actions in a build. The total actions will increase
+ // and might decrease during the course of a build.
+ TotalActions *uint64 `protobuf:"varint,1,opt,name=total_actions,json=totalActions" json:"total_actions,omitempty"`
+ // Total number of completed build actions. This value will never decrease
+ // and finished_actions <= total_actions. At one point of the build, the
+ // finished_actions will be equal to total_actions. This may not represent
+ // that the build is completed as the total_actions may be increased for
+ // additional counted work or is doing non-counted work.
+ FinishedActions *uint64 `protobuf:"varint,2,opt,name=finished_actions,json=finishedActions" json:"finished_actions,omitempty"`
+ // Total number of current actions being executed during a course of a
+ // build and current_actions + finished_actions <= total_actions.
+ CurrentActions *uint64 `protobuf:"varint,3,opt,name=current_actions,json=currentActions" json:"current_actions,omitempty"`
+ // Total number of actions that reported as a failure.
+ FailedActions *uint64 `protobuf:"varint,4,opt,name=failed_actions,json=failedActions" json:"failed_actions,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *BuildProgress) Reset() { *m = BuildProgress{} }
+func (m *BuildProgress) String() string { return proto.CompactTextString(m) }
+func (*BuildProgress) ProtoMessage() {}
+func (*BuildProgress) Descriptor() ([]byte, []int) {
+ return fileDescriptor_a8a463f8e30dab2e, []int{0}
+}
+
+func (m *BuildProgress) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_BuildProgress.Unmarshal(m, b)
+}
+func (m *BuildProgress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_BuildProgress.Marshal(b, m, deterministic)
+}
+func (m *BuildProgress) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_BuildProgress.Merge(m, src)
+}
+func (m *BuildProgress) XXX_Size() int {
+ return xxx_messageInfo_BuildProgress.Size(m)
+}
+func (m *BuildProgress) XXX_DiscardUnknown() {
+ xxx_messageInfo_BuildProgress.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BuildProgress proto.InternalMessageInfo
+
+func (m *BuildProgress) GetTotalActions() uint64 {
+ if m != nil && m.TotalActions != nil {
+ return *m.TotalActions
+ }
+ return 0
+}
+
+func (m *BuildProgress) GetFinishedActions() uint64 {
+ if m != nil && m.FinishedActions != nil {
+ return *m.FinishedActions
+ }
+ return 0
+}
+
+func (m *BuildProgress) GetCurrentActions() uint64 {
+ if m != nil && m.CurrentActions != nil {
+ return *m.CurrentActions
+ }
+ return 0
+}
+
+func (m *BuildProgress) GetFailedActions() uint64 {
+ if m != nil && m.FailedActions != nil {
+ return *m.FailedActions
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*BuildProgress)(nil), "soong_build_progress.BuildProgress")
+}
+
+func init() { proto.RegisterFile("build_progress.proto", fileDescriptor_a8a463f8e30dab2e) }
+
+var fileDescriptor_a8a463f8e30dab2e = []byte{
+ // 165 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x49, 0x2a, 0xcd, 0xcc,
+ 0x49, 0x89, 0x2f, 0x28, 0xca, 0x4f, 0x2f, 0x4a, 0x2d, 0x2e, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
+ 0x17, 0x12, 0x29, 0xce, 0xcf, 0xcf, 0x4b, 0x8f, 0x47, 0x95, 0x53, 0x5a, 0xcf, 0xc8, 0xc5, 0xeb,
+ 0x04, 0x12, 0x0a, 0x80, 0x8a, 0x08, 0x29, 0x73, 0xf1, 0x96, 0xe4, 0x97, 0x24, 0xe6, 0xc4, 0x27,
+ 0x26, 0x97, 0x64, 0xe6, 0xe7, 0x15, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x04, 0xf1, 0x80, 0x05,
+ 0x1d, 0x21, 0x62, 0x42, 0x9a, 0x5c, 0x02, 0x69, 0x99, 0x79, 0x99, 0xc5, 0x19, 0xa9, 0x29, 0x70,
+ 0x75, 0x4c, 0x60, 0x75, 0xfc, 0x30, 0x71, 0x98, 0x52, 0x75, 0x2e, 0xfe, 0xe4, 0xd2, 0xa2, 0xa2,
+ 0xd4, 0xbc, 0x12, 0xb8, 0x4a, 0x66, 0xb0, 0x4a, 0x3e, 0xa8, 0x30, 0x4c, 0xa1, 0x2a, 0x17, 0x5f,
+ 0x5a, 0x62, 0x66, 0x0e, 0x92, 0x89, 0x2c, 0x60, 0x75, 0xbc, 0x10, 0x51, 0xa8, 0x32, 0x27, 0x99,
+ 0x28, 0x29, 0x6c, 0x3e, 0x89, 0x07, 0xfb, 0x12, 0x10, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x6e, 0xc1,
+ 0xef, 0xfc, 0x00, 0x00, 0x00,
+}
diff --git a/ui/status/build_progress_proto/build_progress.proto b/ui/status/build_progress_proto/build_progress.proto
new file mode 100644
index 0000000..d78060a
--- /dev/null
+++ b/ui/status/build_progress_proto/build_progress.proto
@@ -0,0 +1,38 @@
+// Copyright 2020 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.
+
+syntax = "proto2";
+
+package soong_build_progress;
+option go_package = "soong_build_progress_proto";
+
+message BuildProgress {
+ // Total number of actions in a build. The total actions will increase
+ // and might decrease during the course of a build.
+ optional uint64 total_actions = 1;
+
+ // Total number of completed build actions. This value will never decrease
+ // and finished_actions <= total_actions. At one point of the build, the
+ // finished_actions will be equal to total_actions. This may not represent
+ // that the build is completed as the total_actions may be increased for
+ // additional counted work or is doing non-counted work.
+ optional uint64 finished_actions = 2;
+
+ // Total number of current actions being executed during a course of a
+ // build and current_actions + finished_actions <= total_actions.
+ optional uint64 current_actions = 3;
+
+ // Total number of actions that reported as a failure.
+ optional uint64 failed_actions = 4;
+}
diff --git a/ui/status/build_progress_proto/regen.sh b/ui/status/build_progress_proto/regen.sh
new file mode 100755
index 0000000..572785d
--- /dev/null
+++ b/ui/status/build_progress_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of build_completion.proto file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. build_progress.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/status/log.go b/ui/status/log.go
index d407248..4a08acb 100644
--- a/ui/status/log.go
+++ b/ui/status/log.go
@@ -20,12 +20,14 @@
"fmt"
"io"
"io/ioutil"
+ "os"
"strings"
"github.com/golang/protobuf/proto"
"android/soong/ui/logger"
"android/soong/ui/status/build_error_proto"
+ "android/soong/ui/status/build_progress_proto"
)
type verboseLog struct {
@@ -154,6 +156,7 @@
}
func NewProtoErrorLog(log logger.Logger, filename string) StatusOutput {
+ os.Remove(filename)
return &errorProtoLog{
errorProto: soong_build_error_proto.BuildError{},
filename: filename,
@@ -175,20 +178,17 @@
Artifacts: result.Outputs,
Error: proto.String(result.Error.Error()),
})
-}
-func (e *errorProtoLog) Flush() {
- data, err := proto.Marshal(&e.errorProto)
- if err != nil {
- e.log.Printf("Failed to marshal build status proto: %v\n", err)
- return
- }
- err = ioutil.WriteFile(e.filename, []byte(data), 0644)
+ err := writeToFile(&e.errorProto, e.filename)
if err != nil {
e.log.Printf("Failed to write file %s: %v\n", e.filename, err)
}
}
+func (e *errorProtoLog) Flush() {
+ //Not required.
+}
+
func (e *errorProtoLog) Message(level MsgLevel, message string) {
if level > ErrorLvl {
e.errorProto.ErrorMessages = append(e.errorProto.ErrorMessages, message)
@@ -198,3 +198,75 @@
func (e *errorProtoLog) Write(p []byte) (int, error) {
return 0, errors.New("not supported")
}
+
+type buildProgressLog struct {
+ filename string
+ log logger.Logger
+ failedActions uint64
+}
+
+func NewBuildProgressLog(log logger.Logger, filename string) StatusOutput {
+ return &buildProgressLog{
+ filename: filename,
+ log: log,
+ failedActions: 0,
+ }
+}
+
+func (b *buildProgressLog) StartAction(action *Action, counts Counts) {
+ b.updateCounters(counts)
+}
+
+func (b *buildProgressLog) FinishAction(result ActionResult, counts Counts) {
+ if result.Error != nil {
+ b.failedActions++
+ }
+ b.updateCounters(counts)
+}
+
+func (b *buildProgressLog) Flush() {
+ //Not required.
+}
+
+func (b *buildProgressLog) Message(level MsgLevel, message string) {
+ // Not required.
+}
+
+func (b *buildProgressLog) Write(p []byte) (int, error) {
+ return 0, errors.New("not supported")
+}
+
+func (b *buildProgressLog) updateCounters(counts Counts) {
+ err := writeToFile(
+ &soong_build_progress_proto.BuildProgress{
+ CurrentActions: proto.Uint64(uint64(counts.RunningActions)),
+ FinishedActions: proto.Uint64(uint64(counts.FinishedActions)),
+ TotalActions: proto.Uint64(uint64(counts.TotalActions)),
+ FailedActions: proto.Uint64(b.failedActions),
+ },
+ b.filename,
+ )
+ if err != nil {
+ b.log.Printf("Failed to write file %s: %v\n", b.filename, err)
+ }
+}
+
+func writeToFile(pb proto.Message, outputPath string) (err error) {
+ data, err := proto.Marshal(pb)
+ if err != nil {
+ return err
+ }
+
+ tempPath := outputPath + ".tmp"
+ err = ioutil.WriteFile(tempPath, []byte(data), 0644)
+ if err != nil {
+ return err
+ }
+
+ err = os.Rename(tempPath, outputPath)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vnames.go.json b/vnames.go.json
index 5842097..7ce2d4b 100644
--- a/vnames.go.json
+++ b/vnames.go.json
@@ -3,7 +3,7 @@
"pattern": "(.*)",
"vname": {
"corpus": "android.googlesource.com/platform/superproject",
- "path": "build/soong/@1@"
+ "path": "@1@"
}
}
]