Merge "Move creation of paths into hiddenAPIGenerateCSV"
diff --git a/android/mutator.go b/android/mutator.go
index 2a2be6c..6b19dc5 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -48,6 +48,14 @@
func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, bp2buildMutators []RegisterMutatorFunc) {
mctx := ®isterMutatorsContext{}
+ sharedMutators := []RegisterMutatorFunc{
+ RegisterDefaultsPreArchMutators,
+ }
+
+ for _, f := range sharedMutators {
+ f(mctx)
+ }
+
// Register bp2build mutators
for _, f := range bp2buildMutators {
f(mctx)
diff --git a/apex/apex.go b/apex/apex.go
index ade8fa9..c897042 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -89,6 +89,9 @@
Multilib apexMultilibProperties
+ // List of boot images that are embedded inside this APEX bundle.
+ Boot_images []string
+
// List of java libraries that are embedded inside this APEX bundle.
Java_libs []string
@@ -544,6 +547,7 @@
certificateTag = dependencyTag{name: "certificate"}
executableTag = dependencyTag{name: "executable", payload: true}
fsTag = dependencyTag{name: "filesystem", payload: true}
+ bootImageTag = dependencyTag{name: "bootImage", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
keyTag = dependencyTag{name: "key"}
@@ -721,6 +725,7 @@
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
+ ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Boot_images...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@@ -730,10 +735,6 @@
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent")
}
- // The ART boot image depends on dex2oat to compile it.
- if !java.SkipDexpreoptBootJars(ctx) {
- dexpreopt.RegisterToolDeps(ctx)
- }
}
// Dependencies for signing
@@ -1648,6 +1649,23 @@
} else {
ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
}
+ case bootImageTag:
+ {
+ if _, ok := child.(*java.BootImageModule); !ok {
+ ctx.PropertyErrorf("boot_images", "%q is not a boot_image module", depName)
+ return false
+ }
+ bootImageInfo := ctx.OtherModuleProvider(child, java.BootImageInfoProvider).(java.BootImageInfo)
+ for arch, files := range bootImageInfo.AndroidBootImageFilesByArchType() {
+ dirInApex := filepath.Join("javalib", arch.String())
+ for _, f := range files {
+ androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
+ // TODO(b/177892522) - consider passing in the boot image module here instead of nil
+ af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
+ filesInfo = append(filesInfo, af)
+ }
+ }
+ }
case javaLibTag:
switch child.(type) {
case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
@@ -1862,25 +1880,6 @@
return
}
- if a.artApex {
- // Specific to the ART apex: dexpreopt artifacts for libcore Java libraries. Build rules are
- // generated by the dexpreopt singleton, and here we access build artifacts via the global
- // boot image config.
- for arch, files := range java.DexpreoptedArtApexJars(ctx) {
- dirInApex := filepath.Join("javalib", arch.String())
- for _, f := range files {
- localModule := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
- af := newApexFile(ctx, f, localModule, dirInApex, etc, nil)
- filesInfo = append(filesInfo, af)
- }
- }
- // Call GetGlobalSoongConfig to initialize it, which may be necessary if dexpreopt is
- // disabled for libraries/apps, but boot images are still needed.
- if !java.SkipDexpreoptBootJars(ctx) {
- dexpreopt.GetGlobalSoongConfig(ctx)
- }
- }
-
// Remove duplicates in filesInfo
removeDup := func(filesInfo []apexFile) []apexFile {
encountered := make(map[string]apexFile)
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 07feb03..27a1562 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -15,6 +15,8 @@
package apex
import (
+ "reflect"
+ "strings"
"testing"
"android/soong/android"
@@ -69,6 +71,16 @@
],
srcs: ["b.java"],
}
+
+ boot_image {
+ name: "art-boot-image",
+ image_name: "art",
+ }
+
+ boot_image {
+ name: "framework-boot-image",
+ image_name: "boot",
+ }
`,
// Configure some libraries in the art and framework boot images.
withArtBootImageJars("com.android.art:baz", "com.android.art:quuz"),
@@ -83,13 +95,39 @@
)
// Make sure that the framework-boot-image is using the correct configuration.
- checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar")
+ checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar", `
+test_device/dex_bootjars/android/system/framework/arm/boot-foo.art
+test_device/dex_bootjars/android/system/framework/arm/boot-foo.oat
+test_device/dex_bootjars/android/system/framework/arm/boot-foo.vdex
+test_device/dex_bootjars/android/system/framework/arm/boot-bar.art
+test_device/dex_bootjars/android/system/framework/arm/boot-bar.oat
+test_device/dex_bootjars/android/system/framework/arm/boot-bar.vdex
+test_device/dex_bootjars/android/system/framework/arm64/boot-foo.art
+test_device/dex_bootjars/android/system/framework/arm64/boot-foo.oat
+test_device/dex_bootjars/android/system/framework/arm64/boot-foo.vdex
+test_device/dex_bootjars/android/system/framework/arm64/boot-bar.art
+test_device/dex_bootjars/android/system/framework/arm64/boot-bar.oat
+test_device/dex_bootjars/android/system/framework/arm64/boot-bar.vdex
+`)
// Make sure that the art-boot-image is using the correct configuration.
- checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz")
+ checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz", `
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.art
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.oat
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-quuz.vdex
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.art
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.oat
+test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-quuz.vdex
+`)
}
-func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string) {
+func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string, expectedBootImageFiles string) {
t.Helper()
bootImage := ctx.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule)
@@ -99,6 +137,20 @@
if actual := modules.String(); actual != expectedConfiguredModules {
t.Errorf("invalid modules for %s: expected %q, actual %q", moduleName, expectedConfiguredModules, actual)
}
+
+ // Get a list of all the paths in the boot image sorted by arch type.
+ allPaths := []string{}
+ bootImageFilesByArchType := bootImageInfo.AndroidBootImageFilesByArchType()
+ for _, archType := range android.ArchTypeList() {
+ if paths, ok := bootImageFilesByArchType[archType]; ok {
+ for _, path := range paths {
+ allPaths = append(allPaths, android.NormalizePathForTesting(path))
+ }
+ }
+ }
+ if expected, actual := strings.TrimSpace(expectedBootImageFiles), strings.TrimSpace(strings.Join(allPaths, "\n")); !reflect.DeepEqual(expected, actual) {
+ t.Errorf("invalid paths for %s: expected \n%s, actual \n%s", moduleName, expected, actual)
+ }
}
func modifyDexpreoptConfig(configModifier func(dexpreoptConfig *dexpreopt.GlobalConfig)) func(fs map[string][]byte, config android.Config) {
@@ -126,3 +178,61 @@
dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
})
}
+
+func TestBootImageInApex(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ boot_images: [
+ "mybootimage",
+ ],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ }
+
+ boot_image {
+ name: "mybootimage",
+ image_name: "boot",
+ apex_available: [
+ "myapex",
+ ],
+ }
+`,
+ // Configure some libraries in the framework boot image.
+ withFrameworkBootImageJars("platform:foo", "platform:bar"),
+ )
+
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "javalib/arm/boot-bar.art",
+ "javalib/arm/boot-bar.oat",
+ "javalib/arm/boot-bar.vdex",
+ "javalib/arm/boot-foo.art",
+ "javalib/arm/boot-foo.oat",
+ "javalib/arm/boot-foo.vdex",
+ "javalib/arm64/boot-bar.art",
+ "javalib/arm64/boot-bar.oat",
+ "javalib/arm64/boot-bar.vdex",
+ "javalib/arm64/boot-foo.art",
+ "javalib/arm64/boot-foo.oat",
+ "javalib/arm64/boot-foo.vdex",
+ })
+}
+
+// TODO(b/177892522) - add test for host apex.
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 66ed42d..a01a7cd 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -633,3 +633,201 @@
}
}
}
+
+type bp2buildMutator = func(android.TopDownMutatorContext)
+
+func TestBp2BuildInlinesDefaults(t *testing.T) {
+ testCases := []struct {
+ moduleTypesUnderTest map[string]android.ModuleFactory
+ bp2buildMutatorsUnderTest map[string]bp2buildMutator
+ bp string
+ expectedBazelTarget string
+ description string
+ }{
+ {
+ moduleTypesUnderTest: map[string]android.ModuleFactory{
+ "genrule": genrule.GenRuleFactory,
+ "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+ },
+ bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+ "genrule": genrule.GenruleBp2Build,
+ },
+ bp: `genrule_defaults {
+ name: "gen_defaults",
+ cmd: "do-something $(in) $(out)",
+}
+genrule {
+ name: "gen",
+ out: ["out"],
+ srcs: ["in1"],
+ defaults: ["gen_defaults"],
+}
+`,
+ expectedBazelTarget: `genrule(
+ name = "gen",
+ cmd = "do-something $(SRCS) $(OUTS)",
+ outs = [
+ "out",
+ ],
+ srcs = [
+ "in1",
+ ],
+)`,
+ description: "genrule applies properties from a genrule_defaults dependency if not specified",
+ },
+ {
+ moduleTypesUnderTest: map[string]android.ModuleFactory{
+ "genrule": genrule.GenRuleFactory,
+ "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+ },
+ bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+ "genrule": genrule.GenruleBp2Build,
+ },
+ bp: `genrule_defaults {
+ name: "gen_defaults",
+ out: ["out-from-defaults"],
+ srcs: ["in-from-defaults"],
+ cmd: "cmd-from-defaults",
+}
+genrule {
+ name: "gen",
+ out: ["out"],
+ srcs: ["in1"],
+ defaults: ["gen_defaults"],
+ cmd: "do-something $(in) $(out)",
+}
+`,
+ expectedBazelTarget: `genrule(
+ name = "gen",
+ cmd = "do-something $(SRCS) $(OUTS)",
+ outs = [
+ "out-from-defaults",
+ "out",
+ ],
+ srcs = [
+ "in-from-defaults",
+ "in1",
+ ],
+)`,
+ description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
+ },
+ {
+ moduleTypesUnderTest: map[string]android.ModuleFactory{
+ "genrule": genrule.GenRuleFactory,
+ "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+ },
+ bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+ "genrule": genrule.GenruleBp2Build,
+ },
+ bp: `genrule_defaults {
+ name: "gen_defaults1",
+ cmd: "cp $(in) $(out)",
+}
+
+genrule_defaults {
+ name: "gen_defaults2",
+ srcs: ["in1"],
+}
+
+genrule {
+ name: "gen",
+ out: ["out"],
+ defaults: ["gen_defaults1", "gen_defaults2"],
+}
+`,
+ expectedBazelTarget: `genrule(
+ name = "gen",
+ cmd = "cp $(SRCS) $(OUTS)",
+ outs = [
+ "out",
+ ],
+ srcs = [
+ "in1",
+ ],
+)`,
+ description: "genrule applies properties from list of genrule_defaults",
+ },
+ {
+ moduleTypesUnderTest: map[string]android.ModuleFactory{
+ "genrule": genrule.GenRuleFactory,
+ "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+ },
+ bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+ "genrule": genrule.GenruleBp2Build,
+ },
+ bp: `genrule_defaults {
+ name: "gen_defaults1",
+ defaults: ["gen_defaults2"],
+ cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
+}
+
+genrule_defaults {
+ name: "gen_defaults2",
+ defaults: ["gen_defaults3"],
+ cmd: "cmd2 $(in) $(out)",
+ out: ["out-from-2"],
+ srcs: ["in1"],
+}
+
+genrule_defaults {
+ name: "gen_defaults3",
+ out: ["out-from-3"],
+ srcs: ["srcs-from-3"],
+}
+
+genrule {
+ name: "gen",
+ out: ["out"],
+ defaults: ["gen_defaults1"],
+}
+`,
+ expectedBazelTarget: `genrule(
+ name = "gen",
+ cmd = "cmd1 $(SRCS) $(OUTS)",
+ outs = [
+ "out-from-3",
+ "out-from-2",
+ "out",
+ ],
+ srcs = [
+ "srcs-from-3",
+ "in1",
+ ],
+)`,
+ description: "genrule applies properties from genrule_defaults transitively",
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+ ctx := android.NewTestContext(config)
+ for m, factory := range testCase.moduleTypesUnderTest {
+ ctx.RegisterModuleType(m, factory)
+ }
+ for mutator, f := range testCase.bp2buildMutatorsUnderTest {
+ ctx.RegisterBp2BuildMutator(mutator, f)
+ }
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.ResolveDependencies(config)
+ android.FailIfErrored(t, errs)
+
+ bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
+ if actualCount := len(bazelTargets); actualCount != 1 {
+ t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
+ }
+
+ actualBazelTarget := bazelTargets[0]
+ if actualBazelTarget.content != testCase.expectedBazelTarget {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ testCase.expectedBazelTarget,
+ actualBazelTarget.content,
+ )
+ }
+ }
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 040aa0b..9345728 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -168,7 +168,7 @@
}
}
-func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func AndroidMkWriteTestData(data []android.DataPath, entries *android.AndroidMkEntries) {
testFiles := android.AndroidMkDataPaths(data)
if len(testFiles) > 0 {
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
@@ -353,7 +353,7 @@
for _, srcPath := range benchmark.data {
dataPaths = append(dataPaths, android.DataPath{SrcPath: srcPath})
}
- androidMkWriteTestData(dataPaths, ctx, entries)
+ AndroidMkWriteTestData(dataPaths, entries)
}
func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
@@ -378,7 +378,7 @@
}
})
- androidMkWriteTestData(test.data, ctx, entries)
+ AndroidMkWriteTestData(test.data, entries)
androidMkWriteExtraTestConfigs(test.extraTestConfigs, entries)
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 8cd4f97..9dcb5f3 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -19,6 +19,7 @@
"fmt"
"os"
"path/filepath"
+ "strings"
"github.com/google/blueprint/bootstrap"
@@ -166,12 +167,43 @@
// conversion for Bazel conversion.
bp2buildCtx := android.NewContext(configuration)
bp2buildCtx.RegisterForBazelConversion()
+
+ // No need to generate Ninja build rules/statements from Modules and Singletons.
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
+
+ // Run the loading and analysis pipeline.
bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
+ // Run the code-generation phase to convert BazelTargetModules to BUILD files.
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
bp2build.Codegen(codegenContext)
+
+ // Workarounds to support running bp2build in a clean AOSP checkout with no
+ // prior builds, and exiting early as soon as the BUILD files get generated,
+ // therefore not creating build.ninja files that soong_ui and callers of
+ // soong_build expects.
+ //
+ // These files are: build.ninja and build.ninja.d. Since Kati hasn't been
+ // ran as well, and `nothing` is defined in a .mk file, there isn't a ninja
+ // target called `nothing`, so we manually create it here.
+ //
+ // Even though outFile (build.ninja) and depFile (build.ninja.d) are values
+ // passed into bootstrap.Main, they are package-private fields in bootstrap.
+ // Short of modifying Blueprint to add an exported getter, inlining them
+ // here is the next-best practical option.
+ ninjaFileName := "build.ninja"
+ ninjaFile := android.PathForOutput(codegenContext, ninjaFileName)
+ ninjaFileD := android.PathForOutput(codegenContext, ninjaFileName+".d")
+ extraNinjaDepsString := strings.Join(extraNinjaDeps, " \\\n ")
+ // A workaround to create the 'nothing' ninja target so `m nothing` works,
+ // since bp2build runs without Kati, and the 'nothing' target is declared in
+ // a Makefile.
+ android.WriteFileToOutputDir(ninjaFile, []byte("build nothing: phony\n phony_output = true\n"), 0666)
+ android.WriteFileToOutputDir(
+ ninjaFileD,
+ []byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFileName, extraNinjaDepsString)),
+ 0666)
}
// shouldPrepareBuildActions reads configuration and flags if build actions
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index bf610ef..ec62eb3 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -534,3 +534,26 @@
}
return clcs
}
+
+// Convert Soong CLC map to JSON representation for Make.
+func toJsonClassLoaderContext(clcMap ClassLoaderContextMap) jsonClassLoaderContextMap {
+ jClcMap := make(jsonClassLoaderContextMap)
+ for sdkVer, clcs := range clcMap {
+ sdkVerStr := fmt.Sprintf("%d", sdkVer)
+ jClcMap[sdkVerStr] = toJsonClassLoaderContextRec(clcs)
+ }
+ return jClcMap
+}
+
+// Recursive helper for toJsonClassLoaderContext.
+func toJsonClassLoaderContextRec(clcs []*ClassLoaderContext) map[string]*jsonClassLoaderContext {
+ jClcs := make(map[string]*jsonClassLoaderContext, len(clcs))
+ for _, clc := range clcs {
+ jClcs[clc.Name] = &jsonClassLoaderContext{
+ Host: clc.Host.String(),
+ Device: clc.Device,
+ Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
+ }
+ }
+ return jClcs
+}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 867ece6..d55204b 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -114,6 +114,7 @@
ProfileBootListing android.OptionalPath
EnforceUsesLibraries bool
+ ProvidesUsesLibrary string // the name of the <uses-library> (usually the same as its module)
ClassLoaderContexts ClassLoaderContextMap
Archs []android.ArchType
@@ -290,6 +291,42 @@
return config.ModuleConfig, nil
}
+// WriteSlimModuleConfigForMake serializes a subset of ModuleConfig into a per-module
+// dexpreopt.config JSON file. It is a way to pass dexpreopt information about Soong modules to
+// Make, which is needed when a Make module has a <uses-library> dependency on a Soong module.
+func WriteSlimModuleConfigForMake(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) {
+ if path == nil {
+ return
+ }
+
+ // JSON representation of the slim module dexpreopt.config.
+ type slimModuleJSONConfig struct {
+ Name string
+ DexLocation string
+ BuildPath string
+ EnforceUsesLibraries bool
+ ProvidesUsesLibrary string
+ ClassLoaderContexts jsonClassLoaderContextMap
+ }
+
+ jsonConfig := &slimModuleJSONConfig{
+ Name: config.Name,
+ DexLocation: config.DexLocation,
+ BuildPath: config.BuildPath.String(),
+ EnforceUsesLibraries: config.EnforceUsesLibraries,
+ ProvidesUsesLibrary: config.ProvidesUsesLibrary,
+ ClassLoaderContexts: toJsonClassLoaderContext(config.ClassLoaderContexts),
+ }
+
+ data, err := json.MarshalIndent(jsonConfig, "", " ")
+ if err != nil {
+ ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err)
+ return
+ }
+
+ android.WriteFileRule(ctx, path, string(data))
+}
+
// dex2oatModuleName returns the name of the module to use for the dex2oat host
// tool. It should be a binary module with public visibility that is compiled
// and installed for host.
diff --git a/java/androidmk.go b/java/androidmk.go
index cc454b0..21f3012 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -125,6 +125,10 @@
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", library.linter.reports)
+
+ if library.dexpreopter.configPath != nil {
+ entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
+ }
},
},
})
diff --git a/java/app.go b/java/app.go
index e6c9a2d..ce89e9b 100755
--- a/java/app.go
+++ b/java/app.go
@@ -455,6 +455,7 @@
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.installPath = a.installPath(ctx)
+ a.dexpreopter.isApp = true
if a.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
diff --git a/java/app_import.go b/java/app_import.go
index df940f1..6f21bfb 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -255,6 +255,7 @@
installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
}
+ a.dexpreopter.isApp = true
a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
diff --git a/java/boot_image.go b/java/boot_image.go
index 07ef0d8..0a525b7 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -15,9 +15,11 @@
package java
import (
+ "fmt"
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"github.com/google/blueprint"
)
@@ -38,6 +40,7 @@
type BootImageModule struct {
android.ModuleBase
+ android.ApexModuleBase
properties bootImageProperties
}
@@ -45,7 +48,8 @@
func bootImageFactory() android.Module {
m := &BootImageModule{}
m.AddProperties(&m.properties)
- android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibCommon)
+ android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+ android.InitApexModule(m)
return m
}
@@ -53,6 +57,9 @@
type BootImageInfo struct {
// The image config, internal to this module (and the dex_bootjars singleton).
+ //
+ // Will be nil if the BootImageInfo has not been provided for a specific module. That can occur
+ // when SkipDexpreoptBootJars(ctx) returns true.
imageConfig *bootImageConfig
}
@@ -60,12 +67,56 @@
return i.imageConfig.modules
}
+// Get a map from ArchType to the associated boot image's contents for Android.
+//
+// Extension boot images only return their own files, not the files of the boot images they extend.
+func (i BootImageInfo) AndroidBootImageFilesByArchType() map[android.ArchType]android.OutputPaths {
+ files := map[android.ArchType]android.OutputPaths{}
+ if i.imageConfig != nil {
+ for _, variant := range i.imageConfig.variants {
+ // We also generate boot images for host (for testing), but we don't need those in the apex.
+ // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
+ if variant.target.Os == android.Android {
+ files[variant.target.Arch.ArchType] = variant.imagesDeps
+ }
+ }
+ }
+ return files
+}
+
+func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ if tag == dexpreopt.Dex2oatDepTag {
+ // The dex2oat tool is only needed for building and is not required in the apex.
+ return false
+ }
+ panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
+}
+
+func (b *BootImageModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
+ return nil
+}
+
+func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if SkipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
+}
+
func (b *BootImageModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Nothing to do if skipping the dexpreopt of boot image jars.
if SkipDexpreoptBootJars(ctx) {
return
}
+ // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
+ // GenerateSingletonBuildActions method as it cannot create it for itself.
+ dexpreopt.GetGlobalSoongConfig(ctx)
+
// Get a map of the image configs that are supported.
imageConfigs := genBootImageConfigs(ctx)
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index b5830c7..ac00592 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -30,6 +30,7 @@
installPath android.InstallPath
uncompressedDex bool
isSDKLibrary bool
+ isApp bool
isTest bool
isPresignedPrebuilt bool
@@ -38,6 +39,11 @@
classLoaderContexts dexpreopt.ClassLoaderContextMap
builtInstalled string
+
+ // A path to a dexpreopt.config file generated by Soong for libraries that may be used as a
+ // <uses-library> by Make modules. The path is passed to Make via LOCAL_SOONG_DEXPREOPT_CONFIG
+ // variable. If the path is nil, no config is generated (which is the case for apps and tests).
+ configPath android.WritablePath
}
type DexpreoptProperties struct {
@@ -117,7 +123,40 @@
// the dexpreopter struct hasn't been fully initialized before we're called,
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
// disabled, even if installable is true.
- if d.dexpreoptDisabled(ctx) || d.installPath.Base() == "." {
+ if d.installPath.Base() == "." {
+ return
+ }
+
+ dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
+
+ buildPath := android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath
+
+ providesUsesLib := ctx.ModuleName()
+ if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
+ name := ulib.ProvidesUsesLib()
+ if name != nil {
+ providesUsesLib = *name
+ }
+ }
+
+ if !d.isApp && !d.isTest {
+ // Slim dexpreopt config is serialized to dexpreopt.config files and used by
+ // dex_preopt_config_merger.py to get information about <uses-library> dependencies.
+ // Note that it might be needed even if dexpreopt is disabled for this module.
+ slimDexpreoptConfig := &dexpreopt.ModuleConfig{
+ Name: ctx.ModuleName(),
+ DexLocation: dexLocation,
+ BuildPath: buildPath,
+ EnforceUsesLibraries: d.enforceUsesLibs,
+ ProvidesUsesLibrary: providesUsesLib,
+ ClassLoaderContexts: d.classLoaderContexts,
+ // The rest of the fields are not needed.
+ }
+ d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
+ dexpreopt.WriteSlimModuleConfigForMake(ctx, slimDexpreoptConfig, d.configPath)
+ }
+
+ if d.dexpreoptDisabled(ctx) {
return
}
@@ -157,8 +196,6 @@
// The image locations for all Android variants are identical.
imageLocations := bootImage.getAnyAndroidVariant().imageLocations()
- dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
-
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
profileIsTextListing := false
@@ -177,10 +214,11 @@
}
}
+ // Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: ctx.ModuleName(),
DexLocation: dexLocation,
- BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
+ BuildPath: buildPath,
DexPath: dexJarFile,
ManifestPath: d.manifestFile,
UncompressedDex: d.uncompressedDex,
@@ -192,6 +230,7 @@
ProfileBootListing: profileBootListing,
EnforceUsesLibraries: d.enforceUsesLibs,
+ ProvidesUsesLibrary: providesUsesLib,
ClassLoaderContexts: d.classLoaderContexts,
Archs: archs,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 36d0d30..2a7eb42 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -392,22 +392,6 @@
dexpreoptConfigForMake android.WritablePath
}
-// Accessor function for the apex package. Returns nil if dexpreopt is disabled.
-func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
- if SkipDexpreoptBootJars(ctx) {
- return nil
- }
- // Include dexpreopt files for the primary boot image.
- files := map[android.ArchType]android.OutputPaths{}
- for _, variant := range artBootImageConfig(ctx).variants {
- // 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
-}
-
// Provide paths to boot images for use by modules that depend upon them.
//
// The build rules are created in GenerateSingletonBuildActions().
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 5550a4c..a9e0773 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -148,7 +148,7 @@
t.Run(test.name, func(t *testing.T) {
ctx, _ := testJava(t, test.bp)
- dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeDescription("dexpreopt")
+ dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
enabled := dexpreopt.Rule != nil
if enabled != test.enabled {
diff --git a/java/testing.go b/java/testing.go
index 31ff47f..5fcf84c 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -219,16 +219,6 @@
dex_bootjars {
name: "dex_bootjars",
}
-
- boot_image {
- name: "art-boot-image",
- image_name: "art",
- }
-
- boot_image {
- name: "framework-boot-image",
- image_name: "boot",
- }
`
return bp
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 0307727..1a286f7 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -18,6 +18,7 @@
"path/filepath"
"android/soong/android"
+ "android/soong/cc"
)
type AndroidMkContext interface {
@@ -85,7 +86,8 @@
}
func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
- test.binaryDecorator.AndroidMk(ctx, ret)
+ ctx.SubAndroidMk(ret, test.binaryDecorator)
+
ret.Class = "NATIVE_TESTS"
ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.AddCompatibilityTestSuites(test.Properties.Test_suites...)
@@ -95,7 +97,8 @@
entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true))
entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(test.Properties.Test_options.Unit_test))
})
- // TODO(chh): add test data with androidMkWriteTestData(test.data, ctx, ret)
+
+ cc.AndroidMkWriteTestData(test.data, ret)
}
func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index fc7f47e..abc9af9 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -116,6 +116,7 @@
"foo.proto": nil,
"liby.so": nil,
"libz.so": nil,
+ "data.txt": nil,
}
}
diff --git a/rust/test.go b/rust/test.go
index 35e04ff..92b4860 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -43,6 +43,10 @@
// installed into.
Test_suites []string `android:"arch_variant"`
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test
+ Data []string `android:"path,arch_variant"`
+
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
@@ -62,6 +66,12 @@
*binaryDecorator
Properties TestProperties
testConfig android.Path
+
+ data []android.DataPath
+}
+
+func (test *testDecorator) dataPaths() []android.DataPath {
+ return test.data
}
func (test *testDecorator) nativeCoverage() bool {
@@ -89,7 +99,6 @@
}
module.compiler = test
- module.AddProperties(&test.Properties)
return module, test
}
@@ -105,6 +114,12 @@
nil,
test.Properties.Auto_gen_config)
+ dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
+
+ for _, dataSrcPath := range dataSrcPaths {
+ test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
+ }
+
// default relative install path is module name
if !Bool(test.Properties.No_named_install_directory) {
test.baseCompiler.relative = ctx.ModuleName()
diff --git a/rust/test_test.go b/rust/test_test.go
index fea2ad0..892761a 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -26,6 +26,7 @@
rust_test_host {
name: "my_test",
srcs: ["foo.rs"],
+ data: ["data.txt"],
}`)
testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64")
@@ -34,6 +35,12 @@
if !strings.Contains(outPath, expectedOut) {
t.Errorf("wrong output path: %v; expected: %v", outPath, expectedOut)
}
+
+ dataPaths := testingModule.Module().(*Module).compiler.(*testDecorator).dataPaths()
+ if len(dataPaths) != 1 {
+ t.Errorf("expected exactly one test data file. test data files: [%s]", dataPaths)
+ return
+ }
}
func TestRustTestLinkage(t *testing.T) {
diff --git a/scripts/OWNERS b/scripts/OWNERS
index c4c39d5..8198083 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -1,4 +1,5 @@
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
per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
new file mode 100755
index 0000000..4b08ac3
--- /dev/null
+++ b/scripts/build-aml-prebuilts.sh
@@ -0,0 +1,131 @@
+#!/bin/bash -e
+
+# This is a wrapper around "m" that builds the given modules in multi-arch mode
+# for all architectures supported by Mainline modules. The make (kati) stage is
+# skipped, so the build targets in the arguments can only be Soong modules or
+# intermediate output files - make targets and normal installed paths are not
+# supported.
+#
+# This script is typically used with "sdk" or "module_export" modules, which
+# Soong will install in $OUT_DIR/soong/mainline-sdks (cf
+# PathForMainlineSdksInstall in android/paths.go).
+
+export OUT_DIR=${OUT_DIR:-out}
+
+if [ -e ${OUT_DIR}/soong/.soong.kati_enabled ]; then
+ # If ${OUT_DIR} has been created without --skip-make, Soong will create an
+ # ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
+ # expected to be supplied by the .mk files, and that might cause errors in
+ # "m --skip-make" below. We therefore default to a different out dir
+ # location in that case.
+ AML_OUT_DIR=out/aml
+ echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
+ OUT_DIR=${AML_OUT_DIR}
+fi
+
+if [ ! -e "build/envsetup.sh" ]; then
+ echo "$0 must be run from the top of the tree"
+ exit 1
+fi
+
+source build/envsetup.sh
+
+my_get_build_var() {
+ # get_build_var will run Soong in normal in-make mode where it creates
+ # .soong.kati_enabled. That would clobber our real out directory, so we need
+ # to run it in a different one.
+ OUT_DIR=${OUT_DIR}/get_build_var get_build_var "$@"
+}
+
+readonly SOONG_OUT=${OUT_DIR}/soong
+mkdir -p ${SOONG_OUT}
+
+# Some Soong build rules may require this, and the failure mode if it's missing
+# is confusing (b/172548608).
+readonly BUILD_NUMBER="$(my_get_build_var BUILD_NUMBER)"
+echo -n ${BUILD_NUMBER} > ${SOONG_OUT}/build_number.txt
+
+readonly PLATFORM_SDK_VERSION="$(my_get_build_var PLATFORM_SDK_VERSION)"
+readonly PLATFORM_VERSION="$(my_get_build_var PLATFORM_VERSION)"
+PLATFORM_VERSION_ALL_CODENAMES="$(my_get_build_var PLATFORM_VERSION_ALL_CODENAMES)"
+
+# PLATFORM_VERSION_ALL_CODENAMES is a comma separated list like O,P. We need to
+# turn this into ["O","P"].
+PLATFORM_VERSION_ALL_CODENAMES="${PLATFORM_VERSION_ALL_CODENAMES/,/'","'}"
+PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
+
+# Get the list of missing <uses-library> modules and convert it to a JSON array
+# (quote module names, add comma separator and wrap in brackets).
+MISSING_USES_LIBRARIES="$(my_get_build_var INTERNAL_PLATFORM_MISSING_USES_LIBRARIES)"
+MISSING_USES_LIBRARIES="[$(echo $MISSING_USES_LIBRARIES | sed -e 's/\([^ ]\+\)/\"\1\"/g' -e 's/[ ]\+/, /g')]"
+
+# Logic from build/make/core/goma.mk
+if [ "${USE_GOMA}" = true ]; then
+ if [ -n "${GOMA_DIR}" ]; then
+ goma_dir="${GOMA_DIR}"
+ else
+ goma_dir="${HOME}/goma"
+ fi
+ GOMA_CC="${goma_dir}/gomacc"
+ export CC_WRAPPER="${CC_WRAPPER}${CC_WRAPPER:+ }${GOMA_CC}"
+ export CXX_WRAPPER="${CXX_WRAPPER}${CXX_WRAPPER:+ }${GOMA_CC}"
+ export JAVAC_WRAPPER="${JAVAC_WRAPPER}${JAVAC_WRAPPER:+ }${GOMA_CC}"
+else
+ USE_GOMA=false
+fi
+
+readonly SOONG_VARS=${SOONG_OUT}/soong.variables
+
+# Aml_abis: true
+# - This flag configures Soong to compile for all architectures required for
+# Mainline modules.
+# CrossHost: linux_bionic
+# CrossHostArch: x86_64
+# - Enable Bionic on host as ART needs prebuilts for it.
+# VendorVars.art_mdoule.source_build
+# - TODO(b/172480615): Change default to false when platform uses ART Module
+# prebuilts by default.
+cat > ${SOONG_VARS}.new << EOF
+{
+ "BuildNumberFile": "build_number.txt",
+
+ "Platform_version_name": "${PLATFORM_VERSION}",
+ "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
+ "Platform_sdk_codename": "${PLATFORM_VERSION}",
+ "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
+
+ "DeviceName": "generic_arm64",
+ "HostArch": "x86_64",
+ "HostSecondaryArch": "x86",
+ "CrossHost": "linux_bionic",
+ "CrossHostArch": "x86_64",
+ "Aml_abis": true,
+
+ "Allow_missing_dependencies": ${SOONG_ALLOW_MISSING_DEPENDENCIES:-false},
+ "Unbundled_build": ${TARGET_BUILD_UNBUNDLED:-false},
+ "UseGoma": ${USE_GOMA},
+
+ "VendorVars": {
+ "art_module": {
+ "source_build": "${ENABLE_ART_SOURCE_BUILD:-true}"
+ }
+ },
+
+ "MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
+}
+EOF
+
+if [ -f ${SOONG_VARS} ] && cmp -s ${SOONG_VARS} ${SOONG_VARS}.new; then
+ # Don't touch soong.variables if we don't have to, to avoid Soong rebuilding
+ # the ninja file when it isn't necessary.
+ rm ${SOONG_VARS}.new
+else
+ mv ${SOONG_VARS}.new ${SOONG_VARS}
+fi
+
+# 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.
+export FORCE_BUILD_LLVM_COMPONENTS=true
+
+m --skip-make "$@"
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index d6c6f94..ea62af4 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -84,16 +84,10 @@
done
# Create multi-archs SDKs in a different out directory. The multi-arch script
-# uses Soong in --skip-kati mode which cannot use the same directory as normal
+# uses Soong in --skip-make mode which cannot use the same directory as normal
# mode with make.
export OUT_DIR=${OUT_DIR}/aml
-# 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.
-export FORCE_BUILD_LLVM_COMPONENTS=true
-
-echo_and_run build/soong/soong_ui.bash --make-mode --skip-kati \
- TARGET_PRODUCT=mainline_sdk "$@" ${MODULES_SDK_AND_EXPORTS[@]}
+echo_and_run build/soong/scripts/build-aml-prebuilts.sh ${MODULES_SDK_AND_EXPORTS[@]}
rm -rf ${DIST_DIR}/mainline-sdks
echo_and_run cp -R ${OUT_DIR}/soong/mainline-sdks ${DIST_DIR}
diff --git a/ui/build/build.go b/ui/build/build.go
index 926da31..215a6c8 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -252,6 +252,11 @@
if what&BuildSoong != 0 {
// Run Soong
runSoong(ctx, config)
+
+ if config.Environment().IsEnvTrue("GENERATE_BAZEL_FILES") {
+ // Return early, if we're using Soong as the bp2build converter.
+ return
+ }
}
if what&BuildKati != 0 {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 6a93672..899ab5d 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -169,8 +169,11 @@
// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
ninja("bootstrap", ".bootstrap/build.ninja")
- soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
- logSoongBuildMetrics(ctx, soongBuildMetrics)
+ var soongBuildMetrics *soong_metrics_proto.SoongBuildMetrics
+ if shouldCollectBuildSoongMetrics(config) {
+ soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
+ logSoongBuildMetrics(ctx, soongBuildMetrics)
+ }
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
@@ -179,11 +182,16 @@
distGzipFile(ctx, config, config.SoongMakeVarsMk(), "soong")
}
- if ctx.Metrics != nil {
+ if shouldCollectBuildSoongMetrics(config) && ctx.Metrics != nil {
ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
}
}
+func shouldCollectBuildSoongMetrics(config Config) bool {
+ // Do not collect metrics protobuf if the soong_build binary ran as the bp2build converter.
+ return config.Environment().IsFalse("GENERATE_BAZEL_FILES")
+}
+
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)