Merge "Remove unused arguments in droiddoc"
diff --git a/Android.bp b/Android.bp
index fe776df..97233f5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,6 +132,7 @@
pkgPath: "android/soong/cc/config",
deps: [
"soong-android",
+ "soong-remoteexec",
],
srcs: [
"cc/config/clang.go",
@@ -547,6 +548,22 @@
pluginFor: ["soong_build"],
}
+bootstrap_go_package {
+ name: "soong-remoteexec",
+ pkgPath: "android/soong/remoteexec",
+ deps: [
+ "blueprint",
+ "soong-android",
+ ],
+ srcs: [
+ "remoteexec/remoteexec.go",
+ ],
+ testSrcs: [
+ "remoteexec/remoteexec_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
//
// Defaults to enable various configurations of host bionic
//
diff --git a/apex/apex.go b/apex/apex.go
index fd3fb2b..8463ac1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -836,10 +836,13 @@
// Mark the direct and transitive dependencies of apex bundles so that they
// can be built for the apex bundles.
func apexDepsMutator(mctx android.TopDownMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
var apexBundles []android.ApexInfo
var directDep bool
if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
- apexBundles = []android.ApexInfo{android.ApexInfo{
+ apexBundles = []android.ApexInfo{{
ApexName: mctx.ModuleName(),
MinSdkVersion: a.minSdkVersion(mctx),
}}
@@ -877,6 +880,9 @@
// Create apex variations if a module is included in APEX(s).
func apexMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
am.CreateApexVariations(mctx)
} else if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
@@ -914,6 +920,9 @@
}
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
+ if !mctx.Module().Enabled() {
+ return
+ }
if ab, ok := mctx.Module().(*apexBundle); ok {
var variants []string
switch proptools.StringDefault(ab.properties.Payload_type, "image") {
@@ -1732,15 +1741,16 @@
func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
android.Module
Privileged() bool
+ InstallApkName() string
OutputFile() android.Path
JacocoReportClassesFile() android.Path
Certificate() java.Certificate
-}, pkgName string) apexFile {
+}) apexFile {
appDir := "app"
if aapp.Privileged() {
appDir = "priv-app"
}
- dirInApex := filepath.Join(appDir, pkgName)
+ dirInApex := filepath.Join(appDir, aapp.InstallApkName())
fileToCopy := aapp.OutputFile()
af := newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
@@ -2031,14 +2041,13 @@
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
case androidAppTag:
- pkgName := ctx.DeviceConfig().OverridePackageNameFor(depName)
if ap, ok := child.(*java.AndroidApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
return true // track transitive dependencies
} else if ap, ok := child.(*java.AndroidAppImport); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
+ filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
} else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0c8937e..9f55728 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3438,6 +3438,7 @@
dex_preopt: {
enabled: false,
},
+ filename: "AwesomePrebuiltAppFooPriv.apk",
}
`)
@@ -3446,7 +3447,47 @@
copyCmds := apexRule.Args["copy_commands"]
ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt/AppFooPrebuilt.apk")
- ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AppFooPrivPrebuilt.apk")
+ ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AwesomePrebuiltAppFooPriv.apk")
+}
+
+func TestApexWithAppImportsPrefer(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: [
+ "AppFoo",
+ ],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ android_app_import {
+ name: "AppFoo",
+ apk: "AppFooPrebuilt.apk",
+ filename: "AppFooPrebuilt.apk",
+ presigned: true,
+ prefer: true,
+ }
+ `, withFiles(map[string][]byte{
+ "AppFooPrebuilt.apk": nil,
+ }))
+
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "app/AppFoo/AppFooPrebuilt.apk",
+ })
}
func TestApexWithTestHelperApp(t *testing.T) {
@@ -3779,7 +3820,7 @@
copyCmds := apexRule.Args["copy_commands"]
ensureNotContains(t, copyCmds, "image.apex/app/app/app.apk")
- ensureContains(t, copyCmds, "image.apex/app/app/override_app.apk")
+ ensureContains(t, copyCmds, "image.apex/app/override_app/override_app.apk")
apexBundle := module.Module().(*apexBundle)
name := apexBundle.Name()
@@ -4151,6 +4192,27 @@
})
}
+func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `, func(fs map[string][]byte, config android.Config) {
+ delete(config.Targets, android.Android)
+ config.AndroidCommonTarget = android.Target{}
+ })
+
+ if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
+ t.Errorf("Expected variants: %v, but got: %v", expected, got)
+ }
+}
+
func TestApexWithJniLibs_Errors(t *testing.T) {
testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
apex {
diff --git a/cc/builder.go b/cc/builder.go
index 136263b..d8e90b6 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -29,6 +29,7 @@
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/remoteexec"
)
const (
@@ -62,7 +63,7 @@
},
"ccCmd", "cFlags")
- ld = pctx.AndroidStaticRule("ld",
+ ld, ldRE = remoteexec.StaticRules(pctx, "ld",
blueprint.RuleParams{
Command: "$ldCmd ${crtBegin} @${out}.rsp " +
"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
@@ -72,16 +73,28 @@
// clang -Wl,--out-implib doesn't update its output file if it hasn't changed.
Restat: true,
},
- "ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags")
+ &remoteexec.REParams{Labels: map[string]string{"type": "link", "tool": "clang"},
+ ExecStrategy: "${config.RECXXLinksExecStrategy}",
+ Inputs: []string{"${out}.rsp"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"${out}"},
+ ToolchainInputs: []string{"$ldCmd"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
+ }, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, nil)
- partialLd = pctx.AndroidStaticRule("partialLd",
+ 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}",
CommandDeps: []string{"$ldCmd"},
- },
- "ldCmd", "ldFlags")
+ }, &remoteexec.REParams{
+ Labels: map[string]string{"type": "link", "tool": "clang"},
+ ExecStrategy: "${config.RECXXLinksExecStrategy}", Inputs: []string{"$inCommaList"},
+ OutputFiles: []string{"${out}"},
+ ToolchainInputs: []string{"$ldCmd"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.RECXXLinksPool}"},
+ }, []string{"ldCmd", "ldFlags"}, []string{"inCommaList"})
ar = pctx.AndroidStaticRule("ar",
blueprint.RuleParams{
@@ -262,6 +275,7 @@
}
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.Import("android/soong/remoteexec")
}
type builderFlags struct {
@@ -293,7 +307,7 @@
rsFlags string
toolchain config.Toolchain
tidy bool
- coverage bool
+ gcovCoverage bool
sAbiDump bool
emitXrefs bool
@@ -355,7 +369,7 @@
tidyFiles = make(android.Paths, 0, len(srcFiles))
}
var coverageFiles android.Paths
- if flags.coverage {
+ if flags.gcovCoverage {
coverageFiles = make(android.Paths, 0, len(srcFiles))
}
var kytheFiles android.Paths
@@ -456,7 +470,7 @@
var ccCmd string
tidy := flags.tidy
- coverage := flags.coverage
+ coverage := flags.gcovCoverage
dump := flags.sAbiDump
rule := cc
emitXref := flags.emitXrefs
@@ -657,8 +671,13 @@
deps = append(deps, crtBegin.Path(), crtEnd.Path())
}
+ rule := ld
+ if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
+ rule = ldRE
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: ld,
+ Rule: rule,
Description: "link " + outputFile.Base(),
Output: outputFile,
ImplicitOutputs: implicitOutputs,
@@ -798,16 +817,22 @@
ldCmd := "${config.ClangBin}/clang++"
+ rule := partialLd
+ args := map[string]string{
+ "ldCmd": ldCmd,
+ "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
+ }
+ if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
+ rule = partialLdRE
+ args["inCommaList"] = strings.Join(objFiles.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: partialLd,
+ Rule: rule,
Description: "link " + outputFile.Base(),
Output: outputFile,
Inputs: objFiles,
Implicits: deps,
- Args: map[string]string{
- "ldCmd": ldCmd,
- "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
- },
+ Args: args,
})
}
diff --git a/cc/cc.go b/cc/cc.go
index 0201404..24173ee 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -182,11 +182,11 @@
// These must be after any module include flags, which will be in CommonFlags.
SystemIncludeFlags []string
- Toolchain config.Toolchain
- Tidy bool
- Coverage bool
- SAbiDump bool
- EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
+ Toolchain config.Toolchain
+ Tidy bool
+ GcovCoverage bool
+ SAbiDump bool
+ EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
RequiredInstructionSet string
DynamicLinker string
@@ -213,6 +213,9 @@
// two variants to be built, one for the platform and one for apps.
Sdk_version *string
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ Min_sdk_version *string
+
// If true, always create an sdk variant and don't create a platform variant.
Sdk_variant_only *bool
@@ -1195,6 +1198,11 @@
return false
}
+ // Coverage builds have extra symbols.
+ if ctx.mod.isCoverageVariant() {
+ return false
+ }
+
if ctx.ctx.Fuchsia() {
return false
}
@@ -1901,8 +1909,7 @@
addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
var variations []blueprint.Variation
variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
- versionVariantAvail := !c.InRecovery() && !c.InRamdisk()
- if version != "" && versionVariantAvail {
+ if version != "" && VersionVariantAvailable(c) {
// Version is explicitly specified. i.e. libFoo#30
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
depTag.ExplicitlyVersioned = true
@@ -1912,7 +1919,7 @@
// If the version is not specified, add dependency to all stubs libraries.
// The stubs library will be used when the depending module is built for APEX and
// the dependent module is not in the same APEX.
- if version == "" && versionVariantAvail {
+ if version == "" && VersionVariantAvailable(c) {
for _, ver := range stubsVersionsFor(actx.Config())[name] {
// Note that depTag.ExplicitlyVersioned is false in this case.
actx.AddVariationDependencies([]blueprint.Variation{
@@ -2310,7 +2317,7 @@
}
if ccDep.CcLibrary() && !depIsStatic {
depIsStubs := ccDep.BuildStubs()
- depHasStubs := ccDep.HasStubsVariants()
+ depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants()
depInSameApex := android.DirectlyInApex(c.ApexName(), depName)
depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
@@ -2326,8 +2333,8 @@
// If not building for APEX, use stubs only when it is from
// an APEX (and not from platform)
useThisDep = (depInPlatform != depIsStubs)
- if c.InRamdisk() || c.InRecovery() || c.bootstrap() {
- // However, for ramdisk, recovery or bootstrap modules,
+ if c.bootstrap() {
+ // However, for host, ramdisk, recovery or bootstrap modules,
// always link to non-stub variant
useThisDep = !depIsStubs
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 5611a96..d85ac5f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -18,6 +18,7 @@
"strings"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -255,6 +256,9 @@
}
return ""
})
+
+ pctx.VariableFunc("RECXXLinksPool", envOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
+ pctx.VariableFunc("RECXXLinksExecStrategy", envOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
@@ -268,3 +272,12 @@
"-isystem bionic/libc/kernel/android/uapi",
}, " ")
}
+
+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/cc/coverage.go b/cc/coverage.go
index b94b628..bde07fd 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -82,10 +82,10 @@
}
if cov.Properties.CoverageEnabled {
- flags.Coverage = true
cov.linkCoverage = true
if gcovCoverage {
+ flags.GcovCoverage = true
flags.Local.CommonFlags = append(flags.Local.CommonFlags, "--coverage", "-O0")
// Override -Wframe-larger-than and non-default optimization
diff --git a/cc/library.go b/cc/library.go
index 94fffb9..e79d9bd 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1528,10 +1528,18 @@
}
}
-// Version mutator splits a module into the mandatory non-stubs variant
+func VersionVariantAvailable(module interface {
+ Host() bool
+ InRamdisk() bool
+ InRecovery() bool
+}) bool {
+ return !module.Host() && !module.InRamdisk() && !module.InRecovery()
+}
+
+// VersionMutator splits a module into the mandatory non-stubs variant
// (which is unnamed) and zero or more stubs variants.
func VersionMutator(mctx android.BottomUpMutatorContext) {
- if library, ok := mctx.Module().(LinkableInterface); ok && !library.InRecovery() {
+ if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) {
if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
versions := library.StubsVersions()
checkVersions(mctx, versions)
@@ -1567,7 +1575,7 @@
}
if genrule, ok := mctx.Module().(*genrule.Module); ok {
if _, ok := genrule.Extra.(*GenruleExtraProperties); ok {
- if !genrule.InRecovery() {
+ if VersionVariantAvailable(genrule) {
mctx.CreateVariations("")
return
}
diff --git a/cc/linkable.go b/cc/linkable.go
index fbe61a4..4a70d48 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -39,6 +39,8 @@
Shared() bool
Toc() android.OptionalPath
+ Host() bool
+
InRamdisk() bool
OnlyInRamdisk() bool
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 2ef3195..ac990f3 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -43,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 {
@@ -109,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)
@@ -122,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
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 0b018c1..adb44bd 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -184,7 +184,7 @@
})
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) {
@@ -198,7 +198,7 @@
})
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) {
@@ -221,8 +221,53 @@
})
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/util.go b/cc/util.go
index 60070bb..af26268 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -82,7 +82,7 @@
tidyFlags: strings.Join(in.TidyFlags, " "),
sAbiFlags: strings.Join(in.SAbiFlags, " "),
toolchain: in.Toolchain,
- coverage: in.Coverage,
+ gcovCoverage: in.GcovCoverage,
tidy: in.Tidy,
sAbiDump: in.SAbiDump,
emitXrefs: in.EmitXrefs,
diff --git a/java/androidmk.go b/java/androidmk.go
index bbf2c33..7d57525 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -588,14 +588,12 @@
fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
dstubs.checkLastReleasedApiTimestamp.String())
- if dstubs.Name() != "android.car-system-stubs-docs" {
- fmt.Fprintln(w, ".PHONY: checkapi")
- fmt.Fprintln(w, "checkapi:",
- dstubs.checkLastReleasedApiTimestamp.String())
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ dstubs.checkLastReleasedApiTimestamp.String())
- fmt.Fprintln(w, ".PHONY: droidcore")
- fmt.Fprintln(w, "droidcore: checkapi")
- }
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
}
if dstubs.apiLintTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint")
diff --git a/java/app.go b/java/app.go
index ac5121a..7d509ee 100755
--- a/java/app.go
+++ b/java/app.go
@@ -511,6 +511,10 @@
return certificates
}
+func (a *AndroidApp) InstallApkName() string {
+ return a.installApkName
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
@@ -1134,6 +1138,10 @@
a.generateAndroidBuildActions(ctx)
}
+func (a *AndroidAppImport) InstallApkName() string {
+ return a.BaseModuleName()
+}
+
func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
numCertPropsSet := 0
if String(a.properties.Certificate) != "" {
@@ -1191,6 +1199,8 @@
dexOutput = dexUncompressed
}
+ apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
+
// Sign or align the package
// TODO: Handle EXTERNAL
if !Bool(a.properties.Presigned) {
@@ -1201,11 +1211,11 @@
ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
}
a.certificate = certificates[0]
- signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk")
+ signed := android.PathForModuleOut(ctx, "signed", apkFilename)
SignAppPackage(ctx, signed, dexOutput, certificates, nil)
a.outputFile = signed
} else {
- alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk")
+ alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
TransformZipAlign(ctx, alignedApk, dexOutput)
a.outputFile = alignedApk
a.certificate = presignedCertificate
@@ -1213,8 +1223,7 @@
// TODO: Optionally compress the output apk.
- a.installPath = ctx.InstallFile(installDir,
- proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk"), a.outputFile)
+ a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
// TODO: androidmk converter jni libs
}
diff --git a/java/builder.go b/java/builder.go
index 3a0247d..98f70cd 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -147,7 +147,12 @@
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
- Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JarjarCmd} process $rulesFile $in $out",
+ Command: "${config.JavaCmd} ${config.JavaVmFlags}" +
+ // b/146418363 Enable Android specific jarjar transformer to drop compat annotations
+ // for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
+ // avoids adding new hiddenapis after jarjar'ing.
+ " -DremoveAndroidCompatAnnotations=true" +
+ " -jar ${config.JarjarCmd} process $rulesFile $in $out",
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
"rulesFile")
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
new file mode 100644
index 0000000..d43dc6c
--- /dev/null
+++ b/remoteexec/remoteexec.go
@@ -0,0 +1,155 @@
+// 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 remoteexec
+
+import (
+ "sort"
+ "strings"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+const (
+ // ContainerImageKey is the key identifying the container image in the platform spec.
+ ContainerImageKey = "container-image"
+
+ // PoolKey is the key identifying the pool to use for remote execution.
+ PoolKey = "Pool"
+
+ // DefaultImage is the default container image used for Android remote execution. The
+ // image was built with the Dockerfile at
+ // https://android.googlesource.com/platform/prebuilts/remoteexecution-client/+/refs/heads/master/docker/Dockerfile
+ DefaultImage = "docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62"
+
+ // DefaultWrapperPath is the default path to the remote execution wrapper.
+ DefaultWrapperPath = "prebuilts/remoteexecution-client/live/rewrapper"
+
+ // DefaultPool is the name of the pool to use for remote execution when none is specified.
+ DefaultPool = "default"
+
+ // LocalExecStrategy is the exec strategy to indicate that the action should be run locally.
+ LocalExecStrategy = "local"
+
+ // RemoteExecStrategy is the exec strategy to indicate that the action should be run
+ // remotely.
+ RemoteExecStrategy = "remote"
+
+ // RemoteLocalFallbackExecStrategy is the exec strategy to indicate that the action should
+ // be run remotely and fallback to local execution if remote fails.
+ RemoteLocalFallbackExecStrategy = "remote_local_fallback"
+)
+
+var (
+ defaultLabels = map[string]string{"type": "tool"}
+ defaultExecStrategy = LocalExecStrategy
+ pctx = android.NewPackageContext("android/soong/remoteexec")
+)
+
+// REParams holds information pertinent to the remote execution of a rule.
+type REParams struct {
+ // Platform is the key value pair used for remotely executing the action.
+ Platform map[string]string
+ // Labels is a map of labels that identify the rule.
+ Labels map[string]string
+ // ExecStrategy is the remote execution strategy: remote, local, or remote_local_fallback.
+ ExecStrategy string
+ // Inputs is a list of input paths or ninja variables.
+ Inputs []string
+ // RSPFile is the name of the ninja variable used by the rule as a placeholder for an rsp
+ // input.
+ RSPFile string
+ // OutputFiles is a list of output file paths or ninja variables as placeholders for rule
+ // outputs.
+ OutputFiles []string
+ // ToolchainInputs is a list of paths or ninja variables pointing to the location of
+ // toolchain binaries used by the rule.
+ ToolchainInputs []string
+}
+
+func init() {
+ pctx.VariableFunc("Wrapper", func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv("RBE_WRAPPER"); override != "" {
+ return override
+ }
+ return DefaultWrapperPath
+ })
+}
+
+// Generate the remote execution wrapper template to be added as a prefix to the rule's command.
+func (r *REParams) Template() string {
+ template := "${remoteexec.Wrapper}"
+
+ var kvs []string
+ labels := r.Labels
+ if len(labels) == 0 {
+ labels = defaultLabels
+ }
+ for k, v := range labels {
+ kvs = append(kvs, k+"="+v)
+ }
+ sort.Strings(kvs)
+ template += " --labels=" + strings.Join(kvs, ",")
+
+ var platform []string
+ for k, v := range r.Platform {
+ if v == "" {
+ continue
+ }
+ platform = append(platform, k+"="+v)
+ }
+ if _, ok := r.Platform[ContainerImageKey]; !ok {
+ platform = append(platform, ContainerImageKey+"="+DefaultImage)
+ }
+ if platform != nil {
+ sort.Strings(platform)
+ template += " --platform=\"" + strings.Join(platform, ",") + "\""
+ }
+
+ strategy := r.ExecStrategy
+ if strategy == "" {
+ strategy = defaultExecStrategy
+ }
+ template += " --exec_strategy=" + strategy
+
+ if len(r.Inputs) > 0 {
+ template += " --inputs=" + strings.Join(r.Inputs, ",")
+ }
+
+ if r.RSPFile != "" {
+ template += " --input_list_paths=" + r.RSPFile
+ }
+
+ if len(r.OutputFiles) > 0 {
+ template += " --output_files=" + strings.Join(r.OutputFiles, ",")
+ }
+
+ if len(r.ToolchainInputs) > 0 {
+ template += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
+ }
+
+ return template + " -- "
+}
+
+// StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
+// 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
+
+ return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
+ ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
+}
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
new file mode 100644
index 0000000..30e891c
--- /dev/null
+++ b/remoteexec/remoteexec_test.go
@@ -0,0 +1,83 @@
+// 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 remoteexec
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestTemplate(t *testing.T) {
+ tests := []struct {
+ name string
+ params *REParams
+ want string
+ }{
+ {
+ name: "basic",
+ params: &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ },
+ want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage),
+ },
+ {
+ name: "all params",
+ params: &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ ExecStrategy: "remote",
+ RSPFile: "$out.rsp",
+ ToolchainInputs: []string{"clang++"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ },
+ want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp --output_files=$out --toolchain_inputs=clang++ -- ", DefaultImage),
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ if got := test.params.Template(); got != test.want {
+ t.Errorf("Template() returned\n%s\nwant\n%s", got, test.want)
+ }
+ })
+ }
+}
+
+func TestTemplateDeterminism(t *testing.T) {
+ r := &REParams{
+ Labels: map[string]string{"type": "compile", "lang": "cpp", "compiler": "clang"},
+ Inputs: []string{"$in"},
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{
+ ContainerImageKey: DefaultImage,
+ PoolKey: "default",
+ },
+ }
+ want := fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+ for i := 0; i < 1000; i++ {
+ if got := r.Template(); got != want {
+ t.Fatalf("Template() returned\n%s\nwant\n%s", got, want)
+ }
+ }
+}
diff --git a/rust/rust.go b/rust/rust.go
index 6fe8871..5cc8845 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -735,13 +735,14 @@
deps := mod.deps(ctx)
commonDepVariations := []blueprint.Variation{}
- commonDepVariations = append(commonDepVariations,
- blueprint.Variation{Mutator: "version", Variation: ""})
+ if cc.VersionVariantAvailable(mod) {
+ commonDepVariations = append(commonDepVariations,
+ blueprint.Variation{Mutator: "version", Variation: ""})
+ }
if !mod.Host() {
commonDepVariations = append(commonDepVariations,
blueprint.Variation{Mutator: "image", Variation: android.CoreVariation})
}
-
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
{Mutator: "rust_libraries", Variation: "rlib"},
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index a2e35d9..0932873 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -151,6 +151,12 @@
// Whether public stub exists or not.
Public_stub *bool `blueprint:"mutated"`
+
+ Cpp struct {
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ // Forwarded to cc_library.min_sdk_version
+ Min_sdk_version *string
+ }
}
var (
@@ -344,6 +350,7 @@
Vendor_available *bool
Host_supported *bool
Apex_available []string
+ Min_sdk_version *string
}
type javaLibraryProperties struct {
@@ -433,6 +440,7 @@
ccProps.Vendor_available = m.properties.Vendor_available
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
+ ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal"
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/dumpvars.go b/ui/build/dumpvars.go
index ce8f968..a559330 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -190,6 +190,7 @@
// compiler wrappers set up by make
"CC_WRAPPER",
"CXX_WRAPPER",
+ "RBE_WRAPPER",
"JAVAC_WRAPPER",
"R8_WRAPPER",
"D8_WRAPPER",
@@ -228,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",
@@ -237,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",
@@ -257,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 8796a4f..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",
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index dfc3be1..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")
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 9b8d648..2fbf381 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -119,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))
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/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;
+}