diff options
-rw-r--r-- | android/allowlists/allowlists.go | 7 | ||||
-rw-r--r-- | bazel/bazel_proxy.go | 28 | ||||
-rw-r--r-- | bp2build/java_test_host_conversion_test.go | 149 | ||||
-rw-r--r-- | cc/lto.go | 32 | ||||
-rw-r--r-- | cc/test.go | 5 | ||||
-rw-r--r-- | cmd/soong_build/main.go | 6 | ||||
-rw-r--r-- | genrule/allowlists.go | 13 | ||||
-rw-r--r-- | genrule/genrule.go | 28 | ||||
-rwxr-xr-x | java/app.go | 5 | ||||
-rw-r--r-- | java/app_test.go | 8 | ||||
-rw-r--r-- | java/base.go | 4 | ||||
-rw-r--r-- | java/dexpreopt_bootjars.go | 2 | ||||
-rw-r--r-- | java/droidstubs.go | 8 | ||||
-rw-r--r-- | java/java.go | 97 | ||||
-rw-r--r-- | java/java_test.go | 24 | ||||
-rw-r--r-- | rust/builder.go | 2 | ||||
-rw-r--r-- | rust/config/global.go | 3 | ||||
-rwxr-xr-x | tests/genrule_sandbox_test.sh | 111 | ||||
-rw-r--r-- | tradefed/autogen.go | 37 | ||||
-rw-r--r-- | ui/build/config.go | 15 | ||||
-rw-r--r-- | ui/build/ninja.go | 44 | ||||
-rw-r--r-- | ui/build/soong.go | 2 |
22 files changed, 500 insertions, 130 deletions
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 0dd7dae69..bd2d9733c 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -1470,6 +1470,13 @@ var ( // python_test_host with test data "sbom_writers_test", + + // TODO(B/283193845): tradefed and its java_test_host dependents + "tradefed", + "permissive_mte_test", + "ICU4CTestRunner", + + "HelloWorldHostTest", // TODO(b/280452825): Convert HelloWorldHostTest to b test } MixedBuildsDisabledList = []string{ diff --git a/bazel/bazel_proxy.go b/bazel/bazel_proxy.go index 2940b9995..229818da0 100644 --- a/bazel/bazel_proxy.go +++ b/bazel/bazel_proxy.go @@ -26,10 +26,11 @@ import ( "time" ) -// Logs fatal events of ProxyServer. +// Logs events of ProxyServer. type ServerLogger interface { Fatal(v ...interface{}) Fatalf(format string, v ...interface{}) + Println(v ...interface{}) } // CmdRequest is a request to the Bazel Proxy server. @@ -71,9 +72,10 @@ type ProxyClient struct { // The ProxyServer will only live as long as soong_ui does; the // underlying Bazel server will live past the duration of the build. type ProxyServer struct { - logger ServerLogger - outDir string - workspaceDir string + logger ServerLogger + outDir string + workspaceDir string + bazeliskVersion string // The server goroutine will listen on this channel and stop handling requests // once it is written to. done chan struct{} @@ -119,12 +121,17 @@ func (b *ProxyClient) IssueCommand(req CmdRequest) (CmdResponse, error) { } // NewProxyServer is a constructor for a ProxyServer. -func NewProxyServer(logger ServerLogger, outDir string, workspaceDir string) *ProxyServer { +func NewProxyServer(logger ServerLogger, outDir string, workspaceDir string, bazeliskVersion string) *ProxyServer { + if len(bazeliskVersion) > 0 { + logger.Println("** Using Bazelisk for this build, due to env var USE_BAZEL_VERSION=" + bazeliskVersion + " **") + } + return &ProxyServer{ - logger: logger, - outDir: outDir, - workspaceDir: workspaceDir, - done: make(chan struct{}), + logger: logger, + outDir: outDir, + workspaceDir: workspaceDir, + done: make(chan struct{}), + bazeliskVersion: bazeliskVersion, } } @@ -155,6 +162,9 @@ func (b *ProxyServer) handleRequest(conn net.Conn) error { return fmt.Errorf("Error decoding request: %s", err) } + if len(b.bazeliskVersion) > 0 { + req.Env = append(req.Env, "USE_BAZEL_VERSION="+b.bazeliskVersion) + } stdout, stderr, cmdErr := ExecBazel("./build/bazel/bin/bazel", b.workspaceDir, req) errorString := "" if cmdErr != nil { diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go new file mode 100644 index 000000000..f411ffb07 --- /dev/null +++ b/bp2build/java_test_host_conversion_test.go @@ -0,0 +1,149 @@ +// Copyright 2023 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 bp2build + +import ( + "testing" + + "android/soong/android" + "android/soong/java" +) + +func runJavaTestHostTestCase(t *testing.T, tc Bp2buildTestCase) { + t.Helper() + (&tc).ModuleTypeUnderTest = "java_test_host" + (&tc).ModuleTypeUnderTestFactory = java.TestHostFactory + RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("java_library", java.LibraryFactory) + }, tc) +} + +func TestJavaTestHostGeneral(t *testing.T) { + runJavaTestHostTestCase(t, Bp2buildTestCase{ + Description: "java_test_host general", + Filesystem: map[string]string{}, + Blueprint: ` +java_test_host { + name: "java_test_host-1", + srcs: ["a.java", "b.java"], + libs: ["lib_a"], + static_libs: ["static_libs_a"], + exclude_srcs: ["b.java"], + javacflags: ["-Xdoclint:all/protected"], + java_version: "8", +} + +java_library { + name: "lib_a", + bazel_module: { bp2build_available: false }, +} + +java_library { + name: "static_libs_a", + bazel_module: { bp2build_available: false }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_library", "java_test_host-1_lib", AttrNameToString{ + "deps": `[ + ":lib_a-neverlink", + ":static_libs_a", + ]`, + "java_version": `"8"`, + "javacopts": `["-Xdoclint:all/protected"]`, + "srcs": `["a.java"]`, + "target_compatible_with": `select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + }), + MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{ + "runtime_deps": `[":java_test_host-1_lib"]`, + "target_compatible_with": `select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + }), + }, + }) +} + +func TestJavaTestHostNoSrcs(t *testing.T) { + runJavaTestHostTestCase(t, Bp2buildTestCase{ + Description: "java_test_host without srcs", + Filesystem: map[string]string{}, + Blueprint: ` +java_test_host { + name: "java_test_host-1", + libs: ["lib_a"], + static_libs: ["static_libs_a"], +} + +java_library { + name: "lib_a", + bazel_module: { bp2build_available: false }, +} + +java_library { + name: "static_libs_a", + bazel_module: { bp2build_available: false }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{ + "runtime_deps": `[ + ":lib_a-neverlink", + ":static_libs_a", + ]`, + "target_compatible_with": `select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + }), + }, + }) +} + +func TestJavaTestHostKotlinSrcs(t *testing.T) { + runJavaTestHostTestCase(t, Bp2buildTestCase{ + Description: "java_test_host with .kt in srcs", + Filesystem: map[string]string{}, + Blueprint: ` +java_test_host { + name: "java_test_host-1", + srcs: ["a.java", "b.kt"], +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{ + "runtime_deps": `[":java_test_host-1_lib"]`, + "target_compatible_with": `select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + }), + MakeBazelTarget("kt_jvm_library", "java_test_host-1_lib", AttrNameToString{ + "srcs": `[ + "a.java", + "b.kt", + ]`, + "target_compatible_with": `select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + })`, + }), + }, + }) +} @@ -43,16 +43,13 @@ type LTOProperties struct { // referred to in blueprint files as "lto" Lto struct { Never *bool `android:"arch_variant"` - Full *bool `android:"arch_variant"` Thin *bool `android:"arch_variant"` } `android:"arch_variant"` // Dep properties indicate that this module needs to be built with LTO // since it is an object dependency of an LTO module. - FullEnabled bool `blueprint:"mutated"` ThinEnabled bool `blueprint:"mutated"` NoLtoEnabled bool `blueprint:"mutated"` - FullDep bool `blueprint:"mutated"` ThinDep bool `blueprint:"mutated"` NoLtoDep bool `blueprint:"mutated"` @@ -86,8 +83,6 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { var ltoLdFlag string if lto.ThinLTO() { ltoCFlag = "-flto=thin -fsplit-lto-unit" - } else if lto.FullLTO() { - ltoCFlag = "-flto" } else { ltoCFlag = "-flto=thin -fsplit-lto-unit" ltoLdFlag = "-Wl,--lto-O0" @@ -126,13 +121,13 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { } func (lto *lto) LTO(ctx BaseModuleContext) bool { - return lto.ThinLTO() || lto.FullLTO() || lto.DefaultThinLTO(ctx) + return lto.ThinLTO() || lto.DefaultThinLTO(ctx) } func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool { // LP32 has many subtle issues and less test coverage. lib32 := ctx.Arch().ArchType.Multilib == "lib32" - // CFI enables full LTO. + // CFI adds LTO flags by itself. cfi := ctx.isCfi() // Performance and binary size are less important for host binaries and tests. host := ctx.Host() @@ -143,10 +138,6 @@ func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool { return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !test && !vndk } -func (lto *lto) FullLTO() bool { - return lto != nil && (proptools.Bool(lto.Properties.Lto.Full) || lto.Properties.FullEnabled) -} - func (lto *lto) ThinLTO() bool { return lto != nil && (proptools.Bool(lto.Properties.Lto.Thin) || lto.Properties.ThinEnabled) } @@ -164,12 +155,8 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { globalThinLTO := GlobalThinLTO(mctx) if m, ok := mctx.Module().(*Module); ok { - full := m.lto.FullLTO() thin := m.lto.ThinLTO() never := m.lto.Never() - if full && thin { - mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive") - } mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { tag := mctx.OtherModuleDependencyTag(dep) @@ -187,9 +174,6 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { } if dep, ok := dep.(*Module); ok { - if full && !dep.lto.FullLTO() { - dep.lto.Properties.FullDep = true - } if !globalThinLTO && thin && !dep.lto.ThinLTO() { dep.lto.Properties.ThinDep = true } @@ -212,9 +196,6 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { // Create variations for LTO types required as static // dependencies variationNames := []string{""} - if m.lto.Properties.FullDep && !m.lto.FullLTO() { - variationNames = append(variationNames, "lto-full") - } if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() { variationNames = append(variationNames, "lto-thin") } @@ -224,13 +205,10 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { // Use correct dependencies if LTO property is explicitly set // (mutually exclusive) - if m.lto.FullLTO() { - mctx.SetDependencyVariation("lto-full") - } if !globalThinLTO && m.lto.ThinLTO() { mctx.SetDependencyVariation("lto-thin") } - // Never must be the last, it overrides Thin or Full. + // Never must be the last, it overrides Thin. if globalThinLTO && m.lto.Never() { mctx.SetDependencyVariation("lto-none") } @@ -247,9 +225,6 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { } // LTO properties for dependencies - if name == "lto-full" { - variation.lto.Properties.FullEnabled = true - } if name == "lto-thin" { variation.lto.Properties.ThinEnabled = true } @@ -258,7 +233,6 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { } variation.Properties.PreventInstall = true variation.Properties.HideFromMake = true - variation.lto.Properties.FullDep = false variation.lto.Properties.ThinDep = false variation.lto.Properties.NoLtoDep = false } diff --git a/cc/test.go b/cc/test.go index 27de06b07..3f5f71007 100644 --- a/cc/test.go +++ b/cc/test.go @@ -70,6 +70,10 @@ type TestOptions struct { // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an // integer value and the value is less than the min_vndk_version, skip this module. Min_vndk_version *int64 + + // Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., GTest. + // The "key" is optional in each of these. + Test_runner_options []tradefed.Option } type TestBinaryProperties struct { @@ -398,6 +402,7 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { TestConfigTemplateProp: test.Properties.Test_config_template, TestSuites: test.testDecorator.InstallerProperties.Test_suites, Config: configs, + TestRunnerOptions: test.Properties.Test_options.Test_runner_options, AutoGenConfig: test.Properties.Auto_gen_config, TestInstallBase: testInstallBase, DeviceTemplate: "${NativeTestConfigTemplate}", diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index e006c9d7e..d589925c9 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -552,6 +552,12 @@ func main() { } writeMetrics(configuration, ctx.EventHandler, metricsDir) } + + // Register this environment variablesas being an implicit dependencies of + // soong_build. Changes to this environment variable will result in + // retriggering soong_build. + configuration.Getenv("USE_BAZEL_VERSION") + writeUsedEnvironmentFile(configuration) // Touch the output file so that it's the newest file created by soong_build. diff --git a/genrule/allowlists.go b/genrule/allowlists.go index 875dbabed..2954f8bc1 100644 --- a/genrule/allowlists.go +++ b/genrule/allowlists.go @@ -14,10 +14,6 @@ package genrule -import ( - "android/soong/android" -) - var ( DepfileAllowList = []string{ "depfile_allowed_for_test", @@ -136,12 +132,3 @@ var ( "external/perfetto", } ) -var DepfileAllowSet = map[string]bool{} -var SandboxingDenyModuleSet = map[string]bool{} -var SandboxingDenyPathSet = map[string]bool{} - -func init() { - android.AddToStringSet(DepfileAllowSet, DepfileAllowList) - android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...)) - android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList) -} diff --git a/genrule/genrule.go b/genrule/genrule.go index c830fcc43..4992625e5 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -24,6 +24,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "android/soong/bazel/cquery" @@ -60,6 +61,12 @@ var PrepareForIntegrationTestWithGenrule = android.GroupFixturePreparers( PrepareForTestWithGenRuleBuildComponents, ) +var DepfileAllowSet map[string]bool +var SandboxingDenyModuleSet map[string]bool +var SandboxingDenyPathSet map[string]bool +var SandboxingDenyModuleSetLock sync.Mutex +var DepfileAllowSetLock sync.Mutex + func RegisterGenruleBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("genrule_defaults", defaultsFactory) @@ -595,6 +602,12 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Allowlist genrule to use depfile until we have a solution to remove it. // TODO(b/235582219): Remove allowlist for genrule if Bool(g.properties.Depfile) { + if DepfileAllowSet == nil { + DepfileAllowSetLock.Lock() + defer DepfileAllowSetLock.Unlock() + DepfileAllowSet = map[string]bool{} + android.AddToStringSet(DepfileAllowSet, DepfileAllowList) + } // TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in // order to pass the presubmit before internal master is updated. if ctx.DeviceConfig().GenruleSandboxing() && !DepfileAllowSet[g.Name()] { @@ -1024,8 +1037,19 @@ func DefaultsFactory(props ...interface{}) android.Module { } func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder { - if !ctx.DeviceConfig().GenruleSandboxing() || SandboxingDenyPathSet[ctx.ModuleDir()] || - SandboxingDenyModuleSet[ctx.ModuleName()] { + if !ctx.DeviceConfig().GenruleSandboxing() { + return r.SandboxTools() + } + if SandboxingDenyModuleSet == nil { + SandboxingDenyModuleSetLock.Lock() + defer SandboxingDenyModuleSetLock.Unlock() + SandboxingDenyModuleSet = map[string]bool{} + SandboxingDenyPathSet = map[string]bool{} + android.AddToStringSet(SandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...)) + android.AddToStringSet(SandboxingDenyPathSet, SandboxingDenyPathList) + } + + if SandboxingDenyPathSet[ctx.ModuleDir()] || SandboxingDenyModuleSet[ctx.ModuleName()] { return r.SandboxTools() } return r.SandboxInputs() diff --git a/java/app.go b/java/app.go index cdec1e121..58580d420 100755 --- a/java/app.go +++ b/java/app.go @@ -796,8 +796,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall if shouldInstallAppPackage { if a.privAppAllowlist.Valid() { - installPath := android.PathForModuleInstall(ctx, "etc", "permissions") - ctx.InstallFile(installPath, a.privAppAllowlist.Path().Base(), a.privAppAllowlist.Path()) + allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions") + allowlistInstallFilename := a.installApkName + ".xml" + ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path()) } var extraInstalledPaths android.Paths diff --git a/java/app_test.go b/java/app_test.go index 592859c0c..5aed17876 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -3542,8 +3542,8 @@ func TestPrivappAllowlist(t *testing.T) { } // verify that permissions are copied to device - app.Output("out/soong/target/product/test_device/system/etc/permissions/privapp_allowlist_com.android.foo.xml") - overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/privapp_allowlist_com.google.android.foo.xml") + app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml") + overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml") } func TestPrivappAllowlistAndroidMk(t *testing.T) { @@ -3594,7 +3594,7 @@ func TestPrivappAllowlistAndroidMk(t *testing.T) { t, "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist", baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0], - "privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/privapp_allowlist_com.android.foo.xml", + "privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml", ) overrideAndroidApp := overrideApp.Module().(*AndroidApp) @@ -3621,6 +3621,6 @@ func TestPrivappAllowlistAndroidMk(t *testing.T) { t, "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist", overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0], - "\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/privapp_allowlist_com.google.android.foo.xml", + "\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml", ) } diff --git a/java/base.go b/java/base.go index 374138c78..dd02ef8af 100644 --- a/java/base.go +++ b/java/base.go @@ -2188,5 +2188,9 @@ func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { if binary, ok := ctx.Module().(*Binary); ok { javaBinaryHostBp2Build(ctx, binary) } + case "java_test_host": + if testHost, ok := ctx.Module().(*TestHost); ok { + javaTestHostBp2Build(ctx, testHost) + } } } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 116c833e0..35f60979f 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -816,7 +816,7 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]) } - if global.EnableUffdGc { + if global.EnableUffdGc && image.target.Os == android.Android { cmd.Flag("--runtime-arg").Flag("-Xgc:CMC") } diff --git a/java/droidstubs.go b/java/droidstubs.go index 8a521aabb..151c94a43 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -535,6 +535,14 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi // b/223382732 FlagWithArg("--hide ", "ChangedDefault") + // Force metalava to ignore classes on the classpath when an API file contains missing classes. + // See b/285140653 for more information. + cmd.FlagWithArg("--api-class-resolution ", "api") + + // Force metalava to sort overloaded methods by their order in the source code. + // See b/285312164 for more information. + cmd.FlagWithArg("--api-overloaded-method-order ", "source") + return cmd } diff --git a/java/java.go b/java/java.go index aa9f936d0..4f7b4014a 100644 --- a/java/java.go +++ b/java/java.go @@ -936,6 +936,10 @@ type TestOptions struct { // Extra <option> tags to add to the auto generated test xml file. The "key" // is optional in each of these. Tradefed_options []tradefed.Option + + // Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., AndroidJunitTest. + // The "key" is optional in each of these. + Test_runner_options []tradefed.Option } type testProperties struct { @@ -1218,6 +1222,7 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, TestSuites: j.testProperties.Test_suites, Config: configs, OptionsForAutogenerated: j.testProperties.Test_options.Tradefed_options, + TestRunnerOptions: j.testProperties.Test_options.Test_runner_options, AutoGenConfig: j.testProperties.Auto_gen_config, UnitTest: j.testProperties.Test_options.Unit_test, DeviceTemplate: "${JavaTestConfigTemplate}", @@ -1416,6 +1421,8 @@ func TestHostFactory() android.Module { nil, nil) + android.InitBazelModule(module) + InitJavaModuleMultiTargets(module, android.HostSupported) return module @@ -1728,6 +1735,14 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, FlagWithArg("--hide ", "InvalidNullabilityOverride"). FlagWithArg("--hide ", "ChangedDefault") + // Force metalava to ignore classes on the classpath when an API file contains missing classes. + // See b/285140653 for more information. + cmd.FlagWithArg("--api-class-resolution ", "api") + + // Force metalava to sort overloaded methods by their order in the source code. + // See b/285312164 for more information. + cmd.FlagWithArg("--api-overloaded-method-order ", "source") + return cmd } @@ -3114,23 +3129,89 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { return } - libName := m.Name() + "_lib" + libInfo := libraryCreationInfo{ + deps: deps, + attrs: commonAttrs, + baseName: m.Name(), + hasKotlin: bp2BuildInfo.hasKotlin, + } + libName := createLibraryTarget(ctx, libInfo) + binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}}) + + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs) +} + +type javaTestHostAttributes struct { + *javaCommonAttributes + Deps bazel.LabelListAttribute + Runtime_deps bazel.LabelListAttribute +} + +// javaTestHostBp2Build is for java_test_host bp2build. +func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) { + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels + + deps := depLabels.Deps + deps.Append(depLabels.StaticDeps) + + var runtimeDeps bazel.LabelListAttribute + attrs := &javaTestHostAttributes{ + Runtime_deps: runtimeDeps, + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "java_test", + Bzl_load_location: "//build/bazel/rules/java:test.bzl", + } + + if commonAttrs.Srcs.IsEmpty() { + // if there are no sources, then the dependencies can only be used at runtime + attrs.Runtime_deps = deps + attrs.javaCommonAttributes = commonAttrs + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) + return + } + + libInfo := libraryCreationInfo{ + deps: deps, + attrs: commonAttrs, + baseName: m.Name(), + hasKotlin: bp2BuildInfo.hasKotlin, + } + libName := createLibraryTarget(ctx, libInfo) + attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}}) + + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) +} + +// libraryCreationInfo encapsulates the info needed to create java_library target from +// java_binary_host or java_test_host. +type libraryCreationInfo struct { + deps bazel.LabelListAttribute + attrs *javaCommonAttributes + baseName string + hasKotlin bool +} + +// helper function that creates java_library target from java_binary_host or java_test_host, +// and returns the library target name, +func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string { + libName := libInfo.baseName + "_lib" var libProps bazel.BazelTargetModuleProperties - if bp2BuildInfo.hasKotlin { + if libInfo.hasKotlin { libProps = ktJvmLibraryBazelTargetModuleProperties() } else { libProps = javaLibraryBazelTargetModuleProperties() } libAttrs := &javaLibraryAttributes{ - Deps: deps, - javaCommonAttributes: commonAttrs, + Deps: libInfo.deps, + javaCommonAttributes: libInfo.attrs, } ctx.CreateBazelTargetModule(libProps, android.CommonAttributes{Name: libName}, libAttrs) - binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}}) - - // Create the BazelTargetModule. - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs) + return libName } type bazelJavaImportAttributes struct { diff --git a/java/java_test.go b/java/java_test.go index ea89e6eb8..cd5c343ce 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2298,3 +2298,27 @@ java_test_host { t.Errorf("Expected args[\"extraConfigs\"] to equal %q, was %q", expected, args["extraConfigs"]) } } + +func TestTestRunnerOptions(t *testing.T) { + result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` +java_test_host { + name: "foo", + test_options: { + test_runner_options: [ + { + name: "test-timeout", + value: "10m" + } + ] + } +} +`) + + buildOS := result.Config.BuildOS.String() + args := result.ModuleForTests("foo", buildOS+"_common"). + Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args + expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n ") + if args["extraTestRunnerConfigs"] != expected { + t.Errorf("Expected args[\"extraTestRunnerConfigs\"] to equal %q, was %q", expected, args["extraTestRunnerConfigs"]) + } +} diff --git a/rust/builder.go b/rust/builder.go index 0aa2225f7..0dfaef49f 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -261,7 +261,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl // Disallow experimental features modulePath := android.PathForModuleSrc(ctx).String() if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) { - rustcFlags = append(rustcFlags, "-Zallow-features=\"custom_inner_attributes,mixed_integer_ops\"") + rustcFlags = append(rustcFlags, "-Zallow-features=\"\"") } // Collect linker flags diff --git a/rust/config/global.go b/rust/config/global.go index 748bb3d2f..60acc6e28 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -51,9 +51,6 @@ var ( // Use v0 mangling to distinguish from C++ symbols "-C symbol-mangling-version=v0", "--color always", - // TODO (b/267698452): Temporary workaround until the "no unstable - // features" policy is enforced. - "-A stable-features", "-Zdylib-lto", } diff --git a/tests/genrule_sandbox_test.sh b/tests/genrule_sandbox_test.sh new file mode 100755 index 000000000..21b476bad --- /dev/null +++ b/tests/genrule_sandbox_test.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +# Copyright (C) 2023 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. + +set -e + +# Build the given genrule modules with GENRULE_SANDBOXING enabled and disabled, +# then compare the output of the modules and report result. + +function die() { format=$1; shift; printf >&2 "$format\n" $@; exit 1; } + +function usage() { + die "usage: ${0##*/} <-t lunch_target> [module]..." +} + +if [ ! -e "build/make/core/Makefile" ]; then + die "$0 must be run from the top of the Android source tree." +fi + +declare TARGET= +while getopts "t:" opt; do + case $opt in + t) + TARGET=$OPTARG ;; + *) usage ;; + esac +done + +shift $((OPTIND-1)) +MODULES="$@" + +source build/envsetup.sh + +if [[ -n $TARGET ]]; then + lunch $TARGET +fi + +if [[ -z ${OUT_DIR+x} ]]; then + OUT_DIR="out" +fi + +OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)" +PASS=true + +function cleanup { + if [ $PASS = true ]; then + rm -rf "${OUTPUT_DIR}" + fi +} +trap cleanup EXIT + +declare -A GEN_PATH_MAP + +function find_gen_paths() { + for module in $MODULES; do + module_path=$(pathmod "$module") + package_path=${module_path#$ANDROID_BUILD_TOP} + gen_path=$OUT_DIR/soong/.intermediates$package_path/$module + GEN_PATH_MAP[$module]=$gen_path + done +} + +function store_outputs() { + local dir=$1; shift + + for module in $MODULES; do + dest_dir=$dir/${module} + mkdir -p $dest_dir + gen_path=${GEN_PATH_MAP[$module]} + cp -r $gen_path $dest_dir + done +} + +function cmp_outputs() { + local dir1=$1; shift + local dir2=$1; shift + + for module in $MODULES; do + if ! diff -rq --exclude=genrule.sbox.textproto $dir1/$module $dir2/$module; then + PASS=false + echo "$module differ" + fi + done + if [ $PASS = true ]; then + echo "Test passed" + fi +} + +if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then + refreshmod +fi + +find_gen_paths +m --skip-soong-tests GENRULE_SANDBOXING=true "${MODULES[@]}" +store_outputs "$OUTPUT_DIR/sandbox" +m --skip-soong-tests GENRULE_SANDBOXING=false "${MODULES[@]}" +store_outputs "$OUTPUT_DIR/non_sandbox" + +cmp_outputs "$OUTPUT_DIR/non_sandbox" "$OUTPUT_DIR/sandbox" diff --git a/tradefed/autogen.go b/tradefed/autogen.go index 49b09afea..3c55c51e1 100644 --- a/tradefed/autogen.go +++ b/tradefed/autogen.go @@ -40,9 +40,9 @@ func getTestConfig(ctx android.ModuleContext, prop *string) android.Path { } var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{ - Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g;s&{TEST_INSTALL_BASE}&'${testInstallBase}'&g' $template > $out", + Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{EXTRA_TEST_RUNNER_CONFIGS}&'${extraTestRunnerConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g;s&{TEST_INSTALL_BASE}&'${testInstallBase}'&g' $template > $out", CommandDeps: []string{"$template"}, -}, "name", "template", "extraConfigs", "outputFileName", "testInstallBase") +}, "name", "template", "extraConfigs", "outputFileName", "testInstallBase", "extraTestRunnerConfigs") func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) { p := getTestConfig(ctx, prop) @@ -107,7 +107,7 @@ func (ob Object) Config() string { } -func autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string, testInstallBase string) { +func autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, testRunnerConfigs []Option, outputFileName string, testInstallBase string) { if template == "" { ctx.ModuleErrorf("Empty template") } @@ -118,16 +118,27 @@ func autogenTemplate(ctx android.ModuleContext, name string, output android.Writ extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent)) extraConfigs = proptools.NinjaAndShellEscape(extraConfigs) + var testRunnerConfigStrings []string + for _, config := range testRunnerConfigs { + testRunnerConfigStrings = append(testRunnerConfigStrings, config.Config()) + } + extraTestRunnerConfigs := strings.Join(testRunnerConfigStrings, fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)) + if len(extraTestRunnerConfigs) > 0 { + extraTestRunnerConfigs += fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent) + } + extraTestRunnerConfigs = proptools.NinjaAndShellEscape(extraTestRunnerConfigs) + ctx.Build(pctx, android.BuildParams{ Rule: autogenTestConfig, Description: "test config", Output: output, Args: map[string]string{ - "name": name, - "template": template, - "extraConfigs": extraConfigs, - "outputFileName": outputFileName, - "testInstallBase": testInstallBase, + "name": name, + "template": template, + "extraConfigs": extraConfigs, + "outputFileName": outputFileName, + "testInstallBase": testInstallBase, + "extraTestRunnerConfigs": extraTestRunnerConfigs, }, }) } @@ -142,6 +153,7 @@ type AutoGenTestConfigOptions struct { TestSuites []string Config []Config OptionsForAutogenerated []Option + TestRunnerOptions []Option AutoGenConfig *bool UnitTest *bool TestInstallBase string @@ -155,6 +167,7 @@ func AutoGenTestConfig(ctx android.ModuleContext, options AutoGenTestConfigOptio for _, c := range options.OptionsForAutogenerated { configs = append(configs, c) } + testRunnerConfigs := append([]Option{}, options.TestRunnerOptions...) name := options.Name if name == "" { name = ctx.ModuleName() @@ -163,15 +176,15 @@ func AutoGenTestConfig(ctx android.ModuleContext, options AutoGenTestConfigOptio if autogenPath != nil { templatePath := getTestConfigTemplate(ctx, options.TestConfigTemplateProp) if templatePath.Valid() { - autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.OutputFileName, options.TestInstallBase) + autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase) } else { if ctx.Device() { - autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.OutputFileName, options.TestInstallBase) + autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase) } else { if Bool(options.UnitTest) { - autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, options.OutputFileName, options.TestInstallBase) + autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase) } else { - autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, options.OutputFileName, options.TestInstallBase) + autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, testRunnerConfigs, options.OutputFileName, options.TestInstallBase) } } } diff --git a/ui/build/config.go b/ui/build/config.go index bfbf85dd9..711774a8a 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -231,8 +231,9 @@ func UploadOnlyConfig(ctx Context, args ...string) Config { func NewConfig(ctx Context, args ...string) Config { ret := &configImpl{ - environ: OsEnvironment(), - sandboxConfig: &SandboxConfig{}, + environ: OsEnvironment(), + sandboxConfig: &SandboxConfig{}, + ninjaWeightListSource: NINJA_LOG, } // Default matching ninja @@ -1641,6 +1642,16 @@ func (c *configImpl) IsPersistentBazelEnabled() bool { return c.Environment().IsEnvTrue("USE_PERSISTENT_BAZEL") } +// GetBazeliskBazelVersion returns the Bazel version to use for this build, +// or the empty string if the current canonical prod Bazel should be used. +// This environment variable should only be set to debug the build system. +// The Bazel version, if set, will be passed to Bazelisk, and Bazelisk will +// handle downloading and invoking the correct Bazel binary. +func (c *configImpl) GetBazeliskBazelVersion() string { + value, _ := c.Environment().Get("USE_BAZEL_VERSION") + return value +} + func (c *configImpl) BazelModulesForceEnabledByFlag() string { return c.bazelForceEnabledModules } diff --git a/ui/build/ninja.go b/ui/build/ninja.go index 5d56531b2..61aaad86b 100644 --- a/ui/build/ninja.go +++ b/ui/build/ninja.go @@ -35,48 +35,6 @@ const ( ninjaWeightListFileName = ".ninja_weight_list" ) -func useNinjaBuildLog(ctx Context, config Config, cmd *Cmd) { - ninjaLogFile := filepath.Join(config.OutDir(), ninjaLogFileName) - data, err := os.ReadFile(ninjaLogFile) - var outputBuilder strings.Builder - if err == nil { - lines := strings.Split(strings.TrimSpace(string(data)), "\n") - // ninja log: <start> <end> <restat> <name> <cmdhash> - // ninja weight list: <name>,<end-start+1> - for _, line := range lines { - if strings.HasPrefix(line, "#") { - continue - } - fields := strings.Split(line, "\t") - path := fields[3] - start, err := strconv.Atoi(fields[0]) - if err != nil { - continue - } - end, err := strconv.Atoi(fields[1]) - if err != nil { - continue - } - outputBuilder.WriteString(path) - outputBuilder.WriteString(",") - outputBuilder.WriteString(strconv.Itoa(end-start+1) + "\n") - } - } else { - // If there is no ninja log file, just pass empty ninja weight list. - // Because it is still efficient with critical path calculation logic even without weight. - ctx.Verbosef("There is an error during reading ninja log, so ninja will use empty weight list: %s", err) - } - - weightListFile := filepath.Join(config.OutDir(), ninjaWeightListFileName) - - err = os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644) - if err == nil { - cmd.Args = append(cmd.Args, "-o", "usesweightlist="+weightListFile) - } else { - ctx.Panicf("Could not write ninja weight list file %s", err) - } -} - // Constructs and runs the Ninja command line with a restricted set of // environment variables. It's important to restrict the environment Ninja runs // for hermeticity reasons, and to avoid spurious rebuilds. @@ -131,7 +89,7 @@ func runNinjaForBuild(ctx Context, config Config) { switch config.NinjaWeightListSource() { case NINJA_LOG: - useNinjaBuildLog(ctx, config, cmd) + cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes") case EVENLY_DISTRIBUTED: // pass empty weight list means ninja considers every tasks's weight as 1(default value). cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null") diff --git a/ui/build/soong.go b/ui/build/soong.go index 6de8d6f98..986ec702b 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -533,7 +533,7 @@ func runSoong(ctx Context, config Config) { defer ctx.EndTrace() if config.IsPersistentBazelEnabled() { - bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace")) + bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace"), config.GetBazeliskBazelVersion()) bazelProxy.Start() defer bazelProxy.Close() } |