Merge "Enable code coverage for cc shared library"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 07db3c2..63fe462 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -185,6 +185,8 @@
"frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/libshmem": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/audioaidlconversion": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
@@ -205,6 +207,7 @@
"frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
+ "frameworks/native/libs/permission": Bp2BuildDefaultTrue,
"frameworks/native/services/batteryservice": Bp2BuildDefaultTrue,
"frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
@@ -305,6 +308,7 @@
"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
"system/extras/toolchain-extras": Bp2BuildDefaultTrue,
+ "system/hardware/interfaces/media": Bp2BuildDefaultTrueRecursively,
"system/incremental_delivery/incfs": Bp2BuildDefaultTrue,
"system/libartpalette": Bp2BuildDefaultTrueRecursively,
"system/libbase": Bp2BuildDefaultTrueRecursively,
@@ -1360,7 +1364,10 @@
// Bazel prod-mode allowlist. Modules in this list are built by Bazel
// in either prod mode or staging mode.
- ProdMixedBuildsEnabledList = []string{"com.android.tzdata"}
+ ProdMixedBuildsEnabledList = []string{
+ "com.android.tzdata",
+ "test1_com.android.tzdata",
+ }
// Staging-mode allowlist. Modules in this list are only built
// by Bazel with --bazel-mode-staging. This list should contain modules
@@ -1369,5 +1376,6 @@
// also be built - do not add them to this list.
StagingMixedBuildsEnabledList = []string{
"com.android.adbd",
+ "adbd_test",
}
)
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 0529f23..d132d43 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -22,6 +22,7 @@
"path"
"path/filepath"
"runtime"
+ "sort"
"strings"
"sync"
@@ -374,7 +375,7 @@
return []bazel.AqueryDepset{}
}
-func NewBazelContext(c *config) (BazelContext, error) {
+func GetBazelEnabledAndDisabledModules(buildMode SoongBuildMode, forceEnabled map[string]struct{}) (map[string]bool, map[string]bool) {
disabledModules := map[string]bool{}
enabledModules := map[string]bool{}
addToStringSet := func(set map[string]bool, items []string) {
@@ -383,17 +384,17 @@
}
}
- switch c.BuildMode {
+ switch buildMode {
case BazelProdMode:
addToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
- for enabledAdHocModule := range c.BazelModulesForceEnabledByFlag() {
+ for enabledAdHocModule := range forceEnabled {
enabledModules[enabledAdHocModule] = true
}
case BazelStagingMode:
// Staging mode includes all prod modules plus all staging modules.
addToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
addToStringSet(enabledModules, allowlists.StagingMixedBuildsEnabledList)
- for enabledAdHocModule := range c.BazelModulesForceEnabledByFlag() {
+ for enabledAdHocModule := range forceEnabled {
enabledModules[enabledAdHocModule] = true
}
case BazelDevMode:
@@ -405,9 +406,30 @@
}
addToStringSet(disabledModules, allowlists.MixedBuildsDisabledList)
default:
+ panic("Expected BazelProdMode, BazelStagingMode, or BazelDevMode")
+ }
+ return enabledModules, disabledModules
+}
+
+func GetBazelEnabledModules(buildMode SoongBuildMode) []string {
+ enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(buildMode, nil)
+ enabledList := make([]string, 0, len(enabledModules))
+ for module := range enabledModules {
+ if !disabledModules[module] {
+ enabledList = append(enabledList, module)
+ }
+ }
+ sort.Strings(enabledList)
+ return enabledList
+}
+
+func NewBazelContext(c *config) (BazelContext, error) {
+ if c.BuildMode != BazelProdMode && c.BuildMode != BazelStagingMode && c.BuildMode != BazelDevMode {
return noopBazelContext{}, nil
}
+ enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(c.BuildMode, c.BazelModulesForceEnabledByFlag())
+
paths := bazelPaths{
soongOutDir: c.soongOutDir,
}
@@ -645,10 +667,12 @@
mixed_build_root(name = "buildroot",
deps = [%s],
+ testonly = True, # Unblocks testonly deps.
)
phony_root(name = "phonyroot",
deps = [":buildroot"],
+ testonly = True, # Unblocks testonly deps.
)
`
configNodeFormatString := `
@@ -656,6 +680,7 @@
arch = "%s",
os = "%s",
deps = [%s],
+ testonly = True, # Unblocks testonly deps.
)
`
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 3b159d3..1ecb0af 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -455,6 +455,9 @@
func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) string {
moduleName := ctx.OtherModuleName(module)
moduleDir := ctx.OtherModuleDir(module)
+ if moduleDir == Bp2BuildTopLevel {
+ moduleDir = ""
+ }
return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
}
diff --git a/android/config.go b/android/config.go
index 9d9ab30..9c1a484 100644
--- a/android/config.go
+++ b/android/config.go
@@ -21,7 +21,6 @@
"bytes"
"encoding/json"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -70,6 +69,26 @@
type SoongBuildMode int
+type CmdArgs struct {
+ bootstrap.Args
+ RunGoTests bool
+ OutDir string
+ SoongOutDir string
+
+ SymlinkForestMarker string
+ Bp2buildMarker string
+ BazelQueryViewDir string
+ BazelApiBp2buildDir string
+ ModuleGraphFile string
+ ModuleActionsFile string
+ DocFile string
+
+ BazelMode bool
+ BazelModeDev bool
+ BazelModeStaging bool
+ BazelForceEnabledModules string
+}
+
// Build modes that soong_build can run as.
const (
// Don't use bazel at all during module analysis.
@@ -307,7 +326,7 @@
return fmt.Errorf("cannot marshal config data: %s", err.Error())
}
- f, err := ioutil.TempFile(filepath.Dir(filename), "config")
+ f, err := os.CreateTemp(filepath.Dir(filename), "config")
if err != nil {
return fmt.Errorf("cannot create empty config file %s: %s", filename, err.Error())
}
@@ -404,20 +423,19 @@
// NewConfig creates a new Config object. The srcDir argument specifies the path
// to the root source directory. It also loads the config file, if found.
-func NewConfig(moduleListFile string, buildMode SoongBuildMode, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string,
- bazelForceEnabledModules []string) (Config, error) {
+func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) {
// Make a config with default options.
config := &config{
- ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName),
+ ProductVariablesFileName: filepath.Join(cmdArgs.SoongOutDir, productVariablesFileName),
env: availableEnv,
- outDir: outDir,
- soongOutDir: soongOutDir,
- runGoTests: runGoTests,
+ outDir: cmdArgs.OutDir,
+ soongOutDir: cmdArgs.SoongOutDir,
+ runGoTests: cmdArgs.RunGoTests,
multilibConflicts: make(map[ArchType]bool),
- moduleListFile: moduleListFile,
+ moduleListFile: cmdArgs.ModuleListFile,
fs: pathtools.NewOsFs(absSrcDir),
mixedBuildDisabledModules: make(map[string]struct{}),
mixedBuildEnabledModules: make(map[string]struct{}),
@@ -430,7 +448,7 @@
// Soundness check of the build and source directories. This won't catch strange
// configurations with symlinks, but at least checks the obvious case.
- absBuildDir, err := filepath.Abs(soongOutDir)
+ absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir)
if err != nil {
return Config{}, err
}
@@ -450,7 +468,7 @@
return Config{}, err
}
- KatiEnabledMarkerFile := filepath.Join(soongOutDir, ".soong.kati_enabled")
+ KatiEnabledMarkerFile := filepath.Join(cmdArgs.SoongOutDir, ".soong.kati_enabled")
if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil {
config.katiEnabled = true
}
@@ -503,11 +521,32 @@
config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
}
- config.BuildMode = buildMode
+ if cmdArgs.SymlinkForestMarker != "" {
+ config.BuildMode = SymlinkForest
+ } else if cmdArgs.Bp2buildMarker != "" {
+ config.BuildMode = Bp2build
+ } else if cmdArgs.BazelQueryViewDir != "" {
+ config.BuildMode = GenerateQueryView
+ } else if cmdArgs.BazelApiBp2buildDir != "" {
+ config.BuildMode = ApiBp2build
+ } else if cmdArgs.ModuleGraphFile != "" {
+ config.BuildMode = GenerateModuleGraph
+ } else if cmdArgs.DocFile != "" {
+ config.BuildMode = GenerateDocFile
+ } else if cmdArgs.BazelModeDev {
+ config.BuildMode = BazelDevMode
+ } else if cmdArgs.BazelMode {
+ config.BuildMode = BazelProdMode
+ } else if cmdArgs.BazelModeStaging {
+ config.BuildMode = BazelStagingMode
+ } else {
+ config.BuildMode = AnalysisNoBazel
+ }
+
config.BazelContext, err = NewBazelContext(config)
config.Bp2buildPackageConfig = GetBp2BuildAllowList()
- for _, module := range bazelForceEnabledModules {
+ for _, module := range strings.Split(cmdArgs.BazelForceEnabledModules, ",") {
config.bazelForceEnabledModules[module] = struct{}{}
}
@@ -1150,7 +1189,7 @@
return nil, nil
}
ctx.AddNinjaFileDeps(path.String())
- return ioutil.ReadFile(absolutePath(path.String()))
+ return os.ReadFile(absolutePath(path.String()))
}
func (c *deviceConfig) WithDexpreopt() bool {
@@ -1169,7 +1208,7 @@
return c.multilibConflicts[arch]
}
-func (c *config) PrebuiltHiddenApiDir(ctx PathContext) string {
+func (c *config) PrebuiltHiddenApiDir(_ PathContext) string {
return String(c.productVariables.PrebuiltHiddenApiDir)
}
diff --git a/android/override_module.go b/android/override_module.go
index 51e74d4..2d30a85 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -28,6 +28,7 @@
// module based on it.
import (
+ "fmt"
"sort"
"sync"
@@ -48,6 +49,10 @@
// i.e. cases where an overriding module, too, is overridden by a prebuilt module.
setOverriddenByPrebuilt(overridden bool)
getOverriddenByPrebuilt() bool
+
+ // Directory containing the Blueprint definition of the overriding module
+ setModuleDir(string)
+ ModuleDir() string
}
// Base module struct for override module types
@@ -57,6 +62,8 @@
overridingProperties []interface{}
overriddenByPrebuilt bool
+
+ moduleDir string
}
type OverrideModuleProperties struct {
@@ -66,6 +73,14 @@
// TODO(jungjw): Add an optional override_name bool flag.
}
+func (o *OverrideModuleBase) setModuleDir(d string) {
+ o.moduleDir = d
+}
+
+func (o *OverrideModuleBase) ModuleDir() string {
+ return o.moduleDir
+}
+
func (o *OverrideModuleBase) getOverridingProperties() []interface{} {
return o.overridingProperties
}
@@ -108,6 +123,7 @@
override(ctx BaseModuleContext, o OverrideModule)
GetOverriddenBy() string
+ GetOverriddenByModuleDir() string
setOverridesProperty(overridesProperties *[]string)
@@ -117,7 +133,8 @@
}
type overridableModuleProperties struct {
- OverriddenBy string `blueprint:"mutated"`
+ OverriddenBy string `blueprint:"mutated"`
+ OverriddenByModuleDir string `blueprint:"mutated"`
}
// Base module struct for overridable module types
@@ -196,6 +213,7 @@
*b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
}
b.overridableModuleProperties.OverriddenBy = o.Name()
+ b.overridableModuleProperties.OverriddenByModuleDir = o.ModuleDir()
}
// GetOverriddenBy returns the name of the override module that has overridden this module.
@@ -206,6 +224,10 @@
return b.overridableModuleProperties.OverriddenBy
}
+func (b *OverridableModuleBase) GetOverriddenByModuleDir() string {
+ return b.overridableModuleProperties.OverriddenByModuleDir
+}
+
func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
}
@@ -254,7 +276,9 @@
})
baseModule := ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)[0]
if o, ok := baseModule.(OverridableModule); ok {
- o.addOverride(ctx.Module().(OverrideModule))
+ overrideModule := ctx.Module().(OverrideModule)
+ overrideModule.setModuleDir(ctx.ModuleDir())
+ o.addOverride(overrideModule)
}
}
}
@@ -314,11 +338,35 @@
// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
// or if this variant is not overridden.
-func ModuleNameWithPossibleOverride(ctx ModuleContext) string {
+func ModuleNameWithPossibleOverride(ctx BazelConversionContext) string {
if overridable, ok := ctx.Module().(OverridableModule); ok {
if o := overridable.GetOverriddenBy(); o != "" {
return o
}
}
- return ctx.ModuleName()
+ return ctx.OtherModuleName(ctx.Module())
+}
+
+// ModuleDirWithPossibleOverride returns the dir of the OverrideModule that overrides the current
+// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
+// or if this variant is not overridden.
+func moduleDirWithPossibleOverride(ctx BazelConversionContext) string {
+ if overridable, ok := ctx.Module().(OverridableModule); ok {
+ if o := overridable.GetOverriddenByModuleDir(); o != "" {
+ return o
+ }
+ }
+ return ctx.OtherModuleDir(ctx.Module())
+}
+
+// MaybeBp2buildLabelOfOverridingModule returns the bazel label of the
+// overriding module of an OverridableModule (e.g. override_apex label of a base
+// apex), or the module's label itself if not overridden.
+func MaybeBp2buildLabelOfOverridingModule(ctx BazelConversionContext) string {
+ moduleName := ModuleNameWithPossibleOverride(ctx)
+ moduleDir := moduleDirWithPossibleOverride(ctx)
+ if moduleDir == Bp2BuildTopLevel {
+ moduleDir = ""
+ }
+ return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
}
diff --git a/android/register.go b/android/register.go
index 33e9ea3..9a3d3aa 100644
--- a/android/register.go
+++ b/android/register.go
@@ -35,7 +35,7 @@
// tests.
componentName() string
- // register registers this component in the supplied context.
+ // registers this component in the supplied context.
register(ctx *Context)
}
@@ -124,7 +124,7 @@
return func() blueprint.Singleton {
singleton := factory()
if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
- registerSingletonMakeVarsProvider(ctx.config, makevars)
+ ctx.registerSingletonMakeVarsProvider(makevars)
}
return &singletonAdaptor{Singleton: singleton}
}
@@ -208,6 +208,14 @@
singletons.registerAll(ctx)
}
+func (ctx *Context) Config() Config {
+ return ctx.config
+}
+
+func (ctx *Context) registerSingletonMakeVarsProvider(makevars SingletonMakeVarsProvider) {
+ registerSingletonMakeVarsProvider(ctx.config, makevars)
+}
+
func collateGloballyRegisteredSingletons() sortableComponents {
allSingletons := append(sortableComponents(nil), singletons...)
allSingletons = append(allSingletons,
@@ -335,7 +343,7 @@
PreArchMutators(f)
}
-func (ctx *initRegistrationContext) HardCodedPreArchMutators(f RegisterMutatorFunc) {
+func (ctx *initRegistrationContext) HardCodedPreArchMutators(_ RegisterMutatorFunc) {
// Nothing to do as the mutators are hard code in preArch in mutator.go
}
diff --git a/apex/apex.go b/apex/apex.go
index 36ce658..fcac3ab 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1875,6 +1875,17 @@
bazelCtx.QueueBazelRequest(a.GetBazelLabel(ctx, a), cquery.GetApexInfo, android.GetConfigKey(ctx))
}
+// GetBazelLabel returns the bazel label of this apexBundle, or the label of the
+// override_apex module overriding this apexBundle. An apexBundle can be
+// overridden by different override_apex modules (e.g. Google or Go variants),
+// which is handled by the overrides mutators.
+func (a *apexBundle) GetBazelLabel(ctx android.BazelConversionPathContext, module blueprint.Module) string {
+ if _, ok := ctx.Module().(android.OverridableModule); ok {
+ return android.MaybeBp2buildLabelOfOverridingModule(ctx)
+ }
+ return a.BazelModuleBase.GetBazelLabel(ctx, a)
+}
+
func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
if !a.commonBuildActions(ctx) {
return
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c0bdfc4..499d753 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -29,7 +29,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel/cquery"
"android/soong/bpf"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -9804,98 +9803,3 @@
libcCoreVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "core variant should link against source libc", true, hasDep(libfooCoreVariant, libcCoreVariant))
}
-
-func TestApexImageInMixedBuilds(t *testing.T) {
- bp := `
-apex_key{
- name: "foo_key",
-}
-apex {
- name: "foo",
- key: "foo_key",
- updatable: true,
- min_sdk_version: "31",
- file_contexts: ":myapex-file_contexts",
- bazel_module: { label: "//:foo" },
-}`
-
- outputBaseDir := "out/bazel"
- result := android.GroupFixturePreparers(
- prepareForApexTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToApexInfo: map[string]cquery.ApexInfo{
- "//:foo": cquery.ApexInfo{
- SignedOutput: "signed_out.apex",
- UnsignedOutput: "unsigned_out.apex",
- BundleKeyInfo: []string{"public_key", "private_key"},
- ContainerKeyInfo: []string{"container_cert", "container_private"},
- SymbolsUsedByApex: "foo_using.txt",
- JavaSymbolsUsedByApex: "foo_using.xml",
- BundleFile: "apex_bundle.zip",
- InstalledFiles: "installed-files.txt",
- RequiresLibs: []string{"//path/c:c", "//path/d:d"},
-
- // unused
- PackageName: "pkg_name",
- ProvidesLibs: []string{"a", "b"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- m := result.ModuleForTests("foo", "android_common_foo_image").Module()
- ab, ok := m.(*apexBundle)
- if !ok {
- t.Fatalf("Expected module to be an apexBundle, was not")
- }
-
- if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
- t.Errorf("Expected public key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
- t.Errorf("Expected private key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
- t.Errorf("Expected public container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
- t.Errorf("Expected private container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
- t.Errorf("Expected installed-files.txt %q, got %q", w, g)
- }
-
- mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
- var builder strings.Builder
- mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
-
- data := builder.String()
- if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
- if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
- if w := "LOCAL_REQUIRED_MODULES := c d"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
- }
-}
diff --git a/apex/bp2build_test.go b/apex/bp2build_test.go
new file mode 100644
index 0000000..58f30bd
--- /dev/null
+++ b/apex/bp2build_test.go
@@ -0,0 +1,238 @@
+// Copyright 2022 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 apex
+
+import (
+ "android/soong/android"
+ "android/soong/bazel/cquery"
+ "strings"
+ "testing"
+)
+
+func TestApexImageInMixedBuilds(t *testing.T) {
+ bp := `
+apex_key{
+ name: "foo_key",
+}
+apex {
+ name: "foo",
+ key: "foo_key",
+ updatable: true,
+ min_sdk_version: "31",
+ file_contexts: ":myapex-file_contexts",
+ bazel_module: { label: "//:foo" },
+}`
+
+ outputBaseDir := "out/bazel"
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outputBaseDir,
+ LabelToApexInfo: map[string]cquery.ApexInfo{
+ "//:foo": cquery.ApexInfo{
+ SignedOutput: "signed_out.apex",
+ UnsignedOutput: "unsigned_out.apex",
+ BundleKeyInfo: []string{"public_key", "private_key"},
+ ContainerKeyInfo: []string{"container_cert", "container_private"},
+ SymbolsUsedByApex: "foo_using.txt",
+ JavaSymbolsUsedByApex: "foo_using.xml",
+ BundleFile: "apex_bundle.zip",
+ InstalledFiles: "installed-files.txt",
+ RequiresLibs: []string{"//path/c:c", "//path/d:d"},
+
+ // unused
+ PackageName: "pkg_name",
+ ProvidesLibs: []string{"a", "b"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ m := result.ModuleForTests("foo", "android_common_foo_image").Module()
+ ab, ok := m.(*apexBundle)
+ if !ok {
+ t.Fatalf("Expected module to be an apexBundle, was not")
+ }
+
+ if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
+ t.Errorf("Expected public key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
+ t.Errorf("Expected private key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
+ t.Errorf("Expected public container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
+ t.Errorf("Expected private container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
+ t.Errorf("Expected installed-files.txt %q, got %q", w, g)
+ }
+
+ mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
+ var builder strings.Builder
+ mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
+
+ data := builder.String()
+ if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
+ if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
+ if w := "LOCAL_REQUIRED_MODULES := c d"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
+ }
+}
+
+func TestOverrideApexImageInMixedBuilds(t *testing.T) {
+ bp := `
+apex_key{
+ name: "foo_key",
+}
+apex_key{
+ name: "override_foo_key",
+}
+apex {
+ name: "foo",
+ key: "foo_key",
+ updatable: true,
+ min_sdk_version: "31",
+ package_name: "pkg_name",
+ file_contexts: ":myapex-file_contexts",
+ bazel_module: { label: "//:foo" },
+}
+override_apex {
+ name: "override_foo",
+ key: "override_foo_key",
+ package_name: "override_pkg_name",
+ base: "foo",
+ bazel_module: { label: "//:override_foo" },
+}
+`
+
+ outputBaseDir := "out/bazel"
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outputBaseDir,
+ LabelToApexInfo: map[string]cquery.ApexInfo{
+ "//:foo": cquery.ApexInfo{
+ SignedOutput: "signed_out.apex",
+ UnsignedOutput: "unsigned_out.apex",
+ BundleKeyInfo: []string{"public_key", "private_key"},
+ ContainerKeyInfo: []string{"container_cert", "container_private"},
+ SymbolsUsedByApex: "foo_using.txt",
+ JavaSymbolsUsedByApex: "foo_using.xml",
+ BundleFile: "apex_bundle.zip",
+ InstalledFiles: "installed-files.txt",
+ RequiresLibs: []string{"//path/c:c", "//path/d:d"},
+
+ // unused
+ PackageName: "pkg_name",
+ ProvidesLibs: []string{"a", "b"},
+ },
+ "//:override_foo": cquery.ApexInfo{
+ SignedOutput: "override_signed_out.apex",
+ UnsignedOutput: "override_unsigned_out.apex",
+ BundleKeyInfo: []string{"override_public_key", "override_private_key"},
+ ContainerKeyInfo: []string{"override_container_cert", "override_container_private"},
+ SymbolsUsedByApex: "override_foo_using.txt",
+ JavaSymbolsUsedByApex: "override_foo_using.xml",
+ BundleFile: "override_apex_bundle.zip",
+ InstalledFiles: "override_installed-files.txt",
+ RequiresLibs: []string{"//path/c:c", "//path/d:d"},
+
+ // unused
+ PackageName: "override_pkg_name",
+ ProvidesLibs: []string{"a", "b"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ m := result.ModuleForTests("foo", "android_common_override_foo_foo_image").Module()
+ ab, ok := m.(*apexBundle)
+ if !ok {
+ t.Fatalf("Expected module to be an apexBundle, was not")
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_public_key", ab.publicKeyFile.String(); w != g {
+ t.Errorf("Expected public key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_private_key", ab.privateKeyFile.String(); w != g {
+ t.Errorf("Expected private key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_container_cert", ab.containerCertificateFile.String(); w != g {
+ t.Errorf("Expected public container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_container_private", ab.containerPrivateKeyFile.String(); w != g {
+ t.Errorf("Expected private container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_signed_out.apex", ab.outputFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/override_installed-files.txt", ab.installedFilesFile.String(); w != g {
+ t.Errorf("Expected installed-files.txt %q, got %q", w, g)
+ }
+
+ mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
+ var builder strings.Builder
+ mkData.Custom(&builder, "override_foo", "BAZEL_TARGET_", "", mkData)
+
+ data := builder.String()
+ if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/override_apex_bundle.zip"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
+ if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/override_installed-files.txt:override_foo-installed-files.txt)"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
+ if w := "LOCAL_REQUIRED_MODULES := c d"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
+ }
+}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 9feb82b..7c9ae3b 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -11,7 +11,7 @@
GetPythonBinary = &getPythonBinaryRequestType{}
GetCcInfo = &getCcInfoType{}
GetApexInfo = &getApexInfoType{}
- GetCcUnstrippedInfo = &getCcUnstippedInfoType{}
+ GetCcUnstrippedInfo = &getCcUnstrippedInfoType{}
)
type CcInfo struct {
@@ -275,13 +275,13 @@
// getCcUnstrippedInfoType implements cqueryRequest interface. It handles the
// interaction with `bazel cquery` to retrieve CcUnstrippedInfo provided
// by the` cc_binary` and `cc_shared_library` rules.
-type getCcUnstippedInfoType struct{}
+type getCcUnstrippedInfoType struct{}
-func (g getCcUnstippedInfoType) Name() string {
+func (g getCcUnstrippedInfoType) Name() string {
return "getCcUnstrippedInfo"
}
-func (g getCcUnstippedInfoType) StarlarkFunctionBody() string {
+func (g getCcUnstrippedInfoType) StarlarkFunctionBody() string {
return `unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
p = providers(target)
output_path = target.files.to_list()[0].path
@@ -298,7 +298,7 @@
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
-func (g getCcUnstippedInfoType) ParseResult(rawString string) (CcUnstrippedInfo, error) {
+func (g getCcUnstrippedInfoType) ParseResult(rawString string) (CcUnstrippedInfo, error) {
var info CcUnstrippedInfo
err := parseJson(rawString, &info)
return info, err
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 8c2d30d..b20f6ff 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -26,6 +26,7 @@
type ccTestBp2buildTestCase struct {
description string
blueprint string
+ filesystem map[string]string
targets []testBazelTarget
}
@@ -41,12 +42,12 @@
func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) {
t.Helper()
moduleTypeUnderTest := "cc_test"
-
description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description)
t.Run(description, func(t *testing.T) {
t.Helper()
RunBp2BuildTestCase(t, registerCcTestModuleTypes, Bp2buildTestCase{
ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostAndDeviceSupported),
+ Filesystem: testCase.filesystem,
ModuleTypeUnderTest: moduleTypeUnderTest,
ModuleTypeUnderTestFactory: cc.TestFactory,
Description: description,
@@ -172,3 +173,90 @@
},
})
}
+
+func TestCcTest_TestConfig(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test that sets a test_config",
+ filesystem: map[string]string{
+ "test_config.xml": "",
+ },
+ blueprint: `
+cc_test {
+ name: "mytest",
+ srcs: ["test.cpp"],
+ test_config: "test_config.xml",
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "gtest": "True",
+ "isolated": "True",
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ "test_config": `"test_config.xml"`,
+ },
+ },
+ },
+ })
+}
+
+func TestCcTest_TestConfigAndroidTestXML(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test that defaults to test config AndroidTest.xml",
+ filesystem: map[string]string{
+ "AndroidTest.xml": "",
+ },
+ blueprint: `
+cc_test {
+ name: "mytest",
+ srcs: ["test.cpp"],
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "gtest": "True",
+ "isolated": "True",
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ "test_config": `"AndroidTest.xml"`,
+ },
+ },
+ },
+ })
+}
+
+func TestCcTest_TestConfigTemplateOptions(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test that sets test config template attributes",
+ filesystem: map[string]string{
+ "test_config_template.xml": "",
+ },
+ blueprint: `
+cc_test {
+ name: "mytest",
+ srcs: ["test.cpp"],
+ test_config_template: "test_config_template.xml",
+ auto_gen_config: true,
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "auto_generate_test_config": "True",
+ "gtest": "True",
+ "isolated": "True",
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ "template_configs": `[
+ "'<target_preparer class=\"com.android.tradefed.targetprep.RootTargetPreparer\">\\n <option name=\"force-root\" value=\"false\" />\\n </target_preparer>'",
+ "'<option name=\"not-shardable\" value=\"true\" />'",
+ ]`,
+ "template_install_base": `"/data/local/tmp"`,
+ "template_test_config": `"test_config_template.xml"`,
+ },
+ },
+ },
+ })
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6eb93bc..e15dd59 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -55,6 +55,10 @@
files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
+ // TODO(b/262781701): Create an alternate soong_build entrypoint for writing out these files only when requested
+ files = append(files, newFile("allowlists", "mixed_build_prod_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelProdMode), "\n")+"\n"))
+ files = append(files, newFile("allowlists", "mixed_build_staging_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelStagingMode), "\n")+"\n"))
+
return files
}
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 8de2f83..dfc7f0b 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -147,6 +147,14 @@
dir: "api_levels",
basename: "api_levels.bzl",
},
+ {
+ dir: "allowlists",
+ basename: "mixed_build_prod_allowlist.txt",
+ },
+ {
+ dir: "allowlists",
+ basename: "mixed_build_staging_allowlist.txt",
+ },
}
if len(files) != len(expectedFilePaths) {
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index f5d27ff..335910c 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -38,6 +38,7 @@
}
func TestAfdoDeps(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "libTest",
@@ -93,6 +94,7 @@
}
func TestAfdoEnabledOnStaticDepNoAfdo(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "libTest",
diff --git a/cc/binary_test.go b/cc/binary_test.go
index db6fb3a..43aff5c 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -22,6 +22,7 @@
)
func TestCcBinaryWithBazel(t *testing.T) {
+ t.Parallel()
bp := `
cc_binary {
name: "foo",
@@ -55,6 +56,7 @@
}
func TestBinaryLinkerScripts(t *testing.T) {
+ t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
cc_binary {
name: "foo",
diff --git a/cc/cc.go b/cc/cc.go
index 632bdca..6ca2575 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1858,7 +1858,22 @@
c.bazelHandler.QueueBazelCall(ctx, c.getBazelModuleLabel(ctx))
}
+var (
+ mixedBuildSupportedCcTest = []string{
+ "adbd_test",
+ }
+)
+
+// IsMixedBuildSupported returns true if the module should be analyzed by Bazel
+// in any of the --bazel-mode(s). This filters at the module level and takes
+// precedence over the allowlists in allowlists/allowlists.go.
func (c *Module) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+ if c.testBinary() && !android.InList(c.Name(), mixedBuildSupportedCcTest) {
+ // Per-module rollout of mixed-builds for cc_test modules.
+ return false
+ }
+
+ // Enable mixed builds as long as the cc_* module type has a bazel handler.
return c.bazelHandler != nil
}
@@ -1888,6 +1903,8 @@
}
mctx.ctx = mctx
+ // TODO(b/244432500): Get the tradefed config from the bazel target instead
+ // of generating it with Soong.
c.maybeInstall(mctx, apexInfo)
}
@@ -2038,6 +2055,9 @@
}
}
+// maybeInstall is called at the end of both GenerateAndroidBuildActions and
+// ProcessBazelQueryResponse to run the install hooks for installable modules,
+// like binaries and tests.
func (c *Module) maybeInstall(ctx ModuleContext, apexInfo android.ApexInfo) {
if !proptools.BoolDefault(c.Installable(), true) {
// If the module has been specifically configure to not be installed then
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 6a22bd0..6dfd395 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -154,6 +154,7 @@
}
func TestVendorSrc(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library {
name: "libTest",
@@ -220,6 +221,7 @@
}
func TestInstallPartition(t *testing.T) {
+ t.Parallel()
t.Helper()
ctx := prepareForCcTest.RunTestWithBp(t, `
cc_library {
@@ -352,6 +354,7 @@
}
func TestVndk(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libvndk",
@@ -569,6 +572,7 @@
}
func TestVndkWithHostSupported(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library {
name: "libvndk_host_supported",
@@ -605,6 +609,7 @@
}
func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
+ t.Parallel()
bp := `
llndk_libraries_txt {
name: "llndk.libraries.txt",
@@ -621,6 +626,7 @@
}
func TestVndkUsingCoreVariant(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libvndk",
@@ -673,6 +679,7 @@
}
func TestDataLibs(t *testing.T) {
+ t.Parallel()
bp := `
cc_test_library {
name: "test_lib",
@@ -723,6 +730,7 @@
}
func TestDataLibsRelativeInstallPath(t *testing.T) {
+ t.Parallel()
bp := `
cc_test_library {
name: "test_lib",
@@ -781,6 +789,7 @@
}
func TestTestBinaryTestSuites(t *testing.T) {
+ t.Parallel()
bp := `
cc_test {
name: "main_test",
@@ -812,6 +821,7 @@
}
func TestTestLibraryTestSuites(t *testing.T) {
+ t.Parallel()
bp := `
cc_test_library {
name: "main_test_lib",
@@ -843,6 +853,7 @@
}
func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
+ t.Parallel()
ctx := testCcNoVndk(t, `
cc_library {
name: "libvndk",
@@ -899,6 +910,7 @@
}
func TestVndkModuleError(t *testing.T) {
+ t.Parallel()
// Check the error message for vendor_available and product_available properties.
testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
cc_library {
@@ -940,6 +952,7 @@
}
func TestVndkDepError(t *testing.T) {
+ t.Parallel()
// Check whether an error is emitted when a VNDK lib depends on a system lib.
testCcError(t, "dependency \".*\" of \".*\" missing variant", `
cc_library {
@@ -1131,6 +1144,7 @@
}
func TestDoubleLoadbleDep(t *testing.T) {
+ t.Parallel()
// okay to link : LLNDK -> double_loadable VNDK
testCc(t, `
cc_library {
@@ -1235,6 +1249,7 @@
}
func TestDoubleLoadableDepError(t *testing.T) {
+ t.Parallel()
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
cc_library {
@@ -1317,6 +1332,7 @@
}
func TestCheckVndkMembershipBeforeDoubleLoadable(t *testing.T) {
+ t.Parallel()
testCcError(t, "module \"libvndksp\" variant .*: .*: VNDK-SP must only depend on VNDK-SP", `
cc_library {
name: "libvndksp",
@@ -1342,6 +1358,7 @@
}
func TestVndkExt(t *testing.T) {
+ t.Parallel()
// This test checks the VNDK-Ext properties.
bp := `
cc_library {
@@ -1429,6 +1446,7 @@
}
func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
+ t.Parallel()
// This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
ctx := testCcNoVndk(t, `
cc_library {
@@ -1460,6 +1478,7 @@
}
func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
+ t.Parallel()
// This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
ctx := testCcNoProductVndk(t, `
cc_library {
@@ -1491,6 +1510,7 @@
}
func TestVndkExtError(t *testing.T) {
+ t.Parallel()
// This test ensures an error is emitted in ill-formed vndk-ext definition.
testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
cc_library {
@@ -1581,6 +1601,7 @@
}
func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
+ t.Parallel()
// This test ensures an error is emitted for inconsistent support_system_process.
testCcError(t, "module \".*\" with mismatched support_system_process", `
cc_library {
@@ -1630,6 +1651,7 @@
}
func TestVndkExtVendorAvailableFalseError(t *testing.T) {
+ t.Parallel()
// This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
// with `private: true`.
testCcError(t, "`extends` refers module \".*\" which has `private: true`", `
@@ -1680,6 +1702,7 @@
}
func TestVendorModuleUseVndkExt(t *testing.T) {
+ t.Parallel()
// This test ensures a vendor module can depend on a VNDK-Ext library.
testCc(t, `
cc_library {
@@ -1734,6 +1757,7 @@
}
func TestVndkExtUseVendorLib(t *testing.T) {
+ t.Parallel()
// This test ensures a VNDK-Ext library can depend on a vendor library.
testCc(t, `
cc_library {
@@ -1798,6 +1822,7 @@
}
func TestProductVndkExtDependency(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libvndk",
@@ -1865,6 +1890,7 @@
}
func TestVndkSpExtUseVndkError(t *testing.T) {
+ t.Parallel()
// This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
// library.
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
@@ -1951,6 +1977,7 @@
}
func TestVndkUseVndkExtError(t *testing.T) {
+ t.Parallel()
// This test ensures an error is emitted if a VNDK/VNDK-SP library depends on a
// VNDK-Ext/VNDK-SP-Ext library.
testCcError(t, "dependency \".*\" of \".*\" missing variant", `
@@ -2096,6 +2123,7 @@
}
func TestEnforceProductVndkVersion(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libllndk",
@@ -2221,6 +2249,7 @@
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
+ t.Parallel()
testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
cc_library {
name: "libprod",
@@ -2318,6 +2347,7 @@
}
func TestMakeLinkType(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libvndk",
@@ -2609,6 +2639,7 @@
}
func TestStaticLibDepReordering(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library {
name: "a",
@@ -2648,6 +2679,7 @@
}
func TestStaticLibDepReorderingWithShared(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library {
name: "a",
@@ -2695,6 +2727,7 @@
}
func TestLlndkLibrary(t *testing.T) {
+ t.Parallel()
result := prepareForCcTest.RunTestWithBp(t, `
cc_library {
name: "libllndk",
@@ -2782,6 +2815,7 @@
}
func TestLlndkHeaders(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_headers {
name: "libllndk_headers",
@@ -2914,6 +2948,7 @@
`
func TestRuntimeLibs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, runtimeLibAndroidBp)
// runtime_libs for core variants use the module names without suffixes.
@@ -2950,6 +2985,7 @@
}
func TestExcludeRuntimeLibs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, runtimeLibAndroidBp)
variant := "android_arm64_armv8-a_shared"
@@ -2962,6 +2998,7 @@
}
func TestRuntimeLibsNoVndk(t *testing.T) {
+ t.Parallel()
ctx := testCcNoVndk(t, runtimeLibAndroidBp)
// If DeviceVndkVersion is not defined, then runtime_libs are copied as-is.
@@ -3002,6 +3039,7 @@
`
func TestStaticLibDepExport(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, staticLibAndroidBp)
// Check the shared version of lib2.
@@ -3089,6 +3127,7 @@
}
func TestCompilerFlags(t *testing.T) {
+ t.Parallel()
for _, testCase := range compilerFlagsTestCases {
ctx := &mockContext{result: true}
CheckBadCompilerFlags(ctx, "", []string{testCase.in})
@@ -3102,6 +3141,7 @@
}
func TestRecovery(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_shared {
name: "librecovery",
@@ -3137,6 +3177,7 @@
}
func TestDataLibsPrebuiltSharedTestLibrary(t *testing.T) {
+ t.Parallel()
bp := `
cc_prebuilt_test_library_shared {
name: "test_lib",
@@ -3183,6 +3224,7 @@
}
func TestVersionedStubs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_shared {
name: "libFoo",
@@ -3249,6 +3291,7 @@
}
func TestVersioningMacro(t *testing.T) {
+ t.Parallel()
for _, tc := range []struct{ moduleName, expected string }{
{"libc", "__LIBC_API__"},
{"libfoo", "__LIBFOO_API__"},
@@ -3269,6 +3312,7 @@
}
func TestStaticLibArchiveArgs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_static {
name: "foo",
@@ -3309,6 +3353,7 @@
}
func TestSharedLibLinkingArgs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_static {
name: "foo",
@@ -3357,6 +3402,7 @@
}
func TestStaticExecutable(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_binary {
name: "static_test",
@@ -3382,6 +3428,7 @@
}
func TestStaticDepsOrderWithStubs(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_binary {
name: "mybin",
@@ -3422,6 +3469,7 @@
}
func TestErrorsIfAModuleDependsOnDisabled(t *testing.T) {
+ t.Parallel()
testCcError(t, `module "libA" .* depends on disabled module "libB"`, `
cc_library {
name: "libA",
@@ -3549,10 +3597,12 @@
}
func TestAFLFuzzTargetForDevice(t *testing.T) {
+ t.Parallel()
VerifyAFLFuzzTargetVariant(t, "android_arm64_armv8-a")
}
func TestAFLFuzzTargetForLinuxHost(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("requires linux")
}
@@ -3563,6 +3613,7 @@
// Simple smoke test for the cc_fuzz target that ensures the rule compiles
// correctly.
func TestFuzzTarget(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_fuzz {
name: "fuzz_smoke_test",
@@ -3573,9 +3624,6 @@
ctx.ModuleForTests("fuzz_smoke_test", variant).Rule("cc")
}
-func TestAidl(t *testing.T) {
-}
-
func assertString(t *testing.T, got, expected string) {
t.Helper()
if got != expected {
@@ -3604,6 +3652,7 @@
}
func TestDefaults(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_defaults {
name: "defaults",
@@ -3663,6 +3712,7 @@
}
func TestProductVariableDefaults(t *testing.T) {
+ t.Parallel()
bp := `
cc_defaults {
name: "libfoo_defaults",
@@ -3724,6 +3774,7 @@
}
func TestInstallSharedLibs(t *testing.T) {
+ t.Parallel()
bp := `
cc_binary {
name: "bin",
@@ -3819,6 +3870,7 @@
}
func TestStubsLibReexportsHeaders(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_shared {
name: "libclient",
@@ -3851,6 +3903,7 @@
}
func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library {
name: "libfoo",
@@ -3869,6 +3922,7 @@
}
func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
+ t.Parallel()
for _, tc := range []struct {
name string
sdkVersion string
@@ -3921,6 +3975,7 @@
}
func TestMinSdkVersionInClangTriple(t *testing.T) {
+ t.Parallel()
ctx := testCc(t, `
cc_library_shared {
name: "libfoo",
@@ -3933,6 +3988,7 @@
}
func TestNonDigitMinSdkVersionInClangTriple(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "libfoo",
@@ -3952,6 +4008,7 @@
}
func TestIncludeDirsExporting(t *testing.T) {
+ t.Parallel()
// Trim spaces from the beginning, end and immediately after any newline characters. Leaves
// embedded newline characters alone.
@@ -4223,6 +4280,7 @@
}
func TestIncludeDirectoryOrdering(t *testing.T) {
+ t.Parallel()
baseExpectedFlags := []string{
"${config.ArmThumbCflags}",
"${config.ArmCflags}",
@@ -4426,6 +4484,7 @@
}
func TestCcBuildBrokenClangProperty(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
clang bool
@@ -4476,6 +4535,7 @@
}
func TestCcBuildBrokenClangAsFlags(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
clangAsFlags []string
@@ -4521,6 +4581,7 @@
}
func TestCcBuildBrokenClangCFlags(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
clangCFlags []string
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
index 3e448ba..1924b2f 100644
--- a/cc/library_headers_test.go
+++ b/cc/library_headers_test.go
@@ -59,6 +59,7 @@
}
func TestPrebuiltLibraryHeadersPreferred(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_headers {
name: "headers",
diff --git a/cc/library_test.go b/cc/library_test.go
index 2bc9967..dab5bb8 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -23,6 +23,7 @@
)
func TestLibraryReuse(t *testing.T) {
+ t.Parallel()
t.Run("simple", func(t *testing.T) {
ctx := testCc(t, `
cc_library {
@@ -191,6 +192,7 @@
}
func TestStubsVersions(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libfoo",
@@ -214,6 +216,7 @@
}
func TestStubsVersions_NotSorted(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libfoo",
@@ -229,6 +232,7 @@
}
func TestStubsVersions_ParseError(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "libfoo",
@@ -243,6 +247,7 @@
}
func TestCcLibraryWithBazel(t *testing.T) {
+ t.Parallel()
bp := `
cc_library {
name: "foo",
@@ -304,6 +309,7 @@
}
func TestLibraryVersionScript(t *testing.T) {
+ t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
cc_library {
name: "libfoo",
@@ -321,6 +327,7 @@
}
func TestLibraryDynamicList(t *testing.T) {
+ t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
cc_library {
name: "libfoo",
@@ -338,6 +345,7 @@
}
func TestCcLibrarySharedWithBazel(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "foo",
@@ -383,6 +391,7 @@
}
func TestWholeStaticLibPrebuilts(t *testing.T) {
+ t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
cc_prebuilt_library_static {
name: "libprebuilt",
diff --git a/cc/lto_test.go b/cc/lto_test.go
index afd2c77..fbd91be 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -23,6 +23,7 @@
)
func TestThinLtoDeps(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "lto_enabled",
@@ -106,6 +107,7 @@
}
func TestThinLtoOnlyOnStaticDep(t *testing.T) {
+ t.Parallel()
bp := `
cc_library_shared {
name: "root",
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 143602a..fe592dc 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -86,6 +86,7 @@
}
func TestAsan(t *testing.T) {
+ t.Parallel()
bp := `
cc_binary {
name: "bin_with_asan",
@@ -233,6 +234,7 @@
}
func TestTsan(t *testing.T) {
+ t.Parallel()
bp := `
cc_binary {
name: "bin_with_tsan",
@@ -318,6 +320,7 @@
t.Skip("requires linux")
}
+ t.Parallel()
bp := `
cc_binary {
name: "bin_with_ubsan",
@@ -417,6 +420,7 @@
}
func TestFuzz(t *testing.T) {
+ t.Parallel()
bp := `
cc_binary {
name: "bin_with_fuzzer",
@@ -551,6 +555,7 @@
}
func TestUbsan(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("requires linux")
}
@@ -829,6 +834,7 @@
)
func TestSanitizeMemtagHeap(t *testing.T) {
+ t.Parallel()
variant := "android_arm64_armv8-a"
result := android.GroupFixturePreparers(
@@ -901,6 +907,7 @@
}
func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
+ t.Parallel()
variant := "android_arm64_armv8-a"
result := android.GroupFixturePreparers(
@@ -975,6 +982,7 @@
}
func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
+ t.Parallel()
variant := "android_arm64_armv8-a"
result := android.GroupFixturePreparers(
diff --git a/cc/test.go b/cc/test.go
index 536210b..2a4861c 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -23,6 +23,7 @@
"android/soong/android"
"android/soong/bazel"
+ "android/soong/bazel/cquery"
"android/soong/tradefed"
)
@@ -135,6 +136,7 @@
// static_libs dependency on libgtests unless the gtest flag is set to false.
func TestFactory() android.Module {
module := NewTest(android.HostAndDeviceSupported, true)
+ module.bazelHandler = &ccTestBazelHandler{module: module}
return module.Init()
}
@@ -378,12 +380,6 @@
}
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
- // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
- testInstallBase := "/data/local/tmp"
- if ctx.inVendor() || ctx.useVndk() {
- testInstallBase = "/data/local/tests/vendor"
- }
-
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
for _, dataSrcPath := range dataSrcPaths {
@@ -415,49 +411,9 @@
}
})
- var configs []tradefed.Config
- for _, module := range test.Properties.Test_mainline_modules {
- configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
- }
- if Bool(test.Properties.Require_root) {
- configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
- } else {
- var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
- configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
- }
- if Bool(test.Properties.Disable_framework) {
- var options []tradefed.Option
- configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
- }
- if test.isolated(ctx) {
- configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
- }
- if test.Properties.Test_options.Run_test_as != nil {
- configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(test.Properties.Test_options.Run_test_as)})
- }
- for _, tag := range test.Properties.Test_options.Test_suite_tag {
- configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
- }
- if test.Properties.Test_options.Min_shipping_api_level != nil {
- if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
- ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
- }
- var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)})
- configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
- }
- if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
- var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)})
- configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
- }
- if test.Properties.Test_options.Min_vndk_version != nil {
- var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)})
- options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
- configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
- }
+ useVendor := ctx.inVendor() || ctx.useVndk()
+ testInstallBase := getTestInstallBase(useVendor)
+ configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx))
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
test.Properties.Test_config_template, test.testDecorator.InstallerProperties.Test_suites, configs, test.Properties.Auto_gen_config, testInstallBase)
@@ -479,8 +435,66 @@
test.binaryDecorator.baseInstaller.install(ctx, file)
}
+func getTestInstallBase(useVendor bool) string {
+ // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
+ testInstallBase := "/data/local/tmp"
+ if useVendor {
+ testInstallBase = "/data/local/tests/vendor"
+ }
+ return testInstallBase
+}
+
+func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool) []tradefed.Config {
+ var configs []tradefed.Config
+
+ for _, module := range properties.Test_mainline_modules {
+ configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
+ }
+ if Bool(properties.Require_root) {
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
+ } else {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
+ }
+ if Bool(properties.Disable_framework) {
+ var options []tradefed.Option
+ configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
+ }
+ if isolated {
+ configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
+ }
+ if properties.Test_options.Run_test_as != nil {
+ configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(properties.Test_options.Run_test_as)})
+ }
+ for _, tag := range properties.Test_options.Test_suite_tag {
+ configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
+ }
+ if properties.Test_options.Min_shipping_api_level != nil {
+ if properties.Test_options.Vsr_min_shipping_api_level != nil {
+ ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
+ }
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_shipping_api_level), 10)})
+ configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
+ }
+ if properties.Test_options.Vsr_min_shipping_api_level != nil {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Vsr_min_shipping_api_level), 10)})
+ configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
+ }
+ if properties.Test_options.Min_vndk_version != nil {
+ var options []tradefed.Option
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_vndk_version), 10)})
+ options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
+ configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
+ }
+ return configs
+}
+
func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module {
module, binary := newBinary(hod, bazelable)
+ module.bazelable = bazelable
module.multilib = android.MultilibBoth
binary.baseInstaller = NewTestInstaller()
@@ -637,6 +651,30 @@
return module
}
+type ccTestBazelHandler struct {
+ module *Module
+}
+
+var _ BazelHandler = (*ccTestBazelHandler)(nil)
+
+func (handler *ccTestBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
+}
+
+func (handler *ccTestBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+
+ outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
+ handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
+ handler.module.linker.(*testBinary).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
+}
+
// binaryAttributes contains Bazel attributes corresponding to a cc test
type testBinaryAttributes struct {
binaryAttributes
@@ -645,6 +683,7 @@
Isolated bool
tidyAttributes
+ tradefed.TestConfigAttributes
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
@@ -655,7 +694,6 @@
// TODO(b/244432609): handle `isolated` property.
// TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not
// default to bazel. (see linkerInit function)
-// TODO(b/244432500): handle test.testConfig generation (see install function)
func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
var testBinaryAttrs testBinaryAttributes
testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
@@ -688,6 +726,25 @@
}
}
+ for _, testProps := range m.GetProperties() {
+ if p, ok := testProps.(*TestBinaryProperties); ok {
+ useVendor := false // TODO Bug: 262914724
+ testInstallBase := getTestInstallBase(useVendor)
+ testConfigAttributes := tradefed.GetTestConfigAttributes(
+ ctx,
+ p.Test_config,
+ p.Test_options.Extra_test_configs,
+ p.Auto_gen_config,
+ p.Test_options.Test_suite_tag,
+ p.Test_config_template,
+ getTradefedConfigOptions(ctx, p, testBinaryAttrs.Isolated),
+ &testInstallBase,
+ )
+ testBinaryAttrs.TestConfigAttributes = testConfigAttributes
+ }
+ }
+
+ // TODO (b/262914724): convert to tradefed_cc_test and tradefed_cc_test_host
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "cc_test",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index bea8df0..744a10c 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -18,7 +18,6 @@
"bytes"
"flag"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -38,38 +37,26 @@
var (
topDir string
- outDir string
- soongOutDir string
availableEnvFile string
usedEnvFile string
- runGoTests bool
-
globFile string
globListDir string
delveListen string
delvePath string
- moduleGraphFile string
- moduleActionsFile string
- docFile string
- bazelQueryViewDir string
- bazelApiBp2buildDir string
- bp2buildMarker string
- symlinkForestMarker string
-
- cmdlineArgs bootstrap.Args
+ cmdlineArgs android.CmdArgs
)
func init() {
// Flags that make sense in every mode
flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
- flag.StringVar(&soongOutDir, "soong_out", "", "Soong output directory (usually $TOP/out/soong)")
+ flag.StringVar(&cmdlineArgs.SoongOutDir, "soong_out", "", "Soong output directory (usually $TOP/out/soong)")
flag.StringVar(&availableEnvFile, "available_env", "", "File containing available environment variables")
flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables")
flag.StringVar(&globFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
- flag.StringVar(&outDir, "out", "", "the ninja builddir directory")
+ flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory")
flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse")
// Debug flags
@@ -81,13 +68,13 @@
flag.BoolVar(&cmdlineArgs.NoGC, "nogc", false, "turn off GC for debugging")
// Flags representing various modes soong_build can run in
- flag.StringVar(&moduleGraphFile, "module_graph_file", "", "JSON module graph file to output")
- flag.StringVar(&moduleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
- flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
- flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
- flag.StringVar(&bazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
- flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
- flag.StringVar(&symlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
+ flag.StringVar(&cmdlineArgs.ModuleGraphFile, "module_graph_file", "", "JSON module graph file to output")
+ flag.StringVar(&cmdlineArgs.ModuleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
+ flag.StringVar(&cmdlineArgs.DocFile, "soong_docs", "", "build documentation file to output")
+ flag.StringVar(&cmdlineArgs.BazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
+ flag.StringVar(&cmdlineArgs.BazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
+ flag.StringVar(&cmdlineArgs.Bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
+ flag.StringVar(&cmdlineArgs.SymlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.StringVar(&cmdlineArgs.BazelForceEnabledModules, "bazel-force-enabled-modules", "", "additional modules to build with Bazel. Comma-delimited")
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
@@ -95,9 +82,9 @@
flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
flag.BoolVar(&cmdlineArgs.BazelModeDev, "bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
- // Flags that probably shouldn't be flags of soong_build but we haven't found
+ // Flags that probably shouldn't be flags of soong_build, but we haven't found
// the time to remove them yet
- flag.BoolVar(&runGoTests, "t", false, "build and run go tests during bootstrap")
+ flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
// Disable deterministic randomization in the protobuf package, so incremental
// builds with unrelated Soong changes don't trigger large rebuilds (since we
@@ -118,87 +105,44 @@
return ctx
}
-func newConfig(availableEnv map[string]string) android.Config {
- var buildMode android.SoongBuildMode
- var bazelForceEnabledModules []string
- if len(cmdlineArgs.BazelForceEnabledModules) > 0 {
- bazelForceEnabledModules = strings.Split(cmdlineArgs.BazelForceEnabledModules, ",")
- }
-
- if symlinkForestMarker != "" {
- buildMode = android.SymlinkForest
- } else if bp2buildMarker != "" {
- buildMode = android.Bp2build
- } else if bazelQueryViewDir != "" {
- buildMode = android.GenerateQueryView
- } else if bazelApiBp2buildDir != "" {
- buildMode = android.ApiBp2build
- } else if moduleGraphFile != "" {
- buildMode = android.GenerateModuleGraph
- } else if docFile != "" {
- buildMode = android.GenerateDocFile
- } else if cmdlineArgs.BazelModeDev {
- buildMode = android.BazelDevMode
- } else if cmdlineArgs.BazelMode {
- buildMode = android.BazelProdMode
- } else if cmdlineArgs.BazelModeStaging {
- buildMode = android.BazelStagingMode
- } else {
- buildMode = android.AnalysisNoBazel
- }
-
- configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, buildMode, runGoTests, outDir, soongOutDir, availableEnv, bazelForceEnabledModules)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
- return configuration
-}
-
// Bazel-enabled mode. Attaches a mutator to queue Bazel requests, adds a
// BeforePrepareBuildActionsHook to invoke Bazel, and then uses Bazel metadata
// for modules that should be handled by Bazel.
-func runMixedModeBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+func runMixedModeBuild(ctx *android.Context, extraNinjaDeps []string) string {
ctx.EventHandler.Begin("mixed_build")
defer ctx.EventHandler.End("mixed_build")
bazelHook := func() error {
- return configuration.BazelContext.InvokeBazel(configuration, ctx)
+ return ctx.Config().BazelContext.InvokeBazel(ctx.Config(), ctx)
}
ctx.SetBeforePrepareBuildActionsHook(bazelHook)
- ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, ctx.Context, configuration)
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs.Args, bootstrap.DoEverything, ctx.Context, ctx.Config())
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- bazelPaths, err := readBazelPaths(configuration)
+ bazelPaths, err := readFileLines(ctx.Config().Getenv("BAZEL_DEPS_FILE"))
if err != nil {
panic("Bazel deps file not found: " + err.Error())
}
ninjaDeps = append(ninjaDeps, bazelPaths...)
-
- globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
- ninjaDeps = append(ninjaDeps, globListFiles...)
+ ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
return cmdlineArgs.OutFile
}
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
-func runQueryView(queryviewDir, queryviewMarker string, configuration android.Config, ctx *android.Context) {
+func runQueryView(queryviewDir, queryviewMarker string, ctx *android.Context) {
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
- codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.QueryView)
- absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
- if err := createBazelWorkspace(codegenContext, absoluteQueryViewDir); err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
-
+ codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView)
+ err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir))
+ maybeQuit(err, "")
touch(shared.JoinPath(topDir, queryviewMarker))
}
// Run the code-generation phase to convert API contributions to BUILD files.
// Return marker file for the new synthetic workspace
-func runApiBp2build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string {
ctx.EventHandler.Begin("api_bp2build")
defer ctx.EventHandler.End("api_bp2build")
// Do not allow missing dependencies.
@@ -215,28 +159,25 @@
}
// Run the loading and analysis phase
- ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs,
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs.Args,
bootstrap.StopBeforePrepareBuildActions,
ctx.Context,
- configuration)
+ ctx.Config())
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
// Add the globbed dependencies
- globs := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
- ninjaDeps = append(ninjaDeps, globs...)
+ ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
// Run codegen to generate BUILD files
- codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.ApiBp2build)
- absoluteApiBp2buildDir := shared.JoinPath(topDir, bazelApiBp2buildDir)
- if err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir); err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
+ codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build)
+ absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
+ err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir)
+ maybeQuit(err, "")
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
// Create soong_injection repository
- soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CreateCodegenMetrics())
- absoluteSoongInjectionDir := shared.JoinPath(topDir, configuration.SoongOutDir(), bazel.SoongInjectionDirName)
+ soongInjectionFiles := bp2build.CreateSoongInjectionFiles(ctx.Config(), bp2build.CreateCodegenMetrics())
+ absoluteSoongInjectionDir := shared.JoinPath(topDir, ctx.Config().SoongOutDir(), bazel.SoongInjectionDirName)
for _, file := range soongInjectionFiles {
// The API targets in api_bp2build workspace do not have any dependency on api_bp2build.
// But we need to create these files to prevent errors during Bazel analysis.
@@ -246,24 +187,14 @@
writeReadWriteFile(absoluteSoongInjectionDir, file)
}
- workspace := shared.JoinPath(configuration.SoongOutDir(), "api_bp2build")
-
- excludes := bazelArtifacts()
- // Exclude all src BUILD files
- excludes = append(excludes, apiBuildFileExcludes()...)
-
- // Android.bp files for api surfaces are mounted to out/, but out/ should not be a
- // dep for api_bp2build.
- // Otherwise api_bp2build will be run every single time
- excludes = append(excludes, configuration.OutDir())
-
+ workspace := shared.JoinPath(ctx.Config().SoongOutDir(), "api_bp2build")
// Create the symlink forest
symlinkDeps := bp2build.PlantSymlinkForest(
- configuration.IsEnvTrue("BP2BUILD_VERBOSE"),
+ ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE"),
topDir,
workspace,
- bazelApiBp2buildDir,
- excludes)
+ cmdlineArgs.BazelApiBp2buildDir,
+ apiBuildFileExcludes(ctx))
ninjaDeps = append(ninjaDeps, symlinkDeps...)
workspaceMarkerFile := workspace + ".marker"
@@ -274,15 +205,12 @@
// With some exceptions, api_bp2build does not have any dependencies on the checked-in BUILD files
// Exclude them from the generated workspace to prevent unrelated errors during the loading phase
-func apiBuildFileExcludes() []string {
- ret := make([]string, 0)
-
+func apiBuildFileExcludes(ctx *android.Context) []string {
+ ret := bazelArtifacts()
srcs, err := getExistingBazelRelatedFiles(topDir)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
- os.Exit(1)
- }
+ maybeQuit(err, "Error determining existing Bazel-related files")
for _, src := range srcs {
+ // Exclude all src BUILD files
if src != "WORKSPACE" &&
src != "BUILD" &&
src != "BUILD.bazel" &&
@@ -292,6 +220,9 @@
ret = append(ret, src)
}
}
+ // Android.bp files for api surfaces are mounted to out/, but out/ should not be a
+ // dep for api_bp2build. Otherwise, api_bp2build will be run every single time
+ ret = append(ret, ctx.Config().OutDir())
return ret
}
@@ -302,36 +233,30 @@
}
metricsFile := filepath.Join(metricsDir, "soong_build_metrics.pb")
err := android.WriteMetrics(configuration, eventHandler, metricsFile)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
- os.Exit(1)
- }
+ maybeQuit(err, "error writing soong_build metrics %s", metricsFile)
}
-func writeJsonModuleGraphAndActions(ctx *android.Context, graphPath string, actionsPath string) {
- graphFile, graphErr := os.Create(shared.JoinPath(topDir, graphPath))
- actionsFile, actionsErr := os.Create(shared.JoinPath(topDir, actionsPath))
- if graphErr != nil || actionsErr != nil {
- fmt.Fprintf(os.Stderr, "Graph err: %s, actions err: %s", graphErr, actionsErr)
- os.Exit(1)
- }
-
+func writeJsonModuleGraphAndActions(ctx *android.Context, cmdArgs android.CmdArgs) {
+ graphFile, graphErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleGraphFile))
+ maybeQuit(graphErr, "graph err")
defer graphFile.Close()
+ actionsFile, actionsErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleActionsFile))
+ maybeQuit(actionsErr, "actions err")
defer actionsFile.Close()
ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
}
-func writeBuildGlobsNinjaFile(ctx *android.Context, buildDir string, config interface{}) []string {
+func writeBuildGlobsNinjaFile(ctx *android.Context) []string {
ctx.EventHandler.Begin("globs_ninja_file")
defer ctx.EventHandler.End("globs_ninja_file")
- globDir := bootstrap.GlobDirectory(buildDir, globListDir)
+ globDir := bootstrap.GlobDirectory(ctx.Config().SoongOutDir(), globListDir)
bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
GlobLister: ctx.Globs,
GlobFile: globFile,
GlobDir: globDir,
SrcDir: ctx.SrcDir(),
- }, config)
+ }, ctx.Config())
return bootstrap.GlobFileListFiles(globDir)
}
@@ -340,83 +265,50 @@
defer eventHandler.End("ninja_deps")
depFile := shared.JoinPath(topDir, outputFile+".d")
err := deptools.WriteDepFile(depFile, outputFile, ninjaDeps)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", depFile, err)
- os.Exit(1)
- }
-}
-
-// doChosenActivity runs Soong for a specific activity, like bp2build, queryview
-// or the actual Soong build for the build.ninja file. Returns the top level
-// output file of the specific activity.
-func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, metricsDir string) string {
- if configuration.BuildMode == android.SymlinkForest {
- return runSymlinkForestCreation(configuration, ctx, extraNinjaDeps, metricsDir)
- } else if configuration.BuildMode == android.Bp2build {
- // Run the alternate pipeline of bp2build mutators and singleton to convert
- // Blueprint to BUILD files before everything else.
- return runBp2Build(configuration, ctx, extraNinjaDeps, metricsDir)
- } else if configuration.BuildMode == android.ApiBp2build {
- outputFile := runApiBp2build(configuration, ctx, extraNinjaDeps)
- writeMetrics(configuration, ctx.EventHandler, metricsDir)
- return outputFile
- } else {
- ctx.Register()
-
- var outputFile string
- if configuration.IsMixedBuildsEnabled() {
- outputFile = runMixedModeBuild(configuration, ctx, extraNinjaDeps)
- } else {
- outputFile = runSoongOnlyBuild(configuration, ctx, extraNinjaDeps)
- }
-
- writeMetrics(configuration, ctx.EventHandler, metricsDir)
-
- return outputFile
- }
+ maybeQuit(err, "error writing depfile '%s'", depFile)
}
// runSoongOnlyBuild runs the standard Soong build in a number of different modes.
-func runSoongOnlyBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+func runSoongOnlyBuild(ctx *android.Context, extraNinjaDeps []string) string {
ctx.EventHandler.Begin("soong_build")
defer ctx.EventHandler.End("soong_build")
var stopBefore bootstrap.StopBefore
- if configuration.BuildMode == android.GenerateModuleGraph {
+ switch ctx.Config().BuildMode {
+ case android.GenerateModuleGraph:
stopBefore = bootstrap.StopBeforeWriteNinja
- } else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
+ case android.GenerateQueryView | android.GenerateDocFile:
stopBefore = bootstrap.StopBeforePrepareBuildActions
- } else {
+ default:
stopBefore = bootstrap.DoEverything
}
- ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs.Args, stopBefore, ctx.Context, ctx.Config())
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
+ globListFiles := writeBuildGlobsNinjaFile(ctx)
ninjaDeps = append(ninjaDeps, globListFiles...)
// Convert the Soong module graph into Bazel BUILD files.
- if configuration.BuildMode == android.GenerateQueryView {
- queryviewMarkerFile := bazelQueryViewDir + ".marker"
- runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
+ switch ctx.Config().BuildMode {
+ case android.GenerateQueryView:
+ queryviewMarkerFile := cmdlineArgs.BazelQueryViewDir + ".marker"
+ runQueryView(cmdlineArgs.BazelQueryViewDir, queryviewMarkerFile, ctx)
writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
return queryviewMarkerFile
- } else if configuration.BuildMode == android.GenerateModuleGraph {
- writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
- writeDepFile(moduleGraphFile, ctx.EventHandler, ninjaDeps)
- return moduleGraphFile
- } else if configuration.BuildMode == android.GenerateDocFile {
+ case android.GenerateModuleGraph:
+ writeJsonModuleGraphAndActions(ctx, cmdlineArgs)
+ writeDepFile(cmdlineArgs.ModuleGraphFile, ctx.EventHandler, ninjaDeps)
+ return cmdlineArgs.ModuleGraphFile
+ case android.GenerateDocFile:
// TODO: we could make writeDocs() return the list of documentation files
// written and add them to the .d file. Then soong_docs would be re-run
// whenever one is deleted.
- if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
- fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
- os.Exit(1)
- }
- writeDepFile(docFile, ctx.EventHandler, ninjaDeps)
- return docFile
- } else {
+ err := writeDocs(ctx, shared.JoinPath(topDir, cmdlineArgs.DocFile))
+ maybeQuit(err, "error building Soong documentation")
+ writeDepFile(cmdlineArgs.DocFile, ctx.EventHandler, ninjaDeps)
+ return cmdlineArgs.DocFile
+ default:
// The actual output (build.ninja) was written in the RunBlueprint() call
// above
writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
@@ -442,13 +334,8 @@
fmt.Fprintf(os.Stderr, "--available_env not set\n")
os.Exit(1)
}
-
result, err := shared.EnvFromFile(shared.JoinPath(topDir, availableEnvFile))
- if err != nil {
- fmt.Fprintf(os.Stderr, "error reading available environment file '%s': %s\n", availableEnvFile, err)
- os.Exit(1)
- }
-
+ maybeQuit(err, "error reading available environment file '%s'", availableEnvFile)
return result
}
@@ -459,17 +346,13 @@
android.InitSandbox(topDir)
availableEnv := parseAvailableEnv()
-
- configuration := newConfig(availableEnv)
- extraNinjaDeps := []string{
- configuration.ProductVariablesFileName,
- usedEnvFile,
- }
-
+ configuration, err := android.NewConfig(cmdlineArgs, availableEnv)
+ maybeQuit(err, "")
if configuration.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
configuration.SetAllowMissingDependencies()
}
+ extraNinjaDeps := []string{configuration.ProductVariablesFileName, usedEnvFile}
if shared.IsDebugging() {
// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
// enabled even if it completed successfully.
@@ -478,12 +361,33 @@
// Bypass configuration.Getenv, as LOG_DIR does not need to be dependency tracked. By definition, it will
// change between every CI build, so tracking it would require re-running Soong for every build.
- logDir := availableEnv["LOG_DIR"]
+ metricsDir := availableEnv["LOG_DIR"]
ctx := newContext(configuration)
- finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir)
+ var finalOutputFile string
+ // Run Soong for a specific activity, like bp2build, queryview
+ // or the actual Soong build for the build.ninja file.
+ switch configuration.BuildMode {
+ case android.SymlinkForest:
+ finalOutputFile = runSymlinkForestCreation(ctx, extraNinjaDeps, metricsDir)
+ case android.Bp2build:
+ // Run the alternate pipeline of bp2build mutators and singleton to convert
+ // Blueprint to BUILD files before everything else.
+ finalOutputFile = runBp2Build(ctx, extraNinjaDeps, metricsDir)
+ case android.ApiBp2build:
+ finalOutputFile = runApiBp2build(ctx, extraNinjaDeps)
+ writeMetrics(configuration, ctx.EventHandler, metricsDir)
+ default:
+ ctx.Register()
+ if configuration.IsMixedBuildsEnabled() {
+ finalOutputFile = runMixedModeBuild(ctx, extraNinjaDeps)
+ } else {
+ finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps)
+ }
+ writeMetrics(configuration, ctx.EventHandler, metricsDir)
+ }
writeUsedEnvironmentFile(configuration, finalOutputFile)
}
@@ -494,24 +398,19 @@
path := shared.JoinPath(topDir, usedEnvFile)
data, err := shared.EnvFileContents(configuration.EnvDeps())
- if err != nil {
- fmt.Fprintf(os.Stderr, "error writing used environment file '%s': %s\n", usedEnvFile, err)
- os.Exit(1)
- }
+ maybeQuit(err, "error writing used environment file '%s'\n", usedEnvFile)
if preexistingData, err := os.ReadFile(path); err != nil {
if !os.IsNotExist(err) {
- fmt.Fprintf(os.Stderr, "error reading used environment file '%s': %s\n", usedEnvFile, err)
- os.Exit(1)
+ maybeQuit(err, "error reading used environment file '%s'", usedEnvFile)
}
} else if bytes.Equal(preexistingData, data) {
// used environment file is unchanged
return
}
- if err = os.WriteFile(path, data, 0666); err != nil {
- fmt.Fprintf(os.Stderr, "error writing used environment file '%s': %s\n", usedEnvFile, err)
- os.Exit(1)
- }
+ err = os.WriteFile(path, data, 0666)
+ maybeQuit(err, "error writing used environment file '%s'", usedEnvFile)
+
// Touch the output file so that it's not older than the file we just
// wrote. We can't write the environment file earlier because one an access
// new environment variables while writing it.
@@ -520,88 +419,13 @@
func touch(path string) {
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error touching '%s': %s\n", path, err)
- os.Exit(1)
- }
-
+ maybeQuit(err, "Error touching '%s'", path)
err = f.Close()
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error touching '%s': %s\n", path, err)
- os.Exit(1)
- }
+ maybeQuit(err, "Error touching '%s'", path)
currentTime := time.Now().Local()
err = os.Chtimes(path, currentTime, currentTime)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error touching '%s': %s\n", path, err)
- os.Exit(1)
- }
-}
-
-// Find BUILD files in the srcDir which are not in the allowlist
-// (android.Bp2BuildConversionAllowlist#ShouldKeepExistingBuildFileForDir)
-// and return their paths so they can be left out of the Bazel workspace dir (i.e. ignored)
-func getPathsToIgnoredBuildFiles(config android.Bp2BuildConversionAllowlist, topDir string, srcDirBazelFiles []string, verbose bool) []string {
- paths := make([]string, 0)
-
- for _, srcDirBazelFileRelativePath := range srcDirBazelFiles {
- srcDirBazelFileFullPath := shared.JoinPath(topDir, srcDirBazelFileRelativePath)
- fileInfo, err := os.Stat(srcDirBazelFileFullPath)
- if err != nil {
- // Warn about error, but continue trying to check files
- fmt.Fprintf(os.Stderr, "WARNING: Error accessing path '%s', err: %s\n", srcDirBazelFileFullPath, err)
- continue
- }
- if fileInfo.IsDir() {
- // Don't ignore entire directories
- continue
- }
- if fileInfo.Name() != "BUILD" && fileInfo.Name() != "BUILD.bazel" {
- // Don't ignore this file - it is not a build file
- continue
- }
- if config.ShouldKeepExistingBuildFileForDir(filepath.Dir(srcDirBazelFileRelativePath)) {
- // Don't ignore this existing build file
- continue
- }
- if verbose {
- fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath)
- }
- paths = append(paths, srcDirBazelFileRelativePath)
- }
-
- return paths
-}
-
-// Returns temporary symlink forest excludes necessary for bazel build //external/... (and bazel build //frameworks/...) to work
-func getTemporaryExcludes() []string {
- excludes := make([]string, 0)
-
- // FIXME: 'autotest_lib' is a symlink back to external/autotest, and this causes an infinite symlink expansion error for Bazel
- excludes = append(excludes, "external/autotest/venv/autotest_lib")
- excludes = append(excludes, "external/autotest/autotest_lib")
- excludes = append(excludes, "external/autotest/client/autotest_lib/client")
-
- // FIXME: The external/google-fruit/extras/bazel_root/third_party/fruit dir is poison
- // It contains several symlinks back to real source dirs, and those source dirs contain BUILD files we want to ignore
- excludes = append(excludes, "external/google-fruit/extras/bazel_root/third_party/fruit")
-
- // FIXME: 'frameworks/compile/slang' has a filegroup error due to an escaping issue
- excludes = append(excludes, "frameworks/compile/slang")
-
- // FIXME(b/260809113): 'prebuilts/clang/host/linux-x86/clang-dev' is a tool-generated symlink directory that contains a BUILD file.
- // The bazel files finder code doesn't traverse into symlink dirs, and hence is not aware of this BUILD file and exclude it accordingly
- // during symlink forest generation when checking against keepExistingBuildFiles allowlist.
- //
- // This is necessary because globs in //prebuilts/clang/host/linux-x86/BUILD
- // currently assume no subpackages (keepExistingBuildFile is not recursive for that directory).
- //
- // This is a bandaid until we the symlink forest logic can intelligently exclude BUILD files found in source symlink dirs according
- // to the keepExistingBuildFile allowlist.
- excludes = append(excludes, "prebuilts/clang/host/linux-x86/clang-dev")
-
- return excludes
+ maybeQuit(err, "error touching '%s'", path)
}
// Read the bazel.list file that the Soong Finder already dumped earlier (hopefully)
@@ -612,12 +436,7 @@
// Assume this was a relative path under topDir
bazelFinderFile = filepath.Join(topDir, bazelFinderFile)
}
- data, err := ioutil.ReadFile(bazelFinderFile)
- if err != nil {
- return nil, err
- }
- files := strings.Split(strings.TrimSpace(string(data)), "\n")
- return files, nil
+ return readFileLines(bazelFinderFile)
}
func bazelArtifacts() []string {
@@ -639,41 +458,25 @@
// Ideally, bp2build would write a file that contains instructions to the
// symlink tree creation binary. Then the latter would not need to depend on
// the very heavy-weight machinery of soong_build .
-func runSymlinkForestCreation(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
+func runSymlinkForestCreation(ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
ctx.EventHandler.Do("symlink_forest", func() {
var ninjaDeps []string
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
- generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
- workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
-
- excludes := bazelArtifacts()
-
- if outDir[0] != '/' {
- excludes = append(excludes, outDir)
- }
-
- existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
- os.Exit(1)
- }
-
- pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
- excludes = append(excludes, pathsToIgnoredBuildFiles...)
- excludes = append(excludes, getTemporaryExcludes()...)
+ verbose := ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE")
// PlantSymlinkForest() returns all the directories that were readdir()'ed.
// Such a directory SHOULD be added to `ninjaDeps` so that a child directory
// or file created/deleted under it would trigger an update of the symlink forest.
+ generatedRoot := shared.JoinPath(ctx.Config().SoongOutDir(), "bp2build")
+ workspaceRoot := shared.JoinPath(ctx.Config().SoongOutDir(), "workspace")
ctx.EventHandler.Do("plant", func() {
symlinkForestDeps := bp2build.PlantSymlinkForest(
- configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
+ verbose, topDir, workspaceRoot, generatedRoot, excludedFromSymlinkForest(ctx, verbose))
ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
})
- writeDepFile(symlinkForestMarker, ctx.EventHandler, ninjaDeps)
- touch(shared.JoinPath(topDir, symlinkForestMarker))
+ writeDepFile(cmdlineArgs.SymlinkForestMarker, ctx.EventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, cmdlineArgs.SymlinkForestMarker))
})
codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
if codegenMetrics == nil {
@@ -684,21 +487,84 @@
//invocation of codegen. We should simply use a separate .pb file
}
writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
+ return cmdlineArgs.SymlinkForestMarker
+}
- return symlinkForestMarker
+func excludedFromSymlinkForest(ctx *android.Context, verbose bool) []string {
+ excluded := bazelArtifacts()
+ if cmdlineArgs.OutDir[0] != '/' {
+ excluded = append(excluded, cmdlineArgs.OutDir)
+ }
+
+ // Find BUILD files in the srcDir which are not in the allowlist
+ // (android.Bp2BuildConversionAllowlist#ShouldKeepExistingBuildFileForDir)
+ // and return their paths so they can be left out of the Bazel workspace dir (i.e. ignored)
+ existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
+ maybeQuit(err, "Error determining existing Bazel-related files")
+
+ for _, path := range existingBazelFiles {
+ fullPath := shared.JoinPath(topDir, path)
+ fileInfo, err2 := os.Stat(fullPath)
+ if err2 != nil {
+ // Warn about error, but continue trying to check files
+ fmt.Fprintf(os.Stderr, "WARNING: Error accessing path '%s', err: %s\n", fullPath, err2)
+ continue
+ }
+ // Exclude only files named 'BUILD' or 'BUILD.bazel' and unless forcibly kept
+ if fileInfo.IsDir() ||
+ (fileInfo.Name() != "BUILD" && fileInfo.Name() != "BUILD.bazel") ||
+ ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
+ // Don't ignore this existing build file
+ continue
+ }
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", path)
+ }
+ excluded = append(excluded, path)
+ }
+
+ // Temporarily exclude stuff to make `bazel build //external/...` (and `bazel build //frameworks/...`) work
+ excluded = append(excluded,
+ // FIXME: 'autotest_lib' is a symlink back to external/autotest, and this causes an infinite
+ // symlink expansion error for Bazel
+ "external/autotest/venv/autotest_lib",
+ "external/autotest/autotest_lib",
+ "external/autotest/client/autotest_lib/client",
+
+ // FIXME: The external/google-fruit/extras/bazel_root/third_party/fruit dir is poison
+ // It contains several symlinks back to real source dirs, and those source dirs contain
+ // BUILD files we want to ignore
+ "external/google-fruit/extras/bazel_root/third_party/fruit",
+
+ // FIXME: 'frameworks/compile/slang' has a filegroup error due to an escaping issue
+ "frameworks/compile/slang",
+
+ // FIXME(b/260809113): 'prebuilts/clang/host/linux-x86/clang-dev' is a tool-generated symlink
+ // directory that contains a BUILD file. The bazel files finder code doesn't traverse into symlink dirs,
+ // and hence is not aware of this BUILD file and exclude it accordingly during symlink forest generation
+ // when checking against keepExistingBuildFiles allowlist.
+ //
+ // This is necessary because globs in //prebuilts/clang/host/linux-x86/BUILD
+ // currently assume no subpackages (keepExistingBuildFile is not recursive for that directory).
+ //
+ // This is a bandaid until we the symlink forest logic can intelligently exclude BUILD files found in
+ // source symlink dirs according to the keepExistingBuildFile allowlist.
+ "prebuilts/clang/host/linux-x86/clang-dev",
+ )
+ return excluded
}
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
+func runBp2Build(ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
var codegenMetrics *bp2build.CodegenMetrics
ctx.EventHandler.Do("bp2build", func() {
// Propagate "allow misssing dependencies" bit. This is normally set in
// newContext(), but we create ctx without calling that method.
- ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
- ctx.SetNameInterface(newNameResolver(configuration))
+ ctx.SetAllowMissingDependencies(ctx.Config().AllowMissingDependencies())
+ ctx.SetNameInterface(newNameResolver(ctx.Config()))
ctx.RegisterForBazelConversion()
ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
@@ -710,34 +576,35 @@
// from the regular Modules.
ctx.EventHandler.Do("bootstrap", func() {
blueprintArgs := cmdlineArgs
- bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, ctx.Context, configuration)
+ bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs.Args,
+ bootstrap.StopBeforePrepareBuildActions, ctx.Context, ctx.Config())
ninjaDeps = append(ninjaDeps, bootstrapDeps...)
})
- globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
+ globListFiles := writeBuildGlobsNinjaFile(ctx)
ninjaDeps = append(ninjaDeps, globListFiles...)
// Run the code-generation phase to convert BazelTargetModules to BUILD files
// and print conversion codegenMetrics to the user.
- codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.Bp2Build)
+ codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.Bp2Build)
ctx.EventHandler.Do("codegen", func() {
codegenMetrics = bp2build.Codegen(codegenContext)
})
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
- writeDepFile(bp2buildMarker, ctx.EventHandler, ninjaDeps)
- touch(shared.JoinPath(topDir, bp2buildMarker))
+ writeDepFile(cmdlineArgs.Bp2buildMarker, ctx.EventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, cmdlineArgs.Bp2buildMarker))
})
// Only report metrics when in bp2build mode. The metrics aren't relevant
// for queryview, since that's a total repo-wide conversion and there's a
// 1:1 mapping for each module.
- if configuration.IsEnvTrue("BP2BUILD_VERBOSE") {
+ if ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
codegenMetrics.Print()
}
writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
- return bp2buildMarker
+ return cmdlineArgs.Bp2buildMarker
}
// Write Bp2Build metrics into $LOG_DIR
@@ -756,13 +623,22 @@
codegenMetrics.Write(metricsDir)
}
-func readBazelPaths(configuration android.Config) ([]string, error) {
- depsPath := configuration.Getenv("BAZEL_DEPS_FILE")
-
- data, err := os.ReadFile(depsPath)
- if err != nil {
- return nil, err
+func readFileLines(path string) ([]string, error) {
+ data, err := os.ReadFile(path)
+ if err == nil {
+ return strings.Split(strings.TrimSpace(string(data)), "\n"), nil
}
- paths := strings.Split(strings.TrimSpace(string(data)), "\n")
- return paths, nil
+ return nil, err
+
+}
+func maybeQuit(err error, format string, args ...interface{}) {
+ if err == nil {
+ return
+ }
+ if format != "" {
+ fmt.Fprintln(os.Stderr, fmt.Sprintf(format, args...)+": "+err.Error())
+ } else {
+ fmt.Fprintln(os.Stderr, err)
+ }
+ os.Exit(1)
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 928ae17..713ccbe 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -110,6 +110,15 @@
return indexList(s, list) != -1
}
+func deleteStaleMetrics(metricsFilePathSlice []string) error {
+ for _, metricsFilePath := range metricsFilePathSlice {
+ if err := os.Remove(metricsFilePath); err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("Failed to remove %s\nError message: %w", metricsFilePath, err)
+ }
+ }
+ return nil
+}
+
// Main execution of soong_ui. The command format is as follows:
//
// soong_ui <command> [<arg 1> <arg 2> ... <arg n>]
@@ -117,7 +126,6 @@
// Command is the type of soong_ui execution. Only one type of
// execution is specified. The args are specific to the command.
func main() {
- //TODO(juu): Add logic to soong_ui to delete a hardcoded list of metrics files
shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary())
buildStarted := time.Now()
@@ -187,6 +195,12 @@
bp2buildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bp2build_metrics.pb")
soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb")
+ //Delete the stale metrics files
+ staleFileSlice := []string{buildErrorFile, rbeMetricsFile, soongMetricsFile, bp2buildMetricsFile, soongBuildMetricsFile}
+ if err := deleteStaleMetrics(staleFileSlice); err != nil {
+ log.Fatalln(err)
+ }
+
build.PrintOutDirWarning(buildCtx, config)
os.MkdirAll(logsDir, 0777)
diff --git a/java/aar.go b/java/aar.go
index 0fdde03..8a83792 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -29,8 +29,8 @@
)
type AndroidLibraryDependency interface {
+ LibraryDependency
ExportPackage() android.Path
- ExportedProguardFlagFiles() android.Paths
ExportedRRODirs() []rroDir
ExportedStaticPackages() android.Paths
ExportedManifests() android.Paths
@@ -498,8 +498,7 @@
aarFile android.WritablePath
- exportedProguardFlagFiles android.Paths
- exportedStaticPackages android.Paths
+ exportedStaticPackages android.Paths
}
var _ android.OutputFileProducer = (*AndroidLibrary)(nil)
@@ -514,10 +513,6 @@
}
}
-func (a *AndroidLibrary) ExportedProguardFlagFiles() android.Paths {
- return a.exportedProguardFlagFiles
-}
-
func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
return a.exportedStaticPackages
}
@@ -566,13 +561,16 @@
a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
ctx.VisitDirectDeps(func(m android.Module) {
- if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
- a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
- a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportPackage())
- a.exportedStaticPackages = append(a.exportedStaticPackages, lib.ExportedStaticPackages()...)
+ if ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ if lib, ok := m.(LibraryDependency); ok {
+ a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+ }
+ if alib, ok := m.(AndroidLibraryDependency); ok {
+ a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportPackage())
+ a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportedStaticPackages()...)
+ }
}
})
-
a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
diff --git a/java/app.go b/java/app.go
index a822cbf..eb1b474 100755
--- a/java/app.go
+++ b/java/app.go
@@ -457,7 +457,7 @@
func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
var staticLibProguardFlagFiles android.Paths
ctx.VisitDirectDeps(func(m android.Module) {
- if lib, ok := m.(AndroidLibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ if lib, ok := m.(LibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
}
})
diff --git a/java/app_test.go b/java/app_test.go
index e216c63..bc971e3 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1490,6 +1490,7 @@
testCases := []struct {
name string
bp string
+ allowMissingDependencies bool
certificateOverride string
expectedCertSigningFlags string
expectedCertificate string
@@ -1505,7 +1506,7 @@
`,
certificateOverride: "",
expectedCertSigningFlags: "",
- expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
+ expectedCertificate: "build/make/target/product/security/testkey",
},
{
name: "module certificate property",
@@ -1524,7 +1525,7 @@
`,
certificateOverride: "",
expectedCertSigningFlags: "",
- expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ expectedCertificate: "cert/new_cert",
},
{
name: "path certificate property",
@@ -1538,7 +1539,7 @@
`,
certificateOverride: "",
expectedCertSigningFlags: "",
- expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
+ expectedCertificate: "build/make/target/product/security/expiredkey",
},
{
name: "certificate overrides",
@@ -1557,7 +1558,7 @@
`,
certificateOverride: "foo:new_certificate",
expectedCertSigningFlags: "",
- expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ expectedCertificate: "cert/new_cert",
},
{
name: "certificate signing flags",
@@ -1578,7 +1579,7 @@
`,
certificateOverride: "",
expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
- expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ expectedCertificate: "cert/new_cert",
},
{
name: "cert signing flags from filegroup",
@@ -1604,7 +1605,20 @@
`,
certificateOverride: "",
expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
- expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
+ expectedCertificate: "cert/new_cert",
+ },
+ {
+ name: "missing with AllowMissingDependencies",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ certificate: ":new_certificate",
+ sdk_version: "current",
+ }
+ `,
+ expectedCertificate: "out/soong/.intermediates/foo/android_common/missing",
+ allowMissingDependencies: true,
},
}
@@ -1616,17 +1630,32 @@
if test.certificateOverride != "" {
variables.CertificateOverrides = []string{test.certificateOverride}
}
+ if test.allowMissingDependencies {
+ variables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ }
+ }),
+ android.FixtureModifyContext(func(ctx *android.TestContext) {
+ ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
}),
).RunTestWithBp(t, test.bp)
foo := result.ModuleForTests("foo", "android_common")
- signapk := foo.Output("foo.apk")
- signCertificateFlags := signapk.Args["certificates"]
- android.AssertStringEquals(t, "certificates flags", test.expectedCertificate, signCertificateFlags)
+ certificate := foo.Module().(*AndroidApp).certificate
+ android.AssertPathRelativeToTopEquals(t, "certificates key", test.expectedCertificate+".pk8", certificate.Key)
+ // The sign_target_files_apks and check_target_files_signatures
+ // tools require that certificates have a .x509.pem extension.
+ android.AssertPathRelativeToTopEquals(t, "certificates pem", test.expectedCertificate+".x509.pem", certificate.Pem)
- certSigningFlags := signapk.Args["flags"]
- android.AssertStringEquals(t, "cert signing flags", test.expectedCertSigningFlags, certSigningFlags)
+ signapk := foo.Output("foo.apk")
+ if signapk.Rule != android.ErrorRule {
+ signCertificateFlags := signapk.Args["certificates"]
+ expectedFlags := certificate.Pem.String() + " " + certificate.Key.String()
+ android.AssertStringEquals(t, "certificates flags", expectedFlags, signCertificateFlags)
+
+ certSigningFlags := signapk.Args["flags"]
+ android.AssertStringEquals(t, "cert signing flags", test.expectedCertSigningFlags, certSigningFlags)
+ }
})
}
}
diff --git a/java/dex_test.go b/java/dex_test.go
index 6617873..fc6cd0f 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -155,3 +155,57 @@
android.AssertStringDoesNotContain(t, "expected no static_lib header jar in foo javac classpath",
fooD8.Args["d8Flags"], staticLibHeader.String())
}
+
+func TestProguardFlagsInheritance(t *testing.T) {
+ result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, `
+ android_app {
+ name: "app",
+ static_libs: [
+ "primary_android_lib",
+ "primary_lib",
+ ],
+ platform_apis: true,
+ }
+
+ java_library {
+ name: "primary_lib",
+ optimize: {
+ proguard_flags_files: ["primary.flags"],
+ },
+ }
+
+ android_library {
+ name: "primary_android_lib",
+ static_libs: ["secondary_lib"],
+ optimize: {
+ proguard_flags_files: ["primary_android.flags"],
+ },
+ }
+
+ java_library {
+ name: "secondary_lib",
+ static_libs: ["tertiary_lib"],
+ optimize: {
+ proguard_flags_files: ["secondary.flags"],
+ },
+ }
+
+ java_library {
+ name: "tertiary_lib",
+ optimize: {
+ proguard_flags_files: ["tertiary.flags"],
+ },
+ }
+ `)
+
+ app := result.ModuleForTests("app", "android_common")
+ appR8 := app.Rule("r8")
+ android.AssertStringDoesContain(t, "expected primary_lib's proguard flags from direct dep",
+ appR8.Args["r8Flags"], "primary.flags")
+ android.AssertStringDoesContain(t, "expected primary_android_lib's proguard flags from direct dep",
+ appR8.Args["r8Flags"], "primary_android.flags")
+ android.AssertStringDoesContain(t, "expected secondary_lib's proguard flags from inherited dep",
+ appR8.Args["r8Flags"], "secondary.flags")
+ android.AssertStringDoesContain(t, "expected tertiary_lib's proguard flags from inherited dep",
+ appR8.Args["r8Flags"], "tertiary.flags")
+}
diff --git a/java/java.go b/java/java.go
index 9dd5850..b3abc91 100644
--- a/java/java.go
+++ b/java/java.go
@@ -294,6 +294,11 @@
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
+// Provides transitive Proguard flag files to downstream DEX jars.
+type LibraryDependency interface {
+ ExportedProguardFlagFiles() android.Paths
+}
+
// TODO(jungjw): Move this to kythe.go once it's created.
type xref interface {
XrefJavaFiles() android.Paths
@@ -596,9 +601,17 @@
type Library struct {
Module
+ exportedProguardFlagFiles android.Paths
+
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
}
+var _ LibraryDependency = (*Library)(nil)
+
+func (j *Library) ExportedProguardFlagFiles() android.Paths {
+ return j.exportedProguardFlagFiles
+}
+
var _ android.ApexModule = (*Library)(nil)
// Provides access to the list of permitted packages from apex boot jars.
@@ -694,6 +707,15 @@
}
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
+
+ j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles,
+ android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)...)
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if lib, ok := m.(LibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag {
+ j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
+ }
+ })
+ j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles)
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
index f0336a3..a161108 100644
--- a/tradefed/Android.bp
+++ b/tradefed/Android.bp
@@ -11,6 +11,7 @@
],
srcs: [
"autogen.go",
+ "autogen_bazel.go",
"config.go",
"makevars.go",
],
diff --git a/tradefed/autogen_bazel.go b/tradefed/autogen_bazel.go
new file mode 100644
index 0000000..d3109d9
--- /dev/null
+++ b/tradefed/autogen_bazel.go
@@ -0,0 +1,105 @@
+// Copyright 2022 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 tradefed
+
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+
+ "github.com/google/blueprint/proptools"
+)
+
+const (
+ InstrumentationTestConfigTemplate = "build/make/core/instrumentation_test_config_template.xml"
+ JavaTestConfigTemplate = "build/make/core/java_test_config_template.xml"
+ JavaHostTestConfigTemplate = "build/make/core/java_host_test_config_template.xml"
+ JavaHostUnitTestConfigTemplate = "build/make/core/java_host_unit_test_config_template.xml"
+ NativeBenchmarkTestConfigTemplate = "build/make/core/native_benchmark_test_config_template.xml"
+ NativeHostTestConfigTemplate = "build/make/core/native_host_test_config_template.xml"
+ NativeTestConfigTemplate = "build/make/core/native_test_config_template.xml"
+ PythonBinaryHostTestConfigTemplate = "build/make/core/python_binary_host_test_config_template.xml"
+ RustDeviceTestConfigTemplate = "build/make/core/rust_device_test_config_template.xml"
+ RustHostTestConfigTemplate = "build/make/core/rust_host_test_config_template.xml"
+ RustDeviceBenchmarkConfigTemplate = "build/make/core/rust_device_benchmark_config_template.xml"
+ RustHostBenchmarkConfigTemplate = "build/make/core/rust_host_benchmark_config_template.xml"
+ RobolectricTestConfigTemplate = "build/make/core/robolectric_test_config_template.xml"
+ ShellTestConfigTemplate = "build/make/core/shell_test_config_template.xml"
+)
+
+type TestConfigAttributes struct {
+ Test_config *bazel.Label
+
+ Auto_generate_test_config *bool
+ Template_test_config *bazel.Label
+ Template_configs []string
+ Template_install_base *string
+}
+
+func GetTestConfigAttributes(
+ ctx android.TopDownMutatorContext,
+ testConfig *string,
+ extraTestConfigs []string,
+ autoGenConfig *bool,
+ testSuites []string,
+ template *string,
+ templateConfigs []Config,
+ templateInstallBase *string) TestConfigAttributes {
+
+ attrs := TestConfigAttributes{}
+ attrs.Test_config = GetTestConfig(ctx, testConfig)
+ // do not generate a test config if
+ // 1) test config already found
+ // 2) autoGenConfig == false
+ // 3) CTS tests and no template specified.
+ // CTS Modules can be used for test data, so test config files must be explicitly specified.
+ if (attrs.Template_test_config != nil) ||
+ proptools.Bool(autoGenConfig) == false ||
+ (template == nil && !android.InList("cts", testSuites)) {
+
+ return attrs
+ }
+
+ // Add properties for the bazel rule to generate a test config
+ // since a test config was not specified.
+ templateLabel := android.BazelLabelForModuleSrcSingle(ctx, *template)
+ attrs.Template_test_config = &templateLabel
+ attrs.Auto_generate_test_config = autoGenConfig
+ var configStrings []string
+ for _, c := range templateConfigs {
+ configString := proptools.NinjaAndShellEscape(c.Config())
+ configStrings = append(configStrings, configString)
+ }
+ attrs.Template_configs = configStrings
+ attrs.Template_install_base = templateInstallBase
+ return attrs
+}
+
+func GetTestConfig(
+ ctx android.TopDownMutatorContext,
+ testConfig *string,
+) *bazel.Label {
+
+ if testConfig != nil {
+ c, _ := android.BazelStringOrLabelFromProp(ctx, testConfig)
+ if c.Value != nil {
+ return c.Value
+ }
+ }
+
+ // check for default AndroidTest.xml
+ defaultTestConfigPath := ctx.ModuleDir() + "/AndroidTest.xml"
+ c, _ := android.BazelStringOrLabelFromProp(ctx, &defaultTestConfigPath)
+ return c.Value
+}