Merge "Handle include_build_directory prop in bp2build"
diff --git a/android/Android.bp b/android/Android.bp
index 9f6ae02..2406321 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -13,6 +13,7 @@
"soong-android-soongconfig",
"soong-bazel",
"soong-cquery",
+ "soong-remoteexec",
"soong-shared",
"soong-ui-metrics_proto",
],
diff --git a/android/android_test.go b/android/android_test.go
index 68cb705..fb82e37 100644
--- a/android/android_test.go
+++ b/android/android_test.go
@@ -15,34 +15,10 @@
package android
import (
- "io/ioutil"
"os"
"testing"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_android_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
-
-var emptyTestFixtureFactory = NewFixtureFactory(&buildDir)
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 2f568fb..8eda9b2 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -141,21 +141,17 @@
// bp module and then returns the config and the custom module called "foo".
func buildContextAndCustomModuleFoo(t *testing.T, bp string) (*TestContext, *customModule) {
t.Helper()
- config := TestConfig(buildDir, nil, bp, nil)
- config.katiEnabled = true // Enable androidmk Singleton
+ result := GroupFixturePreparers(
+ // Enable androidmk Singleton
+ PrepareForTestWithAndroidMk,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
- ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
- ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- module := ctx.ModuleForTests("foo", "").Module().(*customModule)
- return ctx, module
+ module := result.ModuleForTests("foo", "").Module().(*customModule)
+ return result.TestContext, module
}
func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
diff --git a/android/apex.go b/android/apex.go
index 79d8cdd..a5ff442 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -140,9 +140,24 @@
// DepIsInSameApex tests if the other module 'dep' is considered as part of the same APEX as
// this module. For example, a static lib dependency usually returns true here, while a
// shared lib dependency to a stub library returns false.
+ //
+ // This method must not be called directly without first ignoring dependencies whose tags
+ // implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
+ // are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
+ // IsDepInSameApex instead.
DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
}
+func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool {
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ if _, ok := depTag.(ExcludeFromApexContentsTag); ok {
+ // The tag defines a dependency that never requires the child module to be part of the same
+ // apex as the parent.
+ return false
+ }
+ return module.(DepIsInSameApex).DepIsInSameApex(ctx, dep)
+}
+
// ApexModule is the interface that a module type is expected to implement if the module has to be
// built differently depending on whether the module is destined for an APEX or not (i.e., installed
// to one of the regular partitions).
@@ -257,6 +272,13 @@
}
// Marker interface that identifies dependencies that are excluded from APEX contents.
+//
+// Unless the tag also implements the AlwaysRequireApexVariantTag this will prevent an apex variant
+// from being created for the module.
+//
+// At the moment the sdk.sdkRequirementsMutator relies on the fact that the existing tags which
+// implement this interface do not define dependencies onto members of an sdk_snapshot. If that
+// changes then sdk.sdkRequirementsMutator will need fixing.
type ExcludeFromApexContentsTag interface {
blueprint.DependencyTag
@@ -264,6 +286,17 @@
ExcludeFromApexContents()
}
+// Marker interface that identifies dependencies that always requires an APEX variant to be created.
+//
+// It is possible for a dependency to require an apex variant but exclude the module from the APEX
+// contents. See sdk.sdkMemberDependencyTag.
+type AlwaysRequireApexVariantTag interface {
+ blueprint.DependencyTag
+
+ // Return true if this tag requires that the target dependency has an apex variant.
+ AlwaysRequireApexVariant() bool
+}
+
// Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex state
// from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if
// their implementation is in an apex.
diff --git a/android/apex_test.go b/android/apex_test.go
index 1f786e6..b5323e8 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -121,7 +121,7 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- config := TestConfig(buildDir, nil, "", nil)
+ config := TestConfig(t.TempDir(), nil, "", nil)
ctx := &configErrorWrapper{config: config}
gotMerged, gotAliases := mergeApexVariations(ctx, tt.in)
if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
diff --git a/android/arch_test.go b/android/arch_test.go
index 4cef4c8..633ddaa 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -273,6 +273,13 @@
return m
}
+var prepareForArchTest = GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("module", archTestModuleFactory)
+ }),
+)
+
func TestArchMutator(t *testing.T) {
var buildOSVariants []string
var buildOS32Variants []string
@@ -309,7 +316,7 @@
testCases := []struct {
name string
- config func(Config)
+ preparer FixturePreparer
fooVariants []string
barVariants []string
bazVariants []string
@@ -317,7 +324,7 @@
}{
{
name: "normal",
- config: nil,
+ preparer: nil,
fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"),
bazVariants: nil,
@@ -325,11 +332,11 @@
},
{
name: "host-only",
- config: func(config Config) {
+ preparer: FixtureModifyConfig(func(config Config) {
config.BuildOSTarget = Target{}
config.BuildOSCommonTarget = Target{}
config.Targets[Android] = nil
- },
+ }),
fooVariants: nil,
barVariants: buildOSVariants,
bazVariants: nil,
@@ -351,19 +358,13 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
- config := TestArchConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("module", archTestModuleFactory)
- ctx.Register()
- if tt.config != nil {
- tt.config(config)
- }
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := GroupFixturePreparers(
+ prepareForArchTest,
+ // Test specific preparer
+ OptionalFixturePreparer(tt.preparer),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+ ctx := result.TestContext
if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
@@ -412,14 +413,14 @@
testCases := []struct {
name string
- config func(Config)
+ preparer FixturePreparer
fooVariants []string
barVariants []string
bazVariants []string
}{
{
name: "normal",
- config: nil,
+ preparer: nil,
fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
@@ -440,19 +441,23 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
- config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
+ result := GroupFixturePreparers(
+ prepareForArchTest,
+ // Test specific preparer
+ OptionalFixturePreparer(tt.preparer),
+ // Prepare for native bridge test
+ FixtureModifyConfig(func(config Config) {
+ config.Targets[Android] = []Target{
+ {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
+ {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false},
+ }
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("module", archTestModuleFactory)
- ctx.Register()
- if tt.config != nil {
- tt.config(config)
- }
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ ctx := result.TestContext
if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
diff --git a/android/config.go b/android/config.go
index f4685a1..0de8928 100644
--- a/android/config.go
+++ b/android/config.go
@@ -19,6 +19,7 @@
import (
"encoding/json"
+ "errors"
"fmt"
"io/ioutil"
"os"
@@ -34,6 +35,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android/soongconfig"
+ "android/soong/remoteexec"
)
// Bool re-exports proptools.Bool for the android package.
@@ -72,6 +74,10 @@
return c.buildDir
}
+func (c Config) DebugCompilation() bool {
+ return false // Never compile Go code in the main build for debugging
+}
+
func (c Config) SrcDir() string {
return c.srcDir
}
@@ -278,23 +284,6 @@
return Config{config}
}
-// TestArchConfigNativeBridge returns a Config object suitable for using
-// for tests that need to run the arch mutator for native bridge supported
-// archs.
-func TestArchConfigNativeBridge(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
- testConfig := TestArchConfig(buildDir, env, bp, fs)
- config := testConfig.config
-
- config.Targets[Android] = []Target{
- {Android, Arch{ArchType: X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
- {Android, Arch{ArchType: X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeEnabled, "x86_64", "arm64", false},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeEnabled, "x86", "arm", false},
- }
-
- return testConfig
-}
-
func fuchsiaTargets() map[OsType][]Target {
return map[OsType][]Target{
Fuchsia: {
@@ -1017,7 +1006,7 @@
}
func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
- return ExistentPathForSource(ctx, "frameworks", "base").Valid()
+ return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid()
}
func (c *config) VndkSnapshotBuildArtifacts() bool {
@@ -1400,7 +1389,10 @@
}
func (c *deviceConfig) BoardSepolicyVers() string {
- return String(c.config.productVariables.BoardSepolicyVers)
+ if ver := String(c.config.productVariables.BoardSepolicyVers); ver != "" {
+ return ver
+ }
+ return c.PlatformSepolicyVersion()
}
func (c *deviceConfig) BoardReqdMaskPolicy() []string {
@@ -1487,10 +1479,30 @@
return uncheckedFinalApiLevel(apiLevel)
}
+func (c *deviceConfig) BuildBrokenEnforceSyspropOwner() bool {
+ return c.config.productVariables.BuildBrokenEnforceSyspropOwner
+}
+
+func (c *deviceConfig) BuildBrokenTrebleSyspropNeverallow() bool {
+ return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
+}
+
func (c *deviceConfig) BuildBrokenVendorPropertyNamespace() bool {
return c.config.productVariables.BuildBrokenVendorPropertyNamespace
}
+func (c *deviceConfig) RequiresInsecureExecmemForSwiftshader() bool {
+ return c.config.productVariables.RequiresInsecureExecmemForSwiftshader
+}
+
+func (c *config) SelinuxIgnoreNeverallows() bool {
+ return c.productVariables.SelinuxIgnoreNeverallows
+}
+
+func (c *deviceConfig) SepolicySplit() bool {
+ return c.config.productVariables.SepolicySplit
+}
+
// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
// Such lists are used in the build system for things like bootclasspath jars or system server jars.
// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
@@ -1635,6 +1647,20 @@
return nil
}
+func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
+ if len(l.apexes) != len(l.jars) {
+ return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars))
+ }
+
+ list := make([]string, 0, len(l.apexes))
+
+ for i := 0; i < len(l.apexes); i++ {
+ list = append(list, l.apexes[i]+":"+l.jars[i])
+ }
+
+ return json.Marshal(list)
+}
+
// ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
//
// TODO(b/139391334): hard coded until we find a good way to query the stem of a
@@ -1752,3 +1778,7 @@
func (c *config) UpdatableBootJars() ConfiguredJarList {
return c.productVariables.UpdatableBootJars
}
+
+func (c *config) RBEWrapper() string {
+ return c.GetenvWithDefault("RBE_WRAPPER", remoteexec.DefaultWrapperPath)
+}
diff --git a/android/config_test.go b/android/config_test.go
index a11115d..9df5288 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path/filepath"
"reflect"
"strings"
"testing"
@@ -87,6 +88,37 @@
}
}
+func verifyProductVariableMarshaling(t *testing.T, v productVariables) {
+ dir := t.TempDir()
+ path := filepath.Join(dir, "test.variables")
+ err := saveToConfigFile(&v, path)
+ if err != nil {
+ t.Errorf("Couldn't save default product config: %q", err)
+ }
+
+ var v2 productVariables
+ err = loadFromConfigFile(&v2, path)
+ if err != nil {
+ t.Errorf("Couldn't load default product config: %q", err)
+ }
+}
+func TestDefaultProductVariableMarshaling(t *testing.T) {
+ v := productVariables{}
+ v.SetDefaultConfig()
+ verifyProductVariableMarshaling(t, v)
+}
+
+func TestBootJarsMarshaling(t *testing.T) {
+ v := productVariables{}
+ v.SetDefaultConfig()
+ v.BootJars = ConfiguredJarList{
+ apexes: []string{"apex"},
+ jars: []string{"jar"},
+ }
+
+ verifyProductVariableMarshaling(t, v)
+}
+
func assertStringEquals(t *testing.T, expected, actual string) {
if actual != expected {
t.Errorf("expected %q found %q", expected, actual)
diff --git a/android/csuite_config.go b/android/csuite_config.go
index 56d2408..20bd035 100644
--- a/android/csuite_config.go
+++ b/android/csuite_config.go
@@ -15,7 +15,11 @@
package android
func init() {
- RegisterModuleType("csuite_config", CSuiteConfigFactory)
+ registerCSuiteBuildComponents(InitRegistrationContext)
+}
+
+func registerCSuiteBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("csuite_config", CSuiteConfigFactory)
}
type csuiteConfigProperties struct {
diff --git a/android/csuite_config_test.go b/android/csuite_config_test.go
index 9ac959e..b8a176e 100644
--- a/android/csuite_config_test.go
+++ b/android/csuite_config_test.go
@@ -18,32 +18,21 @@
"testing"
)
-func testCSuiteConfig(test *testing.T, bpFileContents string) *TestContext {
- config := TestArchConfig(buildDir, nil, bpFileContents, nil)
-
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("csuite_config", CSuiteConfigFactory)
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(test, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(test, errs)
- return ctx
-}
-
func TestCSuiteConfig(t *testing.T) {
- ctx := testCSuiteConfig(t, `
-csuite_config { name: "plain"}
-csuite_config { name: "with_manifest", test_config: "manifest.xml" }
-`)
+ result := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureRegisterWithContext(registerCSuiteBuildComponents),
+ FixtureWithRootAndroidBp(`
+ csuite_config { name: "plain"}
+ csuite_config { name: "with_manifest", test_config: "manifest.xml" }
+ `),
+ ).RunTest(t)
- variants := ctx.ModuleVariantsForTests("plain")
+ variants := result.ModuleVariantsForTests("plain")
if len(variants) > 1 {
t.Errorf("expected 1, got %d", len(variants))
}
- expectedOutputFilename := ctx.ModuleForTests(
+ outputFilename := result.ModuleForTests(
"plain", variants[0]).Module().(*CSuiteConfig).OutputFilePath.Base()
- if expectedOutputFilename != "plain" {
- t.Errorf("expected plain, got %q", expectedOutputFilename)
- }
+ AssertStringEquals(t, "output file name", "plain", outputFilename)
}
diff --git a/android/defaults_test.go b/android/defaults_test.go
index 2689d86..a7542ab 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -15,10 +15,7 @@
package android
import (
- "reflect"
"testing"
-
- "github.com/google/blueprint/proptools"
)
type defaultsTestProperties struct {
@@ -58,6 +55,14 @@
return defaults
}
+var prepareForDefaultsTest = GroupFixturePreparers(
+ PrepareForTestWithDefaults,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", defaultsTestModuleFactory)
+ ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
+ }),
+)
+
func TestDefaults(t *testing.T) {
bp := `
defaults {
@@ -78,27 +83,14 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
+ foo := result.Module("foo", "").(*defaultsTestModule)
- ctx.RegisterModuleType("test", defaultsTestModuleFactory)
- ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
-
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
-
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- foo := ctx.ModuleForTests("foo", "").Module().(*defaultsTestModule)
-
- if g, w := foo.properties.Foo, []string{"transitive", "defaults", "module"}; !reflect.DeepEqual(g, w) {
- t.Errorf("expected foo %q, got %q", w, g)
- }
+ AssertDeepEquals(t, "foo", []string{"transitive", "defaults", "module"}, foo.properties.Foo)
}
func TestDefaultsAllowMissingDependencies(t *testing.T) {
@@ -122,34 +114,18 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ PrepareForTestWithAllowMissingDependencies,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
- ctx.SetAllowMissingDependencies(true)
+ missingDefaults := result.ModuleForTests("missing_defaults", "").Output("out")
+ missingTransitiveDefaults := result.ModuleForTests("missing_transitive_defaults", "").Output("out")
- ctx.RegisterModuleType("test", defaultsTestModuleFactory)
- ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
+ AssertSame(t, "missing_defaults rule", ErrorRule, missingDefaults.Rule)
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
-
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- missingDefaults := ctx.ModuleForTests("missing_defaults", "").Output("out")
- missingTransitiveDefaults := ctx.ModuleForTests("missing_transitive_defaults", "").Output("out")
-
- if missingDefaults.Rule != ErrorRule {
- t.Errorf("expected missing_defaults rule to be ErrorRule, got %#v", missingDefaults.Rule)
- }
-
- if g, w := missingDefaults.Args["error"], "module missing_defaults missing dependencies: missing\n"; g != w {
- t.Errorf("want error %q, got %q", w, g)
- }
+ AssertStringEquals(t, "missing_defaults", "module missing_defaults missing dependencies: missing\n", missingDefaults.Args["error"])
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
diff --git a/android/defs.go b/android/defs.go
index 1a76721..b3ff376 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -124,6 +124,10 @@
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
+
+ pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
+ return ctx.Config().RBEWrapper()
+ })
}
var (
@@ -145,7 +149,7 @@
func buildWriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
content = echoEscaper.Replace(content)
- content = proptools.ShellEscape(content)
+ content = proptools.NinjaEscape(proptools.ShellEscapeIncludingSpaces(content))
if content == "" {
content = "''"
}
diff --git a/android/deptag_test.go b/android/deptag_test.go
index bdd449e..eb4fa89 100644
--- a/android/deptag_test.go
+++ b/android/deptag_test.go
@@ -80,21 +80,20 @@
}
`
- config := TestArchConfig(buildDir, nil, bp, nil)
- ctx := NewTestArchContext(config)
+ result := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureWithRootAndroidBp(bp),
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test_module", testInstallDependencyTagModuleFactory)
+ }),
+ ).RunTest(t)
- ctx.RegisterModuleType("test_module", testInstallDependencyTagModuleFactory)
+ config := result.Config
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- hostFoo := ctx.ModuleForTests("foo", config.BuildOSCommonTarget.String()).Description("install")
- hostInstallDep := ctx.ModuleForTests("install_dep", config.BuildOSCommonTarget.String()).Description("install")
- hostTransitive := ctx.ModuleForTests("transitive", config.BuildOSCommonTarget.String()).Description("install")
- hostDep := ctx.ModuleForTests("dep", config.BuildOSCommonTarget.String()).Description("install")
+ hostFoo := result.ModuleForTests("foo", config.BuildOSCommonTarget.String()).Description("install")
+ hostInstallDep := result.ModuleForTests("install_dep", config.BuildOSCommonTarget.String()).Description("install")
+ hostTransitive := result.ModuleForTests("transitive", config.BuildOSCommonTarget.String()).Description("install")
+ hostDep := result.ModuleForTests("dep", config.BuildOSCommonTarget.String()).Description("install")
if g, w := hostFoo.Implicits.Strings(), hostInstallDep.Output.String(); !InList(w, g) {
t.Errorf("expected host dependency %q, got %q", w, g)
@@ -112,10 +111,10 @@
t.Errorf("expected no host dependency %q, got %q", w, g)
}
- deviceFoo := ctx.ModuleForTests("foo", "android_common").Description("install")
- deviceInstallDep := ctx.ModuleForTests("install_dep", "android_common").Description("install")
- deviceTransitive := ctx.ModuleForTests("transitive", "android_common").Description("install")
- deviceDep := ctx.ModuleForTests("dep", "android_common").Description("install")
+ deviceFoo := result.ModuleForTests("foo", "android_common").Description("install")
+ deviceInstallDep := result.ModuleForTests("install_dep", "android_common").Description("install")
+ deviceTransitive := result.ModuleForTests("transitive", "android_common").Description("install")
+ deviceDep := result.ModuleForTests("dep", "android_common").Description("install")
if g, w := deviceFoo.OrderOnly.Strings(), deviceInstallDep.Output.String(); !InList(w, g) {
t.Errorf("expected device dependency %q, got %q", w, g)
diff --git a/android/fixture.go b/android/fixture.go
index 928967d..6c9ea6b 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "strings"
"testing"
)
@@ -29,8 +30,8 @@
// first creating a base Fixture (which is essentially empty) and then applying FixturePreparer
// instances to it to modify the environment.
//
-// FixtureFactory
-// ==============
+// FixtureFactory (deprecated)
+// ===========================
// These are responsible for creating fixtures. Factories are immutable and are intended to be
// initialized once and reused to create multiple fixtures. Each factory has a list of fixture
// preparers that prepare a fixture for running a test. Factories can also be used to create other
@@ -42,7 +43,9 @@
// intended to be immutable and able to prepare multiple Fixture objects simultaneously without
// them sharing any data.
//
-// FixturePreparers are only ever invoked once per test fixture. Prior to invocation the list of
+// They provide the basic capabilities for running tests too.
+//
+// FixturePreparers are only ever applied once per test fixture. Prior to application the list of
// FixturePreparers are flattened and deduped while preserving the order they first appear in the
// list. This makes it easy to reuse, group and combine FixturePreparers together.
//
@@ -118,14 +121,58 @@
// Some files to use in tests in the java package.
//
// var javaMockFS = android.MockFS{
-// "api/current.txt": nil,
-// "api/removed.txt": nil,
+// "api/current.txt": nil,
+// "api/removed.txt": nil,
// ...
// }
//
-// A package private factory for use for testing java within the java package.
+// A package private preparer for use for testing java within the java package.
//
-// var javaFixtureFactory = NewFixtureFactory(
+// var prepareForJavaTest = android.GroupFixturePreparers(
+// PrepareForIntegrationTestWithJava,
+// FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+// ctx.RegisterModuleType("test_module", testModule)
+// }),
+// javaMockFS.AddToFixture(),
+// ...
+// }
+//
+// func TestJavaStuff(t *testing.T) {
+// result := android.GroupFixturePreparers(t,
+// prepareForJavaTest,
+// android.FixtureWithRootAndroidBp(`java_library {....}`),
+// android.MockFS{...}.AddToFixture(),
+// ).RunTest(t)
+// ... test result ...
+// }
+//
+// package cc
+// var PrepareForTestWithCC = android.GroupFixturePreparers(
+// android.PrepareForArchMutator,
+// android.prepareForPrebuilts,
+// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+// ...
+// )
+//
+// package apex
+//
+// var PrepareForApex = GroupFixturePreparers(
+// ...
+// )
+//
+// Use modules and mutators from java, cc and apex. Any duplicate preparers (like
+// android.PrepareForArchMutator) will be automatically deduped.
+//
+// var prepareForApexTest = android.GroupFixturePreparers(
+// PrepareForJava,
+// PrepareForCC,
+// PrepareForApex,
+// )
+//
+// // FixtureFactory instances have been deprecated, this remains for informational purposes to
+// // help explain some of the existing code but will be removed along with FixtureFactory.
+//
+// var javaFixtureFactory = android.NewFixtureFactory(
// PrepareForIntegrationTestWithJava,
// FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
// ctx.RegisterModuleType("test_module", testModule)
@@ -145,7 +192,7 @@
// package cc
// var PrepareForTestWithCC = GroupFixturePreparers(
// android.PrepareForArchMutator,
-// android.prepareForPrebuilts,
+// android.prepareForPrebuilts,
// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
// ...
// )
@@ -169,52 +216,10 @@
//
// This is configured with a set of FixturePreparer objects that are used to
// initialize each Fixture instance this creates.
+//
+// deprecated: Use FixturePreparer instead.
type FixtureFactory interface {
-
- // Creates a copy of this instance and adds some additional preparers.
- //
- // Before the preparers are used they are combined with the preparers provided when the factory
- // was created, any groups of preparers are flattened, and the list is deduped so that each
- // preparer is only used once. See the file documentation in android/fixture.go for more details.
- Extend(preparers ...FixturePreparer) FixtureFactory
-
- // Create a Fixture.
- Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
-
- // ExtendWithErrorHandler creates a new FixtureFactory that will use the supplied error handler
- // to check the errors (may be 0) reported by the test.
- //
- // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
- // errors are reported.
- ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
-
- // Run the test, checking any errors reported and returning a TestResult instance.
- //
- // Shorthand for Fixture(t, preparers...).RunTest()
- RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult
-
- // Run the test with the supplied Android.bp file.
- //
- // Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
- RunTestWithBp(t *testing.T, bp string) *TestResult
-
- // RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
- // the test fixture.
- //
- // In order to allow the Config object to be customized separately to the TestContext a lot of
- // existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
- // from the test and then have the TestContext created and configured automatically. e.g.
- // testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
- //
- // This method allows those methods to be migrated to use the test fixture pattern without
- // requiring that every test that uses those methods be migrated at the same time. That allows
- // those tests to benefit from correctness in the order of registration quickly.
- //
- // This method discards the config (along with its mock file system, product variables,
- // environment, etc.) that may have been set up by FixturePreparers.
- //
- // deprecated
- RunTestWithConfig(t *testing.T, config Config) *TestResult
+ FixturePreparer
}
// Create a new FixtureFactory that will apply the supplied preparers.
@@ -223,14 +228,17 @@
// the package level setUp method. It has to be a pointer to the variable as the variable will not
// have been initialized at the time the factory is created. If it is nil then a test specific
// temporary directory will be created instead.
+//
+// deprecated: The functionality provided by FixtureFactory will be merged into FixturePreparer
func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) FixtureFactory {
- return &fixtureFactory{
+ f := &fixtureFactory{
buildDirSupplier: buildDirSupplier,
- preparers: dedupAndFlattenPreparers(nil, preparers),
-
- // Set the default error handler.
- errorHandler: FixtureExpectsNoErrors,
+ compositeFixturePreparer: compositeFixturePreparer{
+ preparers: dedupAndFlattenPreparers(nil, preparers),
+ },
}
+ f.initBaseFixturePreparer(f)
+ return f
}
// A set of mock files to add to the mock file system.
@@ -241,6 +249,7 @@
// Fails if the supplied map files with the same paths are present in both of them.
func (fs MockFS) Merge(extra map[string][]byte) {
for p, c := range extra {
+ validateFixtureMockFSPath(p)
if _, ok := fs[p]; ok {
panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists", p))
}
@@ -248,10 +257,40 @@
}
}
+// Ensure that tests cannot add paths into the mock file system which would not be allowed in the
+// runtime, e.g. absolute paths, paths relative to the 'out/' directory.
+func validateFixtureMockFSPath(path string) {
+ // This uses validateSafePath rather than validatePath because the latter prevents adding files
+ // that include a $ but there are tests that allow files with a $ to be used, albeit only by
+ // globbing.
+ validatedPath, err := validateSafePath(path)
+ if err != nil {
+ panic(err)
+ }
+
+ // Make sure that the path is canonical.
+ if validatedPath != path {
+ panic(fmt.Errorf("path %q is not a canonical path, use %q instead", path, validatedPath))
+ }
+
+ if path == "out" || strings.HasPrefix(path, "out/") {
+ panic(fmt.Errorf("cannot add output path %q to the mock file system", path))
+ }
+}
+
func (fs MockFS) AddToFixture() FixturePreparer {
return FixtureMergeMockFs(fs)
}
+// FixtureCustomPreparer allows for the modification of any aspect of the fixture.
+//
+// This should only be used if one of the other more specific preparers are not suitable.
+func FixtureCustomPreparer(mutator func(fixture Fixture)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ mutator(f)
+ })
+}
+
// Modify the config
func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
return newSimpleFixturePreparer(func(f *fixture) {
@@ -281,6 +320,11 @@
func FixtureModifyMockFS(mutator func(fs MockFS)) FixturePreparer {
return newSimpleFixturePreparer(func(f *fixture) {
mutator(f.mockFS)
+
+ // Make sure that invalid paths were not added to the mock filesystem.
+ for p, _ := range f.mockFS {
+ validateFixtureMockFSPath(p)
+ }
})
}
@@ -298,6 +342,7 @@
// Fail if the filesystem already contains a file with that path, use FixtureOverrideFile instead.
func FixtureAddFile(path string, contents []byte) FixturePreparer {
return FixtureModifyMockFS(func(fs MockFS) {
+ validateFixtureMockFSPath(path)
if _, ok := fs[path]; ok {
panic(fmt.Errorf("attempted to add file %s to the mock filesystem but it already exists, use FixtureOverride*File instead", path))
}
@@ -378,25 +423,76 @@
// Before preparing the fixture the list of preparers is flattened by replacing each
// instance of GroupFixturePreparers with its contents.
func GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
- return &compositeFixturePreparer{dedupAndFlattenPreparers(nil, preparers)}
+ all := dedupAndFlattenPreparers(nil, preparers)
+ return newFixturePreparer(all)
}
-type simpleFixturePreparerVisitor func(preparer *simpleFixturePreparer)
+// NullFixturePreparer is a preparer that does nothing.
+var NullFixturePreparer = GroupFixturePreparers()
-// FixturePreparer is an opaque interface that can change a fixture.
-type FixturePreparer interface {
- // visit calls the supplied visitor with each *simpleFixturePreparer instances in this preparer,
- visit(simpleFixturePreparerVisitor)
-}
-
-type fixturePreparers []FixturePreparer
-
-func (f fixturePreparers) visit(visitor simpleFixturePreparerVisitor) {
- for _, p := range f {
- p.visit(visitor)
+// OptionalFixturePreparer will return the supplied preparer if it is non-nil, otherwise it will
+// return the NullFixturePreparer
+func OptionalFixturePreparer(preparer FixturePreparer) FixturePreparer {
+ if preparer == nil {
+ return NullFixturePreparer
+ } else {
+ return preparer
}
}
+// FixturePreparer provides the ability to create, modify and then run tests within a fixture.
+type FixturePreparer interface {
+ // Return the flattened and deduped list of simpleFixturePreparer pointers.
+ list() []*simpleFixturePreparer
+
+ // Creates a copy of this instance and adds some additional preparers.
+ //
+ // Before the preparers are used they are combined with the preparers provided when the factory
+ // was created, any groups of preparers are flattened, and the list is deduped so that each
+ // preparer is only used once. See the file documentation in android/fixture.go for more details.
+ //
+ // deprecated: Use GroupFixturePreparers() instead.
+ Extend(preparers ...FixturePreparer) FixturePreparer
+
+ // Create a Fixture.
+ Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
+
+ // ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
+ // to check the errors (may be 0) reported by the test.
+ //
+ // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
+ // errors are reported.
+ ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer
+
+ // Run the test, checking any errors reported and returning a TestResult instance.
+ //
+ // Shorthand for Fixture(t, preparers...).RunTest()
+ RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult
+
+ // Run the test with the supplied Android.bp file.
+ //
+ // Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
+ RunTestWithBp(t *testing.T, bp string) *TestResult
+
+ // RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
+ // the test fixture.
+ //
+ // In order to allow the Config object to be customized separately to the TestContext a lot of
+ // existing test code has `test...WithConfig` funcs that allow the Config object to be supplied
+ // from the test and then have the TestContext created and configured automatically. e.g.
+ // testCcWithConfig, testCcErrorWithConfig, testJavaWithConfig, etc.
+ //
+ // This method allows those methods to be migrated to use the test fixture pattern without
+ // requiring that every test that uses those methods be migrated at the same time. That allows
+ // those tests to benefit from correctness in the order of registration quickly.
+ //
+ // This method discards the config (along with its mock file system, product variables,
+ // environment, etc.) that may have been set up by FixturePreparers.
+ //
+ // deprecated
+ RunTestWithConfig(t *testing.T, config Config) *TestResult
+}
+
// dedupAndFlattenPreparers removes any duplicates and flattens any composite FixturePreparer
// instances.
//
@@ -407,48 +503,73 @@
// preparers - a list of additional unflattened, undeduped preparers that will be applied after the
// base preparers.
//
-// Returns a deduped and flattened list of the preparers minus any that exist in the base preparers.
-func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers fixturePreparers) []*simpleFixturePreparer {
- var list []*simpleFixturePreparer
+// Returns a deduped and flattened list of the preparers starting with the ones in base with any
+// additional ones from the preparers list added afterwards.
+func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers []FixturePreparer) []*simpleFixturePreparer {
+ if len(preparers) == 0 {
+ return base
+ }
+
+ list := make([]*simpleFixturePreparer, len(base))
visited := make(map[*simpleFixturePreparer]struct{})
// Mark the already flattened and deduped preparers, if any, as having been seen so that
- // duplicates of these in the additional preparers will be discarded.
- for _, s := range base {
+ // duplicates of these in the additional preparers will be discarded. Add them to the output
+ // list.
+ for i, s := range base {
visited[s] = struct{}{}
+ list[i] = s
}
- preparers.visit(func(preparer *simpleFixturePreparer) {
- if _, seen := visited[preparer]; !seen {
- visited[preparer] = struct{}{}
- list = append(list, preparer)
+ for _, p := range preparers {
+ for _, s := range p.list() {
+ if _, seen := visited[s]; !seen {
+ visited[s] = struct{}{}
+ list = append(list, s)
+ }
}
- })
+ }
+
return list
}
// compositeFixturePreparer is a FixturePreparer created from a list of fixture preparers.
type compositeFixturePreparer struct {
+ baseFixturePreparer
+ // The flattened and deduped list of simpleFixturePreparer pointers encapsulated within this
+ // composite preparer.
preparers []*simpleFixturePreparer
}
-func (c *compositeFixturePreparer) visit(visitor simpleFixturePreparerVisitor) {
- for _, p := range c.preparers {
- p.visit(visitor)
+func (c *compositeFixturePreparer) list() []*simpleFixturePreparer {
+ return c.preparers
+}
+
+func newFixturePreparer(preparers []*simpleFixturePreparer) FixturePreparer {
+ if len(preparers) == 1 {
+ return preparers[0]
}
+ p := &compositeFixturePreparer{
+ preparers: preparers,
+ }
+ p.initBaseFixturePreparer(p)
+ return p
}
// simpleFixturePreparer is a FixturePreparer that applies a function to a fixture.
type simpleFixturePreparer struct {
+ baseFixturePreparer
function func(fixture *fixture)
}
-func (s *simpleFixturePreparer) visit(visitor simpleFixturePreparerVisitor) {
- visitor(s)
+func (s *simpleFixturePreparer) list() []*simpleFixturePreparer {
+ return []*simpleFixturePreparer{s}
}
func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer {
- return &simpleFixturePreparer{function: preparer}
+ p := &simpleFixturePreparer{function: preparer}
+ p.initBaseFixturePreparer(p)
+ return p
}
// FixtureErrorHandler determines how to respond to errors reported by the code under test.
@@ -493,6 +614,14 @@
},
)
+// FixtureIgnoreErrors ignores any errors.
+//
+// If this is used then it is the responsibility of the test to check the TestResult.Errs does not
+// contain any unexpected errors.
+var FixtureIgnoreErrors = FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) {
+ // Ignore the errors
+})
+
// FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail
// if at least one error that matches the regular expression is not found.
//
@@ -543,6 +672,15 @@
// Fixture defines the test environment.
type Fixture interface {
+ // Config returns the fixture's configuration.
+ Config() Config
+
+ // Context returns the fixture's test context.
+ Context() *TestContext
+
+ // MockFS returns the fixture's mock filesystem.
+ MockFS() MockFS
+
// Run the test, checking any errors reported and returning a TestResult instance.
RunTest() *TestResult
}
@@ -561,84 +699,72 @@
// The errors that were reported during the test.
Errs []error
+
+ // The ninja deps is a list of the ninja files dependencies that were added by the modules and
+ // singletons via the *.AddNinjaFileDeps() methods.
+ NinjaDeps []string
}
-var _ FixtureFactory = (*fixtureFactory)(nil)
+func createFixture(t *testing.T, buildDir string, base []*simpleFixturePreparer, extra []FixturePreparer) Fixture {
+ all := dedupAndFlattenPreparers(base, extra)
-type fixtureFactory struct {
- buildDirSupplier *string
- preparers []*simpleFixturePreparer
- errorHandler FixtureErrorHandler
-}
-
-func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory {
- // Create a new slice to avoid accidentally sharing the preparers slice from this factory with
- // the extending factories.
- var all []*simpleFixturePreparer
- all = append(all, f.preparers...)
- all = append(all, dedupAndFlattenPreparers(f.preparers, preparers)...)
- // Copy the existing factory.
- extendedFactory := &fixtureFactory{}
- *extendedFactory = *f
- // Use the extended list of preparers.
- extendedFactory.preparers = all
- return extendedFactory
-}
-
-func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
- var buildDir string
- if f.buildDirSupplier == nil {
- // Create a new temporary directory for this run. It will be automatically cleaned up when the
- // test finishes.
- buildDir = t.TempDir()
- } else {
- // Retrieve the buildDir from the supplier.
- buildDir = *f.buildDirSupplier
- }
config := TestConfig(buildDir, nil, "", nil)
ctx := NewTestContext(config)
fixture := &fixture{
- factory: f,
- t: t,
- config: config,
- ctx: ctx,
- mockFS: make(MockFS),
- errorHandler: f.errorHandler,
+ preparers: all,
+ t: t,
+ config: config,
+ ctx: ctx,
+ mockFS: make(MockFS),
+ // Set the default error handler.
+ errorHandler: FixtureExpectsNoErrors,
}
- for _, preparer := range f.preparers {
- preparer.function(fixture)
- }
-
- for _, preparer := range dedupAndFlattenPreparers(f.preparers, preparers) {
+ for _, preparer := range all {
preparer.function(fixture)
}
return fixture
}
-func (f *fixtureFactory) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
- newFactory := &fixtureFactory{}
- *newFactory = *f
- newFactory.errorHandler = errorHandler
- return newFactory
+type baseFixturePreparer struct {
+ self FixturePreparer
}
-func (f *fixtureFactory) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
+func (b *baseFixturePreparer) initBaseFixturePreparer(self FixturePreparer) {
+ b.self = self
+}
+
+func (b *baseFixturePreparer) Extend(preparers ...FixturePreparer) FixturePreparer {
+ all := dedupAndFlattenPreparers(b.self.list(), preparers)
+ return newFixturePreparer(all)
+}
+
+func (b *baseFixturePreparer) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
+ return createFixture(t, t.TempDir(), b.self.list(), preparers)
+}
+
+func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
+ return b.self.Extend(newSimpleFixturePreparer(func(fixture *fixture) {
+ fixture.errorHandler = errorHandler
+ }))
+}
+
+func (b *baseFixturePreparer) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
t.Helper()
- fixture := f.Fixture(t, preparers...)
+ fixture := b.self.Fixture(t, preparers...)
return fixture.RunTest()
}
-func (f *fixtureFactory) RunTestWithBp(t *testing.T, bp string) *TestResult {
+func (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
t.Helper()
- return f.RunTest(t, FixtureWithRootAndroidBp(bp))
+ return b.RunTest(t, FixtureWithRootAndroidBp(bp))
}
-func (f *fixtureFactory) RunTestWithConfig(t *testing.T, config Config) *TestResult {
+func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
t.Helper()
// Create the fixture as normal.
- fixture := f.Fixture(t).(*fixture)
+ fixture := b.self.Fixture(t).(*fixture)
// Discard the mock filesystem as otherwise that will override the one in the config.
fixture.mockFS = nil
@@ -657,9 +783,49 @@
return fixture.RunTest()
}
+var _ FixtureFactory = (*fixtureFactory)(nil)
+
+type fixtureFactory struct {
+ compositeFixturePreparer
+
+ buildDirSupplier *string
+}
+
+// Override to preserve the buildDirSupplier.
+func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixturePreparer {
+ // If there is no buildDirSupplier then just use the default implementation.
+ if f.buildDirSupplier == nil {
+ return f.baseFixturePreparer.Extend(preparers...)
+ }
+
+ all := dedupAndFlattenPreparers(f.preparers, preparers)
+
+ // Create a new factory which uses the same buildDirSupplier as the previous one.
+ extendedFactory := &fixtureFactory{
+ buildDirSupplier: f.buildDirSupplier,
+ compositeFixturePreparer: compositeFixturePreparer{
+ preparers: all,
+ },
+ }
+ extendedFactory.initBaseFixturePreparer(extendedFactory)
+ return extendedFactory
+}
+
+func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
+ // If there is no buildDirSupplier then just use the default implementation.
+ if f.buildDirSupplier == nil {
+ return f.baseFixturePreparer.Fixture(t, preparers...)
+ }
+
+ // Retrieve the buildDir from the supplier.
+ buildDir := *f.buildDirSupplier
+
+ return createFixture(t, buildDir, f.preparers, preparers)
+}
+
type fixture struct {
- // The factory used to create this fixture.
- factory *fixtureFactory
+ // The preparers used to create this fixture.
+ preparers []*simpleFixturePreparer
// The gotest state of the go test within which this was created.
t *testing.T
@@ -677,6 +843,18 @@
errorHandler FixtureErrorHandler
}
+func (f *fixture) Config() Config {
+ return f.config
+}
+
+func (f *fixture) Context() *TestContext {
+ return f.ctx
+}
+
+func (f *fixture) MockFS() MockFS {
+ return f.mockFS
+}
+
func (f *fixture) RunTest() *TestResult {
f.t.Helper()
@@ -701,9 +879,14 @@
}
ctx.Register()
- _, errs := ctx.ParseBlueprintsFiles("ignored")
+ var ninjaDeps []string
+ extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
if len(errs) == 0 {
- _, errs = ctx.PrepareBuildActions(f.config)
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ extraNinjaDeps, errs = ctx.PrepareBuildActions(f.config)
+ if len(errs) == 0 {
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ }
}
result := &TestResult{
@@ -711,6 +894,7 @@
fixture: f,
Config: f.config,
Errs: errs,
+ NinjaDeps: ninjaDeps,
}
f.errorHandler.CheckErrors(f.t, result)
@@ -749,6 +933,21 @@
return result
}
+// Preparer will return a FixturePreparer encapsulating all the preparers used to create the fixture
+// that produced this result.
+//
+// e.g. assuming that this result was created by running:
+// factory.Extend(preparer1, preparer2).RunTest(t, preparer3, preparer4)
+//
+// Then this method will be equivalent to running:
+// GroupFixturePreparers(preparer1, preparer2, preparer3, preparer4)
+//
+// This is intended for use by tests whose output is Android.bp files to verify that those files
+// are valid, e.g. tests of the snapshots produced by the sdk module type.
+func (r *TestResult) Preparer() FixturePreparer {
+ return newFixturePreparer(r.fixture.preparers)
+}
+
// Module returns the module with the specific name and of the specified variant.
func (r *TestResult) Module(name string, variant string) Module {
return r.ModuleForTests(name, variant).Module()
diff --git a/android/fixture_test.go b/android/fixture_test.go
index a31ef16..681a034 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -14,7 +14,9 @@
package android
-import "testing"
+import (
+ "testing"
+)
// Make sure that FixturePreparer instances are only called once per fixture and in the order in
// which they were added.
@@ -30,19 +32,54 @@
preparer1 := appendToList("preparer1")
preparer2 := appendToList("preparer2")
preparer3 := appendToList("preparer3")
- preparer4 := appendToList("preparer4")
+ preparer4 := OptionalFixturePreparer(appendToList("preparer4"))
+ nilPreparer := OptionalFixturePreparer(nil)
- preparer1Then2 := GroupFixturePreparers(preparer1, preparer2)
+ preparer1Then2 := GroupFixturePreparers(preparer1, preparer2, nilPreparer)
preparer2Then1 := GroupFixturePreparers(preparer2, preparer1)
- buildDir := "build"
- factory := NewFixtureFactory(&buildDir, preparer1, preparer2, preparer1, preparer1Then2)
+ group := GroupFixturePreparers(preparer1, preparer2, preparer1, preparer1Then2)
- extension := factory.Extend(preparer4, preparer2)
+ extension := group.Extend(preparer4, preparer2)
extension.Fixture(t, preparer1, preparer2, preparer2Then1, preparer3)
AssertDeepEquals(t, "preparers called in wrong order",
[]string{"preparer1", "preparer2", "preparer4", "preparer3"}, list)
}
+
+func TestFixtureValidateMockFS(t *testing.T) {
+ buildDir := "<unused>"
+ factory := NewFixtureFactory(&buildDir)
+
+ t.Run("absolute path", func(t *testing.T) {
+ AssertPanicMessageContains(t, "source path validation failed", "Path is outside directory: /abs/path/Android.bp", func() {
+ factory.Fixture(t, FixtureAddFile("/abs/path/Android.bp", nil))
+ })
+ })
+ t.Run("not canonical", func(t *testing.T) {
+ AssertPanicMessageContains(t, "source path validation failed", `path "path/with/../in/it/Android.bp" is not a canonical path, use "path/in/it/Android.bp" instead`, func() {
+ factory.Fixture(t, FixtureAddFile("path/with/../in/it/Android.bp", nil))
+ })
+ })
+ t.Run("FixtureAddFile", func(t *testing.T) {
+ AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
+ factory.Fixture(t, FixtureAddFile("out/Android.bp", nil))
+ })
+ })
+ t.Run("FixtureMergeMockFs", func(t *testing.T) {
+ AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
+ factory.Fixture(t, FixtureMergeMockFs(MockFS{
+ "out/Android.bp": nil,
+ }))
+ })
+ })
+ t.Run("FixtureModifyMockFS", func(t *testing.T) {
+ AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
+ factory.Fixture(t, FixtureModifyMockFS(func(fs MockFS) {
+ fs["out/Android.bp"] = nil
+ }))
+ })
+ })
+}
diff --git a/android/license_kind_test.go b/android/license_kind_test.go
index 83e83ce..1f09568 100644
--- a/android/license_kind_test.go
+++ b/android/license_kind_test.go
@@ -97,13 +97,14 @@
func TestLicenseKind(t *testing.T) {
for _, test := range licenseKindTests {
t.Run(test.name, func(t *testing.T) {
- licenseTestFixtureFactory.
- Extend(
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.RegisterModuleType("mock_license", newMockLicenseModule)
- }),
- test.fs.AddToFixture(),
- ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ GroupFixturePreparers(
+ prepareForLicenseTest,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("mock_license", newMockLicenseModule)
+ }),
+ test.fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
RunTest(t)
})
}
diff --git a/android/license_test.go b/android/license_test.go
index a564827..2b09a4f 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -5,7 +5,7 @@
)
// Common test set up for license tests.
-var licenseTestFixtureFactory = emptyTestFixtureFactory.Extend(
+var prepareForLicenseTest = GroupFixturePreparers(
// General preparers in alphabetical order.
PrepareForTestWithDefaults,
prepareForTestWithLicenses,
@@ -179,7 +179,8 @@
for _, test := range licenseTests {
t.Run(test.name, func(t *testing.T) {
// Customize the common license text fixture factory.
- licenseTestFixtureFactory.Extend(
+ GroupFixturePreparers(
+ prepareForLicenseTest,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("rule", newMockRuleModule)
}),
diff --git a/android/licenses_test.go b/android/licenses_test.go
index a581932..913dc88 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -470,7 +470,8 @@
for _, test := range licensesTests {
t.Run(test.name, func(t *testing.T) {
// Customize the common license text fixture factory.
- result := licenseTestFixtureFactory.Extend(
+ result := GroupFixturePreparers(
+ prepareForLicenseTest,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
diff --git a/android/module_test.go b/android/module_test.go
index e3cc613..9ac9291 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -163,6 +163,10 @@
return m
}
+var prepareForModuleTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("deps", depsModuleFactory)
+})
+
func TestErrorDependsOnDisabledModule(t *testing.T) {
bp := `
deps {
@@ -175,20 +179,13 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestContext(config)
- ctx.RegisterModuleType("deps", depsModuleFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfNoMatchingErrors(t, `module "foo": depends on disabled module "bar"`, errs)
+ prepareForModuleTests.
+ ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": depends on disabled module "bar"`)).
+ RunTestWithBp(t, bp)
}
func TestValidateCorrectBuildParams(t *testing.T) {
- config := TestConfig(buildDir, nil, "", nil)
+ config := TestConfig(t.TempDir(), nil, "", nil)
pathContext := PathContextForTesting(config)
bparams := convertBuildParams(BuildParams{
// Test with Output
@@ -214,7 +211,7 @@
}
func TestValidateIncorrectBuildParams(t *testing.T) {
- config := TestConfig(buildDir, nil, "", nil)
+ config := TestConfig(t.TempDir(), nil, "", nil)
pathContext := PathContextForTesting(config)
params := BuildParams{
Output: PathForOutput(pathContext, "regular_output"),
@@ -257,16 +254,6 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestContext(config)
- ctx.RegisterModuleType("deps", depsModuleFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
-
expectedErrs := []string{
"\\QAndroid.bp:5:13: module \"foo\": dist.dest: Path is outside directory: ../invalid-dest\\E",
"\\QAndroid.bp:6:12: module \"foo\": dist.dir: Path is outside directory: ../invalid-dir\\E",
@@ -278,5 +265,8 @@
"\\QAndroid.bp:17:14: module \"foo\": dists[1].dir: Path is outside directory: ../invalid-dir1\\E",
"\\QAndroid.bp:18:17: module \"foo\": dists[1].suffix: Suffix may not contain a '/' character.\\E",
}
- CheckErrorsAgainstExpectations(t, errs, expectedErrs)
+
+ prepareForModuleTests.
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
+ RunTestWithBp(t, bp)
}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 1c395c7..21eebd2 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -16,12 +16,10 @@
import (
"fmt"
- "reflect"
"strings"
"testing"
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
type mutatorTestModule struct {
@@ -67,28 +65,20 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ result := GroupFixturePreparers(
+ PrepareForTestWithAllowMissingDependencies,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
+ })
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
- ctx.SetAllowMissingDependencies(true)
+ foo := result.ModuleForTests("foo", "").Module().(*mutatorTestModule)
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
- })
-
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- foo := ctx.ModuleForTests("foo", "").Module().(*mutatorTestModule)
-
- if g, w := foo.missingDeps, []string{"added_missing_dep", "regular_missing_dep"}; !reflect.DeepEqual(g, w) {
- t.Errorf("want foo missing deps %q, got %q", w, g)
- }
+ AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
}
func TestModuleString(t *testing.T) {
@@ -98,52 +88,47 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestContext(config)
-
var moduleStrings []string
- ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("a", "b")
- })
- ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- })
- })
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("c", "d")
- })
- })
+ ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateVariations("a", "b")
+ })
+ ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ })
+ })
- ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateLocalVariations("e", "f")
- })
- ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed2")
- })
- ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- })
- })
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateVariations("c", "d")
+ })
+ })
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.CreateLocalVariations("e", "f")
+ })
+ ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed2")
+ })
+ ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ })
+ })
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
want := []string{
// Initial name.
@@ -184,9 +169,7 @@
"foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
}
- if !reflect.DeepEqual(moduleStrings, want) {
- t.Errorf("want module String() values:\n%q\ngot:\n%q", want, moduleStrings)
- }
+ AssertDeepEquals(t, "module String() values", want, moduleStrings)
}
func TestFinalDepsPhase(t *testing.T) {
@@ -202,52 +185,46 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestContext(config)
-
finalGot := map[string]int{}
- dep1Tag := struct {
- blueprint.BaseDependencyTag
- }{}
- dep2Tag := struct {
- blueprint.BaseDependencyTag
- }{}
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ dep1Tag := struct {
+ blueprint.BaseDependencyTag
+ }{}
+ dep2Tag := struct {
+ blueprint.BaseDependencyTag
+ }{}
- ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) {
- if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
- ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
- }
- })
- ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
- ctx.CreateLocalVariations("a", "b")
- })
- })
-
- ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) {
- if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
- ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2")
- }
- })
- ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
- finalGot[ctx.Module().String()] += 1
- ctx.VisitDirectDeps(func(mod Module) {
- finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1
+ ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) {
+ if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
+ ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
+ }
+ })
+ ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
+ ctx.CreateLocalVariations("a", "b")
+ })
})
- })
- })
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) {
+ if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
+ ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2")
+ }
+ })
+ ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+ finalGot[ctx.Module().String()] += 1
+ ctx.VisitDirectDeps(func(mod Module) {
+ finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1
+ })
+ })
+ })
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
finalWant := map[string]int{
"common_dep_1{variant:a}": 1,
@@ -262,37 +239,31 @@
"foo{variant:b} -> common_dep_2{variant:a}": 1,
}
- if !reflect.DeepEqual(finalWant, finalGot) {
- t.Errorf("want:\n%q\ngot:\n%q", finalWant, finalGot)
- }
+ AssertDeepEquals(t, "final", finalWant, finalGot)
}
func TestNoCreateVariationsInFinalDeps(t *testing.T) {
- config := TestConfig(buildDir, nil, `test {name: "foo"}`, nil)
- ctx := NewTestContext(config)
-
checkErr := func() {
if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
panic("Expected FinalDepsMutators consistency check to fail")
}
}
- ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateVariations("a", "b")
- })
- ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateLocalVariations("a", "b")
- })
- })
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
+ defer checkErr()
+ ctx.CreateVariations("a", "b")
+ })
+ ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
+ defer checkErr()
+ ctx.CreateLocalVariations("a", "b")
+ })
+ })
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(`test {name: "foo"}`),
+ ).RunTest(t)
}
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 45e2cdb..08e221a 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -143,7 +143,7 @@
}
func TestDependingOnModuleInNonImportedNamespace(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -378,7 +378,7 @@
}
func TestImportingNonexistentNamespace(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -402,7 +402,7 @@
}
func TestNamespacesDontInheritParentNamespaces(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -455,7 +455,7 @@
}
func TestNamespaceImportsNotTransitive(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -496,7 +496,7 @@
}
func TestTwoNamepacesInSameDir(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -516,7 +516,7 @@
}
func TestNamespaceNotAtTopOfFile(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
test_module {
@@ -537,7 +537,7 @@
}
func TestTwoModulesWithSameNameInSameNamespace(t *testing.T) {
- _, errs := setupTestExpectErrs(
+ _, errs := setupTestExpectErrs(t,
map[string]string{
"dir1": `
soong_namespace {
@@ -562,7 +562,7 @@
}
func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) {
- _, errs := setupTestFromFiles(
+ _, errs := setupTestFromFiles(t,
map[string][]byte{
"Android.bp": []byte(`
build = ["include.bp"]
@@ -632,39 +632,38 @@
return files
}
-func setupTestFromFiles(bps map[string][]byte) (ctx *TestContext, errs []error) {
- config := TestConfig(buildDir, nil, "", bps)
+func setupTestFromFiles(t *testing.T, bps MockFS) (ctx *TestContext, errs []error) {
+ result := GroupFixturePreparers(
+ FixtureModifyContext(func(ctx *TestContext) {
+ ctx.RegisterModuleType("test_module", newTestModule)
+ ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
+ ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
+ ctx.PreArchMutators(RegisterNamespaceMutator)
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("rename", renameMutator)
+ })
+ }),
+ bps.AddToFixture(),
+ ).
+ // Ignore errors for now so tests can check them later.
+ ExtendWithErrorHandler(FixtureIgnoreErrors).
+ RunTest(t)
- ctx = NewTestContext(config)
- ctx.RegisterModuleType("test_module", newTestModule)
- ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
- ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
- ctx.PreArchMutators(RegisterNamespaceMutator)
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("rename", renameMutator)
- })
- ctx.Register()
-
- _, errs = ctx.ParseBlueprintsFiles("Android.bp")
- if len(errs) > 0 {
- return ctx, errs
- }
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
+ return result.TestContext, result.Errs
}
-func setupTestExpectErrs(bps map[string]string) (ctx *TestContext, errs []error) {
+func setupTestExpectErrs(t *testing.T, bps map[string]string) (ctx *TestContext, errs []error) {
files := make(map[string][]byte, len(bps))
files["Android.bp"] = []byte("")
for dir, text := range bps {
files[filepath.Join(dir, "Android.bp")] = []byte(text)
}
- return setupTestFromFiles(files)
+ return setupTestFromFiles(t, files)
}
func setupTest(t *testing.T, bps map[string]string) (ctx *TestContext) {
t.Helper()
- ctx, errs := setupTestExpectErrs(bps)
+ ctx, errs := setupTestExpectErrs(t, bps)
FailIfErrored(t, errs)
return ctx
}
@@ -698,7 +697,7 @@
testModule, ok := candidate.(*testModule)
if ok {
if testModule.properties.Id == id {
- module = TestingModule{testModule}
+ module = newTestingModule(ctx.config, testModule)
}
}
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index b761065..b8ef0f5 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -28,7 +28,7 @@
rules []Rule
// Additional contents to add to the virtual filesystem used by the tests.
- fs map[string][]byte
+ fs MockFS
// The expected error patterns. If empty then no errors are expected, otherwise each error
// reported must be matched by at least one of these patterns. A pattern matches if the error
@@ -285,41 +285,35 @@
},
}
+var prepareForNeverAllowTest = GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
+ ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
+ ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
+ ctx.PostDepsMutators(RegisterNeverallowMutator)
+ }),
+)
+
func TestNeverallow(t *testing.T) {
for _, test := range neverallowTests {
- // Create a test per config to allow for test specific config, e.g. test rules.
- config := TestConfig(buildDir, nil, "", test.fs)
-
t.Run(test.name, func(t *testing.T) {
- // If the test has its own rules then use them instead of the default ones.
- if test.rules != nil {
- SetTestNeverallowRules(config, test.rules)
- }
- _, errs := testNeverallow(config)
- CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+ GroupFixturePreparers(
+ prepareForNeverAllowTest,
+ FixtureModifyConfig(func(config Config) {
+ // If the test has its own rules then use them instead of the default ones.
+ if test.rules != nil {
+ SetTestNeverallowRules(config, test.rules)
+ }
+ }),
+ test.fs.AddToFixture(),
+ ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
})
}
}
-func testNeverallow(config Config) (*TestContext, []error) {
- ctx := NewTestContext(config)
- ctx.RegisterModuleType("cc_library", newMockCcLibraryModule)
- ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
- ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
- ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
- ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
- ctx.PostDepsMutators(RegisterNeverallowMutator)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
-
type mockCcLibraryProperties struct {
Include_dirs []string
Vendor_available *bool
diff --git a/android/ninja_deps_test.go b/android/ninja_deps_test.go
index d3775ed..947c257 100644
--- a/android/ninja_deps_test.go
+++ b/android/ninja_deps_test.go
@@ -53,23 +53,20 @@
}
func TestNinjaDeps(t *testing.T) {
- fs := map[string][]byte{
+ fs := MockFS{
"test_ninja_deps/exists": nil,
}
- config := TestConfig(buildDir, nil, "", fs)
- ctx := NewTestContext(config)
- ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
- ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- ninjaDeps, errs := ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
+ ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
+ }),
+ fs.AddToFixture(),
+ ).RunTest(t)
// Verify that the ninja file has a dependency on the test_ninja_deps directory.
- if g, w := ninjaDeps, "test_ninja_deps"; !InList(w, g) {
+ if g, w := result.NinjaDeps, "test_ninja_deps"; !InList(w, g) {
t.Errorf("expected %q in %q", w, g)
}
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index 6d0fcb3..c19debb 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -19,6 +19,8 @@
"strings"
"github.com/google/blueprint"
+
+ "android/soong/remoteexec"
)
// PackageContext is a wrapper for blueprint.PackageContext that adds
@@ -260,3 +262,40 @@
return params, nil
}, argNames...)
}
+
+// RemoteStaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
+// locally executable rule and the second rule is a remotely executable rule. commonArgs are args
+// used for both the local and remotely executable rules. reArgs are used only for remote
+// execution.
+func (p PackageContext) RemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams *remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
+ ruleParamsRE := ruleParams
+ ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
+ ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
+
+ return p.AndroidStaticRule(name, ruleParams, commonArgs...),
+ p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
+}
+
+// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first
+// rule is a locally executable rule and the second rule is a remotely executable rule. This
+// function supports multiple remote execution wrappers placed in the template when commands are
+// chained together with &&. commonArgs are args used for both the local and remotely executable
+// rules. reArgs are args used only for remote execution.
+func (p PackageContext) MultiCommandRemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams map[string]*remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
+ ruleParamsRE := ruleParams
+ for k, v := range reParams {
+ ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "")
+ ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template())
+ }
+
+ return p.AndroidStaticRule(name, ruleParams, commonArgs...),
+ p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
+}
+
+// StaticVariableWithEnvOverride creates a static variable that evaluates to the value of the given
+// environment variable if set, otherwise the given default.
+func (p PackageContext) StaticVariableWithEnvOverride(name, envVar, defaultVal string) blueprint.Variable {
+ return p.VariableFunc(name, func(ctx PackageVarContext) string {
+ return ctx.Config().GetenvWithDefault(envVar, defaultVal)
+ })
+}
diff --git a/android/package_test.go b/android/package_test.go
index 99be13f..3bd30cc 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -6,7 +6,7 @@
var packageTests = []struct {
name string
- fs map[string][]byte
+ fs MockFS
expectedErrors []string
}{
// Package default_visibility handling is tested in visibility_test.go
@@ -61,43 +61,13 @@
func TestPackage(t *testing.T) {
for _, test := range packageTests {
t.Run(test.name, func(t *testing.T) {
- _, errs := testPackage(test.fs)
-
- expectedErrors := test.expectedErrors
- if expectedErrors == nil {
- FailIfErrored(t, errs)
- } else {
- for _, expectedError := range expectedErrors {
- FailIfNoMatchingErrors(t, expectedError, errs)
- }
- if len(errs) > len(expectedErrors) {
- t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
- for i, expectedError := range expectedErrors {
- t.Errorf("expectedErrors[%d] = %s", i, expectedError)
- }
- for i, err := range errs {
- t.Errorf("errs[%d] = %s", i, err)
- }
- }
- }
+ GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithPackageModule,
+ test.fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
})
}
}
-
-func testPackage(fs map[string][]byte) (*TestContext, []error) {
-
- // Create a new config per test as visibility information is stored in the config.
- config := TestArchConfig(buildDir, nil, "", fs)
-
- ctx := NewTestArchContext(config)
- RegisterPackageBuildComponents(ctx)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles(".")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
diff --git a/android/packaging.go b/android/packaging.go
index 9b901ce..72c0c17 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -59,7 +59,8 @@
packagingBase() *PackagingBase
// AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
- // When adding the dependencies, depTag is used as the tag.
+ // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
+ // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
// CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
@@ -167,6 +168,24 @@
return ret
}
+// PackagingItem is a marker interface for dependency tags.
+// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
+type PackagingItem interface {
+ // IsPackagingItem returns true if the dep is to be packaged
+ IsPackagingItem() bool
+}
+
+// DepTag provides default implementation of PackagingItem interface.
+// PackagingBase-derived modules can define their own dependency tag by embedding this, which
+// can be passed to AddDeps() or AddDependencies().
+type PackagingItemAlwaysDepTag struct {
+}
+
+// IsPackagingItem returns true if the dep is to be packaged
+func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
+ return true
+}
+
// See PackageModule.AddDeps
func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
for _, t := range p.getSupportedTargets(ctx) {
@@ -182,16 +201,15 @@
// See PackageModule.CopyDepsToZip
func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) {
m := make(map[string]PackagingSpec)
- ctx.WalkDeps(func(child Module, parent Module) bool {
- if !IsInstallDepNeeded(ctx.OtherModuleDependencyTag(child)) {
- return false
+ ctx.VisitDirectDeps(func(child Module) {
+ if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
+ return
}
- for _, ps := range child.PackagingSpecs() {
+ for _, ps := range child.TransitivePackagingSpecs() {
if _, ok := m[ps.relPathInPackage]; !ok {
m[ps.relPathInPackage] = ps
}
}
- return true
})
builder := NewRuleBuilder(pctx, ctx)
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 2c99b97..f91dc5d 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -15,7 +15,6 @@
package android
import (
- "reflect"
"testing"
"github.com/google/blueprint"
@@ -57,7 +56,9 @@
type packageTestModule struct {
ModuleBase
PackagingBase
-
+ properties struct {
+ Install_deps []string `android:`
+ }
entries []string
}
@@ -65,6 +66,7 @@
module := &packageTestModule{}
InitPackageModule(module)
InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
+ module.AddProperties(&module.properties)
return module
}
@@ -72,11 +74,18 @@
module := &packageTestModule{}
InitPackageModule(module)
InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
+ module.AddProperties(&module.properties)
return module
}
+type packagingDepTag struct {
+ blueprint.BaseDependencyTag
+ PackagingItemAlwaysDepTag
+}
+
func (m *packageTestModule) DepsMutator(ctx BottomUpMutatorContext) {
- m.AddDeps(ctx, installDepTag{})
+ m.AddDeps(ctx, packagingDepTag{})
+ ctx.AddDependency(ctx.Module(), installDepTag{}, m.properties.Install_deps...)
}
func (m *packageTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
@@ -87,33 +96,30 @@
func runPackagingTest(t *testing.T, multitarget bool, bp string, expected []string) {
t.Helper()
- config := TestArchConfig(buildDir, nil, bp, nil)
-
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("component", componentTestModuleFactory)
-
var archVariant string
+ var moduleFactory ModuleFactory
if multitarget {
archVariant = "android_common"
- ctx.RegisterModuleType("package_module", packageMultiTargetTestModuleFactory)
+ moduleFactory = packageMultiTargetTestModuleFactory
} else {
archVariant = "android_arm64_armv8-a"
- ctx.RegisterModuleType("package_module", packageTestModuleFactory)
+ moduleFactory = packageTestModuleFactory
}
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("component", componentTestModuleFactory)
+ ctx.RegisterModuleType("package_module", moduleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- p := ctx.ModuleForTests("package", archVariant).Module().(*packageTestModule)
+ p := result.Module("package", archVariant).(*packageTestModule)
actual := p.entries
actual = SortedUniqueStrings(actual)
expected = SortedUniqueStrings(expected)
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("\ngot: %v\nexpected: %v\n", actual, expected)
- }
+ AssertDeepEquals(t, "package entries", expected, actual)
}
func TestPackagingBaseMultiTarget(t *testing.T) {
@@ -341,4 +347,21 @@
},
}
`, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t, multiTarget,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ install_deps: ["bar"],
+ }
+ `, []string{"lib64/foo"})
}
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index 85c96ee..568f868 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -15,7 +15,6 @@
package android
import (
- "reflect"
"testing"
)
@@ -158,23 +157,18 @@
}
`
- config := TestArchConfig(buildDir, nil, bp, nil)
- ctx := NewTestArchContext(config)
+ result := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithFilegroup,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", pathDepsMutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx.RegisterModuleType("test", pathDepsMutatorTestModuleFactory)
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
+ m := result.Module("foo", "android_arm64_armv8-a").(*pathDepsMutatorTestModule)
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- m := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*pathDepsMutatorTestModule)
-
- if g, w := m.sourceDeps, test.deps; !reflect.DeepEqual(g, w) {
- t.Errorf("want deps %q, got %q", w, g)
- }
+ AssertDeepEquals(t, "deps", test.deps, m.sourceDeps)
})
}
}
diff --git a/android/paths_test.go b/android/paths_test.go
index 3734ed2..465ea3b 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -21,8 +21,6 @@
"strconv"
"strings"
"testing"
-
- "github.com/google/blueprint/proptools"
)
type strsTestCase struct {
@@ -977,7 +975,7 @@
rel string
}
-func testPathForModuleSrc(t *testing.T, buildDir string, tests []pathForModuleSrcTestCase) {
+func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fgBp := `
@@ -995,7 +993,7 @@
}
`
- mockFS := map[string][]byte{
+ mockFS := MockFS{
"fg/Android.bp": []byte(fgBp),
"foo/Android.bp": []byte(test.bp),
"ofp/Android.bp": []byte(ofpBp),
@@ -1007,37 +1005,21 @@
"foo/src_special/$": nil,
}
- config := TestConfig(buildDir, nil, "", mockFS)
+ result := GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
+ ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
+ ctx.RegisterModuleType("filegroup", FileGroupFactory)
+ }),
+ mockFS.AddToFixture(),
+ ).RunTest(t)
- ctx := NewTestContext(config)
+ m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
- ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
- ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
-
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"fg/Android.bp", "foo/Android.bp", "ofp/Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- m := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
-
- if g, w := m.srcs, test.srcs; !reflect.DeepEqual(g, w) {
- t.Errorf("want srcs %q, got %q", w, g)
- }
-
- if g, w := m.rels, test.rels; !reflect.DeepEqual(g, w) {
- t.Errorf("want rels %q, got %q", w, g)
- }
-
- if g, w := m.src, test.src; g != w {
- t.Errorf("want src %q, got %q", w, g)
- }
-
- if g, w := m.rel, test.rel; g != w {
- t.Errorf("want rel %q, got %q", w, g)
- }
+ AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
+ AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
+ AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
+ AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
})
}
}
@@ -1094,7 +1076,7 @@
name: "foo",
srcs: [":b"],
}`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
+ srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
rels: []string{"gen/b"},
},
{
@@ -1104,7 +1086,7 @@
name: "foo",
srcs: [":b{.tagged}"],
}`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/c"},
+ srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
rels: []string{"gen/c"},
},
{
@@ -1119,7 +1101,7 @@
name: "c",
outs: ["gen/c"],
}`,
- srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
+ srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
rels: []string{"gen/b"},
},
{
@@ -1134,7 +1116,7 @@
},
}
- testPathForModuleSrc(t, buildDir, tests)
+ testPathForModuleSrc(t, tests)
}
func TestPathForModuleSrc(t *testing.T) {
@@ -1176,7 +1158,7 @@
name: "foo",
src: ":b",
}`,
- src: buildDir + "/.intermediates/ofp/b/gen/b",
+ src: "out/soong/.intermediates/ofp/b/gen/b",
rel: "gen/b",
},
{
@@ -1186,7 +1168,7 @@
name: "foo",
src: ":b{.tagged}",
}`,
- src: buildDir + "/.intermediates/ofp/b/gen/c",
+ src: "out/soong/.intermediates/ofp/b/gen/c",
rel: "gen/c",
},
{
@@ -1201,7 +1183,7 @@
},
}
- testPathForModuleSrc(t, buildDir, tests)
+ testPathForModuleSrc(t, tests)
}
func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
@@ -1221,44 +1203,24 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ result := GroupFixturePreparers(
+ PrepareForTestWithAllowMissingDependencies,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
- ctx.SetAllowMissingDependencies(true)
+ foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
- ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
+ AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
+ AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
+ AssertStringEquals(t, "foo src", "", foo.src)
- ctx.Register()
+ bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- foo := ctx.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
-
- if g, w := foo.missingDeps, []string{"a", "b", "c"}; !reflect.DeepEqual(g, w) {
- t.Errorf("want foo missing deps %q, got %q", w, g)
- }
-
- if g, w := foo.srcs, []string{}; !reflect.DeepEqual(g, w) {
- t.Errorf("want foo srcs %q, got %q", w, g)
- }
-
- if g, w := foo.src, ""; g != w {
- t.Errorf("want foo src %q, got %q", w, g)
- }
-
- bar := ctx.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
-
- if g, w := bar.missingDeps, []string{"d", "e"}; !reflect.DeepEqual(g, w) {
- t.Errorf("want bar missing deps %q, got %q", w, g)
- }
-
- if g, w := bar.srcs, []string{}; !reflect.DeepEqual(g, w) {
- t.Errorf("want bar srcs %q, got %q", w, g)
- }
+ AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
+ AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
}
func TestPathRelativeToTop(t *testing.T) {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 32af5df..ced37fe 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -284,7 +284,7 @@
t.Errorf("windows is assumed to be disabled by default")
}
- result := emptyTestFixtureFactory.Extend(
+ result := GroupFixturePreparers(
PrepareForTestWithArchMutator,
PrepareForTestWithPrebuilts,
PrepareForTestWithOverrides,
diff --git a/android/register.go b/android/register.go
index c9e66e9..900edfa 100644
--- a/android/register.go
+++ b/android/register.go
@@ -263,8 +263,9 @@
// ctx := android.NewTestContext(config)
// RegisterBuildComponents(ctx)
var InitRegistrationContext RegistrationContext = &initRegistrationContext{
- moduleTypes: make(map[string]ModuleFactory),
- singletonTypes: make(map[string]SingletonFactory),
+ moduleTypes: make(map[string]ModuleFactory),
+ singletonTypes: make(map[string]SingletonFactory),
+ preSingletonTypes: make(map[string]SingletonFactory),
}
// Make sure the TestContext implements RegistrationContext.
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 17f211b..0d8e2b7 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint/proptools"
"android/soong/cmd/sbox/sbox_proto"
+ "android/soong/remoteexec"
"android/soong/shared"
)
@@ -48,8 +49,10 @@
sbox bool
highmem bool
remoteable RemoteRuleSupports
+ rbeParams *remoteexec.REParams
outDir WritablePath
sboxTools bool
+ sboxInputs bool
sboxManifestPath WritablePath
missingDeps []string
}
@@ -119,6 +122,18 @@
return r
}
+// Rewrapper marks the rule as running inside rewrapper using the given params in order to support
+// running on RBE. During RuleBuilder.Build the params will be combined with the inputs, outputs
+// and tools known to RuleBuilder to prepend an appropriate rewrapper command line to the rule's
+// command line.
+func (r *RuleBuilder) Rewrapper(params *remoteexec.REParams) *RuleBuilder {
+ if !r.sboxInputs {
+ panic(fmt.Errorf("RuleBuilder.Rewrapper must be called after RuleBuilder.SandboxInputs"))
+ }
+ r.rbeParams = params
+ return r
+}
+
// Sbox marks the rule as needing to be wrapped by sbox. The outputDir should point to the output
// directory that sbox will wipe. It should not be written to by any other rule. manifestPath should
// point to a location where sbox's manifest will be written and must be outside outputDir. sbox
@@ -155,6 +170,25 @@
return r
}
+// SandboxInputs enables input sandboxing for the rule by copying any referenced inputs into the
+// sandbox. It also implies SandboxTools().
+//
+// Sandboxing inputs requires RuleBuilder to be aware of all references to input paths. Paths
+// that are passed to RuleBuilder outside of the methods that expect inputs, for example
+// FlagWithArg, must use RuleBuilderCommand.PathForInput to translate the path to one that matches
+// the sandbox layout.
+func (r *RuleBuilder) SandboxInputs() *RuleBuilder {
+ if !r.sbox {
+ panic("SandboxInputs() must be called after Sbox()")
+ }
+ if len(r.commands) > 0 {
+ panic("SandboxInputs() may not be called after Command()")
+ }
+ r.sboxTools = true
+ r.sboxInputs = true
+ return r
+}
+
// Install associates an output of the rule with an install location, which can be retrieved later using
// RuleBuilder.Installs.
func (r *RuleBuilder) Install(from Path, to string) {
@@ -425,6 +459,26 @@
Inputs(depFiles.Paths())
}
+// composeRspFileContent returns a string that will serve as the contents of the rsp file to pass
+// the listed input files to the command running in the sandbox.
+func (r *RuleBuilder) composeRspFileContent(rspFileInputs Paths) string {
+ if r.sboxInputs {
+ if len(rspFileInputs) > 0 {
+ // When SandboxInputs is used the paths need to be rewritten to be relative to the sandbox
+ // directory so that they are valid after sbox chdirs into the sandbox directory.
+ return proptools.NinjaEscape(strings.Join(r.sboxPathsForInputsRel(rspFileInputs), " "))
+ } else {
+ // If the list of inputs is empty fall back to "$in" so that the rspfilecontent Ninja
+ // variable is set to something non-empty, otherwise ninja will complain. The inputs
+ // will be empty (all the non-rspfile inputs are implicits), so $in will evaluate to
+ // an empty string.
+ return "$in"
+ }
+ } else {
+ return "$in"
+ }
+}
+
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs.
func (r *RuleBuilder) Build(name string, desc string) {
@@ -511,6 +565,27 @@
}
}
+ // If sandboxing inputs is enabled, add copy rules to the manifest to copy each input
+ // into the sbox directory.
+ if r.sboxInputs {
+ for _, input := range inputs {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(input.String()),
+ To: proto.String(r.sboxPathForInputRel(input)),
+ })
+ }
+
+ // If using an rsp file copy it into the sbox directory.
+ if rspFilePath != nil {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(rspFilePath.String()),
+ To: proto.String(r.sboxPathForInputRel(rspFilePath)),
+ })
+ }
+
+ command.Chdir = proto.Bool(true)
+ }
+
// Add copy rules to the manifest to copy each output file from the sbox directory.
// to the output directory after running the commands.
sboxOutputs := make([]string, len(outputs))
@@ -523,6 +598,12 @@
})
}
+ // Outputs that were marked Temporary will not be checked that they are in the output
+ // directory by the loop above, check them here.
+ for path := range r.temporariesSet {
+ Rel(r.ctx, r.outDir.String(), path.String())
+ }
+
// Add a hash of the list of input files to the manifest so that the textproto file
// changes when the list of input files changes and causes the sbox rule that
// depends on it to rerun.
@@ -537,7 +618,7 @@
}
// Create a rule to write the manifest as a the textproto.
- WriteFileRule(r.ctx, r.sboxManifestPath, proptools.NinjaEscape(proto.MarshalTextString(&manifest)))
+ WriteFileRule(r.ctx, r.sboxManifestPath, proto.MarshalTextString(&manifest))
// Generate a new string to use as the command line of the sbox rule. This uses
// a RuleBuilderCommand as a convenience method of building the command line, then
@@ -558,6 +639,25 @@
commandString = sboxCmd.buf.String()
tools = append(tools, sboxCmd.tools...)
inputs = append(inputs, sboxCmd.inputs...)
+
+ if r.rbeParams != nil {
+ var remoteInputs []string
+ remoteInputs = append(remoteInputs, inputs.Strings()...)
+ remoteInputs = append(remoteInputs, tools.Strings()...)
+ remoteInputs = append(remoteInputs, rspFileInputs.Strings()...)
+ if rspFilePath != nil {
+ remoteInputs = append(remoteInputs, rspFilePath.String())
+ }
+ inputsListFile := r.sboxManifestPath.ReplaceExtension(r.ctx, "rbe_inputs.list")
+ inputsListContents := rspFileForInputs(remoteInputs)
+ WriteFileRule(r.ctx, inputsListFile, inputsListContents)
+ inputs = append(inputs, inputsListFile)
+
+ r.rbeParams.OutputFiles = outputs.Strings()
+ r.rbeParams.RSPFile = inputsListFile.String()
+ rewrapperCommand := r.rbeParams.NoVarTemplate(r.ctx.Config().RBEWrapper())
+ commandString = rewrapperCommand + " bash -c '" + strings.ReplaceAll(commandString, `'`, `'\''`) + "'"
+ }
} else {
// If not using sbox the rule will run the command directly, put the hash of the
// list of input files in a comment at the end of the command line to ensure ninja
@@ -574,7 +674,7 @@
var rspFile, rspFileContent string
if rspFilePath != nil {
rspFile = rspFilePath.String()
- rspFileContent = "$in"
+ rspFileContent = r.composeRspFileContent(rspFileInputs)
}
var pool blueprint.Pool
@@ -630,29 +730,45 @@
}
func (c *RuleBuilderCommand) addInput(path Path) string {
- if c.rule.sbox {
- if rel, isRel, _ := maybeRelErr(c.rule.outDir.String(), path.String()); isRel {
- return filepath.Join(sboxOutDir, rel)
- }
- }
c.inputs = append(c.inputs, path)
- return path.String()
+ return c.PathForInput(path)
}
-func (c *RuleBuilderCommand) addImplicit(path Path) string {
- if c.rule.sbox {
- if rel, isRel, _ := maybeRelErr(c.rule.outDir.String(), path.String()); isRel {
- return filepath.Join(sboxOutDir, rel)
- }
- }
+func (c *RuleBuilderCommand) addImplicit(path Path) {
c.implicits = append(c.implicits, path)
- return path.String()
}
func (c *RuleBuilderCommand) addOrderOnly(path Path) {
c.orderOnlys = append(c.orderOnlys, path)
}
+// PathForInput takes an input path and returns the appropriate path to use on the command line. If
+// sbox was enabled via a call to RuleBuilder.Sbox() and the path was an output path it returns a
+// path with the placeholder prefix used for outputs in sbox. If sbox is not enabled it returns the
+// original path.
+func (c *RuleBuilderCommand) PathForInput(path Path) string {
+ if c.rule.sbox {
+ rel, inSandbox := c.rule._sboxPathForInputRel(path)
+ if inSandbox {
+ rel = filepath.Join(sboxSandboxBaseDir, rel)
+ }
+ return rel
+ }
+ return path.String()
+}
+
+// PathsForInputs takes a list of input paths and returns the appropriate paths to use on the
+// command line. If sbox was enabled via a call to RuleBuilder.Sbox() a path was an output path, it
+// returns the path with the placeholder prefix used for outputs in sbox. If sbox is not enabled it
+// returns the original paths.
+func (c *RuleBuilderCommand) PathsForInputs(paths Paths) []string {
+ ret := make([]string, len(paths))
+ for i, path := range paths {
+ ret[i] = c.PathForInput(path)
+ }
+ return ret
+}
+
// PathForOutput takes an output path and returns the appropriate path to use on the command
// line. If sbox was enabled via a call to RuleBuilder.Sbox(), it returns a path with the
// placeholder prefix used for outputs in sbox. If sbox is not enabled it returns the
@@ -684,6 +800,37 @@
return filepath.Join(sboxToolsSubDir, "src", path.String())
}
+func (r *RuleBuilder) _sboxPathForInputRel(path Path) (rel string, inSandbox bool) {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ rel, isRelSboxOut, _ := maybeRelErr(r.outDir.String(), path.String())
+ if isRelSboxOut {
+ return filepath.Join(sboxOutSubDir, rel), true
+ }
+ if r.sboxInputs {
+ // When sandboxing inputs all inputs have to be copied into the sandbox. Input files that
+ // are outputs of other rules could be an arbitrary absolute path if OUT_DIR is set, so they
+ // will be copied to relative paths under __SBOX_OUT_DIR__/out.
+ rel, isRelOut, _ := maybeRelErr(PathForOutput(r.ctx).String(), path.String())
+ if isRelOut {
+ return filepath.Join(sboxOutSubDir, rel), true
+ }
+ }
+ return path.String(), false
+}
+
+func (r *RuleBuilder) sboxPathForInputRel(path Path) string {
+ rel, _ := r._sboxPathForInputRel(path)
+ return rel
+}
+
+func (r *RuleBuilder) sboxPathsForInputsRel(paths Paths) []string {
+ ret := make([]string, len(paths))
+ for i, path := range paths {
+ ret[i] = r.sboxPathForInputRel(path)
+ }
+ return ret
+}
+
// SboxPathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the
// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to
// reference the tool.
@@ -1047,7 +1194,7 @@
}
}
- c.FlagWithArg(flag, rspFile.String())
+ c.FlagWithArg(flag, c.PathForInput(rspFile))
return c
}
@@ -1116,3 +1263,14 @@
return nil
}
func (builderContextForTests) Build(PackageContext, BuildParams) {}
+
+func rspFileForInputs(paths []string) string {
+ s := strings.Builder{}
+ for i, path := range paths {
+ if i != 0 {
+ s.WriteByte(' ')
+ }
+ s.WriteString(proptools.ShellEscape(path))
+ }
+ return s.String()
+}
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 080e236..9cd60a2 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -17,7 +17,6 @@
import (
"fmt"
"path/filepath"
- "reflect"
"regexp"
"strings"
"testing"
@@ -297,35 +296,40 @@
"input3": nil,
}
- pathCtx := PathContextForTesting(TestConfig("out", nil, "", fs))
+ pathCtx := PathContextForTesting(TestConfig("out_local", nil, "", fs))
ctx := builderContextForTests{
PathContext: pathCtx,
}
addCommands := func(rule *RuleBuilder) {
cmd := rule.Command().
- DepFile(PathForOutput(ctx, "DepFile")).
+ DepFile(PathForOutput(ctx, "module/DepFile")).
Flag("Flag").
FlagWithArg("FlagWithArg=", "arg").
- FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "depfile")).
+ FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "module/depfile")).
FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
- FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
+ FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "module/output")).
+ FlagWithRspFileInputList("FlagWithRspFileInputList=", PathForOutput(ctx, "rsp"),
+ Paths{
+ PathForSource(ctx, "RspInput"),
+ PathForOutput(ctx, "other/RspOutput2"),
+ }).
Implicit(PathForSource(ctx, "Implicit")).
- ImplicitDepFile(PathForOutput(ctx, "ImplicitDepFile")).
- ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
+ ImplicitDepFile(PathForOutput(ctx, "module/ImplicitDepFile")).
+ ImplicitOutput(PathForOutput(ctx, "module/ImplicitOutput")).
Input(PathForSource(ctx, "Input")).
- Output(PathForOutput(ctx, "Output")).
+ Output(PathForOutput(ctx, "module/Output")).
OrderOnly(PathForSource(ctx, "OrderOnly")).
- SymlinkOutput(PathForOutput(ctx, "SymlinkOutput")).
- ImplicitSymlinkOutput(PathForOutput(ctx, "ImplicitSymlinkOutput")).
+ SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")).
+ ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
rule.Command().
Text("command2").
- DepFile(PathForOutput(ctx, "depfile2")).
+ DepFile(PathForOutput(ctx, "module/depfile2")).
Input(PathForSource(ctx, "input2")).
- Output(PathForOutput(ctx, "output2")).
+ Output(PathForOutput(ctx, "module/output2")).
OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Tool(PathForSource(ctx, "tool2"))
@@ -338,131 +342,121 @@
rule.Command().
Text("command3").
Input(PathForSource(ctx, "input3")).
- Input(PathForOutput(ctx, "output2")).
- Output(PathForOutput(ctx, "output3"))
+ Input(PathForOutput(ctx, "module/output2")).
+ Output(PathForOutput(ctx, "module/output3")).
+ Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
+ Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
}
wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
- wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "ImplicitSymlinkOutput", "Output", "SymlinkOutput", "output", "output2", "output3"})
- wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
+ wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
+ PathForOutput(ctx, "other/RspOutput2")}
+ wantOutputs := PathsForOutput(ctx, []string{
+ "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput",
+ "module/output", "module/output2", "module/output3"})
+ wantDepFiles := PathsForOutput(ctx, []string{
+ "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
- wantSymlinkOutputs := PathsForOutput(ctx, []string{"ImplicitSymlinkOutput", "SymlinkOutput"})
+ wantSymlinkOutputs := PathsForOutput(ctx, []string{
+ "module/ImplicitSymlinkOutput", "module/SymlinkOutput"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder(pctx, ctx)
addCommands(rule)
wantCommands := []string{
- "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output out/SymlinkOutput Text Tool after command2 old cmd",
- "command2 out/depfile2 input2 out/output2 tool2",
- "command3 input3 out/output2 out/output3",
+ "out_local/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/module/depfile " +
+ "FlagWithInput=input FlagWithOutput=out_local/module/output FlagWithRspFileInputList=out_local/rsp " +
+ "Input out_local/module/Output out_local/module/SymlinkOutput Text Tool after command2 old cmd",
+ "command2 out_local/module/depfile2 input2 out_local/module/output2 tool2",
+ "command3 input3 out_local/module/output2 out_local/module/output3 input3 out_local/module/output2",
}
- wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
+ wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
+ "out_local/module/DepFile out_local/module/depfile out_local/module/ImplicitDepFile out_local/module/depfile2"
- if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
- t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
- }
+ wantRspFileContent := "$in"
- if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.SymlinkOutputs(), wantSymlinkOutputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.SymlinkOutputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
- }
- if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
- if g, w := rule.depFileMergerCmd(rule.DepFiles()).String(), wantDepMergerCommand; g != w {
- t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
+ AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
+ AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
+ AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
+ AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
+ AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
+ AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
+
+ AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
+
+ AssertSame(t, "rule.composeRspFileContent()", wantRspFileContent, rule.composeRspFileContent(rule.RspFileInputs()))
})
t.Run("sbox", func(t *testing.T) {
- rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, ""),
+ rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
PathForOutput(ctx, "sbox.textproto"))
addCommands(rule)
wantCommands := []string{
- "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output Input __SBOX_SANDBOX_DIR__/out/Output __SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
+ "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
+ "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
+ "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
+ "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
- "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3",
+ "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
- wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
+ wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
- if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
- t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
- }
+ wantRspFileContent := "$in"
- if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
- }
- if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
- if g, w := rule.depFileMergerCmd(rule.DepFiles()).String(), wantDepMergerCommand; g != w {
- t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
+ AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
+ AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
+ AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
+ AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
+ AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
+ AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
+
+ AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
+
+ AssertSame(t, "rule.composeRspFileContent()", wantRspFileContent, rule.composeRspFileContent(rule.RspFileInputs()))
})
t.Run("sbox tools", func(t *testing.T) {
- rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, ""),
+ rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
PathForOutput(ctx, "sbox.textproto")).SandboxTools()
addCommands(rule)
wantCommands := []string{
- "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output Input __SBOX_SANDBOX_DIR__/out/Output __SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
+ "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
+ "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
+ "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
+ "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
- "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3",
+ "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
- if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
- t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
- }
+ wantRspFileContent := "$in"
- if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
- }
- if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
- if g, w := rule.depFileMergerCmd(rule.DepFiles()).String(), wantDepMergerCommand; g != w {
- t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
- }
+ AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
+ AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
+ AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
+ AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
+ AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
+ AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
+ AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
+
+ AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
+
+ AssertSame(t, "rule.composeRspFileContent()", wantRspFileContent, rule.composeRspFileContent(rule.RspFileInputs()))
})
}
@@ -524,8 +518,13 @@
rule.Build("rule", "desc")
}
+var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
+ ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
+})
+
func TestRuleBuilder_Build(t *testing.T) {
- fs := map[string][]byte{
+ fs := MockFS{
"bar": nil,
"cp": nil,
}
@@ -543,51 +542,35 @@
}
`
- config := TestConfig(buildDir, nil, bp, fs)
- ctx := NewTestContext(config)
- ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
- ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := GroupFixturePreparers(
+ prepareForRuleBuilderTest,
+ FixtureWithRootAndroidBp(bp),
+ fs.AddToFixture(),
+ ).RunTest(t)
check := func(t *testing.T, params TestingBuildParams, wantCommand, wantOutput, wantDepfile string, wantRestat bool, extraImplicits, extraCmdDeps []string) {
t.Helper()
command := params.RuleParams.Command
re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
command = re.ReplaceAllLiteralString(command, "")
- if command != wantCommand {
- t.Errorf("\nwant RuleParams.Command = %q\n got %q", wantCommand, params.RuleParams.Command)
- }
+
+ AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
wantDeps := append([]string{"cp"}, extraCmdDeps...)
- if !reflect.DeepEqual(params.RuleParams.CommandDeps, wantDeps) {
- t.Errorf("\nwant RuleParams.CommandDeps = %q\n got %q", wantDeps, params.RuleParams.CommandDeps)
- }
+ AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
- if params.RuleParams.Restat != wantRestat {
- t.Errorf("want RuleParams.Restat = %v, got %v", wantRestat, params.RuleParams.Restat)
- }
+ AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
wantImplicits := append([]string{"bar"}, extraImplicits...)
- if !reflect.DeepEqual(params.Implicits.Strings(), wantImplicits) {
- t.Errorf("want Implicits = [%q], got %q", "bar", params.Implicits.Strings())
- }
+ AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
- if params.Output.String() != wantOutput {
- t.Errorf("want Output = %q, got %q", wantOutput, params.Output)
- }
+ AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
if len(params.ImplicitOutputs) != 0 {
t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
}
- if params.Depfile.String() != wantDepfile {
- t.Errorf("want Depfile = %q, got %q", wantDepfile, params.Depfile)
- }
+ AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
if params.Deps != blueprint.DepsGCC {
t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
@@ -595,28 +578,28 @@
}
t.Run("module", func(t *testing.T) {
- outFile := filepath.Join(buildDir, ".intermediates", "foo", "gen", "foo")
- check(t, ctx.ModuleForTests("foo", "").Rule("rule"),
+ outFile := "out/soong/.intermediates/foo/gen/foo"
+ check(t, result.ModuleForTests("foo", "").Rule("rule").RelativeToTop(),
"cp bar "+outFile,
outFile, outFile+".d", true, nil, nil)
})
t.Run("sbox", func(t *testing.T) {
- outDir := filepath.Join(buildDir, ".intermediates", "foo_sbox")
+ outDir := "out/soong/.intermediates/foo_sbox"
outFile := filepath.Join(outDir, "gen/foo_sbox")
depFile := filepath.Join(outDir, "gen/foo_sbox.d")
manifest := filepath.Join(outDir, "sbox.textproto")
- sbox := filepath.Join(buildDir, "host", config.PrebuiltOS(), "bin/sbox")
- sandboxPath := shared.TempDirForOutDir(buildDir)
+ sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
+ sandboxPath := shared.TempDirForOutDir("out/soong")
cmd := `rm -rf ` + outDir + `/gen && ` +
sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
- check(t, ctx.ModuleForTests("foo_sbox", "").Output("gen/foo_sbox"),
+ check(t, result.ModuleForTests("foo_sbox", "").Output("gen/foo_sbox").RelativeToTop(),
cmd, outFile, depFile, false, []string{manifest}, []string{sbox})
})
t.Run("singleton", func(t *testing.T) {
- outFile := filepath.Join(buildDir, "singleton/gen/baz")
- check(t, ctx.SingletonForTests("rule_builder_test").Rule("rule"),
+ outFile := filepath.Join("out/soong/singleton/gen/baz")
+ check(t, result.SingletonForTests("rule_builder_test").Rule("rule").RelativeToTop(),
"cp bar "+outFile, outFile, outFile+".d", true, nil, nil)
})
}
@@ -666,29 +649,22 @@
},
}
- config := TestConfig(buildDir, nil, bp, nil)
- ctx := NewTestContext(config)
- ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := GroupFixturePreparers(
+ prepareForRuleBuilderTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
t.Run("sbox", func(t *testing.T) {
- gen := ctx.ModuleForTests(test.name+"_sbox", "")
+ gen := result.ModuleForTests(test.name+"_sbox", "")
manifest := RuleBuilderSboxProtoForTests(t, gen.Output("sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
- if g, w := hash, test.expectedHash; g != w {
- t.Errorf("Expected has %q, got %q", w, g)
- }
+ AssertStringEquals(t, "hash", test.expectedHash, hash)
})
t.Run("", func(t *testing.T) {
- gen := ctx.ModuleForTests(test.name+"", "")
+ gen := result.ModuleForTests(test.name+"", "")
command := gen.Output("gen/" + test.name).RuleParams.Command
if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
t.Errorf("Expected command line to end with %q, got %q", w, g)
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index 9232eb4..eb5554c 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -15,8 +15,6 @@
package android
import (
- "reflect"
- "strings"
"testing"
)
@@ -43,23 +41,14 @@
return tsm
}
-func runSingletonModuleTest(bp string) (*TestContext, []error) {
- config := TestConfig(buildDir, nil, bp, nil)
+var prepareForSingletonModuleTest = GroupFixturePreparers(
// Enable Kati output to test SingletonModules with MakeVars.
- config.katiEnabled = true
- ctx := NewTestContext(config)
- ctx.RegisterSingletonModuleType("test_singleton_module", testSingletonModuleFactory)
- ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
+ PrepareForTestWithAndroidMk,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterSingletonModuleType("test_singleton_module", testSingletonModuleFactory)
+ ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
+ }),
+)
func TestSingletonModule(t *testing.T) {
bp := `
@@ -67,16 +56,14 @@
name: "test_singleton_module",
}
`
- ctx, errs := runSingletonModuleTest(bp)
- if len(errs) > 0 {
- t.Fatal(errs)
- }
+ result := GroupFixturePreparers(
+ prepareForSingletonModuleTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ops := ctx.ModuleForTests("test_singleton_module", "").Module().(*testSingletonModule).ops
+ ops := result.ModuleForTests("test_singleton_module", "").Module().(*testSingletonModule).ops
wantOps := []string{"GenerateAndroidBuildActions", "GenerateSingletonBuildActions", "MakeVars"}
- if !reflect.DeepEqual(ops, wantOps) {
- t.Errorf("Expected operations %q, got %q", wantOps, ops)
- }
+ AssertDeepEquals(t, "operations", wantOps, ops)
}
func TestDuplicateSingletonModule(t *testing.T) {
@@ -89,23 +76,19 @@
name: "test_singleton_module2",
}
`
- _, errs := runSingletonModuleTest(bp)
- if len(errs) == 0 {
- t.Fatal("expected duplicate SingletonModule error")
- }
- if len(errs) != 1 || !strings.Contains(errs[0].Error(), `Duplicate SingletonModule "test_singleton_module", previously used in`) {
- t.Fatalf("expected duplicate SingletonModule error, got %q", errs)
- }
+
+ prepareForSingletonModuleTest.
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
+ `\QDuplicate SingletonModule "test_singleton_module", previously used in\E`,
+ })).RunTestWithBp(t, bp)
}
func TestUnusedSingletonModule(t *testing.T) {
- bp := ``
- ctx, errs := runSingletonModuleTest(bp)
- if len(errs) > 0 {
- t.Fatal(errs)
- }
+ result := GroupFixturePreparers(
+ prepareForSingletonModuleTest,
+ ).RunTest(t)
- singleton := ctx.SingletonForTests("test_singleton_module").Singleton()
+ singleton := result.SingletonForTests("test_singleton_module").Singleton()
sm := singleton.(*singletonModuleSingletonAdaptor).sm
ops := sm.(*testSingletonModule).ops
if ops != nil {
@@ -126,24 +109,16 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- ctx := NewTestContext(config)
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("test_singleton_module_mutator", testVariantSingletonModuleMutator)
- })
- ctx.RegisterSingletonModuleType("test_singleton_module", testSingletonModuleFactory)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
-
- if len(errs) == 0 {
- _, errs = ctx.PrepareBuildActions(config)
- }
-
- if len(errs) == 0 {
- t.Fatal("expected duplicate SingletonModule error")
- }
- if len(errs) != 1 || !strings.Contains(errs[0].Error(), `GenerateAndroidBuildActions already called for variant`) {
- t.Fatalf("expected duplicate SingletonModule error, got %q", errs)
- }
+ GroupFixturePreparers(
+ prepareForSingletonModuleTest,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("test_singleton_module_mutator", testVariantSingletonModuleMutator)
+ })
+ }),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
+ `\QGenerateAndroidBuildActions already called for variant\E`,
+ })).
+ RunTestWithBp(t, bp)
}
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 45463fd..8f252d9 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -15,7 +15,6 @@
package android
import (
- "reflect"
"testing"
)
@@ -181,17 +180,23 @@
}
`
- run := func(t *testing.T, bp string, fs map[string][]byte) {
+ fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer {
+ return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.VendorVars = vars
+ })
+ }
+
+ run := func(t *testing.T, bp string, fs MockFS) {
testCases := []struct {
name string
- config Config
+ preparer FixturePreparer
fooExpectedFlags []string
fooDefaultsExpectedFlags []string
}{
{
name: "withValues",
- config: testConfigWithVendorVars(buildDir, bp, fs, map[string]map[string]string{
- "acme": map[string]string{
+ preparer: fixtureForVendorVars(map[string]map[string]string{
+ "acme": {
"board": "soc_a",
"size": "42",
"feature1": "true",
@@ -221,8 +226,8 @@
},
{
name: "empty_prop_for_string_var",
- config: testConfigWithVendorVars(buildDir, bp, fs, map[string]map[string]string{
- "acme": map[string]string{"board": "soc_c"}}),
+ preparer: fixtureForVendorVars(map[string]map[string]string{
+ "acme": {"board": "soc_c"}}),
fooExpectedFlags: []string{
"DEFAULT",
"-DGENERIC",
@@ -237,8 +242,8 @@
},
{
name: "unused_string_var",
- config: testConfigWithVendorVars(buildDir, bp, fs, map[string]map[string]string{
- "acme": map[string]string{"board": "soc_d"}}),
+ preparer: fixtureForVendorVars(map[string]map[string]string{
+ "acme": {"board": "soc_d"}}),
fooExpectedFlags: []string{
"DEFAULT",
"-DGENERIC",
@@ -254,8 +259,8 @@
},
{
- name: "conditions_default",
- config: testConfigWithVendorVars(buildDir, bp, fs, map[string]map[string]string{}),
+ name: "conditions_default",
+ preparer: fixtureForVendorVars(map[string]map[string]string{}),
fooExpectedFlags: []string{
"DEFAULT",
"-DGENERIC",
@@ -272,32 +277,29 @@
}
for _, tc := range testCases {
- ctx := NewTestContext(tc.config)
- ctx.RegisterModuleType("soong_config_module_type_import", soongConfigModuleTypeImportFactory)
- ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
- ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
- ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
- ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
- ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.Register()
+ t.Run(tc.name, func(t *testing.T) {
+ result := GroupFixturePreparers(
+ tc.preparer,
+ PrepareForTestWithDefaults,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("soong_config_module_type_import", soongConfigModuleTypeImportFactory)
+ ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory)
+ ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory)
+ ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory)
+ ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
+ ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
+ }),
+ fs.AddToFixture(),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(tc.config)
- FailIfErrored(t, errs)
+ foo := result.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
+ AssertDeepEquals(t, "foo cflags", tc.fooExpectedFlags, foo.props.Cflags)
- foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
- if g, w := foo.props.Cflags, tc.fooExpectedFlags; !reflect.DeepEqual(g, w) {
- t.Errorf("%s: wanted foo cflags %q, got %q", tc.name, w, g)
- }
-
- fooDefaults := ctx.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
- if g, w := fooDefaults.props.Cflags, tc.fooDefaultsExpectedFlags; !reflect.DeepEqual(g, w) {
- t.Errorf("%s: wanted foo_with_defaults cflags %q, got %q", tc.name, w, g)
- }
+ fooDefaults := result.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
+ AssertDeepEquals(t, "foo_with_defaults cflags", tc.fooDefaultsExpectedFlags, fooDefaults.props.Cflags)
+ })
}
-
}
t.Run("single file", func(t *testing.T) {
diff --git a/android/test_asserts.go b/android/test_asserts.go
index 5100abb..bfb88ab 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -15,6 +15,7 @@
package android
import (
+ "fmt"
"reflect"
"strings"
"testing"
@@ -22,6 +23,15 @@
// This file contains general purpose test assert functions.
+// AssertSame checks if the expected and actual values are equal and if they are not then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertSame(t *testing.T, message string, expected interface{}, actual interface{}) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("%s: expected:\n%#v\nactual:\n%#v", message, expected, actual)
+ }
+}
+
// AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
// reports an error prefixed with the supplied message and including a reason for why it failed.
func AssertBoolEquals(t *testing.T, message string, expected bool, actual bool) {
@@ -31,6 +41,15 @@
}
}
+// AssertIntEquals checks if the expected and actual values are equal and if they are not then it
+// reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertIntEquals(t *testing.T, message string, expected int, actual int) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("%s: expected %d, actual %d", message, expected, actual)
+ }
+}
+
// AssertStringEquals checks if the expected and actual values are equal and if they are not then
// it reports an error prefixed with the supplied message and including a reason for why it failed.
func AssertStringEquals(t *testing.T, message string, expected string, actual string) {
@@ -144,19 +163,24 @@
}
}
-// AssertPanic checks that the supplied function panics as expected.
-func AssertPanic(t *testing.T, message string, funcThatShouldPanic func()) {
+// AssertPanicMessageContains checks that the supplied function panics as expected and the message
+// obtained by formatting the recovered value as a string contains the expected contents.
+func AssertPanicMessageContains(t *testing.T, message, expectedMessageContents string, funcThatShouldPanic func()) {
t.Helper()
panicked := false
+ var recovered interface{}
func() {
defer func() {
- if x := recover(); x != nil {
+ if recovered = recover(); recovered != nil {
panicked = true
}
}()
funcThatShouldPanic()
}()
if !panicked {
- t.Error(message)
+ t.Errorf("%s: did not panic", message)
}
+
+ panicMessage := fmt.Sprintf("%s", recovered)
+ AssertStringDoesContain(t, fmt.Sprintf("%s: panic message", message), panicMessage, expectedMessageContents)
}
diff --git a/android/testing.go b/android/testing.go
index af360fa..f17de31 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -479,7 +479,7 @@
}
}
- return TestingModule{module}
+ return newTestingModule(ctx.config, module)
}
func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
@@ -499,8 +499,8 @@
n := ctx.SingletonName(s)
if n == name {
return TestingSingleton{
- singleton: s.(*singletonAdaptor).Singleton,
- provider: s.(testBuildProvider),
+ baseTestingComponent: newBaseTestingComponent(ctx.config, s.(testBuildProvider)),
+ singleton: s.(*singletonAdaptor).Singleton,
}
}
allSingletonNames = append(allSingletonNames, n)
@@ -522,62 +522,170 @@
type TestingBuildParams struct {
BuildParams
RuleParams blueprint.RuleParams
+
+ config Config
}
-func newTestingBuildParams(provider testBuildProvider, bparams BuildParams) TestingBuildParams {
+// RelativeToTop creates a new instance of this which has had any usages of the current test's
+// temporary and test specific build directory replaced with a path relative to the notional top.
+//
+// The parts of this structure which are changed are:
+// * BuildParams
+// * Args
+// * Path instances are intentionally not modified, use AssertPathRelativeToTopEquals or
+// AssertPathsRelativeToTopEquals instead which do something similar.
+//
+// * RuleParams
+// * Command
+// * Depfile
+// * Rspfile
+// * RspfileContent
+// * SymlinkOutputs
+// * CommandDeps
+// * CommandOrderOnly
+//
+// See PathRelativeToTop for more details.
+func (p TestingBuildParams) RelativeToTop() TestingBuildParams {
+ // If this is not a valid params then just return it back. That will make it easy to use with the
+ // Maybe...() methods.
+ if p.Rule == nil {
+ return p
+ }
+ if p.config.config == nil {
+ panic("cannot call RelativeToTop() on a TestingBuildParams previously returned by RelativeToTop()")
+ }
+ // Take a copy of the build params and replace any args that contains test specific temporary
+ // paths with paths relative to the top.
+ bparams := p.BuildParams
+ bparams.Args = normalizeStringMapRelativeToTop(p.config, bparams.Args)
+
+ // Ditto for any fields in the RuleParams.
+ rparams := p.RuleParams
+ rparams.Command = normalizeStringRelativeToTop(p.config, rparams.Command)
+ rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile)
+ rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile)
+ rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent)
+ rparams.SymlinkOutputs = normalizeStringArrayRelativeToTop(p.config, rparams.SymlinkOutputs)
+ rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps)
+ rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly)
+
return TestingBuildParams{
BuildParams: bparams,
- RuleParams: provider.RuleParamsForTests()[bparams.Rule],
+ RuleParams: rparams,
}
}
-func maybeBuildParamsFromRule(provider testBuildProvider, rule string) (TestingBuildParams, []string) {
+// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton.
+type baseTestingComponent struct {
+ config Config
+ provider testBuildProvider
+}
+
+func newBaseTestingComponent(config Config, provider testBuildProvider) baseTestingComponent {
+ return baseTestingComponent{config, provider}
+}
+
+// A function that will normalize a string containing paths, e.g. ninja command, by replacing
+// any references to the test specific temporary build directory that changes with each run to a
+// fixed path relative to a notional top directory.
+//
+// This is similar to StringPathRelativeToTop except that assumes the string is a single path
+// containing at most one instance of the temporary build directory at the start of the path while
+// this assumes that there can be any number at any position.
+func normalizeStringRelativeToTop(config Config, s string) string {
+ // The buildDir usually looks something like: /tmp/testFoo2345/001
+ //
+ // Replace any usage of the buildDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
+ // "out/soong".
+ outSoongDir := filepath.Clean(config.buildDir)
+ re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`)
+ s = re.ReplaceAllString(s, "out/soong")
+
+ // Replace any usage of the buildDir/.. with out, e.g. replace "/tmp/testFoo2345" with
+ // "out". This must come after the previous replacement otherwise this would replace
+ // "/tmp/testFoo2345/001" with "out/001" instead of "out/soong".
+ outDir := filepath.Dir(outSoongDir)
+ re = regexp.MustCompile(`\Q` + outDir + `\E\b`)
+ s = re.ReplaceAllString(s, "out")
+
+ return s
+}
+
+// normalizeStringArrayRelativeToTop creates a new slice constructed by applying
+// normalizeStringRelativeToTop to each item in the slice.
+func normalizeStringArrayRelativeToTop(config Config, slice []string) []string {
+ newSlice := make([]string, len(slice))
+ for i, s := range slice {
+ newSlice[i] = normalizeStringRelativeToTop(config, s)
+ }
+ return newSlice
+}
+
+// normalizeStringMapRelativeToTop creates a new map constructed by applying
+// normalizeStringRelativeToTop to each value in the map.
+func normalizeStringMapRelativeToTop(config Config, m map[string]string) map[string]string {
+ newMap := map[string]string{}
+ for k, v := range m {
+ newMap[k] = normalizeStringRelativeToTop(config, v)
+ }
+ return newMap
+}
+
+func (b baseTestingComponent) newTestingBuildParams(bparams BuildParams) TestingBuildParams {
+ return TestingBuildParams{
+ config: b.config,
+ BuildParams: bparams,
+ RuleParams: b.provider.RuleParamsForTests()[bparams.Rule],
+ }
+}
+
+func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
var searchedRules []string
- for _, p := range provider.BuildParamsForTests() {
+ for _, p := range b.provider.BuildParamsForTests() {
searchedRules = append(searchedRules, p.Rule.String())
if strings.Contains(p.Rule.String(), rule) {
- return newTestingBuildParams(provider, p), searchedRules
+ return b.newTestingBuildParams(p), searchedRules
}
}
return TestingBuildParams{}, searchedRules
}
-func buildParamsFromRule(provider testBuildProvider, rule string) TestingBuildParams {
- p, searchRules := maybeBuildParamsFromRule(provider, rule)
+func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
+ p, searchRules := b.maybeBuildParamsFromRule(rule)
if p.Rule == nil {
panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
}
return p
}
-func maybeBuildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
- for _, p := range provider.BuildParamsForTests() {
+func (b baseTestingComponent) maybeBuildParamsFromDescription(desc string) TestingBuildParams {
+ for _, p := range b.provider.BuildParamsForTests() {
if strings.Contains(p.Description, desc) {
- return newTestingBuildParams(provider, p)
+ return b.newTestingBuildParams(p)
}
}
return TestingBuildParams{}
}
-func buildParamsFromDescription(provider testBuildProvider, desc string) TestingBuildParams {
- p := maybeBuildParamsFromDescription(provider, desc)
+func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
+ p := b.maybeBuildParamsFromDescription(desc)
if p.Rule == nil {
panic(fmt.Errorf("couldn't find description %q", desc))
}
return p
}
-func maybeBuildParamsFromOutput(provider testBuildProvider, file string) (TestingBuildParams, []string) {
+func (b baseTestingComponent) maybeBuildParamsFromOutput(file string) (TestingBuildParams, []string) {
var searchedOutputs []string
- for _, p := range provider.BuildParamsForTests() {
+ for _, p := range b.provider.BuildParamsForTests() {
outputs := append(WritablePaths(nil), p.Outputs...)
outputs = append(outputs, p.ImplicitOutputs...)
if p.Output != nil {
outputs = append(outputs, p.Output)
}
for _, f := range outputs {
- if f.String() == file || f.Rel() == file {
- return newTestingBuildParams(provider, p), nil
+ if f.String() == file || f.Rel() == file || PathRelativeToTop(f) == file {
+ return b.newTestingBuildParams(p), nil
}
searchedOutputs = append(searchedOutputs, f.Rel())
}
@@ -585,18 +693,18 @@
return TestingBuildParams{}, searchedOutputs
}
-func buildParamsFromOutput(provider testBuildProvider, file string) TestingBuildParams {
- p, searchedOutputs := maybeBuildParamsFromOutput(provider, file)
+func (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams {
+ p, searchedOutputs := b.maybeBuildParamsFromOutput(file)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find output %q.\nall outputs: %v",
- file, searchedOutputs))
+ panic(fmt.Errorf("couldn't find output %q.\nall outputs:\n %s\n",
+ file, strings.Join(searchedOutputs, "\n ")))
}
return p
}
-func allOutputs(provider testBuildProvider) []string {
+func (b baseTestingComponent) allOutputs() []string {
var outputFullPaths []string
- for _, p := range provider.BuildParamsForTests() {
+ for _, p := range b.provider.BuildParamsForTests() {
outputs := append(WritablePaths(nil), p.Outputs...)
outputs = append(outputs, p.ImplicitOutputs...)
if p.Output != nil {
@@ -607,64 +715,78 @@
return outputFullPaths
}
+// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
+// BuildParams if no rule is found.
+func (b baseTestingComponent) MaybeRule(rule string) TestingBuildParams {
+ r, _ := b.maybeBuildParamsFromRule(rule)
+ return r
+}
+
+// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
+func (b baseTestingComponent) Rule(rule string) TestingBuildParams {
+ return b.buildParamsFromRule(rule)
+}
+
+// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
+// BuildParams if no rule is found.
+func (b baseTestingComponent) MaybeDescription(desc string) TestingBuildParams {
+ return b.maybeBuildParamsFromDescription(desc)
+}
+
+// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
+// found.
+func (b baseTestingComponent) Description(desc string) TestingBuildParams {
+ return b.buildParamsFromDescription(desc)
+}
+
+// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
+// value matches the provided string. Returns an empty BuildParams if no rule is found.
+func (b baseTestingComponent) MaybeOutput(file string) TestingBuildParams {
+ p, _ := b.maybeBuildParamsFromOutput(file)
+ return p
+}
+
+// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
+// value matches the provided string. Panics if no rule is found.
+func (b baseTestingComponent) Output(file string) TestingBuildParams {
+ return b.buildParamsFromOutput(file)
+}
+
+// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
+func (b baseTestingComponent) AllOutputs() []string {
+ return b.allOutputs()
+}
+
// TestingModule is wrapper around an android.Module that provides methods to find information about individual
// ctx.Build parameters for verification in tests.
type TestingModule struct {
+ baseTestingComponent
module Module
}
+func newTestingModule(config Config, module Module) TestingModule {
+ return TestingModule{
+ newBaseTestingComponent(config, module),
+ module,
+ }
+}
+
// Module returns the Module wrapped by the TestingModule.
func (m TestingModule) Module() Module {
return m.module
}
-// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
-// BuildParams if no rule is found.
-func (m TestingModule) MaybeRule(rule string) TestingBuildParams {
- r, _ := maybeBuildParamsFromRule(m.module, rule)
- return r
-}
-
-// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
-func (m TestingModule) Rule(rule string) TestingBuildParams {
- return buildParamsFromRule(m.module, rule)
-}
-
-// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
-// BuildParams if no rule is found.
-func (m TestingModule) MaybeDescription(desc string) TestingBuildParams {
- return maybeBuildParamsFromDescription(m.module, desc)
-}
-
-// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
-// found.
-func (m TestingModule) Description(desc string) TestingBuildParams {
- return buildParamsFromDescription(m.module, desc)
-}
-
-// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
-// value matches the provided string. Returns an empty BuildParams if no rule is found.
-func (m TestingModule) MaybeOutput(file string) TestingBuildParams {
- p, _ := maybeBuildParamsFromOutput(m.module, file)
- return p
-}
-
-// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
-// value matches the provided string. Panics if no rule is found.
-func (m TestingModule) Output(file string) TestingBuildParams {
- return buildParamsFromOutput(m.module, file)
-}
-
-// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
-func (m TestingModule) AllOutputs() []string {
- return allOutputs(m.module)
+// VariablesForTestsRelativeToTop returns a copy of the Module.VariablesForTests() with every value
+// having any temporary build dir usages replaced with paths relative to a notional top.
+func (m TestingModule) VariablesForTestsRelativeToTop() map[string]string {
+ return normalizeStringMapRelativeToTop(m.config, m.module.VariablesForTests())
}
// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
// ctx.Build parameters for verification in tests.
type TestingSingleton struct {
+ baseTestingComponent
singleton Singleton
- provider testBuildProvider
}
// Singleton returns the Singleton wrapped by the TestingSingleton.
@@ -672,48 +794,6 @@
return s.singleton
}
-// MaybeRule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Returns an empty
-// BuildParams if no rule is found.
-func (s TestingSingleton) MaybeRule(rule string) TestingBuildParams {
- r, _ := maybeBuildParamsFromRule(s.provider, rule)
- return r
-}
-
-// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
-func (s TestingSingleton) Rule(rule string) TestingBuildParams {
- return buildParamsFromRule(s.provider, rule)
-}
-
-// MaybeDescription finds a call to ctx.Build with BuildParams.Description set to a the given string. Returns an empty
-// BuildParams if no rule is found.
-func (s TestingSingleton) MaybeDescription(desc string) TestingBuildParams {
- return maybeBuildParamsFromDescription(s.provider, desc)
-}
-
-// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
-// found.
-func (s TestingSingleton) Description(desc string) TestingBuildParams {
- return buildParamsFromDescription(s.provider, desc)
-}
-
-// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
-// value matches the provided string. Returns an empty BuildParams if no rule is found.
-func (s TestingSingleton) MaybeOutput(file string) TestingBuildParams {
- p, _ := maybeBuildParamsFromOutput(s.provider, file)
- return p
-}
-
-// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
-// value matches the provided string. Panics if no rule is found.
-func (s TestingSingleton) Output(file string) TestingBuildParams {
- return buildParamsFromOutput(s.provider, file)
-}
-
-// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
-func (s TestingSingleton) AllOutputs() []string {
- return allOutputs(s.provider)
-}
-
func FailIfErrored(t *testing.T, errs []error) {
t.Helper()
if len(errs) > 0 {
diff --git a/android/variable.go b/android/variable.go
index a5e9ab4..776a5c7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -379,7 +379,15 @@
ShippingApiLevel *string `json:",omitempty"`
+ BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
+ BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
+
+ RequiresInsecureExecmemForSwiftshader bool `json:",omitempty"`
+
+ SelinuxIgnoreNeverallows bool `json:",omitempty"`
+
+ SepolicySplit bool `json:",omitempty"`
}
func boolPtr(v bool) *bool {
@@ -426,6 +434,9 @@
Malloc_zero_contents: boolPtr(true),
Malloc_pattern_fill_contents: boolPtr(false),
Safestack: boolPtr(false),
+
+ BootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}},
+ UpdatableBootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}},
}
if runtime.GOOS == "linux" {
diff --git a/android/variable_test.go b/android/variable_test.go
index 393fe01..928bca6 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -181,32 +181,30 @@
name: "baz",
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Eng = proptools.BoolPtr(true)
- ctx := NewTestContext(config)
- // A module type that has a srcs property but not a cflags property.
- ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
- Srcs []string
- }{}))
- // A module type that has a cflags property but not a srcs property.
- ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
- Cflags []string
- }{}))
- // A module type that does not have any properties that match product_variables.
- ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
- Foo []string
- }{}))
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", VariableMutator).Parallel()
- })
-
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ GroupFixturePreparers(
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.Eng = proptools.BoolPtr(true)
+ }),
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ // A module type that has a srcs property but not a cflags property.
+ ctx.RegisterModuleType("module1", testProductVariableModuleFactoryFactory(&struct {
+ Srcs []string
+ }{}))
+ // A module type that has a cflags property but not a srcs property.
+ ctx.RegisterModuleType("module2", testProductVariableModuleFactoryFactory(&struct {
+ Cflags []string
+ }{}))
+ // A module type that does not have any properties that match product_variables.
+ ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
+ Foo []string
+ }{}))
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("variable", VariableMutator).Parallel()
+ })
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
}
var testProductVariableDefaultsProperties = struct {
@@ -290,32 +288,23 @@
}
`
- config := TestConfig(buildDir, nil, bp, nil)
- config.TestProductVariables.Eng = boolPtr(true)
+ result := GroupFixturePreparers(
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.Eng = boolPtr(true)
+ }),
+ PrepareForTestWithDefaults,
+ PrepareForTestWithVariables,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+ ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- ctx := NewTestContext(config)
-
- ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
- ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
-
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", VariableMutator).Parallel()
- })
-
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
-
- foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
+ foo := result.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
- if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
- t.Errorf("expected foo %q, got %q", w, g)
- }
+ AssertDeepEquals(t, "foo", want, foo.properties.Foo)
}
func BenchmarkSliceToTypeArray(b *testing.B) {
diff --git a/android/visibility_test.go b/android/visibility_test.go
index fdf18ce..ffd7909 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1142,7 +1142,7 @@
func TestVisibility(t *testing.T) {
for _, test := range visibilityTests {
t.Run(test.name, func(t *testing.T) {
- result := emptyTestFixtureFactory.Extend(
+ result := GroupFixturePreparers(
// General preparers in alphabetical order as test infrastructure will enforce correct
// registration order.
PrepareForTestWithArchMutator,
diff --git a/apex/OWNERS b/apex/OWNERS
index fee739b..8e4ba5c 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1,4 +1 @@
per-file * = jiyong@google.com
-
-per-file allowed_deps.txt = set noparent
-per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,jham@google.com
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
deleted file mode 100644
index 154b9aa..0000000
--- a/apex/allowed_deps.txt
+++ /dev/null
@@ -1,652 +0,0 @@
-# A list of allowed dependencies for all updatable modules.
-#
-# The list tracks all direct and transitive dependencies that end up within any
-# of the updatable binaries; specifically excluding external dependencies
-# required to compile those binaries. This prevents potential regressions in
-# case a new dependency is not aware of the different functional and
-# non-functional requirements being part of an updatable module, for example
-# setting correct min_sdk_version.
-#
-# To update the list, run:
-# repo-root$ build/soong/scripts/update-apex-allowed-deps.sh
-#
-# See go/apex-allowed-deps-error for more details.
-# TODO(b/157465465): introduce automated quality signals and remove this list.
-
-adbd(minSdkVersion:(no version))
-android.hardware.cas.native@1.0(minSdkVersion:29)
-android.hardware.cas@1.0(minSdkVersion:29)
-android.hardware.common-ndk_platform(minSdkVersion:29)
-android.hardware.common-unstable-ndk_platform(minSdkVersion:29)
-android.hardware.common-V2-ndk_platform(minSdkVersion:29)
-android.hardware.graphics.allocator@2.0(minSdkVersion:29)
-android.hardware.graphics.allocator@3.0(minSdkVersion:29)
-android.hardware.graphics.allocator@4.0(minSdkVersion:29)
-android.hardware.graphics.bufferqueue@1.0(minSdkVersion:29)
-android.hardware.graphics.bufferqueue@2.0(minSdkVersion:29)
-android.hardware.graphics.common-ndk_platform(minSdkVersion:29)
-android.hardware.graphics.common-unstable-ndk_platform(minSdkVersion:29)
-android.hardware.graphics.common-V2-ndk_platform(minSdkVersion:29)
-android.hardware.graphics.common@1.0(minSdkVersion:29)
-android.hardware.graphics.common@1.1(minSdkVersion:29)
-android.hardware.graphics.common@1.2(minSdkVersion:29)
-android.hardware.graphics.mapper@2.0(minSdkVersion:29)
-android.hardware.graphics.mapper@2.1(minSdkVersion:29)
-android.hardware.graphics.mapper@3.0(minSdkVersion:29)
-android.hardware.graphics.mapper@4.0(minSdkVersion:29)
-android.hardware.media.bufferpool@2.0(minSdkVersion:29)
-android.hardware.media.c2@1.0(minSdkVersion:29)
-android.hardware.media.c2@1.1(minSdkVersion:29)
-android.hardware.media.omx@1.0(minSdkVersion:29)
-android.hardware.media@1.0(minSdkVersion:29)
-android.hardware.neuralnetworks-V1-ndk_platform(minSdkVersion:30)
-android.hardware.neuralnetworks@1.0(minSdkVersion:30)
-android.hardware.neuralnetworks@1.1(minSdkVersion:30)
-android.hardware.neuralnetworks@1.2(minSdkVersion:30)
-android.hardware.neuralnetworks@1.3(minSdkVersion:30)
-android.hardware.tetheroffload.config-V1.0-java(minSdkVersion:current)
-android.hardware.tetheroffload.control-V1.0-java(minSdkVersion:current)
-android.hidl.allocator@1.0(minSdkVersion:29)
-android.hidl.base-V1.0-java(minSdkVersion:current)
-android.hidl.memory.token@1.0(minSdkVersion:29)
-android.hidl.memory@1.0(minSdkVersion:29)
-android.hidl.safe_union@1.0(minSdkVersion:29)
-android.hidl.token@1.0(minSdkVersion:29)
-android.hidl.token@1.0-utils(minSdkVersion:29)
-android.net.ipsec.ike(minSdkVersion:30)
-android.net.ipsec.ike(minSdkVersion:current)
-android.net.ipsec.ike.xml(minSdkVersion:(no version))
-androidx-constraintlayout_constraintlayout(minSdkVersion:14)
-androidx-constraintlayout_constraintlayout-solver(minSdkVersion:24)
-androidx.activity_activity(minSdkVersion:14)
-androidx.activity_activity-ktx(minSdkVersion:14)
-androidx.annotation_annotation(minSdkVersion:24)
-androidx.annotation_annotation(minSdkVersion:current)
-androidx.appcompat_appcompat(minSdkVersion:14)
-androidx.appcompat_appcompat-resources(minSdkVersion:14)
-androidx.arch.core_core-common(minSdkVersion:24)
-androidx.arch.core_core-common(minSdkVersion:current)
-androidx.arch.core_core-runtime(minSdkVersion:14)
-androidx.asynclayoutinflater_asynclayoutinflater(minSdkVersion:14)
-androidx.autofill_autofill(minSdkVersion:14)
-androidx.cardview_cardview(minSdkVersion:14)
-androidx.collection_collection(minSdkVersion:24)
-androidx.collection_collection(minSdkVersion:current)
-androidx.collection_collection-ktx(minSdkVersion:24)
-androidx.coordinatorlayout_coordinatorlayout(minSdkVersion:14)
-androidx.core_core(minSdkVersion:14)
-androidx.core_core-ktx(minSdkVersion:14)
-androidx.cursoradapter_cursoradapter(minSdkVersion:14)
-androidx.customview_customview(minSdkVersion:14)
-androidx.documentfile_documentfile(minSdkVersion:14)
-androidx.drawerlayout_drawerlayout(minSdkVersion:14)
-androidx.dynamicanimation_dynamicanimation(minSdkVersion:14)
-androidx.fragment_fragment(minSdkVersion:14)
-androidx.fragment_fragment-ktx(minSdkVersion:14)
-androidx.interpolator_interpolator(minSdkVersion:14)
-androidx.leanback_leanback(minSdkVersion:17)
-androidx.leanback_leanback-preference(minSdkVersion:21)
-androidx.legacy_legacy-preference-v14(minSdkVersion:14)
-androidx.legacy_legacy-support-core-ui(minSdkVersion:14)
-androidx.legacy_legacy-support-core-utils(minSdkVersion:14)
-androidx.legacy_legacy-support-v13(minSdkVersion:14)
-androidx.legacy_legacy-support-v4(minSdkVersion:14)
-androidx.lifecycle_lifecycle-common(minSdkVersion:24)
-androidx.lifecycle_lifecycle-common(minSdkVersion:current)
-androidx.lifecycle_lifecycle-common-java8(minSdkVersion:24)
-androidx.lifecycle_lifecycle-extensions(minSdkVersion:14)
-androidx.lifecycle_lifecycle-livedata(minSdkVersion:14)
-androidx.lifecycle_lifecycle-livedata-core(minSdkVersion:14)
-androidx.lifecycle_lifecycle-livedata-core-ktx(minSdkVersion:14)
-androidx.lifecycle_lifecycle-process(minSdkVersion:14)
-androidx.lifecycle_lifecycle-runtime(minSdkVersion:14)
-androidx.lifecycle_lifecycle-runtime-ktx(minSdkVersion:14)
-androidx.lifecycle_lifecycle-service(minSdkVersion:14)
-androidx.lifecycle_lifecycle-viewmodel(minSdkVersion:14)
-androidx.lifecycle_lifecycle-viewmodel-ktx(minSdkVersion:14)
-androidx.lifecycle_lifecycle-viewmodel-savedstate(minSdkVersion:14)
-androidx.loader_loader(minSdkVersion:14)
-androidx.localbroadcastmanager_localbroadcastmanager(minSdkVersion:14)
-androidx.media_media(minSdkVersion:14)
-androidx.navigation_navigation-common(minSdkVersion:14)
-androidx.navigation_navigation-common-ktx(minSdkVersion:14)
-androidx.navigation_navigation-fragment(minSdkVersion:14)
-androidx.navigation_navigation-fragment-ktx(minSdkVersion:14)
-androidx.navigation_navigation-runtime(minSdkVersion:14)
-androidx.navigation_navigation-runtime-ktx(minSdkVersion:14)
-androidx.navigation_navigation-ui(minSdkVersion:14)
-androidx.navigation_navigation-ui-ktx(minSdkVersion:14)
-androidx.preference_preference(minSdkVersion:14)
-androidx.print_print(minSdkVersion:14)
-androidx.recyclerview_recyclerview(minSdkVersion:14)
-androidx.recyclerview_recyclerview-selection(minSdkVersion:14)
-androidx.savedstate_savedstate(minSdkVersion:14)
-androidx.slidingpanelayout_slidingpanelayout(minSdkVersion:14)
-androidx.swiperefreshlayout_swiperefreshlayout(minSdkVersion:14)
-androidx.transition_transition(minSdkVersion:14)
-androidx.vectordrawable_vectordrawable(minSdkVersion:14)
-androidx.vectordrawable_vectordrawable-animated(minSdkVersion:14)
-androidx.versionedparcelable_versionedparcelable(minSdkVersion:14)
-androidx.viewpager_viewpager(minSdkVersion:14)
-apache-commons-compress(minSdkVersion:current)
-art.module.public.api.stubs(minSdkVersion:(no version))
-bcm_object(minSdkVersion:29)
-bionic_libc_platform_headers(minSdkVersion:29)
-boringssl_self_test(minSdkVersion:29)
-bouncycastle_ike_digests(minSdkVersion:current)
-bpf_syscall_wrappers(minSdkVersion:30)
-brotli-java(minSdkVersion:current)
-captiveportal-lib(minSdkVersion:29)
-car-ui-lib(minSdkVersion:28)
-car-ui-lib-overlayable(minSdkVersion:28)
-CellBroadcastApp(minSdkVersion:29)
-CellBroadcastServiceModule(minSdkVersion:29)
-codecs_g711dec(minSdkVersion:29)
-com.google.android.material_material(minSdkVersion:14)
-conscrypt(minSdkVersion:29)
-conscrypt.module.platform.api.stubs(minSdkVersion:(no version))
-conscrypt.module.public.api.stubs(minSdkVersion:(no version))
-core-lambda-stubs(minSdkVersion:(no version))
-core.current.stubs(minSdkVersion:(no version))
-crtbegin_dynamic(minSdkVersion:16)
-crtbegin_dynamic(minSdkVersion:apex_inherit)
-crtbegin_dynamic1(minSdkVersion:16)
-crtbegin_dynamic1(minSdkVersion:apex_inherit)
-crtbegin_so(minSdkVersion:16)
-crtbegin_so(minSdkVersion:apex_inherit)
-crtbegin_so1(minSdkVersion:16)
-crtbegin_so1(minSdkVersion:apex_inherit)
-crtbrand(minSdkVersion:16)
-crtbrand(minSdkVersion:apex_inherit)
-crtend_android(minSdkVersion:16)
-crtend_android(minSdkVersion:apex_inherit)
-crtend_so(minSdkVersion:16)
-crtend_so(minSdkVersion:apex_inherit)
-datastallprotosnano(minSdkVersion:29)
-derive_classpath(minSdkVersion:30)
-derive_sdk(minSdkVersion:30)
-derive_sdk(minSdkVersion:current)
-derive_sdk_prefer32(minSdkVersion:30)
-derive_sdk_prefer32(minSdkVersion:current)
-dnsresolver_aidl_interface-lateststable-ndk_platform(minSdkVersion:29)
-dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29)
-dnsresolver_aidl_interface-V7-ndk_platform(minSdkVersion:29)
-dnsresolver_aidl_interface-V8-ndk_platform(minSdkVersion:29)
-DocumentsUI-res-lib(minSdkVersion:29)
-exoplayer2-extractor(minSdkVersion:16)
-exoplayer2-extractor-annotation-stubs(minSdkVersion:16)
-ExtServices(minSdkVersion:current)
-ExtServices-core(minSdkVersion:current)
-flatbuffer_headers(minSdkVersion:(no version))
-fmtlib(minSdkVersion:29)
-fmtlib_ndk(minSdkVersion:29)
-framework-mediaprovider(minSdkVersion:30)
-framework-permission(minSdkVersion:30)
-framework-permission(minSdkVersion:current)
-framework-permission-s(minSdkVersion:30)
-framework-permission-s-shared(minSdkVersion:30)
-framework-sdkextensions(minSdkVersion:30)
-framework-sdkextensions(minSdkVersion:current)
-framework-statsd(minSdkVersion:30)
-framework-statsd(minSdkVersion:current)
-framework-tethering(minSdkVersion:30)
-framework-tethering(minSdkVersion:current)
-gemmlowp_headers(minSdkVersion:(no version))
-GoogleCellBroadcastApp(minSdkVersion:29)
-GoogleCellBroadcastServiceModule(minSdkVersion:29)
-GoogleExtServices(minSdkVersion:current)
-GooglePermissionController(minSdkVersion:30)
-guava(minSdkVersion:current)
-gwp_asan_headers(minSdkVersion:(no version))
-i18n.module.public.api.stubs(minSdkVersion:(no version))
-iconloader(minSdkVersion:21)
-ike-internals(minSdkVersion:current)
-InProcessTethering(minSdkVersion:30)
-InProcessTethering(minSdkVersion:current)
-ipmemorystore-aidl-interfaces-java(minSdkVersion:29)
-ipmemorystore-aidl-interfaces-unstable-java(minSdkVersion:29)
-ipmemorystore-aidl-interfaces-V10-java(minSdkVersion:29)
-ipmemorystore-aidl-interfaces-V11-java(minSdkVersion:29)
-jni_headers(minSdkVersion:29)
-jsr305(minSdkVersion:14)
-kotlinx-coroutines-android(minSdkVersion:current)
-kotlinx-coroutines-core(minSdkVersion:current)
-legacy.art.module.platform.api.stubs(minSdkVersion:(no version))
-legacy.core.platform.api.stubs(minSdkVersion:(no version))
-legacy.i18n.module.platform.api.stubs(minSdkVersion:(no version))
-libaacextractor(minSdkVersion:29)
-libadb_crypto(minSdkVersion:(no version))
-libadb_pairing_auth(minSdkVersion:(no version))
-libadb_pairing_connection(minSdkVersion:(no version))
-libadb_pairing_server(minSdkVersion:(no version))
-libadb_protos(minSdkVersion:(no version))
-libadb_sysdeps(minSdkVersion:apex_inherit)
-libadb_tls_connection(minSdkVersion:(no version))
-libadbconnection_client(minSdkVersion:(no version))
-libadbconnection_server(minSdkVersion:(no version))
-libadbd(minSdkVersion:(no version))
-libadbd_core(minSdkVersion:(no version))
-libadbd_services(minSdkVersion:(no version))
-liballoc.rust_sysroot(minSdkVersion:29)
-libamrextractor(minSdkVersion:29)
-libapp_processes_protos_lite(minSdkVersion:(no version))
-libarect(minSdkVersion:29)
-libasyncio(minSdkVersion:(no version))
-libatomic(minSdkVersion:(no version))
-libaudio_system_headers(minSdkVersion:29)
-libaudioclient_headers(minSdkVersion:29)
-libaudiofoundation_headers(minSdkVersion:29)
-libaudioutils(minSdkVersion:29)
-libaudioutils_fixedfft(minSdkVersion:29)
-libavcdec(minSdkVersion:29)
-libavcenc(minSdkVersion:29)
-libavservices_minijail(minSdkVersion:29)
-libbacktrace_headers(minSdkVersion:apex_inherit)
-libbacktrace_rs.rust_sysroot(minSdkVersion:29)
-libbacktrace_sys.rust_sysroot(minSdkVersion:29)
-libbase(minSdkVersion:29)
-libbase_headers(minSdkVersion:29)
-libbase_ndk(minSdkVersion:29)
-libbinder_headers(minSdkVersion:29)
-libbinder_headers_platform_shared(minSdkVersion:29)
-libbinderthreadstateutils(minSdkVersion:29)
-libbluetooth-types-header(minSdkVersion:29)
-libbrotli(minSdkVersion:(no version))
-libbuildversion(minSdkVersion:(no version))
-libc(minSdkVersion:(no version))
-libc++(minSdkVersion:apex_inherit)
-libc++_static(minSdkVersion:apex_inherit)
-libc++abi(minSdkVersion:apex_inherit)
-libc++demangle(minSdkVersion:apex_inherit)
-libc_headers(minSdkVersion:apex_inherit)
-libc_headers_arch(minSdkVersion:apex_inherit)
-libcap(minSdkVersion:29)
-libcfg_if(minSdkVersion:29)
-libcfg_if.rust_sysroot(minSdkVersion:29)
-libclang_rt.hwasan-aarch64-android.llndk(minSdkVersion:(no version))
-libcodec2(minSdkVersion:29)
-libcodec2_headers(minSdkVersion:29)
-libcodec2_hidl@1.0(minSdkVersion:29)
-libcodec2_hidl@1.1(minSdkVersion:29)
-libcodec2_internal(minSdkVersion:29)
-libcodec2_soft_aacdec(minSdkVersion:29)
-libcodec2_soft_aacenc(minSdkVersion:29)
-libcodec2_soft_amrnbdec(minSdkVersion:29)
-libcodec2_soft_amrnbenc(minSdkVersion:29)
-libcodec2_soft_amrwbdec(minSdkVersion:29)
-libcodec2_soft_amrwbenc(minSdkVersion:29)
-libcodec2_soft_av1dec_gav1(minSdkVersion:29)
-libcodec2_soft_avcdec(minSdkVersion:29)
-libcodec2_soft_avcenc(minSdkVersion:29)
-libcodec2_soft_common(minSdkVersion:29)
-libcodec2_soft_flacdec(minSdkVersion:29)
-libcodec2_soft_flacenc(minSdkVersion:29)
-libcodec2_soft_g711alawdec(minSdkVersion:29)
-libcodec2_soft_g711mlawdec(minSdkVersion:29)
-libcodec2_soft_gsmdec(minSdkVersion:29)
-libcodec2_soft_h263dec(minSdkVersion:29)
-libcodec2_soft_h263enc(minSdkVersion:29)
-libcodec2_soft_hevcdec(minSdkVersion:29)
-libcodec2_soft_hevcenc(minSdkVersion:29)
-libcodec2_soft_mp3dec(minSdkVersion:29)
-libcodec2_soft_mpeg2dec(minSdkVersion:29)
-libcodec2_soft_mpeg4dec(minSdkVersion:29)
-libcodec2_soft_mpeg4enc(minSdkVersion:29)
-libcodec2_soft_opusdec(minSdkVersion:29)
-libcodec2_soft_opusenc(minSdkVersion:29)
-libcodec2_soft_rawdec(minSdkVersion:29)
-libcodec2_soft_vorbisdec(minSdkVersion:29)
-libcodec2_soft_vp8dec(minSdkVersion:29)
-libcodec2_soft_vp8enc(minSdkVersion:29)
-libcodec2_soft_vp9dec(minSdkVersion:29)
-libcodec2_soft_vp9enc(minSdkVersion:29)
-libcodec2_vndk(minSdkVersion:29)
-libcompiler_builtins.rust_sysroot(minSdkVersion:29)
-libcore.rust_sysroot(minSdkVersion:29)
-libcrypto(minSdkVersion:29)
-libcrypto_static(minSdkVersion:(no version))
-libcrypto_utils(minSdkVersion:(no version))
-libcutils(minSdkVersion:29)
-libcutils_headers(minSdkVersion:29)
-libcutils_sockets(minSdkVersion:29)
-libderive_classpath(minSdkVersion:30)
-libderive_sdk(minSdkVersion:30)
-libdiagnose_usb(minSdkVersion:(no version))
-libdl(minSdkVersion:(no version))
-libdmabufheap(minSdkVersion:29)
-libeigen(minSdkVersion:(no version))
-libfifo(minSdkVersion:29)
-libFLAC(minSdkVersion:29)
-libFLAC-config(minSdkVersion:29)
-libFLAC-headers(minSdkVersion:29)
-libflacextractor(minSdkVersion:29)
-libfmq(minSdkVersion:29)
-libfmq-base(minSdkVersion:29)
-libFraunhoferAAC(minSdkVersion:29)
-libfuse(minSdkVersion:30)
-libfuse_jni(minSdkVersion:30)
-libgav1(minSdkVersion:29)
-libgcc(minSdkVersion:(no version))
-libgcc_stripped(minSdkVersion:(no version))
-libgetopts(minSdkVersion:29)
-libgralloctypes(minSdkVersion:29)
-libgrallocusage(minSdkVersion:29)
-libgsm(minSdkVersion:apex_inherit)
-libgtest_prod(minSdkVersion:apex_inherit)
-libgui_bufferqueue_static(minSdkVersion:29)
-libgui_headers(minSdkVersion:29)
-libhardware(minSdkVersion:29)
-libhardware_headers(minSdkVersion:29)
-libhashbrown.rust_sysroot(minSdkVersion:29)
-libhevcdec(minSdkVersion:29)
-libhevcenc(minSdkVersion:29)
-libhidlbase(minSdkVersion:29)
-libhidlmemory(minSdkVersion:29)
-libhwbinder-impl-internal(minSdkVersion:29)
-libhwbinder_headers(minSdkVersion:29)
-libion(minSdkVersion:29)
-libjavacrypto(minSdkVersion:29)
-libjsoncpp(minSdkVersion:29)
-liblazy_static(minSdkVersion:29)
-liblibc(minSdkVersion:29)
-liblibc.rust_sysroot(minSdkVersion:29)
-libLibGuiProperties(minSdkVersion:29)
-liblibm(minSdkVersion:29)
-liblog(minSdkVersion:(no version))
-liblog_headers(minSdkVersion:29)
-liblog_rust(minSdkVersion:29)
-liblua(minSdkVersion:(no version))
-liblz4(minSdkVersion:(no version))
-libm(minSdkVersion:(no version))
-libmath(minSdkVersion:29)
-libmdnssd(minSdkVersion:(no version))
-libmedia_codecserviceregistrant(minSdkVersion:29)
-libmedia_datasource_headers(minSdkVersion:29)
-libmedia_headers(minSdkVersion:29)
-libmedia_helper_headers(minSdkVersion:29)
-libmedia_midiiowrapper(minSdkVersion:29)
-libmediaparser-jni(minSdkVersion:29)
-libmidiextractor(minSdkVersion:29)
-libminijail(minSdkVersion:29)
-libminijail_gen_constants(minSdkVersion:(no version))
-libminijail_gen_constants_obj(minSdkVersion:29)
-libminijail_gen_syscall(minSdkVersion:(no version))
-libminijail_gen_syscall_obj(minSdkVersion:29)
-libminijail_generated(minSdkVersion:29)
-libmkvextractor(minSdkVersion:29)
-libmodules-utils-build(minSdkVersion:29)
-libmp3extractor(minSdkVersion:29)
-libmp4extractor(minSdkVersion:29)
-libmpeg2dec(minSdkVersion:29)
-libmpeg2extractor(minSdkVersion:29)
-libnativebase_headers(minSdkVersion:29)
-libnativehelper_compat_libc++(minSdkVersion:(no version))
-libnativehelper_header_only(minSdkVersion:29)
-libnativewindow_headers(minSdkVersion:29)
-libnetd_resolv(minSdkVersion:29)
-libnetdbinder_utils_headers(minSdkVersion:29)
-libnetdutils(minSdkVersion:29)
-libnetjniutils(minSdkVersion:29)
-libnetworkstackutilsjni(minSdkVersion:29)
-libneuralnetworks(minSdkVersion:(no version))
-libneuralnetworks_common(minSdkVersion:(no version))
-libneuralnetworks_headers(minSdkVersion:(no version))
-liboggextractor(minSdkVersion:29)
-libonce_cell(minSdkVersion:29)
-libopus(minSdkVersion:29)
-libpanic_unwind.rust_sysroot(minSdkVersion:29)
-libprocessgroup(minSdkVersion:29)
-libprocessgroup_headers(minSdkVersion:29)
-libprocpartition(minSdkVersion:(no version))
-libprofiler_builtins.rust_sysroot(minSdkVersion:29)
-libprotobuf-cpp-lite(minSdkVersion:29)
-libprotobuf-java-lite(minSdkVersion:current)
-libprotobuf-java-nano(minSdkVersion:9)
-libprotoutil(minSdkVersion:(no version))
-libqemu_pipe(minSdkVersion:(no version))
-libquiche_ffi(minSdkVersion:29)
-libring(minSdkVersion:29)
-libring-core(minSdkVersion:29)
-librustc_demangle.rust_sysroot(minSdkVersion:29)
-libruy_static(minSdkVersion:30)
-libsdk_proto(minSdkVersion:30)
-libsfplugin_ccodec_utils(minSdkVersion:29)
-libsonivoxwithoutjet(minSdkVersion:29)
-libspeexresampler(minSdkVersion:29)
-libspin(minSdkVersion:29)
-libssl(minSdkVersion:29)
-libstagefright_amrnb_common(minSdkVersion:29)
-libstagefright_amrnbdec(minSdkVersion:29)
-libstagefright_amrnbenc(minSdkVersion:29)
-libstagefright_amrwbdec(minSdkVersion:29)
-libstagefright_amrwbenc(minSdkVersion:29)
-libstagefright_bufferpool@2.0.1(minSdkVersion:29)
-libstagefright_bufferqueue_helper(minSdkVersion:29)
-libstagefright_enc_common(minSdkVersion:29)
-libstagefright_esds(minSdkVersion:29)
-libstagefright_flacdec(minSdkVersion:29)
-libstagefright_foundation(minSdkVersion:29)
-libstagefright_foundation_headers(minSdkVersion:29)
-libstagefright_foundation_without_imemory(minSdkVersion:29)
-libstagefright_headers(minSdkVersion:29)
-libstagefright_id3(minSdkVersion:29)
-libstagefright_m4vh263dec(minSdkVersion:29)
-libstagefright_m4vh263enc(minSdkVersion:29)
-libstagefright_metadatautils(minSdkVersion:29)
-libstagefright_mp3dec(minSdkVersion:29)
-libstagefright_mp3dec_headers(minSdkVersion:29)
-libstagefright_mpeg2extractor(minSdkVersion:29)
-libstagefright_mpeg2support_nocrypto(minSdkVersion:29)
-libstats_jni(minSdkVersion:(no version))
-libstats_jni(minSdkVersion:30)
-libstatslog_resolv(minSdkVersion:29)
-libstatslog_statsd(minSdkVersion:(no version))
-libstatslog_statsd(minSdkVersion:30)
-libstatspull(minSdkVersion:(no version))
-libstatspull(minSdkVersion:30)
-libstatspush_compat(minSdkVersion:29)
-libstatssocket(minSdkVersion:(no version))
-libstatssocket(minSdkVersion:30)
-libstatssocket_headers(minSdkVersion:29)
-libstd(minSdkVersion:29)
-libsystem_headers(minSdkVersion:apex_inherit)
-libsysutils(minSdkVersion:apex_inherit)
-libterm(minSdkVersion:29)
-libtest(minSdkVersion:29)
-libtetherutilsjni(minSdkVersion:30)
-libtetherutilsjni(minSdkVersion:current)
-libtextclassifier(minSdkVersion:(no version))
-libtextclassifier-java(minSdkVersion:current)
-libtextclassifier_hash_headers(minSdkVersion:(no version))
-libtextclassifier_hash_static(minSdkVersion:(no version))
-libtflite_kernel_utils(minSdkVersion:(no version))
-libtflite_static(minSdkVersion:(no version))
-libui(minSdkVersion:29)
-libui_headers(minSdkVersion:29)
-libunicode_width.rust_sysroot(minSdkVersion:29)
-libuntrusted(minSdkVersion:29)
-libunwind.rust_sysroot(minSdkVersion:29)
-libunwind_llvm(minSdkVersion:apex_inherit)
-libutf(minSdkVersion:(no version))
-libutils(minSdkVersion:apex_inherit)
-libutils_headers(minSdkVersion:apex_inherit)
-libvorbisidec(minSdkVersion:29)
-libvpx(minSdkVersion:29)
-libwatchdog(minSdkVersion:29)
-libwavextractor(minSdkVersion:29)
-libwebm(minSdkVersion:29)
-libyuv(minSdkVersion:29)
-libyuv_static(minSdkVersion:29)
-libzstd(minSdkVersion:(no version))
-media_ndk_headers(minSdkVersion:29)
-media_plugin_headers(minSdkVersion:29)
-MediaProvider(minSdkVersion:30)
-mediaswcodec(minSdkVersion:29)
-metrics-constants-protos(minSdkVersion:29)
-modules-annotation-minsdk(minSdkVersion:29)
-modules-utils-build(minSdkVersion:29)
-modules-utils-build_system(minSdkVersion:29)
-modules-utils-os(minSdkVersion:30)
-ndk_crtbegin_so.19(minSdkVersion:(no version))
-ndk_crtbegin_so.21(minSdkVersion:(no version))
-ndk_crtbegin_so.27(minSdkVersion:(no version))
-ndk_crtend_so.19(minSdkVersion:(no version))
-ndk_crtend_so.21(minSdkVersion:(no version))
-ndk_crtend_so.27(minSdkVersion:(no version))
-ndk_libc++_static(minSdkVersion:(no version))
-ndk_libc++_static(minSdkVersion:16)
-ndk_libc++abi(minSdkVersion:(no version))
-ndk_libc++abi(minSdkVersion:16)
-ndk_libunwind(minSdkVersion:16)
-net-utils-device-common(minSdkVersion:29)
-net-utils-framework-common(minSdkVersion:current)
-netd-client(minSdkVersion:29)
-netd_aidl_interface-java(minSdkVersion:29)
-netd_aidl_interface-lateststable-java(minSdkVersion:29)
-netd_aidl_interface-unstable-java(minSdkVersion:29)
-netd_aidl_interface-V5-java(minSdkVersion:29)
-netd_aidl_interface-V6-java(minSdkVersion:29)
-netd_event_listener_interface-java(minSdkVersion:29)
-netd_event_listener_interface-lateststable-ndk_platform(minSdkVersion:29)
-netd_event_listener_interface-ndk_platform(minSdkVersion:29)
-netd_event_listener_interface-unstable-ndk_platform(minSdkVersion:29)
-netd_event_listener_interface-V1-ndk_platform(minSdkVersion:29)
-netd_event_listener_interface-V2-ndk_platform(minSdkVersion:29)
-netlink-client(minSdkVersion:29)
-networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
-networkstack-aidl-interfaces-V10-java(minSdkVersion:29)
-networkstack-client(minSdkVersion:29)
-NetworkStackApi29Shims(minSdkVersion:29)
-NetworkStackApi30Shims(minSdkVersion:29)
-NetworkStackApiStableDependencies(minSdkVersion:29)
-NetworkStackApiStableLib(minSdkVersion:29)
-NetworkStackApiStableShims(minSdkVersion:29)
-networkstackprotos(minSdkVersion:29)
-NetworkStackShimsCommon(minSdkVersion:29)
-neuralnetworks_types(minSdkVersion:30)
-neuralnetworks_utils_hal_1_0(minSdkVersion:30)
-neuralnetworks_utils_hal_1_1(minSdkVersion:30)
-neuralnetworks_utils_hal_1_2(minSdkVersion:30)
-neuralnetworks_utils_hal_1_3(minSdkVersion:30)
-neuralnetworks_utils_hal_aidl(minSdkVersion:30)
-neuralnetworks_utils_hal_common(minSdkVersion:30)
-neuralnetworks_utils_hal_service(minSdkVersion:30)
-no_op(minSdkVersion:current)
-note_memtag_heap_async(minSdkVersion:16)
-note_memtag_heap_sync(minSdkVersion:16)
-PermissionController(minSdkVersion:30)
-permissioncontroller-statsd(minSdkVersion:current)
-philox_random(minSdkVersion:(no version))
-philox_random_headers(minSdkVersion:(no version))
-prebuilt_androidx-constraintlayout_constraintlayout-nodeps(minSdkVersion:(no version))
-prebuilt_androidx-constraintlayout_constraintlayout-solver-nodeps(minSdkVersion:current)
-prebuilt_androidx.activity_activity-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.activity_activity-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.annotation_annotation-nodeps(minSdkVersion:current)
-prebuilt_androidx.appcompat_appcompat-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.appcompat_appcompat-resources-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.arch.core_core-common-nodeps(minSdkVersion:current)
-prebuilt_androidx.arch.core_core-runtime-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.asynclayoutinflater_asynclayoutinflater-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.autofill_autofill-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.cardview_cardview-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.collection_collection-ktx-nodeps(minSdkVersion:current)
-prebuilt_androidx.collection_collection-nodeps(minSdkVersion:current)
-prebuilt_androidx.coordinatorlayout_coordinatorlayout-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.core_core-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.core_core-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.cursoradapter_cursoradapter-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.customview_customview-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.documentfile_documentfile-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.drawerlayout_drawerlayout-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.dynamicanimation_dynamicanimation-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.fragment_fragment-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.fragment_fragment-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.interpolator_interpolator-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.leanback_leanback-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.leanback_leanback-preference-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.legacy_legacy-support-core-ui-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.legacy_legacy-support-core-utils-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.legacy_legacy-support-v13-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-common-java8-nodeps(minSdkVersion:current)
-prebuilt_androidx.lifecycle_lifecycle-common-nodeps(minSdkVersion:current)
-prebuilt_androidx.lifecycle_lifecycle-extensions-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-livedata-core-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-livedata-core-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-livedata-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-process-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-runtime-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-runtime-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-service-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-viewmodel-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-viewmodel-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.lifecycle_lifecycle-viewmodel-savedstate-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.loader_loader-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.localbroadcastmanager_localbroadcastmanager-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.media_media-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-common-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-common-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-fragment-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-fragment-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-runtime-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-runtime-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-ui-ktx-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.navigation_navigation-ui-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.preference_preference-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.print_print-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.recyclerview_recyclerview-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.recyclerview_recyclerview-selection-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.savedstate_savedstate-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.slidingpanelayout_slidingpanelayout-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.swiperefreshlayout_swiperefreshlayout-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.transition_transition-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.vectordrawable_vectordrawable-animated-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.vectordrawable_vectordrawable-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.versionedparcelable_versionedparcelable-nodeps(minSdkVersion:(no version))
-prebuilt_androidx.viewpager_viewpager-nodeps(minSdkVersion:(no version))
-prebuilt_com.google.android.material_material-nodeps(minSdkVersion:(no version))
-prebuilt_error_prone_annotations(minSdkVersion:(no version))
-prebuilt_kotlin-stdlib(minSdkVersion:current)
-prebuilt_kotlinx-coroutines-android-nodeps(minSdkVersion:(no version))
-prebuilt_kotlinx-coroutines-core-nodeps(minSdkVersion:(no version))
-prebuilt_libclang_rt.builtins-aarch64-android(minSdkVersion:(no version))
-prebuilt_libclang_rt.builtins-arm-android(minSdkVersion:(no version))
-prebuilt_libclang_rt.builtins-i686-android(minSdkVersion:(no version))
-prebuilt_libclang_rt.builtins-x86_64-android(minSdkVersion:(no version))
-prebuilt_libunwind(minSdkVersion:(no version))
-prebuilt_test_framework-sdkextensions(minSdkVersion:(no version))
-server_configurable_flags(minSdkVersion:29)
-service-media-s(minSdkVersion:29)
-service-permission(minSdkVersion:30)
-service-permission(minSdkVersion:current)
-service-permission-shared(minSdkVersion:30)
-service-statsd(minSdkVersion:30)
-service-statsd(minSdkVersion:current)
-SettingsLibActionBarShadow(minSdkVersion:21)
-SettingsLibAppPreference(minSdkVersion:21)
-SettingsLibBarChartPreference(minSdkVersion:21)
-SettingsLibHelpUtils(minSdkVersion:21)
-SettingsLibLayoutPreference(minSdkVersion:21)
-SettingsLibProgressBar(minSdkVersion:21)
-SettingsLibRestrictedLockUtils(minSdkVersion:21)
-SettingsLibSearchWidget(minSdkVersion:21)
-SettingsLibSettingsTheme(minSdkVersion:21)
-SettingsLibUtils(minSdkVersion:21)
-stats_proto(minSdkVersion:29)
-statsd(minSdkVersion:(no version))
-statsd(minSdkVersion:30)
-statsd-aidl-ndk_platform(minSdkVersion:(no version))
-statsd-aidl-ndk_platform(minSdkVersion:30)
-statsprotos(minSdkVersion:29)
-tensorflow_headers(minSdkVersion:(no version))
-Tethering(minSdkVersion:30)
-Tethering(minSdkVersion:current)
-TetheringApiCurrentLib(minSdkVersion:30)
-TetheringApiCurrentLib(minSdkVersion:current)
-TetheringGoogle(minSdkVersion:30)
-TetheringGoogle(minSdkVersion:current)
-textclassifier-statsd(minSdkVersion:current)
-TextClassifierNotificationLibNoManifest(minSdkVersion:29)
-TextClassifierServiceLibNoManifest(minSdkVersion:28)
-updatable-media(minSdkVersion:29)
-xz-java(minSdkVersion:current)
diff --git a/apex/apex.go b/apex/apex.go
index 3db20f4..a67fe1f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -549,24 +549,35 @@
// Determines if the dependent will be part of the APEX payload. Can be false for the
// dependencies to the signing key module, etc.
payload bool
+
+ // True if the dependent can only be a source module, false if a prebuilt module is a suitable
+ // replacement. This is needed because some prebuilt modules do not provide all the information
+ // needed by the apex.
+ sourceOnly bool
}
+func (d dependencyTag) ReplaceSourceWithPrebuilt() bool {
+ return !d.sourceOnly
+}
+
+var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{}
+
var (
- androidAppTag = dependencyTag{name: "androidApp", payload: true}
- bpfTag = dependencyTag{name: "bpf", payload: true}
- certificateTag = dependencyTag{name: "certificate"}
- executableTag = dependencyTag{name: "executable", payload: true}
- fsTag = dependencyTag{name: "filesystem", payload: true}
- bootImageTag = dependencyTag{name: "bootImage", payload: true}
- compatConfigsTag = dependencyTag{name: "compatConfig", payload: true}
- javaLibTag = dependencyTag{name: "javaLib", payload: true}
- jniLibTag = dependencyTag{name: "jniLib", payload: true}
- keyTag = dependencyTag{name: "key"}
- prebuiltTag = dependencyTag{name: "prebuilt", payload: true}
- rroTag = dependencyTag{name: "rro", payload: true}
- sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
- testForTag = dependencyTag{name: "test for"}
- testTag = dependencyTag{name: "test", payload: true}
+ androidAppTag = dependencyTag{name: "androidApp", payload: true}
+ bpfTag = dependencyTag{name: "bpf", payload: true}
+ certificateTag = dependencyTag{name: "certificate"}
+ executableTag = dependencyTag{name: "executable", payload: true}
+ fsTag = dependencyTag{name: "filesystem", payload: true}
+ bootImageTag = dependencyTag{name: "bootImage", payload: true}
+ compatConfigTag = dependencyTag{name: "compatConfig", payload: true, sourceOnly: true}
+ javaLibTag = dependencyTag{name: "javaLib", payload: true}
+ jniLibTag = dependencyTag{name: "jniLib", payload: true}
+ keyTag = dependencyTag{name: "key"}
+ prebuiltTag = dependencyTag{name: "prebuilt", payload: true}
+ rroTag = dependencyTag{name: "rro", payload: true}
+ sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
+ testForTag = dependencyTag{name: "test for"}
+ testTag = dependencyTag{name: "test", payload: true}
)
// TODO(jiyong): shorten this function signature
@@ -741,7 +752,7 @@
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
- ctx.AddFarVariationDependencies(commonVariation, compatConfigsTag, a.properties.Compat_configs...)
+ ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
if a.artApex {
// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
@@ -835,7 +846,15 @@
if !ok || !am.CanHaveApexVariants() {
return false
}
- if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) {
+ depTag := mctx.OtherModuleDependencyTag(child)
+
+ // Check to see if the tag always requires that the child module has an apex variant for every
+ // apex variant of the parent module. If it does not then it is still possible for something
+ // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required.
+ if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() {
+ return true
+ }
+ if !android.IsDepInSameApex(mctx, parent, child) {
return false
}
if excludeVndkLibs {
@@ -979,11 +998,7 @@
// If any of the dep is not available to platform, this module is also considered as being
// not available to platform even if it has "//apex_available:platform"
mctx.VisitDirectDeps(func(child android.Module) {
- depTag := mctx.OtherModuleDependencyTag(child)
- if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
- return
- }
- if !am.DepIsInSameApex(mctx, child) {
+ if !android.IsDepInSameApex(mctx, am, child) {
// if the dependency crosses apex boundary, don't consider it
return
}
@@ -1183,11 +1198,13 @@
}).([]string)
}
-// setUseVendorAllowListForTest overrides useVendorAllowList and must be called before the first
-// call to useVendorAllowList()
-func setUseVendorAllowListForTest(config android.Config, allowList []string) {
- config.Once(useVendorAllowListKey, func() interface{} {
- return allowList
+// setUseVendorAllowListForTest returns a FixturePreparer that overrides useVendorAllowList and
+// must be called before the first call to useVendorAllowList()
+func setUseVendorAllowListForTest(allowList []string) android.FixturePreparer {
+ return android.FixtureModifyConfig(func(config android.Config) {
+ config.Once(useVendorAllowListKey, func() interface{} {
+ return allowList
+ })
})
}
@@ -1743,7 +1760,7 @@
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
}
- case compatConfigsTag:
+ case compatConfigTag:
if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
} else {
@@ -1846,7 +1863,10 @@
// like to record requiredNativeLibs even when
// DepIsInSameAPex is false. We also shouldn't do
// this for host.
- if !am.DepIsInSameApex(ctx, am) {
+ //
+ // TODO(jiyong): explain why the same module is passed in twice.
+ // Switching the first am to parent breaks lots of tests.
+ if !android.IsDepInSameApex(ctx, am, am) {
return false
}
@@ -2169,6 +2189,8 @@
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
+ //
+ // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
@@ -2252,6 +2274,8 @@
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
+ //
+ // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
// As soon as the dependency graph crosses the APEX boundary, don't go
// further.
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index ee9fc81..0ed94af 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -58,8 +58,8 @@
echo "ERROR: go/apex-allowed-deps-error";
echo "******************************";
echo "Detected changes to allowed dependencies in updatable modules.";
- echo "To fix and update build/soong/apex/allowed_deps.txt, please run:";
- echo "$$ (croot && build/soong/scripts/update-apex-allowed-deps.sh)";
+ echo "To fix and update packages/modules/common/build/allowed_deps.txt, please run:";
+ echo "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)";
echo "Members of mainline-modularization@google.com will review the changes.";
echo -e "******************************\n";
exit 1;
@@ -81,25 +81,35 @@
}
})
- allowedDeps := android.ExistentPathForSource(ctx, "build/soong/apex/allowed_deps.txt").Path()
-
+ allowedDepsSource := android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")
newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt")
- ctx.Build(pctx, android.BuildParams{
- Rule: generateApexDepsInfoFilesRule,
- Inputs: append(updatableFlatLists, allowedDeps),
- Output: newAllowedDeps,
- })
-
s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check")
- ctx.Build(pctx, android.BuildParams{
- Rule: diffAllowedApexDepsInfoRule,
- Input: newAllowedDeps,
- Output: s.allowedApexDepsInfoCheckResult,
- Args: map[string]string{
- "allowed_deps": allowedDeps.String(),
- "new_allowed_deps": newAllowedDeps.String(),
- },
- })
+
+ if !allowedDepsSource.Valid() {
+ // Unbundled projects may not have packages/modules/common/ checked out; ignore those.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: s.allowedApexDepsInfoCheckResult,
+ })
+ } else {
+ allowedDeps := allowedDepsSource.Path()
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateApexDepsInfoFilesRule,
+ Inputs: append(updatableFlatLists, allowedDeps),
+ Output: newAllowedDeps,
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: diffAllowedApexDepsInfoRule,
+ Input: newAllowedDeps,
+ Output: s.allowedApexDepsInfoCheckResult,
+ Args: map[string]string{
+ "allowed_deps": allowedDeps.String(),
+ "new_allowed_deps": newAllowedDeps.String(),
+ },
+ })
+ }
ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 21cf5df..b159660 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -50,49 +50,33 @@
return
}
-func testApexError(t *testing.T, pattern, bp string, handlers ...testCustomizer) {
+func testApexError(t *testing.T, pattern, bp string, preparers ...android.FixturePreparer) {
t.Helper()
- ctx, config := testApexContext(t, bp, handlers...)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
- _, errs = ctx.PrepareBuildActions(config)
- if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, pattern, errs)
- return
- }
-
- t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
+ apexFixtureFactory.Extend(preparers...).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
+ RunTestWithBp(t, bp)
}
-func testApex(t *testing.T, bp string, handlers ...testCustomizer) *android.TestContext {
+func testApex(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext {
t.Helper()
- ctx, config := testApexContext(t, bp, handlers...)
- _, errs := ctx.ParseBlueprintsFiles(".")
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return ctx
-}
-
-type testCustomizer func(fs map[string][]byte, config android.Config)
-
-func withFiles(files map[string][]byte) testCustomizer {
- return func(fs map[string][]byte, config android.Config) {
- for k, v := range files {
- fs[k] = v
- }
+ factory := apexFixtureFactory.Extend(preparers...)
+ if bp != "" {
+ factory = factory.Extend(android.FixtureWithRootAndroidBp(bp))
}
+ result := factory.RunTest(t)
+ return result.TestContext
}
-func withTargets(targets map[android.OsType][]android.Target) testCustomizer {
- return func(fs map[string][]byte, config android.Config) {
+func withFiles(files android.MockFS) android.FixturePreparer {
+ return files.AddToFixture()
+}
+
+func withTargets(targets map[android.OsType][]android.Target) android.FixturePreparer {
+ return android.FixtureModifyConfig(func(config android.Config) {
for k, v := range targets {
config.Targets[k] = v
}
- }
+ })
}
// withNativeBridgeTargets sets configuration with targets including:
@@ -100,34 +84,38 @@
// - X86 (secondary)
// - Arm64 on X86_64 (native bridge)
// - Arm on X86 (native bridge)
-func withNativeBridgeEnabled(_ map[string][]byte, config android.Config) {
- config.Targets[android.Android] = []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
- NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
- NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
- NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
- NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
- }
+var withNativeBridgeEnabled = android.FixtureModifyConfig(
+ func(config android.Config) {
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
+ NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
+ NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
+ NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
+ }
+ },
+)
+
+func withManifestPackageNameOverrides(specs []string) android.FixturePreparer {
+ return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.ManifestPackageNameOverrides = specs
+ })
}
-func withManifestPackageNameOverrides(specs []string) testCustomizer {
- return func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.ManifestPackageNameOverrides = specs
- }
-}
+var withBinder32bit = android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Binder32bit = proptools.BoolPtr(true)
+ },
+)
-func withBinder32bit(_ map[string][]byte, config android.Config) {
- config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
-}
-
-func withUnbundledBuild(_ map[string][]byte, config android.Config) {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
-}
-
-var emptyFixtureFactory = android.NewFixtureFactory(&buildDir)
+var withUnbundledBuild = android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ },
+)
var apexFixtureFactory = android.NewFixtureFactory(
&buildDir,
@@ -217,143 +205,6 @@
}),
)
-func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
- bp = bp + `
- filegroup {
- name: "myapex-file_contexts",
- srcs: [
- "system/sepolicy/apex/myapex-file_contexts",
- ],
- }
- `
-
- bp = bp + cc.GatherRequiredDepsForTest(android.Android)
-
- bp = bp + rust.GatherRequiredDepsForTest()
-
- bp = bp + java.GatherRequiredDepsForTest()
-
- fs := map[string][]byte{
- "a.java": nil,
- "PrebuiltAppFoo.apk": nil,
- "PrebuiltAppFooPriv.apk": nil,
- "build/make/target/product/security": nil,
- "apex_manifest.json": nil,
- "AndroidManifest.xml": nil,
- "system/sepolicy/apex/myapex-file_contexts": nil,
- "system/sepolicy/apex/myapex.updatable-file_contexts": nil,
- "system/sepolicy/apex/myapex2-file_contexts": nil,
- "system/sepolicy/apex/otherapex-file_contexts": nil,
- "system/sepolicy/apex/com.android.vndk-file_contexts": nil,
- "system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
- "mylib.cpp": nil,
- "mytest.cpp": nil,
- "mytest1.cpp": nil,
- "mytest2.cpp": nil,
- "mytest3.cpp": nil,
- "myprebuilt": nil,
- "my_include": nil,
- "foo/bar/MyClass.java": nil,
- "prebuilt.jar": nil,
- "prebuilt.so": nil,
- "vendor/foo/devkeys/test.x509.pem": nil,
- "vendor/foo/devkeys/test.pk8": nil,
- "testkey.x509.pem": nil,
- "testkey.pk8": nil,
- "testkey.override.x509.pem": nil,
- "testkey.override.pk8": nil,
- "vendor/foo/devkeys/testkey.avbpubkey": nil,
- "vendor/foo/devkeys/testkey.pem": nil,
- "NOTICE": nil,
- "custom_notice": nil,
- "custom_notice_for_static_lib": nil,
- "testkey2.avbpubkey": nil,
- "testkey2.pem": nil,
- "myapex-arm64.apex": nil,
- "myapex-arm.apex": nil,
- "myapex.apks": nil,
- "frameworks/base/api/current.txt": nil,
- "framework/aidl/a.aidl": nil,
- "build/make/core/proguard.flags": nil,
- "build/make/core/proguard_basic_keeps.flags": nil,
- "dummy.txt": nil,
- "baz": nil,
- "bar/baz": nil,
- "testdata/baz": nil,
- "AppSet.apks": nil,
- "foo.rs": nil,
- "libfoo.jar": nil,
- "libbar.jar": nil,
- }
-
- cc.GatherRequiredFilesForTest(fs)
-
- for _, handler := range handlers {
- // The fs now needs to be populated before creating the config, call handlers twice
- // for now, once to get any fs changes, and later after the config was created to
- // set product variables or targets.
- tempConfig := android.TestArchConfig(buildDir, nil, bp, fs)
- handler(fs, tempConfig)
- }
-
- config := android.TestArchConfig(buildDir, nil, bp, fs)
- config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
- config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
- config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
- config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
- config.TestProductVariables.Platform_version_active_codenames = []string{"Q"}
- config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
-
- for _, handler := range handlers {
- // The fs now needs to be populated before creating the config, call handlers twice
- // for now, earlier to get any fs changes, and now after the config was created to
- // set product variables or targets.
- tempFS := map[string][]byte{}
- handler(tempFS, config)
- }
-
- ctx := android.NewTestArchContext(config)
-
- // from android package
- android.RegisterPackageBuildComponents(ctx)
- ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
-
- registerApexBuildComponents(ctx)
- registerApexKeyBuildComponents(ctx)
-
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(android.RegisterComponentsMutator)
-
- android.RegisterPrebuiltMutators(ctx)
-
- // Register these after the prebuilt mutators have been registered to match what
- // happens at runtime.
- ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
- ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
-
- // These must come after prebuilts and visibility rules to match runtime.
- ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
-
- // These must come after override rules to match the runtime.
- cc.RegisterRequiredBuildComponentsForTest(ctx)
- rust.RegisterRequiredBuildComponentsForTest(ctx)
- java.RegisterRequiredBuildComponentsForTest(ctx)
-
- ctx.RegisterModuleType("cc_test", cc.TestFactory)
- ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
- cc.RegisterVndkLibraryTxtTypes(ctx)
- prebuilt_etc.RegisterPrebuiltEtcBuildComponents(ctx)
- ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
- ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("bpf", bpf.BpfFactory)
-
- ctx.Register()
-
- return ctx, config
-}
-
func setUp() {
var err error
buildDir, err = ioutil.TempDir("", "soong_apex_test")
@@ -1139,11 +990,13 @@
srcs: ["mylib.cpp"],
shared_libs: ["libstub"],
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Z")
- config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
- config.TestProductVariables.Platform_version_active_codenames = []string{"Z"}
- })
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_codename = proptools.StringPtr("Z")
+ variables.Platform_sdk_final = proptools.BoolPtr(false)
+ variables.Platform_version_active_codenames = []string{"Z"}
+ }),
+ )
// Ensure that mylib from myapex is built against the latest stub (current)
mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
@@ -1333,7 +1186,7 @@
)
func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
- result := emptyFixtureFactory.Extend(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
cc_library {
name: "libc",
no_libcrt: true,
@@ -1379,7 +1232,7 @@
}
func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
- result := emptyFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
prepareForTestOfRuntimeApexWithHwasan,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.SanitizeDevice = []string{"hwaddress"}
@@ -1491,9 +1344,10 @@
name: "libbar.llndk",
symbol_file: "",
}
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{"myapex"})
- }, withUnbundledBuild)
+ `,
+ setUseVendorAllowListForTest([]string{"myapex"}),
+ withUnbundledBuild,
+ )
// Ensure that LLNDK dep is not included
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
@@ -1727,9 +1581,11 @@
versions: ["29", "R"],
},
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
- })
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"R"}
+ }),
+ )
expectLink := func(from, from_variant, to, to_variant string) {
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
@@ -1838,6 +1694,12 @@
expectNoLink("libz", "shared", "libz", "shared")
}
+var prepareForTestWithSantitizeHwaddress = android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.SanitizeDevice = []string{"hwaddress"}
+ },
+)
+
func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -1866,9 +1728,9 @@
versions: ["29", "30"],
},
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- })
+ `,
+ prepareForTestWithSantitizeHwaddress,
+ )
expectLink := func(from, from_variant, to, to_variant string) {
ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
libFlags := ld.Args["libFlags"]
@@ -2261,10 +2123,12 @@
}
func TestApexMinSdkVersion_WorksWithSdkCodename(t *testing.T) {
- withSAsActiveCodeNames := func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
- config.TestProductVariables.Platform_version_active_codenames = []string{"S"}
- }
+ withSAsActiveCodeNames := android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_codename = proptools.StringPtr("S")
+ variables.Platform_version_active_codenames = []string{"S"}
+ },
+ )
testApexError(t, `libbar.*: should support min_sdk_version\(S\)`, `
apex {
name: "myapex",
@@ -2291,10 +2155,10 @@
}
func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
- withSAsActiveCodeNames := func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
- config.TestProductVariables.Platform_version_active_codenames = []string{"S", "T"}
- }
+ withSAsActiveCodeNames := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_codename = proptools.StringPtr("S")
+ variables.Platform_version_active_codenames = []string{"S", "T"}
+ })
ctx := testApex(t, `
apex {
name: "myapex",
@@ -2484,9 +2348,9 @@
stl: "none",
apex_available: [ "myapex" ],
}
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{"myapex"})
- })
+ `,
+ setUseVendorAllowListForTest([]string{"myapex"}),
+ )
inputsList := []string{}
for _, i := range ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().BuildParamsForTests() {
@@ -2517,9 +2381,9 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{""})
- })
+ `,
+ setUseVendorAllowListForTest([]string{""}),
+ )
// no error with allow list
testApex(t, `
apex {
@@ -2533,9 +2397,9 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{"myapex"})
- })
+ `,
+ setUseVendorAllowListForTest([]string{"myapex"}),
+ )
}
func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
@@ -2650,7 +2514,7 @@
libs := names(ldRule.Args["libFlags"])
// VNDK libs(libvndk/libc++) as they are
ensureListContains(t, libs, buildDir+"/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
- ensureListContains(t, libs, buildDir+"/.intermediates/libc++/"+vendorVariant+"_shared/libc++.so")
+ ensureListContains(t, libs, buildDir+"/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"libc++/"+vendorVariant+"_shared/libc++.so")
// non-stable Vendor libs as APEX variants
ensureListContains(t, libs, buildDir+"/.intermediates/libvendor/"+vendorVariant+"_shared_apex10000/libvendor.so")
@@ -2665,6 +2529,41 @@
ensureListContains(t, requireNativeLibs, ":vndk")
}
+func TestProductVariant(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ product_specific: true,
+ binaries: ["foo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_binary {
+ name: "foo",
+ product_available: true,
+ apex_available: ["myapex"],
+ srcs: ["foo.cpp"],
+ }
+ `, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.ProductVndkVersion = proptools.StringPtr("current")
+ }),
+ )
+
+ cflags := strings.Fields(
+ ctx.ModuleForTests("foo", "android_product.VER_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
+ ensureListContains(t, cflags, "-D__ANDROID_VNDK__")
+ ensureListContains(t, cflags, "-D__ANDROID_APEX__")
+ ensureListContains(t, cflags, "-D__ANDROID_PRODUCT__")
+ ensureListNotContains(t, cflags, "-D__ANDROID_VENDOR__")
+}
+
func TestApex_withPrebuiltFirmware(t *testing.T) {
testCases := []struct {
name string
@@ -2723,9 +2622,9 @@
vendor_available: true,
apex_available: ["myapex"],
}
- `, func(fs map[string][]byte, config android.Config) {
- setUseVendorAllowListForTest(config, []string{"myapex"})
- })
+ `,
+ setUseVendorAllowListForTest([]string{"myapex"}),
+ )
apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
@@ -5019,9 +4918,11 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.InstallExtraFlattenedApexes = proptools.BoolPtr(true)
- })
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.InstallExtraFlattenedApexes = proptools.BoolPtr(true)
+ }),
+ )
ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
ensureListContains(t, ab.requiredDeps, "myapex.flattened")
mk := android.AndroidMkDataForTest(t, ctx, ab)
@@ -5712,7 +5613,7 @@
}
}
-var filesForSdkLibrary = map[string][]byte{
+var filesForSdkLibrary = android.MockFS{
"api/current.txt": nil,
"api/removed.txt": nil,
"api/system-current.txt": nil,
@@ -6018,6 +5919,13 @@
system_modules: "none",
apex_available: [ "myapex" ],
}
+
+ // Make sure that a preferred prebuilt does not affect the apex contents.
+ prebuilt_platform_compat_config {
+ name: "myjar-platform-compat-config",
+ metadata: "compat-config/metadata.xml",
+ prefer: true,
+ }
`)
ctx := result.TestContext
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
@@ -6327,10 +6235,12 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `, func(fs map[string][]byte, config android.Config) {
- delete(config.Targets, android.Android)
- config.AndroidCommonTarget = android.Target{}
- })
+ `,
+ android.FixtureModifyConfig(func(config android.Config) {
+ delete(config.Targets, android.Android)
+ config.AndroidCommonTarget = android.Target{}
+ }),
+ )
if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
t.Errorf("Expected variants: %v, but got: %v", expected, got)
@@ -6402,7 +6312,7 @@
}
func TestAppSetBundlePrebuilt(t *testing.T) {
- ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, "", android.FixtureModifyMockFS(func(fs android.MockFS) {
bp := `
apex_set {
name: "myapex",
@@ -6413,9 +6323,9 @@
},
}`
fs["Android.bp"] = []byte(bp)
-
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- })
+ }),
+ prepareForTestWithSantitizeHwaddress,
+ )
m := ctx.ModuleForTests("myapex", "android_common")
extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex")
@@ -6980,13 +6890,17 @@
filename: "foo_v2.apex",
overrides: ["foo"],
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.Platform_sdk_version = intPtr(30)
- config.Targets[android.Android] = []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}},
- {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}},
- }
- })
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = intPtr(30)
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}},
+ }
+ }),
+ )
m := ctx.ModuleForTests("myapex", "android_common")
@@ -7194,9 +7108,11 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.CompressedApex = proptools.BoolPtr(true)
- })
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.CompressedApex = proptools.BoolPtr(true)
+ }),
+ )
compressRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("compressRule")
ensureContains(t, compressRule.Output.String(), "myapex.capex.unsigned")
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 2e6ed82..7e37e42 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -15,7 +15,6 @@
package apex
import (
- "reflect"
"strings"
"testing"
@@ -28,7 +27,18 @@
// modules from the ART apex.
func TestBootImages(t *testing.T) {
- ctx := testApex(t, `
+ result := apexFixtureFactory.Extend(
+ // Configure some libraries in the art and framework boot images.
+ dexpreopt.FixtureSetArtBootJars("com.android.art:baz", "com.android.art:quuz"),
+ dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+ filesForSdkLibrary.AddToFixture(),
+ // Some additional files needed for the art apex.
+ android.FixtureMergeMockFs(android.MockFS{
+ "com.android.art.avbpubkey": nil,
+ "com.android.art.pem": nil,
+ "system/sepolicy/apex/com.android.art-file_contexts": nil,
+ }),
+ ).RunTestWithBp(t, `
java_sdk_library {
name: "foo",
srcs: ["b.java"],
@@ -83,20 +93,10 @@
image_name: "boot",
}
`,
- // Configure some libraries in the art and framework boot images.
- withArtBootImageJars("com.android.art:baz", "com.android.art:quuz"),
- withFrameworkBootImageJars("platform:foo", "platform:bar"),
- withFiles(filesForSdkLibrary),
- // Some additional files needed for the art apex.
- withFiles(map[string][]byte{
- "com.android.art.avbpubkey": nil,
- "com.android.art.pem": nil,
- "system/sepolicy/apex/com.android.art-file_contexts": nil,
- }),
)
// Make sure that the framework-boot-image is using the correct configuration.
- checkBootImage(t, ctx, "framework-boot-image", "platform:foo,platform:bar", `
+ checkBootImage(t, result, "framework-boot-image", "platform:foo,platform:bar", `
test_device/dex_bootjars/android/system/framework/arm/boot-foo.art
test_device/dex_bootjars/android/system/framework/arm/boot-foo.oat
test_device/dex_bootjars/android/system/framework/arm/boot-foo.vdex
@@ -112,7 +112,7 @@
`)
// Make sure that the art-boot-image is using the correct configuration.
- checkBootImage(t, ctx, "art-boot-image", "com.android.art:baz,com.android.art:quuz", `
+ checkBootImage(t, result, "art-boot-image", "com.android.art:baz,com.android.art:quuz", `
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat
test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex
@@ -128,16 +128,14 @@
`)
}
-func checkBootImage(t *testing.T, ctx *android.TestContext, moduleName string, expectedConfiguredModules string, expectedBootImageFiles string) {
+func checkBootImage(t *testing.T, result *android.TestResult, moduleName string, expectedConfiguredModules string, expectedBootImageFiles string) {
t.Helper()
- bootImage := ctx.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule)
+ bootImage := result.ModuleForTests(moduleName, "android_common").Module().(*java.BootImageModule)
- bootImageInfo := ctx.ModuleProvider(bootImage, java.BootImageInfoProvider).(java.BootImageInfo)
+ bootImageInfo := result.ModuleProvider(bootImage, java.BootImageInfoProvider).(java.BootImageInfo)
modules := bootImageInfo.Modules()
- if actual := modules.String(); actual != expectedConfiguredModules {
- t.Errorf("invalid modules for %s: expected %q, actual %q", moduleName, expectedConfiguredModules, actual)
- }
+ android.AssertStringEquals(t, "invalid modules for "+moduleName, expectedConfiguredModules, modules.String())
// Get a list of all the paths in the boot image sorted by arch type.
allPaths := []string{}
@@ -149,39 +147,15 @@
}
}
}
- if expected, actual := strings.TrimSpace(expectedBootImageFiles), strings.TrimSpace(strings.Join(allPaths, "\n")); !reflect.DeepEqual(expected, actual) {
- t.Errorf("invalid paths for %s: expected \n%s, actual \n%s", moduleName, expected, actual)
- }
-}
-func modifyDexpreoptConfig(configModifier func(dexpreoptConfig *dexpreopt.GlobalConfig)) func(fs map[string][]byte, config android.Config) {
- return func(fs map[string][]byte, config android.Config) {
- // Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has
- // already been set.
- pathCtx := android.PathContextForTesting(config)
- dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
- dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
-
- // Retrieve the existing configuration and modify it.
- dexpreoptConfig = dexpreopt.GetGlobalConfig(pathCtx)
- configModifier(dexpreoptConfig)
- }
-}
-
-func withArtBootImageJars(bootJars ...string) func(fs map[string][]byte, config android.Config) {
- return modifyDexpreoptConfig(func(dexpreoptConfig *dexpreopt.GlobalConfig) {
- dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars)
- })
-}
-
-func withFrameworkBootImageJars(bootJars ...string) func(fs map[string][]byte, config android.Config) {
- return modifyDexpreoptConfig(func(dexpreoptConfig *dexpreopt.GlobalConfig) {
- dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
- })
+ android.AssertTrimmedStringEquals(t, "invalid paths for "+moduleName, expectedBootImageFiles, strings.Join(allPaths, "\n"))
}
func TestBootImageInApex(t *testing.T) {
- ctx := testApex(t, `
+ result := apexFixtureFactory.Extend(
+ // Configure some libraries in the framework boot image.
+ dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+ ).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -216,12 +190,9 @@
"myapex",
],
}
-`,
- // Configure some libraries in the framework boot image.
- withFrameworkBootImageJars("platform:foo", "platform:bar"),
- )
+ `)
- ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
"javalib/arm/boot-bar.art",
"javalib/arm/boot-bar.oat",
"javalib/arm/boot-bar.vdex",
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 34b9408..015283d 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -48,9 +48,11 @@
stl: "none",
apex_available: [ "com.android.vndk.current" ],
}
- `+vndkLibrariesTxtFiles("current"), func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("")
- })
+ `+vndkLibrariesTxtFiles("current"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = proptools.StringPtr("")
+ }),
+ )
// VNDK-Lite contains only core variants of VNDK-Sp libraries
ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
"lib/libvndksp.so",
@@ -113,20 +115,24 @@
})
t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
- ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
- // Now product variant is available
- config.TestProductVariables.ProductVndkVersion = proptools.StringPtr("current")
- })
+ ctx := testApex(t, bp,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // Now product variant is available
+ variables.ProductVndkVersion = proptools.StringPtr("current")
+ }),
+ )
files := getFiles(t, ctx, "com.android.vndk.current", "android_common_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared/libfoo.so")
})
t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
- ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
- config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
- config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
- })
+ ctx := testApex(t, bp,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.GcovCoverage = proptools.BoolPtr(true)
+ variables.Native_coverage = proptools.BoolPtr(true)
+ }),
+ )
files := getFiles(t, ctx, "com.android.vndk.current", "android_common_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared/libfoo.so")
diff --git a/bootstrap_test.sh b/bootstrap_test.sh
index 68067ee..87f5e31 100755
--- a/bootstrap_test.sh
+++ b/bootstrap_test.sh
@@ -4,7 +4,7 @@
# in a source tree that only contains enough files for Bazel and Soong to work.
HARDWIRED_MOCK_TOP=
-# Uncomment this for to be able to view the source tree after a test is run
+# Uncomment this to be able to view the source tree after a test is run
# HARDWIRED_MOCK_TOP=/tmp/td
REAL_TOP="$(readlink -f "$(dirname "$0")"/../..)"
@@ -85,63 +85,6 @@
export ALLOW_MISSING_DEPENDENCIES=true
mkdir -p out/soong
- # This is necessary because the empty soong.variables file written to satisfy
- # Ninja would contain "BootJars: {}" instead of "BootJars: []" which cannot
- # be parsed back
- # TODO(b/182965747): Fix this.
- cat > out/soong/soong.variables <<'EOF'
-{
- "BuildNumberFile": "build_number.txt",
- "Platform_version_name": "S",
- "Platform_sdk_version": 30,
- "Platform_sdk_codename": "S",
- "Platform_sdk_final": false,
- "Platform_version_active_codenames": [
- "S"
- ],
- "Platform_vndk_version": "S",
- "DeviceName": "generic_arm64",
- "DeviceArch": "arm64",
- "DeviceArchVariant": "armv8-a",
- "DeviceCpuVariant": "generic",
- "DeviceAbi": [
- "arm64-v8a"
- ],
- "DeviceSecondaryArch": "arm",
- "DeviceSecondaryArchVariant": "armv8-a",
- "DeviceSecondaryCpuVariant": "generic",
- "DeviceSecondaryAbi": [
- "armeabi-v7a",
- "armeabi"
- ],
- "HostArch": "x86_64",
- "HostSecondaryArch": "x86",
- "CrossHost": "windows",
- "CrossHostArch": "x86",
- "CrossHostSecondaryArch": "x86_64",
- "AAPTCharacteristics": "nosdcard",
- "AAPTConfig": [
- "normal",
- "large",
- "xlarge",
- "hdpi",
- "xhdpi",
- "xxhdpi"
- ],
- "AAPTPreferredConfig": "xhdpi",
- "AAPTPrebuiltDPI": [
- "xhdpi",
- "xxhdpi"
- ],
- "Malloc_not_svelte": true,
- "Malloc_zero_contents": true,
- "Malloc_pattern_fill_contents": false,
- "Safestack": false,
- "BootJars": [],
- "UpdatableBootJars": [],
- "Native_coverage": null
-}
-EOF
}
function run_soong() {
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index eb0d8c8..51fbc15 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -15,7 +15,6 @@
package bpf
import (
- "io/ioutil"
"os"
"testing"
@@ -23,34 +22,11 @@
"android/soong/cc"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "genrule_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
-
+ os.Exit(m.Run())
}
-var bpfFactory = android.NewFixtureFactory(
- &buildDir,
+var prepareForBpfTest = android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
android.FixtureMergeMockFs(
map[string][]byte{
@@ -76,7 +52,7 @@
}
`
- bpfFactory.RunTestWithBp(t, bp)
+ prepareForBpfTest.RunTestWithBp(t, bp)
// We only verify the above BP configuration is processed successfully since the data property
// value is not available for testing from this package.
diff --git a/cc/builder.go b/cc/builder.go
index 9cd78d5..273cdd3 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -59,7 +59,7 @@
// Rules to invoke ld to link binaries. Uses a .rsp file to list dependencies, as there may
// be many.
- ld, ldRE = remoteexec.StaticRules(pctx, "ld",
+ ld, ldRE = pctx.RemoteStaticRules("ld",
blueprint.RuleParams{
Command: "$reTemplate$ldCmd ${crtBegin} @${out}.rsp " +
"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${extraLibFlags}",
@@ -80,7 +80,7 @@
}, []string{"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags", "extraLibFlags"}, []string{"implicitInputs", "implicitOutputs"})
// Rules for .o files to combine to other .o files, using ld partial linking.
- partialLd, partialLdRE = remoteexec.StaticRules(pctx, "partialLd",
+ partialLd, partialLdRE = pctx.RemoteStaticRules("partialLd",
blueprint.RuleParams{
// Without -no-pie, clang 7.0 adds -pie to link Android files,
// but -r and -pie cannot be used together.
@@ -189,7 +189,7 @@
"crossCompile", "format")
// Rule for invoking clang-tidy (a clang-based linter).
- clangTidy, clangTidyRE = remoteexec.StaticRules(pctx, "clangTidy",
+ clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
blueprint.RuleParams{
Command: "rm -f $out && $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
@@ -228,7 +228,7 @@
_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
- sAbiDump, sAbiDumpRE = remoteexec.StaticRules(pctx, "sAbiDump",
+ sAbiDump, sAbiDumpRE = pctx.RemoteStaticRules("sAbiDump",
blueprint.RuleParams{
Command: "rm -f $out && $reTemplate$sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
CommandDeps: []string{"$sAbiDumper"},
@@ -246,7 +246,7 @@
// Rule to combine .dump sAbi dump files from multiple source files into a single .ldump
// sAbi dump file.
- sAbiLink, sAbiLinkRE = remoteexec.StaticRules(pctx, "sAbiLink",
+ sAbiLink, sAbiLinkRE = pctx.RemoteStaticRules("sAbiLink",
blueprint.RuleParams{
Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ",
CommandDeps: []string{"$sAbiLinker"},
@@ -331,7 +331,6 @@
pctx.StaticVariable("relPwd", PwdPrefix())
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
- pctx.Import("android/soong/remoteexec")
}
// builderFlags contains various types of command line flags (and settings) for use in building
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 16ae7ee..7196615 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2065,6 +2065,7 @@
vendor_available: true,
product_available: true,
nocrt: true,
+ srcs: ["foo.c"],
target: {
vendor: {
suffix: "-vendor",
@@ -2108,12 +2109,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
-
- ctx := testCcWithConfig(t, config)
+ ctx := ccFixtureFactory.RunTestWithBp(t, bp).TestContext
checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
@@ -2123,6 +2119,33 @@
mod_product := ctx.ModuleForTests("libboth_available", productVariant).Module().(*Module)
assertString(t, mod_product.outputFile.Path().Base(), "libboth_available-product.so")
+
+ ensureStringContains := func(t *testing.T, str string, substr string) {
+ t.Helper()
+ if !strings.Contains(str, substr) {
+ t.Errorf("%q is not found in %v", substr, str)
+ }
+ }
+ ensureStringNotContains := func(t *testing.T, str string, substr string) {
+ t.Helper()
+ if strings.Contains(str, substr) {
+ t.Errorf("%q is found in %v", substr, str)
+ }
+ }
+
+ // _static variant is used since _shared reuses *.o from the static variant
+ vendor_static := ctx.ModuleForTests("libboth_available", strings.Replace(vendorVariant, "_shared", "_static", 1))
+ product_static := ctx.ModuleForTests("libboth_available", strings.Replace(productVariant, "_shared", "_static", 1))
+
+ vendor_cflags := vendor_static.Rule("cc").Args["cFlags"]
+ ensureStringContains(t, vendor_cflags, "-D__ANDROID_VNDK__")
+ ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR__")
+ ensureStringNotContains(t, vendor_cflags, "-D__ANDROID_PRODUCT__")
+
+ product_cflags := product_static.Rule("cc").Args["cFlags"]
+ ensureStringContains(t, product_cflags, "-D__ANDROID_VNDK__")
+ ensureStringContains(t, product_cflags, "-D__ANDROID_PRODUCT__")
+ ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR__")
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
diff --git a/cc/compiler.go b/cc/compiler.go
index 791c95b..b09b58e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -360,6 +360,11 @@
if ctx.useVndk() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VNDK__")
+ if ctx.inVendor() {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR__")
+ } else if ctx.inProduct() {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_PRODUCT__")
+ }
}
if ctx.inRecovery() {
diff --git a/cc/config/global.go b/cc/config/global.go
index e60bb3d..7e80900 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -144,8 +144,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r412851"
- ClangDefaultShortVersion = "12.0.3"
+ ClangDefaultVersion = "clang-r416183"
+ ClangDefaultShortVersion = "12.0.4"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -270,13 +270,13 @@
return ""
})
- pctx.VariableFunc("RECXXPool", remoteexec.EnvOverrideFunc("RBE_CXX_POOL", remoteexec.DefaultPool))
- pctx.VariableFunc("RECXXLinksPool", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_POOL", remoteexec.DefaultPool))
- pctx.VariableFunc("REClangTidyPool", remoteexec.EnvOverrideFunc("RBE_CLANG_TIDY_POOL", remoteexec.DefaultPool))
- pctx.VariableFunc("RECXXLinksExecStrategy", remoteexec.EnvOverrideFunc("RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("REClangTidyExecStrategy", remoteexec.EnvOverrideFunc("RBE_CLANG_TIDY_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("REAbiDumperExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("REAbiLinkerExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.StaticVariableWithEnvOverride("RECXXPool", "RBE_CXX_POOL", remoteexec.DefaultPool)
+ pctx.StaticVariableWithEnvOverride("RECXXLinksPool", "RBE_CXX_LINKS_POOL", remoteexec.DefaultPool)
+ pctx.StaticVariableWithEnvOverride("REClangTidyPool", "RBE_CLANG_TIDY_POOL", remoteexec.DefaultPool)
+ pctx.StaticVariableWithEnvOverride("RECXXLinksExecStrategy", "RBE_CXX_LINKS_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("REClangTidyExecStrategy", "RBE_CLANG_TIDY_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("REAbiDumperExecStrategy", "RBE_ABI_DUMPER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("REAbiLinkerExecStrategy", "RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
diff --git a/cc/library_headers.go b/cc/library_headers.go
index dc851a5..115b775 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -90,15 +90,11 @@
return
}
- lib, ok := module.linker.(*libraryDecorator)
- if !ok {
- // Not a cc_library module
+ if ctx.ModuleType() != "cc_library_headers" {
return
}
- if !lib.header() {
- // Not a cc_library_headers module
- return
- }
+
+ lib, _ := module.linker.(*libraryDecorator)
// list of directories that will be added to the include path (using -I) for this
// module and any module that links against this module.
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index f8919a4..f47c601 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -229,13 +229,18 @@
return "", err
}
+ pathToTempDirInSbox := tempDir
+ if command.GetChdir() {
+ pathToTempDirInSbox = "."
+ }
+
if strings.Contains(rawCommand, depFilePlaceholder) {
- depFile = filepath.Join(tempDir, "deps.d")
+ depFile = filepath.Join(pathToTempDirInSbox, "deps.d")
rawCommand = strings.Replace(rawCommand, depFilePlaceholder, depFile, -1)
}
if strings.Contains(rawCommand, sandboxDirPlaceholder) {
- rawCommand = strings.Replace(rawCommand, sandboxDirPlaceholder, tempDir, -1)
+ rawCommand = strings.Replace(rawCommand, sandboxDirPlaceholder, pathToTempDirInSbox, -1)
}
// Emulate ninja's behavior of creating the directories for any output files before
@@ -254,6 +259,15 @@
if command.GetChdir() {
cmd.Dir = tempDir
+ path := os.Getenv("PATH")
+ absPath, err := makeAbsPathEnv(path)
+ if err != nil {
+ return "", err
+ }
+ err = os.Setenv("PATH", absPath)
+ if err != nil {
+ return "", fmt.Errorf("Failed to update PATH: %w", err)
+ }
}
err = cmd.Run()
@@ -466,3 +480,17 @@
}
return filepath.Join(dir, file)
}
+
+func makeAbsPathEnv(pathEnv string) (string, error) {
+ pathEnvElements := filepath.SplitList(pathEnv)
+ for i, p := range pathEnvElements {
+ if !filepath.IsAbs(p) {
+ absPath, err := filepath.Abs(p)
+ if err != nil {
+ return "", fmt.Errorf("failed to make PATH entry %q absolute: %w", p, err)
+ }
+ pathEnvElements[i] = absPath
+ }
+ }
+ return strings.Join(pathEnvElements, string(filepath.ListSeparator)), nil
+}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index f800c48..9c3db3b 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -26,8 +26,7 @@
os.Exit(m.Run())
}
-var prebuiltEtcFixtureFactory = android.NewFixtureFactory(
- nil,
+var prepareForPrebuiltEtcTest = android.GroupFixturePreparers(
android.PrepareForTestWithArchMutator,
PrepareForTestWithPrebuiltEtc,
android.FixtureMergeMockFs(android.MockFS{
@@ -38,7 +37,7 @@
)
func TestPrebuiltEtcVariants(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -72,7 +71,7 @@
}
func TestPrebuiltEtcOutputPath(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -85,7 +84,7 @@
}
func TestPrebuiltEtcGlob(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
name: "my_foo",
src: "foo.*",
@@ -105,7 +104,7 @@
}
func TestPrebuiltEtcAndroidMk(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
name: "foo",
src: "foo.conf",
@@ -139,7 +138,7 @@
}
func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
name: "foo.conf",
src: "foo.conf",
@@ -153,7 +152,7 @@
}
func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) {
- prebuiltEtcFixtureFactory.
+ prepareForPrebuiltEtcTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("relative_install_path is set. Cannot set sub_dir")).
RunTestWithBp(t, `
prebuilt_etc {
@@ -166,7 +165,7 @@
}
func TestPrebuiltEtcHost(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc_host {
name: "foo.conf",
src: "foo.conf",
@@ -181,7 +180,7 @@
}
func TestPrebuiltUserShareInstallDirPath(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_usr_share {
name: "foo.conf",
src: "foo.conf",
@@ -195,7 +194,7 @@
}
func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_usr_share_host {
name: "foo.conf",
src: "foo.conf",
@@ -210,7 +209,7 @@
}
func TestPrebuiltFontInstallDirPath(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, `
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_font {
name: "foo.conf",
src: "foo.conf",
@@ -249,7 +248,7 @@
}}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
})
@@ -283,7 +282,7 @@
}}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
- result := prebuiltEtcFixtureFactory.RunTestWithBp(t, tt.config)
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
})
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index dcdbdcf..791019d 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -14,6 +14,7 @@
"bootimg.go",
"filesystem.go",
"logical_partition.go",
+ "vbmeta.go",
],
testSrcs: [
],
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 372a610..3dcc416 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -17,6 +17,7 @@
import (
"fmt"
"strconv"
+ "strings"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -217,22 +218,46 @@
}
func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.OutputPath) android.OutputPath {
- output := android.PathForModuleOut(ctx, b.installFileName()).OutputPath
- key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
+ propFile, toolDeps := b.buildPropFile(ctx)
+ output := android.PathForModuleOut(ctx, b.installFileName()).OutputPath
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("cp").Input(unsignedImage).Output(output)
- builder.Command().
- BuiltTool("avbtool").
- Flag("add_hash_footer").
- FlagWithArg("--partition_name ", b.partitionName()).
- FlagWithInput("--key ", key).
- FlagWithOutput("--image ", output)
+ builder.Command().BuiltTool("verity_utils").
+ Input(propFile).
+ Implicits(toolDeps).
+ Output(output)
builder.Build("sign_bootimg", fmt.Sprintf("Signing %s", b.BaseModuleName()))
return output
}
+func (b *bootimg) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
+ var sb strings.Builder
+ var deps android.Paths
+ addStr := func(name string, value string) {
+ fmt.Fprintf(&sb, "%s=%s\n", name, value)
+ }
+ addPath := func(name string, path android.Path) {
+ addStr(name, path.String())
+ deps = append(deps, path)
+ }
+
+ addStr("avb_hash_enable", "true")
+ addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool"))
+ algorithm := proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096")
+ addStr("avb_algorithm", algorithm)
+ key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
+ addPath("avb_key_path", key)
+ addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index
+ partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
+ addStr("partition_name", partitionName)
+
+ propFile = android.PathForModuleOut(ctx, "prop").OutputPath
+ android.WriteFileRule(ctx, propFile, sb.String())
+ return propFile, deps
+}
+
var _ android.AndroidMkEntriesProvider = (*bootimg)(nil)
// Implements android.AndroidMkEntriesProvider
@@ -255,6 +280,13 @@
return b.output
}
+func (b *bootimg) SignedOutputPath() android.Path {
+ if proptools.Bool(b.properties.Use_avb) {
+ return b.OutputPath()
+ }
+ return nil
+}
+
var _ android.OutputFileProducer = (*bootimg)(nil)
// Implements android.OutputFileProducer
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 3b0a7ae..b2bd6bd 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -55,6 +55,9 @@
// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
Avb_algorithm *string
+ // Name of the partition stored in vbmeta desc. Defaults to the name of this module.
+ Partition_name *string
+
// Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default
// is ext4.
Type *string
@@ -88,7 +91,7 @@
var dependencyTag = struct {
blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag
+ android.PackagingItemAlwaysDepTag
}{}
func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -279,7 +282,8 @@
key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
addPath("avb_key_path", key)
addStr("avb_add_hashtree_footer_args", "--do_not_generate_fec")
- addStr("partition_name", f.Name())
+ partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
+ addStr("partition_name", partitionName)
}
if proptools.String(f.properties.File_contexts) != "" {
@@ -381,6 +385,10 @@
type Filesystem interface {
android.Module
OutputPath() android.Path
+
+ // Returns the output file that is signed by avbtool. If this module is not signed, returns
+ // nil.
+ SignedOutputPath() android.Path
}
var _ Filesystem = (*filesystem)(nil)
@@ -388,3 +396,10 @@
func (f *filesystem) OutputPath() android.Path {
return f.output
}
+
+func (f *filesystem) SignedOutputPath() android.Path {
+ if proptools.Bool(f.properties.Use_avb) {
+ return f.OutputPath()
+ }
+ return nil
+}
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
index 16b6037..20d9622 100644
--- a/filesystem/logical_partition.go
+++ b/filesystem/logical_partition.go
@@ -209,6 +209,10 @@
return l.output
}
+func (l *logicalPartition) SignedOutputPath() android.Path {
+ return nil // logical partition is not signed by itself
+}
+
var _ android.OutputFileProducer = (*logicalPartition)(nil)
// Implements android.OutputFileProducer
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
new file mode 100644
index 0000000..f823387
--- /dev/null
+++ b/filesystem/vbmeta.go
@@ -0,0 +1,265 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("vbmeta", vbmetaFactory)
+}
+
+type vbmeta struct {
+ android.ModuleBase
+
+ properties vbmetaProperties
+
+ output android.OutputPath
+ installDir android.InstallPath
+}
+
+type vbmetaProperties struct {
+ // Name of the partition stored in vbmeta desc. Defaults to the name of this module.
+ Partition_name *string
+
+ // Set the name of the output. Defaults to <module_name>.img.
+ Stem *string
+
+ // Path to the private key that avbtool will use to sign this vbmeta image.
+ Private_key *string `android:"path"`
+
+ // Algorithm that avbtool will use to sign this vbmeta image. Default is SHA256_RSA4096.
+ Algorithm *string
+
+ // File whose content will provide the rollback index. If unspecified, the rollback index
+ // is from PLATFORM_SECURITY_PATCH
+ Rollback_index_file *string `android:"path"`
+
+ // Rollback index location of this vbmeta image. Must be 0, 1, 2, etc. Default is 0.
+ Rollback_index_location *int64
+
+ // List of filesystem modules that this vbmeta has descriptors for. The filesystem modules
+ // have to be signed (use_avb: true).
+ Partitions []string
+
+ // List of chained partitions that this vbmeta deletages the verification.
+ Chained_partitions []chainedPartitionProperties
+}
+
+type chainedPartitionProperties struct {
+ // Name of the chained partition
+ Name *string
+
+ // Rollback index location of the chained partition. Must be 0, 1, 2, etc. Default is the
+ // index of this partition in the list + 1.
+ Rollback_index_location *int64
+
+ // Path to the public key that the chained partition is signed with. If this is specified,
+ // private_key is ignored.
+ Public_key *string `android:"path"`
+
+ // Path to the private key that the chained partition is signed with. If this is specified,
+ // and public_key is not specified, a public key is extracted from this private key and
+ // the extracted public key is embedded in the vbmeta image.
+ Private_key *string `android:"path"`
+}
+
+// vbmeta is the partition image that has the verification information for other partitions.
+func vbmetaFactory() android.Module {
+ module := &vbmeta{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+type vbmetaDep struct {
+ blueprint.BaseDependencyTag
+ kind string
+}
+
+var vbmetaPartitionDep = vbmetaDep{kind: "partition"}
+
+func (v *vbmeta) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions...)
+}
+
+func (v *vbmeta) installFileName() string {
+ return proptools.StringDefault(v.properties.Stem, v.BaseModuleName()+".img")
+}
+
+func (v *vbmeta) partitionName() string {
+ return proptools.StringDefault(v.properties.Partition_name, v.BaseModuleName())
+}
+
+func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ extractedPublicKeys := v.extractPublicKeys(ctx)
+
+ v.output = android.PathForModuleOut(ctx, v.installFileName()).OutputPath
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command().BuiltTool("avbtool").Text("make_vbmeta_image")
+
+ key := android.PathForModuleSrc(ctx, proptools.String(v.properties.Private_key))
+ cmd.FlagWithInput("--key ", key)
+
+ algorithm := proptools.StringDefault(v.properties.Algorithm, "SHA256_RSA4096")
+ cmd.FlagWithArg("--algorithm ", algorithm)
+
+ cmd.FlagWithArg("--rollback_index ", v.rollbackIndexCommand(ctx))
+ ril := proptools.IntDefault(v.properties.Rollback_index_location, 0)
+ if ril < 0 {
+ ctx.PropertyErrorf("rollback_index_location", "must be 0, 1, 2, ...")
+ return
+ }
+ cmd.FlagWithArg("--rollback_index_location ", strconv.Itoa(ril))
+
+ for _, p := range ctx.GetDirectDepsWithTag(vbmetaPartitionDep) {
+ f, ok := p.(Filesystem)
+ if !ok {
+ ctx.PropertyErrorf("partitions", "%q(type: %s) is not supported",
+ p.Name(), ctx.OtherModuleType(p))
+ continue
+ }
+ signedImage := f.SignedOutputPath()
+ if signedImage == nil {
+ ctx.PropertyErrorf("partitions", "%q(type: %s) is not signed. Use `use_avb: true`",
+ p.Name(), ctx.OtherModuleType(p))
+ continue
+ }
+ cmd.FlagWithInput("--include_descriptors_from_image ", signedImage)
+ }
+
+ for i, cp := range v.properties.Chained_partitions {
+ name := proptools.String(cp.Name)
+ if name == "" {
+ ctx.PropertyErrorf("chained_partitions", "name must be specified")
+ continue
+ }
+
+ ril := proptools.IntDefault(cp.Rollback_index_location, i+1)
+ if ril < 0 {
+ ctx.PropertyErrorf("chained_partitions", "must be 0, 1, 2, ...")
+ continue
+ }
+
+ var publicKey android.Path
+ if cp.Public_key != nil {
+ publicKey = android.PathForModuleSrc(ctx, proptools.String(cp.Public_key))
+ } else {
+ publicKey = extractedPublicKeys[name]
+ }
+ cmd.FlagWithArg("--chain_partition ", fmt.Sprintf("%s:%d:%s", name, ril, publicKey.String()))
+ cmd.Implicit(publicKey)
+ }
+
+ cmd.FlagWithOutput("--output ", v.output)
+ builder.Build("vbmeta", fmt.Sprintf("vbmeta %s", ctx.ModuleName()))
+
+ v.installDir = android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(v.installDir, v.installFileName(), v.output)
+}
+
+// Returns the embedded shell command that prints the rollback index
+func (v *vbmeta) rollbackIndexCommand(ctx android.ModuleContext) string {
+ var cmd string
+ if v.properties.Rollback_index_file != nil {
+ f := android.PathForModuleSrc(ctx, proptools.String(v.properties.Rollback_index_file))
+ cmd = "cat " + f.String()
+ } else {
+ cmd = "date -d 'TZ=\"GMT\" " + ctx.Config().PlatformSecurityPatch() + "' +%s"
+ }
+ // Take the first line and remove the newline char
+ return "$(" + cmd + " | head -1 | tr -d '\n'" + ")"
+}
+
+// Extract public keys from chained_partitions.private_key. The keys are indexed with the partition
+// name.
+func (v *vbmeta) extractPublicKeys(ctx android.ModuleContext) map[string]android.OutputPath {
+ result := make(map[string]android.OutputPath)
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ for _, cp := range v.properties.Chained_partitions {
+ if cp.Private_key == nil {
+ continue
+ }
+
+ name := proptools.String(cp.Name)
+ if name == "" {
+ ctx.PropertyErrorf("chained_partitions", "name must be specified")
+ continue
+ }
+
+ if _, ok := result[name]; ok {
+ ctx.PropertyErrorf("chained_partitions", "name %q is duplicated", name)
+ continue
+ }
+
+ privateKeyFile := android.PathForModuleSrc(ctx, proptools.String(cp.Private_key))
+ publicKeyFile := android.PathForModuleOut(ctx, name+".avbpubkey").OutputPath
+
+ builder.Command().
+ BuiltTool("avbtool").
+ Text("extract_public_key").
+ FlagWithInput("--key ", privateKeyFile).
+ FlagWithOutput("--output ", publicKeyFile)
+
+ result[name] = publicKeyFile
+ }
+ builder.Build("vbmeta_extract_public_key", fmt.Sprintf("Extract public keys for %s", ctx.ModuleName()))
+ return result
+}
+
+var _ android.AndroidMkEntriesProvider = (*vbmeta)(nil)
+
+// Implements android.AndroidMkEntriesProvider
+func (v *vbmeta) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(v.output),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", v.installDir.ToMakePath().String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName())
+ },
+ },
+ }}
+}
+
+var _ Filesystem = (*vbmeta)(nil)
+
+func (v *vbmeta) OutputPath() android.Path {
+ return v.output
+}
+
+func (v *vbmeta) SignedOutputPath() android.Path {
+ return v.OutputPath() // vbmeta is always signed
+}
+
+var _ android.OutputFileProducer = (*vbmeta)(nil)
+
+// Implements android.OutputFileProducer
+func (v *vbmeta) OutputFiles(tag string) (android.Paths, error) {
+ if tag == "" {
+ return []android.Path{v.output}, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index fc6a44f..b43f28e 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -824,6 +824,11 @@
return
}
+ if ctx.ModuleType() != "genrule" {
+ // Not a regular genrule. Could be a cc_genrule or java_genrule.
+ return
+ }
+
// Bazel only has the "tools" attribute.
tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 199a7df..bb17e8e 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -28,8 +28,7 @@
os.Exit(m.Run())
}
-var genruleFixtureFactory = android.NewFixtureFactory(
- nil,
+var prepareForGenRuleTest = android.GroupFixturePreparers(
android.PrepareForTestWithArchMutator,
android.PrepareForTestWithDefaults,
@@ -447,7 +446,8 @@
expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
}
- result := genruleFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
}),
@@ -523,7 +523,7 @@
},
}
- result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
+ result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
@@ -605,7 +605,7 @@
expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
}
- result := genruleFixtureFactory.
+ result := prepareForGenRuleTest.
ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
RunTestWithBp(t, testGenruleBp()+bp)
@@ -642,7 +642,7 @@
}
`
- result := genruleFixtureFactory.RunTestWithBp(t, testGenruleBp()+bp)
+ result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
gen := result.Module("gen", "").(*Module)
@@ -662,11 +662,12 @@
}
`
- result := genruleFixtureFactory.Extend(android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- AllFiles: map[string][]string{
- "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
- })).RunTestWithBp(t, testGenruleBp()+bp)
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ AllFiles: map[string][]string{
+ "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
+ })).RunTestWithBp(t, testGenruleBp()+bp)
gen := result.Module("foo", "").(*Module)
diff --git a/java/Android.bp b/java/Android.bp
index 9e2db83..c67379c 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -28,6 +28,7 @@
"app.go",
"app_import.go",
"app_set.go",
+ "base.go",
"boot_image.go",
"boot_jars.go",
"builder.go",
@@ -75,6 +76,7 @@
"java_test.go",
"jdeps_test.go",
"kotlin_test.go",
+ "platform_compat_config_test.go",
"plugin_test.go",
"rro_test.go",
"sdk_test.go",
diff --git a/java/aar.go b/java/aar.go
index 554ea67..67b9ef0 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -40,15 +40,14 @@
func init() {
RegisterAARBuildComponents(android.InitRegistrationContext)
-
- android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
- })
}
func RegisterAARBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_library_import", AARImportFactory)
ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+ })
}
//
diff --git a/java/android_resources.go b/java/android_resources.go
index 4d420cf..6864ebb 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -22,8 +22,11 @@
)
func init() {
- android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+ registerOverlayBuildComponents(android.InitRegistrationContext)
+}
+func registerOverlayBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
}
var androidResourceIgnoreFilenames = []string{
diff --git a/java/app_builder.go b/java/app_builder.go
index b53c15a..4a18dca 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -30,7 +30,7 @@
)
var (
- Signapk, SignapkRE = remoteexec.StaticRules(pctx, "signapk",
+ Signapk, SignapkRE = pctx.RemoteStaticRules("signapk",
blueprint.RuleParams{
Command: `rm -f $out && $reTemplate${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` +
`-jar ${config.SignapkCmd} $flags $certificates $in $out`,
diff --git a/java/app_test.go b/java/app_test.go
index c189ee5..7168a96 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -370,11 +370,15 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- if test.expectedError == "" {
- testJava(t, test.bp)
- } else {
- testJavaError(t, test.expectedError, test.bp)
+ errorHandler := android.FixtureExpectsNoErrors
+ if test.expectedError != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
}
+ javaFixtureFactory.
+ Extend(FixtureWithPrebuiltApis(map[string][]string{
+ "29": {"foo"},
+ })).
+ ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, test.bp)
})
}
}
@@ -984,12 +988,8 @@
}
}
-func checkSdkVersion(t *testing.T, config android.Config, expectedSdkVersion string) {
- ctx := testContext(config)
-
- run(t, ctx, config)
-
- foo := ctx.ModuleForTests("foo", "android_common")
+func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) {
+ foo := result.ModuleForTests("foo", "android_common")
link := foo.Output("package-res.apk")
linkFlags := strings.Split(link.Args["flags"], " ")
min := android.IndexList("--min-sdk-version", linkFlags)
@@ -1002,15 +1002,9 @@
gotMinSdkVersion := linkFlags[min+1]
gotTargetSdkVersion := linkFlags[target+1]
- if gotMinSdkVersion != expectedSdkVersion {
- t.Errorf("incorrect --min-sdk-version, expected %q got %q",
- expectedSdkVersion, gotMinSdkVersion)
- }
+ android.AssertStringEquals(t, "incorrect --min-sdk-version", expectedSdkVersion, gotMinSdkVersion)
- if gotTargetSdkVersion != expectedSdkVersion {
- t.Errorf("incorrect --target-sdk-version, expected %q got %q",
- expectedSdkVersion, gotTargetSdkVersion)
- }
+ android.AssertStringEquals(t, "incorrect --target-sdk-version", expectedSdkVersion, gotTargetSdkVersion)
}
func TestAppSdkVersion(t *testing.T) {
@@ -1083,13 +1077,19 @@
%s
}`, moduleType, test.sdkVersion, platformApiProp)
- config := testAppConfig(nil, bp, nil)
- config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
- config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
- config.TestProductVariables.Platform_version_active_codenames = test.activeCodenames
- config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
- checkSdkVersion(t, config, test.expectedMinSdkVersion)
+ result := javaFixtureFactory.Extend(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = &test.platformSdkInt
+ variables.Platform_sdk_codename = &test.platformSdkCodename
+ variables.Platform_version_active_codenames = test.activeCodenames
+ variables.Platform_sdk_final = &test.platformSdkFinal
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "14": {"foo"},
+ }),
+ ).RunTestWithBp(t, bp)
+ checkSdkVersion(t, result, test.expectedMinSdkVersion)
})
}
}
@@ -1145,13 +1145,22 @@
vendor: true,
}`, moduleType, sdkKind, test.sdkVersion)
- config := testAppConfig(nil, bp, nil)
- config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
- config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
- config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
- config.TestProductVariables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
- config.TestProductVariables.DeviceSystemSdkVersions = []string{"28", "29"}
- checkSdkVersion(t, config, test.expectedMinSdkVersion)
+ result := javaFixtureFactory.Extend(
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = &test.platformSdkInt
+ variables.Platform_sdk_codename = &test.platformSdkCodename
+ variables.Platform_sdk_final = &test.platformSdkFinal
+ variables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
+ variables.DeviceSystemSdkVersions = []string{"28", "29"}
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ "29": {"foo"},
+ "current": {"foo"},
+ }),
+ ).RunTestWithBp(t, bp)
+
+ checkSdkVersion(t, result, test.expectedMinSdkVersion)
})
}
}
@@ -2360,15 +2369,16 @@
}
`
- config := testAppConfig(nil, bp, nil)
- config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
+ result := javaFixtureFactory.Extend(
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.MissingUsesLibraries = []string{"baz"}
+ }),
+ ).RunTestWithBp(t, bp)
- ctx := testContext(config)
-
- run(t, ctx, config)
-
- app := ctx.ModuleForTests("app", "android_common")
- prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
+ app := result.ModuleForTests("app", "android_common")
+ prebuilt := result.ModuleForTests("prebuilt", "android_common")
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
// This should not include explicit `uses_libs`/`optional_uses_libs` entries.
@@ -2380,10 +2390,7 @@
`--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
`--uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
`--uses-library runtime-library`
- if actualManifestFixerArgs != expectManifestFixerArgs {
- t.Errorf("unexpected manifest_fixer args:\n\texpect: %q\n\tactual: %q",
- expectManifestFixerArgs, actualManifestFixerArgs)
- }
+ android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
// Test that all libraries are verified (library order matters).
verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
@@ -2394,9 +2401,7 @@
`--uses-library runtime-library ` +
`--optional-uses-library bar ` +
`--optional-uses-library baz `
- if !strings.Contains(verifyCmd, verifyArgs) {
- t.Errorf("wanted %q in %q", verifyArgs, verifyCmd)
- }
+ android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
// Test that all libraries are verified for an APK (library order matters).
verifyApkCmd := prebuilt.Rule("verify_uses_libraries").RuleParams.Command
@@ -2405,9 +2410,7 @@
`--uses-library android.test.runner ` +
`--optional-uses-library bar ` +
`--optional-uses-library baz `
- if !strings.Contains(verifyApkCmd, verifyApkArgs) {
- t.Errorf("wanted %q in %q", verifyApkArgs, verifyApkCmd)
- }
+ android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
cmd := app.Rule("dexpreopt").RuleParams.Command
@@ -2418,46 +2421,39 @@
`PCL[/system/framework/non-sdk-lib.jar]#` +
`PCL[/system/framework/bar.jar]#` +
`PCL[/system/framework/runtime-library.jar]`
- if !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt app cmd args", cmd, w)
// Test conditional context for target SDK version 28.
- if w := `--target-context-for-sdk 28` +
- ` PCL[/system/framework/org.apache.http.legacy.jar] `; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt app cmd 28", cmd,
+ `--target-context-for-sdk 28`+
+ ` PCL[/system/framework/org.apache.http.legacy.jar] `)
// Test conditional context for target SDK version 29.
- if w := `--target-context-for-sdk 29` +
- ` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]` +
- `#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt app cmd 29", cmd,
+ `--target-context-for-sdk 29`+
+ ` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]`+
+ `#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `)
// Test conditional context for target SDK version 30.
// "android.test.mock" is absent because "android.test.runner" is not used.
- if w := `--target-context-for-sdk 30` +
- ` PCL[/system/framework/android.test.base.jar] `; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt app cmd 30", cmd,
+ `--target-context-for-sdk 30`+
+ ` PCL[/system/framework/android.test.base.jar] `)
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
- if w := `--target-context-for-sdk any` +
- ` PCL[/system/framework/foo.jar]` +
- `#PCL[/system/framework/non-sdk-lib.jar]` +
- `#PCL[/system/framework/android.test.runner.jar]` +
- `#PCL[/system/framework/bar.jar] `; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd", cmd,
+ `--target-context-for-sdk any`+
+ ` PCL[/system/framework/foo.jar]`+
+ `#PCL[/system/framework/non-sdk-lib.jar]`+
+ `#PCL[/system/framework/android.test.runner.jar]`+
+ `#PCL[/system/framework/bar.jar] `)
// Test conditional context for target SDK version 30.
// "android.test.mock" is present because "android.test.runner" is used.
- if w := `--target-context-for-sdk 30` +
- ` PCL[/system/framework/android.test.base.jar]` +
- `#PCL[/system/framework/android.test.mock.jar] `; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
+ android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd 30", cmd,
+ `--target-context-for-sdk 30`+
+ ` PCL[/system/framework/android.test.base.jar]`+
+ `#PCL[/system/framework/android.test.mock.jar] `)
}
func TestCodelessApp(t *testing.T) {
@@ -2722,28 +2718,24 @@
test := func(t *testing.T, bp string, want bool, unbundled bool) {
t.Helper()
- config := testAppConfig(nil, bp, nil)
- if unbundled {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- }
+ result := javaFixtureFactory.Extend(
+ PrepareForTestWithPrebuiltsOfCurrentApi,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if unbundled {
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ }
+ }),
+ ).RunTestWithBp(t, bp)
- ctx := testContext(config)
-
- run(t, ctx, config)
-
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests("foo", "android_common")
dex := foo.Rule("r8")
uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
aligned := foo.MaybeRule("zipalign").Rule != nil
- if uncompressedInDexJar != want {
- t.Errorf("want uncompressed in dex %v, got %v", want, uncompressedInDexJar)
- }
+ android.AssertBoolEquals(t, "uncompressed in dex", want, uncompressedInDexJar)
- if aligned != want {
- t.Errorf("want aligned %v, got %v", want, aligned)
- }
+ android.AssertBoolEquals(t, "aligne", want, aligned)
}
for _, tt := range testCases {
diff --git a/java/base.go b/java/base.go
new file mode 100644
index 0000000..bd394af
--- /dev/null
+++ b/java/base.go
@@ -0,0 +1,1786 @@
+// Copyright 2021 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 java
+
+import (
+ "fmt"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
+ "android/soong/java/config"
+)
+
+// This file contains the definition and the implementation of the base module that most
+// source-based Java module structs embed.
+
+// TODO:
+// Autogenerated files:
+// Renderscript
+// Post-jar passes:
+// Proguard
+// Rmtypedefs
+// DroidDoc
+// Findbugs
+
+// Properties that are common to most Java modules, i.e. whether it's a host or device module.
+type CommonProperties struct {
+ // list of source files used to compile the Java module. May be .java, .kt, .logtags, .proto,
+ // or .aidl files.
+ Srcs []string `android:"path,arch_variant"`
+
+ // list Kotlin of source files containing Kotlin code that should be treated as common code in
+ // a codebase that supports Kotlin multiplatform. See
+ // https://kotlinlang.org/docs/reference/multiplatform.html. May be only be .kt files.
+ Common_srcs []string `android:"path,arch_variant"`
+
+ // list of source files that should not be used to build the Java module.
+ // This is most useful in the arch/multilib variants to remove non-common files
+ Exclude_srcs []string `android:"path,arch_variant"`
+
+ // list of directories containing Java resources
+ Java_resource_dirs []string `android:"arch_variant"`
+
+ // list of directories that should be excluded from java_resource_dirs
+ Exclude_java_resource_dirs []string `android:"arch_variant"`
+
+ // list of files to use as Java resources
+ Java_resources []string `android:"path,arch_variant"`
+
+ // list of files that should be excluded from java_resources and java_resource_dirs
+ Exclude_java_resources []string `android:"path,arch_variant"`
+
+ // list of module-specific flags that will be used for javac compiles
+ Javacflags []string `android:"arch_variant"`
+
+ // list of module-specific flags that will be used for kotlinc compiles
+ Kotlincflags []string `android:"arch_variant"`
+
+ // list of java libraries that will be in the classpath
+ Libs []string `android:"arch_variant"`
+
+ // list of java libraries that will be compiled into the resulting jar
+ Static_libs []string `android:"arch_variant"`
+
+ // manifest file to be included in resulting jar
+ Manifest *string `android:"path"`
+
+ // if not blank, run jarjar using the specified rules file
+ Jarjar_rules *string `android:"path,arch_variant"`
+
+ // If not blank, set the java version passed to javac as -source and -target
+ Java_version *string
+
+ // If set to true, allow this module to be dexed and installed on devices. Has no
+ // effect on host modules, which are always considered installable.
+ Installable *bool
+
+ // If set to true, include sources used to compile the module in to the final jar
+ Include_srcs *bool
+
+ // If not empty, classes are restricted to the specified packages and their sub-packages.
+ // This restriction is checked after applying jarjar rules and including static libs.
+ Permitted_packages []string
+
+ // List of modules to use as annotation processors
+ Plugins []string
+
+ // List of modules to export to libraries that directly depend on this library as annotation
+ // processors. Note that if the plugins set generates_api: true this will disable the turbine
+ // optimization on modules that depend on this module, which will reduce parallelism and cause
+ // more recompilation.
+ Exported_plugins []string
+
+ // The number of Java source entries each Javac instance can process
+ Javac_shard_size *int64
+
+ // Add host jdk tools.jar to bootclasspath
+ Use_tools_jar *bool
+
+ Openjdk9 struct {
+ // List of source files that should only be used when passing -source 1.9 or higher
+ Srcs []string `android:"path"`
+
+ // List of javac flags that should only be used when passing -source 1.9 or higher
+ Javacflags []string
+ }
+
+ // When compiling language level 9+ .java code in packages that are part of
+ // a system module, patch_module names the module that your sources and
+ // dependencies should be patched into. The Android runtime currently
+ // doesn't implement the JEP 261 module system so this option is only
+ // supported at compile time. It should only be needed to compile tests in
+ // packages that exist in libcore and which are inconvenient to move
+ // elsewhere.
+ Patch_module *string `android:"arch_variant"`
+
+ Jacoco struct {
+ // List of classes to include for instrumentation with jacoco to collect coverage
+ // information at runtime when building with coverage enabled. If unset defaults to all
+ // classes.
+ // Supports '*' as the last character of an entry in the list as a wildcard match.
+ // If preceded by '.' it matches all classes in the package and subpackages, otherwise
+ // it matches classes in the package that have the class name as a prefix.
+ Include_filter []string
+
+ // List of classes to exclude from instrumentation with jacoco to collect coverage
+ // information at runtime when building with coverage enabled. Overrides classes selected
+ // by the include_filter property.
+ // Supports '*' as the last character of an entry in the list as a wildcard match.
+ // If preceded by '.' it matches all classes in the package and subpackages, otherwise
+ // it matches classes in the package that have the class name as a prefix.
+ Exclude_filter []string
+ }
+
+ Errorprone struct {
+ // List of javac flags that should only be used when running errorprone.
+ Javacflags []string
+
+ // List of java_plugin modules that provide extra errorprone checks.
+ Extra_check_modules []string
+ }
+
+ Proto struct {
+ // List of extra options that will be passed to the proto generator.
+ Output_params []string
+ }
+
+ Instrument bool `blueprint:"mutated"`
+
+ // List of files to include in the META-INF/services folder of the resulting jar.
+ Services []string `android:"path,arch_variant"`
+
+ // If true, package the kotlin stdlib into the jar. Defaults to true.
+ Static_kotlin_stdlib *bool `android:"arch_variant"`
+
+ // A list of java_library instances that provide additional hiddenapi annotations for the library.
+ Hiddenapi_additional_annotations []string
+}
+
+// Properties that are specific to device modules. Host module factories should not add these when
+// constructing a new module.
+type DeviceProperties struct {
+ // if not blank, set to the version of the sdk to compile against.
+ // Defaults to compiling against the current platform.
+ Sdk_version *string
+
+ // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
+ // Defaults to sdk_version if not set.
+ Min_sdk_version *string
+
+ // if not blank, set the targetSdkVersion in the AndroidManifest.xml.
+ // Defaults to sdk_version if not set.
+ Target_sdk_version *string
+
+ // Whether to compile against the platform APIs instead of an SDK.
+ // If true, then sdk_version must be empty. The value of this field
+ // is ignored when module's type isn't android_app.
+ Platform_apis *bool
+
+ Aidl struct {
+ // Top level directories to pass to aidl tool
+ Include_dirs []string
+
+ // Directories rooted at the Android.bp file to pass to aidl tool
+ Local_include_dirs []string
+
+ // directories that should be added as include directories for any aidl sources of modules
+ // that depend on this module, as well as to aidl for this module.
+ Export_include_dirs []string
+
+ // whether to generate traces (for systrace) for this interface
+ Generate_traces *bool
+
+ // whether to generate Binder#GetTransaction name method.
+ Generate_get_transaction_name *bool
+
+ // list of flags that will be passed to the AIDL compiler
+ Flags []string
+ }
+
+ // If true, export a copy of the module as a -hostdex module for host testing.
+ Hostdex *bool
+
+ Target struct {
+ Hostdex struct {
+ // Additional required dependencies to add to -hostdex modules.
+ Required []string
+ }
+ }
+
+ // When targeting 1.9 and above, override the modules to use with --system,
+ // otherwise provides defaults libraries to add to the bootclasspath.
+ System_modules *string
+
+ // The name of the module as used in build configuration.
+ //
+ // Allows a library to separate its actual name from the name used in
+ // build configuration, e.g.ctx.Config().BootJars().
+ ConfigurationName *string `blueprint:"mutated"`
+
+ // set the name of the output
+ Stem *string
+
+ IsSDKLibrary bool `blueprint:"mutated"`
+
+ // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
+ // Defaults to false.
+ V4_signature *bool
+
+ // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
+ // public stubs library.
+ SyspropPublicStub string `blueprint:"mutated"`
+}
+
+// Functionality common to Module and Import
+//
+// It is embedded in Module so its functionality can be used by methods in Module
+// but it is currently only initialized by Import and Library.
+type embeddableInModuleAndImport struct {
+
+ // Functionality related to this being used as a component of a java_sdk_library.
+ EmbeddableSdkLibraryComponent
+}
+
+func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
+ e.initSdkLibraryComponent(moduleBase)
+}
+
+// Module/Import's DepIsInSameApex(...) delegates to this method.
+//
+// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
+// the one provided by ApexModuleBase.
+func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ // dependencies other than the static linkage are all considered crossing APEX boundary
+ if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
+ return true
+ }
+ return false
+}
+
+// Module contains the properties and members used by all java module types
+type Module struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.ApexModuleBase
+ android.SdkBase
+
+ // Functionality common to Module and Import.
+ embeddableInModuleAndImport
+
+ properties CommonProperties
+ protoProperties android.ProtoProperties
+ deviceProperties DeviceProperties
+
+ // jar file containing header classes including static library dependencies, suitable for
+ // inserting into the bootclasspath/classpath of another compile
+ headerJarFile android.Path
+
+ // jar file containing implementation classes including static library dependencies but no
+ // resources
+ implementationJarFile android.Path
+
+ // jar file containing only resources including from static library dependencies
+ resourceJar android.Path
+
+ // args and dependencies to package source files into a srcjar
+ srcJarArgs []string
+ srcJarDeps android.Paths
+
+ // jar file containing implementation classes and resources including static library
+ // dependencies
+ implementationAndResourcesJar android.Path
+
+ // output file containing classes.dex and resources
+ dexJarFile android.Path
+
+ // output file containing uninstrumented classes that will be instrumented by jacoco
+ jacocoReportClassesFile android.Path
+
+ // output file of the module, which may be a classes jar or a dex jar
+ outputFile android.Path
+ extraOutputFiles android.Paths
+
+ exportAidlIncludeDirs android.Paths
+
+ logtagsSrcs android.Paths
+
+ // installed file for binary dependency
+ installFile android.Path
+
+ // list of .java files and srcjars that was passed to javac
+ compiledJavaSrcs android.Paths
+ compiledSrcJars android.Paths
+
+ // manifest file to use instead of properties.Manifest
+ overrideManifest android.OptionalPath
+
+ // map of SDK version to class loader context
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+
+ // list of plugins that this java module is exporting
+ exportedPluginJars android.Paths
+
+ // list of plugins that this java module is exporting
+ exportedPluginClasses []string
+
+ // if true, the exported plugins generate API and require disabling turbine.
+ exportedDisableTurbine bool
+
+ // list of source files, collected from srcFiles with unique java and all kt files,
+ // will be used by android.IDEInfo struct
+ expandIDEInfoCompiledSrcs []string
+
+ // expanded Jarjar_rules
+ expandJarjarRules android.Path
+
+ // list of additional targets for checkbuild
+ additionalCheckedModules android.Paths
+
+ // Extra files generated by the module type to be added as java resources.
+ extraResources android.Paths
+
+ hiddenAPI
+ dexer
+ dexpreopter
+ usesLibrary
+ linter
+
+ // list of the xref extraction files
+ kytheFiles android.Paths
+
+ // Collect the module directory for IDE info in java/jdeps.go.
+ modulePaths []string
+
+ hideApexVariantFromMake bool
+}
+
+func (j *Module) CheckStableSdkVersion() error {
+ sdkVersion := j.sdkVersion()
+ if sdkVersion.stable() {
+ return nil
+ }
+ if sdkVersion.kind == sdkCorePlatform {
+ if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
+ return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
+ } else {
+ // Treat stable core platform as stable.
+ return nil
+ }
+ } else {
+ return fmt.Errorf("non stable SDK %v", sdkVersion)
+ }
+}
+
+// checkSdkVersions enforces restrictions around SDK dependencies.
+func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
+ if j.RequiresStableAPIs(ctx) {
+ if sc, ok := ctx.Module().(sdkContext); ok {
+ if !sc.sdkVersion().specified() {
+ ctx.PropertyErrorf("sdk_version",
+ "sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
+ }
+ }
+ }
+
+ // Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
+ // See rank() for details.
+ ctx.VisitDirectDeps(func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ switch module.(type) {
+ // TODO(satayev): cover other types as well, e.g. imports
+ case *Library, *AndroidLibrary:
+ switch tag {
+ case bootClasspathTag, libTag, staticLibTag, java9LibTag:
+ j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
+ }
+ }
+ })
+}
+
+func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
+ if sc, ok := ctx.Module().(sdkContext); ok {
+ usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
+ sdkVersionSpecified := sc.sdkVersion().specified()
+ if usePlatformAPI && sdkVersionSpecified {
+ ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
+ } else if !usePlatformAPI && !sdkVersionSpecified {
+ ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
+ }
+
+ }
+}
+
+func (j *Module) addHostProperties() {
+ j.AddProperties(
+ &j.properties,
+ &j.protoProperties,
+ &j.usesLibraryProperties,
+ )
+}
+
+func (j *Module) addHostAndDeviceProperties() {
+ j.addHostProperties()
+ j.AddProperties(
+ &j.deviceProperties,
+ &j.dexer.dexProperties,
+ &j.dexpreoptProperties,
+ &j.linter.properties,
+ )
+}
+
+func (j *Module) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
+ case android.DefaultDistTag:
+ return android.Paths{j.outputFile}, nil
+ case ".jar":
+ return android.Paths{j.implementationAndResourcesJar}, nil
+ case ".proguard_map":
+ if j.dexer.proguardDictionary.Valid() {
+ return android.Paths{j.dexer.proguardDictionary.Path()}, nil
+ }
+ return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+var _ android.OutputFileProducer = (*Module)(nil)
+
+func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
+ initJavaModule(module, hod, false)
+}
+
+func InitJavaModuleMultiTargets(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
+ initJavaModule(module, hod, true)
+}
+
+func initJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported, multiTargets bool) {
+ multilib := android.MultilibCommon
+ if multiTargets {
+ android.InitAndroidMultiTargetsArchModule(module, hod, multilib)
+ } else {
+ android.InitAndroidArchModule(module, hod, multilib)
+ }
+ android.InitDefaultableModule(module)
+}
+
+func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
+ return j.properties.Instrument &&
+ ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
+ ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
+}
+
+func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
+ return j.shouldInstrument(ctx) &&
+ (ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") ||
+ ctx.Config().UnbundledBuild())
+}
+
+func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
+ // Force enable the instrumentation for java code that is built for APEXes ...
+ // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
+ // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+ if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
+ if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
+ return true
+ } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ return true
+ }
+ }
+ return false
+}
+
+func (j *Module) sdkVersion() sdkSpec {
+ return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
+}
+
+func (j *Module) systemModules() string {
+ return proptools.String(j.deviceProperties.System_modules)
+}
+
+func (j *Module) minSdkVersion() sdkSpec {
+ if j.deviceProperties.Min_sdk_version != nil {
+ return sdkSpecFrom(*j.deviceProperties.Min_sdk_version)
+ }
+ return j.sdkVersion()
+}
+
+func (j *Module) targetSdkVersion() sdkSpec {
+ if j.deviceProperties.Target_sdk_version != nil {
+ return sdkSpecFrom(*j.deviceProperties.Target_sdk_version)
+ }
+ return j.sdkVersion()
+}
+
+func (j *Module) MinSdkVersion() string {
+ return j.minSdkVersion().version.String()
+}
+
+func (j *Module) AvailableFor(what string) bool {
+ if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
+ // Exception: for hostdex: true libraries, the platform variant is created
+ // even if it's not marked as available to platform. In that case, the platform
+ // variant is used only for the hostdex and not installed to the device.
+ return true
+ }
+ return j.ApexModuleBase.AvailableFor(what)
+}
+
+func (j *Module) deps(ctx android.BottomUpMutatorContext) {
+ if ctx.Device() {
+ j.linter.deps(ctx)
+
+ sdkDeps(ctx, sdkContext(j), j.dexer)
+
+ if j.deviceProperties.SyspropPublicStub != "" {
+ // This is a sysprop implementation library that has a corresponding sysprop public
+ // stubs library, and a dependency on it so that dependencies on the implementation can
+ // be forwarded to the public stubs library when necessary.
+ ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub)
+ }
+ }
+
+ libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
+
+ // Add dependency on libraries that provide additional hidden api annotations.
+ ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
+
+ if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
+ // Require java_sdk_library at inter-partition java dependency to ensure stable
+ // interface between partitions. If inter-partition java_library dependency is detected,
+ // raise build error because java_library doesn't have a stable interface.
+ //
+ // Inputs:
+ // PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
+ // if true, enable enforcement
+ // PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
+ // exception list of java_library names to allow inter-partition dependency
+ for idx := range j.properties.Libs {
+ if libDeps[idx] == nil {
+ continue
+ }
+
+ if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
+ // java_sdk_library is always allowed at inter-partition dependency.
+ // So, skip check.
+ if _, ok := javaDep.(*SdkLibrary); ok {
+ continue
+ }
+
+ j.checkPartitionsForJavaDependency(ctx, "libs", javaDep)
+ }
+ }
+ }
+
+ // For library dependencies that are component libraries (like stubs), add the implementation
+ // as a dependency (dexpreopt needs to be against the implementation library, not stubs).
+ for _, dep := range libDeps {
+ if dep != nil {
+ if component, ok := dep.(SdkLibraryComponentDependency); ok {
+ if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
+ ctx.AddVariationDependencies(nil, usesLibTag, *lib)
+ }
+ }
+ }
+ }
+
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...)
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
+
+ android.ProtoDeps(ctx, &j.protoProperties)
+ if j.hasSrcExt(".proto") {
+ protoDeps(ctx, &j.protoProperties)
+ }
+
+ if j.hasSrcExt(".kt") {
+ // TODO(ccross): move this to a mutator pass that can tell if generated sources contain
+ // Kotlin files
+ ctx.AddVariationDependencies(nil, kotlinStdlibTag,
+ "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
+ if len(j.properties.Plugins) > 0 {
+ ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
+ }
+ }
+
+ // Framework libraries need special handling in static coverage builds: they should not have
+ // static dependency on jacoco, otherwise there would be multiple conflicting definitions of
+ // the same jacoco classes coming from different bootclasspath jars.
+ if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
+ if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ j.properties.Instrument = true
+ }
+ } else if j.shouldInstrumentStatic(ctx) {
+ ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
+ }
+}
+
+func hasSrcExt(srcs []string, ext string) bool {
+ for _, src := range srcs {
+ if filepath.Ext(src) == ext {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (j *Module) hasSrcExt(ext string) bool {
+ return hasSrcExt(j.properties.Srcs, ext)
+}
+
+func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
+ aidlIncludeDirs android.Paths) (string, android.Paths) {
+
+ aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
+ aidlIncludes = append(aidlIncludes,
+ android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)...)
+ aidlIncludes = append(aidlIncludes,
+ android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)
+
+ var flags []string
+ var deps android.Paths
+
+ flags = append(flags, j.deviceProperties.Aidl.Flags...)
+
+ if aidlPreprocess.Valid() {
+ flags = append(flags, "-p"+aidlPreprocess.String())
+ deps = append(deps, aidlPreprocess.Path())
+ } else if len(aidlIncludeDirs) > 0 {
+ flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
+ }
+
+ if len(j.exportAidlIncludeDirs) > 0 {
+ flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
+ }
+
+ if len(aidlIncludes) > 0 {
+ flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
+ }
+
+ flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
+ if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
+ flags = append(flags, "-I"+src.String())
+ }
+
+ if Bool(j.deviceProperties.Aidl.Generate_traces) {
+ flags = append(flags, "-t")
+ }
+
+ if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) {
+ flags = append(flags, "--transaction_names")
+ }
+
+ return strings.Join(flags, " "), deps
+}
+
+func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
+
+ var flags javaBuilderFlags
+
+ // javaVersion flag.
+ flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
+
+ if ctx.Config().RunErrorProne() {
+ if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
+ ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
+ }
+
+ errorProneFlags := []string{
+ "-Xplugin:ErrorProne",
+ "${config.ErrorProneChecks}",
+ }
+ errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...)
+
+ flags.errorProneExtraJavacFlags = "${config.ErrorProneFlags} " +
+ "'" + strings.Join(errorProneFlags, " ") + "'"
+ flags.errorProneProcessorPath = classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
+ }
+
+ // classpath
+ flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
+ flags.classpath = append(flags.classpath, deps.classpath...)
+ flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
+ flags.processorPath = append(flags.processorPath, deps.processorPath...)
+ flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...)
+
+ flags.processors = append(flags.processors, deps.processorClasses...)
+ flags.processors = android.FirstUniqueStrings(flags.processors)
+
+ if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
+ decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() {
+ // Give host-side tools a version of OpenJDK's standard libraries
+ // close to what they're targeting. As of Dec 2017, AOSP is only
+ // bundling OpenJDK 8 and 9, so nothing < 8 is available.
+ //
+ // When building with OpenJDK 8, the following should have no
+ // effect since those jars would be available by default.
+ //
+ // When building with OpenJDK 9 but targeting a version < 1.8,
+ // putting them on the bootclasspath means that:
+ // a) code can't (accidentally) refer to OpenJDK 9 specific APIs
+ // b) references to existing APIs are not reinterpreted in an
+ // OpenJDK 9-specific way, eg. calls to subclasses of
+ // java.nio.Buffer as in http://b/70862583
+ java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
+ flags.bootClasspath = append(flags.bootClasspath,
+ android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"),
+ android.PathForSource(ctx, java8Home, "jre/lib/rt.jar"))
+ if Bool(j.properties.Use_tools_jar) {
+ flags.bootClasspath = append(flags.bootClasspath,
+ android.PathForSource(ctx, java8Home, "lib/tools.jar"))
+ }
+ }
+
+ // systemModules
+ flags.systemModules = deps.systemModules
+
+ // aidl flags.
+ flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
+
+ return flags
+}
+
+func (j *Module) collectJavacFlags(
+ ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
+ // javac flags.
+ javacFlags := j.properties.Javacflags
+
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ // For non-host binaries, override the -g flag passed globally to remove
+ // local variable debug info to reduce disk and memory usage.
+ javacFlags = append(javacFlags, "-g:source,lines")
+ }
+ javacFlags = append(javacFlags, "-Xlint:-dep-ann")
+
+ if flags.javaVersion.usesJavaModules() {
+ javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+
+ if j.properties.Patch_module != nil {
+ // Manually specify build directory in case it is not under the repo root.
+ // (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
+ // just adding a symlink under the root doesn't help.)
+ patchPaths := []string{".", ctx.Config().BuildDir()}
+
+ // b/150878007
+ //
+ // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
+ // execution root for --patch-module. If this javac command line is
+ // invoked within Bazel's execution root working directory, the top
+ // level directories (e.g. libcore/, tools/, frameworks/) are all
+ // symlinks. JDK9 javac does not traverse into symlinks, which causes
+ // --patch-module to fail source file lookups when invoked in the
+ // execution root.
+ //
+ // Short of patching javac or enumerating *all* directories as possible
+ // input dirs, manually add the top level dir of the source files to be
+ // compiled.
+ topLevelDirs := map[string]bool{}
+ for _, srcFilePath := range srcFiles {
+ srcFileParts := strings.Split(srcFilePath.String(), "/")
+ // Ignore source files that are already in the top level directory
+ // as well as generated files in the out directory. The out
+ // directory may be an absolute path, which means srcFileParts[0] is the
+ // empty string, so check that as well. Note that "out" in Bazel's execution
+ // root is *not* a symlink, which doesn't cause problems for --patch-modules
+ // anyway, so it's fine to not apply this workaround for generated
+ // source files.
+ if len(srcFileParts) > 1 &&
+ srcFileParts[0] != "" &&
+ srcFileParts[0] != "out" {
+ topLevelDirs[srcFileParts[0]] = true
+ }
+ }
+ patchPaths = append(patchPaths, android.SortedStringKeys(topLevelDirs)...)
+
+ classPath := flags.classpath.FormJavaClassPath("")
+ if classPath != "" {
+ patchPaths = append(patchPaths, classPath)
+ }
+ javacFlags = append(
+ javacFlags,
+ "--patch-module="+String(j.properties.Patch_module)+"="+strings.Join(patchPaths, ":"))
+ }
+ }
+
+ if len(javacFlags) > 0 {
+ // optimization.
+ ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
+ flags.javacFlags = "$javacFlags"
+ }
+
+ return flags
+}
+
+func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
+ j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
+
+ deps := j.collectDeps(ctx)
+ flags := j.collectBuilderFlags(ctx, deps)
+
+ if flags.javaVersion.usesJavaModules() {
+ j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
+ }
+ srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+ if hasSrcExt(srcFiles.Strings(), ".proto") {
+ flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
+ }
+
+ kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
+ if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
+ ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
+ }
+
+ srcFiles = j.genSources(ctx, srcFiles, flags)
+
+ // Collect javac flags only after computing the full set of srcFiles to
+ // ensure that the --patch-module lookup paths are complete.
+ flags = j.collectJavacFlags(ctx, flags, srcFiles)
+
+ srcJars := srcFiles.FilterByExt(".srcjar")
+ srcJars = append(srcJars, deps.srcJars...)
+ if aaptSrcJar != nil {
+ srcJars = append(srcJars, aaptSrcJar)
+ }
+
+ if j.properties.Jarjar_rules != nil {
+ j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+ }
+
+ jarName := ctx.ModuleName() + ".jar"
+
+ javaSrcFiles := srcFiles.FilterByExt(".java")
+ var uniqueSrcFiles android.Paths
+ set := make(map[string]bool)
+ for _, v := range javaSrcFiles {
+ if _, found := set[v.String()]; !found {
+ set[v.String()] = true
+ uniqueSrcFiles = append(uniqueSrcFiles, v)
+ }
+ }
+
+ // Collect .java files for AIDEGen
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
+
+ var kotlinJars android.Paths
+
+ if srcFiles.HasExt(".kt") {
+ // user defined kotlin flags.
+ kotlincFlags := j.properties.Kotlincflags
+ CheckKotlincFlags(ctx, kotlincFlags)
+
+ // Dogfood the JVM_IR backend.
+ kotlincFlags = append(kotlincFlags, "-Xuse-ir")
+
+ // If there are kotlin files, compile them first but pass all the kotlin and java files
+ // kotlinc will use the java files to resolve types referenced by the kotlin files, but
+ // won't emit any classes for them.
+ kotlincFlags = append(kotlincFlags, "-no-stdlib")
+ if ctx.Device() {
+ kotlincFlags = append(kotlincFlags, "-no-jdk")
+ }
+ if len(kotlincFlags) > 0 {
+ // optimization.
+ ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
+ flags.kotlincFlags += "$kotlincFlags"
+ }
+
+ var kotlinSrcFiles android.Paths
+ kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
+ kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
+
+ // Collect .kt files for AIDEGen
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
+
+ flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
+ flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
+
+ flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
+ flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
+
+ if len(flags.processorPath) > 0 {
+ // Use kapt for annotation processing
+ kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
+ kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
+ kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ srcJars = append(srcJars, kaptSrcJar)
+ kotlinJars = append(kotlinJars, kaptResJar)
+ // Disable annotation processing in javac, it's already been handled by kapt
+ flags.processorPath = nil
+ flags.processors = nil
+ }
+
+ kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
+ kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ if ctx.Failed() {
+ return
+ }
+
+ // Make javac rule depend on the kotlinc rule
+ flags.classpath = append(flags.classpath, kotlinJar)
+
+ kotlinJars = append(kotlinJars, kotlinJar)
+ // Jar kotlin classes into the final jar after javac
+ if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
+ kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
+ }
+ }
+
+ jars := append(android.Paths(nil), kotlinJars...)
+
+ // Store the list of .java files that was passed to javac
+ j.compiledJavaSrcs = uniqueSrcFiles
+ j.compiledSrcJars = srcJars
+
+ enableSharding := false
+ var headerJarFileWithoutJarjar android.Path
+ if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
+ if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
+ enableSharding = true
+ // Formerly, there was a check here that prevented annotation processors
+ // from being used when sharding was enabled, as some annotation processors
+ // do not function correctly in sharded environments. It was removed to
+ // allow for the use of annotation processors that do function correctly
+ // with sharding enabled. See: b/77284273.
+ }
+ headerJarFileWithoutJarjar, j.headerJarFile =
+ j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
+ if ctx.Failed() {
+ return
+ }
+ }
+ if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
+ var extraJarDeps android.Paths
+ if ctx.Config().RunErrorProne() {
+ // If error-prone is enabled, add an additional rule to compile the java files into
+ // a separate set of classes (so that they don't overwrite the normal ones and require
+ // a rebuild when error-prone is turned off).
+ // TODO(ccross): Once we always compile with javac9 we may be able to conditionally
+ // enable error-prone without affecting the output class files.
+ errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+ RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
+ extraJarDeps = append(extraJarDeps, errorprone)
+ }
+
+ if enableSharding {
+ flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
+ shardSize := int(*(j.properties.Javac_shard_size))
+ var shardSrcs []android.Paths
+ if len(uniqueSrcFiles) > 0 {
+ shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
+ for idx, shardSrc := range shardSrcs {
+ classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
+ nil, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
+ }
+ if len(srcJars) > 0 {
+ classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
+ nil, srcJars, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
+ } else {
+ classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
+ if ctx.Failed() {
+ return
+ }
+ }
+
+ j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
+
+ var includeSrcJar android.WritablePath
+ if Bool(j.properties.Include_srcs) {
+ includeSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+".srcjar")
+ TransformResourcesToJar(ctx, includeSrcJar, j.srcJarArgs, j.srcJarDeps)
+ }
+
+ dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs,
+ j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources)
+ fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources)
+ extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources
+
+ var resArgs []string
+ var resDeps android.Paths
+
+ resArgs = append(resArgs, dirArgs...)
+ resDeps = append(resDeps, dirDeps...)
+
+ resArgs = append(resArgs, fileArgs...)
+ resDeps = append(resDeps, fileDeps...)
+
+ resArgs = append(resArgs, extraArgs...)
+ resDeps = append(resDeps, extraDeps...)
+
+ if len(resArgs) > 0 {
+ resourceJar := android.PathForModuleOut(ctx, "res", jarName)
+ TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
+ j.resourceJar = resourceJar
+ if ctx.Failed() {
+ return
+ }
+ }
+
+ var resourceJars android.Paths
+ if j.resourceJar != nil {
+ resourceJars = append(resourceJars, j.resourceJar)
+ }
+ if Bool(j.properties.Include_srcs) {
+ resourceJars = append(resourceJars, includeSrcJar)
+ }
+ resourceJars = append(resourceJars, deps.staticResourceJars...)
+
+ if len(resourceJars) > 1 {
+ combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
+ false, nil, nil)
+ j.resourceJar = combinedJar
+ } else if len(resourceJars) == 1 {
+ j.resourceJar = resourceJars[0]
+ }
+
+ if len(deps.staticJars) > 0 {
+ jars = append(jars, deps.staticJars...)
+ }
+
+ manifest := j.overrideManifest
+ if !manifest.Valid() && j.properties.Manifest != nil {
+ manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest))
+ }
+
+ services := android.PathsForModuleSrc(ctx, j.properties.Services)
+ if len(services) > 0 {
+ servicesJar := android.PathForModuleOut(ctx, "services", jarName)
+ var zipargs []string
+ for _, file := range services {
+ serviceFile := file.String()
+ zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile)
+ }
+ rule := zip
+ args := map[string]string{
+ "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
+ }
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ZIP") {
+ rule = zipRE
+ args["implicits"] = strings.Join(services.Strings(), ",")
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Output: servicesJar,
+ Implicits: services,
+ Args: args,
+ })
+ jars = append(jars, servicesJar)
+ }
+
+ // Combine the classes built from sources, any manifests, and any static libraries into
+ // classes.jar. If there is only one input jar this step will be skipped.
+ var outputFile android.OutputPath
+
+ if len(jars) == 1 && !manifest.Valid() {
+ // Optimization: skip the combine step as there is nothing to do
+ // TODO(ccross): this leaves any module-info.class files, but those should only come from
+ // prebuilt dependencies until we support modules in the platform build, so there shouldn't be
+ // any if len(jars) == 1.
+
+ // Transform the single path to the jar into an OutputPath as that is required by the following
+ // code.
+ if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
+ // The path contains an embedded OutputPath so reuse that.
+ outputFile = moduleOutPath.OutputPath
+ } else if outputPath, ok := jars[0].(android.OutputPath); ok {
+ // The path is an OutputPath so reuse it directly.
+ outputFile = outputPath
+ } else {
+ // The file is not in the out directory so create an OutputPath into which it can be copied
+ // and which the following code can use to refer to it.
+ combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: jars[0],
+ Output: combinedJar,
+ })
+ outputFile = combinedJar.OutputPath
+ }
+ } else {
+ combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
+ false, nil, nil)
+ outputFile = combinedJar.OutputPath
+ }
+
+ // jarjar implementation jar if necessary
+ if j.expandJarjarRules != nil {
+ // Transform classes.jar into classes-jarjar.jar
+ jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName).OutputPath
+ TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
+ outputFile = jarjarFile
+
+ // jarjar resource jar if necessary
+ if j.resourceJar != nil {
+ resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName)
+ TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules)
+ j.resourceJar = resourceJarJarFile
+ }
+
+ if ctx.Failed() {
+ return
+ }
+ }
+
+ // Check package restrictions if necessary.
+ if len(j.properties.Permitted_packages) > 0 {
+ // Check packages and copy to package-checked file.
+ pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")
+ CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
+ j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile)
+
+ if ctx.Failed() {
+ return
+ }
+ }
+
+ j.implementationJarFile = outputFile
+ if j.headerJarFile == nil {
+ j.headerJarFile = j.implementationJarFile
+ }
+
+ if j.shouldInstrumentInApex(ctx) {
+ j.properties.Instrument = true
+ }
+
+ if j.shouldInstrument(ctx) {
+ outputFile = j.instrument(ctx, flags, outputFile, jarName)
+ }
+
+ // merge implementation jar with resources if necessary
+ implementationAndResourcesJar := outputFile
+ if j.resourceJar != nil {
+ jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
+ false, nil, nil)
+ implementationAndResourcesJar = combinedJar
+ }
+
+ j.implementationAndResourcesJar = implementationAndResourcesJar
+
+ // Enable dex compilation for the APEX variants, unless it is disabled explicitly
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
+ if j.dexProperties.Compile_dex == nil {
+ j.dexProperties.Compile_dex = proptools.BoolPtr(true)
+ }
+ if j.deviceProperties.Hostdex == nil {
+ j.deviceProperties.Hostdex = proptools.BoolPtr(true)
+ }
+ }
+
+ if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if j.hasCode(ctx) {
+ if j.shouldInstrumentStatic(ctx) {
+ j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
+ }
+ // Dex compilation
+ var dexOutputFile android.OutputPath
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ if ctx.Failed() {
+ return
+ }
+
+ // Hidden API CSV generation and dex encoding
+ dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
+ proptools.Bool(j.dexProperties.Uncompress_dex))
+
+ // merge dex jar with resources if necessary
+ if j.resourceJar != nil {
+ jars := android.Paths{dexOutputFile, j.resourceJar}
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
+ TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ if *j.dexProperties.Uncompress_dex {
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ dexOutputFile = combinedAlignedJar
+ } else {
+ dexOutputFile = combinedJar
+ }
+ }
+
+ j.dexJarFile = dexOutputFile
+
+ // Dexpreopting
+ j.dexpreopt(ctx, dexOutputFile)
+
+ outputFile = dexOutputFile
+ } else {
+ // There is no code to compile into a dex jar, make sure the resources are propagated
+ // to the APK if this is an app.
+ outputFile = implementationAndResourcesJar
+ j.dexJarFile = j.resourceJar
+ }
+
+ if ctx.Failed() {
+ return
+ }
+ } else {
+ outputFile = implementationAndResourcesJar
+ }
+
+ if ctx.Device() {
+ lintSDKVersionString := func(sdkSpec sdkSpec) string {
+ if v := sdkSpec.version; v.isNumbered() {
+ return v.String()
+ } else {
+ return ctx.Config().DefaultAppTargetSdk(ctx).String()
+ }
+ }
+
+ j.linter.name = ctx.ModuleName()
+ j.linter.srcs = srcFiles
+ j.linter.srcJars = srcJars
+ j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
+ j.linter.classes = j.implementationJarFile
+ j.linter.minSdkVersion = lintSDKVersionString(j.minSdkVersion())
+ j.linter.targetSdkVersion = lintSDKVersionString(j.targetSdkVersion())
+ j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
+ j.linter.javaLanguageLevel = flags.javaVersion.String()
+ j.linter.kotlinLanguageLevel = "1.3"
+ if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
+ j.linter.buildModuleReportZip = true
+ }
+ j.linter.lint(ctx)
+ }
+
+ ctx.CheckbuildFile(outputFile)
+
+ ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
+ ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
+ ResourceJars: android.PathsIfNonNil(j.resourceJar),
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ SrcJarArgs: j.srcJarArgs,
+ SrcJarDeps: j.srcJarDeps,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ JacocoReportClassesFile: j.jacocoReportClassesFile,
+ })
+
+ // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
+ j.outputFile = outputFile.WithoutRel()
+}
+
+func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
+
+ kzipName := pathtools.ReplaceExtension(jarName, "kzip")
+ if idx >= 0 {
+ kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
+ jarName += strconv.Itoa(idx)
+ }
+
+ classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
+ TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
+
+ if ctx.Config().EmitXrefRules() {
+ extractionFile := android.PathForModuleOut(ctx, kzipName)
+ emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
+ j.kytheFiles = append(j.kytheFiles, extractionFile)
+ }
+
+ return classes
+}
+
+// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
+// since some of these flags may be used internally.
+func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
+ for _, flag := range flags {
+ flag = strings.TrimSpace(flag)
+
+ if !strings.HasPrefix(flag, "-") {
+ ctx.PropertyErrorf("kotlincflags", "Flag `%s` must start with `-`", flag)
+ } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
+ ctx.PropertyErrorf("kotlincflags",
+ "Bad flag: `%s`, only use internal compiler for consistency.", flag)
+ } else if inList(flag, config.KotlincIllegalFlags) {
+ ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
+ } else if flag == "-include-runtime" {
+ ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
+ } else {
+ args := strings.Split(flag, " ")
+ if args[0] == "-kotlin-home" {
+ ctx.PropertyErrorf("kotlincflags",
+ "Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo).", flag)
+ }
+ }
+ }
+}
+
+func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
+ deps deps, flags javaBuilderFlags, jarName string,
+ extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
+
+ var jars android.Paths
+ if len(srcFiles) > 0 || len(srcJars) > 0 {
+ // Compile java sources into turbine.jar.
+ turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
+ TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
+ if ctx.Failed() {
+ return nil, nil
+ }
+ jars = append(jars, turbineJar)
+ }
+
+ jars = append(jars, extraJars...)
+
+ // Combine any static header libraries into classes-header.jar. If there is only
+ // one input jar this step will be skipped.
+ jars = append(jars, deps.staticHeaderJars...)
+
+ // we cannot skip the combine step for now if there is only one jar
+ // since we have to strip META-INF/TRANSITIVE dir from turbine.jar
+ combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
+ false, nil, []string{"META-INF/TRANSITIVE"})
+ headerJar = combinedJar
+ jarjarHeaderJar = combinedJar
+
+ if j.expandJarjarRules != nil {
+ // Transform classes.jar into classes-jarjar.jar
+ jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
+ TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
+ jarjarHeaderJar = jarjarFile
+ if ctx.Failed() {
+ return nil, nil
+ }
+ }
+
+ return headerJar, jarjarHeaderJar
+}
+
+func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
+ classesJar android.Path, jarName string) android.OutputPath {
+
+ specs := j.jacocoModuleToZipCommand(ctx)
+
+ jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
+ instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
+
+ jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
+
+ j.jacocoReportClassesFile = jacocoReportClassesFile
+
+ return instrumentedJar
+}
+
+func (j *Module) HeaderJars() android.Paths {
+ if j.headerJarFile == nil {
+ return nil
+ }
+ return android.Paths{j.headerJarFile}
+}
+
+func (j *Module) ImplementationJars() android.Paths {
+ if j.implementationJarFile == nil {
+ return nil
+ }
+ return android.Paths{j.implementationJarFile}
+}
+
+func (j *Module) DexJarBuildPath() android.Path {
+ return j.dexJarFile
+}
+
+func (j *Module) DexJarInstallPath() android.Path {
+ return j.installFile
+}
+
+func (j *Module) ImplementationAndResourcesJars() android.Paths {
+ if j.implementationAndResourcesJar == nil {
+ return nil
+ }
+ return android.Paths{j.implementationAndResourcesJar}
+}
+
+func (j *Module) AidlIncludeDirs() android.Paths {
+ // exportAidlIncludeDirs is type android.Paths already
+ return j.exportAidlIncludeDirs
+}
+
+func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return j.classLoaderContexts
+}
+
+// Collect information for opening IDE project files in java/jdeps.go.
+func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
+ dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
+ dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
+ dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
+ if j.expandJarjarRules != nil {
+ dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
+ }
+ dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
+}
+
+func (j *Module) CompilerDeps() []string {
+ jdeps := []string{}
+ jdeps = append(jdeps, j.properties.Libs...)
+ jdeps = append(jdeps, j.properties.Static_libs...)
+ return jdeps
+}
+
+func (j *Module) hasCode(ctx android.ModuleContext) bool {
+ srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+ return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
+}
+
+// Implements android.ApexModule
+func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+ return j.depIsInSameApex(ctx, dep)
+}
+
+// Implements android.ApexModule
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+ sdkVersion android.ApiLevel) error {
+ sdkSpec := j.minSdkVersion()
+ if !sdkSpec.specified() {
+ return fmt.Errorf("min_sdk_version is not specified")
+ }
+ if sdkSpec.kind == sdkCore {
+ return nil
+ }
+ ver, err := sdkSpec.effectiveVersion(ctx)
+ if err != nil {
+ return err
+ }
+ if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
+ return fmt.Errorf("newer SDK(%v)", ver)
+ }
+ return nil
+}
+
+func (j *Module) Stem() string {
+ return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
+}
+
+// ConfigurationName returns the name of the module as used in build configuration.
+//
+// This is usually the same as BaseModuleName() except for the <x>.impl libraries created by
+// java_sdk_library in which case this is the BaseModuleName() without the ".impl" suffix,
+// i.e. just <x>.
+func (j *Module) ConfigurationName() string {
+ return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName())
+}
+
+func (j *Module) JacocoReportClassesFile() android.Path {
+ return j.jacocoReportClassesFile
+}
+
+func (j *Module) IsInstallable() bool {
+ return Bool(j.properties.Installable)
+}
+
+type sdkLinkType int
+
+const (
+ // TODO(jiyong) rename these for better readability. Make the allowed
+ // and disallowed link types explicit
+ // order is important here. See rank()
+ javaCore sdkLinkType = iota
+ javaSdk
+ javaSystem
+ javaModule
+ javaSystemServer
+ javaPlatform
+)
+
+func (lt sdkLinkType) String() string {
+ switch lt {
+ case javaCore:
+ return "core Java API"
+ case javaSdk:
+ return "Android API"
+ case javaSystem:
+ return "system API"
+ case javaModule:
+ return "module API"
+ case javaSystemServer:
+ return "system server API"
+ case javaPlatform:
+ return "private API"
+ default:
+ panic(fmt.Errorf("unrecognized linktype: %d", lt))
+ }
+}
+
+// rank determines the total order among sdkLinkType. An SDK link type of rank A can link to
+// another SDK link type of rank B only when B <= A. For example, a module linking to Android SDK
+// can't statically depend on modules that use Platform API.
+func (lt sdkLinkType) rank() int {
+ return int(lt)
+}
+
+type moduleWithSdkDep interface {
+ android.Module
+ getSdkLinkType(name string) (ret sdkLinkType, stubs bool)
+}
+
+func (m *Module) getSdkLinkType(name string) (ret sdkLinkType, stubs bool) {
+ switch name {
+ case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ "stub-annotations", "private-stub-annotations-jar",
+ "core-lambda-stubs", "core-generated-annotation-stubs":
+ return javaCore, true
+ case "android_stubs_current":
+ return javaSdk, true
+ case "android_system_stubs_current":
+ return javaSystem, true
+ case "android_module_lib_stubs_current":
+ return javaModule, true
+ case "android_system_server_stubs_current":
+ return javaSystemServer, true
+ case "android_test_stubs_current":
+ return javaSystem, true
+ }
+
+ if stub, linkType := moduleStubLinkType(name); stub {
+ return linkType, true
+ }
+
+ ver := m.sdkVersion()
+ switch ver.kind {
+ case sdkCore:
+ return javaCore, false
+ case sdkSystem:
+ return javaSystem, false
+ case sdkPublic:
+ return javaSdk, false
+ case sdkModule:
+ return javaModule, false
+ case sdkSystemServer:
+ return javaSystemServer, false
+ case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
+ return javaPlatform, false
+ }
+
+ if !ver.valid() {
+ panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
+ }
+ return javaSdk, false
+}
+
+// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
+// this module's. See the comment on rank() for details and an example.
+func (j *Module) checkSdkLinkType(
+ ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) {
+ if ctx.Host() {
+ return
+ }
+
+ myLinkType, stubs := j.getSdkLinkType(ctx.ModuleName())
+ if stubs {
+ return
+ }
+ depLinkType, _ := dep.getSdkLinkType(ctx.OtherModuleName(dep))
+
+ if myLinkType.rank() < depLinkType.rank() {
+ ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+
+ "In order to fix this, consider adjusting sdk_version: OR platform_apis: "+
+ "property of the source or target module so that target module is built "+
+ "with the same or smaller API set when compared to the source.",
+ myLinkType, ctx.OtherModuleName(dep), depLinkType)
+ }
+}
+
+func (j *Module) collectDeps(ctx android.ModuleContext) deps {
+ var deps deps
+
+ if ctx.Device() {
+ sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ if sdkDep.invalidVersion {
+ ctx.AddMissingDependencies(sdkDep.bootclasspath)
+ ctx.AddMissingDependencies(sdkDep.java9Classpath)
+ } else if sdkDep.useFiles {
+ // sdkDep.jar is actually equivalent to turbine header.jar.
+ deps.classpath = append(deps.classpath, sdkDep.jars...)
+ deps.aidlPreprocess = sdkDep.aidl
+ } else {
+ deps.aidlPreprocess = sdkDep.aidl
+ }
+ }
+
+ sdkLinkType, _ := j.getSdkLinkType(ctx.ModuleName())
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ otherName := ctx.OtherModuleName(module)
+ tag := ctx.OtherModuleDependencyTag(module)
+
+ if IsJniDepTag(tag) {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+ if tag == certificateTag {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+
+ if dep, ok := module.(SdkLibraryDependency); ok {
+ switch tag {
+ case libTag:
+ deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ case staticLibTag:
+ ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+ }
+ } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
+ dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if sdkLinkType != javaPlatform &&
+ ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
+ dep = syspropDep.JavaInfo
+ }
+ switch tag {
+ case bootClasspathTag:
+ deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
+ case libTag, instrumentationForTag:
+ deps.classpath = append(deps.classpath, dep.HeaderJars...)
+ deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
+ addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
+ deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+ case java9LibTag:
+ deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
+ case staticLibTag:
+ deps.classpath = append(deps.classpath, dep.HeaderJars...)
+ deps.staticJars = append(deps.staticJars, dep.ImplementationJars...)
+ deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars...)
+ deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars...)
+ deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
+ addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
+ // Turbine doesn't run annotation processors, so any module that uses an
+ // annotation processor that generates API is incompatible with the turbine
+ // optimization.
+ deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+ case pluginTag:
+ if plugin, ok := module.(*Plugin); ok {
+ if plugin.pluginProperties.Processor_class != nil {
+ addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class)
+ } else {
+ addPlugins(&deps, dep.ImplementationAndResourcesJars)
+ }
+ // Turbine doesn't run annotation processors, so any module that uses an
+ // annotation processor that generates API is incompatible with the turbine
+ // optimization.
+ deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
+ } else {
+ ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
+ }
+ case errorpronePluginTag:
+ if _, ok := module.(*Plugin); ok {
+ deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...)
+ } else {
+ ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
+ }
+ case exportedPluginTag:
+ if plugin, ok := module.(*Plugin); ok {
+ j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...)
+ if plugin.pluginProperties.Processor_class != nil {
+ j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
+ }
+ // Turbine doesn't run annotation processors, so any module that uses an
+ // annotation processor that generates API is incompatible with the turbine
+ // optimization.
+ j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api)
+ } else {
+ ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
+ }
+ case kotlinStdlibTag:
+ deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
+ case kotlinAnnotationsTag:
+ deps.kotlinAnnotations = dep.HeaderJars
+ case syspropPublicStubDepTag:
+ // This is a sysprop implementation library, forward the JavaInfoProvider from
+ // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
+ ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ JavaInfo: dep,
+ })
+ }
+ } else if dep, ok := module.(android.SourceFileProducer); ok {
+ switch tag {
+ case libTag:
+ checkProducesJars(ctx, dep)
+ deps.classpath = append(deps.classpath, dep.Srcs()...)
+ case staticLibTag:
+ checkProducesJars(ctx, dep)
+ deps.classpath = append(deps.classpath, dep.Srcs()...)
+ deps.staticJars = append(deps.staticJars, dep.Srcs()...)
+ deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
+ }
+ } else {
+ switch tag {
+ case bootClasspathTag:
+ // If a system modules dependency has been added to the bootclasspath
+ // then add its libs to the bootclasspath.
+ sm := module.(SystemModulesProvider)
+ deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
+
+ case systemModulesTag:
+ if deps.systemModules != nil {
+ panic("Found two system module dependencies")
+ }
+ sm := module.(SystemModulesProvider)
+ outputDir, outputDeps := sm.OutputDirAndDeps()
+ deps.systemModules = &systemModules{outputDir, outputDeps}
+ }
+ }
+
+ addCLCFromDep(ctx, module, j.classLoaderContexts)
+ })
+
+ return deps
+}
+
+func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
+ deps.processorPath = append(deps.processorPath, pluginJars...)
+ deps.processorClasses = append(deps.processorClasses, pluginClasses...)
+}
+
+// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
+// this interface.
+type ProvidesUsesLib interface {
+ ProvidesUsesLib() *string
+}
+
+func (j *Module) ProvidesUsesLib() *string {
+ return j.usesLibraryProperties.Provides_uses_lib
+}
diff --git a/java/builder.go b/java/builder.go
index 33206ce..fc740a8 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -40,7 +40,7 @@
// (if the rule produces .class files) or a .srcjar file (if the rule produces .java files).
// .srcjar files are unzipped into a temporary directory when compiled with javac.
// TODO(b/143658984): goma can't handle the --system argument to javac.
- javac, javacRE = remoteexec.MultiCommandStaticRules(pctx, "javac",
+ javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" "$out" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
@@ -129,7 +129,7 @@
},
"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition")
- turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine",
+ turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
@@ -157,7 +157,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
}, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"})
- jar, jarRE = remoteexec.StaticRules(pctx, "jar",
+ jar, jarRE = pctx.RemoteStaticRules("jar",
blueprint.RuleParams{
Command: `$reTemplate${config.SoongZipCmd} -jar -o $out @$out.rsp`,
CommandDeps: []string{"${config.SoongZipCmd}"},
@@ -172,7 +172,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
}, []string{"jarArgs"}, nil)
- zip, zipRE = remoteexec.StaticRules(pctx, "zip",
+ zip, zipRE = pctx.RemoteStaticRules("zip",
blueprint.RuleParams{
Command: `${config.SoongZipCmd} -o $out @$out.rsp`,
CommandDeps: []string{"${config.SoongZipCmd}"},
@@ -244,7 +244,6 @@
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
- pctx.Import("android/soong/remoteexec")
}
type javaBuilderFlags struct {
diff --git a/java/config/config.go b/java/config/config.go
index 31e2b0f..30c6f91 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -149,14 +149,14 @@
pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen")
- pctx.VariableFunc("REJavaPool", remoteexec.EnvOverrideFunc("RBE_JAVA_POOL", "java16"))
- pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
- pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
- pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy))
- pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
- pctx.VariableFunc("REZipExecStrategy", remoteexec.EnvOverrideFunc("RBE_ZIP_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.StaticVariableWithEnvOverride("REJavaPool", "RBE_JAVA_POOL", "java16")
+ pctx.StaticVariableWithEnvOverride("REJavacExecStrategy", "RBE_JAVAC_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy)
+ pctx.StaticVariableWithEnvOverride("RED8ExecStrategy", "RBE_D8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy)
+ pctx.StaticVariableWithEnvOverride("RER8ExecStrategy", "RBE_R8_EXEC_STRATEGY", remoteexec.RemoteLocalFallbackExecStrategy)
+ pctx.StaticVariableWithEnvOverride("RETurbineExecStrategy", "RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("RESignApkExecStrategy", "RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("REJarExecStrategy", "RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ pctx.StaticVariableWithEnvOverride("REZipExecStrategy", "RBE_ZIP_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar")
diff --git a/java/dex.go b/java/dex.go
index b2a998f..b042f13 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -83,7 +83,7 @@
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
-var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8",
+var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
@@ -111,7 +111,7 @@
},
}, []string{"outDir", "d8Flags", "zipFlags"}, nil)
-var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8",
+var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 1b910fa..aadf6ad 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -44,8 +44,11 @@
`
result := javaFixtureFactory.
- Extend(dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar", "platform:baz")).
- RunTestWithBp(t, bp)
+ Extend(
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar", "platform:baz"),
+ ).RunTestWithBp(t, bp)
dexpreoptBootJars := result.SingletonForTests("dex_bootjars")
rule := dexpreoptBootJars.Output(ruleFile)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index da13c62..a892b36 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1235,7 +1235,7 @@
ToolchainInputs: []string{config.JavaCmd(ctx).String()},
Platform: map[string]string{remoteexec.PoolKey: pool},
EnvironmentVariables: []string{"ANDROID_SDK_HOME"},
- }).NoVarTemplate(ctx.Config()))
+ }).NoVarTemplate(ctx.Config().RBEWrapper()))
}
cmd.BuiltTool("metalava").
@@ -1678,14 +1678,17 @@
func zipSyncCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
srcJarDir android.ModuleOutPath, srcJars android.Paths) android.OutputPath {
- rule.Command().Text("rm -rf").Text(srcJarDir.String())
- rule.Command().Text("mkdir -p").Text(srcJarDir.String())
+ cmd := rule.Command()
+ cmd.Text("rm -rf").Text(cmd.PathForOutput(srcJarDir))
+ cmd = rule.Command()
+ cmd.Text("mkdir -p").Text(cmd.PathForOutput(srcJarDir))
srcJarList := srcJarDir.Join(ctx, "list")
rule.Temporary(srcJarList)
- rule.Command().BuiltTool("zipsync").
- FlagWithArg("-d ", srcJarDir.String()).
+ cmd = rule.Command()
+ cmd.BuiltTool("zipsync").
+ FlagWithArg("-d ", cmd.PathForOutput(srcJarDir)).
FlagWithOutput("-l ", srcJarList).
FlagWithArg("-f ", `"*.java"`).
Inputs(srcJars)
diff --git a/java/gen.go b/java/gen.go
index 4f928d5..445a2d8 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -174,6 +174,12 @@
logtags() android.Paths
}
+func (j *Module) logtags() android.Paths {
+ return j.logtagsSrcs
+}
+
+var _ logtagsProducer = (*Module)(nil)
+
type logtagsSingleton struct{}
func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
diff --git a/java/java.go b/java/java.go
index 8c714ee..9786947 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,11 +21,9 @@
import (
"fmt"
"path/filepath"
- "strconv"
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -122,441 +120,6 @@
}
-// TODO:
-// Autogenerated files:
-// Renderscript
-// Post-jar passes:
-// Proguard
-// Rmtypedefs
-// DroidDoc
-// Findbugs
-
-// Properties that are common to most Java modules, i.e. whether it's a host or device module.
-type CommonProperties struct {
- // list of source files used to compile the Java module. May be .java, .kt, .logtags, .proto,
- // or .aidl files.
- Srcs []string `android:"path,arch_variant"`
-
- // list Kotlin of source files containing Kotlin code that should be treated as common code in
- // a codebase that supports Kotlin multiplatform. See
- // https://kotlinlang.org/docs/reference/multiplatform.html. May be only be .kt files.
- Common_srcs []string `android:"path,arch_variant"`
-
- // list of source files that should not be used to build the Java module.
- // This is most useful in the arch/multilib variants to remove non-common files
- Exclude_srcs []string `android:"path,arch_variant"`
-
- // list of directories containing Java resources
- Java_resource_dirs []string `android:"arch_variant"`
-
- // list of directories that should be excluded from java_resource_dirs
- Exclude_java_resource_dirs []string `android:"arch_variant"`
-
- // list of files to use as Java resources
- Java_resources []string `android:"path,arch_variant"`
-
- // list of files that should be excluded from java_resources and java_resource_dirs
- Exclude_java_resources []string `android:"path,arch_variant"`
-
- // list of module-specific flags that will be used for javac compiles
- Javacflags []string `android:"arch_variant"`
-
- // list of module-specific flags that will be used for kotlinc compiles
- Kotlincflags []string `android:"arch_variant"`
-
- // list of of java libraries that will be in the classpath
- Libs []string `android:"arch_variant"`
-
- // list of java libraries that will be compiled into the resulting jar
- Static_libs []string `android:"arch_variant"`
-
- // manifest file to be included in resulting jar
- Manifest *string `android:"path"`
-
- // if not blank, run jarjar using the specified rules file
- Jarjar_rules *string `android:"path,arch_variant"`
-
- // If not blank, set the java version passed to javac as -source and -target
- Java_version *string
-
- // If set to true, allow this module to be dexed and installed on devices. Has no
- // effect on host modules, which are always considered installable.
- Installable *bool
-
- // If set to true, include sources used to compile the module in to the final jar
- Include_srcs *bool
-
- // If not empty, classes are restricted to the specified packages and their sub-packages.
- // This restriction is checked after applying jarjar rules and including static libs.
- Permitted_packages []string
-
- // List of modules to use as annotation processors
- Plugins []string
-
- // List of modules to export to libraries that directly depend on this library as annotation
- // processors. Note that if the plugins set generates_api: true this will disable the turbine
- // optimization on modules that depend on this module, which will reduce parallelism and cause
- // more recompilation.
- Exported_plugins []string
-
- // The number of Java source entries each Javac instance can process
- Javac_shard_size *int64
-
- // Add host jdk tools.jar to bootclasspath
- Use_tools_jar *bool
-
- Openjdk9 struct {
- // List of source files that should only be used when passing -source 1.9 or higher
- Srcs []string `android:"path"`
-
- // List of javac flags that should only be used when passing -source 1.9 or higher
- Javacflags []string
- }
-
- // When compiling language level 9+ .java code in packages that are part of
- // a system module, patch_module names the module that your sources and
- // dependencies should be patched into. The Android runtime currently
- // doesn't implement the JEP 261 module system so this option is only
- // supported at compile time. It should only be needed to compile tests in
- // packages that exist in libcore and which are inconvenient to move
- // elsewhere.
- Patch_module *string `android:"arch_variant"`
-
- Jacoco struct {
- // List of classes to include for instrumentation with jacoco to collect coverage
- // information at runtime when building with coverage enabled. If unset defaults to all
- // classes.
- // Supports '*' as the last character of an entry in the list as a wildcard match.
- // If preceded by '.' it matches all classes in the package and subpackages, otherwise
- // it matches classes in the package that have the class name as a prefix.
- Include_filter []string
-
- // List of classes to exclude from instrumentation with jacoco to collect coverage
- // information at runtime when building with coverage enabled. Overrides classes selected
- // by the include_filter property.
- // Supports '*' as the last character of an entry in the list as a wildcard match.
- // If preceded by '.' it matches all classes in the package and subpackages, otherwise
- // it matches classes in the package that have the class name as a prefix.
- Exclude_filter []string
- }
-
- Errorprone struct {
- // List of javac flags that should only be used when running errorprone.
- Javacflags []string
-
- // List of java_plugin modules that provide extra errorprone checks.
- Extra_check_modules []string
- }
-
- Proto struct {
- // List of extra options that will be passed to the proto generator.
- Output_params []string
- }
-
- Instrument bool `blueprint:"mutated"`
-
- // List of files to include in the META-INF/services folder of the resulting jar.
- Services []string `android:"path,arch_variant"`
-
- // If true, package the kotlin stdlib into the jar. Defaults to true.
- Static_kotlin_stdlib *bool `android:"arch_variant"`
-
- // A list of java_library instances that provide additional hiddenapi annotations for the library.
- Hiddenapi_additional_annotations []string
-}
-
-// Properties that are specific to device modules. Host module factories should not add these when
-// constructing a new module.
-type DeviceProperties struct {
- // if not blank, set to the version of the sdk to compile against.
- // Defaults to compiling against the current platform.
- Sdk_version *string
-
- // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
- // Defaults to sdk_version if not set.
- Min_sdk_version *string
-
- // if not blank, set the targetSdkVersion in the AndroidManifest.xml.
- // Defaults to sdk_version if not set.
- Target_sdk_version *string
-
- // Whether to compile against the platform APIs instead of an SDK.
- // If true, then sdk_version must be empty. The value of this field
- // is ignored when module's type isn't android_app.
- Platform_apis *bool
-
- Aidl struct {
- // Top level directories to pass to aidl tool
- Include_dirs []string
-
- // Directories rooted at the Android.bp file to pass to aidl tool
- Local_include_dirs []string
-
- // directories that should be added as include directories for any aidl sources of modules
- // that depend on this module, as well as to aidl for this module.
- Export_include_dirs []string
-
- // whether to generate traces (for systrace) for this interface
- Generate_traces *bool
-
- // whether to generate Binder#GetTransaction name method.
- Generate_get_transaction_name *bool
-
- // list of flags that will be passed to the AIDL compiler
- Flags []string
- }
-
- // If true, export a copy of the module as a -hostdex module for host testing.
- Hostdex *bool
-
- Target struct {
- Hostdex struct {
- // Additional required dependencies to add to -hostdex modules.
- Required []string
- }
- }
-
- // When targeting 1.9 and above, override the modules to use with --system,
- // otherwise provides defaults libraries to add to the bootclasspath.
- System_modules *string
-
- // The name of the module as used in build configuration.
- //
- // Allows a library to separate its actual name from the name used in
- // build configuration, e.g.ctx.Config().BootJars().
- ConfigurationName *string `blueprint:"mutated"`
-
- // set the name of the output
- Stem *string
-
- IsSDKLibrary bool `blueprint:"mutated"`
-
- // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
- // Defaults to false.
- V4_signature *bool
-
- // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
- // public stubs library.
- SyspropPublicStub string `blueprint:"mutated"`
-}
-
-// Functionality common to Module and Import
-//
-// It is embedded in Module so its functionality can be used by methods in Module
-// but it is currently only initialized by Import and Library.
-type embeddableInModuleAndImport struct {
-
- // Functionality related to this being used as a component of a java_sdk_library.
- EmbeddableSdkLibraryComponent
-}
-
-func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
- e.initSdkLibraryComponent(moduleBase)
-}
-
-// Module/Import's DepIsInSameApex(...) delegates to this method.
-//
-// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
-// the one provided by ApexModuleBase.
-func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- // dependencies other than the static linkage are all considered crossing APEX boundary
- if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
- return true
- }
- return false
-}
-
-// Module contains the properties and members used by all java module types
-type Module struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.ApexModuleBase
- android.SdkBase
-
- // Functionality common to Module and Import.
- embeddableInModuleAndImport
-
- properties CommonProperties
- protoProperties android.ProtoProperties
- deviceProperties DeviceProperties
-
- // jar file containing header classes including static library dependencies, suitable for
- // inserting into the bootclasspath/classpath of another compile
- headerJarFile android.Path
-
- // jar file containing implementation classes including static library dependencies but no
- // resources
- implementationJarFile android.Path
-
- // jar file containing only resources including from static library dependencies
- resourceJar android.Path
-
- // args and dependencies to package source files into a srcjar
- srcJarArgs []string
- srcJarDeps android.Paths
-
- // jar file containing implementation classes and resources including static library
- // dependencies
- implementationAndResourcesJar android.Path
-
- // output file containing classes.dex and resources
- dexJarFile android.Path
-
- // output file containing uninstrumented classes that will be instrumented by jacoco
- jacocoReportClassesFile android.Path
-
- // output file of the module, which may be a classes jar or a dex jar
- outputFile android.Path
- extraOutputFiles android.Paths
-
- exportAidlIncludeDirs android.Paths
-
- logtagsSrcs android.Paths
-
- // installed file for binary dependency
- installFile android.Path
-
- // list of .java files and srcjars that was passed to javac
- compiledJavaSrcs android.Paths
- compiledSrcJars android.Paths
-
- // manifest file to use instead of properties.Manifest
- overrideManifest android.OptionalPath
-
- // map of SDK version to class loader context
- classLoaderContexts dexpreopt.ClassLoaderContextMap
-
- // list of plugins that this java module is exporting
- exportedPluginJars android.Paths
-
- // list of plugins that this java module is exporting
- exportedPluginClasses []string
-
- // if true, the exported plugins generate API and require disabling turbine.
- exportedDisableTurbine bool
-
- // list of source files, collected from srcFiles with unique java and all kt files,
- // will be used by android.IDEInfo struct
- expandIDEInfoCompiledSrcs []string
-
- // expanded Jarjar_rules
- expandJarjarRules android.Path
-
- // list of additional targets for checkbuild
- additionalCheckedModules android.Paths
-
- // Extra files generated by the module type to be added as java resources.
- extraResources android.Paths
-
- hiddenAPI
- dexer
- dexpreopter
- usesLibrary
- linter
-
- // list of the xref extraction files
- kytheFiles android.Paths
-
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
-
- hideApexVariantFromMake bool
-}
-
-func (j *Module) CheckStableSdkVersion() error {
- sdkVersion := j.sdkVersion()
- if sdkVersion.stable() {
- return nil
- }
- if sdkVersion.kind == sdkCorePlatform {
- if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
- return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
- } else {
- // Treat stable core platform as stable.
- return nil
- }
- } else {
- return fmt.Errorf("non stable SDK %v", sdkVersion)
- }
-}
-
-// checkSdkVersions enforces restrictions around SDK dependencies.
-func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
- if j.RequiresStableAPIs(ctx) {
- if sc, ok := ctx.Module().(sdkContext); ok {
- if !sc.sdkVersion().specified() {
- ctx.PropertyErrorf("sdk_version",
- "sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
- }
- }
- }
-
- // Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
- // See rank() for details.
- ctx.VisitDirectDeps(func(module android.Module) {
- tag := ctx.OtherModuleDependencyTag(module)
- switch module.(type) {
- // TODO(satayev): cover other types as well, e.g. imports
- case *Library, *AndroidLibrary:
- switch tag {
- case bootClasspathTag, libTag, staticLibTag, java9LibTag:
- j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
- }
- }
- })
-}
-
-func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
- if sc, ok := ctx.Module().(sdkContext); ok {
- usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
- sdkVersionSpecified := sc.sdkVersion().specified()
- if usePlatformAPI && sdkVersionSpecified {
- ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
- } else if !usePlatformAPI && !sdkVersionSpecified {
- ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
- }
-
- }
-}
-
-func (j *Module) addHostProperties() {
- j.AddProperties(
- &j.properties,
- &j.protoProperties,
- &j.usesLibraryProperties,
- )
-}
-
-func (j *Module) addHostAndDeviceProperties() {
- j.addHostProperties()
- j.AddProperties(
- &j.deviceProperties,
- &j.dexer.dexProperties,
- &j.dexpreoptProperties,
- &j.linter.properties,
- )
-}
-
-func (j *Module) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
- case android.DefaultDistTag:
- return android.Paths{j.outputFile}, nil
- case ".jar":
- return android.Paths{j.implementationAndResourcesJar}, nil
- case ".proguard_map":
- if j.dexer.proguardDictionary.Valid() {
- return android.Paths{j.dexer.proguardDictionary.Path()}, nil
- }
- return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
-var _ android.OutputFileProducer = (*Module)(nil)
-
// JavaInfo contains information about a java module for use by modules that depend on it.
type JavaInfo struct {
// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
@@ -627,6 +190,7 @@
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
+// TODO(jungjw): Move this to kythe.go once it's created.
type xref interface {
XrefJavaFiles() android.Paths
}
@@ -635,24 +199,6 @@
return j.kytheFiles
}
-func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
- initJavaModule(module, hod, false)
-}
-
-func InitJavaModuleMultiTargets(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
- initJavaModule(module, hod, true)
-}
-
-func initJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported, multiTargets bool) {
- multilib := android.MultilibCommon
- if multiTargets {
- android.InitAndroidMultiTargetsArchModule(module, hod, multilib)
- } else {
- android.InitAndroidArchModule(module, hod, multilib)
- }
- android.InitDefaultableModule(module)
-}
-
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -758,70 +304,6 @@
unstrippedFile android.Path
}
-func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
- return j.properties.Instrument &&
- ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
- ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
-}
-
-func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
- return j.shouldInstrument(ctx) &&
- (ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") ||
- ctx.Config().UnbundledBuild())
-}
-
-func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
- // Force enable the instrumentation for java code that is built for APEXes ...
- // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
- // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- isJacocoAgent := ctx.ModuleName() == "jacocoagent"
- if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
- if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
- return true
- } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- return true
- }
- }
- return false
-}
-
-func (j *Module) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
-}
-
-func (j *Module) systemModules() string {
- return proptools.String(j.deviceProperties.System_modules)
-}
-
-func (j *Module) minSdkVersion() sdkSpec {
- if j.deviceProperties.Min_sdk_version != nil {
- return sdkSpecFrom(*j.deviceProperties.Min_sdk_version)
- }
- return j.sdkVersion()
-}
-
-func (j *Module) targetSdkVersion() sdkSpec {
- if j.deviceProperties.Target_sdk_version != nil {
- return sdkSpecFrom(*j.deviceProperties.Target_sdk_version)
- }
- return j.sdkVersion()
-}
-
-func (j *Module) MinSdkVersion() string {
- return j.minSdkVersion().version.String()
-}
-
-func (j *Module) AvailableFor(what string) bool {
- if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
- // Exception: for hostdex: true libraries, the platform variant is created
- // even if it's not marked as available to platform. In that case, the platform
- // variant is used only for the hostdex and not installed to the device.
- return true
- }
- return j.ApexModuleBase.AvailableFor(what)
-}
-
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext sdkContext, d dexer) {
sdkDep := decodeSdkDep(ctx, sdkContext)
if sdkDep.useModule {
@@ -840,155 +322,6 @@
}
}
-func (j *Module) deps(ctx android.BottomUpMutatorContext) {
- if ctx.Device() {
- j.linter.deps(ctx)
-
- sdkDeps(ctx, sdkContext(j), j.dexer)
-
- if j.deviceProperties.SyspropPublicStub != "" {
- // This is a sysprop implementation library that has a corresponding sysprop public
- // stubs library, and a dependency on it so that dependencies on the implementation can
- // be forwarded to the public stubs library when necessary.
- ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub)
- }
- }
-
- libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
- ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
-
- // Add dependency on libraries that provide additional hidden api annotations.
- ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
-
- if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
- // Require java_sdk_library at inter-partition java dependency to ensure stable
- // interface between partitions. If inter-partition java_library dependency is detected,
- // raise build error because java_library doesn't have a stable interface.
- //
- // Inputs:
- // PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
- // if true, enable enforcement
- // PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
- // exception list of java_library names to allow inter-partition dependency
- for idx := range j.properties.Libs {
- if libDeps[idx] == nil {
- continue
- }
-
- if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
- // java_sdk_library is always allowed at inter-partition dependency.
- // So, skip check.
- if _, ok := javaDep.(*SdkLibrary); ok {
- continue
- }
-
- j.checkPartitionsForJavaDependency(ctx, "libs", javaDep)
- }
- }
- }
-
- // For library dependencies that are component libraries (like stubs), add the implementation
- // as a dependency (dexpreopt needs to be against the implementation library, not stubs).
- for _, dep := range libDeps {
- if dep != nil {
- if component, ok := dep.(SdkLibraryComponentDependency); ok {
- if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
- ctx.AddVariationDependencies(nil, usesLibTag, *lib)
- }
- }
- }
- }
-
- ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
- ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...)
- ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
-
- android.ProtoDeps(ctx, &j.protoProperties)
- if j.hasSrcExt(".proto") {
- protoDeps(ctx, &j.protoProperties)
- }
-
- if j.hasSrcExt(".kt") {
- // TODO(ccross): move this to a mutator pass that can tell if generated sources contain
- // Kotlin files
- ctx.AddVariationDependencies(nil, kotlinStdlibTag,
- "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
- if len(j.properties.Plugins) > 0 {
- ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
- }
- }
-
- // Framework libraries need special handling in static coverage builds: they should not have
- // static dependency on jacoco, otherwise there would be multiple conflicting definitions of
- // the same jacoco classes coming from different bootclasspath jars.
- if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
- if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- j.properties.Instrument = true
- }
- } else if j.shouldInstrumentStatic(ctx) {
- ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
- }
-}
-
-func hasSrcExt(srcs []string, ext string) bool {
- for _, src := range srcs {
- if filepath.Ext(src) == ext {
- return true
- }
- }
-
- return false
-}
-
-func (j *Module) hasSrcExt(ext string) bool {
- return hasSrcExt(j.properties.Srcs, ext)
-}
-
-func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
- aidlIncludeDirs android.Paths) (string, android.Paths) {
-
- aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
- aidlIncludes = append(aidlIncludes,
- android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)...)
- aidlIncludes = append(aidlIncludes,
- android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)
-
- var flags []string
- var deps android.Paths
-
- flags = append(flags, j.deviceProperties.Aidl.Flags...)
-
- if aidlPreprocess.Valid() {
- flags = append(flags, "-p"+aidlPreprocess.String())
- deps = append(deps, aidlPreprocess.Path())
- } else if len(aidlIncludeDirs) > 0 {
- flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
- }
-
- if len(j.exportAidlIncludeDirs) > 0 {
- flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
- }
-
- if len(aidlIncludes) > 0 {
- flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
- }
-
- flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
- if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
- flags = append(flags, "-I"+src.String())
- }
-
- if Bool(j.deviceProperties.Aidl.Generate_traces) {
- flags = append(flags, "-t")
- }
-
- if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) {
- flags = append(flags, "--transaction_names")
- }
-
- return strings.Join(flags, " "), deps
-}
-
type deps struct {
classpath classpath
java9Classpath classpath
@@ -1019,272 +352,6 @@
}
}
-type sdkLinkType int
-
-const (
- // TODO(jiyong) rename these for better readability. Make the allowed
- // and disallowed link types explicit
- // order is important here. See rank()
- javaCore sdkLinkType = iota
- javaSdk
- javaSystem
- javaModule
- javaSystemServer
- javaPlatform
-)
-
-func (lt sdkLinkType) String() string {
- switch lt {
- case javaCore:
- return "core Java API"
- case javaSdk:
- return "Android API"
- case javaSystem:
- return "system API"
- case javaModule:
- return "module API"
- case javaSystemServer:
- return "system server API"
- case javaPlatform:
- return "private API"
- default:
- panic(fmt.Errorf("unrecognized linktype: %d", lt))
- }
-}
-
-// rank determines the total order among sdkLinkType. An SDK link type of rank A can link to
-// another SDK link type of rank B only when B <= A. For example, a module linking to Android SDK
-// can't statically depend on modules that use Platform API.
-func (lt sdkLinkType) rank() int {
- return int(lt)
-}
-
-type moduleWithSdkDep interface {
- android.Module
- getSdkLinkType(name string) (ret sdkLinkType, stubs bool)
-}
-
-func (m *Module) getSdkLinkType(name string) (ret sdkLinkType, stubs bool) {
- switch name {
- case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
- "stub-annotations", "private-stub-annotations-jar",
- "core-lambda-stubs", "core-generated-annotation-stubs":
- return javaCore, true
- case "android_stubs_current":
- return javaSdk, true
- case "android_system_stubs_current":
- return javaSystem, true
- case "android_module_lib_stubs_current":
- return javaModule, true
- case "android_system_server_stubs_current":
- return javaSystemServer, true
- case "android_test_stubs_current":
- return javaSystem, true
- }
-
- if stub, linkType := moduleStubLinkType(name); stub {
- return linkType, true
- }
-
- ver := m.sdkVersion()
- switch ver.kind {
- case sdkCore:
- return javaCore, false
- case sdkSystem:
- return javaSystem, false
- case sdkPublic:
- return javaSdk, false
- case sdkModule:
- return javaModule, false
- case sdkSystemServer:
- return javaSystemServer, false
- case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
- return javaPlatform, false
- }
-
- if !ver.valid() {
- panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
- }
- return javaSdk, false
-}
-
-// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
-// this module's. See the comment on rank() for details and an example.
-func (j *Module) checkSdkLinkType(
- ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) {
- if ctx.Host() {
- return
- }
-
- myLinkType, stubs := j.getSdkLinkType(ctx.ModuleName())
- if stubs {
- return
- }
- depLinkType, _ := dep.getSdkLinkType(ctx.OtherModuleName(dep))
-
- if myLinkType.rank() < depLinkType.rank() {
- ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+
- "In order to fix this, consider adjusting sdk_version: OR platform_apis: "+
- "property of the source or target module so that target module is built "+
- "with the same or smaller API set when compared to the source.",
- myLinkType, ctx.OtherModuleName(dep), depLinkType)
- }
-}
-
-func (j *Module) collectDeps(ctx android.ModuleContext) deps {
- var deps deps
-
- if ctx.Device() {
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
- if sdkDep.invalidVersion {
- ctx.AddMissingDependencies(sdkDep.bootclasspath)
- ctx.AddMissingDependencies(sdkDep.java9Classpath)
- } else if sdkDep.useFiles {
- // sdkDep.jar is actually equivalent to turbine header.jar.
- deps.classpath = append(deps.classpath, sdkDep.jars...)
- deps.aidlPreprocess = sdkDep.aidl
- } else {
- deps.aidlPreprocess = sdkDep.aidl
- }
- }
-
- sdkLinkType, _ := j.getSdkLinkType(ctx.ModuleName())
-
- ctx.VisitDirectDeps(func(module android.Module) {
- otherName := ctx.OtherModuleName(module)
- tag := ctx.OtherModuleDependencyTag(module)
-
- if IsJniDepTag(tag) {
- // Handled by AndroidApp.collectAppDeps
- return
- }
- if tag == certificateTag {
- // Handled by AndroidApp.collectAppDeps
- return
- }
-
- if dep, ok := module.(SdkLibraryDependency); ok {
- switch tag {
- case libTag:
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
- case staticLibTag:
- ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
- }
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if sdkLinkType != javaPlatform &&
- ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
- // dep is a sysprop implementation library, but this module is not linking against
- // the platform, so it gets the sysprop public stubs library instead. Replace
- // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
- syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
- dep = syspropDep.JavaInfo
- }
- switch tag {
- case bootClasspathTag:
- deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
- case libTag, instrumentationForTag:
- deps.classpath = append(deps.classpath, dep.HeaderJars...)
- deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
- addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
- deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
- case java9LibTag:
- deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
- case staticLibTag:
- deps.classpath = append(deps.classpath, dep.HeaderJars...)
- deps.staticJars = append(deps.staticJars, dep.ImplementationJars...)
- deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars...)
- deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars...)
- deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
- addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
- // Turbine doesn't run annotation processors, so any module that uses an
- // annotation processor that generates API is incompatible with the turbine
- // optimization.
- deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
- case pluginTag:
- if plugin, ok := module.(*Plugin); ok {
- if plugin.pluginProperties.Processor_class != nil {
- addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class)
- } else {
- addPlugins(&deps, dep.ImplementationAndResourcesJars)
- }
- // Turbine doesn't run annotation processors, so any module that uses an
- // annotation processor that generates API is incompatible with the turbine
- // optimization.
- deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
- } else {
- ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
- }
- case errorpronePluginTag:
- if _, ok := module.(*Plugin); ok {
- deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...)
- } else {
- ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
- }
- case exportedPluginTag:
- if plugin, ok := module.(*Plugin); ok {
- j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...)
- if plugin.pluginProperties.Processor_class != nil {
- j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
- }
- // Turbine doesn't run annotation processors, so any module that uses an
- // annotation processor that generates API is incompatible with the turbine
- // optimization.
- j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api)
- } else {
- ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
- }
- case kotlinStdlibTag:
- deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
- case kotlinAnnotationsTag:
- deps.kotlinAnnotations = dep.HeaderJars
- case syspropPublicStubDepTag:
- // This is a sysprop implementation library, forward the JavaInfoProvider from
- // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
- ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
- JavaInfo: dep,
- })
- }
- } else if dep, ok := module.(android.SourceFileProducer); ok {
- switch tag {
- case libTag:
- checkProducesJars(ctx, dep)
- deps.classpath = append(deps.classpath, dep.Srcs()...)
- case staticLibTag:
- checkProducesJars(ctx, dep)
- deps.classpath = append(deps.classpath, dep.Srcs()...)
- deps.staticJars = append(deps.staticJars, dep.Srcs()...)
- deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
- }
- } else {
- switch tag {
- case bootClasspathTag:
- // If a system modules dependency has been added to the bootclasspath
- // then add its libs to the bootclasspath.
- sm := module.(SystemModulesProvider)
- deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
-
- case systemModulesTag:
- if deps.systemModules != nil {
- panic("Found two system module dependencies")
- }
- sm := module.(SystemModulesProvider)
- outputDir, outputDeps := sm.OutputDirAndDeps()
- deps.systemModules = &systemModules{outputDir, outputDeps}
- }
- }
-
- addCLCFromDep(ctx, module, j.classLoaderContexts)
- })
-
- return deps
-}
-
-func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
- deps.processorPath = append(deps.processorPath, pluginJars...)
- deps.processorClasses = append(deps.processorClasses, pluginClasses...)
-}
-
func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion {
if javaVersion != "" {
return normalizeJavaVersion(ctx, javaVersion)
@@ -1344,824 +411,6 @@
}
}
-func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
-
- var flags javaBuilderFlags
-
- // javaVersion flag.
- flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
-
- if ctx.Config().RunErrorProne() {
- if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
- ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
- }
-
- errorProneFlags := []string{
- "-Xplugin:ErrorProne",
- "${config.ErrorProneChecks}",
- }
- errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...)
-
- flags.errorProneExtraJavacFlags = "${config.ErrorProneFlags} " +
- "'" + strings.Join(errorProneFlags, " ") + "'"
- flags.errorProneProcessorPath = classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
- }
-
- // classpath
- flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
- flags.classpath = append(flags.classpath, deps.classpath...)
- flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
- flags.processorPath = append(flags.processorPath, deps.processorPath...)
- flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...)
-
- flags.processors = append(flags.processors, deps.processorClasses...)
- flags.processors = android.FirstUniqueStrings(flags.processors)
-
- if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
- decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() {
- // Give host-side tools a version of OpenJDK's standard libraries
- // close to what they're targeting. As of Dec 2017, AOSP is only
- // bundling OpenJDK 8 and 9, so nothing < 8 is available.
- //
- // When building with OpenJDK 8, the following should have no
- // effect since those jars would be available by default.
- //
- // When building with OpenJDK 9 but targeting a version < 1.8,
- // putting them on the bootclasspath means that:
- // a) code can't (accidentally) refer to OpenJDK 9 specific APIs
- // b) references to existing APIs are not reinterpreted in an
- // OpenJDK 9-specific way, eg. calls to subclasses of
- // java.nio.Buffer as in http://b/70862583
- java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
- flags.bootClasspath = append(flags.bootClasspath,
- android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"),
- android.PathForSource(ctx, java8Home, "jre/lib/rt.jar"))
- if Bool(j.properties.Use_tools_jar) {
- flags.bootClasspath = append(flags.bootClasspath,
- android.PathForSource(ctx, java8Home, "lib/tools.jar"))
- }
- }
-
- // systemModules
- flags.systemModules = deps.systemModules
-
- // aidl flags.
- flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
-
- return flags
-}
-
-func (j *Module) collectJavacFlags(
- ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
- // javac flags.
- javacFlags := j.properties.Javacflags
-
- if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
- // For non-host binaries, override the -g flag passed globally to remove
- // local variable debug info to reduce disk and memory usage.
- javacFlags = append(javacFlags, "-g:source,lines")
- }
- javacFlags = append(javacFlags, "-Xlint:-dep-ann")
-
- if flags.javaVersion.usesJavaModules() {
- javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
-
- if j.properties.Patch_module != nil {
- // Manually specify build directory in case it is not under the repo root.
- // (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
- // just adding a symlink under the root doesn't help.)
- patchPaths := []string{".", ctx.Config().BuildDir()}
-
- // b/150878007
- //
- // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
- // execution root for --patch-module. If this javac command line is
- // invoked within Bazel's execution root working directory, the top
- // level directories (e.g. libcore/, tools/, frameworks/) are all
- // symlinks. JDK9 javac does not traverse into symlinks, which causes
- // --patch-module to fail source file lookups when invoked in the
- // execution root.
- //
- // Short of patching javac or enumerating *all* directories as possible
- // input dirs, manually add the top level dir of the source files to be
- // compiled.
- topLevelDirs := map[string]bool{}
- for _, srcFilePath := range srcFiles {
- srcFileParts := strings.Split(srcFilePath.String(), "/")
- // Ignore source files that are already in the top level directory
- // as well as generated files in the out directory. The out
- // directory may be an absolute path, which means srcFileParts[0] is the
- // empty string, so check that as well. Note that "out" in Bazel's execution
- // root is *not* a symlink, which doesn't cause problems for --patch-modules
- // anyway, so it's fine to not apply this workaround for generated
- // source files.
- if len(srcFileParts) > 1 &&
- srcFileParts[0] != "" &&
- srcFileParts[0] != "out" {
- topLevelDirs[srcFileParts[0]] = true
- }
- }
- patchPaths = append(patchPaths, android.SortedStringKeys(topLevelDirs)...)
-
- classPath := flags.classpath.FormJavaClassPath("")
- if classPath != "" {
- patchPaths = append(patchPaths, classPath)
- }
- javacFlags = append(
- javacFlags,
- "--patch-module="+String(j.properties.Patch_module)+"="+strings.Join(patchPaths, ":"))
- }
- }
-
- if len(javacFlags) > 0 {
- // optimization.
- ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
- flags.javacFlags = "$javacFlags"
- }
-
- return flags
-}
-
-func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
- j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
-
- deps := j.collectDeps(ctx)
- flags := j.collectBuilderFlags(ctx, deps)
-
- if flags.javaVersion.usesJavaModules() {
- j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
- }
- srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
- if hasSrcExt(srcFiles.Strings(), ".proto") {
- flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
- }
-
- kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
- if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
- ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
- }
-
- srcFiles = j.genSources(ctx, srcFiles, flags)
-
- // Collect javac flags only after computing the full set of srcFiles to
- // ensure that the --patch-module lookup paths are complete.
- flags = j.collectJavacFlags(ctx, flags, srcFiles)
-
- srcJars := srcFiles.FilterByExt(".srcjar")
- srcJars = append(srcJars, deps.srcJars...)
- if aaptSrcJar != nil {
- srcJars = append(srcJars, aaptSrcJar)
- }
-
- if j.properties.Jarjar_rules != nil {
- j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
- }
-
- jarName := ctx.ModuleName() + ".jar"
-
- javaSrcFiles := srcFiles.FilterByExt(".java")
- var uniqueSrcFiles android.Paths
- set := make(map[string]bool)
- for _, v := range javaSrcFiles {
- if _, found := set[v.String()]; !found {
- set[v.String()] = true
- uniqueSrcFiles = append(uniqueSrcFiles, v)
- }
- }
-
- // Collect .java files for AIDEGen
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
-
- var kotlinJars android.Paths
-
- if srcFiles.HasExt(".kt") {
- // user defined kotlin flags.
- kotlincFlags := j.properties.Kotlincflags
- CheckKotlincFlags(ctx, kotlincFlags)
-
- // Dogfood the JVM_IR backend.
- kotlincFlags = append(kotlincFlags, "-Xuse-ir")
-
- // If there are kotlin files, compile them first but pass all the kotlin and java files
- // kotlinc will use the java files to resolve types referenced by the kotlin files, but
- // won't emit any classes for them.
- kotlincFlags = append(kotlincFlags, "-no-stdlib")
- if ctx.Device() {
- kotlincFlags = append(kotlincFlags, "-no-jdk")
- }
- if len(kotlincFlags) > 0 {
- // optimization.
- ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
- flags.kotlincFlags += "$kotlincFlags"
- }
-
- var kotlinSrcFiles android.Paths
- kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
- kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
-
- // Collect .kt files for AIDEGen
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
-
- flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
- flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
-
- flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
- flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
-
- if len(flags.processorPath) > 0 {
- // Use kapt for annotation processing
- kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
- kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
- kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
- srcJars = append(srcJars, kaptSrcJar)
- kotlinJars = append(kotlinJars, kaptResJar)
- // Disable annotation processing in javac, it's already been handled by kapt
- flags.processorPath = nil
- flags.processors = nil
- }
-
- kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
- if ctx.Failed() {
- return
- }
-
- // Make javac rule depend on the kotlinc rule
- flags.classpath = append(flags.classpath, kotlinJar)
-
- kotlinJars = append(kotlinJars, kotlinJar)
- // Jar kotlin classes into the final jar after javac
- if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
- kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
- }
- }
-
- jars := append(android.Paths(nil), kotlinJars...)
-
- // Store the list of .java files that was passed to javac
- j.compiledJavaSrcs = uniqueSrcFiles
- j.compiledSrcJars = srcJars
-
- enableSharding := false
- var headerJarFileWithoutJarjar android.Path
- if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
- if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
- enableSharding = true
- // Formerly, there was a check here that prevented annotation processors
- // from being used when sharding was enabled, as some annotation processors
- // do not function correctly in sharded environments. It was removed to
- // allow for the use of annotation processors that do function correctly
- // with sharding enabled. See: b/77284273.
- }
- headerJarFileWithoutJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
- if ctx.Failed() {
- return
- }
- }
- if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
- var extraJarDeps android.Paths
- if ctx.Config().RunErrorProne() {
- // If error-prone is enabled, add an additional rule to compile the java files into
- // a separate set of classes (so that they don't overwrite the normal ones and require
- // a rebuild when error-prone is turned off).
- // TODO(ccross): Once we always compile with javac9 we may be able to conditionally
- // enable error-prone without affecting the output class files.
- errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
- extraJarDeps = append(extraJarDeps, errorprone)
- }
-
- if enableSharding {
- flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
- shardSize := int(*(j.properties.Javac_shard_size))
- var shardSrcs []android.Paths
- if len(uniqueSrcFiles) > 0 {
- shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
- for idx, shardSrc := range shardSrcs {
- classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
- nil, flags, extraJarDeps)
- jars = append(jars, classes)
- }
- }
- if len(srcJars) > 0 {
- classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
- nil, srcJars, flags, extraJarDeps)
- jars = append(jars, classes)
- }
- } else {
- classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
- jars = append(jars, classes)
- }
- if ctx.Failed() {
- return
- }
- }
-
- j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
-
- var includeSrcJar android.WritablePath
- if Bool(j.properties.Include_srcs) {
- includeSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+".srcjar")
- TransformResourcesToJar(ctx, includeSrcJar, j.srcJarArgs, j.srcJarDeps)
- }
-
- dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs,
- j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources)
- fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources)
- extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources
-
- var resArgs []string
- var resDeps android.Paths
-
- resArgs = append(resArgs, dirArgs...)
- resDeps = append(resDeps, dirDeps...)
-
- resArgs = append(resArgs, fileArgs...)
- resDeps = append(resDeps, fileDeps...)
-
- resArgs = append(resArgs, extraArgs...)
- resDeps = append(resDeps, extraDeps...)
-
- if len(resArgs) > 0 {
- resourceJar := android.PathForModuleOut(ctx, "res", jarName)
- TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
- j.resourceJar = resourceJar
- if ctx.Failed() {
- return
- }
- }
-
- var resourceJars android.Paths
- if j.resourceJar != nil {
- resourceJars = append(resourceJars, j.resourceJar)
- }
- if Bool(j.properties.Include_srcs) {
- resourceJars = append(resourceJars, includeSrcJar)
- }
- resourceJars = append(resourceJars, deps.staticResourceJars...)
-
- if len(resourceJars) > 1 {
- combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
- false, nil, nil)
- j.resourceJar = combinedJar
- } else if len(resourceJars) == 1 {
- j.resourceJar = resourceJars[0]
- }
-
- if len(deps.staticJars) > 0 {
- jars = append(jars, deps.staticJars...)
- }
-
- manifest := j.overrideManifest
- if !manifest.Valid() && j.properties.Manifest != nil {
- manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest))
- }
-
- services := android.PathsForModuleSrc(ctx, j.properties.Services)
- if len(services) > 0 {
- servicesJar := android.PathForModuleOut(ctx, "services", jarName)
- var zipargs []string
- for _, file := range services {
- serviceFile := file.String()
- zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile)
- }
- rule := zip
- args := map[string]string{
- "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
- }
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ZIP") {
- rule = zipRE
- args["implicits"] = strings.Join(services.Strings(), ",")
- }
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Output: servicesJar,
- Implicits: services,
- Args: args,
- })
- jars = append(jars, servicesJar)
- }
-
- // Combine the classes built from sources, any manifests, and any static libraries into
- // classes.jar. If there is only one input jar this step will be skipped.
- var outputFile android.OutputPath
-
- if len(jars) == 1 && !manifest.Valid() {
- // Optimization: skip the combine step as there is nothing to do
- // TODO(ccross): this leaves any module-info.class files, but those should only come from
- // prebuilt dependencies until we support modules in the platform build, so there shouldn't be
- // any if len(jars) == 1.
-
- // Transform the single path to the jar into an OutputPath as that is required by the following
- // code.
- if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
- // The path contains an embedded OutputPath so reuse that.
- outputFile = moduleOutPath.OutputPath
- } else if outputPath, ok := jars[0].(android.OutputPath); ok {
- // The path is an OutputPath so reuse it directly.
- outputFile = outputPath
- } else {
- // The file is not in the out directory so create an OutputPath into which it can be copied
- // and which the following code can use to refer to it.
- combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: jars[0],
- Output: combinedJar,
- })
- outputFile = combinedJar.OutputPath
- }
- } else {
- combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
- false, nil, nil)
- outputFile = combinedJar.OutputPath
- }
-
- // jarjar implementation jar if necessary
- if j.expandJarjarRules != nil {
- // Transform classes.jar into classes-jarjar.jar
- jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName).OutputPath
- TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
- outputFile = jarjarFile
-
- // jarjar resource jar if necessary
- if j.resourceJar != nil {
- resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName)
- TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules)
- j.resourceJar = resourceJarJarFile
- }
-
- if ctx.Failed() {
- return
- }
- }
-
- // Check package restrictions if necessary.
- if len(j.properties.Permitted_packages) > 0 {
- // Check packages and copy to package-checked file.
- pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")
- CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
- j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile)
-
- if ctx.Failed() {
- return
- }
- }
-
- j.implementationJarFile = outputFile
- if j.headerJarFile == nil {
- j.headerJarFile = j.implementationJarFile
- }
-
- if j.shouldInstrumentInApex(ctx) {
- j.properties.Instrument = true
- }
-
- if j.shouldInstrument(ctx) {
- outputFile = j.instrument(ctx, flags, outputFile, jarName)
- }
-
- // merge implementation jar with resources if necessary
- implementationAndResourcesJar := outputFile
- if j.resourceJar != nil {
- jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
- combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
- false, nil, nil)
- implementationAndResourcesJar = combinedJar
- }
-
- j.implementationAndResourcesJar = implementationAndResourcesJar
-
- // Enable dex compilation for the APEX variants, unless it is disabled explicitly
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
- if j.dexProperties.Compile_dex == nil {
- j.dexProperties.Compile_dex = proptools.BoolPtr(true)
- }
- if j.deviceProperties.Hostdex == nil {
- j.deviceProperties.Hostdex = proptools.BoolPtr(true)
- }
- }
-
- if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
- if j.hasCode(ctx) {
- if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
- android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
- }
- // Dex compilation
- var dexOutputFile android.OutputPath
- dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
- if ctx.Failed() {
- return
- }
-
- // Hidden API CSV generation and dex encoding
- dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.dexProperties.Uncompress_dex))
-
- // merge dex jar with resources if necessary
- if j.resourceJar != nil {
- jars := android.Paths{dexOutputFile, j.resourceJar}
- combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
- false, nil, nil)
- if *j.dexProperties.Uncompress_dex {
- combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
- TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
- dexOutputFile = combinedAlignedJar
- } else {
- dexOutputFile = combinedJar
- }
- }
-
- j.dexJarFile = dexOutputFile
-
- // Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
-
- outputFile = dexOutputFile
- } else {
- // There is no code to compile into a dex jar, make sure the resources are propagated
- // to the APK if this is an app.
- outputFile = implementationAndResourcesJar
- j.dexJarFile = j.resourceJar
- }
-
- if ctx.Failed() {
- return
- }
- } else {
- outputFile = implementationAndResourcesJar
- }
-
- if ctx.Device() {
- lintSDKVersionString := func(sdkSpec sdkSpec) string {
- if v := sdkSpec.version; v.isNumbered() {
- return v.String()
- } else {
- return ctx.Config().DefaultAppTargetSdk(ctx).String()
- }
- }
-
- j.linter.name = ctx.ModuleName()
- j.linter.srcs = srcFiles
- j.linter.srcJars = srcJars
- j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
- j.linter.classes = j.implementationJarFile
- j.linter.minSdkVersion = lintSDKVersionString(j.minSdkVersion())
- j.linter.targetSdkVersion = lintSDKVersionString(j.targetSdkVersion())
- j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
- j.linter.javaLanguageLevel = flags.javaVersion.String()
- j.linter.kotlinLanguageLevel = "1.3"
- if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
- j.linter.buildModuleReportZip = true
- }
- j.linter.lint(ctx)
- }
-
- ctx.CheckbuildFile(outputFile)
-
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
- ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
- ResourceJars: android.PathsIfNonNil(j.resourceJar),
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- SrcJarArgs: j.srcJarArgs,
- SrcJarDeps: j.srcJarDeps,
- ExportedPlugins: j.exportedPluginJars,
- ExportedPluginClasses: j.exportedPluginClasses,
- ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- JacocoReportClassesFile: j.jacocoReportClassesFile,
- })
-
- // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
- j.outputFile = outputFile.WithoutRel()
-}
-
-func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
-
- kzipName := pathtools.ReplaceExtension(jarName, "kzip")
- if idx >= 0 {
- kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
- jarName += strconv.Itoa(idx)
- }
-
- classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
- TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
-
- if ctx.Config().EmitXrefRules() {
- extractionFile := android.PathForModuleOut(ctx, kzipName)
- emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
- j.kytheFiles = append(j.kytheFiles, extractionFile)
- }
-
- return classes
-}
-
-// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
-// since some of these flags may be used internally.
-func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
- for _, flag := range flags {
- flag = strings.TrimSpace(flag)
-
- if !strings.HasPrefix(flag, "-") {
- ctx.PropertyErrorf("kotlincflags", "Flag `%s` must start with `-`", flag)
- } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
- ctx.PropertyErrorf("kotlincflags",
- "Bad flag: `%s`, only use internal compiler for consistency.", flag)
- } else if inList(flag, config.KotlincIllegalFlags) {
- ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
- } else if flag == "-include-runtime" {
- ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
- } else {
- args := strings.Split(flag, " ")
- if args[0] == "-kotlin-home" {
- ctx.PropertyErrorf("kotlincflags",
- "Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo).", flag)
- }
- }
- }
-}
-
-func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
- deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
-
- var jars android.Paths
- if len(srcFiles) > 0 || len(srcJars) > 0 {
- // Compile java sources into turbine.jar.
- turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
- TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
- if ctx.Failed() {
- return nil, nil
- }
- jars = append(jars, turbineJar)
- }
-
- jars = append(jars, extraJars...)
-
- // Combine any static header libraries into classes-header.jar. If there is only
- // one input jar this step will be skipped.
- jars = append(jars, deps.staticHeaderJars...)
-
- // we cannot skip the combine step for now if there is only one jar
- // since we have to strip META-INF/TRANSITIVE dir from turbine.jar
- combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
- false, nil, []string{"META-INF/TRANSITIVE"})
- headerJar = combinedJar
- jarjarHeaderJar = combinedJar
-
- if j.expandJarjarRules != nil {
- // Transform classes.jar into classes-jarjar.jar
- jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
- TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
- jarjarHeaderJar = jarjarFile
- if ctx.Failed() {
- return nil, nil
- }
- }
-
- return headerJar, jarjarHeaderJar
-}
-
-func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.OutputPath {
-
- specs := j.jacocoModuleToZipCommand(ctx)
-
- jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
- instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
-
- jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
-
- j.jacocoReportClassesFile = jacocoReportClassesFile
-
- return instrumentedJar
-}
-
-func (j *Module) HeaderJars() android.Paths {
- if j.headerJarFile == nil {
- return nil
- }
- return android.Paths{j.headerJarFile}
-}
-
-func (j *Module) ImplementationJars() android.Paths {
- if j.implementationJarFile == nil {
- return nil
- }
- return android.Paths{j.implementationJarFile}
-}
-
-func (j *Module) DexJarBuildPath() android.Path {
- return j.dexJarFile
-}
-
-func (j *Module) DexJarInstallPath() android.Path {
- return j.installFile
-}
-
-func (j *Module) ImplementationAndResourcesJars() android.Paths {
- if j.implementationAndResourcesJar == nil {
- return nil
- }
- return android.Paths{j.implementationAndResourcesJar}
-}
-
-func (j *Module) AidlIncludeDirs() android.Paths {
- // exportAidlIncludeDirs is type android.Paths already
- return j.exportAidlIncludeDirs
-}
-
-func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
- return j.classLoaderContexts
-}
-
-var _ logtagsProducer = (*Module)(nil)
-
-func (j *Module) logtags() android.Paths {
- return j.logtagsSrcs
-}
-
-// Collect information for opening IDE project files in java/jdeps.go.
-func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
- dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
- dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
- dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
- if j.expandJarjarRules != nil {
- dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
- }
- dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
-}
-
-func (j *Module) CompilerDeps() []string {
- jdeps := []string{}
- jdeps = append(jdeps, j.properties.Libs...)
- jdeps = append(jdeps, j.properties.Static_libs...)
- return jdeps
-}
-
-func (j *Module) hasCode(ctx android.ModuleContext) bool {
- srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
- return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
-}
-
-// Implements android.ApexModule
-func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return j.depIsInSameApex(ctx, dep)
-}
-
-// Implements android.ApexModule
-func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- sdkSpec := j.minSdkVersion()
- if !sdkSpec.specified() {
- return fmt.Errorf("min_sdk_version is not specified")
- }
- if sdkSpec.kind == sdkCore {
- return nil
- }
- ver, err := sdkSpec.effectiveVersion(ctx)
- if err != nil {
- return err
- }
- if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", ver)
- }
- return nil
-}
-
-func (j *Module) Stem() string {
- return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
-}
-
-// ConfigurationName returns the name of the module as used in build configuration.
-//
-// This is usually the same as BaseModuleName() except for the <x>.impl libraries created by
-// java_sdk_library in which case this is the BaseModuleName() without the ".impl" suffix,
-// i.e. just <x>.
-func (j *Module) ConfigurationName() string {
- return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName())
-}
-
-func (j *Module) JacocoReportClassesFile() android.Path {
- return j.jacocoReportClassesFile
-}
-
-func (j *Module) IsInstallable() bool {
- return Bool(j.properties.Installable)
-}
-
//
// Java libraries (.jar file)
//
@@ -3412,16 +1661,6 @@
var String = proptools.String
var inList = android.InList
-// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
-// this interface.
-type ProvidesUsesLib interface {
- ProvidesUsesLib() *string
-}
-
-func (j *Module) ProvidesUsesLib() *string {
- return j.usesLibraryProperties.Provides_uses_lib
-}
-
// Add class loader context (CLC) of a given dependency to the current CLC.
func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
clcMap dexpreopt.ClassLoaderContextMap) {
diff --git a/java/java_test.go b/java/java_test.go
index 2eb7241..d27a73d 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -25,12 +25,12 @@
"strings"
"testing"
- "android/soong/genrule"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
+ "android/soong/genrule"
"android/soong/python"
)
@@ -48,24 +48,36 @@
os.RemoveAll(buildDir)
}
-// Factory to use to create fixtures for tests in this package.
+// Legacy factory to use to create fixtures for tests in this package.
+//
+// deprecated: See prepareForJavaTest
var javaFixtureFactory = android.NewFixtureFactory(
&buildDir,
+ prepareForJavaTest,
+)
+
+// Legacy preparer used for running tests within the java package.
+//
+// This includes everything that was needed to run any test in the java package prior to the
+// introduction of the test fixtures. Tests that are being converted to use fixtures directly
+// rather than through the testJava...() methods should avoid using this and instead use the
+// various preparers directly, using android.GroupFixturePreparers(...) to group them when
+// necessary.
+//
+// deprecated
+var prepareForJavaTest = android.GroupFixturePreparers(
genrule.PrepareForTestWithGenRuleBuildComponents,
// Get the CC build components but not default modules.
cc.PrepareForTestWithCcBuildComponents,
// Include all the default java modules.
PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithOverlayBuildComponents,
+ python.PrepareForTestWithPythonBuildComponents,
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_plugin", PluginFactory)
- ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
- ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
- ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
}),
- javaMockFS().AddToFixture(),
- PrepareForTestWithJavaSdkLibraryFiles,
dexpreopt.PrepareForTestWithDexpreopt,
)
@@ -100,11 +112,9 @@
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterModuleType("java_plugin", PluginFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
- ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
@@ -116,10 +126,6 @@
// Register module types and mutators from cc needed for JNI testing
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
- })
-
return ctx
}
@@ -247,7 +253,14 @@
// defaultModuleToPath constructs a path to the turbine generate jar for a default test module that
// is defined in PrepareForIntegrationTestWithJava
func defaultModuleToPath(name string) string {
- return filepath.Join(buildDir, ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
+ switch {
+ case name == `""`:
+ return name
+ case strings.HasSuffix(name, ".jar"):
+ return name
+ default:
+ return filepath.Join(buildDir, ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
+ }
}
func TestJavaLinkType(t *testing.T) {
@@ -1298,9 +1311,9 @@
})
foo := ctx.ModuleForTests("foo", "android_common")
- rule := foo.Rule("lint")
- if !strings.Contains(rule.RuleParams.Command, "--baseline lint-baseline.xml") {
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
t.Error("did not pass --baseline flag")
}
}
@@ -1320,9 +1333,9 @@
`, map[string][]byte{})
foo := ctx.ModuleForTests("foo", "android_common")
- rule := foo.Rule("lint")
- if strings.Contains(rule.RuleParams.Command, "--baseline") {
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command, "--baseline") {
t.Error("passed --baseline flag for non existent file")
}
}
@@ -1378,9 +1391,9 @@
})
foo := ctx.ModuleForTests("foo", "android_common")
- rule := foo.Rule("lint")
- if !strings.Contains(rule.RuleParams.Command, "--baseline mybaseline.xml") {
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
t.Error("did not use the correct file for baseline")
}
}
@@ -1422,7 +1435,9 @@
}
func TestTurbine(t *testing.T) {
- ctx, _ := testJava(t, `
+ result := javaFixtureFactory.
+ Extend(FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})).
+ RunTestWithBp(t, `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -1444,30 +1459,20 @@
}
`)
- fooTurbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine")
- barTurbine := ctx.ModuleForTests("bar", "android_common").Rule("turbine")
- barJavac := ctx.ModuleForTests("bar", "android_common").Rule("javac")
- barTurbineCombined := ctx.ModuleForTests("bar", "android_common").Description("for turbine")
- bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
+ fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
+ barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
+ barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
+ barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
+ bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
- if len(fooTurbine.Inputs) != 1 || fooTurbine.Inputs[0].String() != "a.java" {
- t.Errorf(`foo inputs %v != ["a.java"]`, fooTurbine.Inputs)
- }
+ android.AssertArrayString(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs.Strings())
fooHeaderJar := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
- if !strings.Contains(barTurbine.Args["classpath"], fooHeaderJar) {
- t.Errorf("bar turbine classpath %v does not contain %q", barTurbine.Args["classpath"], fooHeaderJar)
- }
- if !strings.Contains(barJavac.Args["classpath"], fooHeaderJar) {
- t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], fooHeaderJar)
- }
- if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar {
- t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar)
- }
- if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar") {
- t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
- "prebuilts/sdk/14/public/android.jar")
- }
+ barTurbineJar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine", "bar.jar")
+ android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["classpath"], fooHeaderJar)
+ android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
+ android.AssertArrayString(t, "bar turbine combineJar", []string{barTurbineJar, fooHeaderJar}, barTurbineCombined.Inputs.Strings())
+ android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "prebuilts/sdk/14/public/android.jar")
}
func TestSharding(t *testing.T) {
diff --git a/java/lint.go b/java/lint.go
index fccd1a5..938e2b0 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -218,7 +218,7 @@
// The list of resources may be too long to put on the command line, but
// we can't use the rsp file because it is already being used for srcs.
// Insert a second rule to write out the list of resources to a file.
- resourcesList = android.PathForModuleOut(ctx, "lint", "resources.list")
+ resourcesList = android.PathForModuleOut(ctx, "resources.list")
resListRule := android.NewRuleBuilder(pctx, ctx)
resListRule.Command().Text("cp").
FlagWithRspFileInputList("", resourcesList.ReplaceExtension(ctx, "rsp"), l.resources).
@@ -233,7 +233,7 @@
cacheDir := android.PathForModuleOut(ctx, "lint", "cache")
homeDir := android.PathForModuleOut(ctx, "lint", "home")
- srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
+ srcJarDir := android.PathForModuleOut(ctx, "lint", "srcjars")
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
// TODO(ccross): this is a little fishy. The files extracted from the srcjars are referenced
// by the project.xml and used by the later lint rule, but the lint rule depends on the srcjars,
@@ -248,6 +248,7 @@
FlagWithRspFileInputList("", srcsListRsp, l.srcs).
Output(srcsList)
trackRSPDependency(l.srcs, srcsList)
+ rule.Temporary(srcsList)
cmd := rule.Command().
BuiltTool("lint-project-xml").
@@ -262,11 +263,11 @@
cmd.Flag("--test")
}
if l.manifest != nil {
- cmd.FlagWithArg("--manifest ", l.manifest.String())
+ cmd.FlagWithArg("--manifest ", cmd.PathForInput(l.manifest))
trackInputDependency(l.manifest)
}
if l.mergedManifest != nil {
- cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String())
+ cmd.FlagWithArg("--merged_manifest ", cmd.PathForInput(l.mergedManifest))
trackInputDependency(l.mergedManifest)
}
@@ -279,23 +280,17 @@
}
if l.classes != nil {
- cmd.FlagWithArg("--classes ", l.classes.String())
+ cmd.FlagWithArg("--classes ", cmd.PathForInput(l.classes))
trackInputDependency(l.classes)
}
- cmd.FlagForEachArg("--classpath ", l.classpath.Strings())
+ cmd.FlagForEachArg("--classpath ", cmd.PathsForInputs(l.classpath))
trackInputDependency(l.classpath...)
- cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
+ cmd.FlagForEachArg("--extra_checks_jar ", cmd.PathsForInputs(l.extraLintCheckJars))
trackInputDependency(l.extraLintCheckJars...)
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") &&
- lintRBEExecStrategy(ctx) != remoteexec.LocalExecStrategy {
- // TODO(b/181912787): remove these and use "." instead.
- cmd.FlagWithArg("--root_dir ", "/b/f/w")
- } else {
- cmd.FlagWithArg("--root_dir ", "$PWD")
- }
+ cmd.FlagWithArg("--root_dir ", "$PWD")
// The cache tag in project.xml is relative to the root dir, or the project.xml file if
// the root dir is not set.
@@ -325,7 +320,7 @@
// generateManifest adds a command to the rule to write a simple manifest that contains the
// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
-func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.Path {
+func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml")
rule.Command().Text("(").
@@ -356,18 +351,36 @@
}
}
- rule := android.NewRuleBuilder(pctx, ctx)
+ rule := android.NewRuleBuilder(pctx, ctx).
+ Sbox(android.PathForModuleOut(ctx, "lint"),
+ android.PathForModuleOut(ctx, "lint.sbox.textproto")).
+ SandboxInputs()
+
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+ pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
+ rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+ rule.Rewrapper(&remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "lint"},
+ ExecStrategy: lintRBEExecStrategy(ctx),
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ EnvironmentVariables: []string{
+ "LANG",
+ },
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ })
+ }
if l.manifest == nil {
manifest := l.generateManifest(ctx, rule)
l.manifest = manifest
+ rule.Temporary(manifest)
}
lintPaths := l.writeLintProjectXML(ctx, rule)
- html := android.PathForModuleOut(ctx, "lint-report.html")
- text := android.PathForModuleOut(ctx, "lint-report.txt")
- xml := android.PathForModuleOut(ctx, "lint-report.xml")
+ html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
+ text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
+ xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
@@ -397,43 +410,7 @@
FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
- pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
- // TODO(b/181912787): this should be local fallback once the hack that passes /b/f/w in project.xml
- // is removed.
- execStrategy := lintRBEExecStrategy(ctx)
- labels := map[string]string{"type": "tool", "name": "lint"}
- rule.Remoteable(android.RemoteRuleSupports{RBE: true})
- remoteInputs := lintPaths.remoteInputs
- remoteInputs = append(remoteInputs,
- lintPaths.projectXML,
- lintPaths.configXML,
- lintPaths.homeDir,
- lintPaths.cacheDir,
- ctx.Config().HostJavaToolPath(ctx, "lint.jar"),
- annotationsZipPath,
- apiVersionsXMLPath,
- )
-
- cmd.Text((&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Inputs: remoteInputs.Strings(),
- OutputFiles: android.Paths{html, text, xml}.Strings(),
- RSPFile: strings.Join(lintPaths.remoteRSPInputs.Strings(), ","),
- EnvironmentVariables: []string{
- "JAVA_OPTS",
- "ANDROID_SDK_HOME",
- "SDK_ANNOTATIONS",
- "LINT_OPTS",
- "LANG",
- },
- Platform: map[string]string{remoteexec.PoolKey: pool},
- }).NoVarTemplate(ctx.Config()))
- }
-
- cmd.BuiltTool("lint").
+ cmd.BuiltTool("lint").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "lint.jar")).
Flag("--quiet").
FlagWithInput("--project ", lintPaths.projectXML).
FlagWithInput("--config ", lintPaths.configXML).
@@ -450,6 +427,9 @@
Implicit(apiVersionsXMLPath).
Implicits(lintPaths.deps)
+ rule.Temporary(lintPaths.projectXML)
+ rule.Temporary(lintPaths.configXML)
+
if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
cmd.FlagWithArg("--check ", checkOnly)
}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 4bfd4e2..03e82c2 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -15,17 +15,29 @@
package java
import (
+ "path/filepath"
+
"android/soong/android"
+ "github.com/google/blueprint"
+
"fmt"
)
func init() {
registerPlatformCompatConfigBuildComponents(android.InitRegistrationContext)
+
+ android.RegisterSdkMemberType(&compatConfigMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "compat_configs",
+ SupportsSdk: true,
+ },
+ })
}
func registerPlatformCompatConfigBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
ctx.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
+ ctx.RegisterModuleType("prebuilt_platform_compat_config", prebuiltCompatConfigFactory)
ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
}
@@ -35,16 +47,13 @@
return android.PathForOutput(ctx, "compat_config", "merged_compat_config.xml")
}
-type platformCompatConfigSingleton struct {
- metadata android.Path
-}
-
type platformCompatConfigProperties struct {
Src *string `android:"path"`
}
type platformCompatConfig struct {
android.ModuleBase
+ android.SdkBase
properties platformCompatConfigProperties
installDirPath android.InstallPath
@@ -52,7 +61,7 @@
metadataFile android.OutputPath
}
-func (p *platformCompatConfig) compatConfigMetadata() android.OutputPath {
+func (p *platformCompatConfig) compatConfigMetadata() android.Path {
return p.metadataFile
}
@@ -64,52 +73,20 @@
return "compatconfig"
}
+type platformCompatConfigMetadataProvider interface {
+ compatConfigMetadata() android.Path
+}
+
type PlatformCompatConfigIntf interface {
android.Module
- compatConfigMetadata() android.OutputPath
CompatConfig() android.OutputPath
// Sub dir under etc dir.
SubDir() string
}
var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil)
-
-// compat singleton rules
-func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
-
- var compatConfigMetadata android.Paths
-
- ctx.VisitAllModules(func(module android.Module) {
- if c, ok := module.(PlatformCompatConfigIntf); ok {
- metadata := c.compatConfigMetadata()
- compatConfigMetadata = append(compatConfigMetadata, metadata)
- }
- })
-
- if compatConfigMetadata == nil {
- // nothing to do.
- return
- }
-
- rule := android.NewRuleBuilder(pctx, ctx)
- outputPath := platformCompatConfigPath(ctx)
-
- rule.Command().
- BuiltTool("process-compat-config").
- FlagForEachInput("--xml ", compatConfigMetadata).
- FlagWithOutput("--merged-config ", outputPath)
-
- rule.Build("merged-compat-config", "Merge compat config")
-
- p.metadata = outputPath
-}
-
-func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
- if p.metadata != nil {
- ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String())
- }
-}
+var _ platformCompatConfigMetadataProvider = (*platformCompatConfig)(nil)
func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule := android.NewRuleBuilder(pctx, ctx)
@@ -145,17 +122,144 @@
}}
}
-func platformCompatConfigSingletonFactory() android.Singleton {
- return &platformCompatConfigSingleton{}
-}
-
func PlatformCompatConfigFactory() android.Module {
module := &platformCompatConfig{}
module.AddProperties(&module.properties)
+ android.InitSdkAwareModule(module)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
+type compatConfigMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (b *compatConfigMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+ mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (b *compatConfigMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*platformCompatConfig)
+ return ok
+}
+
+func (b *compatConfigMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
+ return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_platform_compat_config")
+}
+
+func (b *compatConfigMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ return &compatConfigSdkMemberProperties{}
+}
+
+type compatConfigSdkMemberProperties struct {
+ android.SdkMemberPropertiesBase
+
+ Metadata android.Path
+}
+
+func (b *compatConfigSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
+ module := variant.(*platformCompatConfig)
+ b.Metadata = module.metadataFile
+}
+
+func (b *compatConfigSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
+ builder := ctx.SnapshotBuilder()
+ if b.Metadata != nil {
+ snapshotRelativePath := filepath.Join("compat_configs", ctx.Name(), b.Metadata.Base())
+ builder.CopyToSnapshot(b.Metadata, snapshotRelativePath)
+ propertySet.AddProperty("metadata", snapshotRelativePath)
+ }
+}
+
+var _ android.SdkMemberType = (*compatConfigMemberType)(nil)
+
+// A prebuilt version of the platform compat config module.
+type prebuiltCompatConfigModule struct {
+ android.ModuleBase
+ android.SdkBase
+ prebuilt android.Prebuilt
+
+ properties prebuiltCompatConfigProperties
+
+ metadataFile android.Path
+}
+
+type prebuiltCompatConfigProperties struct {
+ Metadata *string `android:"path"`
+}
+
+func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
+ return &module.prebuilt
+}
+
+func (module *prebuiltCompatConfigModule) Name() string {
+ return module.prebuilt.Name(module.ModuleBase.Name())
+}
+
+func (module *prebuiltCompatConfigModule) compatConfigMetadata() android.Path {
+ return module.metadataFile
+}
+
+var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
+
+func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
+}
+
+// A prebuilt version of platform_compat_config that provides the metadata.
+func prebuiltCompatConfigFactory() android.Module {
+ m := &prebuiltCompatConfigModule{}
+ m.AddProperties(&m.properties)
+ android.InitSingleSourcePrebuiltModule(m, &m.properties, "Metadata")
+ android.InitSdkAwareModule(m)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+// compat singleton rules
+type platformCompatConfigSingleton struct {
+ metadata android.Path
+}
+
+func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+
+ var compatConfigMetadata android.Paths
+
+ ctx.VisitAllModules(func(module android.Module) {
+ if c, ok := module.(platformCompatConfigMetadataProvider); ok {
+ metadata := c.compatConfigMetadata()
+ compatConfigMetadata = append(compatConfigMetadata, metadata)
+ }
+ })
+
+ if compatConfigMetadata == nil {
+ // nothing to do.
+ return
+ }
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ outputPath := platformCompatConfigPath(ctx)
+
+ rule.Command().
+ BuiltTool("process-compat-config").
+ FlagForEachInput("--xml ", compatConfigMetadata).
+ FlagWithOutput("--merged-config ", outputPath)
+
+ rule.Build("merged-compat-config", "Merge compat config")
+
+ p.metadata = outputPath
+}
+
+func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
+ if p.metadata != nil {
+ ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String())
+ }
+}
+
+func platformCompatConfigSingletonFactory() android.Singleton {
+ return &platformCompatConfigSingleton{}
+}
+
//============== merged_compat_config =================
type globalCompatConfigProperties struct {
// name of the file into which the metadata will be copied.
diff --git a/java/platform_compat_config_test.go b/java/platform_compat_config_test.go
new file mode 100644
index 0000000..80d991c
--- /dev/null
+++ b/java/platform_compat_config_test.go
@@ -0,0 +1,44 @@
+// Copyright 2021 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 java
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestPlatformCompatConfig(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithPlatformCompatConfig,
+ android.FixtureWithRootAndroidBp(`
+ platform_compat_config {
+ name: "myconfig2",
+ }
+ platform_compat_config {
+ name: "myconfig1",
+ }
+ platform_compat_config {
+ name: "myconfig3",
+ }
+ `),
+ ).RunTest(t)
+
+ CheckMergedCompatConfigInputs(t, result, "myconfig",
+ "out/soong/.intermediates/myconfig1/myconfig1_meta.xml",
+ "out/soong/.intermediates/myconfig2/myconfig2_meta.xml",
+ "out/soong/.intermediates/myconfig3/myconfig3_meta.xml",
+ )
+}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index dc90ea3..37875a4 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -27,6 +27,7 @@
)
func TestClasspath(t *testing.T) {
+ const frameworkAidl = "-I" + defaultJavaDir + "/framework/aidl"
var classpathTestcases = []struct {
name string
unbundled bool
@@ -52,7 +53,7 @@
system: config.StableCorePlatformSystemModules,
java8classpath: config.FrameworkLibraries,
java9classpath: config.FrameworkLibraries,
- aidl: "-Iframework/aidl",
+ aidl: frameworkAidl,
},
{
name: `sdk_version:"core_platform"`,
@@ -69,7 +70,7 @@
system: config.StableCorePlatformSystemModules,
java8classpath: config.FrameworkLibraries,
java9classpath: config.FrameworkLibraries,
- aidl: "-Iframework/aidl",
+ aidl: frameworkAidl,
},
{
@@ -263,7 +264,7 @@
convertModulesToPaths := func(cp []string) []string {
ret := make([]string, len(cp))
for i, e := range cp {
- ret[i] = moduleToPath(e)
+ ret[i] = defaultModuleToPath(e)
}
return ret
}
@@ -299,6 +300,8 @@
dir := ""
if strings.HasPrefix(testcase.system, "sdk_public_") {
dir = "prebuilts/sdk"
+ } else {
+ dir = defaultJavaDir
}
system = "--system=" + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system")
// The module-relative parts of these paths are hardcoded in system_modules.go:
@@ -309,8 +312,8 @@
}
}
- checkClasspath := func(t *testing.T, ctx *android.TestContext, isJava8 bool) {
- foo := ctx.ModuleForTests("foo", variant)
+ checkClasspath := func(t *testing.T, result *android.TestResult, isJava8 bool) {
+ foo := result.ModuleForTests("foo", variant)
javac := foo.Rule("javac")
var deps []string
@@ -349,78 +352,68 @@
}
}
+ fixtureFactory := javaFixtureFactory.Extend(
+ FixtureWithPrebuiltApis(map[string][]string{
+ "29": {},
+ "30": {},
+ "current": {},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if testcase.unbundled {
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ }
+ }),
+ android.FixtureModifyEnv(func(env map[string]string) {
+ if env["ANDROID_JAVA8_HOME"] == "" {
+ env["ANDROID_JAVA8_HOME"] = "jdk8"
+ }
+ }),
+ )
+
// Test with legacy javac -source 1.8 -target 1.8
t.Run("Java language level 8", func(t *testing.T) {
- config := testConfig(nil, bpJava8, nil)
- if testcase.unbundled {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- }
- ctx := testContext(config)
- run(t, ctx, config)
+ result := fixtureFactory.RunTestWithBp(t, bpJava8)
- checkClasspath(t, ctx, true /* isJava8 */)
+ checkClasspath(t, result, true /* isJava8 */)
if testcase.host != android.Host {
- aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
+ aidl := result.ModuleForTests("foo", variant).Rule("aidl")
- if g, w := aidl.RuleParams.Command, testcase.aidl+" -I."; !strings.Contains(g, w) {
- t.Errorf("want aidl command to contain %q, got %q", w, g)
- }
+ android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
})
// Test with default javac -source 9 -target 9
t.Run("Java language level 9", func(t *testing.T) {
- config := testConfig(nil, bp, nil)
- if testcase.unbundled {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- }
- ctx := testContext(config)
- run(t, ctx, config)
+ result := fixtureFactory.RunTestWithBp(t, bp)
- checkClasspath(t, ctx, false /* isJava8 */)
+ checkClasspath(t, result, false /* isJava8 */)
if testcase.host != android.Host {
- aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
+ aidl := result.ModuleForTests("foo", variant).Rule("aidl")
- if g, w := aidl.RuleParams.Command, testcase.aidl+" -I."; !strings.Contains(g, w) {
- t.Errorf("want aidl command to contain %q, got %q", w, g)
- }
+ android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
})
+ prepareWithPlatformVersionRel := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_codename = proptools.StringPtr("REL")
+ variables.Platform_sdk_final = proptools.BoolPtr(true)
+ })
+
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8
t.Run("REL + Java language level 8", func(t *testing.T) {
- config := testConfig(nil, bpJava8, nil)
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
- config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
+ result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8)
- if testcase.unbundled {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- }
- ctx := testContext(config)
- run(t, ctx, config)
-
- checkClasspath(t, ctx, true /* isJava8 */)
+ checkClasspath(t, result, true /* isJava8 */)
})
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9
t.Run("REL + Java language level 9", func(t *testing.T) {
- config := testConfig(nil, bp, nil)
- config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
- config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
+ result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bp)
- if testcase.unbundled {
- config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
- config.TestProductVariables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- }
- ctx := testContext(config)
- run(t, ctx, config)
-
- checkClasspath(t, ctx, false /* isJava8 */)
+ checkClasspath(t, result, false /* isJava8 */)
})
})
}
diff --git a/java/testing.go b/java/testing.go
index 896bcf8..b0290dc 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -24,8 +24,6 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/python"
-
"github.com/google/blueprint"
)
@@ -41,18 +39,23 @@
// module types as possible. The exceptions are those module types that require mutators and/or
// singletons in order to function in which case they should be kept together in a separate
// preparer.
-var PrepareForTestWithJavaBuildComponents = android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest)
+var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers(
+ // Make sure that mutators and module types, e.g. prebuilt mutators available.
+ android.PrepareForTestWithAndroidBuildComponents,
+ // Make java build components available to the test.
+ android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+)
// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
- // Make sure that mutators and module types, e.g. prebuilt mutators available.
- android.PrepareForTestWithAndroidBuildComponents,
// Make sure that all the module types used in the defaults are registered.
PrepareForTestWithJavaBuildComponents,
// The java default module definitions.
android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", GatherRequiredDepsForTest()),
)
+var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents)
+
// Prepare a fixture to use all java module types, mutators and singletons fully.
//
// This should only be used by tests that want to run with as much of the build enabled as possible.
@@ -62,9 +65,7 @@
)
// Prepare a fixture with the standard files required by a java_sdk_library module.
-var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(javaSdkLibraryFiles)
-
-var javaSdkLibraryFiles = android.MockFS{
+var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(android.MockFS{
"api/current.txt": nil,
"api/removed.txt": nil,
"api/system-current.txt": nil,
@@ -75,7 +76,7 @@
"api/module-lib-removed.txt": nil,
"api/system-server-current.txt": nil,
"api/system-server-removed.txt": nil,
-}
+})
// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified
// modules for the `last` API release. By `last` it just means last in the list of supplied versions
@@ -127,49 +128,15 @@
mockFS.Merge(prebuiltApisFilesForLibs([]string{release}, libs))
}
return android.GroupFixturePreparers(
- // A temporary measure to discard the definitions provided by default by javaMockFS() to allow
- // the changes that use this preparer to fix tests to be separated from the change to remove
- // javaMockFS().
- android.FixtureModifyMockFS(func(fs android.MockFS) {
- for k, _ := range fs {
- if strings.HasPrefix(k, "prebuilts/sdk/") {
- delete(fs, k)
- }
- }
- }),
android.FixtureAddTextFile(path, bp),
android.FixtureMergeMockFs(mockFS),
)
}
-func javaMockFS() android.MockFS {
- mockFS := android.MockFS{
- "prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
- "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`),
-
- "bin.py": nil,
- python.StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
- MAIN_FILE = '%main%'`),
- }
-
- levels := []string{"14", "28", "29", "30", "current"}
- libs := []string{
- "android", "foo", "bar", "sdklib", "barney", "betty", "foo-shared_library",
- "foo-no_shared_library", "core-for-system-modules", "quuz", "qux", "fred",
- "runtime-library",
- }
- for k, v := range prebuiltApisFilesForLibs(levels, libs) {
- mockFS[k] = v
- }
-
- return mockFS
-}
-
func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
bp += GatherRequiredDepsForTest()
- mockFS := javaMockFS()
- mockFS.Merge(javaSdkLibraryFiles)
+ mockFS := android.MockFS{}
cc.GatherRequiredFilesForTest(mockFS)
@@ -354,3 +321,12 @@
t.Errorf("Expected hiddenapi rule inputs:\n%s\nactual inputs:\n%s", expected, actual)
}
}
+
+// Check that the merged file create by platform_compat_config_singleton has the correct inputs.
+func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) {
+ sourceGlobalCompatConfig := result.SingletonForTests("platform_compat_config_singleton")
+ allOutputs := sourceGlobalCompatConfig.AllOutputs()
+ android.AssertIntEquals(t, message+": output len", 1, len(allOutputs))
+ output := sourceGlobalCompatConfig.Output(allOutputs[0])
+ android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits)
+}
diff --git a/python/Android.bp b/python/Android.bp
index b633f1e..e49fa6a 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -20,6 +20,7 @@
"proto.go",
"python.go",
"test.go",
+ "testing.go",
],
testSrcs: [
"python_test.go",
diff --git a/python/binary.go b/python/binary.go
index 372b8a8..6061ad4 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -26,10 +26,14 @@
)
func init() {
- android.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
+ registerPythonBinaryComponents(android.InitRegistrationContext)
android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
}
+func registerPythonBinaryComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
+}
+
type bazelPythonBinaryAttributes struct {
Main string
Srcs bazel.LabelList
diff --git a/python/library.go b/python/library.go
index b724d2b..9663b3c 100644
--- a/python/library.go
+++ b/python/library.go
@@ -21,8 +21,12 @@
)
func init() {
- android.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
- android.RegisterModuleType("python_library", PythonLibraryFactory)
+ registerPythonLibraryComponents(android.InitRegistrationContext)
+}
+
+func registerPythonLibraryComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
+ ctx.RegisterModuleType("python_library", PythonLibraryFactory)
}
func PythonLibraryHostFactory() android.Module {
diff --git a/python/python.go b/python/python.go
index a078c0b..4444a70 100644
--- a/python/python.go
+++ b/python/python.go
@@ -29,7 +29,11 @@
)
func init() {
- android.PreDepsMutators(RegisterPythonPreDepsMutators)
+ registerPythonMutators(android.InitRegistrationContext)
+}
+
+func registerPythonMutators(ctx android.RegistrationContext) {
+ ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
}
// Exported to support other packages using Python modules in tests.
diff --git a/python/python_test.go b/python/python_test.go
index 5c4efa7..f57f504 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -15,21 +15,15 @@
package python
import (
- "errors"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
- "reflect"
- "sort"
- "strings"
+ "regexp"
"testing"
"android/soong/android"
)
-var buildDir string
-
type pyModule struct {
name string
actualVersion string
@@ -56,7 +50,7 @@
data = []struct {
desc string
- mockFiles map[string][]byte
+ mockFiles android.MockFS
errors []string
expectedBinaries []pyModule
@@ -64,7 +58,6 @@
{
desc: "module without any src files",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -79,7 +72,6 @@
{
desc: "module with bad src file ext",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -98,7 +90,6 @@
{
desc: "module with bad data file ext",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -121,7 +112,6 @@
{
desc: "module with bad pkg_path format",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -159,7 +149,6 @@
{
desc: "module with bad runfile src path format",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -187,7 +176,6 @@
{
desc: "module with duplicate runfile path",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_library_host {
name: "lib1",
@@ -207,21 +195,32 @@
"lib1",
],
}
+
+ python_binary_host {
+ name: "bin",
+ pkg_path: "e/",
+ srcs: [
+ "bin.py",
+ ],
+ libs: [
+ "lib2",
+ ],
+ }
`,
),
"dir/c/file1.py": nil,
"dir/file1.py": nil,
+ "dir/bin.py": nil,
},
errors: []string{
- fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:9:6",
- "lib2", "PY3", "a/b/c/file1.py", "lib2", "dir/file1.py",
+ fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:20:6",
+ "bin", "PY3", "a/b/c/file1.py", "bin", "dir/file1.py",
"lib1", "dir/c/file1.py"),
},
},
{
desc: "module for testing dependencies",
mockFiles: map[string][]byte{
- bpFile: []byte(`subdirs = ["dir"]`),
filepath.Join("dir", bpFile): []byte(
`python_defaults {
name: "default_lib",
@@ -314,10 +313,10 @@
"e/default_py3.py",
"e/file4.py",
},
- srcsZip: "@prefix@/.intermediates/dir/bin/PY3/bin.py.srcszip",
+ srcsZip: "out/soong/.intermediates/dir/bin/PY3/bin.py.srcszip",
depsSrcsZips: []string{
- "@prefix@/.intermediates/dir/lib5/PY3/lib5.py.srcszip",
- "@prefix@/.intermediates/dir/lib6/PY3/lib6.py.srcszip",
+ "out/soong/.intermediates/dir/lib5/PY3/lib5.py.srcszip",
+ "out/soong/.intermediates/dir/lib6/PY3/lib6.py.srcszip",
},
},
},
@@ -327,60 +326,36 @@
func TestPythonModule(t *testing.T) {
for _, d := range data {
+ if d.desc != "module with duplicate runfile path" {
+ continue
+ }
+ errorPatterns := make([]string, len(d.errors))
+ for i, s := range d.errors {
+ errorPatterns[i] = regexp.QuoteMeta(s)
+ }
+
t.Run(d.desc, func(t *testing.T) {
- config := android.TestConfig(buildDir, nil, "", d.mockFiles)
- ctx := android.NewTestContext(config)
- ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
- ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
- ctx.RegisterModuleType("python_binary_host", PythonBinaryHostFactory)
- ctx.RegisterModuleType("python_defaults", defaultsFactory)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.Register()
- _, testErrs := ctx.ParseBlueprintsFiles(bpFile)
- android.FailIfErrored(t, testErrs)
- _, actErrs := ctx.PrepareBuildActions(config)
- if len(actErrs) > 0 {
- testErrs = append(testErrs, expectErrors(t, actErrs, d.errors)...)
- } else {
- for _, e := range d.expectedBinaries {
- testErrs = append(testErrs,
- expectModule(t, ctx, buildDir, e.name,
- e.actualVersion,
- e.srcsZip,
- e.pyRunfiles,
- e.depsSrcsZips)...)
- }
+ result := android.GroupFixturePreparers(
+ android.PrepareForTestWithDefaults,
+ PrepareForTestWithPythonBuildComponents,
+ d.mockFiles.AddToFixture(),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(errorPatterns)).
+ RunTest(t)
+
+ if len(result.Errs) > 0 {
+ return
}
- android.FailIfErrored(t, testErrs)
+
+ for _, e := range d.expectedBinaries {
+ t.Run(e.name, func(t *testing.T) {
+ expectModule(t, result.TestContext, e.name, e.actualVersion, e.srcsZip, e.pyRunfiles, e.depsSrcsZips)
+ })
+ }
})
}
}
-func expectErrors(t *testing.T, actErrs []error, expErrs []string) (testErrs []error) {
- actErrStrs := []string{}
- for _, v := range actErrs {
- actErrStrs = append(actErrStrs, v.Error())
- }
- sort.Strings(actErrStrs)
- if len(actErrStrs) != len(expErrs) {
- t.Errorf("got (%d) errors, expected (%d) errors!", len(actErrStrs), len(expErrs))
- for _, v := range actErrStrs {
- testErrs = append(testErrs, errors.New(v))
- }
- } else {
- sort.Strings(expErrs)
- for i, v := range actErrStrs {
- if !strings.Contains(v, expErrs[i]) {
- testErrs = append(testErrs, errors.New(v))
- }
- }
- }
-
- return
-}
-
-func expectModule(t *testing.T, ctx *android.TestContext, buildDir, name, variant, expectedSrcsZip string,
- expectedPyRunfiles, expectedDepsSrcsZips []string) (testErrs []error) {
+func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles, expectedDepsSrcsZips []string) {
module := ctx.ModuleForTests(name, variant)
base, baseOk := module.Module().(*Module)
@@ -393,56 +368,13 @@
actualPyRunfiles = append(actualPyRunfiles, path.dest)
}
- if !reflect.DeepEqual(actualPyRunfiles, expectedPyRunfiles) {
- testErrs = append(testErrs, errors.New(fmt.Sprintf(
- `binary "%s" variant "%s" has unexpected pyRunfiles: %q! (expected: %q)`,
- base.Name(),
- base.properties.Actual_version,
- actualPyRunfiles,
- expectedPyRunfiles)))
- }
+ android.AssertDeepEquals(t, "pyRunfiles", expectedPyRunfiles, actualPyRunfiles)
- if base.srcsZip.String() != strings.Replace(expectedSrcsZip, "@prefix@", buildDir, 1) {
- testErrs = append(testErrs, errors.New(fmt.Sprintf(
- `binary "%s" variant "%s" has unexpected srcsZip: %q!`,
- base.Name(),
- base.properties.Actual_version,
- base.srcsZip)))
- }
+ android.AssertPathRelativeToTopEquals(t, "srcsZip", expectedSrcsZip, base.srcsZip)
- for i, _ := range expectedDepsSrcsZips {
- expectedDepsSrcsZips[i] = strings.Replace(expectedDepsSrcsZips[i], "@prefix@", buildDir, 1)
- }
- if !reflect.DeepEqual(base.depsSrcsZips.Strings(), expectedDepsSrcsZips) {
- testErrs = append(testErrs, errors.New(fmt.Sprintf(
- `binary "%s" variant "%s" has unexpected depsSrcsZips: %q!`,
- base.Name(),
- base.properties.Actual_version,
- base.depsSrcsZips)))
- }
-
- return
-}
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_python_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
+ android.AssertPathsRelativeToTopEquals(t, "depsSrcsZips", expectedDepsSrcsZips, base.depsSrcsZips)
}
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
diff --git a/python/test.go b/python/test.go
index b7cd475..6713189 100644
--- a/python/test.go
+++ b/python/test.go
@@ -22,8 +22,12 @@
// This file contains the module types for building Python test.
func init() {
- android.RegisterModuleType("python_test_host", PythonTestHostFactory)
- android.RegisterModuleType("python_test", PythonTestFactory)
+ registerPythonTestComponents(android.InitRegistrationContext)
+}
+
+func registerPythonTestComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_test_host", PythonTestHostFactory)
+ ctx.RegisterModuleType("python_test", PythonTestFactory)
}
// Test option struct.
diff --git a/python/testing.go b/python/testing.go
new file mode 100644
index 0000000..ce1a5ab
--- /dev/null
+++ b/python/testing.go
@@ -0,0 +1,24 @@
+// Copyright 2021 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 python
+
+import "android/soong/android"
+
+var PrepareForTestWithPythonBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerPythonBinaryComponents),
+ android.FixtureRegisterWithContext(registerPythonLibraryComponents),
+ android.FixtureRegisterWithContext(registerPythonTestComponents),
+ android.FixtureRegisterWithContext(registerPythonMutators),
+)
diff --git a/remoteexec/Android.bp b/remoteexec/Android.bp
index 9f75df5..0d55168 100644
--- a/remoteexec/Android.bp
+++ b/remoteexec/Android.bp
@@ -5,10 +5,6 @@
bootstrap_go_package {
name: "soong-remoteexec",
pkgPath: "android/soong/remoteexec",
- deps: [
- "blueprint",
- "soong-android",
- ],
srcs: [
"remoteexec.go",
],
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index 5f0426a..166f68c 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -17,10 +17,6 @@
import (
"sort"
"strings"
-
- "android/soong/android"
-
- "github.com/google/blueprint"
)
const (
@@ -56,7 +52,6 @@
var (
defaultLabels = map[string]string{"type": "tool"}
defaultExecStrategy = LocalExecStrategy
- pctx = android.NewPackageContext("android/soong/remoteexec")
)
// REParams holds information pertinent to the remote execution of a rule.
@@ -87,28 +82,18 @@
}
func init() {
- pctx.VariableFunc("Wrapper", func(ctx android.PackageVarContext) string {
- return wrapper(ctx.Config())
- })
-}
-
-func wrapper(cfg android.Config) string {
- if override := cfg.Getenv("RBE_WRAPPER"); override != "" {
- return override
- }
- return DefaultWrapperPath
}
// Template generates the remote execution wrapper template to be added as a prefix to the rule's
// command.
func (r *REParams) Template() string {
- return "${remoteexec.Wrapper}" + r.wrapperArgs()
+ return "${android.RBEWrapper}" + r.wrapperArgs()
}
// NoVarTemplate generates the remote execution wrapper template without variables, to be used in
// RuleBuilder.
-func (r *REParams) NoVarTemplate(cfg android.Config) string {
- return wrapper(cfg) + r.wrapperArgs()
+func (r *REParams) NoVarTemplate(wrapper string) string {
+ return wrapper + r.wrapperArgs()
}
func (r *REParams) wrapperArgs() string {
@@ -171,43 +156,3 @@
return args + " -- "
}
-
-// StaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
-// locally executable rule and the second rule is a remotely executable rule. commonArgs are args
-// used for both the local and remotely executable rules. reArgs are used only for remote
-// execution.
-func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams *REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
- ruleParamsRE := ruleParams
- ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
- ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
-
- return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
- ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
-}
-
-// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first
-// rule is a locally executable rule and the second rule is a remotely executable rule. This
-// function supports multiple remote execution wrappers placed in the template when commands are
-// chained together with &&. commonArgs are args used for both the local and remotely executable
-// rules. reArgs are args used only for remote execution.
-func MultiCommandStaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams map[string]*REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
- ruleParamsRE := ruleParams
- for k, v := range reParams {
- ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "")
- ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template())
- }
-
- return ctx.AndroidStaticRule(name, ruleParams, commonArgs...),
- ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
-}
-
-// EnvOverrideFunc retrieves a variable func that evaluates to the value of the given environment
-// variable if set, otherwise the given default.
-func EnvOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string {
- return func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv(envVar); override != "" {
- return override
- }
- return defaultVal
- }
-}
diff --git a/remoteexec/remoteexec_test.go b/remoteexec/remoteexec_test.go
index 56985d3..875aa6a 100644
--- a/remoteexec/remoteexec_test.go
+++ b/remoteexec/remoteexec_test.go
@@ -17,8 +17,6 @@
import (
"fmt"
"testing"
-
- "android/soong/android"
)
func TestTemplate(t *testing.T) {
@@ -38,7 +36,7 @@
PoolKey: "default",
},
},
- want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage),
+ want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage),
},
{
name: "all params",
@@ -54,7 +52,7 @@
PoolKey: "default",
},
},
- want: fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp --output_files=$out --toolchain_inputs=clang++ -- ", DefaultImage),
+ want: fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=remote --inputs=$in --input_list_paths=$out.rsp --output_files=$out --toolchain_inputs=clang++ -- ", DefaultImage),
},
}
for _, test := range tests {
@@ -77,7 +75,7 @@
},
}
want := fmt.Sprintf("prebuilts/remoteexecution-client/live/rewrapper --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
- if got := params.NoVarTemplate(android.NullConfig("")); got != want {
+ if got := params.NoVarTemplate(DefaultWrapperPath); got != want {
t.Errorf("NoVarTemplate() returned\n%s\nwant\n%s", got, want)
}
}
@@ -92,7 +90,7 @@
PoolKey: "default",
},
}
- want := fmt.Sprintf("${remoteexec.Wrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
+ want := fmt.Sprintf("${android.RBEWrapper} --labels=compiler=clang,lang=cpp,type=compile --platform=\"Pool=default,container-image=%s\" --exec_strategy=local --inputs=$in --output_files=$out -- ", DefaultImage)
for i := 0; i < 1000; i++ {
if got := r.Template(); got != want {
t.Fatalf("Template() returned\n%s\nwant\n%s", got, want)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 56d660e..db69e23 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r399163b"
+ bindgenClangVersion = "clang-r412851"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 67460ba..2f44b20 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -46,7 +46,6 @@
"-C llvm-args=-sanitizer-coverage-trace-geps",
"-C llvm-args=-sanitizer-coverage-prune-blocks=0",
"-C llvm-args=-sanitizer-coverage-pc-table",
- "-C link-dead-code=y",
"-Z sanitizer=address",
// Sancov breaks with lto
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 310c959..9e8a602 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -55,7 +55,9 @@
libs: [
"manifest_utils",
],
- test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
}
python_library_host {
@@ -110,7 +112,9 @@
libs: [
"manifest_utils",
],
- test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
}
python_binary_host {
diff --git a/scripts/TEST_MAPPING b/scripts/TEST_MAPPING
deleted file mode 100644
index 1b0a229..0000000
--- a/scripts/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit" : [
- {
- "name": "manifest_check_test",
- "host": true
- },
- {
- "name": "manifest_fixer_test",
- "host": true
- }
- ]
-}
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 973a675..1343f35 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -19,6 +19,7 @@
from __future__ import print_function
import argparse
+import json
import re
import subprocess
import sys
@@ -61,6 +62,10 @@
dest='extract_target_sdk_version',
action='store_true',
help='print the targetSdkVersion from the manifest')
+ parser.add_argument('--dexpreopt-config',
+ dest='dexpreopt_configs',
+ action='append',
+ help='a paths to a dexpreopt.config of some library')
parser.add_argument('--aapt',
dest='aapt',
help='path to aapt executable')
@@ -85,12 +90,6 @@
else:
manifest_required, manifest_optional = extract_uses_libs_xml(manifest)
- if required is None:
- required = []
-
- if optional is None:
- optional = []
-
err = []
if manifest_required != required:
err.append('Expected required <uses-library> tags "%s", got "%s"' %
@@ -222,6 +221,35 @@
return target_attr.value
+def load_dexpreopt_configs(configs):
+ """Load dexpreopt.config files and map module names to library names."""
+ module_to_libname = {}
+
+ if configs is None:
+ configs = []
+
+ for config in configs:
+ with open(config, 'r') as f:
+ contents = json.load(f)
+ module_to_libname[contents['Name']] = contents['ProvidesUsesLibrary']
+
+ return module_to_libname
+
+
+def translate_libnames(modules, module_to_libname):
+ """Translate module names into library names using the mapping."""
+ if modules is None:
+ modules = []
+
+ libnames = []
+ for name in modules:
+ if name in module_to_libname:
+ name = module_to_libname[name]
+ libnames.append(name)
+
+ return libnames
+
+
def main():
"""Program entry point."""
try:
@@ -237,12 +265,20 @@
manifest = minidom.parse(args.input)
if args.enforce_uses_libraries:
+ # Load dexpreopt.config files and build a mapping from module names to
+ # library names. This is necessary because build system addresses
+ # libraries by their module name (`uses_libs`, `optional_uses_libs`,
+ # `LOCAL_USES_LIBRARIES`, `LOCAL_OPTIONAL_LIBRARY_NAMES` all contain
+ # module names), while the manifest addresses libraries by their name.
+ mod_to_lib = load_dexpreopt_configs(args.dexpreopt_configs)
+ required = translate_libnames(args.uses_libraries, mod_to_lib)
+ optional = translate_libnames(args.optional_uses_libraries, mod_to_lib)
+
# Check if the <uses-library> lists in the build system agree with those
# in the manifest. Raise an exception on mismatch, unless the script was
# passed a special parameter to suppress exceptions.
- errmsg = enforce_uses_libraries(manifest, args.uses_libraries,
- args.optional_uses_libraries, args.enforce_uses_libraries_relax,
- is_apk)
+ errmsg = enforce_uses_libraries(manifest, required, optional,
+ args.enforce_uses_libraries_relax, is_apk)
# Create a status file that is empty on success, or contains an error
# message on failure. When exceptions are suppressed, dexpreopt command
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 5b7a6da..43e6cbf 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -87,7 +87,7 @@
comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols"
echo >> "${outfile}.keep_symbols" # Ensure that the keep_symbols file is not empty.
"${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
- "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
+ "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --remove-section .rustc --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
"${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
"${XZ}" --block-size=64k --threads=0 "${outfile}.mini_debuginfo"
diff --git a/scripts/update-apex-allowed-deps.sh b/scripts/update-apex-allowed-deps.sh
deleted file mode 100755
index 872d746..0000000
--- a/scripts/update-apex-allowed-deps.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash -e
-#
-# The script to run locally to re-generate global allowed list of dependencies
-# for updatable modules.
-
-if [ ! -e "build/envsetup.sh" ]; then
- echo "ERROR: $0 must be run from the top of the tree"
- exit 1
-fi
-
-source build/envsetup.sh > /dev/null || exit 1
-
-readonly OUT_DIR=$(get_build_var OUT_DIR)
-
-readonly ALLOWED_DEPS_FILE="build/soong/apex/allowed_deps.txt"
-readonly NEW_ALLOWED_DEPS_FILE="${OUT_DIR}/soong/apex/depsinfo/new-allowed-deps.txt"
-
-# If the script is run after droidcore failure, ${NEW_ALLOWED_DEPS_FILE}
-# should already be built. If running the script manually, make sure it exists.
-m "${NEW_ALLOWED_DEPS_FILE}" -j
-
-cat > "${ALLOWED_DEPS_FILE}" << EndOfFileComment
-# A list of allowed dependencies for all updatable modules.
-#
-# The list tracks all direct and transitive dependencies that end up within any
-# of the updatable binaries; specifically excluding external dependencies
-# required to compile those binaries. This prevents potential regressions in
-# case a new dependency is not aware of the different functional and
-# non-functional requirements being part of an updatable module, for example
-# setting correct min_sdk_version.
-#
-# To update the list, run:
-# repo-root$ build/soong/scripts/update-apex-allowed-deps.sh
-#
-# See go/apex-allowed-deps-error for more details.
-# TODO(b/157465465): introduce automated quality signals and remove this list.
-EndOfFileComment
-
-cat "${NEW_ALLOWED_DEPS_FILE}" >> "${ALLOWED_DEPS_FILE}"
diff --git a/sdk/Android.bp b/sdk/Android.bp
index 6e49c6d..7b034e6 100644
--- a/sdk/Android.bp
+++ b/sdk/Android.bp
@@ -23,6 +23,7 @@
"boot_image_sdk_test.go",
"bp_test.go",
"cc_sdk_test.go",
+ "compat_config_sdk_test.go",
"exports_test.go",
"java_sdk_test.go",
"sdk_test.go",
diff --git a/sdk/boot_image_sdk_test.go b/sdk/boot_image_sdk_test.go
index 9805a6a..5a03e34 100644
--- a/sdk/boot_image_sdk_test.go
+++ b/sdk/boot_image_sdk_test.go
@@ -14,20 +14,27 @@
package sdk
-import "testing"
+import (
+ "testing"
+
+ "android/soong/android"
+)
func TestSnapshotWithBootImage(t *testing.T) {
- result := testSdkWithJava(t, `
- sdk {
- name: "mysdk",
- boot_images: ["mybootimage"],
- }
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ boot_images: ["mybootimage"],
+ }
- boot_image {
- name: "mybootimage",
- image_name: "art",
- }
- `)
+ boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ }
+ `),
+ ).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
@@ -60,3 +67,39 @@
`),
checkAllCopyRules(""))
}
+
+// Test that boot_image works with sdk.
+func TestBasicSdkWithBootImage(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForSdkTestWithApex,
+ prepareForSdkTestWithJava,
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ boot_images: ["mybootimage"],
+ }
+
+ boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ apex_available: ["myapex"],
+ }
+
+ sdk_snapshot {
+ name: "mysdk@1",
+ boot_images: ["mybootimage_mysdk_1"],
+ }
+
+ prebuilt_boot_image {
+ name: "mybootimage_mysdk_1",
+ sdk_member_name: "mybootimage",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: [
+ "myapex",
+ ],
+ image_name: "art",
+ }
+ `),
+ ).RunTest(t)
+}
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index 2bd8a43..c620ac2 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -84,9 +84,9 @@
set.AddProperty(name, val)
android.AssertDeepEquals(t, "wrong value", val, set.getValue(name))
}
- android.AssertPanic(t, "adding x again should panic",
+ android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`,
func() { set.AddProperty("x", "taxi") })
- android.AssertPanic(t, "adding arr again should panic",
+ android.AssertPanicMessageContains(t, "adding arr again should panic", `Property "arr" already exists in property set`,
func() { set.AddProperty("arr", []string{"d"}) })
}
@@ -124,14 +124,14 @@
t.Run("add conflicting subset", func(t *testing.T) {
set := propertySetFixture().(*bpPropertySet)
- android.AssertPanic(t, "adding x again should panic",
+ android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`,
func() { set.AddProperty("x", propertySetFixture()) })
})
t.Run("add non-pointer struct", func(t *testing.T) {
set := propertySetFixture().(*bpPropertySet)
str := propertyStructFixture().(*propertyStruct)
- android.AssertPanic(t, "adding a non-pointer struct should panic",
+ android.AssertPanicMessageContains(t, "adding a non-pointer struct should panic", "Value is a struct, not a pointer to one:",
func() { set.AddProperty("new", *str) })
})
}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index a2539c9..9626a04 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -808,7 +808,8 @@
}
func TestSnapshotWithSingleHostOsType(t *testing.T) {
- result := sdkFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForSdkTest,
ccTestFs.AddToFixture(),
cc.PrepareForTestOnLinuxBionic,
android.FixtureModifyConfig(func(config android.Config) {
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
new file mode 100644
index 0000000..dffc02a
--- /dev/null
+++ b/sdk/compat_config_sdk_test.go
@@ -0,0 +1,70 @@
+// Copyright 2021 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 sdk
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func TestSnapshotWithCompatConfig(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithPlatformCompatConfig,
+ ).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ compat_configs: ["myconfig"],
+ }
+
+ platform_compat_config {
+ name: "myconfig",
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_platform_compat_config {
+ name: "mysdk_myconfig@current",
+ sdk_member_name: "myconfig",
+ visibility: ["//visibility:public"],
+ metadata: "compat_configs/myconfig/myconfig_meta.xml",
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ visibility: ["//visibility:public"],
+ compat_configs: ["mysdk_myconfig@current"],
+}
+`),
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_platform_compat_config {
+ name: "myconfig",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ metadata: "compat_configs/myconfig/myconfig_meta.xml",
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myconfig/android_common/myconfig_meta.xml -> compat_configs/myconfig/myconfig_meta.xml
+`),
+ )
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index f4e9380..2be3c9c 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -21,6 +21,11 @@
"android/soong/java"
)
+var prepareForSdkTestWithJava = android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithSdkBuildComponents,
+)
+
func testSdkWithJava(t *testing.T, bp string) *android.TestResult {
t.Helper()
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 2c84a2e..e561529 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -358,15 +358,36 @@
// For dependencies from an in-development version of an SDK member to frozen versions of the same member
// e.g. libfoo -> libfoo.mysdk.11 and libfoo.mysdk.12
+//
+// The dependency represented by this tag requires that for every APEX variant created for the
+// `from` module that an equivalent APEX variant is created for the 'to' module. This is because an
+// APEX that requires a specific version of an sdk (via the `uses_sdks` property will replace
+// dependencies on the unversioned sdk member with a dependency on the appropriate versioned sdk
+// member. In order for that to work the versioned sdk member needs to have a variant for that APEX.
+// As it is not known at the time that the APEX variants are created which specific APEX variants of
+// a versioned sdk members will be required it is necessary for the versioned sdk members to have
+// variants for any APEX that it could be used within.
+//
+// If the APEX selects a versioned sdk member then it will not have a dependency on the `from`
+// module at all so any dependencies of that module will not affect the APEX. However, if the APEX
+// selects the unversioned sdk member then it must exclude all the versioned sdk members. In no
+// situation would this dependency cause the `to` module to be added to the APEX hence why this tag
+// also excludes the `to` module from being added to the APEX contents.
type sdkMemberVersionedDepTag struct {
dependencyTag
member string
version string
}
+func (t sdkMemberVersionedDepTag) AlwaysRequireApexVariant() bool {
+ return true
+}
+
// Mark this tag so dependencies that use it are excluded from visibility enforcement.
func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {}
+var _ android.AlwaysRequireApexVariantTag = sdkMemberVersionedDepTag{}
+
// Step 1: create dependencies from an SDK module to its members.
func memberMutator(mctx android.BottomUpMutatorContext) {
if s, ok := mctx.Module().(*sdk); ok {
@@ -424,20 +445,26 @@
}
}
+// An interface that encapsulates all the functionality needed to manage the sdk dependencies.
+//
+// It is a mixture of apex and sdk module functionality.
+type sdkAndApexModule interface {
+ android.Module
+ android.DepIsInSameApex
+ android.RequiredSdks
+}
+
// Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its
// descendants
func sdkDepsMutator(mctx android.TopDownMutatorContext) {
- if parent, ok := mctx.Module().(interface {
- android.DepIsInSameApex
- android.RequiredSdks
- }); ok {
+ if parent, ok := mctx.Module().(sdkAndApexModule); ok {
// Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks()
// by reading its own properties like `uses_sdks`.
requiredSdks := parent.RequiredSdks()
if len(requiredSdks) > 0 {
mctx.VisitDirectDeps(func(m android.Module) {
// Only propagate required sdks from the apex onto its contents.
- if dep, ok := m.(android.SdkAware); ok && parent.DepIsInSameApex(mctx, dep) {
+ if dep, ok := m.(android.SdkAware); ok && android.IsDepInSameApex(mctx, parent, dep) {
dep.BuildWithSdks(requiredSdks)
}
})
@@ -476,10 +503,7 @@
// Step 6: ensure that the dependencies outside of the APEX are all from the required SDKs
func sdkRequirementsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(interface {
- android.DepIsInSameApex
- android.RequiredSdks
- }); ok {
+ if m, ok := mctx.Module().(sdkAndApexModule); ok {
requiredSdks := m.RequiredSdks()
if len(requiredSdks) == 0 {
return
@@ -498,9 +522,18 @@
return
}
- // If the dep is outside of the APEX, but is not in any of the
- // required SDKs, we know that the dep is a violation.
+ // If the dep is outside of the APEX, but is not in any of the required SDKs, we know that the
+ // dep is a violation.
if sa, ok := dep.(android.SdkAware); ok {
+ // It is not an error if a dependency that is excluded from the apex due to the tag is not
+ // in one of the required SDKs. That is because all of the existing tags that implement it
+ // do not depend on modules which can or should belong to an sdk_snapshot.
+ if _, ok := tag.(android.ExcludeFromApexContentsTag); ok {
+ // The tag defines a dependency that never requires the child module to be part of the
+ // same apex.
+ return
+ }
+
if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) {
mctx.ModuleErrorf("depends on %q (in SDK %q) that isn't part of the required SDKs: %v",
sa.Name(), sa.ContainingSdk(), requiredSdks)
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 05d8bdb..b7da95c 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -31,7 +31,7 @@
os.Exit(0)
}
- runTestWithBuildDir(m)
+ os.Exit(m.Run())
}
func TestDepNotInRequiredSdks(t *testing.T) {
diff --git a/sdk/testing.go b/sdk/testing.go
index a5519f8..d21f425 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -16,8 +16,6 @@
import (
"fmt"
- "io/ioutil"
- "os"
"path/filepath"
"strings"
"testing"
@@ -29,14 +27,9 @@
"android/soong/java"
)
-var sdkFixtureFactory = android.NewFixtureFactory(
- &buildDir,
+// Prepare for running an sdk test with an apex.
+var prepareForSdkTestWithApex = android.GroupFixturePreparers(
apex.PrepareForTestWithApexBuildComponents,
- cc.PrepareForTestWithCcDefaultModules,
- genrule.PrepareForTestWithGenRuleBuildComponents,
- java.PrepareForTestWithJavaBuildComponents,
- PrepareForTestWithSdkBuildComponents,
-
android.FixtureAddTextFile("sdk/tests/Android.bp", `
apex_key {
name: "myapex.key",
@@ -61,6 +54,24 @@
"myapex.x509.pem": nil,
"myapex.pk8": nil,
}),
+)
+
+// Legacy preparer used for running tests within the sdk package.
+//
+// This includes everything that was needed to run any test in the sdk package prior to the
+// introduction of the test fixtures. Tests that are being converted to use fixtures directly
+// rather than through the testSdkError() and testSdkWithFs() methods should avoid using this and
+// instead should use the various preparers directly using android.GroupFixturePreparers(...) to
+// group them when necessary.
+//
+// deprecated
+var prepareForSdkTest = android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithSdkBuildComponents,
+
+ prepareForSdkTestWithApex,
cc.PrepareForTestOnWindows,
android.FixtureModifyConfig(func(config android.Config) {
@@ -79,12 +90,12 @@
func testSdkWithFs(t *testing.T, bp string, fs android.MockFS) *android.TestResult {
t.Helper()
- return sdkFixtureFactory.RunTest(t, fs.AddToFixture(), android.FixtureWithRootAndroidBp(bp))
+ return prepareForSdkTest.RunTest(t, fs.AddToFixture(), android.FixtureWithRootAndroidBp(bp))
}
func testSdkError(t *testing.T, pattern, bp string) {
t.Helper()
- sdkFixtureFactory.
+ prepareForSdkTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
RunTestWithBp(t, bp)
}
@@ -203,13 +214,33 @@
// Populate a mock filesystem with the files that would have been copied by
// the rules.
- fs := make(map[string][]byte)
+ fs := android.MockFS{}
+ snapshotSubDir := "snapshot"
for _, dest := range snapshotBuildInfo.snapshotContents {
- fs[dest] = nil
+ fs[filepath.Join(snapshotSubDir, dest)] = nil
}
+ fs[filepath.Join(snapshotSubDir, "Android.bp")] = []byte(snapshotBuildInfo.androidBpContents)
- // Process the generated bp file to make sure it is valid.
- testSdkWithFs(t, snapshotBuildInfo.androidBpContents, fs)
+ preparer := result.Preparer()
+
+ // Process the generated bp file to make sure it is valid. Use the same preparer as was used to
+ // produce this result.
+ t.Run("snapshot without source", func(t *testing.T) {
+ android.GroupFixturePreparers(
+ preparer,
+ // TODO(b/183184375): Set Config.TestAllowNonExistentPaths = false to verify that all the
+ // files the snapshot needs are actually copied into the snapshot.
+
+ // Add the files (including bp) created for this snapshot to the test fixture.
+ fs.AddToFixture(),
+
+ // Remove the source Android.bp file to make sure it works without.
+ // TODO(b/183184375): Add a test with the source.
+ android.FixtureModifyMockFS(func(fs android.MockFS) {
+ delete(fs, "Android.bp")
+ }),
+ ).RunTest(t)
+ })
}
type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
@@ -326,28 +357,3 @@
// The final output zip.
outputZip string
}
-
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_sdk_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- _ = os.RemoveAll(buildDir)
-}
-
-func runTestWithBuildDir(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
-}
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 5887b56..9e7e594 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -13,8 +13,7 @@
os.Exit(m.Run())
}
-var shFixtureFactory = android.NewFixtureFactory(
- nil,
+var prepareForShTest = android.GroupFixturePreparers(
cc.PrepareForTestWithCcBuildComponents,
PrepareForTestWithShBuildComponents,
android.FixtureMergeMockFs(android.MockFS{
@@ -24,19 +23,19 @@
}),
)
-// testShBinary runs tests using the shFixtureFactory
+// testShBinary runs tests using the prepareForShTest
//
-// Do not add any new usages of this, instead use the shFixtureFactory directly as it makes it much
+// Do not add any new usages of this, instead use the prepareForShTest directly as it makes it much
// easier to customize the test behavior.
//
// If it is necessary to customize the behavior of an existing test that uses this then please first
-// convert the test to using shFixtureFactory first and then in a following change add the
+// convert the test to using prepareForShTest first and then in a following change add the
// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
// that it did not change the test behavior unexpectedly.
//
// deprecated
func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
- result := shFixtureFactory.RunTestWithBp(t, bp)
+ result := prepareForShTest.RunTestWithBp(t, bp)
return result.TestContext, result.Config
}
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
index 540a8da..1d5eb31 100644
--- a/sysprop/Android.bp
+++ b/sysprop/Android.bp
@@ -14,6 +14,7 @@
],
srcs: [
"sysprop_library.go",
+ "testing.go",
],
testSrcs: [
"sysprop_test.go",
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 892a16c..f1c2d0d 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -193,7 +193,11 @@
}
func init() {
- android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
+ registerSyspropBuildComponents(android.InitRegistrationContext)
+}
+
+func registerSyspropBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
}
func (m *syspropLibrary) Name() string {
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index fde41d6..e9d9051 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -15,72 +15,24 @@
package sysprop
import (
- "reflect"
+ "os"
+ "strings"
+ "testing"
"android/soong/android"
"android/soong/cc"
"android/soong/java"
- "io/ioutil"
- "os"
- "strings"
- "testing"
-
"github.com/google/blueprint/proptools"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_sysprop_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
-func testContext(config android.Config) *android.TestContext {
-
- ctx := android.NewTestArchContext(config)
- java.RegisterRequiredBuildComponentsForTest(ctx)
-
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
-
- android.RegisterPrebuiltMutators(ctx)
-
- cc.RegisterRequiredBuildComponentsForTest(ctx)
-
- ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
-
- ctx.Register()
-
- return ctx
-}
-
-func run(t *testing.T, ctx *android.TestContext, config android.Config) {
+func test(t *testing.T, bp string) *android.TestResult {
t.Helper()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-}
-func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
bp += `
cc_library {
name: "libbase",
@@ -126,9 +78,7 @@
}
`
- bp += cc.GatherRequiredDepsForTest(android.Android)
-
- mockFS := map[string][]byte{
+ mockFS := android.MockFS{
"a.java": nil,
"b.java": nil,
"c.java": nil,
@@ -172,31 +122,24 @@
"com/android2/OdmProperties.sysprop": nil,
}
- for k, v := range fs {
- mockFS[k] = v
- }
+ result := android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ java.PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithSyspropBuildComponents,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceSystemSdkVersions = []string{"28"}
+ variables.DeviceVndkVersion = proptools.StringPtr("current")
+ variables.Platform_vndk_version = proptools.StringPtr("VER")
+ }),
+ mockFS.AddToFixture(),
+ android.FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
- config := java.TestConfig(buildDir, env, bp, mockFS)
-
- config.TestProductVariables.DeviceSystemSdkVersions = []string{"28"}
- config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
-
- return config
-
-}
-
-func test(t *testing.T, bp string) *android.TestContext {
- t.Helper()
- config := testConfig(nil, bp, nil)
- ctx := testContext(config)
- run(t, ctx, config)
-
- return ctx
+ return result
}
func TestSyspropLibrary(t *testing.T) {
- ctx := test(t, `
+ result := test(t, `
sysprop_library {
name: "sysprop-platform",
apex_available: ["//apex_available:platform"],
@@ -308,9 +251,9 @@
"android_vendor.VER_arm64_armv8-a_shared",
"android_vendor.VER_arm64_armv8-a_static",
} {
- ctx.ModuleForTests("libsysprop-platform", variant)
- ctx.ModuleForTests("libsysprop-vendor", variant)
- ctx.ModuleForTests("libsysprop-odm", variant)
+ result.ModuleForTests("libsysprop-platform", variant)
+ result.ModuleForTests("libsysprop-vendor", variant)
+ result.ModuleForTests("libsysprop-odm", variant)
}
for _, variant := range []string{
@@ -319,21 +262,18 @@
"android_arm64_armv8-a_shared",
"android_arm64_armv8-a_static",
} {
- library := ctx.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
+ library := result.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
expectedApexAvailableOnLibrary := []string{"//apex_available:platform"}
- if !reflect.DeepEqual(library.ApexProperties.Apex_available, expectedApexAvailableOnLibrary) {
- t.Errorf("apex available property on libsysprop-platform must be %#v, but was %#v.",
- expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
- }
+ android.AssertDeepEquals(t, "apex available property on libsysprop-platform", expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
// product variant of vendor-owned sysprop_library
- ctx.ModuleForTests("libsysprop-vendor-on-product", variant)
+ result.ModuleForTests("libsysprop-vendor-on-product", variant)
}
- ctx.ModuleForTests("sysprop-platform", "android_common")
- ctx.ModuleForTests("sysprop-platform_public", "android_common")
- ctx.ModuleForTests("sysprop-vendor", "android_common")
- ctx.ModuleForTests("sysprop-vendor-on-product", "android_common")
+ result.ModuleForTests("sysprop-platform", "android_common")
+ result.ModuleForTests("sysprop-platform_public", "android_common")
+ result.ModuleForTests("sysprop-vendor", "android_common")
+ result.ModuleForTests("sysprop-vendor-on-product", "android_common")
// Check for exported includes
coreVariant := "android_arm64_armv8-a_static"
@@ -348,25 +288,19 @@
vendorInternalPath := "libsysprop-vendor/android_vendor.VER_arm64_armv8-a_static/gen/sysprop/include"
vendorPublicPath := "libsysprop-vendor-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include"
- platformClient := ctx.ModuleForTests("cc-client-platform", coreVariant)
+ platformClient := result.ModuleForTests("cc-client-platform", coreVariant)
platformFlags := platformClient.Rule("cc").Args["cFlags"]
// platform should use platform's internal header
- if !strings.Contains(platformFlags, platformInternalPath) {
- t.Errorf("flags for platform must contain %#v, but was %#v.",
- platformInternalPath, platformFlags)
- }
+ android.AssertStringDoesContain(t, "flags for platform", platformFlags, platformInternalPath)
- platformStaticClient := ctx.ModuleForTests("cc-client-platform-static", coreVariant)
+ platformStaticClient := result.ModuleForTests("cc-client-platform-static", coreVariant)
platformStaticFlags := platformStaticClient.Rule("cc").Args["cFlags"]
// platform-static should use platform's internal header
- if !strings.Contains(platformStaticFlags, platformInternalPath) {
- t.Errorf("flags for platform-static must contain %#v, but was %#v.",
- platformInternalPath, platformStaticFlags)
- }
+ android.AssertStringDoesContain(t, "flags for platform-static", platformStaticFlags, platformInternalPath)
- productClient := ctx.ModuleForTests("cc-client-product", coreVariant)
+ productClient := result.ModuleForTests("cc-client-product", coreVariant)
productFlags := productClient.Rule("cc").Args["cFlags"]
// Product should use platform's and vendor's public headers
@@ -376,7 +310,7 @@
platformPublicCorePath, vendorPublicPath, productFlags)
}
- vendorClient := ctx.ModuleForTests("cc-client-vendor", vendorVariant)
+ vendorClient := result.ModuleForTests("cc-client-vendor", vendorVariant)
vendorFlags := vendorClient.Rule("cc").Args["cFlags"]
// Vendor should use platform's public header and vendor's internal header
@@ -387,15 +321,15 @@
}
// Java modules linking against system API should use public stub
- javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common").Rule("javac")
- syspropPlatformPublic := ctx.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
+ javaSystemApiClient := result.ModuleForTests("java-platform", "android_common").Rule("javac")
+ syspropPlatformPublic := result.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
if g, w := javaSystemApiClient.Implicits.Strings(), syspropPlatformPublic.Output.String(); !android.InList(w, g) {
t.Errorf("system api client should use public stub %q, got %q", w, g)
}
}
func TestApexAvailabilityIsForwarded(t *testing.T) {
- ctx := test(t, `
+ result := test(t, `
sysprop_library {
name: "sysprop-platform",
apex_available: ["//apex_available:platform"],
@@ -407,23 +341,17 @@
expected := []string{"//apex_available:platform"}
- ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
propFromCc := ccModule.ApexProperties.Apex_available
- if !reflect.DeepEqual(propFromCc, expected) {
- t.Errorf("apex_available not forwarded to cc module. expected %#v, got %#v",
- expected, propFromCc)
- }
+ android.AssertDeepEquals(t, "apex_available forwarding to cc module", expected, propFromCc)
- javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.ApexProperties.Apex_available
- if !reflect.DeepEqual(propFromJava, expected) {
- t.Errorf("apex_available not forwarded to java module. expected %#v, got %#v",
- expected, propFromJava)
- }
+ android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava)
}
func TestMinSdkVersionIsForwarded(t *testing.T) {
- ctx := test(t, `
+ result := test(t, `
sysprop_library {
name: "sysprop-platform",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
@@ -438,17 +366,11 @@
}
`)
- ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
- if propFromCc != "29" {
- t.Errorf("min_sdk_version not forwarded to cc module. expected %#v, got %#v",
- "29", propFromCc)
- }
+ android.AssertStringEquals(t, "min_sdk_version forwarding to cc module", "29", propFromCc)
- javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.MinSdkVersion()
- if propFromJava != "30" {
- t.Errorf("min_sdk_version not forwarded to java module. expected %#v, got %#v",
- "30", propFromJava)
- }
+ android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
}
diff --git a/sysprop/testing.go b/sysprop/testing.go
new file mode 100644
index 0000000..3e14be1
--- /dev/null
+++ b/sysprop/testing.go
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package sysprop
+
+import "android/soong/android"
+
+var PrepareForTestWithSyspropBuildComponents = android.FixtureRegisterWithContext(registerSyspropBuildComponents)
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 81ce939..ec561d5 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -116,6 +116,7 @@
"RBE_exec_strategy",
"RBE_invocation_id",
"RBE_log_dir",
+ "RBE_num_retries_if_mismatched",
"RBE_platform",
"RBE_remote_accept_cache",
"RBE_remote_update_cache",
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 893fd6d..5961c45 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -145,6 +145,7 @@
"RBE_exec_strategy",
"RBE_invocation_id",
"RBE_log_dir",
+ "RBE_num_retries_if_mismatched",
"RBE_platform",
"RBE_remote_accept_cache",
"RBE_remote_update_cache",
diff --git a/ui/build/soong.go b/ui/build/soong.go
index fee5723..9afcb88 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -65,9 +65,10 @@
// A tiny struct used to tell Blueprint that it's in bootstrap mode. It would
// probably be nicer to use a flag in bootstrap.Args instead.
type BlueprintConfig struct {
- srcDir string
- buildDir string
- ninjaBuildDir string
+ srcDir string
+ buildDir string
+ ninjaBuildDir string
+ debugCompilation bool
}
func (c BlueprintConfig) SrcDir() string {
@@ -82,6 +83,10 @@
return c.ninjaBuildDir
}
+func (c BlueprintConfig) DebugCompilation() bool {
+ return c.debugCompilation
+}
+
func bootstrapBlueprint(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
defer ctx.EndTrace()
@@ -102,9 +107,10 @@
blueprintCtx := blueprint.NewContext()
blueprintCtx.SetIgnoreUnknownModuleTypes(true)
blueprintConfig := BlueprintConfig{
- srcDir: os.Getenv("TOP"),
- buildDir: config.SoongOutDir(),
- ninjaBuildDir: config.OutDir(),
+ srcDir: os.Getenv("TOP"),
+ buildDir: config.SoongOutDir(),
+ ninjaBuildDir: config.OutDir(),
+ debugCompilation: os.Getenv("SOONG_DELVE") != "",
}
bootstrap.RunBlueprint(args, blueprintCtx, blueprintConfig)
diff --git a/xml/Android.bp b/xml/Android.bp
index a5e5f4c..1542930 100644
--- a/xml/Android.bp
+++ b/xml/Android.bp
@@ -13,6 +13,7 @@
"soong-etc",
],
srcs: [
+ "testing.go",
"xml.go",
],
testSrcs: [
diff --git a/xml/testing.go b/xml/testing.go
new file mode 100644
index 0000000..1d09f10
--- /dev/null
+++ b/xml/testing.go
@@ -0,0 +1,19 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xml
+
+import "android/soong/android"
+
+var PreparerForTestWithXmlBuildComponents = android.FixtureRegisterWithContext(registerXmlBuildComponents)
diff --git a/xml/xml.go b/xml/xml.go
index 8810ae4..c281078 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -53,10 +53,14 @@
)
func init() {
- android.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
+ registerXmlBuildComponents(android.InitRegistrationContext)
pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
}
+func registerXmlBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
+}
+
type prebuiltEtcXmlProperties struct {
// Optional DTD that will be used to validate the xml file.
Schema *string `android:"path"`
diff --git a/xml/xml_test.go b/xml/xml_test.go
index 138503c..a59a293 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -15,7 +15,6 @@
package xml
import (
- "io/ioutil"
"os"
"testing"
@@ -23,62 +22,31 @@
"android/soong/etc"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_xml_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
-func testXml(t *testing.T, bp string) *android.TestContext {
- fs := map[string][]byte{
+func testXml(t *testing.T, bp string) *android.TestResult {
+ fs := android.MockFS{
"foo.xml": nil,
"foo.dtd": nil,
"bar.xml": nil,
"bar.xsd": nil,
"baz.xml": nil,
}
- config := android.TestArchConfig(buildDir, nil, bp, fs)
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
- ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
- return ctx
-}
-
-func assertEqual(t *testing.T, name, expected, actual string) {
- t.Helper()
- if expected != actual {
- t.Errorf(name+" expected %q != got %q", expected, actual)
- }
+ return android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ etc.PrepareForTestWithPrebuiltEtc,
+ PreparerForTestWithXmlBuildComponents,
+ fs.AddToFixture(),
+ android.FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
}
// Minimal test
func TestPrebuiltEtcXml(t *testing.T) {
- ctx := testXml(t, `
+ result := testXml(t, `
prebuilt_etc_xml {
name: "foo.xml",
src: "foo.xml",
@@ -103,14 +71,14 @@
{rule: "xmllint-minimal", input: "baz.xml"},
} {
t.Run(tc.schemaType, func(t *testing.T) {
- rule := ctx.ModuleForTests(tc.input, "android_arm64_armv8-a").Rule(tc.rule)
- assertEqual(t, "input", tc.input, rule.Input.String())
+ rule := result.ModuleForTests(tc.input, "android_arm64_armv8-a").Rule(tc.rule)
+ android.AssertStringEquals(t, "input", tc.input, rule.Input.String())
if tc.schemaType != "" {
- assertEqual(t, "schema", tc.schema, rule.Args[tc.schemaType])
+ android.AssertStringEquals(t, "schema", tc.schema, rule.Args[tc.schemaType])
}
})
}
- m := ctx.ModuleForTests("foo.xml", "android_arm64_armv8-a").Module().(*prebuiltEtcXml)
- assertEqual(t, "installDir", buildDir+"/target/product/test_device/system/etc", m.InstallDirPath().String())
+ m := result.ModuleForTests("foo.xml", "android_arm64_armv8-a").Module().(*prebuiltEtcXml)
+ android.AssertPathRelativeToTopEquals(t, "installDir", "out/soong/target/product/test_device/system/etc", m.InstallDirPath())
}