summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aconfig/Android.bp4
-rw-r--r--aconfig/aconfig_declarations.go22
-rw-r--r--aconfig/aconfig_declarations_test.go5
-rw-r--r--aconfig/cc_aconfig_library.go128
-rw-r--r--aconfig/init.go43
-rw-r--r--aconfig/java_aconfig_library.go21
-rw-r--r--aconfig/java_aconfig_library_test.go191
-rw-r--r--aconfig/rust_aconfig_library.go89
-rw-r--r--aconfig/rust_aconfig_library_test.go60
-rw-r--r--android/Android.bp1
-rw-r--r--android/allowlists/allowlists.go178
-rw-r--r--android/api_levels.go4
-rw-r--r--android/arch.go4
-rw-r--r--android/bazel.go85
-rw-r--r--android/bazel_handler.go183
-rw-r--r--android/bazel_handler_test.go51
-rw-r--r--android/bazel_paths.go37
-rw-r--r--android/bazel_paths_test.go11
-rw-r--r--android/bazel_test.go9
-rw-r--r--android/config.go136
-rw-r--r--android/config_test.go10
-rw-r--r--android/configured_jars.go41
-rw-r--r--android/configured_jars_test.go46
-rw-r--r--android/depset_generic.go6
-rw-r--r--android/filegroup.go37
-rw-r--r--android/fixture.go2
-rw-r--r--android/module.go94
-rw-r--r--android/mutator.go24
-rw-r--r--android/override_module.go10
-rw-r--r--android/paths.go26
-rw-r--r--android/prebuilt_build_tool.go4
-rw-r--r--android/proto.go139
-rw-r--r--android/rule_builder.go16
-rw-r--r--android/sdk_version_test.go2
-rw-r--r--android/test_config.go2
-rw-r--r--android/util.go22
-rw-r--r--android/util_test.go63
-rw-r--r--android/variable.go52
-rw-r--r--android_sdk/sdk_repo_host.go2
-rw-r--r--apex/apex.go41
-rw-r--r--apex/apex_test.go339
-rw-r--r--apex/bootclasspath_fragment_test.go199
-rw-r--r--apex/dexpreopt_bootjars_test.go14
-rw-r--r--apex/vndk.go2
-rw-r--r--apex/vndk_test.go1
-rw-r--r--bazel/aquery.go89
-rw-r--r--bazel/aquery_test.go133
-rw-r--r--bazel/configurability.go56
-rw-r--r--bazel/properties.go70
-rw-r--r--bazel/properties_test.go105
-rw-r--r--bp2build/Android.bp3
-rw-r--r--bp2build/android_app_conversion_test.go18
-rw-r--r--bp2build/apex_conversion_test.go4
-rw-r--r--bp2build/bp2build.go34
-rw-r--r--bp2build/bp2build_product_config.go291
-rw-r--r--bp2build/bp2build_product_config_test.go89
-rw-r--r--bp2build/build_conversion.go430
-rw-r--r--bp2build/build_conversion_test.go48
-rw-r--r--bp2build/bzl_conversion_test.go5
-rw-r--r--bp2build/cc_binary_conversion_test.go88
-rw-r--r--bp2build/cc_library_conversion_test.go183
-rw-r--r--bp2build/cc_library_shared_conversion_test.go9
-rw-r--r--bp2build/cc_library_static_conversion_test.go94
-rw-r--r--bp2build/cc_object_conversion_test.go2
-rw-r--r--bp2build/cc_test_conversion_test.go135
-rw-r--r--bp2build/conversion.go12
-rw-r--r--bp2build/conversion_test.go3
-rw-r--r--bp2build/filegroup_conversion_test.go33
-rw-r--r--bp2build/genrule_conversion_test.go257
-rw-r--r--bp2build/go_conversion_test.go208
-rw-r--r--bp2build/java_library_conversion_test.go28
-rw-r--r--bp2build/java_test_host_conversion_test.go9
-rw-r--r--bp2build/prebuilt_etc_conversion_test.go4
-rw-r--r--bp2build/soong_config_module_type_conversion_test.go285
-rw-r--r--bp2build/testing.go8
-rwxr-xr-xbuild_kzip.bash4
-rw-r--r--cc/Android.bp3
-rw-r--r--cc/afdo.go4
-rw-r--r--cc/api_level.go6
-rw-r--r--cc/binary.go12
-rw-r--r--cc/bp2build.go269
-rw-r--r--cc/cc.go98
-rw-r--r--cc/cc_test.go3
-rw-r--r--cc/compiler.go12
-rw-r--r--cc/config/arm64_device.go10
-rw-r--r--cc/config/arm_device.go11
-rw-r--r--cc/config/global.go22
-rw-r--r--cc/config/riscv64_device.go3
-rw-r--r--cc/config/toolchain.go2
-rw-r--r--cc/coverage.go2
-rw-r--r--cc/fuzz.go56
-rw-r--r--cc/generated_cc_library.go38
-rw-r--r--cc/image.go7
-rw-r--r--cc/library.go38
-rw-r--r--cc/linkable.go9
-rw-r--r--cc/lto.go80
-rw-r--r--cc/ndk_library.go73
-rw-r--r--cc/ndk_sysroot.go1
-rw-r--r--cc/orderfile.go256
-rw-r--r--cc/orderfile_test.go470
-rw-r--r--cc/rs.go11
-rw-r--r--cc/sanitize.go16
-rw-r--r--cc/snapshot_prebuilt.go6
-rw-r--r--cc/snapshot_utils.go8
-rw-r--r--cc/stl.go13
-rw-r--r--cc/test.go65
-rw-r--r--cc/testing.go24
-rw-r--r--cc/util.go4
-rw-r--r--cc/vendor_snapshot.go33
-rw-r--r--cc/vndk.go31
-rw-r--r--cmd/merge_zips/merge_zips.go22
-rw-r--r--cmd/merge_zips/merge_zips_test.go68
-rw-r--r--cmd/pom2bp/pom2bp.go3
-rw-r--r--cmd/soong_build/main.go13
-rw-r--r--cmd/soong_build/queryview.go5
-rw-r--r--cmd/soong_ui/main.go5
-rw-r--r--cmd/zip2zip/BUILD.bazel18
-rw-r--r--dexpreopt/config.go4
-rw-r--r--dexpreopt/testing.go7
-rw-r--r--fuzz/fuzz_common.go2
-rw-r--r--genrule/allowlists.go26
-rw-r--r--genrule/genrule.go123
-rw-r--r--genrule/genrule_test.go85
-rw-r--r--jar/Android.bp1
-rw-r--r--jar/services.go128
-rw-r--r--java/Android.bp1
-rw-r--r--java/aapt2.go75
-rw-r--r--java/aar.go518
-rw-r--r--java/android_manifest_test.go103
-rw-r--r--java/androidmk.go31
-rwxr-xr-xjava/app.go73
-rw-r--r--java/app_builder.go33
-rw-r--r--java/app_import.go75
-rw-r--r--java/app_test.go536
-rw-r--r--java/base.go90
-rw-r--r--java/bootclasspath.go5
-rw-r--r--java/bootclasspath_fragment.go268
-rw-r--r--java/bootclasspath_fragment_test.go35
-rw-r--r--java/builder.go55
-rw-r--r--java/config/config.go2
-rw-r--r--java/core-libraries/Android.bp90
-rw-r--r--java/core-libraries/TxtStubLibraries.bp20
-rw-r--r--java/device_host_converter.go2
-rw-r--r--java/device_host_converter_test.go3
-rw-r--r--java/dexpreopt_bootjars.go327
-rw-r--r--java/dexpreopt_config.go93
-rw-r--r--java/dexpreopt_config_test.go20
-rw-r--r--java/dexpreopt_config_testing.go188
-rw-r--r--java/droiddoc.go1
-rw-r--r--java/droidstubs.go25
-rw-r--r--java/fuzz_test.go4
-rw-r--r--java/generated_java_library.go4
-rw-r--r--java/generated_java_library_test.go3
-rw-r--r--java/hiddenapi.go2
-rw-r--r--java/hiddenapi_modular.go1
-rw-r--r--java/hiddenapi_singleton.go6
-rw-r--r--java/java.go166
-rw-r--r--java/java_test.go57
-rw-r--r--java/kotlin.go2
-rw-r--r--java/lint_defaults.txt14
-rw-r--r--java/platform_bootclasspath.go91
-rw-r--r--java/plugin.go5
-rw-r--r--java/sdk_library.go61
-rw-r--r--java/sdk_library_test.go6
-rw-r--r--python/bp2build.go6
-rw-r--r--python/builder.go4
-rw-r--r--python/proto.go3
-rw-r--r--python/python.go36
-rw-r--r--python/tests/par_test.py9
-rw-r--r--python/tests/py-cmd_test.py16
-rw-r--r--rust/binary.go5
-rw-r--r--rust/binary_test.go27
-rw-r--r--rust/bindgen.go31
-rw-r--r--rust/bindgen_test.go25
-rw-r--r--rust/builder.go31
-rw-r--r--rust/compiler.go16
-rw-r--r--rust/config/arm64_device.go17
-rw-r--r--rust/config/global.go3
-rw-r--r--rust/fuzz.go6
-rw-r--r--rust/fuzz_test.go10
-rw-r--r--rust/image.go13
-rw-r--r--rust/library.go44
-rw-r--r--rust/protobuf.go2
-rw-r--r--rust/rust.go71
-rw-r--r--rust/rust_test.go30
-rw-r--r--rust/sanitize.go45
-rw-r--r--rust/snapshot_prebuilt.go24
-rw-r--r--rust/snapshot_utils.go11
-rw-r--r--rust/testing.go1
-rw-r--r--rust/vendor_snapshot_test.go317
-rwxr-xr-xscripts/mkcratersp.py12
-rwxr-xr-xscripts/unpack-prebuilt-apex.sh2
-rw-r--r--sdk/bootclasspath_fragment_sdk_test.go40
-rw-r--r--sdk/java_sdk_test.go8
-rw-r--r--starlark_fmt/format.go67
-rw-r--r--starlark_import/unmarshal.go20
-rw-r--r--starlark_import/unmarshal_test.go21
-rw-r--r--sysprop/sysprop_library.go30
-rwxr-xr-xtests/genrule_sandbox_test.py142
-rw-r--r--tests/lib.sh9
-rwxr-xr-xtests/run_integration_tests.sh4
-rwxr-xr-xtests/sbom_test.sh139
-rw-r--r--third_party/zip/android.go2
-rw-r--r--ui/build/config.go114
-rw-r--r--ui/metrics/bp2build_progress_metrics_proto/bp2build.proto3
-rw-r--r--zip/cmd/BUILD.bazel20
-rw-r--r--zip/cmd/main.go2
-rw-r--r--zip/zip.go7
208 files changed, 9325 insertions, 2610 deletions
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index ae8276f39..d2ddfdfc6 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -14,20 +14,24 @@ bootstrap_go_package {
"soong-bazel",
"soong-android",
"soong-java",
+ "soong-rust",
],
srcs: [
"aconfig_declarations.go",
"aconfig_values.go",
"aconfig_value_set.go",
"all_aconfig_declarations.go",
+ "cc_aconfig_library.go",
"init.go",
"java_aconfig_library.go",
"testing.go",
+ "rust_aconfig_library.go",
],
testSrcs: [
"aconfig_declarations_test.go",
"aconfig_values_test.go",
"aconfig_value_set_test.go",
+ "java_aconfig_library_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 007d5290f..4e199dd24 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -17,8 +17,9 @@ package aconfig
import (
"android/soong/android"
"fmt"
- "github.com/google/blueprint"
"strings"
+
+ "github.com/google/blueprint"
)
type DeclarationsModule struct {
@@ -96,6 +97,15 @@ func joinAndPrefix(prefix string, values []string) string {
return sb.String()
}
+func optionalVariable(prefix string, value string) string {
+ var sb strings.Builder
+ if value != "" {
+ sb.WriteString(prefix)
+ sb.WriteString(value)
+ }
+ return sb.String()
+}
+
// Provider published by aconfig_value_set
type declarationsProviderData struct {
Package string
@@ -123,15 +133,17 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module
// Intermediate format
inputFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
intermediatePath := android.PathForModuleOut(ctx, "intermediate.pb")
+ defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission()
ctx.Build(pctx, android.BuildParams{
Rule: aconfigRule,
- Inputs: inputFiles,
Output: intermediatePath,
Description: "aconfig_declarations",
Args: map[string]string{
- "release_version": ctx.Config().ReleaseVersion(),
- "package": module.properties.Package,
- "values": joinAndPrefix(" --values ", module.properties.Values),
+ "release_version": ctx.Config().ReleaseVersion(),
+ "package": module.properties.Package,
+ "declarations": android.JoinPathsWithPrefix(inputFiles, "--declarations "),
+ "values": joinAndPrefix(" --values ", module.properties.Values),
+ "default-permission": optionalVariable(" --default-permission ", defaultPermission),
},
})
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index e14ca3851..e0d8f7d5a 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -26,7 +26,10 @@ func TestAconfigDeclarations(t *testing.T) {
aconfig_declarations {
name: "module_name",
package: "com.example.package",
- srcs: ["foo.aconfig"],
+ srcs: [
+ "foo.aconfig",
+ "bar.aconfig",
+ ],
}
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go
new file mode 100644
index 000000000..14090bc90
--- /dev/null
+++ b/aconfig/cc_aconfig_library.go
@@ -0,0 +1,128 @@
+// 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 aconfig
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "github.com/google/blueprint"
+
+ "fmt"
+ "strings"
+)
+
+type ccDeclarationsTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var ccDeclarationsTag = ccDeclarationsTagType{}
+
+type CcAconfigLibraryProperties struct {
+ // name of the aconfig_declarations module to generate a library for
+ Aconfig_declarations string
+}
+
+type CcAconfigLibraryCallbacks struct {
+ properties *CcAconfigLibraryProperties
+
+ generatedDir android.WritablePath
+ headerDir android.WritablePath
+ generatedCpp android.WritablePath
+ generatedH android.WritablePath
+}
+
+func CcAconfigLibraryFactory() android.Module {
+ callbacks := &CcAconfigLibraryCallbacks{
+ properties: &CcAconfigLibraryProperties{},
+ }
+ return cc.GeneratedCcLibraryModuleFactory("cc_aconfig_library", callbacks)
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorInit(ctx cc.BaseModuleContext) {
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorProps() []interface{} {
+ return []interface{}{this.properties}
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorDeps(ctx cc.DepsContext, deps cc.Deps) cc.Deps {
+ // Add a dependency for the declarations module
+ declarations := this.properties.Aconfig_declarations
+ if len(declarations) == 0 {
+ ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
+ } else {
+ ctx.AddDependency(ctx.Module(), ccDeclarationsTag, declarations)
+ }
+
+ // Add a dependency for the aconfig flags base library
+ deps.SharedLibs = append(deps.SharedLibs, "server_configurable_flags")
+ // TODO: It'd be really nice if we could reexport this library and not make everyone do it.
+
+ return deps
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorSources(ctx cc.ModuleContext) cc.GeneratedSource {
+ result := cc.GeneratedSource{}
+
+ // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+ declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+ if len(declarationsModules) != 1 {
+ panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ }
+ declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+ // Figure out the generated file paths. This has to match aconfig's codegen_cpp.rs.
+ this.generatedDir = android.PathForModuleGen(ctx)
+
+ this.headerDir = android.PathForModuleGen(ctx, "include")
+ result.IncludeDirs = []android.Path{this.headerDir}
+ result.ReexportedDirs = []android.Path{this.headerDir}
+
+ basename := strings.ReplaceAll(declarations.Package, ".", "_")
+
+ this.generatedCpp = android.PathForModuleGen(ctx, basename+".cc")
+ result.Sources = []android.Path{this.generatedCpp}
+
+ this.generatedH = android.PathForModuleGen(ctx, "include", basename+".h")
+ result.Headers = []android.Path{this.generatedH}
+
+ return result
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorFlags(ctx cc.ModuleContext, flags cc.Flags, deps cc.PathDeps) cc.Flags {
+ return flags
+}
+
+func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContext, flags cc.Flags, deps cc.PathDeps) {
+ // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+ declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+ if len(declarationsModules) != 1 {
+ panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ }
+ declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: cppRule,
+ Input: declarations.IntermediatePath,
+ Outputs: []android.WritablePath{
+ this.generatedCpp,
+ this.generatedH,
+ },
+ Description: "cc_aconfig_library",
+ Args: map[string]string{
+ "gendir": this.generatedDir.String(),
+ },
+ })
+}
diff --git a/aconfig/init.go b/aconfig/init.go
index 161fd4248..797388d6c 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -16,6 +16,7 @@ package aconfig
import (
"android/soong/android"
+
"github.com/google/blueprint"
)
@@ -27,23 +28,25 @@ var (
blueprint.RuleParams{
Command: `${aconfig} create-cache` +
` --package ${package}` +
- ` --declarations ${in}` +
+ ` ${declarations}` +
` ${values}` +
+ ` ${default-permission}` +
` --cache ${out}.tmp` +
- ` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
+ ` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
// ` --build-id ${release_version}` +
CommandDeps: []string{
"${aconfig}",
},
Restat: true,
- }, "release_version", "package", "values")
+ }, "release_version", "package", "declarations", "values", "default-permission")
// For java_aconfig_library: Generate java file
- srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
+ javaRule = pctx.AndroidStaticRule("java_aconfig_library",
blueprint.RuleParams{
Command: `rm -rf ${out}.tmp` +
` && mkdir -p ${out}.tmp` +
` && ${aconfig} create-java-lib` +
+ ` --mode ${mode}` +
` --cache ${in}` +
` --out ${out}.tmp` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
@@ -53,7 +56,35 @@ var (
"$soong_zip",
},
Restat: true,
- })
+ }, "mode")
+
+ // For java_aconfig_library: Generate java file
+ cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
+ blueprint.RuleParams{
+ Command: `rm -rf ${gendir}` +
+ ` && mkdir -p ${gendir}` +
+ ` && ${aconfig} create-cpp-lib` +
+ ` --cache ${in}` +
+ ` --out ${gendir}`,
+ CommandDeps: []string{
+ "$aconfig",
+ "$soong_zip",
+ },
+ }, "gendir")
+
+ rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
+ blueprint.RuleParams{
+ Command: `rm -rf ${gendir}` +
+ ` && mkdir -p ${gendir}` +
+ ` && ${aconfig} create-rust-lib` +
+ ` --mode ${mode}` +
+ ` --cache ${in}` +
+ ` --out ${gendir}`,
+ CommandDeps: []string{
+ "$aconfig",
+ "$soong_zip",
+ },
+ }, "gendir", "mode")
// For all_aconfig_declarations
allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump",
@@ -75,6 +106,8 @@ func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
ctx.RegisterModuleType("aconfig_values", ValuesFactory)
ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
+ ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
+ ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
}
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
index 0eeb14ffc..53f8bd1ba 100644
--- a/aconfig/java_aconfig_library.go
+++ b/aconfig/java_aconfig_library.go
@@ -30,6 +30,9 @@ var declarationsTag = declarationsTagType{}
type JavaAconfigDeclarationsLibraryProperties struct {
// name of the aconfig_declarations module to generate a library for
Aconfig_declarations string
+
+ // whether to generate test mode version of the library
+ Test bool
}
type JavaAconfigDeclarationsLibraryCallbacks struct {
@@ -51,7 +54,7 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *ja
}
}
-func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
if len(declarationsModules) != 1 {
@@ -59,13 +62,27 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild
}
declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+ // Generate the action to build the srcjar
srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
+ var mode string
+ if callbacks.properties.Test {
+ mode = "test"
+ } else {
+ mode = "production"
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: srcJarRule,
+ Rule: javaRule,
Input: declarations.IntermediatePath,
Output: srcJarPath,
Description: "aconfig.srcjar",
+ Args: map[string]string{
+ "mode": mode,
+ },
})
+ // Tell the java module about the .aconfig files, so they can be propagated up the dependency chain.
+ // TODO: It would be nice to have that propagation code here instead of on java.Module and java.JavaInfo.
+ module.AddAconfigIntermediate(declarations.IntermediatePath)
+
return srcJarPath
}
diff --git a/aconfig/java_aconfig_library_test.go b/aconfig/java_aconfig_library_test.go
new file mode 100644
index 000000000..af50848f1
--- /dev/null
+++ b/aconfig/java_aconfig_library_test.go
@@ -0,0 +1,191 @@
+// 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 aconfig
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+// Note: These tests cover the code in the java package. It'd be ideal of that code could
+// be in the aconfig package.
+
+// With the bp parameter that defines a my_module, make sure it has the LOCAL_ACONFIG_FILES entries
+func runJavaAndroidMkTest(t *testing.T, bp string) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, bp+`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ }
+ `)
+
+ module := result.ModuleForTests("my_module", "android_common").Module()
+
+ entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
+
+ makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
+ android.AssertIntEquals(t, "len(LOCAL_ACONFIG_FILES)", 1, len(makeVar))
+ if !strings.HasSuffix(makeVar[0], "intermediate.pb") {
+ t.Errorf("LOCAL_ACONFIG_FILES should end with /intermediates.pb, instead it is: %s", makeVar[0])
+ }
+}
+
+func TestAndroidMkJavaLibrary(t *testing.T) {
+ bp := `
+ java_library {
+ name: "my_module",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library",
+ ],
+ platform_apis: true,
+ }
+ `
+
+ runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkAndroidApp(t *testing.T) {
+ bp := `
+ android_app {
+ name: "my_module",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library",
+ ],
+ platform_apis: true,
+ }
+ `
+
+ runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkBinary(t *testing.T) {
+ bp := `
+ java_binary {
+ name: "my_module",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library",
+ ],
+ platform_apis: true,
+ main_class: "foo",
+ }
+ `
+
+ runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkAndroidLibrary(t *testing.T) {
+ bp := `
+ android_library {
+ name: "my_module",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library",
+ ],
+ platform_apis: true,
+ }
+ `
+
+ runJavaAndroidMkTest(t, bp)
+}
+
+func TestAndroidMkBinaryThatLinksAgainstAar(t *testing.T) {
+ // Tests AndroidLibrary's propagation of flags through JavaInfo
+ bp := `
+ android_library {
+ name: "some_library",
+ srcs: [
+ "src/foo.java",
+ ],
+ static_libs: [
+ "my_java_aconfig_library",
+ ],
+ platform_apis: true,
+ }
+ java_binary {
+ name: "my_module",
+ srcs: [
+ "src/bar.java",
+ ],
+ static_libs: [
+ "some_library",
+ ],
+ platform_apis: true,
+ main_class: "foo",
+ }
+ `
+
+ runJavaAndroidMkTest(t, bp)
+}
+
+func testCodegenMode(t *testing.T, bpMode string, ruleMode string) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+
+ module := result.ModuleForTests("my_java_aconfig_library", "android_common")
+ rule := module.Rule("java_aconfig_library")
+ android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
+}
+
+func TestDefaultProdMode(t *testing.T) {
+ testCodegenMode(t, "", "production")
+}
+
+func TestProdMode(t *testing.T) {
+ testCodegenMode(t, "test: false,", "production")
+}
+
+func TestTestMode(t *testing.T) {
+ testCodegenMode(t, "test: true,", "test")
+}
diff --git a/aconfig/rust_aconfig_library.go b/aconfig/rust_aconfig_library.go
new file mode 100644
index 000000000..de41776a3
--- /dev/null
+++ b/aconfig/rust_aconfig_library.go
@@ -0,0 +1,89 @@
+package aconfig
+
+import (
+ "android/soong/android"
+ "android/soong/rust"
+ "fmt"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+type rustDeclarationsTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var rustDeclarationsTag = rustDeclarationsTagType{}
+
+type RustAconfigLibraryProperties struct {
+ // name of the aconfig_declarations module to generate a library for
+ Aconfig_declarations string
+ Test *bool
+}
+
+type aconfigDecorator struct {
+ *rust.BaseSourceProvider
+
+ Properties RustAconfigLibraryProperties
+}
+
+func NewRustAconfigLibrary(hod android.HostOrDeviceSupported) (*rust.Module, *aconfigDecorator) {
+ aconfig := &aconfigDecorator{
+ BaseSourceProvider: rust.NewSourceProvider(),
+ Properties: RustAconfigLibraryProperties{},
+ }
+
+ module := rust.NewSourceProviderModule(android.HostAndDeviceSupported, aconfig, false, false)
+ return module, aconfig
+}
+
+// rust_aconfig_library generates aconfig rust code from the provided aconfig declaration. This module type will
+// create library variants that can be used as a crate dependency by adding it to the rlibs, dylibs, and rustlibs
+// properties of other modules.
+func RustAconfigLibraryFactory() android.Module {
+ module, _ := NewRustAconfigLibrary(android.HostAndDeviceSupported)
+ return module.Init()
+}
+
+func (a *aconfigDecorator) SourceProviderProps() []interface{} {
+ return append(a.BaseSourceProvider.SourceProviderProps(), &a.Properties)
+}
+
+func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
+ generatedDir := android.PathForModuleGen(ctx)
+ generatedSource := android.PathForModuleGen(ctx, "src", "lib.rs")
+
+ declarationsModules := ctx.GetDirectDepsWithTag(rustDeclarationsTag)
+
+ if len(declarationsModules) != 1 {
+ panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ }
+ declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+ mode := "production"
+ if proptools.Bool(a.Properties.Test) {
+ mode = "test"
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rustRule,
+ Input: declarations.IntermediatePath,
+ Outputs: []android.WritablePath{
+ generatedSource,
+ },
+ Description: "rust_aconfig_library",
+ Args: map[string]string{
+ "gendir": generatedDir.String(),
+ "mode": mode,
+ },
+ })
+ a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
+ return generatedSource
+}
+
+func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps {
+ deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps)
+ deps.Rustlibs = append(deps.Rustlibs, "libflags_rust")
+ ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
+ return deps
+}
diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go
new file mode 100644
index 000000000..17385c3d1
--- /dev/null
+++ b/aconfig/rust_aconfig_library_test.go
@@ -0,0 +1,60 @@
+package aconfig
+
+import (
+ "android/soong/android"
+ "android/soong/rust"
+ "fmt"
+ "testing"
+)
+
+func TestRustAconfigLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ rust.PrepareForTestWithRustIncludeVndk,
+ android.PrepareForTestWithArchMutator,
+ android.PrepareForTestWithDefaults,
+ android.PrepareForTestWithPrebuilts,
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library",
+ crate_name: "my_rust_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ }
+ `))
+
+ sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
+ rule := sourceVariant.Rule("rust_aconfig_library")
+ android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")
+
+ dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
+ rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
+ rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
+
+ variants := []android.TestingModule{
+ dylibVariant,
+ rlibDylibStdVariant,
+ rlibRlibStdVariant,
+ }
+
+ for _, variant := range variants {
+ android.AssertStringEquals(
+ t,
+ "dylib variant builds from generated rust code",
+ "out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
+ variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
+ )
+ }
+}
diff --git a/android/Android.bp b/android/Android.bp
index fc5198fee..f5bb785ff 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -107,6 +107,7 @@ bootstrap_go_package {
"bazel_test.go",
"config_test.go",
"config_bp2build_test.go",
+ "configured_jars_test.go",
"csuite_config_test.go",
"defaults_test.go",
"depset_test.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index d320599e1..056c1a87a 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -121,6 +121,7 @@ var (
"development/sdk": Bp2BuildDefaultTrueRecursively,
"external/aac": Bp2BuildDefaultTrueRecursively,
+ "external/abseil-cpp": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
"external/auto": Bp2BuildDefaultTrue,
"external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
@@ -141,11 +142,13 @@ var (
"external/expat": Bp2BuildDefaultTrueRecursively,
"external/f2fs-tools": Bp2BuildDefaultTrue,
"external/flac": Bp2BuildDefaultTrueRecursively,
+ "external/flatbuffers": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/fsverity-utils": Bp2BuildDefaultTrueRecursively,
- "external/guava": Bp2BuildDefaultTrueRecursively,
+ "external/gflags": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
+ "external/guava": Bp2BuildDefaultTrueRecursively,
"external/gwp_asan": Bp2BuildDefaultTrueRecursively,
"external/hamcrest": Bp2BuildDefaultTrueRecursively,
"external/icu": Bp2BuildDefaultTrueRecursively,
@@ -188,7 +191,11 @@ var (
"external/ow2-asm": Bp2BuildDefaultTrueRecursively,
"external/pcre": Bp2BuildDefaultTrueRecursively,
"external/protobuf": Bp2BuildDefaultTrueRecursively,
+ "external/python/pyyaml/lib/yaml": Bp2BuildDefaultTrueRecursively,
"external/python/six": Bp2BuildDefaultTrueRecursively,
+ "external/python/jinja/src": Bp2BuildDefaultTrueRecursively,
+ "external/python/markupsafe/src": Bp2BuildDefaultTrueRecursively,
+ "external/python/setuptools": Bp2BuildDefaultTrueRecursively,
"external/rappor": Bp2BuildDefaultTrueRecursively,
"external/scudo": Bp2BuildDefaultTrueRecursively,
"external/selinux/checkpolicy": Bp2BuildDefaultTrueRecursively,
@@ -227,6 +234,7 @@ var (
"frameworks/hardware/interfaces/stats/aidl": Bp2BuildDefaultTrue,
"frameworks/libs/modules-utils/build": Bp2BuildDefaultTrueRecursively,
"frameworks/libs/net/common/native": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native": Bp2BuildDefaultTrue,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/gui": Bp2BuildDefaultTrue,
@@ -429,8 +437,11 @@ var (
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
"external/bazelbuild-rules_android":/* recursive = */ true,
+ "external/bazelbuild-rules_java":/* recursive = */ true,
"external/bazelbuild-rules_license":/* recursive = */ true,
"external/bazelbuild-rules_go":/* recursive = */ true,
+ "external/bazelbuild-rules_python":/* recursive = */ true,
+ "external/bazelbuild-rules_rust":/* recursive = */ true,
"external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
@@ -458,6 +469,7 @@ var (
"prebuilts/sdk/tools":/* recursive = */ false,
"prebuilts/r8":/* recursive = */ false,
"prebuilts/runtime":/* recursive = */ false,
+ "prebuilts/rust":/* recursive = */ true,
// not recursive due to conflicting workspace paths in tools/atest/bazel/rules
"tools/asuite/atest":/* recursive = */ false,
@@ -471,8 +483,36 @@ var (
}
Bp2buildModuleAlwaysConvertList = []string{
+ // ext
+ "tagsoup",
+
+ // framework-res
+ "remote-color-resources-compile-public",
+ "remote-color-resources-compile-colors",
+
+ // framework-minus-apex
+ "android.mime.types.minimized",
+ "debian.mime.types.minimized",
+ "framework-javastream-protos",
+ "libview-inspector-annotation-processor",
+
+ // services
+ "apache-commons-math",
+ "cbor-java",
+ "icu4j_calendar_astronomer",
+ "json",
+ "remote-color-resources-compile-public",
+ "statslog-art-java-gen",
+ "statslog-framework-java-gen",
+
+ "AndroidCommonLint",
+ "ImmutabilityAnnotation",
+ "ImmutabilityAnnotationProcessorHostLibrary",
+
"libidmap2_policies",
"libSurfaceFlingerProp",
+ "toolbox_input_labels",
+
// cc mainline modules
// com.android.media.swcodec
@@ -490,7 +530,6 @@ var (
"code_coverage.policy.other",
"codec2_soft_exports",
"compatibility_matrix_schema",
- "flatbuffer_headers",
"framework-connectivity-protos",
"gemmlowp_headers",
"gl_headers",
@@ -613,10 +652,6 @@ var (
"libhidlbase", // needed by cc_hidl_library
"libhidl_gtest_helper",
- //frameworks/native
- "framework_native_aidl_binder",
- "framework_native_aidl_gui",
-
//frameworks/native/libs/input
"inputconstants_aidl",
@@ -674,6 +709,7 @@ var (
"libcodec2_hidl@1.2",
"libcodec2_hidl_plugin_stub",
"libcodec2_hidl_plugin",
+ "libcodec2_hal_common",
"libstagefright_bufferqueue_helper_novndk",
"libGLESv2",
"libEGL",
@@ -763,6 +799,7 @@ var (
// Mainline Module Apps
"CaptivePortalLogin",
+ "ModuleMetadata",
"libstagefright_headers",
@@ -805,6 +842,14 @@ var (
"rs-headers",
"rs_script_api",
"libRSDispatch",
+
+ // hal_unit_tests and deps
+ "android.hardware.contexthub_interface", // created implicitly by android.hardware.contexthub
+ "chre_flatbuffers",
+ "event_logger",
+ "hal_unit_tests",
+
+ "merge_annotation_zips_test",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -828,6 +873,10 @@ var (
// the "prebuilt_" prefix to the name, so that it's differentiable from
// the source versions within Soong's module graph.
Bp2buildModuleDoNotConvertList = []string{
+ // TODO(b/263326760): Failed already.
+ "minijail_compiler_unittest",
+ "minijail_parser_unittest",
+
// Depends on unconverted libandroid, libgui
"dvr_buffer_queue-test",
"dvr_display-test",
@@ -909,13 +958,15 @@ var (
"libart_headers", // depends on unconverted modules: art_libartbase_headers
"libartbase-art-gtest", // depends on unconverted modules: libgtest_isolated, libart, libart-compiler, libdexfile, libprofile
"libartbased-art-gtest", // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled
+ "libart-runtime", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
+ "libart-runtime-for-test", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
"libartd", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
+ "libartd-runtime", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
"libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
"libdebuggerd", // depends on unconverted module: libdexfile
"libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
"libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
- "libfastdeploy_host", // depends on unconverted modules: libandroidfw, libusb, AdbWinApi
"libgmock_main_ndk", // depends on unconverted modules: libgtest_ndk_c++
"libgmock_ndk", // depends on unconverted modules: libgtest_ndk_c++
"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
@@ -931,9 +982,6 @@ var (
"test_fips", // depends on unconverted modules: adb
"timezone-host", // depends on unconverted modules: art.module.api.annotations
- // '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
- "toybox-static",
-
// aidl files not created
"overlayable_policy_aidl_interface",
@@ -972,8 +1020,6 @@ var (
"svcenc", "svcdec",
// Failing host cc_tests
- "libprocinfo_test",
- "ziparchive-tests",
"gtest_isolated_tests",
"libunwindstack_unit_test",
"power_tests", // failing test on server, but not on host
@@ -992,7 +1038,7 @@ var (
"libnativebridge6-test-case",
"libnativebridge6prezygotefork",
- "libandroidfw_tests", "aapt2_tests", // failing due to data path issues
+ "libandroidfw_tests", // failing due to data path issues
// error: overriding commands for target
// `out/host/linux-x86/nativetest64/gmock_tests/gmock_tests__cc_runner_test',
@@ -1016,6 +1062,7 @@ var (
"bionic-unit-tests-static",
"boringssl_crypto_test",
"boringssl_ssl_test",
+ "boringssl_test_support", //b/244431896
"cfi_test_helper",
"cfi_test_helper2",
"cintltst32",
@@ -1049,6 +1096,7 @@ var (
"ion-unit-tests",
"jemalloc5_integrationtests",
"jemalloc5_unittests",
+ "jemalloc5_stresstests", // run by run_jemalloc_tests.sh and will be deleted after V
"ld_config_test_helper",
"ld_preload_test_helper",
"libBionicCtsGtestMain", // depends on unconverted modules: libgtest_isolated
@@ -1078,7 +1126,6 @@ var (
"memunreachable_binder_test", // depends on unconverted modules: libbinder
"memunreachable_test",
"metadata_tests",
- "minijail0_cli_unittest_gtest",
"mpeg2dec",
"mvcdec",
"ns_hidden_child_helper",
@@ -1090,14 +1137,12 @@ var (
"rappor-tests", // depends on unconverted modules: jsr305, guava
"scudo_unit_tests",
"stats-log-api-gen-test", // depends on unconverted modules: libstats_proto_host
- "syscall_filter_unittest_gtest",
"thread_exit_cb_helper",
"tls_properties_helper",
"ulp",
"vec_test",
"yuvconstants",
"yuvconvert",
- "zipalign_tests",
// cc_test_library
"clang_diagnostic_tests",
@@ -1493,8 +1538,6 @@ var (
"ICU4CTestRunner",
"DeviceLongPollingStubTest",
- "HelloWorldHostTest", // TODO(b/280452825): Convert HelloWorldHostTest to b test
-
"libprotobuf-full-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
"libprotobuf-lite-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
@@ -1507,73 +1550,10 @@ var (
"libart_generated_headers",
"libart-runtime-gtest",
"libartd-runtime-gtest",
- }
+ "libart-unstripped",
- MixedBuildsDisabledList = []string{
- "libruy_static", "libtflite_kernel_utils", // TODO(b/237315968); Depend on prebuilt stl, not from source
-
- "art_libdexfile_dex_instruction_list_header", // breaks libart_mterp.armng, header not found
-
- "libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
- "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
-
- "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
- "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
- "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
-
- // Depends on libprotobuf-cpp-*
- "libadb_pairing_connection",
- "libadb_pairing_connection_static",
- "libadb_pairing_server", "libadb_pairing_server_static",
-
- // java_import[_host] issues
- // tradefed prebuilts depend on libprotobuf
- "prebuilt_tradefed",
- "prebuilt_tradefed-test-framework",
- // handcrafted BUILD.bazel files in //prebuilts/...
- "prebuilt_r8lib-prebuilt",
- "prebuilt_sdk-core-lambda-stubs",
- "prebuilt_android-support-collections-nodeps",
- "prebuilt_android-arch-core-common-nodeps",
- "prebuilt_android-arch-lifecycle-common-java8-nodeps",
- "prebuilt_android-arch-lifecycle-common-nodeps",
- "prebuilt_android-support-annotations-nodeps",
- "prebuilt_android-arch-paging-common-nodeps",
- "prebuilt_android-arch-room-common-nodeps",
- // TODO(b/217750501) exclude_dirs property not supported
- "prebuilt_kotlin-reflect",
- "prebuilt_kotlin-stdlib",
- "prebuilt_kotlin-stdlib-jdk7",
- "prebuilt_kotlin-stdlib-jdk8",
- "prebuilt_kotlin-test",
- // TODO(b/217750501) exclude_files property not supported
- "prebuilt_currysrc_org.eclipse",
-
- // TODO(b/266459895): re-enable libunwindstack
- "libunwindstack",
- "libunwindstack_stdout_log",
- "libunwindstack_no_dex",
- "libunwindstack_utils",
- "unwind_reg_info",
- "libunwindstack_local",
- "unwind_for_offline",
- "unwind",
- "unwind_info",
- "unwind_symbols",
- "libEGL",
- "libGLESv2",
- "libc_malloc_debug",
- "libcodec2_hidl@1.0",
- "libcodec2_hidl@1.1",
- "libcodec2_hidl@1.2",
- "libfdtrack",
- "libgui",
- "libgui_bufferqueue_static",
- "libmedia_codecserviceregistrant",
- "libstagefright_bufferqueue_helper_novndk",
- "libutils_test",
- "libutilscallstack",
- "mediaswcodec",
+ // depends on libart-unstripped and new module type llvm_prebuilt_build_tool
+ "check_cfi",
}
// Bazel prod-mode allowlist. Modules in this list are built by Bazel
@@ -1598,6 +1578,11 @@ var (
"test_com.android.neuralnetworks",
"libneuralnetworks",
"libneuralnetworks_static",
+ // M13: media.swcodec launch
+ "com.android.media.swcodec",
+ "test_com.android.media.swcodec",
+ "libstagefright_foundation",
+ "libcodec2_hidl@1.0",
}
// Staging-mode allowlist. Modules in this list are only built
@@ -1605,13 +1590,7 @@ var (
// which will soon be added to the prod allowlist.
// It is implicit that all modules in ProdMixedBuildsEnabledList will
// also be built - do not add them to this list.
- StagingMixedBuildsEnabledList = []string{
- // M13: media.swcodec launch
- "com.android.media.swcodec",
- "test_com.android.media.swcodec",
- "libstagefright_foundation",
- "libcodec2_hidl@1.0",
- }
+ StagingMixedBuildsEnabledList = []string{}
// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
ProdDclaMixedBuildsEnabledList = []string{
@@ -1619,14 +1598,13 @@ var (
"libc++",
"libcrypto",
"libcutils",
- }
-
- // These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
- StagingDclaMixedBuildsEnabledList = []string{
"libstagefright_flacdec",
"libutils",
}
+ // These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
+ StagingDclaMixedBuildsEnabledList = []string{}
+
// TODO(b/269342245): Enable the rest of the DCLA libs
// "libssl",
@@ -1638,4 +1616,14 @@ var (
"art_": DEFAULT_PRIORITIZED_WEIGHT,
"ndk_library": DEFAULT_PRIORITIZED_WEIGHT,
}
+
+ BazelSandwichTargets = []struct {
+ Label string
+ Host bool
+ }{
+ {
+ Label: "//build/bazel/examples/partitions:system_image",
+ Host: false,
+ },
+ }
)
diff --git a/android/api_levels.go b/android/api_levels.go
index 2391e6cc2..44c86403d 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -275,10 +275,6 @@ var FirstAndroidRelrVersion = uncheckedFinalApiLevel(28)
// relocations itself.
var FirstPackedRelocationsVersion = uncheckedFinalApiLevel(23)
-// The first API level that does not require NDK code to link
-// libandroid_support.
-var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21)
-
// LastWithoutModuleLibCoreSystemModules is the last API level where prebuilts/sdk does not contain
// a core-for-system-modules.jar for the module-lib API scope.
var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel(31)
diff --git a/android/arch.go b/android/arch.go
index 4b4691b3d..152016cd1 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1884,10 +1884,10 @@ func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]
buildTargets = filterMultilibTargets(targets, "lib64")
// Reverse the targets so that the first architecture can depend on the second
// architecture module in order to merge the outputs.
- reverseSliceInPlace(buildTargets)
+ ReverseSliceInPlace(buildTargets)
case "darwin_universal_common_first":
archTargets := filterMultilibTargets(targets, "lib64")
- reverseSliceInPlace(archTargets)
+ ReverseSliceInPlace(archTargets)
buildTargets = append(getCommonTargets(targets), archTargets...)
default:
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
diff --git a/android/bazel.go b/android/bazel.go
index 1bfbdec00..e4fada0fe 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -21,7 +21,9 @@ import (
"strings"
"android/soong/ui/metrics/bp2build_metrics_proto"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
"android/soong/android/allowlists"
@@ -152,8 +154,8 @@ type Bazelable interface {
HasHandcraftedLabel() bool
HandcraftedLabel() string
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
- ShouldConvertWithBp2build(ctx BazelConversionContext) bool
- shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool
+ ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool
+ shouldConvertWithBp2build(shouldConvertModuleContext, shouldConvertParams) bool
// ConvertWithBp2build either converts the module to a Bazel build target or
// declares the module as unconvertible (for logging and metrics).
@@ -255,7 +257,7 @@ func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module b
if b.ShouldConvertWithBp2build(ctx) {
return bp2buildModuleLabel(ctx, module)
}
- panic(fmt.Errorf("requested non-existent label for module ", module.Name()))
+ panic(fmt.Errorf("requested non-existent label for module %s", module.Name()))
}
type Bp2BuildConversionAllowlist struct {
@@ -426,18 +428,53 @@ func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus {
return ModuleIncompatibility
}
+func isGoModule(module blueprint.Module) bool {
+ if _, ok := module.(*bootstrap.GoPackage); ok {
+ return true
+ }
+ if _, ok := module.(*bootstrap.GoBinary); ok {
+ return true
+ }
+ return false
+}
+
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
+ // Special-case bootstrap_go_package and bootstrap_go_binary
+ // These do not implement Bazelable, but have been converted
+ if isGoModule(module) {
+ return true
+ }
b, ok := module.(Bazelable)
if !ok {
return false
}
- return b.shouldConvertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
+
+ return b.HasHandcraftedLabel() || b.shouldConvertWithBp2build(ctx, shouldConvertParams{
+ module: module,
+ moduleDir: ctx.OtherModuleDir(module),
+ moduleName: ctx.OtherModuleName(module),
+ moduleType: ctx.OtherModuleType(module),
+ })
+}
+
+type ShouldConvertWithBazelContext interface {
+ ModuleErrorf(format string, args ...interface{})
+ Module() Module
+ Config() Config
+ ModuleType() string
+ ModuleName() string
+ ModuleDir() string
}
// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
-func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx BazelConversionContext) bool {
- return b.shouldConvertWithBp2build(ctx, ctx.Module())
+func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool {
+ return b.shouldConvertWithBp2build(ctx, shouldConvertParams{
+ module: ctx.Module(),
+ moduleDir: ctx.ModuleDir(),
+ moduleName: ctx.ModuleName(),
+ moduleType: ctx.ModuleType(),
+ })
}
type bazelOtherModuleContext interface {
@@ -455,11 +492,24 @@ func isPlatformIncompatible(osType OsType, arch ArchType) bool {
arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported.
}
-func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool {
+type shouldConvertModuleContext interface {
+ ModuleErrorf(format string, args ...interface{})
+ Config() Config
+}
+
+type shouldConvertParams struct {
+ module blueprint.Module
+ moduleType string
+ moduleDir string
+ moduleName string
+}
+
+func (b *BazelModuleBase) shouldConvertWithBp2build(ctx shouldConvertModuleContext, p shouldConvertParams) bool {
if !b.bazelProps().Bazel_module.CanConvertToBazel {
return false
}
+ module := p.module
// In api_bp2build mode, all soong modules that can provide API contributions should be converted
// This is irrespective of its presence/absence in bp2build allowlists
if ctx.Config().BuildMode == ApiBp2build {
@@ -468,7 +518,7 @@ func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext,
}
propValue := b.bazelProperties.Bazel_module.Bp2build_available
- packagePath := moduleDirWithPossibleOverride(ctx, module)
+ packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir)
// Modules in unit tests which are enabled in the allowlist by type or name
// trigger this conditional because unit tests run under the "." package path
@@ -477,10 +527,10 @@ func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext,
return true
}
- moduleName := moduleNameWithPossibleOverride(ctx, module)
+ moduleName := moduleNameWithPossibleOverride(ctx, module, p.moduleName)
allowlist := ctx.Config().Bp2buildPackageConfig
moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
- moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[ctx.OtherModuleType(module)]
+ moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType]
allowlistConvert := moduleNameAllowed || moduleTypeAllowed
if moduleNameAllowed && moduleTypeAllowed {
ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert")
@@ -572,8 +622,21 @@ func bp2buildConversionMutator(ctx TopDownMutatorContext) {
ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
return
}
+ // There may be cases where the target is created by a macro rather than in a BUILD file, those
+ // should be captured as well.
+ if bModule.HasHandcraftedLabel() {
+ // Defer to the BUILD target. Generating an additional target would
+ // cause a BUILD file conflict.
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
+ return
+ }
// TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities.
- if !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
+ if !bModule.shouldConvertWithBp2build(ctx, shouldConvertParams{
+ module: ctx.Module(),
+ moduleDir: ctx.ModuleDir(),
+ moduleName: ctx.ModuleName(),
+ moduleType: ctx.ModuleType(),
+ }) {
ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
return
}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index d5ccfcad8..fda8a2251 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -16,10 +16,13 @@ package android
import (
"bytes"
+ "crypto/sha1"
+ "encoding/hex"
"fmt"
"os"
"path"
"path/filepath"
+ "regexp"
"runtime"
"sort"
"strings"
@@ -184,6 +187,8 @@ type BazelContext interface {
// Returns the depsets defined in Bazel's aquery response.
AqueryDepsets() []bazel.AqueryDepset
+
+ QueueBazelSandwichCqueryRequests(config Config) error
}
type bazelRunner interface {
@@ -262,6 +267,10 @@ func (m MockBazelContext) QueueBazelRequest(label string, requestType cqueryRequ
m.BazelRequests[key] = true
}
+func (m MockBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
+ panic("unimplemented")
+}
+
func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
result, ok := m.LabelToOutputFiles[label]
if !ok {
@@ -422,6 +431,10 @@ func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configK
panic("unimplemented")
}
+func (n noopBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
+ panic("unimplemented")
+}
+
func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
panic("unimplemented")
}
@@ -1040,6 +1053,64 @@ var (
allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd}
)
+func GetBazelSandwichCqueryRequests(config Config) ([]cqueryKey, error) {
+ result := make([]cqueryKey, 0, len(allowlists.BazelSandwichTargets))
+ labelRegex := regexp.MustCompile("^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$")
+ // Note that bazel "targets" are different from soong "targets", the bazel targets are
+ // synonymous with soong modules, and soong targets are a configuration a module is built in.
+ for _, target := range allowlists.BazelSandwichTargets {
+ match := labelRegex.FindStringSubmatch(target.Label)
+ if match == nil {
+ return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target.Label)
+ }
+ if _, err := os.Stat(absolutePath(match[1])); err != nil {
+ if os.IsNotExist(err) {
+ // Ignore bazel sandwich targets that don't exist.
+ continue
+ } else {
+ return nil, err
+ }
+ }
+
+ var soongTarget Target
+ if target.Host {
+ soongTarget = config.BuildOSTarget
+ } else {
+ soongTarget = config.AndroidCommonTarget
+ if soongTarget.Os.Class != Device {
+ // kernel-build-tools seems to set the AndroidCommonTarget to a linux host
+ // target for some reason, disable device builds in that case.
+ continue
+ }
+ }
+
+ result = append(result, cqueryKey{
+ label: target.Label,
+ requestType: cquery.GetOutputFiles,
+ configKey: configKey{
+ arch: soongTarget.Arch.String(),
+ osType: soongTarget.Os,
+ },
+ })
+ }
+ return result, nil
+}
+
+// QueueBazelSandwichCqueryRequests queues cquery requests for all the bazel labels in
+// bazel_sandwich_targets. These will later be given phony targets so that they can be built on the
+// command line.
+func (context *mixedBuildBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
+ requests, err := GetBazelSandwichCqueryRequests(config)
+ if err != nil {
+ return err
+ }
+ for _, request := range requests {
+ context.QueueBazelRequest(request.label, request.requestType, request.configKey)
+ }
+
+ return nil
+}
+
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx invokeBazelContext) error {
@@ -1222,7 +1293,11 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
ctx.AddNinjaFileDeps(file)
}
+ depsetHashToDepset := map[string]bazel.AqueryDepset{}
+
for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
+ depsetHashToDepset[depset.ContentHash] = depset
+
var outputs []Path
var orderOnlies []Path
for _, depsetDepHash := range depset.TransitiveDepSetHashes {
@@ -1249,6 +1324,11 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__")
bazelOutDir := path.Join(executionRoot, "bazel-out")
+ rel, err := filepath.Rel(ctx.Config().OutDir(), executionRoot)
+ if err != nil {
+ ctx.Errorf("%s", err.Error())
+ }
+ dotdotsToOutRoot := strings.Repeat("../", strings.Count(rel, "/")+1)
for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
// nil build statements are a valid case where we do not create an action because it is
// unnecessary or handled by other processing
@@ -1257,7 +1337,31 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
}
if len(buildStatement.Command) > 0 {
rule := NewRuleBuilder(pctx, ctx)
- createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx)
+ intermediateDir, intermediateDirHash := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
+ if buildStatement.ShouldRunInSbox {
+ // Create a rule to build the output inside a sandbox
+ // This will create two changes of working directory
+ // 1. From ANDROID_BUILD_TOP to sbox top
+ // 2. From sbox top to a a synthetic mixed build execution root relative to it
+ // Finally, the outputs will be copied to intermediateDir
+ rule.Sbox(intermediateDir,
+ PathForOutput(ctx, "mixed_build_sbox_intermediates", intermediateDirHash+".textproto")).
+ SandboxInputs().
+ // Since we will cd to mixed build execution root, set sbox's out subdir to empty
+ // Without this, we will try to copy from $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
+ SetSboxOutDirDirAsEmpty()
+
+ // Create another set of rules to copy files from the intermediate dir to mixed build execution root
+ for _, outputPath := range buildStatement.OutputPaths {
+ ctx.Build(pctx, BuildParams{
+ Rule: CpIfChanged,
+ Input: intermediateDir.Join(ctx, executionRoot, outputPath),
+ Output: PathForBazelOut(ctx, outputPath),
+ })
+ }
+ }
+ createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx, depsetHashToDepset, dotdotsToOutRoot)
+
desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
rule.Build(fmt.Sprintf("bazel %d", index), desc)
continue
@@ -1270,6 +1374,12 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
// because this would cause circular dependency. So, until we move aquery processing
// to the 'android' package, we need to handle special cases here.
switch buildStatement.Mnemonic {
+ case "RepoMappingManifest":
+ // It appears RepoMappingManifest files currently have
+ // non-deterministic content. Just emit empty files for
+ // now because they're unused.
+ out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
+ WriteFileRuleVerbatim(ctx, out, "")
case "FileWrite", "SourceSymlinkManifest":
out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
@@ -1296,12 +1406,45 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
}
}
+
+ // Create phony targets for all the bazel sandwich output files
+ requests, err := GetBazelSandwichCqueryRequests(ctx.Config())
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+ for _, request := range requests {
+ files, err := ctx.Config().BazelContext.GetOutputFiles(request.label, request.configKey)
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+ filesAsPaths := make([]Path, 0, len(files))
+ for _, file := range files {
+ filesAsPaths = append(filesAsPaths, PathForBazelOut(ctx, file))
+ }
+ ctx.Phony("bazel_sandwich", filesAsPaths...)
+ }
+ ctx.Phony("checkbuild", PathForPhony(ctx, "bazel_sandwich"))
+}
+
+// Returns a out dir path for a sandboxed mixed build action
+func intermediatePathForSboxMixedBuildAction(ctx PathContext, statement *bazel.BuildStatement) (OutputPath, string) {
+ // An artifact can be generated by a single buildstatement.
+ // Use the hash of the first artifact to create a unique path
+ uniqueDir := sha1.New()
+ uniqueDir.Write([]byte(statement.OutputPaths[0]))
+ uniqueDirHashString := hex.EncodeToString(uniqueDir.Sum(nil))
+ return PathForOutput(ctx, "mixed_build_sbox_intermediates", uniqueDirHashString), uniqueDirHashString
}
// Register bazel-owned build statements (obtained from the aquery invocation).
-func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext) {
+func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext, depsetHashToDepset map[string]bazel.AqueryDepset, dotdotsToOutRoot string) {
// executionRoot is the action cwd.
- cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
+ if buildStatement.ShouldRunInSbox {
+ // mkdir -p ensures that the directory exists when run via sbox
+ cmd.Text(fmt.Sprintf("mkdir -p '%s' && cd '%s' &&", executionRoot, executionRoot))
+ } else {
+ cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
+ }
// Remove old outputs, as some actions might not rerun if the outputs are detected.
if len(buildStatement.OutputPaths) > 0 {
@@ -1317,25 +1460,47 @@ func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement
cmd.Flag(pair.Key + "=" + pair.Value)
}
+ command := buildStatement.Command
+ command = strings.ReplaceAll(command, "{DOTDOTS_TO_OUTPUT_ROOT}", dotdotsToOutRoot)
+
// The actual Bazel action.
- if len(buildStatement.Command) > 16*1024 {
+ if len(command) > 16*1024 {
commandFile := PathForBazelOut(ctx, buildStatement.OutputPaths[0]+".sh")
- WriteFileRule(ctx, commandFile, buildStatement.Command)
+ WriteFileRule(ctx, commandFile, command)
cmd.Text("bash").Text(buildStatement.OutputPaths[0] + ".sh").Implicit(commandFile)
} else {
- cmd.Text(buildStatement.Command)
+ cmd.Text(command)
}
for _, outputPath := range buildStatement.OutputPaths {
- cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
+ if buildStatement.ShouldRunInSbox {
+ // The full path has three components that get joined together
+ // 1. intermediate output dir that `sbox` will place the artifacts at
+ // 2. mixed build execution root
+ // 3. artifact path returned by aquery
+ intermediateDir, _ := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
+ cmd.ImplicitOutput(intermediateDir.Join(ctx, executionRoot, outputPath))
+ } else {
+ cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
+ }
}
for _, inputPath := range buildStatement.InputPaths {
cmd.Implicit(PathForBazelOut(ctx, inputPath))
}
for _, inputDepsetHash := range buildStatement.InputDepsetHashes {
- otherDepsetName := bazelDepsetName(inputDepsetHash)
- cmd.Implicit(PathForPhony(ctx, otherDepsetName))
+ if buildStatement.ShouldRunInSbox {
+ // Bazel depsets are phony targets that are used to group files.
+ // We need to copy the grouped files into the sandbox
+ ds, _ := depsetHashToDepset[inputDepsetHash]
+ cmd.Implicits(PathsForBazelOut(ctx, ds.DirectArtifacts))
+ } else {
+ otherDepsetName := bazelDepsetName(inputDepsetHash)
+ cmd.Implicit(PathForPhony(ctx, otherDepsetName))
+ }
+ }
+ for _, implicitPath := range buildStatement.ImplicitDeps {
+ cmd.Implicit(PathForArbitraryOutput(ctx, implicitPath))
}
if depfile := buildStatement.Depfile; depfile != nil {
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 65cd5a836..9a3c8fc7c 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -181,13 +181,62 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
cmd := RuleBuilderCommand{}
ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
- createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx)
+ createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
t.Errorf("expected: [%s], actual: [%s]", expected, actual)
}
}
}
+func TestMixedBuildSandboxedAction(t *testing.T) {
+ input := `{
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_Id": 1,
+ "action_Key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_Ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
+}`
+ data, err := JsonToActionGraphContainer(input)
+ if err != nil {
+ t.Error(err)
+ }
+ bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
+
+ err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
+ if err != nil {
+ t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err)
+ }
+
+ statement := bazelContext.BuildStatementsToRegister()[0]
+ statement.ShouldRunInSbox = true
+
+ cmd := RuleBuilderCommand{}
+ ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
+ createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
+ // Assert that the output is generated in an intermediate directory
+ // fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one"
+ if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual {
+ t.Errorf("expected: [%s], actual: [%s]", expected, actual)
+ }
+
+ // Assert the actual command remains unchanged inside the sandbox
+ if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual {
+ t.Errorf("expected: [%s], actual: [%s]", expected, actual)
+ }
+}
+
func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
testConfig.productVariables.ClangCoverage = boolPtr(true)
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 872e908e8..02ae5ca20 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -88,6 +88,8 @@ type BazelConversionPathContext interface {
EarlyModulePathContext
BazelConversionContext
+ ModuleName() string
+ ModuleType() string
ModuleErrorf(fmt string, args ...interface{})
PropertyErrorf(property, fmt string, args ...interface{})
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
@@ -124,6 +126,7 @@ func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []str
labels.Includes = []bazel.Label{}
return labels
}
+ modules = FirstUniqueStrings(modules)
for _, module := range modules {
bpText := module
if m := SrcIsModule(module); m == "" {
@@ -179,7 +182,7 @@ func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) b
// paths, relative to the local module, or Bazel-labels (absolute if in a different package or
// relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the path_deps mutator.
+// will have already been handled by the pathdeps mutator.
func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
}
@@ -189,7 +192,7 @@ func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) baze
// references in paths, minus those in excludes, relative to the local module, or Bazel-labels
// (absolute if in a different package or relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the path_deps mutator.
+// will have already been handled by the pathdeps mutator.
func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
excluded := make([]string, 0, len(excludeLabels.Includes))
@@ -198,7 +201,7 @@ func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, exclu
}
labels := expandSrcsForBazel(ctx, paths, excluded)
labels.Excludes = excludeLabels.Includes
- labels = transformSubpackagePaths(ctx, labels)
+ labels = TransformSubpackagePaths(ctx.Config(), ctx.ModuleDir(), labels)
return labels
}
@@ -237,7 +240,7 @@ func isPackageBoundary(config Config, prefix string, components []string, compon
// if the "async_safe" directory is actually a package and not just a directory.
//
// In particular, paths that extend into packages are transformed into absolute labels beginning with //.
-func transformSubpackagePath(ctx BazelConversionPathContext, path bazel.Label) bazel.Label {
+func transformSubpackagePath(cfg Config, dir string, path bazel.Label) bazel.Label {
var newPath bazel.Label
// Don't transform OriginalModuleName
@@ -281,7 +284,7 @@ func transformSubpackagePath(ctx BazelConversionPathContext, path bazel.Label) b
for i := len(pathComponents) - 1; i >= 0; i-- {
pathComponent := pathComponents[i]
var sep string
- if !foundPackageBoundary && isPackageBoundary(ctx.Config(), ctx.ModuleDir(), pathComponents, i) {
+ if !foundPackageBoundary && isPackageBoundary(cfg, dir, pathComponents, i) {
sep = ":"
foundPackageBoundary = true
} else {
@@ -295,7 +298,7 @@ func transformSubpackagePath(ctx BazelConversionPathContext, path bazel.Label) b
}
if foundPackageBoundary {
// Ensure paths end up looking like //bionic/... instead of //./bionic/...
- moduleDir := ctx.ModuleDir()
+ moduleDir := dir
if strings.HasPrefix(moduleDir, ".") {
moduleDir = moduleDir[1:]
}
@@ -313,13 +316,13 @@ func transformSubpackagePath(ctx BazelConversionPathContext, path bazel.Label) b
// Transform paths to acknowledge package boundaries
// See transformSubpackagePath() for more information
-func transformSubpackagePaths(ctx BazelConversionPathContext, paths bazel.LabelList) bazel.LabelList {
+func TransformSubpackagePaths(cfg Config, dir string, paths bazel.LabelList) bazel.LabelList {
var newPaths bazel.LabelList
for _, include := range paths.Includes {
- newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(ctx, include))
+ newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(cfg, dir, include))
}
for _, exclude := range paths.Excludes {
- newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(ctx, exclude))
+ newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(cfg, dir, exclude))
}
return newPaths
}
@@ -355,7 +358,7 @@ func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []ba
//
// Properties passed as the paths or excludes argument must have been annotated with struct tag
// `android:"path"` so that dependencies on other modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
if paths == nil {
return bazel.LabelList{}
@@ -375,7 +378,13 @@ func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes
if m, tag := SrcIsModuleWithTag(p); m != "" {
l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel)
if l != nil && !InList(l.Label, expandedExcludes) {
- l.OriginalModuleName = fmt.Sprintf(":%s", m)
+ if strings.HasPrefix(m, "//") {
+ // this is a module in a soong namespace
+ // It appears as //<namespace>:<module_name> in srcs, and not ://<namespace>:<module_name>
+ l.OriginalModuleName = m
+ } else {
+ l.OriginalModuleName = fmt.Sprintf(":%s", m)
+ }
labels.Includes = append(labels.Includes, *l)
}
} else {
@@ -430,7 +439,7 @@ func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string,
func BazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
- if !convertedToBazel(ctx, module) {
+ if !convertedToBazel(ctx, module) || isGoModule(module) {
return bp2buildModuleLabel(ctx, module)
}
b, _ := module.(Bazelable)
@@ -458,8 +467,8 @@ func samePackage(label1, label2 string) bool {
}
func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) string {
- moduleName := moduleNameWithPossibleOverride(ctx, module)
- moduleDir := moduleDirWithPossibleOverride(ctx, module)
+ moduleName := moduleNameWithPossibleOverride(ctx, module, ctx.OtherModuleName(module))
+ moduleDir := moduleDirWithPossibleOverride(ctx, module, ctx.OtherModuleDir(module))
if moduleDir == Bp2BuildTopLevel {
moduleDir = ""
}
diff --git a/android/bazel_paths_test.go b/android/bazel_paths_test.go
index 450bf7674..75b77a36c 100644
--- a/android/bazel_paths_test.go
+++ b/android/bazel_paths_test.go
@@ -19,6 +19,7 @@ import (
"testing"
"android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
)
@@ -157,6 +158,14 @@ func (ctx *TestBazelConversionPathContext) ModuleDir() string {
return ctx.moduleDir
}
+func (ctx *TestBazelConversionPathContext) ModuleName() string {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) ModuleType() string {
+ panic("Unimplemented")
+}
+
func TestTransformSubpackagePath(t *testing.T) {
cfg := NullConfig("out", "out/soong")
cfg.fs = pathtools.MockFs(map[string][]byte{
@@ -175,7 +184,7 @@ func TestTransformSubpackagePath(t *testing.T) {
"./z/b.c": "z/b.c",
}
for in, out := range pairs {
- actual := transformSubpackagePath(ctx, bazel.Label{Label: in}).Label
+ actual := transformSubpackagePath(ctx.Config(), ctx.ModuleDir(), bazel.Label{Label: in}).Label
if actual != out {
t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
}
diff --git a/android/bazel_test.go b/android/bazel_test.go
index 13fd40849..194a6b359 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -373,7 +373,14 @@ func TestBp2BuildAllowlist(t *testing.T) {
allowlist: test.allowlist,
}
- shouldConvert := test.module.shouldConvertWithBp2build(bcc, test.module.TestModuleInfo)
+ shouldConvert := test.module.shouldConvertWithBp2build(bcc,
+ shouldConvertParams{
+ module: test.module.TestModuleInfo,
+ moduleDir: test.module.TestModuleInfo.Dir,
+ moduleType: test.module.TestModuleInfo.Typ,
+ moduleName: test.module.TestModuleInfo.ModuleName,
+ },
+ )
if test.shouldConvert != shouldConvert {
t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert)
}
diff --git a/android/config.go b/android/config.go
index fa439625d..3e7bb1426 100644
--- a/android/config.go
+++ b/android/config.go
@@ -18,7 +18,6 @@ package android
// product variables necessary for soong_build's operation.
import (
- "bytes"
"encoding/json"
"fmt"
"os"
@@ -171,6 +170,19 @@ func (c Config) RunningInsideUnitTest() bool {
return c.config.TestProductVariables != nil
}
+// DisableHiddenApiChecks returns true if hiddenapi checks have been disabled.
+// For 'eng' target variant hiddenapi checks are disabled by default for performance optimisation,
+// but can be enabled by setting environment variable ENABLE_HIDDENAPI_FLAGS=true.
+// For other target variants hiddenapi check are enabled by default but can be disabled by
+// setting environment variable UNSAFE_DISABLE_HIDDENAPI_FLAGS=true.
+// If both ENABLE_HIDDENAPI_FLAGS=true and UNSAFE_DISABLE_HIDDENAPI_FLAGS=true, then
+// ENABLE_HIDDENAPI_FLAGS=true will be triggered and hiddenapi checks will be considered enabled.
+func (c Config) DisableHiddenApiChecks() bool {
+ return !c.IsEnvTrue("ENABLE_HIDDENAPI_FLAGS") &&
+ (c.IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") ||
+ Bool(c.productVariables.Eng))
+}
+
// MaxPageSizeSupported returns the max page size supported by the device. This
// value will define the ELF segment alignment for binaries (executables and
// shared libraries).
@@ -178,6 +190,12 @@ func (c Config) MaxPageSizeSupported() string {
return String(c.config.productVariables.DeviceMaxPageSizeSupported)
}
+// PageSizeAgnostic returns true when AOSP is page size agnostic,
+// othersise it returns false.
+func (c Config) PageSizeAgnostic() bool {
+ return Bool(c.config.productVariables.DevicePageSizeAgnostic)
+}
+
// The release version passed to aconfig, derived from RELEASE_VERSION
func (c Config) ReleaseVersion() string {
return c.config.productVariables.ReleaseVersion
@@ -188,6 +206,12 @@ func (c Config) ReleaseAconfigValueSets() []string {
return c.config.productVariables.ReleaseAconfigValueSets
}
+// The flag default permission value passed to aconfig
+// derived from RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION
+func (c Config) ReleaseAconfigFlagDefaultPermission() string {
+ return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -202,10 +226,10 @@ type VendorConfig soongconfig.SoongConfig
// product configuration values are read from Kati-generated soong.variables.
type config struct {
// Options configurable with soong.variables
- productVariables productVariables
+ productVariables ProductVariables
// Only available on configs created by TestConfig
- TestProductVariables *productVariables
+ TestProductVariables *ProductVariables
// A specialized context object for Bazel/Soong mixed builds and migration
// purposes.
@@ -321,7 +345,7 @@ func loadConfig(config *config) error {
// loadFromConfigFile loads and decodes configuration options from a JSON file
// in the current working directory.
-func loadFromConfigFile(configurable *productVariables, filename string) error {
+func loadFromConfigFile(configurable *ProductVariables, filename string) error {
// Try to open the file
configFileReader, err := os.Open(filename)
defer configFileReader.Close()
@@ -373,7 +397,7 @@ func loadFromConfigFile(configurable *productVariables, filename string) error {
// atomically writes the config file in case two copies of soong_build are running simultaneously
// (for example, docs generation and ninja manifest generation)
-func saveToConfigFile(config *productVariables, filename string) error {
+func saveToConfigFile(config *ProductVariables, filename string) error {
data, err := json.MarshalIndent(&config, "", " ")
if err != nil {
return fmt.Errorf("cannot marshal config data: %s", err.Error())
@@ -402,65 +426,52 @@ func saveToConfigFile(config *productVariables, filename string) error {
return nil
}
-func saveToBazelConfigFile(config *productVariables, outDir string) error {
+type productVariableStarlarkRepresentation struct {
+ soongType string
+ selectable bool
+ archVariant bool
+}
+
+func saveToBazelConfigFile(config *ProductVariables, outDir string) error {
dir := filepath.Join(outDir, bazel.SoongInjectionDirName, "product_config")
err := createDirIfNonexistent(dir, os.ModePerm)
if err != nil {
return fmt.Errorf("Could not create dir %s: %s", dir, err)
}
- nonArchVariantProductVariables := []string{}
- archVariantProductVariables := []string{}
+ allProductVariablesType := reflect.TypeOf((*ProductVariables)(nil)).Elem()
+ productVariablesInfo := make(map[string]productVariableStarlarkRepresentation)
p := variableProperties{}
t := reflect.TypeOf(p.Product_variables)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
- nonArchVariantProductVariables = append(nonArchVariantProductVariables, strings.ToLower(f.Name))
- if proptools.HasTag(f, "android", "arch_variant") {
- archVariantProductVariables = append(archVariantProductVariables, strings.ToLower(f.Name))
+ archVariant := proptools.HasTag(f, "android", "arch_variant")
+ if mainProductVariablesStructField, ok := allProductVariablesType.FieldByName(f.Name); ok {
+ productVariablesInfo[f.Name] = productVariableStarlarkRepresentation{
+ soongType: stringRepresentationOfSimpleType(mainProductVariablesStructField.Type),
+ selectable: true,
+ archVariant: archVariant,
+ }
+ } else {
+ panic("Unknown variable " + f.Name)
}
}
- nonArchVariantProductVariablesJson := starlark_fmt.PrintStringList(nonArchVariantProductVariables, 0)
- if err != nil {
- return fmt.Errorf("cannot marshal product variable data: %s", err.Error())
- }
-
- archVariantProductVariablesJson := starlark_fmt.PrintStringList(archVariantProductVariables, 0)
- if err != nil {
- return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
- }
-
- configJson, err := json.MarshalIndent(&config, "", " ")
- if err != nil {
- return fmt.Errorf("cannot marshal config data: %s", err.Error())
- }
- // The backslashes need to be escaped because this text is going to be put
- // inside a Starlark string literal.
- configJson = bytes.ReplaceAll(configJson, []byte("\\"), []byte("\\\\"))
-
- bzl := []string{
- bazel.GeneratedBazelFileWarning,
- fmt.Sprintf(`_product_vars = json.decode("""%s""")`, configJson),
- fmt.Sprintf(`_product_var_constraints = %s`, nonArchVariantProductVariablesJson),
- fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
- "\n", `
-product_vars = _product_vars
-
-# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
-product_var_constraints = _product_var_constraints
-arch_variant_product_var_constraints = _arch_variant_product_var_constraints
-`,
- }
- err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variables.bzl"),
- []byte(strings.Join(bzl, "\n")), 0644)
- if err != nil {
- return fmt.Errorf("Could not write .bzl config file %s", err)
- }
err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
-product_var_constraints = %s
-arch_variant_product_var_constraints = %s
-`, nonArchVariantProductVariablesJson, archVariantProductVariablesJson)), 0644)
+# product_var_constant_info is a map of product variables to information about them. The fields are:
+# - soongType: The type of the product variable as it appears in soong's ProductVariables struct.
+# examples are string, bool, int, *bool, *string, []string, etc. This may be an overly
+# conservative estimation of the type, for example a *bool could oftentimes just be a
+# bool that defaults to false.
+# - selectable: if this product variable can be selected on in Android.bp/build files. This means
+# it's listed in the "variableProperties" soong struct. Currently all variables in
+# this list are selectable because we only need the selectable ones at the moment,
+# but the list may be expanded later.
+# - archVariant: If the variable is tagged as arch variant in the "variableProperties" struct.
+product_var_constant_info = %s
+product_var_constraints = [k for k, v in product_var_constant_info.items() if v.selectable]
+arch_variant_product_var_constraints = [k for k, v in product_var_constant_info.items() if v.selectable and v.archVariant]
+`, starlark_fmt.PrintAny(productVariablesInfo, 0))), 0644)
if err != nil {
return fmt.Errorf("Could not write .bzl config file %s", err)
}
@@ -473,6 +484,23 @@ arch_variant_product_var_constraints = %s
return nil
}
+func stringRepresentationOfSimpleType(ty reflect.Type) string {
+ switch ty.Kind() {
+ case reflect.String:
+ return "string"
+ case reflect.Bool:
+ return "bool"
+ case reflect.Int:
+ return "int"
+ case reflect.Slice:
+ return "[]" + stringRepresentationOfSimpleType(ty.Elem())
+ case reflect.Pointer:
+ return "*" + stringRepresentationOfSimpleType(ty.Elem())
+ default:
+ panic("unimplemented type: " + ty.Kind().String())
+ }
+}
+
// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
// use the android package.
func NullConfig(outDir, soongOutDir string) Config {
@@ -1355,6 +1383,10 @@ func (c *config) BazelModulesForceEnabledByFlag() map[string]struct{} {
return c.bazelForceEnabledModules
}
+func (c *config) IsVndkDeprecated() bool {
+ return !Bool(c.productVariables.KeepVndk)
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -1932,6 +1964,10 @@ func (c *deviceConfig) RequiresInsecureExecmemForSwiftshader() bool {
return c.config.productVariables.RequiresInsecureExecmemForSwiftshader
}
+func (c *deviceConfig) Release_aidl_use_unfrozen() bool {
+ return Bool(c.config.productVariables.Release_aidl_use_unfrozen)
+}
+
func (c *config) SelinuxIgnoreNeverallows() bool {
return c.productVariables.SelinuxIgnoreNeverallows
}
diff --git a/android/config_test.go b/android/config_test.go
index 9df5288a1..7d327a27e 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -75,7 +75,7 @@ Did you mean to use an annotation of ",omitempty"?
// run validateConfigAnnotations against each type that might have json annotations
func TestProductConfigAnnotations(t *testing.T) {
- err := validateConfigAnnotations(&productVariables{})
+ err := validateConfigAnnotations(&ProductVariables{})
if err != nil {
t.Errorf(err.Error())
}
@@ -88,7 +88,7 @@ func TestMissingVendorConfig(t *testing.T) {
}
}
-func verifyProductVariableMarshaling(t *testing.T, v productVariables) {
+func verifyProductVariableMarshaling(t *testing.T, v ProductVariables) {
dir := t.TempDir()
path := filepath.Join(dir, "test.variables")
err := saveToConfigFile(&v, path)
@@ -96,20 +96,20 @@ func verifyProductVariableMarshaling(t *testing.T, v productVariables) {
t.Errorf("Couldn't save default product config: %q", err)
}
- var v2 productVariables
+ 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 := ProductVariables{}
v.SetDefaultConfig()
verifyProductVariableMarshaling(t, v)
}
func TestBootJarsMarshaling(t *testing.T) {
- v := productVariables{}
+ v := ProductVariables{}
v.SetDefaultConfig()
v.BootJars = ConfiguredJarList{
apexes: []string{"apex"},
diff --git a/android/configured_jars.go b/android/configured_jars.go
index 53fef052a..c7b808f3d 100644
--- a/android/configured_jars.go
+++ b/android/configured_jars.go
@@ -178,7 +178,7 @@ func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
paths := make(WritablePaths, l.Len())
for i, jar := range l.jars {
- paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
+ paths[i] = dir.Join(ctx, ModuleStem(ctx.Config(), l.Apex(i), jar)+".jar")
}
return paths
}
@@ -187,8 +187,8 @@ func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) Writable
// prefix.
func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
paths := map[string]WritablePath{}
- for _, jar := range l.jars {
- paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
+ for i, jar := range l.jars {
+ paths[jar] = dir.Join(ctx, ModuleStem(ctx.Config(), l.Apex(i), jar)+".jar")
}
return paths
}
@@ -228,24 +228,32 @@ func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
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
-// module before any other mutators are run.
-func ModuleStem(module string) string {
- if module == "framework-minus-apex" {
- return "framework"
+func OverrideConfiguredJarLocationFor(cfg Config, apex string, jar string) (newApex string, newJar string) {
+ for _, entry := range cfg.productVariables.ConfiguredJarLocationOverrides {
+ tuple := strings.Split(entry, ":")
+ if len(tuple) != 4 {
+ panic("malformed configured jar location override '%s', expected format: <old_apex>:<old_jar>:<new_apex>:<new_jar>")
+ }
+ if apex == tuple[0] && jar == tuple[1] {
+ return tuple[2], tuple[3]
+ }
}
- return module
+ return apex, jar
+}
+
+// ModuleStem returns the overridden jar name.
+func ModuleStem(cfg Config, apex string, jar string) string {
+ _, newJar := OverrideConfiguredJarLocationFor(cfg, apex, jar)
+ return newJar
}
// DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
// based on the operating system.
func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
paths := make([]string, l.Len())
- for i, jar := range l.jars {
- apex := l.apexes[i]
- name := ModuleStem(jar) + ".jar"
+ for i := 0; i < l.Len(); i++ {
+ apex, jar := OverrideConfiguredJarLocationFor(cfg, l.Apex(i), l.Jar(i))
+ name := jar + ".jar"
var subdir string
if apex == "platform" {
@@ -311,4 +319,9 @@ func EmptyConfiguredJarList() ConfiguredJarList {
return ConfiguredJarList{}
}
+// IsConfiguredJarForPlatform returns true if the given apex name is a special name for the platform.
+func IsConfiguredJarForPlatform(apex string) bool {
+ return apex == "platform" || apex == "system_ext"
+}
+
var earlyBootJarsKey = NewOnceKey("earlyBootJars")
diff --git a/android/configured_jars_test.go b/android/configured_jars_test.go
new file mode 100644
index 000000000..4b586e4d7
--- /dev/null
+++ b/android/configured_jars_test.go
@@ -0,0 +1,46 @@
+// 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 android
+
+import (
+ "testing"
+)
+
+func TestOverrideConfiguredJarLocationFor(t *testing.T) {
+ cfg := NullConfig("", "")
+
+ cfg.productVariables = ProductVariables{
+ ConfiguredJarLocationOverrides: []string{
+ "platform:libfoo-old:com.android.foo:libfoo-new",
+ "com.android.bar:libbar-old:platform:libbar-new",
+ },
+ }
+
+ apex, jar := OverrideConfiguredJarLocationFor(cfg, "platform", "libfoo-old")
+ AssertStringEquals(t, "", "com.android.foo", apex)
+ AssertStringEquals(t, "", "libfoo-new", jar)
+
+ apex, jar = OverrideConfiguredJarLocationFor(cfg, "platform", "libbar-old")
+ AssertStringEquals(t, "", "platform", apex)
+ AssertStringEquals(t, "", "libbar-old", jar)
+
+ apex, jar = OverrideConfiguredJarLocationFor(cfg, "com.android.bar", "libbar-old")
+ AssertStringEquals(t, "", "platform", apex)
+ AssertStringEquals(t, "", "libbar-new", jar)
+
+ apex, jar = OverrideConfiguredJarLocationFor(cfg, "platform", "libbar-old")
+ AssertStringEquals(t, "", "platform", apex)
+ AssertStringEquals(t, "", "libbar-old", jar)
+}
diff --git a/android/depset_generic.go b/android/depset_generic.go
index 4f31b8697..45c193715 100644
--- a/android/depset_generic.go
+++ b/android/depset_generic.go
@@ -79,8 +79,8 @@ func NewDepSet[T depSettableType](order DepSetOrder, direct []T, transitive []*D
if order == TOPOLOGICAL {
// TOPOLOGICAL is implemented as a postorder traversal followed by reversing the output.
// Pre-reverse the inputs here so their order is maintained in the output.
- directCopy = reverseSlice(direct)
- transitiveCopy = reverseSlice(transitive)
+ directCopy = ReverseSlice(direct)
+ transitiveCopy = ReverseSlice(transitive)
} else {
directCopy = append([]T(nil), direct...)
transitiveCopy = append([]*DepSet[T](nil), transitive...)
@@ -184,7 +184,7 @@ func (d *DepSet[T]) ToList() []T {
})
list = firstUniqueInPlace(list)
if d.reverse {
- reverseSliceInPlace(list)
+ ReverseSliceInPlace(list)
}
return list
}
diff --git a/android/filegroup.go b/android/filegroup.go
index 3b866550d..6cc9232b6 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -24,6 +24,7 @@ import (
"android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -141,8 +142,14 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
attrs)
} else {
if fg.ShouldConvertToProtoLibrary(ctx) {
+ pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), bazel.MakeLabelList(srcs.Value.Includes))
+ if len(pkgToSrcs) > 1 {
+ ctx.ModuleErrorf("TODO: Add bp2build support for multiple package .protosrcs in filegroup")
+ return
+ }
+ pkg := SortedKeys(pkgToSrcs)[0]
attrs := &ProtoAttrs{
- Srcs: srcs,
+ Srcs: bazel.MakeLabelListAttribute(pkgToSrcs[pkg]),
Strip_import_prefix: fg.properties.Path,
}
@@ -151,13 +158,39 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
// TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
"manual",
}
+ if pkg != ctx.ModuleDir() {
+ // Since we are creating the proto_library in a subpackage, create an import_prefix relative to the current package
+ if rel, err := filepath.Rel(ctx.ModuleDir(), pkg); err != nil {
+ ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
+ } else if rel != "." {
+ attrs.Import_prefix = &rel
+ // Strip the package prefix
+ attrs.Strip_import_prefix = proptools.StringPtr("")
+ }
+ }
+
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
CommonAttributes{
- Name: fg.Name() + convertedProtoLibrarySuffix,
+ Name: fg.Name() + "_proto",
+ Dir: proptools.StringPtr(pkg),
Tags: bazel.MakeStringListAttribute(tags),
},
attrs)
+
+ // Create an alias in the current dir. The actual target might exist in a different package, but rdeps
+ // can reliabily use this alias
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{Rule_class: "alias"},
+ CommonAttributes{
+ Name: fg.Name() + convertedProtoLibrarySuffix,
+ // TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
+ Tags: bazel.MakeStringListAttribute(tags),
+ },
+ &bazelAliasAttributes{
+ Actual: bazel.MakeLabelAttribute("//" + pkg + ":" + fg.Name() + "_proto"),
+ },
+ )
}
// TODO(b/242847534): Still convert to a filegroup because other unconverted
diff --git a/android/fixture.go b/android/fixture.go
index dbc3bc5e0..6660afd65 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -369,7 +369,7 @@ func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
// Allow access to the product variables when preparing the fixture.
type FixtureProductVariables struct {
- *productVariables
+ *ProductVariables
}
// Modify product variables.
diff --git a/android/module.go b/android/module.go
index 384776a65..19502bae8 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1021,6 +1021,11 @@ type CommonAttributes struct {
Applicable_licenses bazel.LabelListAttribute
Testonly *bool
+
+ // Dir is neither a Soong nor Bazel target attribute
+ // If set, the bazel target will be created in this directory
+ // If unset, the bazel target will default to be created in the directory of the visited soong module
+ Dir *string
}
// constraintAttributes represents Bazel attributes pertaining to build constraints,
@@ -1373,15 +1378,15 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator
}
}
- productConfigEnabledLabels := []bazel.Label{}
+ productConfigEnabledAttribute := bazel.LabelListAttribute{}
// TODO(b/234497586): Soong config variables and product variables have different overriding behavior, we
// should handle it correctly
if !proptools.BoolDefault(enabledProperty.Value, true) && !neitherHostNorDevice {
// If the module is not enabled by default, then we can check if a
// product variable enables it
- productConfigEnabledLabels = productVariableConfigEnableLabels(ctx)
+ productConfigEnabledAttribute = productVariableConfigEnableAttribute(ctx)
- if len(productConfigEnabledLabels) > 0 {
+ if len(productConfigEnabledAttribute.ConfigurableValues) > 0 {
// In this case, an existing product variable configuration overrides any
// module-level `enable: false` definition
newValue := true
@@ -1389,10 +1394,6 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator
}
}
- productConfigEnabledAttribute := bazel.MakeLabelListAttribute(bazel.LabelList{
- productConfigEnabledLabels, nil,
- })
-
platformEnabledAttribute, err := enabledProperty.ToLabelListAttribute(
bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil},
bazel.LabelList{[]bazel.Label{}, nil})
@@ -1423,31 +1424,35 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator
// Check product variables for `enabled: true` flag override.
// Returns a list of the constraint_value targets who enable this override.
-func productVariableConfigEnableLabels(ctx *topDownMutatorContext) []bazel.Label {
+func productVariableConfigEnableAttribute(ctx *topDownMutatorContext) bazel.LabelListAttribute {
+ result := bazel.LabelListAttribute{}
productVariableProps := ProductVariableProperties(ctx, ctx.Module())
- productConfigEnablingTargets := []bazel.Label{}
- const propName = "Enabled"
- if productConfigProps, exists := productVariableProps[propName]; exists {
+ if productConfigProps, exists := productVariableProps["Enabled"]; exists {
for productConfigProp, prop := range productConfigProps {
flag, ok := prop.(*bool)
if !ok {
- ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
+ ctx.ModuleErrorf("Could not convert product variable enabled property")
}
- if *flag {
+ if flag == nil {
+ // soong config var is not used to set `enabled`. nothing to do.
+ continue
+ } else if *flag {
axis := productConfigProp.ConfigurationAxis()
- targetLabel := axis.SelectKey(productConfigProp.SelectKey())
- productConfigEnablingTargets = append(productConfigEnablingTargets, bazel.Label{
- Label: targetLabel,
- })
+ result.SetSelectValue(axis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{{Label: "@platforms//:incompatible"}}))
+ result.SetSelectValue(axis, productConfigProp.SelectKey(), bazel.LabelList{Includes: []bazel.Label{}})
+ } else if scp, isSoongConfigProperty := productConfigProp.(SoongConfigProperty); isSoongConfigProperty && scp.value == bazel.ConditionsDefaultConfigKey {
+ // productVariableConfigEnableAttribute runs only if `enabled: false` is set at the top-level outside soong_config_variables
+ // conditions_default { enabled: false} is a no-op in this case
+ continue
} else {
// TODO(b/210546943): handle negative case where `enabled: false`
- ctx.ModuleErrorf("`enabled: false` is not currently supported for configuration variables. See b/210546943", proptools.PropertyNameForField(propName))
+ ctx.ModuleErrorf("`enabled: false` is not currently supported for configuration variables. See b/210546943")
}
}
}
- return productConfigEnablingTargets
+ return result
}
// A ModuleBase object contains the properties that are common to all Android
@@ -4029,43 +4034,26 @@ type XsdConfigBp2buildTargets interface {
JavaBp2buildTargetName() string
}
-// PartitionXsdSrcs partitions srcs into xsd_config modules and others
-// Since xsd_config are soong modules, we cannot use file extension for partitioning
-func PartitionXsdSrcs(ctx BazelConversionPathContext, srcs []string) ([]string, []string) {
- //isXsd returns true if src is a soong module of type xsd_config
- isXsd := func(src string) bool {
- mod, exists := ctx.ModuleFromName(src)
+// XsdModuleToTargetName is a function that takes an XsdConfigBp2buildTarget
+type XsdModuleToTargetName func(xsd XsdConfigBp2buildTargets) string
+
+// XsdLabelMapper returns a bazel.LabelMapper for partitioning XSD sources/headers given an
+// XsdModuleToTargetName function.
+func XsdLabelMapper(targetName XsdModuleToTargetName) bazel.LabelMapper {
+ return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+ mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
if !exists {
- return false
+ return label.Label, false
}
- _, _isXsd := mod.(XsdConfigBp2buildTargets)
- return _isXsd
- }
- nonXsd := []string{}
- xsd := []string{}
-
- for _, src := range srcs {
- if isXsd(src) {
- xsd = append(xsd, src)
- } else {
- nonXsd = append(nonXsd, src)
+ xsdMod, isXsd := mod.(XsdConfigBp2buildTargets)
+ if !isXsd {
+ return label.Label, false
}
- }
-
- return nonXsd, xsd
-}
-// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-{cpp|java}
-// The new target name is provided by the `targetName` callback function
-func XsdConfigBp2buildTarget(ctx BazelConversionPathContext, mod blueprint.Module, targetName func(xsd XsdConfigBp2buildTargets) string) string {
- xsd, isXsd := mod.(XsdConfigBp2buildTargets)
- if !isXsd {
- ctx.ModuleErrorf("xsdConfigJavaTarget called on %v, which is not an xsd_config", mod)
+ // Remove the base module name
+ ret := strings.TrimSuffix(label.Label, mod.Name())
+ // Append the language specific target name
+ ret += targetName(xsdMod)
+ return ret, true
}
- ret := BazelModuleLabel(ctx, mod)
- // Remove the base module name
- ret = strings.TrimSuffix(ret, mod.Name())
- // Append the language specific target name
- ret += targetName(xsd)
- return ret
}
diff --git a/android/mutator.go b/android/mutator.go
index 2ec051e59..6bcac93c1 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -17,6 +17,7 @@ package android
import (
"android/soong/bazel"
"android/soong/ui/metrics/bp2build_metrics_proto"
+ "path/filepath"
"github.com/google/blueprint"
)
@@ -757,6 +758,27 @@ func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
mod.base().addBp2buildInfo(info)
}
+// Returns the directory in which the bazel target will be generated
+// If ca.Dir is not nil, use that
+// Otherwise default to the directory of the soong module
+func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) string {
+ dir := t.OtherModuleDir(t.Module())
+ if ca.Dir != nil {
+ dir = *ca.Dir
+ // Restrict its use to dirs that contain an Android.bp file.
+ // There are several places in bp2build where we use the existence of Android.bp/BUILD on the filesystem
+ // to curate a compatible label for src files (e.g. headers for cc).
+ // If we arbritrarily create BUILD files, then it might render those curated labels incompatible.
+ if exists, _, _ := t.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
+ t.ModuleErrorf("Cannot use ca.Dir to create a BazelTarget in dir: %v since it does not contain an Android.bp file", dir)
+ }
+
+ // Set ca.Dir to nil so that it does not get emitted to the BUILD files
+ ca.Dir = nil
+ }
+ return dir
+}
+
func (t *topDownMutatorContext) CreateBazelConfigSetting(
csa bazel.ConfigSettingAttributes,
ca CommonAttributes,
@@ -851,7 +873,7 @@ func (t *topDownMutatorContext) createBazelTargetModule(
constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
mod := t.Module()
info := bp2buildInfo{
- Dir: t.OtherModuleDir(mod),
+ Dir: dirForBazelTargetGeneration(t, &commonAttrs),
BazelProps: bazelProps,
CommonAttrs: commonAttrs,
ConstraintAttrs: constraintAttributes,
diff --git a/android/override_module.go b/android/override_module.go
index a4b7431f6..9e0de6fd0 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -353,26 +353,26 @@ func replaceDepsOnOverridingModuleMutator(ctx BottomUpMutatorContext) {
// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
// or if this variant is not overridden.
func ModuleNameWithPossibleOverride(ctx BazelConversionContext) string {
- return moduleNameWithPossibleOverride(ctx, ctx.Module())
+ return moduleNameWithPossibleOverride(ctx, ctx.Module(), ctx.OtherModuleName(ctx.Module()))
}
-func moduleNameWithPossibleOverride(ctx bazelOtherModuleContext, module blueprint.Module) string {
+func moduleNameWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, name string) string {
if overridable, ok := module.(OverridableModule); ok {
if o := overridable.GetOverriddenBy(); o != "" {
return o
}
}
- return ctx.OtherModuleName(module)
+ return name
}
// moduleDirWithPossibleOverride returns the dir of the OverrideModule that overrides the current
// variant of the given OverridableModule, or ctx.OtherModuleName() if the module is not an
// OverridableModule or if the variant is not overridden.
-func moduleDirWithPossibleOverride(ctx bazelOtherModuleContext, module blueprint.Module) string {
+func moduleDirWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, dir string) string {
if overridable, ok := module.(OverridableModule); ok {
if o := overridable.GetOverriddenByModuleDir(); o != "" {
return o
}
}
- return ctx.OtherModuleDir(module)
+ return dir
}
diff --git a/android/paths.go b/android/paths.go
index fda4d2f46..325a953c4 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -396,7 +396,7 @@ func ExistentPathsForSources(ctx PathGlobContext, paths []string) Paths {
//
// Properties passed as the paths argument must have been annotated with struct tag
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
// If a requested module is not found as a dependency:
// - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
// missing dependencies
@@ -425,7 +425,7 @@ type SourceInput struct {
// excluding the items (similarly resolved
// Properties passed as the paths argument must have been annotated with struct tag
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
// If a requested module is not found as a dependency:
// - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having
// missing dependencies
@@ -560,7 +560,7 @@ func GetModuleFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string)
// and a list of the module names of missing module dependencies are returned as the second return.
// Properties passed as the paths argument must have been annotated with struct tag
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
-// path_deps mutator.
+// pathdeps mutator.
func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) (Paths, []string) {
return PathsAndMissingDepsRelativeToModuleSourceDir(SourceInput{
Context: ctx,
@@ -1029,16 +1029,16 @@ func (p basePath) withRel(rel string) basePath {
return p
}
+func (p basePath) RelativeToTop() Path {
+ ensureTestOnly()
+ return p
+}
+
// SourcePath is a Path representing a file path rooted from SrcDir
type SourcePath struct {
basePath
}
-func (p SourcePath) RelativeToTop() Path {
- ensureTestOnly()
- return p
-}
-
var _ Path = SourcePath{}
func (p SourcePath) withRel(rel string) SourcePath {
@@ -1126,6 +1126,16 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
return path
}
+// PathForArbitraryOutput creates a path for the given components. Unlike PathForOutput,
+// the path is relative to the root of the output folder, not the out/soong folder.
+func PathForArbitraryOutput(ctx PathContext, pathComponents ...string) Path {
+ p, err := validatePath(pathComponents...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+ return basePath{path: filepath.Join(ctx.Config().OutDir(), p)}
+}
+
// MaybeExistentPathForSource joins the provided path components and validates that the result
// neither escapes the source dir nor is in the out dir.
// It does not validate whether the path exists.
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index e5edf9129..aeae20f48 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -102,6 +102,10 @@ var _ HostToolProvider = &prebuiltBuildTool{}
// prebuilt_build_tool is to declare prebuilts to be used during the build, particularly for use
// in genrules with the "tools" property.
func prebuiltBuildToolFactory() Module {
+ return NewPrebuiltBuildTool()
+}
+
+func NewPrebuiltBuildTool() Module {
module := &prebuiltBuildTool{}
module.AddProperties(&module.properties)
InitSingleSourcePrebuiltModule(module, &module.properties, "Src")
diff --git a/android/proto.go b/android/proto.go
index cebbd59cd..b21efd640 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -15,6 +15,7 @@
package android
import (
+ "path/filepath"
"strings"
"android/soong/bazel"
@@ -156,12 +157,12 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths,
// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
type Bp2buildProtoInfo struct {
Type *string
- Name string
Proto_libs bazel.LabelList
}
type ProtoAttrs struct {
Srcs bazel.LabelListAttribute
+ Import_prefix *string
Strip_import_prefix *string
Deps bazel.LabelListAttribute
}
@@ -172,6 +173,35 @@ var includeDirsToProtoDeps = map[string]string{
"external/protobuf/src": "//external/protobuf:libprotobuf-proto",
}
+// Partitions srcs by the pkg it is in
+// srcs has been created using `TransformSubpackagePaths`
+// This function uses existence of Android.bp/BUILD files to create a label that is compatible with the package structure of bp2build workspace
+func partitionSrcsByPackage(currentDir string, srcs bazel.LabelList) map[string]bazel.LabelList {
+ getPackageFromLabel := func(label string) string {
+ // Remove any preceding //
+ label = strings.TrimPrefix(label, "//")
+ split := strings.Split(label, ":")
+ if len(split) == 1 {
+ // e.g. foo.proto
+ return currentDir
+ } else if split[0] == "" {
+ // e.g. :foo.proto
+ return currentDir
+ } else {
+ return split[0]
+ }
+ }
+
+ pkgToSrcs := map[string]bazel.LabelList{}
+ for _, src := range srcs.Includes {
+ pkg := getPackageFromLabel(src.Label)
+ list := pkgToSrcs[pkg]
+ list.Add(&src)
+ pkgToSrcs[pkg] = list
+ }
+ return pkgToSrcs
+}
+
// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
// information necessary for language-specific handling.
func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
@@ -197,54 +227,87 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz
}
}
- info.Name = m.Name() + "_proto"
+ name := m.Name() + "_proto"
- if len(directProtoSrcs.Includes) > 0 {
- attrs := ProtoAttrs{
- Srcs: bazel.MakeLabelListAttribute(directProtoSrcs),
- }
- attrs.Deps.Append(bazel.MakeLabelListAttribute(protoLibraries))
-
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
- for _, rawProps := range configToProps {
- var props *ProtoProperties
- var ok bool
- if props, ok = rawProps.(*ProtoProperties); !ok {
- ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
- }
- if axis == bazel.NoConfigAxis {
- info.Type = props.Proto.Type
+ depsFromFilegroup := protoLibraries
+ var canonicalPathFromRoot bool
- if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
- // an empty string indicates to strips the package path
- path := ""
- attrs.Strip_import_prefix = &path
+ if len(directProtoSrcs.Includes) > 0 {
+ pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), directProtoSrcs)
+ for _, pkg := range SortedStringKeys(pkgToSrcs) {
+ srcs := pkgToSrcs[pkg]
+ attrs := ProtoAttrs{
+ Srcs: bazel.MakeLabelListAttribute(srcs),
+ }
+ attrs.Deps.Append(bazel.MakeLabelListAttribute(depsFromFilegroup))
+
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
+ for _, rawProps := range configToProps {
+ var props *ProtoProperties
+ var ok bool
+ if props, ok = rawProps.(*ProtoProperties); !ok {
+ ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
}
+ if axis == bazel.NoConfigAxis {
+ info.Type = props.Proto.Type
+
+ canonicalPathFromRoot = proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault)
+ if !canonicalPathFromRoot {
+ // an empty string indicates to strips the package path
+ path := ""
+ attrs.Strip_import_prefix = &path
+ }
- for _, dir := range props.Proto.Include_dirs {
- if dep, ok := includeDirsToProtoDeps[dir]; ok {
- attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
- } else {
- ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir)
+ for _, dir := range props.Proto.Include_dirs {
+ if dep, ok := includeDirsToProtoDeps[dir]; ok {
+ attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
+ } else {
+ ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir)
+ }
}
+ } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
+ ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
}
- } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
- ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
}
}
- }
- tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
+ tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{Name: info.Name, Tags: tags},
- &attrs,
- )
+ moduleDir := ctx.ModuleDir()
+ if !canonicalPathFromRoot {
+ // Since we are creating the proto_library in a subpackage, set the import_prefix relative to the current package
+ if rel, err := filepath.Rel(moduleDir, pkg); err != nil {
+ ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
+ } else if rel != "." {
+ attrs.Import_prefix = &rel
+ }
+ }
- protoLibraries.Add(&bazel.Label{
- Label: ":" + info.Name,
- })
+ // TODO - b/246997908: Handle potential orphaned proto_library targets
+ // To create proto_library targets in the same package, we split the .proto files
+ // This means that if a proto_library in a subpackage imports another proto_library from the parent package
+ // (or a different subpackage), it will not find it.
+ // The CcProtoGen action itself runs fine because we construct the correct ProtoInfo,
+ // but the FileDescriptorSet of each proto_library might not be compile-able
+ if pkg != ctx.ModuleDir() {
+ tags.Append(bazel.MakeStringListAttribute([]string{"manual"}))
+ }
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+ CommonAttributes{Name: name, Dir: proptools.StringPtr(pkg), Tags: tags},
+ &attrs,
+ )
+
+ l := ""
+ if pkg == moduleDir { // same package that the original module lives in
+ l = ":" + name
+ } else {
+ l = "//" + pkg + ":" + name
+ }
+ protoLibraries.Add(&bazel.Label{
+ Label: l,
+ })
+ }
}
info.Proto_libs = protoLibraries
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 155fbdf71..777c1cfc3 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -53,6 +53,7 @@ type RuleBuilder struct {
remoteable RemoteRuleSupports
rbeParams *remoteexec.REParams
outDir WritablePath
+ sboxOutSubDir string
sboxTools bool
sboxInputs bool
sboxManifestPath WritablePath
@@ -65,9 +66,18 @@ func NewRuleBuilder(pctx PackageContext, ctx BuilderContext) *RuleBuilder {
pctx: pctx,
ctx: ctx,
temporariesSet: make(map[WritablePath]bool),
+ sboxOutSubDir: sboxOutSubDir,
}
}
+// SetSboxOutDirDirAsEmpty sets the out subdirectory to an empty string
+// This is useful for sandboxing actions that change the execution root to a path in out/ (e.g mixed builds)
+// For such actions, SetSboxOutDirDirAsEmpty ensures that the path does not become $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
+func (rb *RuleBuilder) SetSboxOutDirDirAsEmpty() *RuleBuilder {
+ rb.sboxOutSubDir = ""
+ return rb
+}
+
// RuleBuilderInstall is a tuple of install from and to locations.
type RuleBuilderInstall struct {
From Path
@@ -582,12 +592,10 @@ func (r *RuleBuilder) Build(name string, desc string) {
// 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))
- for i, output := range outputs {
+ for _, output := range outputs {
rel := Rel(r.ctx, r.outDir.String(), output.String())
- sboxOutputs[i] = filepath.Join(sboxOutDir, rel)
command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{
- From: proto.String(filepath.Join(sboxOutSubDir, rel)),
+ From: proto.String(filepath.Join(r.sboxOutSubDir, rel)),
To: proto.String(output.String()),
})
}
diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go
index ea99c4d62..30bd002c2 100644
--- a/android/sdk_version_test.go
+++ b/android/sdk_version_test.go
@@ -75,7 +75,7 @@ func TestSdkSpecFrom(t *testing.T) {
config := NullConfig("", "")
- config.productVariables = productVariables{
+ config.productVariables = ProductVariables{
Platform_sdk_version: intPtr(31),
Platform_sdk_codename: stringPtr("Tiramisu"),
Platform_version_active_codenames: []string{"Tiramisu"},
diff --git a/android/test_config.go b/android/test_config.go
index 28d9ec403..2a59d9228 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -35,7 +35,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
envCopy["PATH"] = os.Getenv("PATH")
config := &config{
- productVariables: productVariables{
+ productVariables: ProductVariables{
DeviceName: stringPtr("test_device"),
DeviceProduct: stringPtr("test_product"),
Platform_sdk_version: intPtr(30),
diff --git a/android/util.go b/android/util.go
index 50bf5aa54..5375373a6 100644
--- a/android/util.go
+++ b/android/util.go
@@ -137,19 +137,17 @@ func SortedUniqueStringValues(m interface{}) []string {
}
// IndexList returns the index of the first occurrence of the given string in the list or -1
-func IndexList(s string, list []string) int {
+func IndexList[T comparable](t T, list []T) int {
for i, l := range list {
- if l == s {
+ if l == t {
return i
}
}
-
return -1
}
-// InList checks if the string belongs to the list
-func InList(s string, list []string) bool {
- return IndexList(s, list) != -1
+func InList[T comparable](t T, list []T) bool {
+ return IndexList(t, list) != -1
}
func setFromList[T comparable](l []T) map[T]bool {
@@ -351,15 +349,19 @@ func firstUniqueMap[T comparable](in []T) []T {
return in[0:writeIndex]
}
-// reverseSliceInPlace reverses the elements of a slice in place.
-func reverseSliceInPlace[T any](in []T) {
+// ReverseSliceInPlace reverses the elements of a slice in place and returns it.
+func ReverseSliceInPlace[T any](in []T) []T {
for i, j := 0, len(in)-1; i < j; i, j = i+1, j-1 {
in[i], in[j] = in[j], in[i]
}
+ return in
}
-// reverseSlice returns a copy of a slice in reverse order.
-func reverseSlice[T any](in []T) []T {
+// ReverseSlice returns a copy of a slice in reverse order.
+func ReverseSlice[T any](in []T) []T {
+ if in == nil {
+ return in
+ }
out := make([]T, len(in))
for i := 0; i < len(in); i++ {
out[i] = in[len(in)-1-i]
diff --git a/android/util_test.go b/android/util_test.go
index 0e28b568b..20161e52d 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -20,6 +20,7 @@ import (
"strconv"
"strings"
"testing"
+ "unsafe"
)
var firstUniqueStringsTestCases = []struct {
@@ -754,3 +755,65 @@ func TestSortedUniqueStringValues(t *testing.T) {
})
}
}
+
+var reverseTestCases = []struct {
+ name string
+ in []string
+ expected []string
+}{
+ {
+ name: "nil",
+ in: nil,
+ expected: nil,
+ },
+ {
+ name: "empty",
+ in: []string{},
+ expected: []string{},
+ },
+ {
+ name: "one",
+ in: []string{"one"},
+ expected: []string{"one"},
+ },
+ {
+ name: "even",
+ in: []string{"one", "two"},
+ expected: []string{"two", "one"},
+ },
+ {
+ name: "odd",
+ in: []string{"one", "two", "three"},
+ expected: []string{"three", "two", "one"},
+ },
+}
+
+func TestReverseSliceInPlace(t *testing.T) {
+ for _, testCase := range reverseTestCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ slice := CopyOf(testCase.in)
+ slice2 := slice
+ ReverseSliceInPlace(slice)
+ if !reflect.DeepEqual(slice, testCase.expected) {
+ t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+ }
+ if unsafe.SliceData(slice) != unsafe.SliceData(slice2) {
+ t.Errorf("expected slices to share backing array")
+ }
+ })
+ }
+}
+
+func TestReverseSlice(t *testing.T) {
+ for _, testCase := range reverseTestCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ slice := ReverseSlice(testCase.in)
+ if !reflect.DeepEqual(slice, testCase.expected) {
+ t.Errorf("expected %#v, got %#v", testCase.expected, slice)
+ }
+ if slice != nil && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) {
+ t.Errorf("expected slices to have different backing arrays")
+ }
+ })
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index 3bec854ea..ca9a221b1 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -138,6 +138,7 @@ type variableProperties struct {
Srcs []string
Exclude_srcs []string
+ Cmd *string
}
// eng is true for -eng builds, and can be used to turn on additional heavyweight debugging
@@ -156,10 +157,6 @@ type variableProperties struct {
}
}
- Pdk struct {
- Enabled *bool `android:"arch_variant"`
- } `android:"arch_variant"`
-
Uml struct {
Cppflags []string
}
@@ -180,12 +177,19 @@ type variableProperties struct {
Srcs []string `android:"arch_variant"`
Exclude_srcs []string `android:"arch_variant"`
} `android:"arch_variant"`
+
+ // release_aidl_use_unfrozen is "true" when a device can
+ // use the unfrozen versions of AIDL interfaces.
+ Release_aidl_use_unfrozen struct {
+ Cflags []string
+ Cmd *string
+ }
} `android:"arch_variant"`
}
var defaultProductVariables interface{} = variableProperties{}
-type productVariables struct {
+type ProductVariables struct {
// Suffix to add to generated Makefiles
Make_suffix *string `json:",omitempty"`
@@ -220,6 +224,7 @@ type productVariables struct {
DeviceCurrentApiLevelForVendorModules *string `json:",omitempty"`
DeviceSystemSdkVersions []string `json:",omitempty"`
DeviceMaxPageSizeSupported *string `json:",omitempty"`
+ DevicePageSizeAgnostic *bool `json:",omitempty"`
RecoverySnapshotVersion *string `json:",omitempty"`
@@ -401,9 +406,10 @@ type productVariables struct {
WithDexpreopt bool `json:",omitempty"`
- ManifestPackageNameOverrides []string `json:",omitempty"`
- CertificateOverrides []string `json:",omitempty"`
- PackageNameOverrides []string `json:",omitempty"`
+ ManifestPackageNameOverrides []string `json:",omitempty"`
+ CertificateOverrides []string `json:",omitempty"`
+ PackageNameOverrides []string `json:",omitempty"`
+ ConfiguredJarLocationOverrides []string `json:",omitempty"`
ApexGlobalMinSdkVersionOverride *string `json:",omitempty"`
@@ -456,6 +462,8 @@ type productVariables struct {
SelinuxIgnoreNeverallows bool `json:",omitempty"`
+ Release_aidl_use_unfrozen *bool `json:",omitempty"`
+
SepolicyFreezeTestExtraDirs []string `json:",omitempty"`
SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
@@ -474,6 +482,10 @@ type productVariables struct {
ReleaseVersion string `json:",omitempty"`
ReleaseAconfigValueSets []string `json:",omitempty"`
+
+ ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
+
+ KeepVndk *bool `json:",omitempty"`
}
func boolPtr(v bool) *bool {
@@ -488,8 +500,8 @@ func stringPtr(v string) *string {
return &v
}
-func (v *productVariables) SetDefaultConfig() {
- *v = productVariables{
+func (v *ProductVariables) SetDefaultConfig() {
+ *v = ProductVariables{
BuildNumberFile: stringPtr("build_number.txt"),
Platform_version_name: stringPtr("S"),
@@ -514,6 +526,7 @@ func (v *productVariables) SetDefaultConfig() {
DeviceSecondaryCpuVariant: stringPtr("generic"),
DeviceSecondaryAbi: []string{"armeabi-v7a", "armeabi"},
DeviceMaxPageSizeSupported: stringPtr("4096"),
+ DevicePageSizeAgnostic: boolPtr(false),
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
AAPTPreferredConfig: stringPtr("xhdpi"),
@@ -665,11 +678,16 @@ func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductCon
if moduleBase.variableProperties != nil {
productVariablesProperty := proptools.FieldNameForProperty("product_variables")
- for /* axis */ _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
- for config, props := range configToProps {
- variableValues := reflect.ValueOf(props).Elem().FieldByName(productVariablesProperty)
- productConfigProperties.AddProductConfigProperties(variableValues, config)
+ if moduleBase.ArchSpecific() {
+ for /* axis */ _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
+ for config, props := range configToProps {
+ variableValues := reflect.ValueOf(props).Elem().FieldByName(productVariablesProperty)
+ productConfigProperties.AddProductConfigProperties(variableValues, config)
+ }
}
+ } else {
+ variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName(productVariablesProperty)
+ productConfigProperties.AddProductConfigProperties(variableValues, "")
}
}
@@ -725,7 +743,9 @@ func (p *ProductConfigProperties) AddEitherProperty(
dst = append(dst, src...)
(*p)[propertyName][key] = dst
default:
- panic(fmt.Errorf("TODO: handle merging value %#v", existing))
+ if existing != propertyValue {
+ panic(fmt.Errorf("TODO: handle merging value %#v", existing))
+ }
}
} else {
(*p)[propertyName][key] = propertyValue
@@ -938,7 +958,7 @@ func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties
productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, os.Name, property.Interface())
}
}
- } else {
+ } else if !archOrOsSpecificStruct.IsZero() {
// One problem with supporting additional fields is that if multiple branches of
// "target" overlap, we don't want them to be in the same select statement (aka
// configuration axis). "android" and "host" are disjoint, so it's ok that we only
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index 9623a8bc4..7212a0740 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -166,7 +166,7 @@ func (s *sdkRepoHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
} else {
llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
- llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so.1")
+ llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so")
for _, strip := range s.properties.Strip_files {
cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib)
if !ctx.Windows() {
diff --git a/apex/apex.go b/apex/apex.go
index 1d094eb31..8c21d3d7c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -993,7 +993,7 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
// the non-system APEXes because the VNDK libraries won't be included (and duped) in the
// APEX, but shared across APEXes via the VNDK APEX.
useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface())
- excludeVndkLibs := useVndk && proptools.Bool(a.properties.Use_vndk_as_stable)
+ excludeVndkLibs := useVndk && a.useVndkAsStable(mctx)
if proptools.Bool(a.properties.Use_vndk_as_stable) {
if !useVndk {
mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes")
@@ -1685,6 +1685,7 @@ func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
}
+ dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
fileToCopy := android.OutputFileForModule(ctx, rustm, "")
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
@@ -1704,6 +1705,7 @@ func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) a
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
}
+ dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
fileToCopy := android.OutputFileForModule(ctx, rustm, "")
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
@@ -2394,7 +2396,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
// tags used below are private (e.g. `cc.sharedDepTag`).
if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
if ch, ok := child.(*cc.Module); ok {
- if ch.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && ch.IsVndk() {
+ if ch.UseVndk() && a.useVndkAsStable(ctx) && ch.IsVndk() {
vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk")
return false
}
@@ -3277,31 +3279,6 @@ func makeApexAvailableBaseline() map[string][]string {
// Module separator
//
m["com.android.runtime"] = []string{
- "libc_aeabi",
- "libc_bionic",
- "libc_bionic_ndk",
- "libc_bootstrap",
- "libc_common",
- "libc_common_shared",
- "libc_dns",
- "libc_dynamic_dispatch",
- "libc_fortify",
- "libc_freebsd",
- "libc_freebsd_large_stack",
- "libc_gdtoa",
- "libc_init_dynamic",
- "libc_init_static",
- "libc_jemalloc_wrapper",
- "libc_netbsd",
- "libc_nomalloc",
- "libc_nopthread",
- "libc_openbsd",
- "libc_openbsd_large_stack",
- "libc_openbsd_ndk",
- "libc_pthread",
- "libc_syscalls",
- "libc_tzcode",
- "libc_unwind_static",
"libdebuggerd",
"libdebuggerd_common_headers",
"libdebuggerd_handler_core",
@@ -3313,7 +3290,6 @@ func makeApexAvailableBaseline() map[string][]string {
"libprocinfo",
"libpropertyinfoparser",
"libscudo",
- "libstdc++",
"libsystemproperties",
"libtombstoned_client_static",
"libunwindstack",
@@ -3742,3 +3718,12 @@ func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
func (a *apexBundle) IsTestApex() bool {
return a.testApex
}
+
+func (a *apexBundle) useVndkAsStable(ctx android.BaseModuleContext) bool {
+ // VNDK cannot be linked if it is deprecated
+ if ctx.Config().IsVndkDeprecated() {
+ return false
+ }
+
+ return proptools.Bool(a.properties.Use_vndk_as_stable)
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index b67535a18..da059eb0a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -390,7 +390,7 @@ func TestBasicApex(t *testing.T) {
name: "foo.rust",
srcs: ["foo.rs"],
rlibs: ["libfoo.rlib.rust"],
- dylibs: ["libfoo.dylib.rust"],
+ rustlibs: ["libfoo.dylib.rust"],
apex_available: ["myapex"],
}
@@ -2794,7 +2794,7 @@ func TestFilesInSubDir(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
- binaries: ["mybin"],
+ binaries: ["mybin", "mybin.rust"],
prebuilts: ["myetc"],
compile_multilib: "both",
updatable: false,
@@ -2829,6 +2829,13 @@ func TestFilesInSubDir(t *testing.T) {
stl: "none",
apex_available: [ "myapex" ],
}
+
+ rust_binary {
+ name: "mybin.rust",
+ srcs: ["foo.rs"],
+ relative_install_path: "rust_subdir",
+ apex_available: [ "myapex" ],
+ }
`)
generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
@@ -2847,6 +2854,7 @@ func TestFilesInSubDir(t *testing.T) {
ensureContains(t, cmd, "/bin ")
ensureContains(t, cmd, "/bin/foo ")
ensureContains(t, cmd, "/bin/foo/bar ")
+ ensureContains(t, cmd, "/bin/rust_subdir ")
}
func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
@@ -3029,7 +3037,11 @@ func TestVendorApex_use_vndk_as_stable(t *testing.T) {
vendor: true,
shared_libs: ["libvndk", "libvendor"],
}
- `)
+ `,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.KeepVndk = proptools.BoolPtr(true)
+ }),
+ )
vendorVariant := "android_vendor.29_arm64_armv8-a"
@@ -3858,6 +3870,7 @@ func TestVndkApexCurrent(t *testing.T) {
}
`+vndkLibrariesTxtFiles("current"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = proptools.StringPtr(tc.vndkVersion)
+ variables.KeepVndk = proptools.BoolPtr(true)
}))
ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", tc.expectedFiles)
})
@@ -5587,6 +5600,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
@@ -5664,6 +5678,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
@@ -5758,6 +5773,28 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
t.Run("prebuilt library preferred with source", func(t *testing.T) {
bp := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
prebuilt_apex {
name: "myapex",
arch: {
@@ -5773,6 +5810,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
prebuilt_bootclasspath_fragment {
name: "my-bootclasspath-fragment",
+ prefer: true,
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
hidden_api: {
@@ -5797,6 +5835,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
name: "libfoo",
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
+ installable: true,
}
java_sdk_library_import {
@@ -5815,6 +5854,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
unsafe_ignore_missing_latest_api: true,
apex_available: ["myapex"],
+ compile_dex: true,
}
`
@@ -5827,6 +5867,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
@@ -5835,8 +5876,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
apex {
name: "myapex",
key: "myapex.key",
- java_libs: ["libfoo", "libbar"],
updatable: false,
+ bootclasspath_fragments: ["my-bootclasspath-fragment"],
}
apex_key {
@@ -5845,6 +5886,15 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
private_key: "testkey.pem",
}
+ bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
prebuilt_apex {
name: "myapex",
arch: {
@@ -5883,6 +5933,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
permitted_packages: ["foo"],
+ installable: true,
}
java_sdk_library_import {
@@ -5900,6 +5951,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
unsafe_ignore_missing_latest_api: true,
apex_available: ["myapex"],
permitted_packages: ["bar"],
+ compile_dex: true,
}
`
@@ -5910,8 +5962,9 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
- my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
@@ -5921,7 +5974,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
name: "myapex",
enabled: false,
key: "myapex.key",
- java_libs: ["libfoo", "libbar"],
+ bootclasspath_fragments: ["my-bootclasspath-fragment"],
}
apex_key {
@@ -5930,6 +5983,16 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
private_key: "testkey.pem",
}
+ bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ enabled: false,
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
prebuilt_apex {
name: "myapex",
arch: {
@@ -5959,7 +6022,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
java_import {
name: "libfoo",
- prefer: true,
jars: ["libfoo.jar"],
apex_available: ["myapex"],
permitted_packages: ["foo"],
@@ -5967,13 +6029,14 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
java_library {
name: "libfoo",
+ enabled: false,
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
+ installable: true,
}
java_sdk_library_import {
name: "libbar",
- prefer: true,
public: {
jars: ["libbar.jar"],
},
@@ -5984,9 +6047,11 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
java_sdk_library {
name: "libbar",
+ enabled: false,
srcs: ["foo/bar/MyClass.java"],
unsafe_ignore_missing_latest_api: true,
apex_available: ["myapex"],
+ compile_dex: true,
}
`
@@ -5999,6 +6064,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
}
@@ -6737,6 +6803,10 @@ func TestApexAvailable_ApexAvailableNameWithVersionCode(t *testing.T) {
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
+ override_apex {
+ name: "myoverrideapex",
+ base: "bar",
+ }
`)
fooManifestRule := result.ModuleForTests("foo", "android_common_foo_image").Rule("apexManifestRule")
@@ -6753,6 +6823,12 @@ func TestApexAvailable_ApexAvailableNameWithVersionCode(t *testing.T) {
if barActualDefaultVersion != barExpectedDefaultVersion {
t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
}
+
+ overrideBarManifestRule := result.ModuleForTests("bar", "android_common_myoverrideapex_bar_image").Rule("apexManifestRule")
+ overrideBarActualDefaultVersion := overrideBarManifestRule.Args["default_version"]
+ if overrideBarActualDefaultVersion != barExpectedDefaultVersion {
+ t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
+ }
}
func TestApexAvailable_ApexAvailableName(t *testing.T) {
@@ -8163,126 +8239,6 @@ func TestApexSetApksModuleAssignment(t *testing.T) {
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
}
-func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) {
- t.Helper()
-
- bp := `
- java_library {
- name: "some-updatable-apex-lib",
- srcs: ["a.java"],
- sdk_version: "current",
- apex_available: [
- "some-updatable-apex",
- ],
- permitted_packages: ["some.updatable.apex.lib"],
- min_sdk_version: "33",
- }
-
- java_library {
- name: "some-non-updatable-apex-lib",
- srcs: ["a.java"],
- apex_available: [
- "some-non-updatable-apex",
- ],
- compile_dex: true,
- permitted_packages: ["some.non.updatable.apex.lib"],
- }
-
- bootclasspath_fragment {
- name: "some-non-updatable-fragment",
- contents: ["some-non-updatable-apex-lib"],
- apex_available: [
- "some-non-updatable-apex",
- ],
- hidden_api: {
- split_packages: ["*"],
- },
- }
-
- java_library {
- name: "some-platform-lib",
- srcs: ["a.java"],
- sdk_version: "current",
- installable: true,
- }
-
- java_library {
- name: "some-art-lib",
- srcs: ["a.java"],
- sdk_version: "current",
- apex_available: [
- "com.android.art.debug",
- ],
- hostdex: true,
- compile_dex: true,
- min_sdk_version: "33",
- }
-
- apex {
- name: "some-updatable-apex",
- key: "some-updatable-apex.key",
- java_libs: ["some-updatable-apex-lib"],
- updatable: true,
- min_sdk_version: "33",
- }
-
- apex {
- name: "some-non-updatable-apex",
- key: "some-non-updatable-apex.key",
- bootclasspath_fragments: ["some-non-updatable-fragment"],
- updatable: false,
- }
-
- apex_key {
- name: "some-updatable-apex.key",
- }
-
- apex_key {
- name: "some-non-updatable-apex.key",
- }
-
- apex {
- name: "com.android.art.debug",
- key: "com.android.art.debug.key",
- bootclasspath_fragments: ["art-bootclasspath-fragment"],
- updatable: true,
- min_sdk_version: "33",
- }
-
- bootclasspath_fragment {
- name: "art-bootclasspath-fragment",
- image_name: "art",
- contents: ["some-art-lib"],
- apex_available: [
- "com.android.art.debug",
- ],
- hidden_api: {
- split_packages: ["*"],
- },
- }
-
- apex_key {
- name: "com.android.art.debug.key",
- }
-
- filegroup {
- name: "some-updatable-apex-file_contexts",
- srcs: [
- "system/sepolicy/apex/some-updatable-apex-file_contexts",
- ],
- }
-
- filegroup {
- name: "some-non-updatable-apex-file_contexts",
- srcs: [
- "system/sepolicy/apex/some-non-updatable-apex-file_contexts",
- ],
- }
- `
-
- testDexpreoptWithApexes(t, bp, errmsg, preparer, fragments...)
-}
-
func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext {
t.Helper()
@@ -8306,7 +8262,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F
result := android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
java.PrepareForTestWithHiddenApiBuildComponents,
- java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithDexpreopt,
java.PrepareForTestWithJavaSdkLibraryFiles,
PrepareForTestWithApexBuildComponents,
preparer,
@@ -8321,12 +8277,16 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F
platform_bootclasspath {
name: "platform-bootclasspath",
fragments: [
+ {apex: "com.android.art", module: "art-bootclasspath-fragment"},
%s
],
}
`, insert))
}
}),
+ // Dexpreopt for boot jars requires the ART boot image profile.
+ java.PrepareApexBootJarModule("com.android.art", "core-oj"),
+ dexpreopt.FixtureSetArtBootJars("com.android.art:core-oj"),
dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
).
ExtendWithErrorHandler(errorHandler).
@@ -8633,126 +8593,6 @@ func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) {
)
}
-func TestNoUpdatableJarsInBootImage(t *testing.T) {
- // Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can
- // result in an invalid configuration as it does not set the ArtApexJars and allows art apex
- // modules to be included in the BootJars.
- prepareSetBootJars := func(bootJars ...string) android.FixturePreparer {
- return android.GroupFixturePreparers(
- dexpreopt.FixtureSetBootJars(bootJars...),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
- }),
- )
- }
-
- // Set the ArtApexJars and BootJars in dexpreopt.GlobalConfig and productVariables all to the
- // same value. This can result in an invalid configuration as it allows non art apex jars to be
- // specified in the ArtApexJars configuration.
- prepareSetArtJars := func(bootJars ...string) android.FixturePreparer {
- return android.GroupFixturePreparers(
- dexpreopt.FixtureSetArtBootJars(bootJars...),
- dexpreopt.FixtureSetBootJars(bootJars...),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
- }),
- )
- }
-
- t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
- preparer := android.GroupFixturePreparers(
- java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib"),
- java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
- )
- fragments := []java.ApexVariantReference{
- {
- Apex: proptools.StringPtr("com.android.art.debug"),
- Module: proptools.StringPtr("art-bootclasspath-fragment"),
- },
- {
- Apex: proptools.StringPtr("some-non-updatable-apex"),
- Module: proptools.StringPtr("some-non-updatable-fragment"),
- },
- }
- testNoUpdatableJarsInBootImage(t, "", preparer, fragments...)
- })
-
- t.Run("updatable jar from ART apex in the platform bootclasspath => error", func(t *testing.T) {
- err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the platform bootclasspath`
- // Update the dexpreopt BootJars directly.
- preparer := android.GroupFixturePreparers(
- prepareSetBootJars("com.android.art.debug:some-art-lib"),
- java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
- )
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err := `ArtApexJars expects this to be in apex "some-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
- // Update the dexpreopt ArtApexJars directly.
- preparer := prepareSetArtJars("some-updatable-apex:some-updatable-apex-lib")
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err := `ArtApexJars expects this to be in apex "some-non-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
- // Update the dexpreopt ArtApexJars directly.
- preparer := prepareSetArtJars("some-non-updatable-apex:some-non-updatable-apex-lib")
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("updatable jar from some other apex in the platform bootclasspath => error", func(t *testing.T) {
- err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the platform bootclasspath`
- preparer := android.GroupFixturePreparers(
- java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib"),
- java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
- )
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("non-updatable jar from some other apex in the platform bootclasspath => ok", func(t *testing.T) {
- preparer := java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
- fragment := java.ApexVariantReference{
- Apex: proptools.StringPtr("some-non-updatable-apex"),
- Module: proptools.StringPtr("some-non-updatable-fragment"),
- }
- testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
- })
-
- t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
- err := `"platform-bootclasspath" depends on undefined module "nonexistent"`
- preparer := java.FixtureConfigureBootJars("platform:nonexistent")
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("nonexistent jar in the platform bootclasspath => error", func(t *testing.T) {
- err := `"platform-bootclasspath" depends on undefined module "nonexistent"`
- preparer := java.FixtureConfigureBootJars("platform:nonexistent")
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
- err := `ArtApexJars is invalid as it requests a platform variant of "some-platform-lib"`
- // Update the dexpreopt ArtApexJars directly.
- preparer := prepareSetArtJars("platform:some-platform-lib")
- testNoUpdatableJarsInBootImage(t, err, preparer)
- })
-
- t.Run("platform jar in the platform bootclasspath => ok", func(t *testing.T) {
- preparer := android.GroupFixturePreparers(
- java.FixtureConfigureBootJars("platform:some-platform-lib"),
- java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
- )
- fragments := []java.ApexVariantReference{
- {
- Apex: proptools.StringPtr("some-non-updatable-apex"),
- Module: proptools.StringPtr("some-non-updatable-fragment"),
- },
- }
- testNoUpdatableJarsInBootImage(t, "", preparer, fragments...)
- })
-}
-
func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
preparer := java.FixtureConfigureApexBootJars("myapex:libfoo")
t.Run("prebuilt no source", func(t *testing.T) {
@@ -10736,6 +10576,7 @@ func TestTrimmedApex(t *testing.T) {
src: "libc.so",
min_sdk_version: "29",
recovery_available: true,
+ vendor_available: true,
}
api_imports {
name: "api_imports",
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 1b5288696..f30f7f666 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -46,78 +46,6 @@ var prepareForTestWithArtApex = android.GroupFixturePreparers(
dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
)
-func TestBootclasspathFragments(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForTestWithBootclasspathFragment,
- // Configure some libraries in the art bootclasspath_fragment and platform_bootclasspath.
- java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo", "platform:bar"),
- prepareForTestWithArtApex,
-
- java.PrepareForTestWithJavaSdkLibraryFiles,
- java.FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["b.java"],
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java"],
- installable: true,
- }
-
- apex {
- name: "com.android.art",
- key: "com.android.art.key",
- bootclasspath_fragments: ["art-bootclasspath-fragment"],
- updatable: false,
- }
-
- apex_key {
- name: "com.android.art.key",
- public_key: "com.android.art.avbpubkey",
- private_key: "com.android.art.pem",
- }
-
- java_library {
- name: "baz",
- apex_available: [
- "com.android.art",
- ],
- srcs: ["b.java"],
- compile_dex: true,
- }
-
- java_library {
- name: "quuz",
- apex_available: [
- "com.android.art",
- ],
- srcs: ["b.java"],
- compile_dex: true,
- }
-
- bootclasspath_fragment {
- name: "art-bootclasspath-fragment",
- image_name: "art",
- // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
- contents: ["baz", "quuz"],
- apex_available: [
- "com.android.art",
- ],
- hidden_api: {
- split_packages: ["*"],
- },
- }
-`,
- )
-
- // Make sure that the art-bootclasspath-fragment is using the correct configuration.
- checkBootclasspathFragment(t, result, "art-bootclasspath-fragment", "android_common_apex10000",
- "com.android.art:baz,com.android.art:quuz")
-}
-
func TestBootclasspathFragments_FragmentDependency(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
@@ -248,16 +176,6 @@ func TestBootclasspathFragments_FragmentDependency(t *testing.T) {
checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope)
}
-func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string) {
- t.Helper()
-
- bootclasspathFragment := result.ModuleForTests(moduleName, variantName).Module().(*java.BootclasspathFragmentModule)
-
- bootclasspathFragmentInfo := result.ModuleProvider(bootclasspathFragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
- modules := bootclasspathFragmentInfo.Modules()
- android.AssertStringEquals(t, "invalid modules for "+moduleName, expectedConfiguredModules, modules.String())
-}
-
func TestBootclasspathFragmentInArtApex(t *testing.T) {
commonPreparer := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
@@ -268,10 +186,10 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
name: "com.android.art",
key: "com.android.art.key",
bootclasspath_fragments: [
- "mybootclasspathfragment",
+ "art-bootclasspath-fragment",
],
// bar (like foo) should be transitively included in this apex because it is part of the
- // mybootclasspathfragment bootclasspath_fragment.
+ // art-bootclasspath-fragment bootclasspath_fragment.
updatable: false,
}
@@ -280,42 +198,6 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
-
- java_library {
- name: "foo",
- srcs: ["b.java"],
- installable: true,
- apex_available: [
- "com.android.art",
- ],
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java"],
- installable: true,
- apex_available: [
- "com.android.art",
- ],
- }
-
- java_import {
- name: "foo",
- jars: ["foo.jar"],
- apex_available: [
- "com.android.art",
- ],
- compile_dex: true,
- }
-
- java_import {
- name: "bar",
- jars: ["bar.jar"],
- apex_available: [
- "com.android.art",
- ],
- compile_dex: true,
- }
`),
)
@@ -330,7 +212,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
addSource := func(contents ...string) android.FixturePreparer {
text := fmt.Sprintf(`
bootclasspath_fragment {
- name: "mybootclasspathfragment",
+ name: "art-bootclasspath-fragment",
image_name: "art",
%s
apex_available: [
@@ -342,6 +224,19 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
}
`, contentsInsert(contents))
+ for _, content := range contents {
+ text += fmt.Sprintf(`
+ java_library {
+ name: "%[1]s",
+ srcs: ["%[1]s.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+ `, content)
+ }
+
return android.FixtureAddTextFile("art/build/boot/Android.bp", text)
}
@@ -357,11 +252,11 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
src: "com.android.art-arm.apex",
},
},
- exported_bootclasspath_fragments: ["mybootclasspathfragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
prebuilt_bootclasspath_fragment {
- name: "mybootclasspathfragment",
+ name: "art-bootclasspath-fragment",
image_name: "art",
%s
prefer: %t,
@@ -369,14 +264,29 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
"com.android.art",
],
hidden_api: {
- annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
- metadata: "mybootclasspathfragment/metadata.csv",
- index: "mybootclasspathfragment/index.csv",
- stub_flags: "mybootclasspathfragment/stub-flags.csv",
- all_flags: "mybootclasspathfragment/all-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ stub_flags: "hiddenapi/stub-flags.csv",
+ all_flags: "hiddenapi/all-flags.csv",
},
}
`, contentsInsert(contents), prefer)
+
+ for _, content := range contents {
+ text += fmt.Sprintf(`
+ java_import {
+ name: "%[1]s",
+ prefer: %[2]t,
+ jars: ["%[1]s.jar"],
+ apex_available: [
+ "com.android.art",
+ ],
+ compile_dex: true,
+ }
+ `, content, prefer)
+ }
+
return android.FixtureAddTextFile("prebuilts/module_sdk/art/Android.bp", text)
}
@@ -387,6 +297,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
// Configure some libraries in the art bootclasspath_fragment that match the source
// bootclasspath_fragment's contents property.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
addSource("foo", "bar"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
@@ -399,13 +310,13 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
})
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ `art-bootclasspath-fragment`,
`com.android.art.key`,
- `mybootclasspathfragment`,
})
// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
- module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ module := result.ModuleForTests("dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
@@ -454,6 +365,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
// Configure some libraries in the art bootclasspath_fragment that match the source
// bootclasspath_fragment's contents property.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
addSource("foo", "bar"),
// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
@@ -469,14 +381,14 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
})
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ `art-bootclasspath-fragment`,
`com.android.art.key`,
- `mybootclasspathfragment`,
`prebuilt_com.android.art`,
})
// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
- module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
+ module := result.ModuleForTests("dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
@@ -552,6 +464,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
// Configure some libraries in the art bootclasspath_fragment.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
)
@@ -566,7 +479,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
src: "com.android.art-arm.apex",
},
},
- exported_bootclasspath_fragments: ["mybootclasspathfragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
java_import {
@@ -586,7 +499,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
}
prebuilt_bootclasspath_fragment {
- name: "mybootclasspathfragment",
+ name: "art-bootclasspath-fragment",
image_name: "art",
// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
contents: ["foo", "bar"],
@@ -594,11 +507,11 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
"com.android.art",
],
hidden_api: {
- annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
- metadata: "mybootclasspathfragment/metadata.csv",
- index: "mybootclasspathfragment/index.csv",
- stub_flags: "mybootclasspathfragment/stub-flags.csv",
- all_flags: "mybootclasspathfragment/all-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ stub_flags: "hiddenapi/stub-flags.csv",
+ all_flags: "hiddenapi/all-flags.csv",
},
}
@@ -608,7 +521,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
apex_name: "com.android.art",
%s
src: "com.mycompany.android.art.apex",
- exported_bootclasspath_fragments: ["mybootclasspathfragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
`
@@ -617,17 +530,17 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
`com.android.art.apex.selector`,
- `prebuilt_mybootclasspathfragment`,
+ `prebuilt_art-bootclasspath-fragment`,
})
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
`com.android.art.deapexer`,
`dex2oatd`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
+ module := result.ModuleForTests("dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index bba8bb6cb..2e828cade 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -138,8 +138,8 @@ func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOu
prepareForTestWithArtApex,
).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
- platformBootclasspath := result.ModuleForTests("platform-bootclasspath", "android_common")
- rule := platformBootclasspath.Output(ruleFile)
+ dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+ rule := dexBootJars.Output(ruleFile)
inputs := rule.Implicits.Strings()
sort.Strings(inputs)
@@ -155,15 +155,15 @@ func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOu
}
func TestDexpreoptBootJarsWithSourceArtApex(t *testing.T) {
- ruleFile := "boot.art"
+ ruleFile := "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art"
expectedInputs := []string{
"out/soong/dexpreopt_arm64/dex_bootjars_input/core-oj.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/dexpreopt_arm64/dex_artjars/boot.prof",
- "out/soong/dexpreopt_arm64/dex_bootjars/boot.prof",
+ "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+ "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
}
expectedOutputs := []string{
@@ -192,7 +192,7 @@ func TestDexpreoptBootJarsWithSourceArtApex(t *testing.T) {
// The only difference is that the ART profile should be deapexed from the prebuilt APEX. Other
// inputs and outputs should be the same as above.
func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
- ruleFile := "boot.art"
+ ruleFile := "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art"
expectedInputs := []string{
"out/soong/dexpreopt_arm64/dex_bootjars_input/core-oj.jar",
@@ -200,7 +200,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) {
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
"out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
- "out/soong/dexpreopt_arm64/dex_bootjars/boot.prof",
+ "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
}
expectedOutputs := []string{
diff --git a/apex/vndk.go b/apex/vndk.go
index 095e89db3..889324090 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -103,7 +103,7 @@ func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
}
} else if a, ok := mctx.Module().(*apexBundle); ok && a.vndkApex {
vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
- mctx.AddDependency(mctx.Module(), prebuiltTag, cc.VndkLibrariesTxtModules(vndkVersion)...)
+ mctx.AddDependency(mctx.Module(), prebuiltTag, cc.VndkLibrariesTxtModules(vndkVersion, mctx)...)
}
}
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 21526c3eb..4327a61f8 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -51,6 +51,7 @@ func TestVndkApexForVndkLite(t *testing.T) {
`+vndkLibrariesTxtFiles("current"),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = proptools.StringPtr("")
+ variables.KeepVndk = proptools.BoolPtr(true)
}),
)
// VNDK-Lite contains only core variants of VNDK-Sp libraries
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 95e52ae73..d77d59acf 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -17,15 +17,15 @@ package bazel
import (
"crypto/sha256"
"encoding/base64"
+ "encoding/json"
"fmt"
"path/filepath"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
"reflect"
"sort"
"strings"
"sync"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
-
"github.com/google/blueprint/metrics"
"github.com/google/blueprint/proptools"
"google.golang.org/protobuf/proto"
@@ -116,6 +116,13 @@ type BuildStatement struct {
InputDepsetHashes []string
InputPaths []string
FileContents string
+ // If ShouldRunInSbox is true, Soong will use sbox to created an isolated environment
+ // and run the mixed build action there
+ ShouldRunInSbox bool
+ // A list of files to add as implicit deps to the outputs of this BuildStatement.
+ // Unlike most properties in BuildStatement, these paths must be relative to the root of
+ // the whole out/ folder, instead of relative to ctx.Config().BazelContext.OutputBase()
+ ImplicitDeps []string
}
// A helper type for aquery processing which facilitates retrieval of path IDs from their
@@ -456,7 +463,7 @@ func (a *aqueryArtifactHandler) depsetContentHashes(inputDepsetIds []uint32) ([]
// escapes the args received from aquery and creates a command string
func commandString(actionEntry *analysis_v2_proto.Action) string {
switch actionEntry.Mnemonic {
- case "GoCompilePkg":
+ case "GoCompilePkg", "GoStdlib":
argsEscaped := []string{}
for _, arg := range actionEntry.Arguments {
if arg == "" {
@@ -496,6 +503,12 @@ func (a *aqueryArtifactHandler) normalActionBuildStatement(actionEntry *analysis
Env: actionEntry.EnvironmentVariables,
Mnemonic: actionEntry.Mnemonic,
}
+ if buildStatement.Mnemonic == "GoToolchainBinaryBuild" {
+ // Unlike b's execution root, mixed build execution root contains a symlink to prebuilts/go
+ // This causes issues for `GOCACHE=$(mktemp -d) go build ...`
+ // To prevent this, sandbox this action in mixed builds as well
+ buildStatement.ShouldRunInSbox = true
+ }
return buildStatement, nil
}
@@ -572,6 +585,72 @@ func (a *aqueryArtifactHandler) symlinkTreeActionBuildStatement(actionEntry *ana
}, nil
}
+type bazelSandwichJson struct {
+ Target string `json:"target"`
+ DependOnTarget *bool `json:"depend_on_target,omitempty"`
+ ImplicitDeps []string `json:"implicit_deps"`
+}
+
+func (a *aqueryArtifactHandler) unresolvedSymlinkActionBuildStatement(actionEntry *analysis_v2_proto.Action) (*BuildStatement, error) {
+ outputPaths, depfile, err := a.getOutputPaths(actionEntry)
+ if err != nil {
+ return nil, err
+ }
+ if len(actionEntry.InputDepSetIds) != 0 || len(outputPaths) != 1 {
+ return nil, fmt.Errorf("expected 0 inputs and 1 output to symlink action, got: input %q, output %q", actionEntry.InputDepSetIds, outputPaths)
+ }
+ target := actionEntry.UnresolvedSymlinkTarget
+ if target == "" {
+ return nil, fmt.Errorf("expected an unresolved_symlink_target, but didn't get one")
+ }
+ if filepath.Clean(target) != target {
+ return nil, fmt.Errorf("expected %q, got %q", filepath.Clean(target), target)
+ }
+ if strings.HasPrefix(target, "/") {
+ return nil, fmt.Errorf("no absolute symlinks allowed: %s", target)
+ }
+
+ out := outputPaths[0]
+ outDir := filepath.Dir(out)
+ var implicitDeps []string
+ if strings.HasPrefix(target, "bazel_sandwich:") {
+ j := bazelSandwichJson{}
+ err := json.Unmarshal([]byte(target[len("bazel_sandwich:"):]), &j)
+ if err != nil {
+ return nil, err
+ }
+ if proptools.BoolDefault(j.DependOnTarget, true) {
+ implicitDeps = append(implicitDeps, j.Target)
+ }
+ implicitDeps = append(implicitDeps, j.ImplicitDeps...)
+ dotDotsToReachCwd := ""
+ if outDir != "." {
+ dotDotsToReachCwd = strings.Repeat("../", strings.Count(outDir, "/")+1)
+ }
+ target = proptools.ShellEscapeIncludingSpaces(j.Target)
+ target = "{DOTDOTS_TO_OUTPUT_ROOT}" + dotDotsToReachCwd + target
+ } else {
+ target = proptools.ShellEscapeIncludingSpaces(target)
+ }
+
+ outDir = proptools.ShellEscapeIncludingSpaces(outDir)
+ out = proptools.ShellEscapeIncludingSpaces(out)
+ // Use absolute paths, because some soong actions don't play well with relative paths (for example, `cp -d`).
+ command := fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -sf %[3]s %[2]s", outDir, out, target)
+ symlinkPaths := outputPaths[:]
+
+ buildStatement := &BuildStatement{
+ Command: command,
+ Depfile: depfile,
+ OutputPaths: outputPaths,
+ Env: actionEntry.EnvironmentVariables,
+ Mnemonic: actionEntry.Mnemonic,
+ SymlinkPaths: symlinkPaths,
+ ImplicitDeps: implicitDeps,
+ }
+ return buildStatement, nil
+}
+
func (a *aqueryArtifactHandler) symlinkActionBuildStatement(actionEntry *analysis_v2_proto.Action) (*BuildStatement, error) {
outputPaths, depfile, err := a.getOutputPaths(actionEntry)
if err != nil {
@@ -677,10 +756,12 @@ func (a *aqueryArtifactHandler) actionToBuildStatement(actionEntry *analysis_v2_
if len(actionEntry.Arguments) < 1 {
return a.templateExpandActionBuildStatement(actionEntry)
}
- case "FileWrite", "SourceSymlinkManifest":
+ case "FileWrite", "SourceSymlinkManifest", "RepoMappingManifest":
return a.fileWriteActionBuildStatement(actionEntry)
case "SymlinkTree":
return a.symlinkTreeActionBuildStatement(actionEntry)
+ case "UnresolvedSymlink":
+ return a.unresolvedSymlinkActionBuildStatement(actionEntry)
}
if len(actionEntry.Arguments) < 1 {
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 19a584f23..32c87a0a6 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -357,9 +357,11 @@ func TestDepfiles(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
if expected := 1; len(actual) != expected {
t.Fatalf("Expected %d build statements, got %d", expected, len(actual))
+ return
}
bs := actual[0]
@@ -544,6 +546,7 @@ func TestSymlinkTree(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
assertBuildStatements(t, []*BuildStatement{
&BuildStatement{
@@ -756,9 +759,11 @@ func TestMiddlemenAction(t *testing.T) {
actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
if expected := 2; len(actualBuildStatements) != expected {
t.Fatalf("Expected %d build statements, got %d %#v", expected, len(actualBuildStatements), actualBuildStatements)
+ return
}
expectedDepsetFiles := [][]string{
@@ -859,6 +864,7 @@ func TestSimpleSymlink(t *testing.T) {
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
expectedBuildStatements := []*BuildStatement{
@@ -907,6 +913,7 @@ func TestSymlinkQuotesPaths(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
expectedBuildStatements := []*BuildStatement{
@@ -1017,6 +1024,7 @@ func TestTemplateExpandActionSubstitutions(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
expectedBuildStatements := []*BuildStatement{
@@ -1088,6 +1096,7 @@ func TestFileWrite(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
assertBuildStatements(t, []*BuildStatement{
&BuildStatement{
@@ -1126,6 +1135,7 @@ func TestSourceSymlinkManifest(t *testing.T) {
actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
+ return
}
assertBuildStatements(t, []*BuildStatement{
&BuildStatement{
@@ -1136,6 +1146,126 @@ func TestSourceSymlinkManifest(t *testing.T) {
}, actual)
}
+func TestUnresolvedSymlink(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }
+ ],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "UnresolvedSymlink",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "unresolved_symlink_target": "symlink/target"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "path/to/symlink" }
+ ]
+}
+`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ return
+ }
+ assertBuildStatements(t, []*BuildStatement{{
+ Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf symlink/target path/to/symlink",
+ OutputPaths: []string{"path/to/symlink"},
+ Mnemonic: "UnresolvedSymlink",
+ SymlinkPaths: []string{"path/to/symlink"},
+ }}, actual)
+}
+
+func TestUnresolvedSymlinkBazelSandwich(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }
+ ],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "UnresolvedSymlink",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "unresolved_symlink_target": "bazel_sandwich:{\"target\":\"target/product/emulator_x86_64/system\"}"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "path/to/symlink" }
+ ]
+}
+`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ return
+ }
+ assertBuildStatements(t, []*BuildStatement{{
+ Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf {DOTDOTS_TO_OUTPUT_ROOT}../../target/product/emulator_x86_64/system path/to/symlink",
+ OutputPaths: []string{"path/to/symlink"},
+ Mnemonic: "UnresolvedSymlink",
+ SymlinkPaths: []string{"path/to/symlink"},
+ ImplicitDeps: []string{"target/product/emulator_x86_64/system"},
+ }}, actual)
+}
+
+func TestUnresolvedSymlinkBazelSandwichWithAlternativeDeps(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }
+ ],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "UnresolvedSymlink",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "unresolved_symlink_target": "bazel_sandwich:{\"depend_on_target\":false,\"implicit_deps\":[\"target/product/emulator_x86_64/obj/PACKAGING/systemimage_intermediates/staging_dir.stamp\"],\"target\":\"target/product/emulator_x86_64/system\"}"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "path/to/symlink" }
+ ]
+}
+`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ return
+ }
+ assertBuildStatements(t, []*BuildStatement{{
+ Command: "mkdir -p path/to && rm -f path/to/symlink && ln -sf {DOTDOTS_TO_OUTPUT_ROOT}../../target/product/emulator_x86_64/system path/to/symlink",
+ OutputPaths: []string{"path/to/symlink"},
+ Mnemonic: "UnresolvedSymlink",
+ SymlinkPaths: []string{"path/to/symlink"},
+ // Note that the target of the symlink, target/product/emulator_x86_64/system, is not listed here
+ ImplicitDeps: []string{"target/product/emulator_x86_64/obj/PACKAGING/systemimage_intermediates/staging_dir.stamp"},
+ }}, actual)
+}
+
func assertError(t *testing.T, err error, expected string) {
t.Helper()
if err == nil {
@@ -1201,6 +1331,9 @@ func buildStatementEquals(first *BuildStatement, second *BuildStatement) string
if !reflect.DeepEqual(sortedStrings(first.SymlinkPaths), sortedStrings(second.SymlinkPaths)) {
return "SymlinkPaths"
}
+ if !reflect.DeepEqual(sortedStrings(first.ImplicitDeps), sortedStrings(second.ImplicitDeps)) {
+ return "ImplicitDeps"
+ }
if first.Depfile != second.Depfile {
return "Depfile"
}
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 8f63ec45b..aa58fdc7e 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -67,13 +67,17 @@ const (
ConditionsDefaultSelectKey = "//conditions:default"
- productVariableBazelPackage = "//build/bazel/product_variables"
+ productVariableBazelPackage = "//build/bazel/product_config/config_settings"
AndroidAndInApex = "android-in_apex"
AndroidPlatform = "system"
InApex = "in_apex"
NonApex = "non_apex"
+
+ ErrorproneDisabled = "errorprone_disabled"
+ // TODO: b/294868620 - Remove when completing the bug
+ SanitizersEnabled = "sanitizers_enabled"
)
func PowerSetWithoutEmptySet[T any](items []T) [][]T {
@@ -216,6 +220,17 @@ var (
NonApex: "//build/bazel/rules/apex:non_apex",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
}
+
+ errorProneMap = map[string]string{
+ ErrorproneDisabled: "//build/bazel/rules/java/errorprone:errorprone_globally_disabled",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
+ }
+
+ // TODO: b/294868620 - Remove when completing the bug
+ sanitizersEnabledMap = map[string]string{
+ SanitizersEnabled: "//build/bazel/rules/cc:sanitizers_enabled",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
+ }
)
// basic configuration types
@@ -229,6 +244,9 @@ const (
productVariables
osAndInApex
inApex
+ errorProneDisabled
+ // TODO: b/294868620 - Remove when completing the bug
+ sanitizersEnabled
)
func osArchString(os string, arch string) string {
@@ -237,13 +255,16 @@ func osArchString(os string, arch string) string {
func (ct configurationType) String() string {
return map[configurationType]string{
- noConfig: "no_config",
- arch: "arch",
- os: "os",
- osArch: "arch_os",
- productVariables: "product_variables",
- osAndInApex: "os_in_apex",
- inApex: "in_apex",
+ noConfig: "no_config",
+ arch: "arch",
+ os: "os",
+ osArch: "arch_os",
+ productVariables: "product_variables",
+ osAndInApex: "os_in_apex",
+ inApex: "in_apex",
+ errorProneDisabled: "errorprone_disabled",
+ // TODO: b/294868620 - Remove when completing the bug
+ sanitizersEnabled: "sanitizers_enabled",
}[ct]
}
@@ -274,6 +295,15 @@ func (ct configurationType) validateConfig(config string) {
if _, ok := inApexMap[config]; !ok {
panic(fmt.Errorf("Unknown in_apex config: %s", config))
}
+ case errorProneDisabled:
+ if _, ok := errorProneMap[config]; !ok {
+ panic(fmt.Errorf("Unknown errorprone config: %s", config))
+ }
+ // TODO: b/294868620 - Remove when completing the bug
+ case sanitizersEnabled:
+ if _, ok := sanitizersEnabledMap[config]; !ok {
+ panic(fmt.Errorf("Unknown sanitizers_enabled config: %s", config))
+ }
default:
panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
}
@@ -303,6 +333,11 @@ func (ca ConfigurationAxis) SelectKey(config string) string {
return config
case inApex:
return inApexMap[config]
+ case errorProneDisabled:
+ return errorProneMap[config]
+ // TODO: b/294868620 - Remove when completing the bug
+ case sanitizersEnabled:
+ return sanitizersEnabledMap[config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
}
@@ -321,6 +356,11 @@ var (
OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
// An axis for in_apex-specific configurations
InApexAxis = ConfigurationAxis{configurationType: inApex}
+
+ ErrorProneAxis = ConfigurationAxis{configurationType: errorProneDisabled}
+
+ // TODO: b/294868620 - Remove when completing the bug
+ SanitizersEnabledAxis = ConfigurationAxis{configurationType: sanitizersEnabled}
)
// ProductVariableConfigurationAxis returns an axis for the given product variable
diff --git a/bazel/properties.go b/bazel/properties.go
index e22f4dbe7..9c63bc04b 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -194,14 +194,7 @@ func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, Lab
// UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
// the slice in a sorted order.
func UniqueSortedBazelLabels(originalLabels []Label) []Label {
- uniqueLabelsSet := make(map[Label]bool)
- for _, l := range originalLabels {
- uniqueLabelsSet[l] = true
- }
- var uniqueLabels []Label
- for l, _ := range uniqueLabelsSet {
- uniqueLabels = append(uniqueLabels, l)
- }
+ uniqueLabels := FirstUniqueBazelLabels(originalLabels)
sort.SliceStable(uniqueLabels, func(i, j int) bool {
return uniqueLabels[i].Label < uniqueLabels[j].Label
})
@@ -210,13 +203,13 @@ func UniqueSortedBazelLabels(originalLabels []Label) []Label {
func FirstUniqueBazelLabels(originalLabels []Label) []Label {
var labels []Label
- found := make(map[Label]bool, len(originalLabels))
+ found := make(map[string]bool, len(originalLabels))
for _, l := range originalLabels {
- if _, ok := found[l]; ok {
+ if _, ok := found[l.Label]; ok {
continue
}
labels = append(labels, l)
- found[l] = true
+ found[l.Label] = true
}
return labels
}
@@ -288,6 +281,41 @@ func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
return result
}
+// FirstUniqueBazelLabelListAttribute takes a LabelListAttribute and makes the LabelList for
+// each axis/configuration by keeping the first instance of a Label and omitting all subsequent
+// repetitions.
+func FirstUniqueBazelLabelListAttribute(attr LabelListAttribute) LabelListAttribute {
+ var result LabelListAttribute
+ result.Value = FirstUniqueBazelLabelList(attr.Value)
+ if attr.HasConfigurableValues() {
+ result.ConfigurableValues = make(configurableLabelLists)
+ }
+ for axis, configToLabels := range attr.ConfigurableValues {
+ for c, l := range configToLabels {
+ result.SetSelectValue(axis, c, FirstUniqueBazelLabelList(l))
+ }
+ }
+
+ return result
+}
+
+// SubtractBazelLabelListAttribute subtract needle from haystack for LabelList in each
+// axis/configuration.
+func SubtractBazelLabelListAttribute(haystack LabelListAttribute, needle LabelListAttribute) LabelListAttribute {
+ var result LabelListAttribute
+ result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
+ if haystack.HasConfigurableValues() {
+ result.ConfigurableValues = make(configurableLabelLists)
+ }
+ for axis, configToLabels := range haystack.ConfigurableValues {
+ for haystackConfig, haystackLabels := range configToLabels {
+ result.SetSelectValue(axis, haystackConfig, SubtractBazelLabelList(haystackLabels, needle.SelectValue(axis, haystackConfig)))
+ }
+ }
+
+ return result
+}
+
type Attribute interface {
HasConfigurableValues() bool
}
@@ -398,7 +426,7 @@ func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string,
switch axis.configurationType {
case noConfig:
la.Value = &value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
if la.ConfigurableValues == nil {
la.ConfigurableValues = make(configurableLabels)
}
@@ -414,7 +442,7 @@ func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *La
switch axis.configurationType {
case noConfig:
return la.Value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
return la.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
@@ -484,7 +512,7 @@ func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, v
switch axis.configurationType {
case noConfig:
ba.Value = value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
if ba.ConfigurableValues == nil {
ba.ConfigurableValues = make(configurableBools)
}
@@ -631,7 +659,7 @@ func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool
switch axis.configurationType {
case noConfig:
return ba.Value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
if v, ok := ba.ConfigurableValues[axis][config]; ok {
return &v
} else {
@@ -766,7 +794,7 @@ func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config str
switch axis.configurationType {
case noConfig:
lla.Value = list
- case arch, os, osArch, productVariables, osAndInApex, inApex:
+ case arch, os, osArch, productVariables, osAndInApex, inApex, errorProneDisabled, sanitizersEnabled:
if lla.ConfigurableValues == nil {
lla.ConfigurableValues = make(configurableLabelLists)
}
@@ -782,7 +810,7 @@ func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string
switch axis.configurationType {
case noConfig:
return lla.Value
- case arch, os, osArch, productVariables, osAndInApex, inApex:
+ case arch, os, osArch, productVariables, osAndInApex, inApex, errorProneDisabled, sanitizersEnabled:
return lla.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
@@ -1140,7 +1168,7 @@ func (sa *StringAttribute) SetSelectValue(axis ConfigurationAxis, config string,
switch axis.configurationType {
case noConfig:
sa.Value = str
- case arch, os, osArch, productVariables:
+ case arch, os, osArch, productVariables, sanitizersEnabled:
if sa.ConfigurableValues == nil {
sa.ConfigurableValues = make(configurableStrings)
}
@@ -1156,7 +1184,7 @@ func (sa *StringAttribute) SelectValue(axis ConfigurationAxis, config string) *s
switch axis.configurationType {
case noConfig:
return sa.Value
- case arch, os, osArch, productVariables:
+ case arch, os, osArch, productVariables, sanitizersEnabled:
if v, ok := sa.ConfigurableValues[axis][config]; ok {
return v
} else {
@@ -1346,7 +1374,7 @@ func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config st
switch axis.configurationType {
case noConfig:
sla.Value = list
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, errorProneDisabled, sanitizersEnabled:
if sla.ConfigurableValues == nil {
sla.ConfigurableValues = make(configurableStringLists)
}
@@ -1362,7 +1390,7 @@ func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config strin
switch axis.configurationType {
case noConfig:
return sla.Value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, errorProneDisabled, sanitizersEnabled:
return sla.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index c56d11f3f..751cb8b30 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -33,8 +33,12 @@ func TestUniqueBazelLabels(t *testing.T) {
{Label: "b"},
{Label: "a"},
{Label: "c"},
+ // namespaces
+ {Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
+ {Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when reference from root namespace
},
expectedUniqueLabels: []Label{
+ {Label: "//foo:bar", OriginalModuleName: "bar"},
{Label: "a"},
{Label: "b"},
{Label: "c"},
@@ -125,6 +129,63 @@ func TestSubtractBazelLabelList(t *testing.T) {
}
}
}
+
+func TestSubtractBazelLabelListAttribute(t *testing.T) {
+ testCases := []struct {
+ haystack LabelListAttribute
+ needle LabelListAttribute
+ expected LabelListAttribute
+ }{
+ {
+ haystack: LabelListAttribute{
+ Value: makeLabelList(
+ []string{"a", "b", "a", "c"},
+ []string{"x", "x", "y", "z"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{"arm_1", "arm_2"}, []string{}),
+ "x86": makeLabelList([]string{"x86_3", "x86_4", "x86_5"}, []string{"x86_5"}),
+ },
+ },
+ },
+ needle: LabelListAttribute{
+ Value: makeLabelList(
+ []string{"d", "a"},
+ []string{"x", "y2", "z2"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{"arm_1", "arm_3"}, []string{}),
+ "x86": makeLabelList([]string{"x86_3", "x86_4"}, []string{"x86_6"}),
+ },
+ },
+ },
+ expected: LabelListAttribute{
+ Value: makeLabelList(
+ []string{"b", "c"},
+ []string{"x", "x", "y", "z"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{"arm_2"}, []string{}),
+ "x86": makeLabelList([]string{"x86_5"}, []string{"x86_5"}),
+ },
+ },
+ ForceSpecifyEmptyList: false,
+ EmitEmptyList: false,
+ Prepend: false,
+ },
+ },
+ }
+ for _, tc := range testCases {
+ got := SubtractBazelLabelListAttribute(tc.haystack, tc.needle)
+ if !reflect.DeepEqual(tc.expected, got) {
+ t.Fatalf("Expected\n%v, but got\n%v", tc.expected, got)
+ }
+ }
+}
+
func TestFirstUniqueBazelLabelList(t *testing.T) {
testCases := []struct {
originalLabelList LabelList
@@ -137,6 +198,9 @@ func TestFirstUniqueBazelLabelList(t *testing.T) {
{Label: "b"},
{Label: "a"},
{Label: "c"},
+ // namespaces
+ {Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
+ {Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when referenced from root namespace
},
Excludes: []Label{
{Label: "x"},
@@ -150,6 +214,7 @@ func TestFirstUniqueBazelLabelList(t *testing.T) {
{Label: "a"},
{Label: "b"},
{Label: "c"},
+ {Label: "//foo:bar", OriginalModuleName: "bar"},
},
Excludes: []Label{
{Label: "x"},
@@ -167,6 +232,46 @@ func TestFirstUniqueBazelLabelList(t *testing.T) {
}
}
+func TestFirstUniqueBazelLabelListAttribute(t *testing.T) {
+ testCases := []struct {
+ originalLabelList LabelListAttribute
+ expectedUniqueLabelList LabelListAttribute
+ }{
+ {
+ originalLabelList: LabelListAttribute{
+ Value: makeLabelList(
+ []string{"a", "b", "a", "c"},
+ []string{"x", "x", "y", "z"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{"1", "2", "1"}, []string{}),
+ "x86": makeLabelList([]string{"3", "4", "4"}, []string{"5", "5"}),
+ },
+ },
+ },
+ expectedUniqueLabelList: LabelListAttribute{
+ Value: makeLabelList(
+ []string{"a", "b", "c"},
+ []string{"x", "y", "z"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{"1", "2"}, []string{}),
+ "x86": makeLabelList([]string{"3", "4"}, []string{"5"}),
+ },
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabelList := FirstUniqueBazelLabelListAttribute(tc.originalLabelList)
+ if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
+ }
+ }
+}
+
func TestUniqueSortedBazelLabelList(t *testing.T) {
testCases := []struct {
originalLabelList LabelList
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 782a88c72..4a3786feb 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@ bootstrap_go_package {
"testing.go",
],
deps: [
+ "blueprint-bootstrap",
"soong-aidl-library",
"soong-android",
"soong-android-allowlists",
@@ -37,6 +38,7 @@ bootstrap_go_package {
"soong-ui-metrics",
],
testSrcs: [
+ "go_conversion_test.go",
"aar_conversion_test.go",
"aidl_library_conversion_test.go",
"android_app_certificate_conversion_test.go",
@@ -44,6 +46,7 @@ bootstrap_go_package {
"apex_conversion_test.go",
"apex_key_conversion_test.go",
"build_conversion_test.go",
+ "bp2build_product_config_test.go",
"bzl_conversion_test.go",
"cc_binary_conversion_test.go",
"cc_library_conversion_test.go",
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 7f7aa6a3a..8ed94b498 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -40,6 +40,7 @@ func TestMinimalAndroidApp(t *testing.T) {
"app.java": "",
"res/res.png": "",
"AndroidManifest.xml": "",
+ "assets/asset.png": "",
},
Blueprint: `
android_app {
@@ -54,6 +55,8 @@ android_app {
"manifest": `"AndroidManifest.xml"`,
"resource_files": `["res/res.png"]`,
"sdk_version": `"current"`,
+ "assets": `["assets/asset.png"]`,
+ "assets_dir": `"assets"`,
}),
}})
}
@@ -68,6 +71,7 @@ func TestAndroidAppAllSupportedFields(t *testing.T) {
"resa/res.png": "",
"resb/res.png": "",
"manifest/AndroidManifest.xml": "",
+ "assets_/asset.png": "",
},
Blueprint: simpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + `
android_app {
@@ -81,6 +85,7 @@ android_app {
java_version: "7",
certificate: "foocert",
required: ["static_lib_dep"],
+ asset_dirs: ["assets_"],
}
`,
ExpectedBazelTargets: []string{
@@ -91,6 +96,8 @@ android_app {
"resa/res.png",
"resb/res.png",
]`,
+ "assets": `["assets_/asset.png"]`,
+ "assets_dir": `"assets_"`,
"custom_package": `"com.google"`,
"deps": `[":static_lib_dep"]`,
"java_version": `"7"`,
@@ -349,7 +356,7 @@ android_app {
}})
}
-func TestAndroidAppMinSdkProvided(t *testing.T) {
+func TestAndroidAppManifestSdkVersionsProvided(t *testing.T) {
runAndroidAppTestCase(t, Bp2buildTestCase{
Description: "Android app with value for min_sdk_version",
ModuleTypeUnderTest: "android_app",
@@ -359,7 +366,9 @@ func TestAndroidAppMinSdkProvided(t *testing.T) {
android_app {
name: "foo",
sdk_version: "current",
- min_sdk_version: "24",
+ min_sdk_version: "24",
+ max_sdk_version: "30",
+ target_sdk_version: "29",
}
`,
ExpectedBazelTargets: []string{
@@ -367,14 +376,16 @@ android_app {
"manifest": `"AndroidManifest.xml"`,
"resource_files": `[]`,
"manifest_values": `{
+ "maxSdkVersion": "30",
"minSdkVersion": "24",
+ "targetSdkVersion": "29",
}`,
"sdk_version": `"current"`,
}),
}})
}
-func TestAndroidAppMinSdkDefaultToSdkVersion(t *testing.T) {
+func TestAndroidAppMinAndTargetSdkDefaultToSdkVersion(t *testing.T) {
runAndroidAppTestCase(t, Bp2buildTestCase{
Description: "Android app with value for sdk_version",
ModuleTypeUnderTest: "android_app",
@@ -392,6 +403,7 @@ android_app {
"resource_files": `[]`,
"manifest_values": `{
"minSdkVersion": "30",
+ "targetSdkVersion": "30",
}`,
"sdk_version": `"30"`,
}),
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 84c7ea2e3..238324761 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -1555,7 +1555,7 @@ override_apex {
"file_contexts": `":foo-file_contexts"`,
"manifest": `"apex_manifest.json"`,
"min_sdk_version": `select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": "30",
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "30",
"//conditions:default": "31",
})`,
"package_name": `"pkg_name"`,
@@ -1564,7 +1564,7 @@ override_apex {
"file_contexts": `":foo-file_contexts"`,
"manifest": `"apex_manifest.json"`,
"min_sdk_version": `select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": "30",
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "30",
"//conditions:default": "31",
})`,
"package_name": `"override_pkg_name"`,
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index b22cb2861..5f7b382f0 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -15,7 +15,6 @@
package bp2build
import (
- "android/soong/starlark_import"
"fmt"
"os"
"path/filepath"
@@ -24,6 +23,7 @@ import (
"android/soong/android"
"android/soong/bazel"
"android/soong/shared"
+ "android/soong/starlark_import"
)
func deleteFilesExcept(ctx *CodegenContext, rootOutputPath android.OutputPath, except []BazelFile) {
@@ -67,6 +67,8 @@ func deleteFilesExcept(ctx *CodegenContext, rootOutputPath android.OutputPath, e
// writing .bzl files that are equivalent to Android.bp files that are capable
// of being built with Bazel.
func Codegen(ctx *CodegenContext) *CodegenMetrics {
+ ctx.Context().BeginEvent("Codegen")
+ defer ctx.Context().EndEvent("Codegen")
// This directory stores BUILD files that could be eventually checked-in.
bp2buildDir := android.PathForOutput(ctx, "bp2build")
@@ -79,7 +81,16 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics {
fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n"))
os.Exit(1)
}
- bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode)
+ var bp2buildFiles []BazelFile
+ ctx.Context().EventHandler.Do("CreateBazelFile", func() {
+ bp2buildFiles = CreateBazelFiles(nil, res.buildFileToTargets, ctx.mode)
+ })
+ injectionFiles, additionalBp2buildFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
+ if err != nil {
+ fmt.Printf("%s\n", err.Error())
+ os.Exit(1)
+ }
+ bp2buildFiles = append(bp2buildFiles, additionalBp2buildFiles...)
writeFiles(ctx, bp2buildDir, bp2buildFiles)
// Delete files under the bp2build root which weren't just written. An
// alternative would have been to delete the whole directory and write these
@@ -88,11 +99,6 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics {
// performance implications.
deleteFilesExcept(ctx, bp2buildDir, bp2buildFiles)
- injectionFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
- if err != nil {
- fmt.Printf("%s\n", err.Error())
- os.Exit(1)
- }
writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles)
starlarkDeps, err := starlark_import.GetNinjaDeps()
if err != nil {
@@ -107,20 +113,20 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics {
// This includes
// 1. config value(s) that are hardcoded in Soong
// 2. product_config variables
-func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, error) {
+func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
var ret []BazelFile
- productConfigFiles, err := CreateProductConfigFiles(ctx)
+ productConfigInjectionFiles, productConfigBp2BuildDirFiles, err := CreateProductConfigFiles(ctx, metrics)
if err != nil {
- return nil, err
+ return nil, nil, err
}
- ret = append(ret, productConfigFiles...)
+ ret = append(ret, productConfigInjectionFiles...)
injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics)
if err != nil {
- return nil, err
+ return nil, nil, err
}
- ret = append(ret, injectionFiles...)
- return ret, nil
+ ret = append(injectionFiles, ret...)
+ return ret, productConfigBp2BuildDirFiles, nil
}
// Get the output directory and create it if it doesn't exist.
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 72244961d..e8c2ef7e0 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -1,14 +1,23 @@
package bp2build
import (
+ "android/soong/android"
+ "android/soong/android/soongconfig"
+ "android/soong/starlark_import"
+ "encoding/json"
"fmt"
"os"
"path/filepath"
+ "reflect"
"strings"
+
+ "github.com/google/blueprint/proptools"
+ "go.starlark.net/starlark"
)
func CreateProductConfigFiles(
- ctx *CodegenContext) ([]BazelFile, error) {
+ ctx *CodegenContext,
+ metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
cfg := &ctx.config
targetProduct := "unknown"
if cfg.HasDeviceProduct() {
@@ -25,9 +34,14 @@ func CreateProductConfigFiles(
if !strings.HasPrefix(productVariablesFileName, "/") {
productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
}
- bytes, err := os.ReadFile(productVariablesFileName)
+ productVariablesBytes, err := os.ReadFile(productVariablesFileName)
+ if err != nil {
+ return nil, nil, err
+ }
+ productVariables := android.ProductVariables{}
+ err = json.Unmarshal(productVariablesBytes, &productVariables)
if err != nil {
- return nil, err
+ return nil, nil, err
}
// TODO(b/249685973): the name is product_config_platforms because product_config
@@ -39,11 +53,29 @@ func CreateProductConfigFiles(
"{VARIANT}", targetBuildVariant,
"{PRODUCT_FOLDER}", currentProductFolder)
- result := []BazelFile{
+ platformMappingContent, err := platformMappingContent(
+ productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"),
+ &productVariables,
+ ctx.Config().Bp2buildSoongConfigDefinitions,
+ metrics.convertedModulePathMap)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ productsForTestingMap, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
+ if err != nil {
+ return nil, nil, err
+ }
+ productsForTesting := android.SortedKeys(productsForTestingMap)
+ for i := range productsForTesting {
+ productsForTesting[i] = fmt.Sprintf(" \"@//build/bazel/tests/products:%s\",", productsForTesting[i])
+ }
+
+ injectionDirFiles := []BazelFile{
newFile(
currentProductFolder,
"soong.variables.bzl",
- `variables = json.decode("""`+strings.ReplaceAll(string(bytes), "\\", "\\\\")+`""")`),
+ `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
newFile(
currentProductFolder,
"BUILD",
@@ -80,6 +112,7 @@ load("@//build/bazel/product_config:android_product.bzl", "android_product")
android_product(
name = "mixed_builds_product-{VARIANT}",
soong_variables = _soong_variables,
+ extra_constraints = ["@//build/bazel/platforms:mixed_builds"],
)
`)),
newFile(
@@ -92,16 +125,17 @@ android_product(
# currently lunched product, they should all be listed here
product_labels = [
"@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}",
- "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"
-]
-`)),
+ "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
+`)+strings.Join(productsForTesting, "\n")+"\n]\n"),
newFile(
"product_config_platforms",
"common.bazelrc",
productReplacer.Replace(`
+build --platform_mappings=platform_mappings
build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
+build:linux_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86
build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
@@ -120,6 +154,247 @@ build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_lin
build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
`)),
}
+ bp2buildDirFiles := []BazelFile{
+ newFile(
+ "",
+ "platform_mappings",
+ platformMappingContent),
+ }
+ return injectionDirFiles, bp2buildDirFiles, nil
+}
+
+func platformMappingContent(
+ mainProductLabel string,
+ mainProductVariables *android.ProductVariables,
+ soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
+ convertedModulePathMap map[string]string) (string, error) {
+ productsForTesting, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
+ if err != nil {
+ return "", err
+ }
+ var result strings.Builder
+
+ mergedConvertedModulePathMap := make(map[string]string)
+ for k, v := range convertedModulePathMap {
+ mergedConvertedModulePathMap[k] = v
+ }
+ additionalModuleNamesToPackages, err := starlark_import.GetStarlarkValue[map[string]string]("additional_module_names_to_packages")
+ if err != nil {
+ return "", err
+ }
+ for k, v := range additionalModuleNamesToPackages {
+ mergedConvertedModulePathMap[k] = v
+ }
+
+ result.WriteString("platforms:\n")
+ platformMappingSingleProduct(mainProductLabel, mainProductVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
+ for product, productVariablesStarlark := range productsForTesting {
+ productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
+ if err != nil {
+ return "", err
+ }
+ platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
+ }
+ return result.String(), nil
+}
+
+var bazelPlatformSuffixes = []string{
+ "",
+ "_darwin_arm64",
+ "_darwin_x86_64",
+ "_linux_bionic_arm64",
+ "_linux_bionic_x86_64",
+ "_linux_musl_x86",
+ "_linux_musl_x86_64",
+ "_linux_x86",
+ "_linux_x86_64",
+ "_windows_x86",
+ "_windows_x86_64",
+}
+
+func platformMappingSingleProduct(
+ label string,
+ productVariables *android.ProductVariables,
+ soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
+ convertedModulePathMap map[string]string,
+ result *strings.Builder) {
+ targetBuildVariant := "user"
+ if proptools.Bool(productVariables.Eng) {
+ targetBuildVariant = "eng"
+ } else if proptools.Bool(productVariables.Debuggable) {
+ targetBuildVariant = "userdebug"
+ }
+
+ platform_sdk_version := -1
+ if productVariables.Platform_sdk_version != nil {
+ platform_sdk_version = *productVariables.Platform_sdk_version
+ }
+
+ defaultAppCertificateFilegroup := "//build/bazel/utils:empty_filegroup"
+ if proptools.String(productVariables.DefaultAppCertificate) != "" {
+ defaultAppCertificateFilegroup = "@//" + filepath.Dir(proptools.String(productVariables.DefaultAppCertificate)) + ":android_certificate_directory"
+ }
+
+ for _, suffix := range bazelPlatformSuffixes {
+ result.WriteString(" ")
+ result.WriteString(label)
+ result.WriteString(suffix)
+ result.WriteString("\n")
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:always_use_prebuilt_sdks=%t\n", proptools.Bool(productVariables.Always_use_prebuilt_sdks)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:arc=%t\n", proptools.Bool(productVariables.Arc)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:binder32bit=%t\n", proptools.Bool(productVariables.Binder32bit)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_from_text_stub=%t\n", proptools.Bool(productVariables.Build_from_text_stub)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_id=%s\n", proptools.String(productVariables.BuildId)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_version_tags=%s\n", strings.Join(productVariables.BuildVersionTags, ",")))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ",")))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ",")))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:compressed_apex=%t\n", proptools.Bool(productVariables.CompressedApex)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:debuggable=%t\n", proptools.Bool(productVariables.Debuggable)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate=%s\n", proptools.String(productVariables.DefaultAppCertificate)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate_filegroup=%s\n", defaultAppCertificateFilegroup))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ",")))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_max_page_size_supported=%s\n", proptools.String(productVariables.DeviceMaxPageSizeSupported)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_name=%s\n", proptools.String(productVariables.DeviceName)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_page_size_agnostic=%t\n", proptools.Bool(productVariables.DevicePageSizeAgnostic)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_product=%s\n", proptools.String(productVariables.DeviceProduct)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enforce_vintf_manifest=%t\n", proptools.Bool(productVariables.Enforce_vintf_manifest)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:eng=%t\n", proptools.Bool(productVariables.Eng)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_pattern_fill_contents=%t\n", proptools.Bool(productVariables.Malloc_pattern_fill_contents)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_zero_contents=%t\n", proptools.Bool(productVariables.Malloc_zero_contents)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:manifest_package_name_overrides=%s\n", strings.Join(productVariables.ManifestPackageNameOverrides, ",")))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:native_coverage=%t\n", proptools.Bool(productVariables.Native_coverage)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_brand=%s\n", productVariables.ProductBrand))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_manufacturer=%s\n", productVariables.ProductManufacturer))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_sdk_version=%d\n", platform_sdk_version))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:safestack=%t\n", proptools.Bool(productVariables.Safestack)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:target_build_variant=%s\n", targetBuildVariant))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:treble_linker_namespaces=%t\n", proptools.Bool(productVariables.Treble_linker_namespaces)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:tidy_checks=%s\n", proptools.String(productVariables.TidyChecks)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:uml=%t\n", proptools.Bool(productVariables.Uml)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build=%t\n", proptools.Bool(productVariables.Unbundled_build)))
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build_apps=%s\n", strings.Join(productVariables.Unbundled_build_apps, ",")))
+
+ for _, override := range productVariables.CertificateOverrides {
+ parts := strings.SplitN(override, ":", 2)
+ if apexPath, ok := convertedModulePathMap[parts[0]]; ok {
+ if overrideCertPath, ok := convertedModulePathMap[parts[1]]; ok {
+ result.WriteString(fmt.Sprintf(" --%s:%s_certificate_override=%s:%s\n", apexPath, parts[0], overrideCertPath, parts[1]))
+ }
+ }
+ }
+
+ for namespace, namespaceContents := range productVariables.VendorVars {
+ for variable, value := range namespaceContents {
+ key := namespace + "__" + variable
+ _, hasBool := soongConfigDefinitions.BoolVars[key]
+ _, hasString := soongConfigDefinitions.StringVars[key]
+ _, hasValue := soongConfigDefinitions.ValueVars[key]
+ if !hasBool && !hasString && !hasValue {
+ // Not all soong config variables are defined in Android.bp files. For example,
+ // prebuilt_bootclasspath_fragment uses soong config variables in a nonstandard
+ // way, that causes them to be present in the soong.variables file but not
+ // defined in an Android.bp file. There's also nothing stopping you from setting
+ // a variable in make that doesn't exist in soong. We only generate build
+ // settings for the ones that exist in soong, so skip all others.
+ continue
+ }
+ if hasBool && hasString || hasBool && hasValue || hasString && hasValue {
+ panic(fmt.Sprintf("Soong config variable %s:%s appears to be of multiple types. bool? %t, string? %t, value? %t", namespace, variable, hasBool, hasString, hasValue))
+ }
+ if hasBool {
+ // Logic copied from soongConfig.Bool()
+ value = strings.ToLower(value)
+ if value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" {
+ value = "true"
+ } else {
+ value = "false"
+ }
+ }
+ result.WriteString(fmt.Sprintf(" --//build/bazel/product_config/soong_config_variables:%s=%s\n", strings.ToLower(key), value))
+ }
+ }
+ }
+}
+
+func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) {
+ result := android.ProductVariables{}
+ productVarsReflect := reflect.ValueOf(&result).Elem()
+ for i := 0; i < productVarsReflect.NumField(); i++ {
+ field := productVarsReflect.Field(i)
+ fieldType := productVarsReflect.Type().Field(i)
+ name := fieldType.Name
+ if name == "BootJars" || name == "ApexBootJars" || name == "VendorSnapshotModules" ||
+ name == "RecoverySnapshotModules" {
+ // These variables have more complicated types, and we don't need them right now
+ continue
+ }
+ if _, ok := in[name]; ok {
+ if name == "VendorVars" {
+ vendorVars, err := starlark_import.Unmarshal[map[string]map[string]string](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.Set(reflect.ValueOf(vendorVars))
+ continue
+ }
+ switch field.Type().Kind() {
+ case reflect.Bool:
+ val, err := starlark_import.Unmarshal[bool](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.SetBool(val)
+ case reflect.String:
+ val, err := starlark_import.Unmarshal[string](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.SetString(val)
+ case reflect.Slice:
+ if field.Type().Elem().Kind() != reflect.String {
+ return result, fmt.Errorf("slices of types other than strings are unimplemented")
+ }
+ val, err := starlark_import.UnmarshalReflect(in[name], field.Type())
+ if err != nil {
+ return result, err
+ }
+ field.Set(val)
+ case reflect.Pointer:
+ switch field.Type().Elem().Kind() {
+ case reflect.Bool:
+ val, err := starlark_import.UnmarshalNoneable[bool](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.Set(reflect.ValueOf(val))
+ case reflect.String:
+ val, err := starlark_import.UnmarshalNoneable[string](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.Set(reflect.ValueOf(val))
+ case reflect.Int:
+ val, err := starlark_import.UnmarshalNoneable[int](in[name])
+ if err != nil {
+ return result, err
+ }
+ field.Set(reflect.ValueOf(val))
+ default:
+ return result, fmt.Errorf("pointers of types other than strings/bools are unimplemented: %s", field.Type().Elem().Kind().String())
+ }
+ default:
+ return result, fmt.Errorf("unimplemented type: %s", field.Type().String())
+ }
+ }
+ }
+
+ result.Native_coverage = proptools.BoolPtr(
+ proptools.Bool(result.GcovCoverage) ||
+ proptools.Bool(result.ClangCoverage))
return result, nil
}
diff --git a/bp2build/bp2build_product_config_test.go b/bp2build/bp2build_product_config_test.go
new file mode 100644
index 000000000..02d83b4d1
--- /dev/null
+++ b/bp2build/bp2build_product_config_test.go
@@ -0,0 +1,89 @@
+package bp2build
+
+import (
+ "android/soong/android"
+ "android/soong/starlark_import"
+ "encoding/json"
+ "reflect"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+ "go.starlark.net/starlark"
+)
+
+func createStarlarkValue(t *testing.T, code string) starlark.Value {
+ t.Helper()
+ result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, nil)
+ if err != nil {
+ t.Error(err)
+ }
+ return result["x"]
+}
+
+func createStarlarkProductVariablesMap(t *testing.T, code string) map[string]starlark.Value {
+ t.Helper()
+ rawValue := createStarlarkValue(t, code)
+ value, err := starlark_import.Unmarshal[map[string]starlark.Value](rawValue)
+ if err != nil {
+ t.Error(err)
+ }
+ return value
+}
+
+func TestStarlarkMapToProductVariables(t *testing.T) {
+ thirty := 30
+ cases := []struct {
+ starlark string
+ result android.ProductVariables
+ }{
+ {
+ starlark: `{"CompressedApex": True}`,
+ result: android.ProductVariables{CompressedApex: proptools.BoolPtr(true)},
+ },
+ {
+ starlark: `{"ApexGlobalMinSdkVersionOverride": "Tiramisu"}`,
+ result: android.ProductVariables{ApexGlobalMinSdkVersionOverride: proptools.StringPtr("Tiramisu")},
+ },
+ {
+ starlark: `{"ProductManufacturer": "Google"}`,
+ result: android.ProductVariables{ProductManufacturer: "Google"},
+ },
+ {
+ starlark: `{"Unbundled_build_apps": ["app1", "app2"]}`,
+ result: android.ProductVariables{Unbundled_build_apps: []string{"app1", "app2"}},
+ },
+ {
+ starlark: `{"Platform_sdk_version": 30}`,
+ result: android.ProductVariables{Platform_sdk_version: &thirty},
+ },
+ {
+ starlark: `{"HostFakeSnapshotEnabled": True}`,
+ result: android.ProductVariables{HostFakeSnapshotEnabled: true},
+ },
+ }
+
+ for _, testCase := range cases {
+ productVariables, err := starlarkMapToProductVariables(createStarlarkProductVariablesMap(t,
+ testCase.starlark))
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ testCase.result.Native_coverage = proptools.BoolPtr(false)
+ if !reflect.DeepEqual(testCase.result, productVariables) {
+ expected, err := json.Marshal(testCase.result)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ actual, err := json.Marshal(productVariables)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ expectedStr := string(expected)
+ actualStr := string(actual)
+ t.Errorf("expected %q, but got %q", expectedStr, actualStr)
+ }
+ }
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 46a5bd8cb..cd1bc7f19 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -29,7 +29,9 @@ import (
"android/soong/bazel"
"android/soong/starlark_fmt"
"android/soong/ui/metrics/bp2build_metrics_proto"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
)
@@ -93,16 +95,16 @@ func (targets BazelTargets) sort() {
// statements (use LoadStatements for that), since the targets are usually not
// adjacent to the load statements at the top of the BUILD file.
func (targets BazelTargets) String() string {
- var res string
+ var res strings.Builder
for i, target := range targets {
if target.ruleClass != "package" {
- res += target.content
+ res.WriteString(target.content)
}
if i != len(targets)-1 {
- res += "\n\n"
+ res.WriteString("\n\n")
}
}
- return res
+ return res.String()
}
// LoadStatements return the string representation of the sorted and deduplicated
@@ -252,7 +254,408 @@ func (r conversionResults) BuildDirToTargets() map[string]BazelTargets {
return r.buildFileToTargets
}
+// struct to store state of go bazel targets
+// this implements bp2buildModule interface and is passed to generateBazelTargets
+type goBazelTarget struct {
+ targetName string
+ targetPackage string
+ bazelRuleClass string
+ bazelRuleLoadLocation string
+ bazelAttributes []interface{}
+}
+
+var _ bp2buildModule = (*goBazelTarget)(nil)
+
+func (g goBazelTarget) TargetName() string {
+ return g.targetName
+}
+
+func (g goBazelTarget) TargetPackage() string {
+ return g.targetPackage
+}
+
+func (g goBazelTarget) BazelRuleClass() string {
+ return g.bazelRuleClass
+}
+
+func (g goBazelTarget) BazelRuleLoadLocation() string {
+ return g.bazelRuleLoadLocation
+}
+
+func (g goBazelTarget) BazelAttributes() []interface{} {
+ return g.bazelAttributes
+}
+
+// Creates a target_compatible_with entry that is *not* compatible with android
+func targetNotCompatibleWithAndroid() bazel.LabelListAttribute {
+ ret := bazel.LabelListAttribute{}
+ ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid,
+ bazel.MakeLabelList(
+ []bazel.Label{
+ bazel.Label{
+ Label: "@platforms//:incompatible",
+ },
+ },
+ ),
+ )
+ return ret
+}
+
+// helper function to return labels for srcs used in bootstrap_go_package and bootstrap_go_binary
+// this function has the following limitations which make it unsuitable for widespread use
+// - wildcard patterns in srcs
+// This is ok for go since build/blueprint does not support it.
+//
+// Prefer to use `BazelLabelForModuleSrc` instead
+func goSrcLabels(cfg android.Config, moduleDir string, srcs []string, linuxSrcs, darwinSrcs []string) bazel.LabelListAttribute {
+ labels := func(srcs []string) bazel.LabelList {
+ ret := []bazel.Label{}
+ for _, src := range srcs {
+ srcLabel := bazel.Label{
+ Label: src,
+ }
+ ret = append(ret, srcLabel)
+ }
+ // Respect package boundaries
+ return android.TransformSubpackagePaths(
+ cfg,
+ moduleDir,
+ bazel.MakeLabelList(ret),
+ )
+ }
+
+ ret := bazel.LabelListAttribute{}
+ // common
+ ret.SetSelectValue(bazel.NoConfigAxis, "", labels(srcs))
+ // linux
+ ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsLinux, labels(linuxSrcs))
+ // darwin
+ ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsDarwin, labels(darwinSrcs))
+ return ret
+}
+
+func goDepLabels(deps []string, goModulesMap nameToGoLibraryModule) bazel.LabelListAttribute {
+ labels := []bazel.Label{}
+ for _, dep := range deps {
+ moduleDir := goModulesMap[dep].Dir
+ if moduleDir == "." {
+ moduleDir = ""
+ }
+ label := bazel.Label{
+ Label: fmt.Sprintf("//%s:%s", moduleDir, dep),
+ }
+ labels = append(labels, label)
+ }
+ return bazel.MakeLabelListAttribute(bazel.MakeLabelList(labels))
+}
+
+// attributes common to blueprint_go_binary and bootstap_go_package
+type goAttributes struct {
+ Importpath bazel.StringAttribute
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Data bazel.LabelListAttribute
+ Target_compatible_with bazel.LabelListAttribute
+
+ // attributes for the dynamically generated go_test target
+ Embed bazel.LabelListAttribute
+}
+
+type goTestProperties struct {
+ name string
+ dir string
+ testSrcs []string
+ linuxTestSrcs []string
+ darwinTestSrcs []string
+ testData []string
+ // Name of the target that should be compiled together with the test
+ embedName string
+}
+
+// Creates a go_test target for bootstrap_go_package / blueprint_go_binary
+func generateBazelTargetsGoTest(ctx *android.Context, goModulesMap nameToGoLibraryModule, gp goTestProperties) (BazelTarget, error) {
+ ca := android.CommonAttributes{
+ Name: gp.name,
+ }
+ ga := goAttributes{
+ Srcs: goSrcLabels(ctx.Config(), gp.dir, gp.testSrcs, gp.linuxTestSrcs, gp.darwinTestSrcs),
+ Data: goSrcLabels(ctx.Config(), gp.dir, gp.testData, []string{}, []string{}),
+ Embed: bazel.MakeLabelListAttribute(
+ bazel.MakeLabelList(
+ []bazel.Label{bazel.Label{Label: ":" + gp.embedName}},
+ ),
+ ),
+ Target_compatible_with: targetNotCompatibleWithAndroid(),
+ }
+
+ libTest := goBazelTarget{
+ targetName: gp.name,
+ targetPackage: gp.dir,
+ bazelRuleClass: "go_test",
+ bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+ bazelAttributes: []interface{}{&ca, &ga},
+ }
+ return generateBazelTarget(ctx, libTest)
+}
+
+// TODO - b/288491147: testSrcs of certain bootstrap_go_package/blueprint_go_binary are not hermetic and depend on
+// testdata checked into the filesystem.
+// Denylist the generation of go_test targets for these Soong modules.
+// The go_library/go_binary will still be generated, since those are hermitic.
+var (
+ goTestsDenylist = []string{
+ "android-archive-zip",
+ "bazel_notice_gen",
+ "blueprint-bootstrap-bpdoc",
+ "blueprint-microfactory",
+ "blueprint-pathtools",
+ "bssl_ar",
+ "compliance_checkmetadata",
+ "compliance_checkshare",
+ "compliance_dumpgraph",
+ "compliance_dumpresolutions",
+ "compliance_listshare",
+ "compliance-module",
+ "compliancenotice_bom",
+ "compliancenotice_shippedlibs",
+ "compliance_rtrace",
+ "compliance_sbom",
+ "golang-protobuf-internal-fuzz-jsonfuzz",
+ "golang-protobuf-internal-fuzz-textfuzz",
+ "golang-protobuf-internal-fuzz-wirefuzz",
+ "htmlnotice",
+ "protoc-gen-go",
+ "rbcrun-module",
+ "spdx-tools-builder",
+ "spdx-tools-builder2v1",
+ "spdx-tools-builder2v2",
+ "spdx-tools-builder2v3",
+ "spdx-tools-idsearcher",
+ "spdx-tools-spdx-json",
+ "spdx-tools-utils",
+ "soong-ui-build",
+ "textnotice",
+ "xmlnotice",
+ }
+)
+
+func testOfGoPackageIsIncompatible(g *bootstrap.GoPackage) bool {
+ return android.InList(g.Name(), goTestsDenylist) ||
+ // Denylist tests of soong_build
+ // Theses tests have a guard that prevent usage outside a test environment
+ // The guard (`ensureTestOnly`) looks for a `-test` in os.Args, which is present in soong's gotestrunner, but missing in `b test`
+ g.IsPluginFor("soong_build") ||
+ // soong-android is a dep of soong_build
+ // This dependency is created by soong_build by listing it in its deps explicitly in Android.bp, and not via `plugin_for` in `soong-android`
+ g.Name() == "soong-android"
+}
+
+func testOfGoBinaryIsIncompatible(g *bootstrap.GoBinary) bool {
+ return android.InList(g.Name(), goTestsDenylist)
+}
+
+func generateBazelTargetsGoPackage(ctx *android.Context, g *bootstrap.GoPackage, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
+ ca := android.CommonAttributes{
+ Name: g.Name(),
+ }
+
+ // For this bootstrap_go_package dep chain,
+ // A --> B --> C ( ---> depends on)
+ // Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
+ // Bazel OTOH
+ // 1. requires C to be listed in `deps` expllicity.
+ // 2. does not require C to be listed if src of A does not import C
+ //
+ // bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
+ transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
+
+ ga := goAttributes{
+ Importpath: bazel.StringAttribute{
+ Value: proptools.StringPtr(g.GoPkgPath()),
+ },
+ Srcs: goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
+ Deps: goDepLabels(
+ android.FirstUniqueStrings(transitiveDeps),
+ goModulesMap,
+ ),
+ Target_compatible_with: targetNotCompatibleWithAndroid(),
+ }
+
+ lib := goBazelTarget{
+ targetName: g.Name(),
+ targetPackage: ctx.ModuleDir(g),
+ bazelRuleClass: "go_library",
+ bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+ bazelAttributes: []interface{}{&ca, &ga},
+ }
+ retTargets := []BazelTarget{}
+ var retErrs []error
+ if libTarget, err := generateBazelTarget(ctx, lib); err == nil {
+ retTargets = append(retTargets, libTarget)
+ } else {
+ retErrs = []error{err}
+ }
+
+ // If the library contains test srcs, create an additional go_test target
+ if !testOfGoPackageIsIncompatible(g) && (len(g.TestSrcs()) > 0 || len(g.LinuxTestSrcs()) > 0 || len(g.DarwinTestSrcs()) > 0) {
+ gp := goTestProperties{
+ name: g.Name() + "-test",
+ dir: ctx.ModuleDir(g),
+ testSrcs: g.TestSrcs(),
+ linuxTestSrcs: g.LinuxTestSrcs(),
+ darwinTestSrcs: g.DarwinTestSrcs(),
+ testData: g.TestData(),
+ embedName: g.Name(), // embed the source go_library in the test so that its .go files are included in the compilation unit
+ }
+ if libTestTarget, err := generateBazelTargetsGoTest(ctx, goModulesMap, gp); err == nil {
+ retTargets = append(retTargets, libTestTarget)
+ } else {
+ retErrs = append(retErrs, err)
+ }
+ }
+
+ return retTargets, retErrs
+}
+
+type goLibraryModule struct {
+ Dir string
+ Deps []string
+}
+
+type nameToGoLibraryModule map[string]goLibraryModule
+
+// Visit each module in the graph
+// If a module is of type `bootstrap_go_package`, return a map containing metadata like its dir and deps
+func createGoLibraryModuleMap(ctx *android.Context) nameToGoLibraryModule {
+ ret := nameToGoLibraryModule{}
+ ctx.VisitAllModules(func(m blueprint.Module) {
+ moduleType := ctx.ModuleType(m)
+ // We do not need to store information about blueprint_go_binary since it does not have any rdeps
+ if moduleType == "bootstrap_go_package" {
+ ret[m.Name()] = goLibraryModule{
+ Dir: ctx.ModuleDir(m),
+ Deps: m.(*bootstrap.GoPackage).Deps(),
+ }
+ }
+ })
+ return ret
+}
+
+// Returns the deps in the transitive closure of a go target
+func transitiveGoDeps(directDeps []string, goModulesMap nameToGoLibraryModule) []string {
+ allDeps := directDeps
+ i := 0
+ for i < len(allDeps) {
+ curr := allDeps[i]
+ allDeps = append(allDeps, goModulesMap[curr].Deps...)
+ i += 1
+ }
+ allDeps = android.SortedUniqueStrings(allDeps)
+ return allDeps
+}
+
+func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
+ ca := android.CommonAttributes{
+ Name: g.Name(),
+ }
+
+ retTargets := []BazelTarget{}
+ var retErrs []error
+
+ // For this bootstrap_go_package dep chain,
+ // A --> B --> C ( ---> depends on)
+ // Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
+ // Bazel OTOH
+ // 1. requires C to be listed in `deps` expllicity.
+ // 2. does not require C to be listed if src of A does not import C
+ //
+ // bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
+ transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
+
+ goSource := ""
+ // If the library contains test srcs, create an additional go_test target
+ // The go_test target will embed a go_source containining the source .go files it tests
+ if !testOfGoBinaryIsIncompatible(g) && (len(g.TestSrcs()) > 0 || len(g.LinuxTestSrcs()) > 0 || len(g.DarwinTestSrcs()) > 0) {
+ // Create a go_source containing the source .go files of go_library
+ // This target will be an `embed` of the go_binary and go_test
+ goSource = g.Name() + "-source"
+ ca := android.CommonAttributes{
+ Name: goSource,
+ }
+ ga := goAttributes{
+ Srcs: goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
+ Deps: goDepLabels(transitiveDeps, goModulesMap),
+ Target_compatible_with: targetNotCompatibleWithAndroid(),
+ }
+ libTestSource := goBazelTarget{
+ targetName: goSource,
+ targetPackage: ctx.ModuleDir(g),
+ bazelRuleClass: "go_source",
+ bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+ bazelAttributes: []interface{}{&ca, &ga},
+ }
+ if libSourceTarget, err := generateBazelTarget(ctx, libTestSource); err == nil {
+ retTargets = append(retTargets, libSourceTarget)
+ } else {
+ retErrs = append(retErrs, err)
+ }
+
+ // Create a go_test target
+ gp := goTestProperties{
+ name: g.Name() + "-test",
+ dir: ctx.ModuleDir(g),
+ testSrcs: g.TestSrcs(),
+ linuxTestSrcs: g.LinuxTestSrcs(),
+ darwinTestSrcs: g.DarwinTestSrcs(),
+ testData: g.TestData(),
+ // embed the go_source in the test
+ embedName: g.Name() + "-source",
+ }
+ if libTestTarget, err := generateBazelTargetsGoTest(ctx, goModulesMap, gp); err == nil {
+ retTargets = append(retTargets, libTestTarget)
+ } else {
+ retErrs = append(retErrs, err)
+ }
+
+ }
+
+ // Create a go_binary target
+ ga := goAttributes{
+ Deps: goDepLabels(transitiveDeps, goModulesMap),
+ Target_compatible_with: targetNotCompatibleWithAndroid(),
+ }
+
+ // If the binary has testSrcs, embed the common `go_source`
+ if goSource != "" {
+ ga.Embed = bazel.MakeLabelListAttribute(
+ bazel.MakeLabelList(
+ []bazel.Label{bazel.Label{Label: ":" + goSource}},
+ ),
+ )
+ } else {
+ ga.Srcs = goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs())
+ }
+
+ bin := goBazelTarget{
+ targetName: g.Name(),
+ targetPackage: ctx.ModuleDir(g),
+ bazelRuleClass: "go_binary",
+ bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
+ bazelAttributes: []interface{}{&ca, &ga},
+ }
+
+ if binTarget, err := generateBazelTarget(ctx, bin); err == nil {
+ retTargets = append(retTargets, binTarget)
+ } else {
+ retErrs = []error{err}
+ }
+
+ return retTargets, retErrs
+}
+
func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) {
+ ctx.Context().BeginEvent("GenerateBazelTargets")
+ defer ctx.Context().EndEvent("GenerateBazelTargets")
buildFileToTargets := make(map[string]BazelTargets)
// Simple metrics tracking for bp2build
@@ -262,6 +665,10 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
var errs []error
+ // Visit go libraries in a pre-run and store its state in a map
+ // The time complexity remains O(N), and this does not add significant wall time.
+ nameToGoLibMap := createGoLibraryModuleMap(ctx.Context())
+
bpCtx := ctx.Context()
bpCtx.VisitAllModules(func(m blueprint.Module) {
dir := bpCtx.ModuleDir(m)
@@ -269,6 +676,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
dirs[dir] = true
var targets []BazelTarget
+ var targetErrs []error
switch ctx.Mode() {
case Bp2Build:
@@ -278,6 +686,9 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
//
// bp2build converters are used for the majority of modules.
if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
+ if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
+ panic(fmt.Errorf("module %q [%s] [%s] was both converted with bp2build and has a handcrafted label", bpCtx.ModuleName(m), moduleType, dir))
+ }
// Handle modules converted to handcrafted targets.
//
// Since these modules are associated with some handcrafted
@@ -317,7 +728,6 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
return
}
}
- var targetErrs []error
targets, targetErrs = generateBazelTargets(bpCtx, aModule)
errs = append(errs, targetErrs...)
for _, t := range targets {
@@ -336,6 +746,16 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers
metrics.AddUnconvertedModule(m, moduleType, dir, *reason)
}
return
+ } else if glib, ok := m.(*bootstrap.GoPackage); ok {
+ targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap)
+ errs = append(errs, targetErrs...)
+ metrics.IncrementRuleClassCount("go_library")
+ metrics.AddConvertedModule(glib, "go_library", dir)
+ } else if gbin, ok := m.(*bootstrap.GoBinary); ok {
+ targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap)
+ errs = append(errs, targetErrs...)
+ metrics.IncrementRuleClassCount("go_binary")
+ metrics.AddConvertedModule(gbin, "go_binary", dir)
} else {
metrics.AddUnconvertedModule(m, moduleType, dir, android.UnconvertedReason{
ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED),
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index e127fd542..8ee0439c0 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -640,7 +640,10 @@ func TestBp2buildHostAndDevice(t *testing.T) {
}`,
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `["//build/bazel/product_variables:unbundled_build"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/product_config/config_settings:unbundled_build": [],
+ "//conditions:default": ["@platforms//:incompatible"],
+ })`,
}),
},
},
@@ -1946,3 +1949,46 @@ func TestPrettyPrintSelectMapEqualValues(t *testing.T) {
actual, _ := prettyPrintAttribute(lla, 0)
android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual)
}
+
+// If CommonAttributes.Dir is set, the bazel target should be created in that dir
+func TestCreateBazelTargetInDifferentDir(t *testing.T) {
+ t.Parallel()
+ bp := `
+ custom {
+ name: "foo",
+ dir: "subdir",
+ }
+ `
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ // Check that foo is not created in root dir
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Description: "foo is not created in root dir because it sets dir explicitly",
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "subdir/Android.bp": "",
+ },
+ ExpectedBazelTargets: []string{},
+ })
+ // Check that foo is created in `subdir`
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Description: "foo is created in `subdir` because it sets dir explicitly",
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "subdir/Android.bp": "",
+ },
+ Dir: "subdir",
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("custom", "foo", AttrNameToString{}),
+ },
+ })
+ // Check that we cannot create target in different dir if it is does not an Android.bp
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Description: "foo cannot be created in `subdir` because it does not contain an Android.bp file",
+ Blueprint: bp,
+ Dir: "subdir",
+ ExpectedErr: fmt.Errorf("Cannot use ca.Dir to create a BazelTarget in dir: subdir since it does not contain an Android.bp file"),
+ })
+
+}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index fa1bf8af6..402d4b013 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -94,6 +94,7 @@ custom = rule(
# bazel_module end
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
+ "dir": attr.string(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
@@ -126,6 +127,7 @@ custom_defaults = rule(
"arch_paths_exclude": attr.string_list(),
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
+ "dir": attr.string(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
@@ -158,6 +160,7 @@ custom_test_ = rule(
"arch_paths_exclude": attr.string_list(),
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
+ "dir": attr.string(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
@@ -199,7 +202,7 @@ func TestGenerateSoongModuleBzl(t *testing.T) {
content: "irrelevant",
},
}
- files := CreateBazelFiles(android.NullConfig("out", "out/soong"), ruleShims, make(map[string]BazelTargets), QueryView)
+ files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView)
var actualSoongModuleBzl BazelFile
for _, f := range files {
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 18cb9e116..90db36573 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -880,8 +880,15 @@ func TestCcBinaryWithSanitizerBlocklist(t *testing.T) {
}`,
targets: []testBazelTarget{
{"cc_binary", "foo", AttrNameToString{
+ "copts": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
+ "//conditions:default": [],
+ })`,
+ "additional_compiler_inputs": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
+ "//conditions:default": [],
+ })`,
"local_includes": `["."]`,
- "features": `["ubsan_blocklist_foo_blocklist_txt"]`,
}},
},
})
@@ -1214,3 +1221,82 @@ func TestCCBinaryRscriptSrc(t *testing.T) {
},
})
}
+
+func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+ blueprint: soongCcLibraryStaticPreamble +
+ simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+
+cc_library {
+ name: "libm",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_binary {
+ name: "used_in_bionic_oses",
+ target: {
+ android: {
+ static_libs: ["libc"],
+ },
+ linux_bionic: {
+ static_libs: ["libc"],
+ },
+ },
+ include_build_directory: false,
+ static_executable: true,
+}
+
+cc_binary {
+ name: "all",
+ static_libs: ["libc"],
+ include_build_directory: false,
+ static_executable: true,
+}
+
+cc_binary {
+ name: "keep_for_empty_system_shared_libs",
+ static_libs: ["libc"],
+ system_shared_libs: [],
+ include_build_directory: false,
+ static_executable: true,
+}
+
+cc_binary {
+ name: "used_with_stubs",
+ static_libs: ["libm"],
+ include_build_directory: false,
+ static_executable: true,
+}
+
+cc_binary {
+ name: "keep_with_stubs",
+ static_libs: ["libm"],
+ system_shared_libs: [],
+ include_build_directory: false,
+ static_executable: true,
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_binary", "all", AttrNameToString{
+ "linkshared": "False",
+ }},
+ {"cc_binary", "keep_for_empty_system_shared_libs", AttrNameToString{
+ "deps": `[":libc_bp2build_cc_library_static"]`,
+ "system_deps": `[]`,
+ "linkshared": "False",
+ }},
+ {"cc_binary", "keep_with_stubs", AttrNameToString{
+ "linkshared": "False",
+ "deps": `[":libm_bp2build_cc_library_static"]`,
+ "system_deps": `[]`,
+ }},
+ {"cc_binary", "used_in_bionic_oses", AttrNameToString{
+ "linkshared": "False",
+ }},
+ {"cc_binary", "used_with_stubs", AttrNameToString{
+ "linkshared": "False",
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 1e3d72e6e..e70cd106f 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1260,14 +1260,14 @@ cc_library {
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte": [],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": [],
"//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
})`,
"implementation_dynamic_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_shared_lib_excludes"],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
"//conditions:default": [],
})`,
"srcs_c": `["common.c"]`,
@@ -1275,7 +1275,7 @@ cc_library {
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
"//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
})`,
}),
@@ -1307,7 +1307,7 @@ cc_library {
`,
ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
"implementation_deps": `select({
- "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_header_lib"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_header_lib"],
"//conditions:default": [],
})`,
"srcs_c": `["common.c"]`,
@@ -2434,12 +2434,18 @@ cc_library {
}), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+ }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
"tags": `[
"apex_available=//apex_available:anyapex",
"manual",
]`,
+ }), MakeBazelTargetNoRestrictions("alias", "a_fg_proto_bp2build_converted", AttrNameToString{
+ "actual": `"//.:a_fg_proto_proto"`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
}),
@@ -2476,12 +2482,18 @@ cc_library {
}), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
"whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+ }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
"tags": `[
"apex_available=//apex_available:anyapex",
"manual",
]`,
+ }), MakeBazelTargetNoRestrictions("alias", "a_fg_proto_bp2build_converted", AttrNameToString{
+ "actual": `"//.:a_fg_proto_proto"`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
}),
@@ -4194,11 +4206,25 @@ cc_library {
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["ubsan_blocklist_foo_blocklist_txt"]`,
+ "copts": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
+ "//conditions:default": [],
+ })`,
+ "additional_compiler_inputs": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
+ "//conditions:default": [],
+ })`,
"local_includes": `["."]`,
}),
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["ubsan_blocklist_foo_blocklist_txt"]`,
+ "copts": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
+ "//conditions:default": [],
+ })`,
+ "additional_compiler_inputs": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
+ "//conditions:default": [],
+ })`,
"local_includes": `["."]`,
}),
},
@@ -4631,7 +4657,7 @@ func TestCcLibraryCppFlagsInProductVariables(t *testing.T) {
"-Wextra",
"-DDEBUG_ONLY_CODE=0",
] + select({
- "//build/bazel/product_variables:eng": [
+ "//build/bazel/product_config/config_settings:eng": [
"-UDEBUG_ONLY_CODE",
"-DDEBUG_ONLY_CODE=1",
],
@@ -4903,3 +4929,142 @@ cc_library_shared {
},
})
}
+
+// Bazel enforces that proto_library and the .proto file are in the same bazel package
+func TestGenerateProtoLibraryInSamePackage(t *testing.T) {
+ tc := Bp2buildTestCase{
+ Description: "cc_library depends on .proto files from multiple packages",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "foo.proto",
+ "bar/bar.proto", // Different package because there is a bar/Android.bp
+ "baz/subbaz/baz.proto", // Different package because there is baz/subbaz/Android.bp
+ ],
+ proto: {
+ canonical_path_from_root: true,
+ }
+}
+` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+ Filesystem: map[string]string{
+ "bar/Android.bp": "",
+ "baz/subbaz/Android.bp": "",
+ },
+ }
+
+ // We will run the test 3 times and check in the root, bar and baz/subbaz directories
+ // Root dir
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["foo.proto"]`,
+ }),
+ MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
+ "deps": `[
+ ":foo_proto",
+ "//bar:foo_proto",
+ "//baz/subbaz:foo_proto",
+ ]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+
+ // bar dir
+ tc.Dir = "bar"
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["//bar:bar.proto"]`,
+ "tags": `["manual"]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+
+ // baz/subbaz dir
+ tc.Dir = "baz/subbaz"
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["//baz/subbaz:baz.proto"]`,
+ "tags": `["manual"]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+}
+
+// Bazel enforces that proto_library and the .proto file are in the same bazel package
+func TestGenerateProtoLibraryInSamePackageNotCanonicalFromRoot(t *testing.T) {
+ tc := Bp2buildTestCase{
+ Description: "cc_library depends on .proto files from multiple packages",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "foo.proto",
+ "bar/bar.proto", // Different package because there is a bar/Android.bp
+ "baz/subbaz/baz.proto", // Different package because there is baz/subbaz/Android.bp
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ }
+}
+` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+ Filesystem: map[string]string{
+ "bar/Android.bp": "",
+ "baz/subbaz/Android.bp": "",
+ },
+ }
+
+ // We will run the test 3 times and check in the root, bar and baz/subbaz directories
+ // Root dir
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["foo.proto"]`,
+ "strip_import_prefix": `""`,
+ }),
+ MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
+ "deps": `[
+ ":foo_proto",
+ "//bar:foo_proto",
+ "//baz/subbaz:foo_proto",
+ ]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+
+ // bar dir
+ tc.Dir = "bar"
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["//bar:bar.proto"]`,
+ "strip_import_prefix": `""`,
+ "import_prefix": `"bar"`,
+ "tags": `["manual"]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+
+ // baz/subbaz dir
+ tc.Dir = "baz/subbaz"
+ tc.ExpectedBazelTargets = []string{
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["//baz/subbaz:baz.proto"]`,
+ "strip_import_prefix": `""`,
+ "import_prefix": `"baz/subbaz"`,
+ "tags": `["manual"]`,
+ }),
+ }
+ runCcLibraryTestCase(t, tc)
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 2d61d5355..90b13b03f 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -1225,7 +1225,14 @@ cc_library_shared {
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["ubsan_blocklist_foo_blocklist_txt"]`,
+ "copts": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
+ "//conditions:default": [],
+ })`,
+ "additional_compiler_inputs": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
+ "//conditions:default": [],
+ })`,
"local_includes": `["."]`,
}),
},
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 18225dfa2..89ec8f9a7 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1003,6 +1003,38 @@ cc_library_static {
})
}
+func TestCcLibraryStaticGeneratedHeadersMultipleExports(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Blueprint: soongCcLibraryStaticPreamble + `
+genrule {
+ name: "generated_hdr",
+ cmd: "nothing to see here",
+ export_include_dirs: ["foo", "bar"],
+ bazel_module: { bp2build_available: false },
+}
+
+genrule {
+ name: "export_generated_hdr",
+ cmd: "nothing to see here",
+ export_include_dirs: ["a", "b"],
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library_static {
+ name: "foo_static",
+ generated_headers: ["generated_hdr", "export_generated_hdr"],
+ export_generated_headers: ["export_generated_hdr"],
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
+ "deps": `[":export_generated_hdr__header_library"]`,
+ "implementation_deps": `[":generated_hdr__header_library"]`,
+ }),
+ },
+ })
+}
+
// generated_headers has "variant_prepend" tag. In bp2build output,
// variant info(select) should go before general info.
func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
@@ -1156,13 +1188,13 @@ cc_library_static {
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
"copts": `select({
- "//build/bazel/product_variables:binder32bit": ["-Wbinder32bit"],
+ "//build/bazel/product_config/config_settings:binder32bit": ["-Wbinder32bit"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": ["-Wmalloc_not_svelte"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_zero_contents": ["-Wmalloc_zero_contents"],
+ "//build/bazel/product_config/config_settings:malloc_zero_contents": ["-Wmalloc_zero_contents"],
"//conditions:default": [],
})`,
"srcs_c": `["common.c"]`,
@@ -1216,19 +1248,19 @@ cc_library_static {
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
"copts": `select({
- "//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte": ["-Wmalloc_not_svelte"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte-android": ["-Wandroid_malloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte-android": ["-Wandroid_malloc_not_svelte"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte-arm": ["-Wlib32_malloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte-arm": ["-Wlib32_malloc_not_svelte"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte-arm64": ["-Warm64_malloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte-arm64": ["-Warm64_malloc_not_svelte"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte-x86": ["-Wlib32_malloc_not_svelte"],
+ "//build/bazel/product_config/config_settings:malloc_not_svelte-x86": ["-Wlib32_malloc_not_svelte"],
"//conditions:default": [],
})`,
"srcs_c": `["common.c"]`,
@@ -1255,7 +1287,7 @@ cc_library_static {
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
"asflags": `select({
- "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
+ "//build/bazel/product_config/config_settings:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
"//conditions:default": [],
})`,
"srcs_as": `["common.S"]`,
@@ -1918,7 +1950,14 @@ cc_library_static {
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["ubsan_blocklist_foo_blocklist_txt"]`,
+ "copts": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
+ "//conditions:default": [],
+ })`,
+ "additional_compiler_inputs": `select({
+ "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
+ "//conditions:default": [],
+ })`,
"local_includes": `["."]`,
}),
},
@@ -2215,3 +2254,38 @@ cc_library_static{
]`,
})}})
}
+
+func TestCcLibraryWithProtoInGeneratedSrcs(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with a .proto file generated from a genrule",
+ ModuleTypeUnderTest: "cc_library_static",
+ ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ Blueprint: soongCcLibraryPreamble + `
+cc_library_static {
+ name: "mylib",
+ generated_sources: ["myprotogen"],
+}
+genrule {
+ name: "myprotogen",
+ out: ["myproto.proto"],
+}
+` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "mylib", AttrNameToString{
+ "local_includes": `["."]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":mylib_cc_proto_lite"]`,
+ }),
+ MakeBazelTarget("cc_lite_proto_library", "mylib_cc_proto_lite", AttrNameToString{
+ "deps": `[":mylib_proto"]`,
+ }),
+ MakeBazelTarget("proto_library", "mylib_proto", AttrNameToString{
+ "srcs": `[":myprotogen"]`,
+ }),
+ MakeBazelTargetNoRestrictions("genrule", "myprotogen", AttrNameToString{
+ "cmd": `""`,
+ "outs": `["myproto.proto"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index eab84e152..ecfcb5a93 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -200,7 +200,7 @@ func TestCcObjectProductVariable(t *testing.T) {
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_object", "foo", AttrNameToString{
"asflags": `select({
- "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
+ "//build/bazel/product_config/config_settings:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
"//conditions:default": [],
})`,
"copts": `["-fno-addrsig"]`,
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 4df4d4d46..3c037b494 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -94,7 +94,9 @@ cc_test_library {
simpleModuleDoNotConvertBp2build("genrule", "data_mod") +
simpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") +
simpleModuleDoNotConvertBp2build("cc_library", "cc_lib") +
- simpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2"),
+ simpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
targets: []testBazelTarget{
{"cc_library_shared", "cc_test_lib1", AttrNameToString{}},
{"cc_library_static", "cc_test_lib1_bp2build_cc_library_static", AttrNameToString{}},
@@ -106,7 +108,11 @@ cc_test_library {
":cc_bin",
":cc_lib",
]`,
- "deps": `[":cc_test_lib1_bp2build_cc_library_static"] + select({
+ "deps": `[
+ ":cc_test_lib1_bp2build_cc_library_static",
+ ":libgtest_main",
+ ":libgtest",
+ ] + select({
"//build/bazel/platforms/os:darwin": [":hostlib"],
"//build/bazel/platforms/os:linux_bionic": [":hostlib"],
"//build/bazel/platforms/os:linux_glibc": [":hostlib"],
@@ -114,8 +120,6 @@ cc_test_library {
"//build/bazel/platforms/os:windows": [":hostlib"],
"//conditions:default": [],
})`,
- "gtest": "True",
- "isolated": "True",
"local_includes": `["."]`,
"dynamic_deps": `[":cc_test_lib2"] + select({
"//build/bazel/platforms/os:android": [":foolib"],
@@ -152,7 +156,6 @@ cc_test {
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"gtest": "False",
- "isolated": "False",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
},
@@ -171,14 +174,17 @@ cc_test {
srcs: ["test.cpp"],
test_options: { tags: ["no-remote"] },
}
-`,
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"tags": `["no-remote"]`,
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
- "gtest": "True",
- "isolated": "True",
+ "deps": `[
+ ":libgtest_main",
+ ":libgtest",
+ ]`,
},
},
},
@@ -197,15 +203,18 @@ cc_test {
srcs: ["test.cpp"],
test_config: "test_config.xml",
}
-`,
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
- "gtest": "True",
- "isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
"test_config": `"test_config.xml"`,
+ "deps": `[
+ ":libgtest_main",
+ ":libgtest",
+ ]`,
},
},
},
@@ -223,15 +232,18 @@ cc_test {
name: "mytest",
srcs: ["test.cpp"],
}
-`,
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
- "gtest": "True",
- "isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
"test_config": `"AndroidTest.xml"`,
+ "deps": `[
+ ":libgtest_main",
+ ":libgtest",
+ ]`,
},
},
},
@@ -250,13 +262,13 @@ cc_test {
srcs: ["test.cpp"],
test_config_template: "test_config_template.xml",
auto_gen_config: true,
+ isolated: true,
}
-`,
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+ simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"auto_generate_test_config": "True",
- "gtest": "True",
- "isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
@@ -266,6 +278,95 @@ cc_test {
]`,
"template_install_base": `"/data/local/tmp"`,
"template_test_config": `"test_config_template.xml"`,
+ "deps": `[":libgtest_isolated_main"]`,
+ "dynamic_deps": `[":liblog"]`,
+ },
+ },
+ },
+ })
+}
+
+func TestCcTest_WithExplicitGTestDepInAndroidBp(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file",
+ blueprint: `
+cc_test {
+ name: "mytest",
+ srcs: ["test.cpp"],
+ static_libs: ["libgtest"],
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ "deps": `[
+ ":libgtest",
+ ":libgtest_main",
+ ]`,
+ },
+ },
+ },
+ })
+
+}
+
+func TestCcTest_WithIsolatedTurnedOn(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main",
+ blueprint: `
+cc_test {
+ name: "mytest",
+ srcs: ["test.cpp"],
+ isolated: true,
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
+ simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ "deps": `[":libgtest_isolated_main"]`,
+ "dynamic_deps": `[":liblog"]`,
+ },
+ },
+ },
+ })
+
+}
+
+func TestCcTest_GtestExplicitlySpecifiedInAndroidBp(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well",
+ blueprint: `
+cc_test {
+ name: "mytest_with_gtest",
+ gtest: true,
+}
+cc_test {
+ name: "mytest_with_no_gtest",
+ gtest: false,
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
+ targets: []testBazelTarget{
+ {"cc_test", "mytest_with_gtest", AttrNameToString{
+ "local_includes": `["."]`,
+ "deps": `[
+ ":libgtest_main",
+ ":libgtest",
+ ]`,
+ "gtest": "True",
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ },
+ {"cc_test", "mytest_with_no_gtest", AttrNameToString{
+ "local_includes": `["."]`,
+ "gtest": "False",
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
},
},
},
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index d5f2386c3..f28092431 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,7 +1,6 @@
package bp2build
import (
- "android/soong/starlark_fmt"
"encoding/json"
"fmt"
"reflect"
@@ -9,11 +8,11 @@ import (
"strings"
"android/soong/android"
+ "android/soong/apex"
"android/soong/cc"
cc_config "android/soong/cc/config"
java_config "android/soong/java/config"
-
- "android/soong/apex"
+ "android/soong/starlark_fmt"
"github.com/google/blueprint/proptools"
)
@@ -105,12 +104,7 @@ platform_versions = struct(
`, starlark_fmt.PrintBool(cfg.PlatformSdkFinal()), platformSdkVersion, cfg.PlatformSdkCodename(), strings.Join(platformVersionActiveCodenames, ", "))
}
-func CreateBazelFiles(
- cfg android.Config,
- ruleShims map[string]RuleShim,
- buildToTargets map[string]BazelTargets,
- mode CodegenMode) []BazelFile {
-
+func CreateBazelFiles(ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
var files []BazelFile
if mode == QueryView {
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 00ffd793e..15284ce03 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -27,8 +27,7 @@ type bazelFilepath struct {
}
func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
- files := CreateBazelFiles(android.NullConfig("out", "out/soong"),
- map[string]RuleShim{}, map[string]BazelTargets{}, QueryView)
+ files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, QueryView)
expectedFilePaths := []bazelFilepath{
{
dir: "",
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index 7ce559d9b..cb2e2076a 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -137,7 +137,7 @@ filegroup {
path: "proto",
}`,
ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("proto_library", "foo_bp2build_converted", AttrNameToString{
+ MakeBazelTargetNoRestrictions("proto_library", "foo_proto", AttrNameToString{
"srcs": `["proto/foo.proto"]`,
"strip_import_prefix": `"proto"`,
"tags": `[
@@ -145,6 +145,13 @@ filegroup {
"manual",
]`,
}),
+ MakeBazelTargetNoRestrictions("alias", "foo_bp2build_converted", AttrNameToString{
+ "actual": `"//.:foo_proto"`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
+ }),
MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
"srcs": `["proto/foo.proto"]`}),
}})
@@ -170,3 +177,27 @@ filegroup {
]`}),
}})
}
+
+func TestFilegroupWithProtoInDifferentPackage(t *testing.T) {
+ runFilegroupTestCase(t, Bp2buildTestCase{
+ Description: "filegroup with .proto in different package",
+ Filesystem: map[string]string{
+ "subdir/Android.bp": "",
+ },
+ Blueprint: `
+filegroup {
+ name: "foo",
+ srcs: ["subdir/foo.proto"],
+}`,
+ Dir: "subdir", // check in subdir
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["//subdir:foo.proto"]`,
+ "import_prefix": `"subdir"`,
+ "strip_import_prefix": `""`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`}),
+ }})
+}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 5cf4fb216..2a10a14d4 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -16,6 +16,7 @@ package bp2build
import (
"fmt"
+ "path/filepath"
"testing"
"android/soong/android"
@@ -26,6 +27,8 @@ import (
func registerGenruleModuleTypes(ctx android.RegistrationContext) {
ctx.RegisterModuleType("genrule_defaults", func() android.Module { return genrule.DefaultsFactory() })
+ ctx.RegisterModuleType("cc_binary", func() android.Module { return cc.BinaryFactory() })
+ ctx.RegisterModuleType("soong_namespace", func() android.Module { return android.NamespaceFactory() })
}
func runGenruleTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -695,3 +698,257 @@ func TestCcGenruleArchAndExcludeSrcs(t *testing.T) {
})
})
}
+
+func TestGenruleWithExportIncludeDirs(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ hod android.HostOrDeviceSupported
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
+ },
+ {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ hod: android.HostSupported,
+ },
+ }
+
+ dir := "baz"
+
+ bp := `%s {
+ name: "foo",
+ out: ["foo.out.h"],
+ srcs: ["foo.in"],
+ cmd: "cp $(in) $(out)",
+ export_include_dirs: ["foo", "bar", "."],
+ bazel_module: { bp2build_available: true },
+}`
+
+ for _, tc := range testCases {
+ moduleAttrs := AttrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out.h"]`,
+ "srcs": `["foo.in"]`,
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
+ makeBazelTargetHostOrDevice("cc_library_headers", "foo__header_library", AttrNameToString{
+ "hdrs": `[":foo"]`,
+ "export_includes": `[
+ "foo",
+ "baz/foo",
+ "bar",
+ "baz/bar",
+ ".",
+ "baz",
+ ]`,
+ },
+ tc.hod),
+ }
+
+ t.Run(tc.moduleType, func(t *testing.T) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ Bp2buildTestCase{
+ ModuleTypeUnderTest: tc.moduleType,
+ ModuleTypeUnderTestFactory: tc.factory,
+ Filesystem: map[string]string{
+ filepath.Join(dir, "Android.bp"): fmt.Sprintf(bp, tc.moduleType),
+ },
+ Dir: dir,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestGenruleWithSoongConfigVariableConfiguredCmd(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ hod android.HostOrDeviceSupported
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
+ },
+ {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ hod: android.HostSupported,
+ },
+ }
+
+ bp := `
+soong_config_module_type {
+ name: "my_genrule",
+ module_type: "%s",
+ config_namespace: "my_namespace",
+ bool_variables: ["my_variable"],
+ properties: ["cmd"],
+}
+
+my_genrule {
+ name: "foo",
+ out: ["foo.txt"],
+ cmd: "echo 'no variable' > $(out)",
+ soong_config_variables: {
+ my_variable: {
+ cmd: "echo 'with variable' > $(out)",
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`
+
+ for _, tc := range testCases {
+ moduleAttrs := AttrNameToString{
+ "cmd": `select({
+ "//build/bazel/product_config/config_settings:my_namespace__my_variable": "echo 'with variable' > $(OUTS)",
+ "//conditions:default": "echo 'no variable' > $(OUTS)",
+ })`,
+ "outs": `["foo.txt"]`,
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
+ }
+
+ t.Run(tc.moduleType, func(t *testing.T) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { android.RegisterSoongConfigModuleBuildComponents(ctx) },
+ Bp2buildTestCase{
+ Blueprint: fmt.Sprintf(bp, tc.moduleType),
+ ModuleTypeUnderTest: tc.moduleType,
+ ModuleTypeUnderTestFactory: tc.factory,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestGenruleWithProductVariableConfiguredCmd(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ hod android.HostOrDeviceSupported
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
+ },
+ {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ hod: android.DeviceSupported,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ hod: android.HostSupported,
+ },
+ }
+
+ bp := `
+
+%s {
+ name: "foo",
+ out: ["foo.txt"],
+ cmd: "echo 'no variable' > $(out)",
+ product_variables: {
+ debuggable: {
+ cmd: "echo 'with variable' > $(out)",
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`
+
+ for _, tc := range testCases {
+ moduleAttrs := AttrNameToString{
+ "cmd": `select({
+ "//build/bazel/product_config/config_settings:debuggable": "echo 'with variable' > $(OUTS)",
+ "//conditions:default": "echo 'no variable' > $(OUTS)",
+ })`,
+ "outs": `["foo.txt"]`,
+ }
+
+ expectedBazelTargets := []string{
+ makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
+ }
+
+ t.Run(tc.moduleType, func(t *testing.T) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { android.RegisterSoongConfigModuleBuildComponents(ctx) },
+ Bp2buildTestCase{
+ Blueprint: fmt.Sprintf(bp, tc.moduleType),
+ ModuleTypeUnderTest: tc.moduleType,
+ ModuleTypeUnderTestFactory: tc.factory,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestGenruleWithModulesInNamespaces(t *testing.T) {
+ bp := `
+genrule {
+ name: "mygenrule",
+ cmd: "echo $(location //mynamespace:mymodule) > $(out)",
+ srcs: ["//mynamespace:mymodule"],
+ out: ["myout"],
+}
+`
+ fs := map[string]string{
+ "mynamespace/Android.bp": `soong_namespace {}`,
+ "mynamespace/dir/Android.bp": `cc_binary {name: "mymodule"}`,
+ }
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("genrule", "mygenrule", AttrNameToString{
+ // The fully qualified soong label is <namespace>:<module_name>
+ // - here the prefix is mynamespace
+ // The fully qualifed bazel label is <package>:<module_name>
+ // - here the prefix is mynamespace/dir, since there is a BUILD file at each level of this FS path
+ "cmd": `"echo $(location //mynamespace/dir:mymodule) > $(OUTS)"`,
+ "outs": `["myout"]`,
+ "srcs": `["//mynamespace/dir:mymodule"]`,
+ }),
+ }
+
+ t.Run("genrule that uses module from a different namespace", func(t *testing.T) {
+ runGenruleTestCase(t, Bp2buildTestCase{
+ Blueprint: bp,
+ Filesystem: fs,
+ ModuleTypeUnderTest: "genrule",
+ ModuleTypeUnderTestFactory: genrule.GenRuleFactory,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+
+}
diff --git a/bp2build/go_conversion_test.go b/bp2build/go_conversion_test.go
new file mode 100644
index 000000000..2387641f2
--- /dev/null
+++ b/bp2build/go_conversion_test.go
@@ -0,0 +1,208 @@
+// 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"
+
+ "github.com/google/blueprint/bootstrap"
+
+ "android/soong/android"
+)
+
+func runGoTests(t *testing.T, tc Bp2buildTestCase) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ tCtx := ctx.(*android.TestContext)
+ bootstrap.RegisterGoModuleTypes(tCtx.Context.Context) // android.TestContext --> android.Context --> blueprint.Context
+ }, tc)
+}
+
+func TestConvertGoPackage(t *testing.T) {
+ bp := `
+bootstrap_go_package {
+ name: "foo",
+ pkgPath: "android/foo",
+ deps: [
+ "bar",
+ ],
+ srcs: [
+ "foo1.go",
+ "foo2.go",
+ ],
+ linux: {
+ srcs: [
+ "foo_linux.go",
+ ],
+ testSrcs: [
+ "foo_linux_test.go",
+ ],
+ },
+ darwin: {
+ srcs: [
+ "foo_darwin.go",
+ ],
+ testSrcs: [
+ "foo_darwin_test.go",
+ ],
+ },
+ testSrcs: [
+ "foo1_test.go",
+ "foo2_test.go",
+ ],
+}
+`
+ depBp := `
+bootstrap_go_package {
+ name: "bar",
+}
+`
+ t.Parallel()
+ runGoTests(t, Bp2buildTestCase{
+ Description: "Convert bootstrap_go_package to go_library",
+ ModuleTypeUnderTest: "bootrstap_go_package",
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
+ },
+ ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_library", "foo",
+ AttrNameToString{
+ "deps": `["//bar:bar"]`,
+ "importpath": `"android/foo"`,
+ "srcs": `[
+ "foo1.go",
+ "foo2.go",
+ ] + select({
+ "//build/bazel/platforms/os:darwin": ["foo_darwin.go"],
+ "//build/bazel/platforms/os:linux_glibc": ["foo_linux.go"],
+ "//conditions:default": [],
+ })`,
+ },
+ android.HostSupported,
+ ),
+ makeBazelTargetHostOrDevice("go_test", "foo-test",
+ AttrNameToString{
+ "embed": `[":foo"]`,
+ "srcs": `[
+ "foo1_test.go",
+ "foo2_test.go",
+ ] + select({
+ "//build/bazel/platforms/os:darwin": ["foo_darwin_test.go"],
+ "//build/bazel/platforms/os:linux_glibc": ["foo_linux_test.go"],
+ "//conditions:default": [],
+ })`,
+ },
+ android.HostSupported,
+ )},
+ })
+}
+
+func TestConvertGoBinaryWithTransitiveDeps(t *testing.T) {
+ bp := `
+blueprint_go_binary {
+ name: "foo",
+ srcs: ["main.go"],
+ deps: ["bar"],
+}
+`
+ depBp := `
+bootstrap_go_package {
+ name: "bar",
+ deps: ["baz"],
+}
+bootstrap_go_package {
+ name: "baz",
+}
+`
+ t.Parallel()
+ runGoTests(t, Bp2buildTestCase{
+ Description: "Convert blueprint_go_binary to go_binary",
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
+ },
+ ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
+ AttrNameToString{
+ "deps": `[
+ "//bar:bar",
+ "//bar:baz",
+ ]`,
+ "srcs": `["main.go"]`,
+ },
+ android.HostSupported,
+ )},
+ })
+}
+
+func TestConvertGoBinaryWithTestSrcs(t *testing.T) {
+ bp := `
+blueprint_go_binary {
+ name: "foo",
+ srcs: ["main.go"],
+ testSrcs: ["main_test.go"],
+}
+`
+ t.Parallel()
+ runGoTests(t, Bp2buildTestCase{
+ Description: "Convert blueprint_go_binary with testSrcs",
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{
+ makeBazelTargetHostOrDevice("go_binary", "foo",
+ AttrNameToString{
+ "deps": `[]`,
+ "embed": `[":foo-source"]`,
+ },
+ android.HostSupported,
+ ),
+ makeBazelTargetHostOrDevice("go_source", "foo-source",
+ AttrNameToString{
+ "deps": `[]`,
+ "srcs": `["main.go"]`,
+ },
+ android.HostSupported,
+ ),
+ makeBazelTargetHostOrDevice("go_test", "foo-test",
+ AttrNameToString{
+ "embed": `[":foo-source"]`,
+ "srcs": `["main_test.go"]`,
+ },
+ android.HostSupported,
+ ),
+ },
+ })
+}
+
+func TestConvertGoBinaryWithSrcInDifferentPackage(t *testing.T) {
+ bp := `
+blueprint_go_binary {
+ name: "foo",
+ srcs: ["subdir/main.go"],
+}
+`
+ t.Parallel()
+ runGoTests(t, Bp2buildTestCase{
+ Description: "Convert blueprint_go_binary with src in different package",
+ Blueprint: bp,
+ Filesystem: map[string]string{
+ "subdir/Android.bp": "",
+ },
+ ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
+ AttrNameToString{
+ "deps": `[]`,
+ "srcs": `["//subdir:main.go"]`,
+ },
+ android.HostSupported,
+ )},
+ })
+}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index fd92e95c6..c501a7bcb 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -183,8 +183,8 @@ func TestJavaLibraryJavaVersion(t *testing.T) {
})
}
-func TestJavaLibraryErrorproneJavacflagsEnabledManually(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
+func TestJavaLibraryErrorproneEnabledManually(t *testing.T) {
+ runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
Blueprint: `java_library {
name: "java-lib-1",
srcs: ["a.java"],
@@ -192,7 +192,13 @@ func TestJavaLibraryErrorproneJavacflagsEnabledManually(t *testing.T) {
errorprone: {
enabled: true,
javacflags: ["-Xep:SpeedLimit:OFF"],
+ extra_check_modules: ["plugin2"],
},
+}
+java_plugin {
+ name: "plugin2",
+ srcs: ["a.java"],
+ bazel_module: { bp2build_available: false },
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
@@ -200,10 +206,14 @@ func TestJavaLibraryErrorproneJavacflagsEnabledManually(t *testing.T) {
"-Xsuper-fast",
"-Xep:SpeedLimit:OFF",
]`,
- "srcs": `["a.java"]`,
+ "plugins": `[":plugin2"]`,
+ "srcs": `["a.java"]`,
+ "errorprone_force_enable": `True`,
}),
MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
+ }, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_plugin", java.PluginFactory)
})
}
@@ -227,21 +237,23 @@ func TestJavaLibraryErrorproneJavacflagsErrorproneDisabledByDefault(t *testing.T
})
}
-func TestJavaLibraryErrorproneJavacflagsErrorproneDisabledManually(t *testing.T) {
+func TestJavaLibraryErrorproneDisabledManually(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
Blueprint: `java_library {
name: "java-lib-1",
srcs: ["a.java"],
javacflags: ["-Xsuper-fast"],
errorprone: {
- enabled: false,
- javacflags: ["-Xep:SpeedLimit:OFF"],
+ enabled: false,
},
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "javacopts": `["-Xsuper-fast"]`,
- "srcs": `["a.java"]`,
+ "javacopts": `[
+ "-Xsuper-fast",
+ "-XepDisableAllChecks",
+ ]`,
+ "srcs": `["a.java"]`,
}),
MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go
index f411ffb07..f41345e87 100644
--- a/bp2build/java_test_host_conversion_test.go
+++ b/bp2build/java_test_host_conversion_test.go
@@ -71,6 +71,11 @@ java_library {
}),
MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
"runtime_deps": `[":java_test_host-1_lib"]`,
+ "deps": `[
+ ":lib_a-neverlink",
+ ":static_libs_a",
+ ]`,
+ "srcs": `["a.java"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -128,6 +133,10 @@ java_test_host {
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.kt",
+ ]`,
"runtime_deps": `[":java_test_host-1_lib"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index aa0a5b728..5b2d609ac 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -149,7 +149,7 @@ prebuilt_etc {
MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
"filename": `"tz_version"`,
"src": `select({
- "//build/bazel/product_variables:native_coverage": "src1",
+ "//build/bazel/product_config/config_settings:native_coverage": "src1",
"//conditions:default": "version/tz_version",
})`,
"dir": `"etc"`,
@@ -318,7 +318,7 @@ prebuilt_etc {
"dir": `"etc"`,
"src": `select({
"//build/bazel/platforms/arch:arm": "armSrc",
- "//build/bazel/product_variables:native_coverage-arm": "nativeCoverageArmSrc",
+ "//build/bazel/product_config/config_settings:native_coverage-arm": "nativeCoverageArmSrc",
"//conditions:default": None,
})`,
})}})
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index 813773d00..8302ce87b 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -91,7 +91,7 @@ custom_cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -140,7 +140,7 @@ custom_cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -191,9 +191,9 @@ custom_cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_variables:acme__board__soc_c": [],
+ "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
"//conditions:default": ["-DSOC_DEFAULT"],
}),
local_includes = ["."],
@@ -240,7 +240,7 @@ custom_cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -310,15 +310,15 @@ custom_cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_variables:acme__board__soc_c": [],
+ "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
"//conditions:default": ["-DSOC_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}) + select({
- "//build/bazel/product_variables:acme__feature2": ["-DFEATURE2"],
+ "//build/bazel/product_config/config_settings:acme__feature2": ["-DFEATURE2"],
"//conditions:default": ["-DDEFAULT2"],
}),
local_includes = ["."],
@@ -380,15 +380,15 @@ cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_ava
ExpectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_variables:acme__board__soc_c": [],
+ "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
"//conditions:default": ["-DSOC_DEFAULT"],
}),
implementation_deps = select({
- "//build/bazel/product_variables:acme__board__soc_a": ["//foo/bar:soc_a_dep"],
- "//build/bazel/product_variables:acme__board__soc_b": ["//foo/bar:soc_b_dep"],
- "//build/bazel/product_variables:acme__board__soc_c": [],
+ "//build/bazel/product_config/config_settings:acme__board__soc_a": ["//foo/bar:soc_a_dep"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_b": ["//foo/bar:soc_b_dep"],
+ "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
"//conditions:default": ["//foo/bar:soc_default_static_dep"],
}),
local_includes = ["."],
@@ -446,7 +446,7 @@ cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
- "//build/bazel/product_variables:vendor_foo__feature": [
+ "//build/bazel/product_config/config_settings:vendor_foo__feature": [
"-cflag_feature_2",
"-cflag_feature_1",
],
@@ -527,11 +527,11 @@ cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "lib",
asflags = select({
- "//build/bazel/product_variables:acme__feature": ["-asflag_bar"],
+ "//build/bazel/product_config/config_settings:acme__feature": ["-asflag_bar"],
"//conditions:default": ["-asflag_default_bar"],
}),
copts = select({
- "//build/bazel/product_variables:acme__feature": [
+ "//build/bazel/product_config/config_settings:acme__feature": [
"-cflag_foo",
"-cflag_bar",
],
@@ -546,11 +546,11 @@ cc_library_static {
`cc_library_static(
name = "lib2",
asflags = select({
- "//build/bazel/product_variables:acme__feature": ["-asflag_bar"],
+ "//build/bazel/product_config/config_settings:acme__feature": ["-asflag_bar"],
"//conditions:default": ["-asflag_default_bar"],
}),
copts = select({
- "//build/bazel/product_variables:acme__feature": [
+ "//build/bazel/product_config/config_settings:acme__feature": [
"-cflag_bar",
"-cflag_foo",
],
@@ -643,13 +643,13 @@ cc_library_static {
ExpectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
- "//build/bazel/product_variables:vendor_bar__feature": ["-DVENDOR_BAR_FEATURE"],
+ "//build/bazel/product_config/config_settings:vendor_bar__feature": ["-DVENDOR_BAR_FEATURE"],
"//conditions:default": ["-DVENDOR_BAR_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:vendor_foo__feature": ["-DVENDOR_FOO_FEATURE"],
+ "//build/bazel/product_config/config_settings:vendor_foo__feature": ["-DVENDOR_FOO_FEATURE"],
"//conditions:default": ["-DVENDOR_FOO_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:vendor_qux__feature": ["-DVENDOR_QUX_FEATURE"],
+ "//build/bazel/product_config/config_settings:vendor_qux__feature": ["-DVENDOR_QUX_FEATURE"],
"//conditions:default": ["-DVENDOR_QUX_DEFAULT"],
}),
local_includes = ["."],
@@ -697,7 +697,7 @@ library_linking_strategy_custom {
ExpectedBazelTargets: []string{
MakeBazelTarget("custom", "foo", AttrNameToString{
"string_literal_prop": `select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": "29",
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "29",
"//conditions:default": "30",
})`,
}),
@@ -779,7 +779,7 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
ExpectedBazelTargets: []string{`cc_binary(
name = "library_linking_strategy_sample_binary",
dynamic_deps = select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
"//conditions:default": [
"//foo/bar:lib_b",
"//foo/bar:lib_a",
@@ -868,7 +868,7 @@ cc_library { name: "lib_c", bazel_module: { bp2build_available: false } }
ExpectedBazelTargets: []string{
MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary", AttrNameToString{
"dynamic_deps": `select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
"//conditions:default": [
"//foo/bar:lib_b",
"//foo/bar:lib_c",
@@ -877,7 +877,7 @@ cc_library { name: "lib_c", bazel_module: { bp2build_available: false } }
}),
MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary_with_excludes", AttrNameToString{
"dynamic_deps": `select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
"//conditions:default": ["//foo/bar:lib_b"],
})`,
}),
@@ -965,14 +965,14 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
ExpectedBazelTargets: []string{`cc_binary(
name = "library_linking_strategy_sample_binary",
deps = select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [
"//foo/bar:lib_b_bp2build_cc_library_static",
"//foo/bar:lib_a_bp2build_cc_library_static",
],
"//conditions:default": [],
}),
dynamic_deps = select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
"//conditions:default": [
"//foo/bar:lib_b",
"//foo/bar:lib_a",
@@ -1046,14 +1046,14 @@ cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
ExpectedBazelTargets: []string{`cc_binary(
name = "library_linking_strategy_sample_binary",
deps = select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [
"//foo/bar:lib_a_bp2build_cc_library_static",
"//foo/bar:lib_b_bp2build_cc_library_static",
],
"//conditions:default": [],
}),
dynamic_deps = select({
- "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [],
+ "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
"//conditions:default": [
"//foo/bar:lib_a",
"//foo/bar:lib_b",
@@ -1134,13 +1134,13 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
ExpectedBazelTargets: []string{`cc_binary(
name = "alphabet_binary",
deps = select({
- "//build/bazel/product_variables:android__alphabet__a": [],
- "//build/bazel/product_variables:android__alphabet__b": [],
+ "//build/bazel/product_config/config_settings:android__alphabet__a": [],
+ "//build/bazel/product_config/config_settings:android__alphabet__b": [],
"//conditions:default": ["//foo/bar:lib_default_bp2build_cc_library_static"],
}),
dynamic_deps = select({
- "//build/bazel/product_variables:android__alphabet__a": ["//foo/bar:lib_a"],
- "//build/bazel/product_variables:android__alphabet__b": ["//foo/bar:lib_b"],
+ "//build/bazel/product_config/config_settings:android__alphabet__a": ["//foo/bar:lib_a"],
+ "//build/bazel/product_config/config_settings:android__alphabet__b": ["//foo/bar:lib_b"],
"//conditions:default": [],
}),
local_includes = ["."],
@@ -1199,7 +1199,7 @@ cc_binary {
name = "alphabet_binary",
local_includes = ["."],
srcs = ["main.cc"],
- target_compatible_with = ["//build/bazel/product_variables:alphabet_module__special_build"] + select({
+ target_compatible_with = select({
"//build/bazel/platforms/os_arch:android_x86_64": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
@@ -1208,6 +1208,9 @@ cc_binary {
"//build/bazel/platforms/os_arch:linux_musl_x86_64": ["@platforms//:incompatible"],
"//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
"//conditions:default": [],
+ }) + select({
+ "//build/bazel/product_config/config_settings:alphabet_module__special_build": [],
+ "//conditions:default": ["@platforms//:incompatible"],
}),
)`}})
}
@@ -1240,6 +1243,24 @@ cc_binary {
srcs: ["main.cc"],
defaults: ["alphabet_sample_cc_defaults"],
enabled: false,
+}
+
+alphabet_cc_defaults {
+ name: "alphabet_sample_cc_defaults_conditions_default",
+ soong_config_variables: {
+ special_build: {
+ conditions_default: {
+ enabled: false,
+ },
+ },
+ },
+}
+
+cc_binary {
+ name: "alphabet_binary_conditions_default",
+ srcs: ["main.cc"],
+ defaults: ["alphabet_sample_cc_defaults_conditions_default"],
+ enabled: false,
}`
runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
@@ -1252,8 +1273,17 @@ cc_binary {
name = "alphabet_binary",
local_includes = ["."],
srcs = ["main.cc"],
- target_compatible_with = ["//build/bazel/product_variables:alphabet_module__special_build"],
-)`}})
+ target_compatible_with = select({
+ "//build/bazel/product_config/config_settings:alphabet_module__special_build": [],
+ "//conditions:default": ["@platforms//:incompatible"],
+ }),
+)`,
+ MakeBazelTarget("cc_binary", "alphabet_binary_conditions_default", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["main.cc"]`,
+ "target_compatible_with": `["@platforms//:incompatible"]`,
+ }),
+ }})
}
func TestSoongConfigModuleType_ProductVariableIgnoredIfEnabledByDefault(t *testing.T) {
@@ -1389,16 +1419,16 @@ cc_binary {
"//build/bazel/platforms/os:android": ["-DFOO"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:my_namespace__my_bool_variable__android": ["-DBAR"],
- "//build/bazel/product_variables:my_namespace__my_bool_variable__conditions_default__android": ["-DBAZ"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_bool_variable__android": ["-DBAR"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_bool_variable__conditions_default__android": ["-DBAZ"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:my_namespace__my_string_variable__value1": ["-DVALUE1_NOT_ANDROID"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value1": ["-DVALUE1_NOT_ANDROID"],
"//conditions:default": [],
}) + select({
- "//build/bazel/product_variables:my_namespace__my_string_variable__conditions_default__android": ["-DSTRING_VAR_CONDITIONS_DEFAULT"],
- "//build/bazel/product_variables:my_namespace__my_string_variable__value1__android": ["-DVALUE1"],
- "//build/bazel/product_variables:my_namespace__my_string_variable__value2__android": ["-DVALUE2"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__conditions_default__android": ["-DSTRING_VAR_CONDITIONS_DEFAULT"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value1__android": ["-DVALUE1"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value2__android": ["-DVALUE2"],
"//conditions:default": [],
}),
local_includes = ["."],
@@ -1406,3 +1436,166 @@ cc_binary {
target_compatible_with = ["//build/bazel/platforms/os:android"],
)`}})
}
+
+// If we have
+// A. a soong_config_module_type with target.android_<arch>.* in properties
+// B. a module that uses this module type but does not set target.android_<arch>.* via soong config vars
+// Then we should not panic
+func TestPanicsIfSoongConfigModuleTypeHasArchSpecificProperties(t *testing.T) {
+ commonBp := `
+soong_config_bool_variable {
+ name: "my_bool_variable",
+}
+soong_config_module_type {
+ name: "special_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "my_namespace",
+ bool_variables: ["my_bool_variable"],
+ properties: [
+ "cflags",
+ "target.android_arm64.shared_libs",
+ ],
+}
+cc_binary {
+ name: "my_binary",
+ defaults: ["my_special_cc_defaults"],
+}
+`
+ testCases := []struct {
+ desc string
+ additionalBp string
+ isPanicExpected bool
+ }{
+ {
+ desc: "target.android_arm64 is not set, bp2build should not panic",
+ additionalBp: `
+special_cc_defaults {
+ name: "my_special_cc_defaults",
+ soong_config_variables: {
+ my_bool_variable: {
+ cflags: ["-DFOO"],
+ conditions_default: {
+ cflags: ["-DBAR"],
+ }
+ }
+ },
+}
+ `,
+ isPanicExpected: false,
+ },
+ {
+ desc: "target.android_arm64 is set using the bool soong config var, bp2build should panic",
+ additionalBp: `
+special_cc_defaults {
+ name: "my_special_cc_defaults",
+ soong_config_variables: {
+ my_bool_variable: {
+ cflags: ["-DFOO"],
+ target: {
+ android_arm64: {
+ shared_libs: ["liblog"],
+ },
+ },
+ conditions_default: {
+ cflags: ["-DBAR"],
+ }
+ }
+ },
+}
+ `,
+ isPanicExpected: true,
+ },
+ {
+ desc: "target.android_arm64 is set using conditions_default for the bool soong config var, bp2build should panic",
+ additionalBp: `
+special_cc_defaults {
+ name: "my_special_cc_defaults",
+ soong_config_variables: {
+ my_bool_variable: {
+ cflags: ["-DFOO"],
+ conditions_default: {
+ cflags: ["-DBAR"],
+ target: {
+ android_arm64: {
+ shared_libs: ["liblog"],
+ },
+ },
+ }
+ }
+ },
+}
+ `,
+ isPanicExpected: true,
+ },
+ }
+ for _, tc := range testCases {
+ bp2buildTestCase := Bp2buildTestCase{
+ Description: tc.desc,
+ ModuleTypeUnderTest: "cc_binary",
+ ModuleTypeUnderTestFactory: cc.BinaryFactory,
+ Blueprint: commonBp + tc.additionalBp,
+ // Check in `foo` dir so that we can check whether it panics or not and not trip over an empty `ExpectedBazelTargets`
+ Dir: "foo",
+ ExpectedBazelTargets: []string{},
+ }
+ if tc.isPanicExpected {
+ bp2buildTestCase.ExpectedErr = fmt.Errorf("TODO: support other target types in soong config variable structs: Android_arm64")
+ }
+ runSoongConfigModuleTypeTest(t, bp2buildTestCase)
+ }
+}
+
+func TestNoPanicIfEnabledIsNotUsed(t *testing.T) {
+ bp := `
+soong_config_string_variable {
+ name: "my_string_variable",
+ values: ["val1", "val2"],
+}
+soong_config_module_type {
+ name: "special_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "my_namespace",
+ variables: ["my_string_variable"],
+ properties: [
+ "cflags",
+ "enabled",
+ ],
+}
+special_cc_defaults {
+ name: "my_special_cc_defaults",
+ soong_config_variables: {
+ my_string_variable: {
+ val1: {
+ cflags: ["-DFOO"],
+ },
+ val2: {
+ cflags: ["-DBAR"],
+ },
+ },
+ },
+}
+cc_binary {
+ name: "my_binary",
+ enabled: false,
+ defaults: ["my_special_cc_defaults"],
+}
+`
+ tc := Bp2buildTestCase{
+ Description: "Soong config vars is not used to set `enabled` property",
+ ModuleTypeUnderTest: "cc_binary",
+ ModuleTypeUnderTestFactory: cc.BinaryFactory,
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_binary", "my_binary", AttrNameToString{
+ "copts": `select({
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__val1": ["-DFOO"],
+ "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__val2": ["-DBAR"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ "target_compatible_with": `["@platforms//:incompatible"]`,
+ }),
+ },
+ }
+ runSoongConfigModuleTypeTest(t, tc)
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 140b214cf..18ae82de9 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -336,6 +336,8 @@ type customProps struct {
Api *string // File describing the APIs of this module
Test_config_setting *bool // Used to test generation of config_setting targets
+
+ Dir *string // Dir in which the Bazel Target will be created
}
type customModule struct {
@@ -461,6 +463,10 @@ type customBazelModuleAttributes struct {
Api bazel.LabelAttribute
}
+func (m *customModule) dir() *string {
+ return m.props.Dir
+}
+
func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
if p := m.props.One_to_many_prop; p != nil && *p {
customBp2buildOneToMany(ctx, m)
@@ -508,7 +514,7 @@ func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Rule_class: "custom",
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name(), Dir: m.dir()}, attrs)
if proptools.Bool(m.props.Test_config_setting) {
m.createConfigSetting(ctx)
diff --git a/build_kzip.bash b/build_kzip.bash
index dddcd3f3f..4c42048dd 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -44,7 +44,7 @@ kzip_targets=(
# xref_rust
)
-build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k "${kzip_targets[@]}"
+build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k --skip-soong-tests --ninja_weight_source=not_used "${kzip_targets[@]}"
# Build extraction file for Go the files in build/{blueprint,soong} directories.
declare -r abspath_out=$(realpath "${out}")
@@ -71,7 +71,7 @@ done
set +e
declare -r kzip_count=$(find "$out" -name '*.kzip' | wc -l)
-(($kzip_count>100000)) || { printf "Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
+(($kzip_count>100000)) || { >&2 printf "ERROR: Too few kzip files were generated: %d\n" $kzip_count; exit 1; }
# Pack
declare -r allkzip="$KZIP_NAME.kzip"
diff --git a/cc/Android.bp b/cc/Android.bp
index f49dc1a9e..c32d85490 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -32,10 +32,12 @@ bootstrap_go_package {
"check.go",
"coverage.go",
"gen.go",
+ "generated_cc_library.go",
"image.go",
"linkable.go",
"lto.go",
"makevars.go",
+ "orderfile.go",
"pgo.go",
"prebuilt.go",
"proto.go",
@@ -103,6 +105,7 @@ bootstrap_go_package {
"lto_test.go",
"ndk_test.go",
"object_test.go",
+ "orderfile_test.go",
"prebuilt_test.go",
"proto_test.go",
"sanitize_test.go",
diff --git a/cc/afdo.go b/cc/afdo.go
index bc7cd5212..23d196dba 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -131,6 +131,10 @@ func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
return
}
+ if !c.afdo.afdoEnabled() {
+ return
+ }
+
ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
diff --git a/cc/api_level.go b/cc/api_level.go
index a5571f31f..69a0d3ae4 100644
--- a/cc/api_level.go
+++ b/cc/api_level.go
@@ -31,7 +31,11 @@ func MinApiForArch(ctx android.EarlyModuleContext,
case android.Arm64, android.X86_64:
return android.FirstLp64Version
case android.Riscv64:
- return android.FutureApiLevel
+ apiLevel, err := android.ApiLevelFromUser(ctx, "VanillaIceCream")
+ if err != nil {
+ panic(err)
+ }
+ return apiLevel
default:
panic(fmt.Errorf("Unknown arch %q", arch))
}
diff --git a/cc/binary.go b/cc/binary.go
index 5ba33a24a..4606b623e 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -638,7 +638,8 @@ func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAtt
Stl: baseAttrs.stl,
Cpp_std: baseAttrs.cppStd,
- Additional_linker_inputs: baseAttrs.additionalLinkerInputs,
+ Additional_linker_inputs: baseAttrs.additionalLinkerInputs,
+ Additional_compiler_inputs: baseAttrs.additionalCompilerInputs,
Strip: stripAttributes{
Keep_symbols: baseAttrs.stripKeepSymbols,
@@ -680,10 +681,11 @@ type binaryAttributes struct {
Srcs_c bazel.LabelListAttribute
Srcs_as bazel.LabelListAttribute
- Copts bazel.StringListAttribute
- Cppflags bazel.StringListAttribute
- Conlyflags bazel.StringListAttribute
- Asflags bazel.StringListAttribute
+ Copts bazel.StringListAttribute
+ Cppflags bazel.StringListAttribute
+ Conlyflags bazel.StringListAttribute
+ Asflags bazel.StringListAttribute
+ Additional_compiler_inputs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 5459595e2..0157632aa 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -22,6 +22,7 @@ import (
"android/soong/android"
"android/soong/bazel"
"android/soong/cc/config"
+ "android/soong/genrule"
"github.com/google/blueprint"
@@ -43,6 +44,14 @@ const (
rScriptSrcPartition = "renderScript"
+ xsdSrcPartition = "xsd"
+
+ genrulePartition = "genrule"
+
+ protoFromGenPartition = "proto_gen"
+
+ hdrPartition = "hdr"
+
stubsSuffix = "_stub_libs_current"
)
@@ -56,6 +65,8 @@ type staticOrSharedAttributes struct {
Hdrs bazel.LabelListAttribute
Copts bazel.StringListAttribute
+ Additional_compiler_inputs bazel.LabelListAttribute
+
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
@@ -119,6 +130,41 @@ func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAtt
}
}
+// Returns an unchanged label and a bool indicating whether the dep is a genrule that produces .proto files
+func protoFromGenPartitionMapper(pathCtx android.BazelConversionContext) bazel.LabelMapper {
+ return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+ mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
+ if !exists {
+ return label.Label, false
+ }
+ gen, isGen := mod.(*genrule.Module)
+ if !isGen {
+ return label.Label, false
+ }
+ if containsProto(ctx, gen.RawOutputFiles(pathCtx)) {
+ // Return unmodified label + true
+ // True will ensure that this module gets dropped from `srcs` of the generated cc_* target. `srcs` is reserved for .cpp files
+ return label.Label, true
+ }
+ return label.Label, false
+ }
+}
+
+// Returns true if srcs contains only .proto files
+// Raises an exception if there is a combination of .proto and non .proto srcs
+func containsProto(ctx bazel.OtherModuleContext, srcs []string) bool {
+ onlyProtos := false
+ for _, src := range srcs {
+ if strings.HasSuffix(src, ".proto") {
+ onlyProtos = true
+ } else if onlyProtos {
+ // This is not a proto file, and we have encountered a .proto file previously
+ ctx.ModuleErrorf("TOOD: Add bp2build support combination of .proto and non .proto files in outs of genrule")
+ }
+ }
+ return onlyProtos
+}
+
// groupSrcsByExtension partitions `srcs` into groups based on file extension.
func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
// Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
@@ -152,9 +198,11 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab
// contains .l or .ll files we will need to find a way to add a
// LabelMapper for these that identifies these filegroups and
// converts them appropriately
- lSrcPartition: bazel.LabelPartition{Extensions: []string{".l"}},
- llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}},
- rScriptSrcPartition: bazel.LabelPartition{Extensions: []string{".fs", ".rscript"}},
+ lSrcPartition: bazel.LabelPartition{Extensions: []string{".l"}},
+ llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}},
+ rScriptSrcPartition: bazel.LabelPartition{Extensions: []string{".fs", ".rscript"}},
+ xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
+ protoFromGenPartition: bazel.LabelPartition{LabelMapper: protoFromGenPartitionMapper(ctx)},
// C++ is the "catch-all" group, and comprises generated sources because we don't
// know the language of these sources until the genrule is executed.
cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
@@ -165,6 +213,15 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab
return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
}
+func partitionHeaders(ctx android.BazelConversionPathContext, hdrs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
+ labels := bazel.LabelPartitions{
+ xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
+ genrulePartition: bazel.LabelPartition{LabelMapper: genrule.GenruleCcHeaderLabelMapper},
+ hdrPartition: bazel.LabelPartition{Keep_remainder: true},
+ }
+ return bazel.PartitionLabelListAttribute(ctx, &hdrs, labels)
+}
+
// bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes {
lib, ok := module.compiler.(*libraryDecorator)
@@ -403,7 +460,12 @@ type compilerAttributes struct {
srcs bazel.LabelListAttribute
// xsd config sources
- xsdInSrcs bazel.StringListAttribute
+ xsdSrcs bazel.LabelListAttribute
+ exportXsdSrcs bazel.LabelListAttribute
+
+ // genrule headers
+ genruleHeaders bazel.LabelListAttribute
+ exportGenruleHeaders bazel.LabelListAttribute
// Lex sources and options
lSrcs bazel.LabelListAttribute
@@ -448,6 +510,8 @@ type compilerAttributes struct {
suffix bazel.StringAttribute
fdoProfile bazel.LabelAttribute
+
+ additionalCompilerInputs bazel.LabelListAttribute
}
type filterOutFn func(string) bool
@@ -494,14 +558,11 @@ func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []stri
func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
- srcsList, xsdList, ok := parseSrcs(ctx, props)
+ srcsList, ok := parseSrcs(ctx, props)
if ok {
ca.srcs.SetSelectValue(axis, config, srcsList)
}
- if len(xsdList) > 0 {
- ca.xsdInSrcs.SetSelectValue(axis, config, xsdList)
- }
localIncludeDirs := props.Local_include_dirs
if axis == bazel.NoConfigAxis {
@@ -568,11 +629,14 @@ func (ca *compilerAttributes) convertProductVariables(ctx android.BazelConversio
}
}
-func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, implementationHdrs bazel.LabelListAttribute) {
+func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, implementationHdrs, exportHdrs bazel.LabelListAttribute) {
ca.srcs.ResolveExcludes()
partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
+ partitionedImplHdrs := partitionHeaders(ctx, implementationHdrs)
+ partitionedHdrs := partitionHeaders(ctx, exportHdrs)
ca.protoSrcs = partitionedSrcs[protoSrcPartition]
+ ca.protoSrcs.Append(partitionedSrcs[protoFromGenPartition])
ca.aidlSrcs = partitionedSrcs[aidlSrcPartition]
for p, lla := range partitionedSrcs {
@@ -580,10 +644,22 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i
if lla.IsEmpty() {
continue
}
- lla.Append(implementationHdrs)
+ lla.Append(partitionedImplHdrs[hdrPartition])
partitionedSrcs[p] = lla
}
+ ca.hdrs = partitionedHdrs[hdrPartition]
+
+ ca.includesFromHeaders(ctx, partitionedImplHdrs[hdrPartition], partitionedHdrs[hdrPartition])
+
+ xsdSrcs := bazel.SubtractBazelLabelListAttribute(partitionedSrcs[xsdSrcPartition], partitionedHdrs[xsdSrcPartition])
+ xsdSrcs.Append(partitionedImplHdrs[xsdSrcPartition])
+ ca.exportXsdSrcs = partitionedHdrs[xsdSrcPartition]
+ ca.xsdSrcs = bazel.FirstUniqueBazelLabelListAttribute(xsdSrcs)
+
+ ca.genruleHeaders = partitionedImplHdrs[genrulePartition]
+ ca.exportGenruleHeaders = partitionedHdrs[genrulePartition]
+
ca.srcs = partitionedSrcs[cppSrcPartition]
ca.cSrcs = partitionedSrcs[cSrcPartition]
ca.asSrcs = partitionedSrcs[asSrcPartition]
@@ -604,11 +680,11 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i
}
// Parse srcs from an arch or OS's props value.
-func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, []string, bool) {
+func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
anySrcs := false
// Add srcs-like dependencies such as generated files.
// First create a LabelList containing these dependencies, then merge the values with srcs.
- genSrcs, xsd := android.PartitionXsdSrcs(ctx, props.Generated_sources)
+ genSrcs := props.Generated_sources
generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, genSrcs, props.Exclude_generated_sources)
if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 {
anySrcs = true
@@ -620,7 +696,7 @@ func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProper
anySrcs = true
}
- return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), xsd, anySrcs
+ return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
}
func bp2buildStdVal(std *string, prefix string, useGnu bool) *string {
@@ -667,8 +743,43 @@ func packageFromLabel(label string) (string, bool) {
return split[0][2:], true
}
-// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList>
-func includesFromLabelList(labelList bazel.LabelList) (relative, absolute []string) {
+// includesFromHeaders gets the include directories needed from generated headers
+func (ca *compilerAttributes) includesFromHeaders(ctx android.BazelConversionPathContext, implHdrs, hdrs bazel.LabelListAttribute) {
+ local, absolute := includesFromLabelListAttribute(implHdrs, ca.localIncludes, ca.absoluteIncludes)
+ localExport, absoluteExport := includesFromLabelListAttribute(hdrs, ca.includes.Includes, ca.includes.AbsoluteIncludes)
+
+ ca.localIncludes = local
+ ca.absoluteIncludes = absolute
+
+ ca.includes.Includes = localExport
+ ca.includes.AbsoluteIncludes = absoluteExport
+}
+
+// includesFromLabelList extracts the packages from a LabelListAttribute that should be includes and
+// combines them with existing local/absolute includes.
+func includesFromLabelListAttribute(attr bazel.LabelListAttribute, existingLocal, existingAbsolute bazel.StringListAttribute) (bazel.StringListAttribute, bazel.StringListAttribute) {
+ localAttr := existingLocal.Clone()
+ absoluteAttr := existingAbsolute.Clone()
+ if !attr.Value.IsEmpty() {
+ l, a := includesFromLabelList(attr.Value, existingLocal.Value, existingAbsolute.Value)
+ localAttr.SetSelectValue(bazel.NoConfigAxis, "", l)
+ absoluteAttr.SetSelectValue(bazel.NoConfigAxis, "", a)
+ }
+ for axis, configToLabels := range attr.ConfigurableValues {
+ for c, labels := range configToLabels {
+ local := existingLocal.SelectValue(axis, c)
+ absolute := existingAbsolute.SelectValue(axis, c)
+ l, a := includesFromLabelList(labels, local, absolute)
+ localAttr.SetSelectValue(axis, c, l)
+ absoluteAttr.SetSelectValue(axis, c, a)
+ }
+ }
+ return *localAttr, *absoluteAttr
+}
+
+// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList.
+func includesFromLabelList(labelList bazel.LabelList, existingRel, existingAbs []string) ([]string, []string) {
+ var relative, absolute []string
for _, hdr := range labelList.Includes {
if pkg, hasPkg := packageFromLabel(hdr.Label); hasPkg {
absolute = append(absolute, pkg)
@@ -676,6 +787,12 @@ func includesFromLabelList(labelList bazel.LabelList) (relative, absolute []stri
relative = append(relative, pkg)
}
}
+ if len(relative)+len(existingRel) != 0 {
+ relative = android.FirstUniqueStrings(append(append([]string{}, existingRel...), relative...))
+ }
+ if len(absolute)+len(existingAbs) != 0 {
+ absolute = android.FirstUniqueStrings(append(append([]string{}, existingAbs...), absolute...))
+ }
return relative, absolute
}
@@ -740,8 +857,6 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
archVariantLibraryProperties := module.GetArchVariantProperties(ctx, &LibraryProperties{})
- var implementationHdrs bazel.LabelListAttribute
-
axisToConfigs := map[bazel.ConfigurationAxis]map[string]bool{}
allAxesAndConfigs := func(cp android.ConfigurationAxisToArchVariantProperties) {
for axis, configMap := range cp {
@@ -761,6 +876,7 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
linkerAttrs := linkerAttributes{}
var aidlLibs bazel.LabelList
+ var implementationHdrs, exportHdrs bazel.LabelListAttribute
// Iterate through these axes in a deterministic order. This is required
// because processing certain dependencies may result in concatenating
@@ -770,9 +886,9 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
for _, axis := range bazel.SortedConfigurationAxes(axisToConfigs) {
configs := axisToConfigs[axis]
for cfg := range configs {
- var allHdrs, allHdrsXsd []string
+ var allHdrs []string
if baseCompilerProps, ok := archVariantCompilerProps[axis][cfg].(*BaseCompilerProperties); ok {
- allHdrs, allHdrsXsd = android.PartitionXsdSrcs(ctx, baseCompilerProps.Generated_headers)
+ allHdrs = baseCompilerProps.Generated_headers
if baseCompilerProps.Lex != nil {
compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
@@ -786,36 +902,17 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs))
}
- var exportHdrs, exportHdrsXsd []string
+ var exportedHdrs []string
if baseLinkerProps, ok := archVariantLinkerProps[axis][cfg].(*BaseLinkerProperties); ok {
- exportHdrs, exportHdrsXsd = android.PartitionXsdSrcs(ctx, baseLinkerProps.Export_generated_headers)
+ exportedHdrs = baseLinkerProps.Export_generated_headers
(&linkerAttrs).bp2buildForAxisAndConfig(ctx, module, axis, cfg, baseLinkerProps)
}
- // in the synthetic bp2build workspace, xsd sources are compiled to a static library
- xsdList := compilerAttrs.xsdInSrcs.SelectValue(axis, cfg)
- allHdrsXsd = android.FirstUniqueStrings(append(xsdList, allHdrsXsd...))
- headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportHdrs, android.BazelLabelForModuleDeps)
- xsdConfigLibs := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrsXsd, exportHdrsXsd, bazelLabelForXsdConfig)
+ headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportedHdrs, android.BazelLabelForModuleDeps)
implementationHdrs.SetSelectValue(axis, cfg, headers.implementation)
- compilerAttrs.hdrs.SetSelectValue(axis, cfg, headers.export)
-
- exportIncludes, exportAbsoluteIncludes := includesFromLabelList(headers.export)
- compilerAttrs.includes.Includes.SetSelectValue(axis, cfg, exportIncludes)
- compilerAttrs.includes.AbsoluteIncludes.SetSelectValue(axis, cfg, exportAbsoluteIncludes)
-
- includes, absoluteIncludes := includesFromLabelList(headers.implementation)
- currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, cfg)
- currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...))
-
- compilerAttrs.absoluteIncludes.SetSelectValue(axis, cfg, currAbsoluteIncludes)
-
- currIncludes := compilerAttrs.localIncludes.SelectValue(axis, cfg)
- currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...))
-
- compilerAttrs.localIncludes.SetSelectValue(axis, cfg, currIncludes)
+ exportHdrs.SetSelectValue(axis, cfg, headers.export)
if libraryProps, ok := archVariantLibraryProperties[axis][cfg].(*LibraryProperties); ok {
if axis == bazel.NoConfigAxis {
@@ -835,14 +932,6 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
}
}
- if len(allHdrsXsd) > 0 {
- wholeStaticLibs := linkerAttrs.implementationWholeArchiveDeps.SelectValue(axis, cfg)
- (&wholeStaticLibs).Append(xsdConfigLibs.implementation)
- linkerAttrs.implementationWholeArchiveDeps.SetSelectValue(axis, cfg, wholeStaticLibs)
- wholeStaticLibs = linkerAttrs.wholeArchiveDeps.SelectValue(axis, cfg)
- (&wholeStaticLibs).Append(xsdConfigLibs.export)
- linkerAttrs.wholeArchiveDeps.SetSelectValue(axis, cfg, wholeStaticLibs)
- }
}
}
@@ -860,11 +949,17 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
(&compilerAttrs).convertProductVariables(ctx, productVariableProps)
(&linkerAttrs).convertProductVariables(ctx, productVariableProps)
- (&compilerAttrs).finalize(ctx, implementationHdrs)
+ (&compilerAttrs).finalize(ctx, implementationHdrs, exportHdrs)
(&linkerAttrs).finalize(ctx)
(&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
+ (&linkerAttrs).deps.Append(compilerAttrs.exportGenruleHeaders)
+ (&linkerAttrs).implementationDeps.Append(compilerAttrs.genruleHeaders)
+
+ (&linkerAttrs).wholeArchiveDeps.Append(compilerAttrs.exportXsdSrcs)
+ (&linkerAttrs).implementationWholeArchiveDeps.Append(compilerAttrs.xsdSrcs)
+
protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
// bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
@@ -925,13 +1020,25 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module)
(&compilerAttrs).localIncludes.Append(rsLocalIncludes)
(&compilerAttrs).localIncludes.Value = android.FirstUniqueStrings(compilerAttrs.localIncludes.Value)
- features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(bp2buildSanitizerFeatures(ctx, module))
+ sanitizerValues := bp2buildSanitizerFeatures(ctx, module)
+
+ features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(sanitizerValues.features)
features = features.Append(bp2buildLtoFeatures(ctx, module))
features = features.Append(convertHiddenVisibilityToFeatureBase(ctx, module))
features.DeduplicateAxesFromBase()
+ compilerAttrs.copts = *compilerAttrs.copts.Append(sanitizerValues.copts)
+ compilerAttrs.additionalCompilerInputs = *compilerAttrs.additionalCompilerInputs.Append(sanitizerValues.additionalCompilerInputs)
+
addMuslSystemDynamicDeps(ctx, linkerAttrs)
+ // Dedupe all deps.
+ (&linkerAttrs).deps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).deps.Value)
+ (&linkerAttrs).implementationDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationDeps.Value)
+ (&linkerAttrs).implementationDynamicDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationDynamicDeps.Value)
+ (&linkerAttrs).wholeArchiveDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).wholeArchiveDeps.Value)
+ (&linkerAttrs).implementationWholeArchiveDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationWholeArchiveDeps.Value)
+
return baseAttributes{
compilerAttrs,
linkerAttrs,
@@ -1139,6 +1246,7 @@ type linkerAttributes struct {
wholeArchiveDeps bazel.LabelListAttribute
implementationWholeArchiveDeps bazel.LabelListAttribute
systemDynamicDeps bazel.LabelListAttribute
+ usedSystemDynamicDepAsStaticDep map[string]bool
usedSystemDynamicDepAsDynamicDep map[string]bool
useVersionLib bazel.BoolAttribute
@@ -1201,6 +1309,18 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion
// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
+ if isBinary && module.StaticExecutable() {
+ usedSystemStatic := android.FilterListPred(staticLibs, func(s string) bool {
+ return android.InList(s, soongSystemSharedLibs) && !android.InList(s, props.Exclude_static_libs)
+ })
+
+ for _, el := range usedSystemStatic {
+ if la.usedSystemDynamicDepAsStaticDep == nil {
+ la.usedSystemDynamicDepAsStaticDep = map[string]bool{}
+ }
+ la.usedSystemDynamicDepAsStaticDep[el] = true
+ }
+ }
staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(
ctx,
!isBinary,
@@ -1233,6 +1353,7 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion
usedSystem := android.FilterListPred(sharedLibs, func(s string) bool {
return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs)
})
+
for _, el := range usedSystem {
if la.usedSystemDynamicDepAsDynamicDep == nil {
la.usedSystemDynamicDepAsDynamicDep = map[string]bool{}
@@ -1625,6 +1746,15 @@ func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
}
la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList(stubsToRemove))
}
+ if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsStaticDep) > 0 {
+ toRemove := bazelLabelForStaticDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsStaticDep))
+ la.deps.Exclude(bazel.NoConfigAxis, "", toRemove)
+ la.deps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+ la.deps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+ la.implementationDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
+ la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+ la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+ }
la.deps.ResolveExcludes()
la.implementationDeps.ResolveExcludes()
@@ -1725,16 +1855,8 @@ func bazelLabelForStaticWholeModuleDeps(ctx android.BazelConversionPathContext,
return label
}
-// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-cpp
-func xsdConfigCppTarget(ctx android.BazelConversionPathContext, mod blueprint.Module) string {
- callback := func(xsd android.XsdConfigBp2buildTargets) string {
- return xsd.CppBp2buildTargetName()
- }
- return android.XsdConfigBp2buildTarget(ctx, mod, callback)
-}
-
-func bazelLabelForXsdConfig(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, xsdConfigCppTarget)
+func xsdConfigCppTarget(xsd android.XsdConfigBp2buildTargets) string {
+ return xsd.CppBp2buildTargetName()
}
func bazelLabelForWholeDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
@@ -1804,8 +1926,16 @@ func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module
return attrs
}
-func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
+type sanitizerValues struct {
+ features bazel.StringListAttribute
+ copts bazel.StringListAttribute
+ additionalCompilerInputs bazel.LabelListAttribute
+}
+
+func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module) sanitizerValues {
sanitizerFeatures := bazel.StringListAttribute{}
+ sanitizerCopts := bazel.StringListAttribute{}
+ sanitizerCompilerInputs := bazel.LabelListAttribute{}
bp2BuildPropParseHelper(ctx, m, &SanitizeProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
var features []string
if sanitizerProps, ok := props.(*SanitizeProperties); ok {
@@ -1817,9 +1947,10 @@ func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module
}
blocklist := sanitizerProps.Sanitize.Blocklist
if blocklist != nil {
- // Format the blocklist name to be used in a feature name
- blocklistFeatureSuffix := strings.Replace(strings.ToLower(*blocklist), ".", "_", -1)
- features = append(features, "ubsan_blocklist_"+blocklistFeatureSuffix)
+ // TODO: b/294868620 - Change this not to use the special axis when completing the bug
+ coptValue := fmt.Sprintf("-fsanitize-ignorelist=$(location %s)", *blocklist)
+ sanitizerCopts.SetSelectValue(bazel.SanitizersEnabledAxis, bazel.SanitizersEnabled, []string{coptValue})
+ sanitizerCompilerInputs.SetSelectValue(bazel.SanitizersEnabledAxis, bazel.SanitizersEnabled, bazel.MakeLabelListFromTargetNames([]string{*blocklist}))
}
if sanitizerProps.Sanitize.Cfi != nil && !proptools.Bool(sanitizerProps.Sanitize.Cfi) {
features = append(features, "-android_cfi")
@@ -1832,7 +1963,11 @@ func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module
sanitizerFeatures.SetSelectValue(axis, config, features)
}
})
- return sanitizerFeatures
+ return sanitizerValues{
+ features: sanitizerFeatures,
+ copts: sanitizerCopts,
+ additionalCompilerInputs: sanitizerCompilerInputs,
+ }
}
func bp2buildLtoFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
diff --git a/cc/cc.go b/cc/cc.go
index 608797092..3b92696bc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -42,6 +42,7 @@ import (
func init() {
RegisterCCBuildComponents(android.InitRegistrationContext)
+ pctx.Import("android/soong/android")
pctx.Import("android/soong/cc/config")
}
@@ -73,6 +74,9 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
ctx.TopDown("afdo_deps", afdoDepsMutator)
ctx.BottomUp("afdo", afdoMutator).Parallel()
+ ctx.TopDown("orderfile_deps", orderfileDepsMutator)
+ ctx.BottomUp("orderfile", orderfileMutator).Parallel()
+
ctx.TopDown("lto_deps", ltoDepsMutator)
ctx.BottomUp("lto", ltoMutator).Parallel()
@@ -525,6 +529,7 @@ type ModuleContextIntf interface {
getVndkExtendsModuleName() string
isAfdoCompile() bool
isPgoCompile() bool
+ isOrderfileCompile() bool
isCfi() bool
isFuzzer() bool
isNDKStubLibrary() bool
@@ -568,6 +573,24 @@ type feature interface {
props() []interface{}
}
+// Information returned from Generator about the source code it's generating
+type GeneratedSource struct {
+ IncludeDirs android.Paths
+ Sources android.Paths
+ Headers android.Paths
+ ReexportedDirs android.Paths
+}
+
+// generator allows injection of generated code
+type Generator interface {
+ GeneratorProps() []interface{}
+ GeneratorInit(ctx BaseModuleContext)
+ GeneratorDeps(ctx DepsContext, deps Deps) Deps
+ GeneratorFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags
+ GeneratorSources(ctx ModuleContext) GeneratedSource
+ GeneratorBuildActions(ctx ModuleContext, flags Flags, deps PathDeps)
+}
+
// compiler is the interface for a compiler helper object. Different module decorators may implement
// this helper differently.
type compiler interface {
@@ -850,6 +873,7 @@ type Module struct {
// type-specific logic. These members may reference different objects or the same object.
// Functions of these decorators will be invoked to initialize and register type-specific
// build statements.
+ generators []Generator
compiler compiler
linker linker
installer installer
@@ -865,6 +889,7 @@ type Module struct {
lto *lto
afdo *afdo
pgo *pgo
+ orderfile *orderfile
library libraryInterface
@@ -1079,6 +1104,10 @@ func (c *Module) CcLibraryInterface() bool {
return false
}
+func (c *Module) RlibStd() bool {
+ panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
+}
+
func (c *Module) RustLibraryInterface() bool {
return false
}
@@ -1196,6 +1225,9 @@ func (c *Module) VndkVersion() string {
func (c *Module) Init() android.Module {
c.AddProperties(&c.Properties, &c.VendorProperties)
+ for _, generator := range c.generators {
+ c.AddProperties(generator.GeneratorProps()...)
+ }
if c.compiler != nil {
c.AddProperties(c.compiler.compilerProps()...)
}
@@ -1232,6 +1264,9 @@ func (c *Module) Init() android.Module {
if c.pgo != nil {
c.AddProperties(c.pgo.props()...)
}
+ if c.orderfile != nil {
+ c.AddProperties(c.orderfile.props()...)
+ }
for _, feature := range c.features {
c.AddProperties(feature.props()...)
}
@@ -1365,9 +1400,16 @@ func (c *Module) isPgoCompile() bool {
return false
}
+func (c *Module) isOrderfileCompile() bool {
+ if orderfile := c.orderfile; orderfile != nil {
+ return orderfile.Properties.OrderfileLoad
+ }
+ return false
+}
+
func (c *Module) isCfi() bool {
if sanitize := c.sanitize; sanitize != nil {
- return Bool(sanitize.Properties.Sanitize.Cfi)
+ return Bool(sanitize.Properties.SanitizeMutated.Cfi)
}
return false
}
@@ -1670,6 +1712,10 @@ func (ctx *moduleContextImpl) isPgoCompile() bool {
return ctx.mod.isPgoCompile()
}
+func (ctx *moduleContextImpl) isOrderfileCompile() bool {
+ return ctx.mod.isOrderfileCompile()
+}
+
func (ctx *moduleContextImpl) isCfi() bool {
return ctx.mod.isCfi()
}
@@ -1779,6 +1825,7 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo
module.lto = &lto{}
module.afdo = &afdo{}
module.pgo = &pgo{}
+ module.orderfile = &orderfile{}
return module
}
@@ -2144,6 +2191,25 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
return
}
+ for _, generator := range c.generators {
+ gen := generator.GeneratorSources(ctx)
+ deps.IncludeDirs = append(deps.IncludeDirs, gen.IncludeDirs...)
+ deps.ReexportedDirs = append(deps.ReexportedDirs, gen.ReexportedDirs...)
+ deps.GeneratedDeps = append(deps.GeneratedDeps, gen.Headers...)
+ deps.ReexportedGeneratedHeaders = append(deps.ReexportedGeneratedHeaders, gen.Headers...)
+ deps.ReexportedDeps = append(deps.ReexportedDeps, gen.Headers...)
+ if len(deps.Objs.objFiles) == 0 {
+ // If we are reusuing object files (which happens when we're a shared library and we're
+ // reusing our static variant's object files), then skip adding the actual source files,
+ // because we already have the object for it.
+ deps.GeneratedSources = append(deps.GeneratedSources, gen.Sources...)
+ }
+ }
+
+ if ctx.Failed() {
+ return
+ }
+
if c.stubLibraryMultipleApexViolation(actx) {
actx.PropertyErrorf("apex_available",
"Stub libraries should have a single apex_available (test apexes excluded). Got %v", c.ApexAvailable())
@@ -2158,6 +2224,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
Toolchain: c.toolchain(ctx),
EmitXrefs: ctx.Config().EmitXrefRules(),
}
+ for _, generator := range c.generators {
+ flags = generator.GeneratorFlags(ctx, flags, deps)
+ }
if c.compiler != nil {
flags = c.compiler.compilerFlags(ctx, flags, deps)
}
@@ -2185,6 +2254,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if c.pgo != nil {
flags = c.pgo.flags(ctx, flags)
}
+ if c.orderfile != nil {
+ flags = c.orderfile.flags(ctx, flags)
+ }
for _, feature := range c.features {
flags = feature.flags(ctx, flags)
}
@@ -2215,6 +2287,10 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
flags.AssemblerWithCpp = inList("-xassembler-with-cpp", flags.Local.AsFlags)
+ for _, generator := range c.generators {
+ generator.GeneratorBuildActions(ctx, flags, deps)
+ }
+
var objs Objects
if c.compiler != nil {
objs = c.compiler.compile(ctx, flags, deps)
@@ -2302,6 +2378,9 @@ func (c *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
}
func (c *Module) begin(ctx BaseModuleContext) {
+ for _, generator := range c.generators {
+ generator.GeneratorInit(ctx)
+ }
if c.compiler != nil {
c.compiler.compilerInit(ctx)
}
@@ -2320,6 +2399,9 @@ func (c *Module) begin(ctx BaseModuleContext) {
if c.lto != nil {
c.lto.begin(ctx)
}
+ if c.orderfile != nil {
+ c.orderfile.begin(ctx)
+ }
if c.pgo != nil {
c.pgo.begin(ctx)
}
@@ -2337,6 +2419,9 @@ func (c *Module) begin(ctx BaseModuleContext) {
func (c *Module) deps(ctx DepsContext) Deps {
deps := Deps{}
+ for _, generator := range c.generators {
+ deps = generator.GeneratorDeps(ctx, deps)
+ }
if c.compiler != nil {
deps = c.compiler.compilerDeps(ctx, deps)
}
@@ -2945,20 +3030,20 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin
ctx.ModuleErrorf("links %q built against newer API version %q",
ctx.OtherModuleName(to.Module()), "current")
} else {
- fromApi, err := strconv.Atoi(from.SdkVersion())
+ fromApi, err := android.ApiLevelFromUserWithConfig(ctx.Config(), from.SdkVersion())
if err != nil {
ctx.PropertyErrorf("sdk_version",
- "Invalid sdk_version value (must be int or current): %q",
+ "Invalid sdk_version value (must be int, preview or current): %q",
from.SdkVersion())
}
- toApi, err := strconv.Atoi(to.SdkVersion())
+ toApi, err := android.ApiLevelFromUserWithConfig(ctx.Config(), to.SdkVersion())
if err != nil {
ctx.PropertyErrorf("sdk_version",
- "Invalid sdk_version value (must be int or current): %q",
+ "Invalid sdk_version value (must be int, preview or current): %q",
to.SdkVersion())
}
- if toApi > fromApi {
+ if toApi.GreaterThan(fromApi) {
ctx.ModuleErrorf("links %q built against newer API version %q",
ctx.OtherModuleName(to.Module()), to.SdkVersion())
}
@@ -4225,6 +4310,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
&LTOProperties{},
&AfdoProperties{},
&PgoProperties{},
+ &OrderfileProperties{},
&android.ProtoProperties{},
// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
&RustBindgenClangProperties{},
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7534db222..7ce0f3715 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -654,6 +654,7 @@ func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
+ config.TestProductVariables.KeepVndk = BoolPtr(true)
ctx := testCcWithConfig(t, config)
module := ctx.ModuleForTests("llndk.libraries.txt", "android_common")
@@ -3261,7 +3262,7 @@ func TestLibDepAndroidMkExportInMixedBuilds(t *testing.T) {
},
},
LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
- "//:test": cquery.CcUnstrippedInfo{
+ "//:test__tf_internal": cquery.CcUnstrippedInfo{
CcAndroidMkInfo: tc.androidMkInfo,
},
"//:binary": cquery.CcUnstrippedInfo{
diff --git a/cc/compiler.go b/cc/compiler.go
index 16f4a6ec0..5bed8a72f 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -189,13 +189,13 @@ type BaseCompilerProperties struct {
// build the recovery variant of the C/C++ module.
Exclude_generated_sources []string
}
- Vendor_ramdisk struct {
+ Ramdisk, Vendor_ramdisk struct {
// list of source files that should not be used to
- // build the vendor ramdisk variant of the C/C++ module.
+ // build the ramdisk variants of the C/C++ module.
Exclude_srcs []string `android:"path"`
- // List of additional cflags that should be used to build the vendor ramdisk
- // variant of the C/C++ module.
+ // List of additional cflags that should be used to build the ramdisk
+ // variants of the C/C++ module.
Cflags []string
}
Platform struct {
@@ -351,6 +351,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
CheckBadCompilerFlags(ctx, "product.cflags", compiler.Properties.Target.Product.Cflags)
CheckBadCompilerFlags(ctx, "recovery.cflags", compiler.Properties.Target.Recovery.Cflags)
+ CheckBadCompilerFlags(ctx, "ramdisk.cflags", compiler.Properties.Target.Ramdisk.Cflags)
CheckBadCompilerFlags(ctx, "vendor_ramdisk.cflags", compiler.Properties.Target.Vendor_ramdisk.Cflags)
CheckBadCompilerFlags(ctx, "platform.cflags", compiler.Properties.Target.Platform.Cflags)
@@ -536,6 +537,9 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
if ctx.inVendorRamdisk() {
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor_ramdisk.Cflags)...)
}
+ if ctx.inRamdisk() {
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Ramdisk.Cflags)...)
+ }
if !ctx.useSdk() {
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Platform.Cflags)...)
}
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index ca2e05fc3..12722a7de 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -100,7 +100,15 @@ func init() {
return strings.Join(flags, " ")
})
- exportedVars.ExportStringListStaticVariable("Arm64Cflags", arm64Cflags)
+ exportedVars.ExportStringList("Arm64Cflags", arm64Cflags)
+ pctx.VariableFunc("Arm64Cflags", func(ctx android.PackageVarContext) string {
+ flags := arm64Cflags
+ if ctx.Config().PageSizeAgnostic() {
+ flags = append(flags, "-D__BIONIC_NO_PAGE_SIZE_MACRO")
+ }
+ return strings.Join(flags, " ")
+ })
+
exportedVars.ExportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
exportedVars.ExportVariableReferenceDict("Arm64ArchVariantCflags", arm64ArchVariantCflagsVar)
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index dec2b4552..3d6890cf0 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -43,9 +43,7 @@ var (
armNoFixCortexA8LdFlags = []string{"-Wl,--no-fix-cortex-a8"}
- armArmCflags = []string{
- "-fstrict-aliasing",
- }
+ armArmCflags = []string{}
armThumbCflags = []string{
"-mthumb",
@@ -185,12 +183,7 @@ func init() {
exportedVars.ExportString("ArmClangTriple", clangTriple)
exportedVars.ExportStringListStaticVariable("ArmLdflags", armLdflags)
- exportedVars.ExportStringList("ArmLldflags", armLldflags)
- pctx.VariableFunc("ArmLldflags", func(ctx android.PackageVarContext) string {
- maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
- flags := append(armLldflags, maxPageSizeFlag)
- return strings.Join(flags, " ")
- })
+ exportedVars.ExportStringListStaticVariable("ArmLldflags", armLldflags)
exportedVars.ExportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
exportedVars.ExportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
diff --git a/cc/config/global.go b/cc/config/global.go
index e450ba7ba..ff5ab051e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -48,7 +48,6 @@ var (
"-Wno-multichar",
"-O2",
- "-g",
"-fdebug-default-version=5",
"-fno-strict-aliasing",
@@ -111,6 +110,9 @@ var (
// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
"-ffp-contract=off",
+
+ // Using simple template names reduces the size of debug builds.
+ "-gsimple-template-names",
}
commonGlobalConlyflags = []string{}
@@ -147,6 +149,7 @@ var (
commonGlobalLldflags = []string{
"-fuse-ld=lld",
"-Wl,--icf=safe",
+ "-Wl,--no-demangle",
}
deviceGlobalCppflags = []string{
@@ -305,7 +308,7 @@ var (
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r487747c"
+ ClangDefaultVersion = "clang-r498229"
ClangDefaultShortVersion = "17"
// Directories with warnings from Android.bp files.
@@ -374,6 +377,21 @@ func init() {
flags = append(flags, "-Wno-error=unknown-warning-option")
}
+ switch ctx.Config().Getenv("CLANG_DEFAULT_DEBUG_LEVEL") {
+ case "debug_level_0":
+ flags = append(flags, "-g0")
+ case "debug_level_1":
+ flags = append(flags, "-g1")
+ case "debug_level_2":
+ flags = append(flags, "-g2")
+ case "debug_level_3":
+ flags = append(flags, "-g3")
+ case "debug_level_g":
+ flags = append(flags, "-g")
+ default:
+ flags = append(flags, "-g")
+ }
+
return strings.Join(flags, " ")
})
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 3bc1e69c3..40919c0cf 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -26,9 +26,6 @@ var (
// Help catch common 32/64-bit errors.
"-Werror=implicit-function-declaration",
"-fno-emulated-tls",
- // A temporary fix for SExtWRemoval miscompilation bug.
- "-mllvm",
- "-riscv-disable-sextw-removal=true",
"-march=rv64gc_zba_zbb_zbs",
}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index a0ef57595..62f75d1bd 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -261,5 +261,3 @@ func LibFuzzerRuntimeLibrary(t Toolchain) string {
func LibFuzzerRuntimeInterceptors(t Toolchain) string {
return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
}
-
-var inList = android.InList
diff --git a/cc/coverage.go b/cc/coverage.go
index c0f697398..cbd8a6f3e 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -48,6 +48,7 @@ func (cov *coverage) props() []interface{} {
func getGcovProfileLibraryName(ctx ModuleContextIntf) string {
// This function should only ever be called for a cc.Module, so the
// following statement should always succeed.
+ // LINT.IfChange
if ctx.useSdk() {
return "libprofile-extras_ndk"
} else {
@@ -63,6 +64,7 @@ func getClangProfileLibraryName(ctx ModuleContextIntf) string {
} else {
return "libprofile-clang-extras"
}
+ // LINT.ThenChange(library.go)
}
func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 636ad855b..227fe8bcf 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -29,6 +29,7 @@ import (
func init() {
android.RegisterModuleType("cc_fuzz", LibFuzzFactory)
android.RegisterParallelSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
+ android.RegisterParallelSingletonType("cc_fuzz_presubmit_packaging", fuzzPackagingFactoryPresubmit)
}
type FuzzProperties struct {
@@ -258,25 +259,29 @@ func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
- builder := android.NewRuleBuilder(pctx, ctx)
intermediateDir := android.PathForModuleOut(ctx, "corpus")
+
+ // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit.
for _, entry := range fuzzPackagedModule.Corpus {
- builder.Command().Text("cp").
- Input(entry).
- Output(intermediateDir.Join(ctx, entry.Base()))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: intermediateDir.Join(ctx, entry.Base()),
+ Input: entry,
+ })
}
- builder.Build("copy_corpus", "copy corpus")
fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
- builder = android.NewRuleBuilder(pctx, ctx)
intermediateDir = android.PathForModuleOut(ctx, "data")
+
+ // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit.
for _, entry := range fuzzPackagedModule.Data {
- builder.Command().Text("cp").
- Input(entry).
- Output(intermediateDir.Join(ctx, entry.Rel()))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: intermediateDir.Join(ctx, entry.Rel()),
+ Input: entry,
+ })
}
- builder.Build("copy_data", "copy data")
fuzzPackagedModule.DataIntermediateDir = intermediateDir
if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
@@ -352,9 +357,10 @@ func NewFuzzer(hod android.HostOrDeviceSupported) *Module {
// their architecture & target/host specific zip file.
type ccRustFuzzPackager struct {
fuzz.FuzzPackager
- fuzzPackagingArchModules string
- fuzzTargetSharedDepsInstallPairs string
- allFuzzTargetsName string
+ fuzzPackagingArchModules string
+ fuzzTargetSharedDepsInstallPairs string
+ allFuzzTargetsName string
+ onlyIncludePresubmits bool
}
func fuzzPackagingFactory() android.Singleton {
@@ -363,6 +369,18 @@ func fuzzPackagingFactory() android.Singleton {
fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
allFuzzTargetsName: "ALL_FUZZ_TARGETS",
+ onlyIncludePresubmits: false,
+ }
+ return fuzzPackager
+}
+
+func fuzzPackagingFactoryPresubmit() android.Singleton {
+
+ fuzzPackager := &ccRustFuzzPackager{
+ fuzzPackagingArchModules: "SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES",
+ fuzzTargetSharedDepsInstallPairs: "PRESUBMIT_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+ allFuzzTargetsName: "ALL_PRESUBMIT_FUZZ_TARGETS",
+ onlyIncludePresubmits: true,
}
return fuzzPackager
}
@@ -386,7 +404,6 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
if !ok || ccModule.PreventInstall() {
return
}
-
// Discard non-fuzz targets.
if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok {
return
@@ -403,6 +420,9 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
} else if ccModule.Host() {
hostOrTargetString = "host"
}
+ if s.onlyIncludePresubmits == true {
+ hostOrTargetString = "presubmit-" + hostOrTargetString
+ }
fpm := fuzz.FuzzPackagedModule{}
if ok {
@@ -427,6 +447,14 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext)
// The executable.
files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, ccModule, "unstripped")})
+ if s.onlyIncludePresubmits == true {
+ if fpm.FuzzProperties.Fuzz_config == nil {
+ return
+ }
+ if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false){
+ return
+ }
+ }
archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
return
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
new file mode 100644
index 000000000..55e19f9a9
--- /dev/null
+++ b/cc/generated_cc_library.go
@@ -0,0 +1,38 @@
+// 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 cc
+
+import (
+ "android/soong/android"
+)
+
+func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) android.Module {
+ module, _ := NewLibrary(android.HostAndDeviceSupported)
+
+ // Can be used as both a static and a shared library.
+ module.sdkMemberTypes = []android.SdkMemberType{
+ sharedLibrarySdkMemberType,
+ staticLibrarySdkMemberType,
+ staticAndSharedLibrarySdkMemberType,
+ }
+
+ // TODO: Need to be bazelable
+ // module.bazelable = true
+ // module.bazelHandler = &ccLibraryBazelHandler{module: module}
+
+ module.generators = append(module.generators, callbacks)
+
+ return module.Init()
+}
diff --git a/cc/image.go b/cc/image.go
index e65a9aadb..f91762adc 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -678,10 +678,17 @@ func squashVendorRamdiskSrcs(m *Module) {
}
}
+func squashRamdiskSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...)
+ }
+}
+
func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
m := module.(*Module)
if variant == android.RamdiskVariation {
m.MakeAsPlatform()
+ squashRamdiskSrcs(m)
} else if variant == android.VendorRamdiskVariation {
m.MakeAsPlatform()
squashVendorRamdiskSrcs(m)
diff --git a/cc/library.go b/cc/library.go
index aec6433d8..2d4d60440 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -32,6 +32,20 @@ import (
"github.com/google/blueprint/proptools"
)
+var (
+ alwaysLinkLibraries = map[string]bool{
+ // Coverage libraries are _always_ added as a whole_static_dep. By converting as these as
+ // alwayslink = True, we can add these as to deps (e.g. as a regular static dep) in Bazel
+ // without any extra complications in cc_shared_library roots to prevent linking the same
+ // library repeatedly.
+ "libprofile-extras_ndk": true,
+ "libprofile-extras": true,
+ "libprofile-clang-extras_ndk": true,
+ "libprofile-clang-extras_cfi_support": true,
+ "libprofile-clang-extras": true,
+ }
+)
+
// LibraryProperties is a collection of properties shared by cc library rules/cc.
type LibraryProperties struct {
// local file name to pass to the linker as -unexported_symbols_list
@@ -335,6 +349,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Runtime_deps: linkerAttrs.runtimeDeps,
sdkAttributes: bp2BuildParseSdkAttributes(m),
Native_coverage: baseAttributes.Native_coverage,
+ Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
}
includeAttrs := includesAttributes{
@@ -362,6 +377,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Runtime_deps: linkerAttrs.runtimeDeps,
sdkAttributes: bp2BuildParseSdkAttributes(m),
Native_coverage: baseAttributes.Native_coverage,
+ Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
}
staticTargetAttrs := &bazelCcLibraryStaticAttributes{
@@ -435,6 +451,10 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
Bzl_load_location: "//build/bazel/rules/cc:cc_library_shared.bzl",
}
+ if _, ok := alwaysLinkLibraries[m.Name()]; ok {
+ staticTargetAttrs.Alwayslink = proptools.BoolPtr(true)
+ }
+
var tagsForStaticVariant bazel.StringListAttribute
if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
@@ -1963,6 +1983,10 @@ func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, referen
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName + " -ref-dump-dir $$ANDROID_BUILD_TOP/" + refDumpDir
+ // Most opt-in libraries do not have dumps for all default architectures.
+ if ctx.Config().HasDeviceProduct() {
+ errorMessage += " -products " + ctx.Config().DeviceProduct()
+ }
library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt,
isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
@@ -2271,7 +2295,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
// do not install vndk libs
// vndk libs are packaged into VNDK APEX
- if ctx.isVndk() && !ctx.IsVndkExt() {
+ if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() {
return
}
} else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() {
@@ -2940,6 +2964,7 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo
sdkAttributes: bp2BuildParseSdkAttributes(module),
Runtime_deps: linkerAttrs.runtimeDeps,
Native_coverage: baseAttributes.Native_coverage,
+ Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
}
module.convertTidyAttributes(ctx, &commonAttrs.tidyAttributes)
@@ -2947,6 +2972,10 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo
var attrs interface{}
if isStatic {
commonAttrs.Deps.Add(baseAttributes.protoDependency)
+ var alwayslink *bool
+ if _, ok := alwaysLinkLibraries[module.Name()]; ok && isStatic {
+ alwayslink = proptools.BoolPtr(true)
+ }
attrs = &bazelCcLibraryStaticAttributes{
staticOrSharedAttributes: commonAttrs,
Rtti: compilerAttrs.rtti,
@@ -2960,8 +2989,10 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
- Features: *features,
+ Alwayslink: alwayslink,
+ Features: *features,
}
+
} else {
commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
@@ -3043,7 +3074,8 @@ type bazelCcLibraryStaticAttributes struct {
Conlyflags bazel.StringListAttribute
Asflags bazel.StringListAttribute
- Features bazel.StringListAttribute
+ Alwayslink *bool
+ Features bazel.StringListAttribute
}
// TODO(b/199902614): Can this be factored to share with the other Attributes?
diff --git a/cc/linkable.go b/cc/linkable.go
index 19e6501de..209939916 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -87,6 +87,12 @@ type Snapshottable interface {
// SnapshotStaticLibs returns the list of static library dependencies for this module.
SnapshotStaticLibs() []string
+ // SnapshotDylibs returns the list of dylib library dependencies for this module.
+ SnapshotDylibs() []string
+
+ // SnapshotRlibs returns the list of rlib library dependencies for this module.
+ SnapshotRlibs() []string
+
// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
IsSnapshotPrebuilt() bool
}
@@ -239,6 +245,9 @@ type LinkableInterface interface {
// Dylib returns true if this is an dylib module.
Dylib() bool
+ // RlibStd returns true if this is an rlib which links against an rlib libstd.
+ RlibStd() bool
+
// Static returns true if this is a static library module.
Static() bool
diff --git a/cc/lto.go b/cc/lto.go
index 510dd79de..820c1f08c 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -47,6 +47,7 @@ type LTOProperties struct {
} `android:"arch_variant"`
LtoEnabled bool `blueprint:"mutated"`
+ LtoDefault bool `blueprint:"mutated"`
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
@@ -66,7 +67,37 @@ func (lto *lto) props() []interface{} {
}
func (lto *lto) begin(ctx BaseModuleContext) {
- lto.Properties.LtoEnabled = lto.LTO(ctx)
+ // First, determine the module indepedent default LTO mode.
+ ltoDefault := GlobalThinLTO(ctx)
+ if ctx.Config().IsEnvTrue("DISABLE_LTO") {
+ ltoDefault = false
+ } else if ctx.Host() {
+ // Performance and binary size are less important for host binaries.
+ ltoDefault = false
+ } else if ctx.Arch().ArchType.Multilib == "lib32" {
+ // LP32 has many subtle issues and less test coverage.
+ ltoDefault = false
+ }
+
+ // Then, determine the actual LTO mode to use. If different from `ltoDefault`, a variant needs
+ // to be created.
+ ltoEnabled := ltoDefault
+ if lto.Never() {
+ ltoEnabled = false
+ } else if lto.ThinLTO() {
+ // Module explicitly requests for LTO.
+ ltoEnabled = true
+ } else if ctx.testBinary() || ctx.testLibrary() {
+ // Do not enable LTO for tests for better debugging.
+ ltoEnabled = false
+ } else if ctx.isVndk() {
+ // FIXME: ThinLTO for VNDK produces different output.
+ // b/169217596
+ ltoEnabled = false
+ }
+
+ lto.Properties.LtoDefault = ltoDefault
+ lto.Properties.LtoEnabled = ltoEnabled
}
func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
@@ -80,7 +111,7 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
var ltoLdFlags []string
// The module did not explicitly turn on LTO. Only leverage LTO's
- // better dead code elinmination and CFG simplification, but do
+ // better dead code elimination and CFG simplification, but do
// not perform costly optimizations for a balance between compile
// time, binary size and performance.
if !lto.ThinLTO() {
@@ -104,10 +135,14 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
ltoLdFlags = append(ltoLdFlags, cachePolicyFormat+policy)
}
- // If the module does not have a profile, be conservative and limit cross TU inline
- // limit to 5 LLVM IR instructions, to balance binary size increase and performance.
- if !ctx.Darwin() && !ctx.isPgoCompile() && !ctx.isAfdoCompile() {
- ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=5")
+ // Reduce the inlining threshold for a better balance of binary size and
+ // performance.
+ if !ctx.Darwin() {
+ if ctx.isPgoCompile() || ctx.isAfdoCompile() {
+ ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=40")
+ } else {
+ ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=5")
+ }
}
flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlags...)
@@ -118,34 +153,6 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
return flags
}
-// Determine which LTO mode to use for the given module.
-func (lto *lto) LTO(ctx BaseModuleContext) bool {
- if lto.Never() {
- return false
- }
- if ctx.Config().IsEnvTrue("DISABLE_LTO") {
- return false
- }
- // Module explicitly requests for LTO.
- if lto.ThinLTO() {
- return true
- }
- // LP32 has many subtle issues and less test coverage.
- if ctx.Arch().ArchType.Multilib == "lib32" {
- return false
- }
- // Performance and binary size are less important for host binaries and tests.
- if ctx.Host() || ctx.testBinary() || ctx.testLibrary() {
- return false
- }
- // FIXME: ThinLTO for VNDK produces different output.
- // b/169217596
- if ctx.isVndk() {
- return false
- }
- return GlobalThinLTO(ctx)
-}
-
func (lto *lto) ThinLTO() bool {
return lto != nil && proptools.Bool(lto.Properties.Lto.Thin)
}
@@ -160,10 +167,8 @@ func GlobalThinLTO(ctx android.BaseModuleContext) bool {
// Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
- defaultLTOMode := GlobalThinLTO(mctx)
-
if m, ok := mctx.Module().(*Module); ok {
- if m.lto == nil || m.lto.Properties.LtoEnabled == defaultLTOMode {
+ if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault {
return
}
@@ -238,6 +243,7 @@ func ltoMutator(mctx android.BottomUpMutatorContext) {
}
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
+ variation.lto.Properties.LtoDefault = m.lto.Properties.LtoDefault
variation.lto.Properties.LtoDep = false
variation.lto.Properties.NoLtoDep = false
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index f0b7cc52b..9281aebb5 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -31,9 +31,8 @@ import (
func init() {
pctx.HostBinToolVariable("ndkStubGenerator", "ndkstubgen")
- pctx.HostBinToolVariable("abidiff", "abidiff")
- pctx.HostBinToolVariable("abitidy", "abitidy")
- pctx.HostBinToolVariable("abidw", "abidw")
+ pctx.HostBinToolVariable("stg", "stg")
+ pctx.HostBinToolVariable("stgdiff", "stgdiff")
}
var (
@@ -44,28 +43,20 @@ var (
CommandDeps: []string{"$ndkStubGenerator"},
}, "arch", "apiLevel", "apiMap", "flags")
- abidw = pctx.AndroidStaticRule("abidw",
+ stg = pctx.AndroidStaticRule("stg",
blueprint.RuleParams{
- Command: "$abidw --type-id-style hash --no-corpus-path " +
- "--no-show-locs --no-comp-dir-path -w $symbolList " +
- "$in --out-file $out",
- CommandDeps: []string{"$abidw"},
+ Command: "$stg -S :$symbolList --elf $in -o $out",
+ CommandDeps: []string{"$stg"},
}, "symbolList")
- abitidy = pctx.AndroidStaticRule("abitidy",
- blueprint.RuleParams{
- Command: "$abitidy --all $flags -i $in -o $out",
- CommandDeps: []string{"$abitidy"},
- }, "flags")
-
- abidiff = pctx.AndroidStaticRule("abidiff",
+ stgdiff = pctx.AndroidStaticRule("stgdiff",
blueprint.RuleParams{
// Need to create *some* output for ninja. We don't want to use tee
// because we don't want to spam the build output with "nothing
// changed" messages, so redirect output message to $out, and if
// changes were detected print the output and fail.
- Command: "$abidiff $args $in > $out || (cat $out && false)",
- CommandDeps: []string{"$abidiff"},
+ Command: "$stgdiff $args --stg $in -o $out || (cat $out && false)",
+ CommandDeps: []string{"$stgdiff"},
}, "args")
ndkLibrarySuffix = ".ndk"
@@ -107,12 +98,6 @@ type libraryProperties struct {
// https://github.com/android-ndk/ndk/issues/265.
Unversioned_until *string
- // If true, does not emit errors when APIs lacking type information are
- // found. This is false by default and should not be enabled outside bionic,
- // where it is enabled pending a fix for http://b/190554910 (no debug info
- // for asm implemented symbols).
- Allow_untyped_symbols *bool
-
// Headers presented by this library to the Public API Surface
Export_header_libs []string
}
@@ -326,7 +311,7 @@ func (this *stubDecorator) findPrebuiltAbiDump(ctx ModuleContext,
apiLevel android.ApiLevel) android.OptionalPath {
subpath := filepath.Join("prebuilts/abi-dumps/ndk", apiLevel.String(),
- ctx.Arch().ArchType.String(), this.libraryName(ctx), "abi.xml")
+ ctx.Arch().ArchType.String(), this.libraryName(ctx), "abi.stg")
return android.ExistentPathForSource(ctx, subpath)
}
@@ -359,34 +344,17 @@ func canDiffAbi() bool {
func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
implementationLibrary := this.findImplementationLibrary(ctx)
- abiRawPath := getNdkAbiDumpInstallBase(ctx).Join(ctx,
+ this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
this.apiLevel.String(), ctx.Arch().ArchType.String(),
- this.libraryName(ctx), "abi.raw.xml")
+ this.libraryName(ctx), "abi.stg")
ctx.Build(pctx, android.BuildParams{
- Rule: abidw,
- Description: fmt.Sprintf("abidw %s", implementationLibrary),
+ Rule: stg,
+ Description: fmt.Sprintf("stg %s", implementationLibrary),
Input: implementationLibrary,
- Output: abiRawPath,
Implicit: symbolList,
- Args: map[string]string{
- "symbolList": symbolList.String(),
- },
- })
-
- this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
- this.apiLevel.String(), ctx.Arch().ArchType.String(),
- this.libraryName(ctx), "abi.xml")
- untypedFlag := "--abort-on-untyped-symbols"
- if proptools.BoolDefault(this.properties.Allow_untyped_symbols, false) {
- untypedFlag = ""
- }
- ctx.Build(pctx, android.BuildParams{
- Rule: abitidy,
- Description: fmt.Sprintf("abitidy %s", implementationLibrary),
- Input: abiRawPath,
Output: this.abiDumpPath,
Args: map[string]string{
- "flags": untypedFlag,
+ "symbolList": symbolList.String(),
},
})
}
@@ -405,7 +373,7 @@ func findNextApiLevel(ctx ModuleContext, apiLevel android.ApiLevel) *android.Api
func (this *stubDecorator) diffAbi(ctx ModuleContext) {
// Catch any ABI changes compared to the checked-in definition of this API
// level.
- abiDiffPath := android.PathForModuleOut(ctx, "abidiff.timestamp")
+ abiDiffPath := android.PathForModuleOut(ctx, "stgdiff.timestamp")
prebuiltAbiDump := this.findPrebuiltAbiDump(ctx, this.apiLevel)
missingPrebuiltError := fmt.Sprintf(
"Did not find prebuilt ABI dump for %q (%q). Generate with "+
@@ -421,11 +389,14 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) {
})
} else {
ctx.Build(pctx, android.BuildParams{
- Rule: abidiff,
- Description: fmt.Sprintf("abidiff %s %s", prebuiltAbiDump,
+ Rule: stgdiff,
+ Description: fmt.Sprintf("Comparing ABI %s %s", prebuiltAbiDump,
this.abiDumpPath),
Output: abiDiffPath,
Inputs: android.Paths{prebuiltAbiDump.Path(), this.abiDumpPath},
+ Args: map[string]string{
+ "args": "--format=small",
+ },
})
}
this.abiDiffPaths = append(this.abiDiffPaths, abiDiffPath)
@@ -452,13 +423,13 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) {
})
} else {
ctx.Build(pctx, android.BuildParams{
- Rule: abidiff,
+ Rule: stgdiff,
Description: fmt.Sprintf("abidiff %s %s", this.abiDumpPath,
nextAbiDump),
Output: nextAbiDiffPath,
Inputs: android.Paths{this.abiDumpPath, nextAbiDump.Path()},
Args: map[string]string{
- "args": "--no-added-syms",
+ "args": "--format=small --ignore=interface_addition",
},
})
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 0cf21b65a..feb388037 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -58,7 +58,6 @@ import (
func init() {
RegisterNdkModuleTypes(android.InitRegistrationContext)
- pctx.Import("android/soong/android")
}
func RegisterNdkModuleTypes(ctx android.RegistrationContext) {
diff --git a/cc/orderfile.go b/cc/orderfile.go
new file mode 100644
index 000000000..b64c1c7a1
--- /dev/null
+++ b/cc/orderfile.go
@@ -0,0 +1,256 @@
+// 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.
+//
+// Note: If you want to know how to use orderfile for your binary or shared
+// library, you can go look at the README in toolchains/pgo-profiles/orderfiles
+
+package cc
+
+import (
+ "fmt"
+
+ "android/soong/android"
+)
+
+// Order files are text files containing symbols representing functions names.
+// Linkers (lld) uses order files to layout functions in a specific order.
+// These binaries with ordered symbols will reduce page faults and improve a program's launch time
+// due to the efficient loading of symbols during a program’s cold-start.
+var (
+ // Add flags to ignore warnings about symbols not be found
+ // or not allowed to be ordered
+ orderfileOtherFlags = []string{
+ "-Wl,--no-warn-symbol-ordering",
+ }
+
+ // Add folder projects for orderfiles
+ globalOrderfileProjects = []string{
+ "toolchain/pgo-profiles/orderfiles",
+ "vendor/google_data/pgo_profile/orderfiles",
+ }
+)
+
+var orderfileProjectsConfigKey = android.NewOnceKey("OrderfileProjects")
+
+const orderfileProfileFlag = "-forder-file-instrumentation"
+const orderfileUseFormat = "-Wl,--symbol-ordering-file=%s"
+
+func getOrderfileProjects(config android.DeviceConfig) []string {
+ return config.OnceStringSlice(orderfileProjectsConfigKey, func() []string {
+ return globalOrderfileProjects
+ })
+}
+
+func recordMissingOrderfile(ctx BaseModuleContext, missing string) {
+ getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
+}
+
+type OrderfileProperties struct {
+ Orderfile struct {
+ Instrumentation *bool
+ Order_file_path *string `android:"arch_variant"`
+ Load_order_file *bool `android:"arch_variant"`
+ // Additional compiler flags to use when building this module
+ // for orderfile profiling.
+ Cflags []string `android:"arch_variant"`
+ } `android:"arch_variant"`
+
+ ShouldProfileModule bool `blueprint:"mutated"`
+ OrderfileLoad bool `blueprint:"mutated"`
+ OrderfileInstrLink bool `blueprint:"mutated"`
+}
+
+type orderfile struct {
+ Properties OrderfileProperties
+}
+
+func (props *OrderfileProperties) shouldInstrument() bool {
+ return Bool(props.Orderfile.Instrumentation)
+}
+
+// ShouldLoadOrderfile returns true if we need to load the order file rather than
+// profile the binary or shared library
+func (props *OrderfileProperties) shouldLoadOrderfile() bool {
+ return Bool(props.Orderfile.Load_order_file) && props.Orderfile.Order_file_path != nil
+}
+
+// orderfileEnabled returns true for binaries and shared libraries
+// if instrument flag is set to true
+func (orderfile *orderfile) orderfileEnabled() bool {
+ return orderfile != nil && orderfile.Properties.shouldInstrument()
+}
+
+// orderfileLinkEnabled returns true for binaries and shared libraries
+// if you should instrument dependencies
+func (orderfile *orderfile) orderfileLinkEnabled() bool {
+ return orderfile != nil && orderfile.Properties.OrderfileInstrLink
+}
+
+func (orderfile *orderfile) props() []interface{} {
+ return []interface{}{&orderfile.Properties}
+}
+
+// Get the path to the order file by checking it is valid and not empty
+func (props *OrderfileProperties) getOrderfile(ctx BaseModuleContext) android.OptionalPath {
+ orderFile := *props.Orderfile.Order_file_path
+
+ // Test if the order file is present in any of the Orderfile projects
+ for _, profileProject := range getOrderfileProjects(ctx.DeviceConfig()) {
+ path := android.ExistentPathForSource(ctx, profileProject, orderFile)
+ if path.Valid() {
+ return path
+ }
+ }
+
+ // Record that this module's order file is absent
+ missing := *props.Orderfile.Order_file_path + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
+ recordMissingOrderfile(ctx, missing)
+
+ return android.OptionalPath{}
+}
+
+func (props *OrderfileProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+ flags.Local.CFlags = append(flags.Local.CFlags, orderfileProfileFlag)
+ flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm -enable-order-file-instrumentation")
+ flags.Local.CFlags = append(flags.Local.CFlags, props.Orderfile.Cflags...)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, orderfileProfileFlag)
+ return flags
+}
+
+
+func (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string {
+ flags := []string{fmt.Sprintf(orderfileUseFormat, file)}
+ flags = append(flags, orderfileOtherFlags...)
+ return flags
+}
+
+func (props *OrderfileProperties) addLoadFlags(ctx ModuleContext, flags Flags) Flags {
+ orderFile := props.getOrderfile(ctx)
+ orderFilePath := orderFile.Path()
+ loadFlags := props.loadOrderfileFlags(ctx, orderFilePath.String())
+
+ flags.Local.LdFlags = append(flags.Local.LdFlags, loadFlags...)
+
+ // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+ // if orderfile gets updated
+ flags.CFlagsDeps = append(flags.CFlagsDeps, orderFilePath)
+ flags.LdFlagsDeps = append(flags.LdFlagsDeps, orderFilePath)
+ return flags
+}
+
+func (orderfile *orderfile) begin(ctx BaseModuleContext) {
+ // Currently, we are not enabling orderfiles for host
+ if ctx.Host() {
+ return
+ }
+
+ // Currently, we are not enabling orderfiles to begin from static libraries
+ if ctx.static() && !ctx.staticBinary() {
+ return
+ }
+
+ if ctx.DeviceConfig().ClangCoverageEnabled() {
+ return
+ }
+
+ // Checking if orderfile is enabled for this module
+ if !orderfile.orderfileEnabled() {
+ return
+ }
+
+ orderfile.Properties.OrderfileLoad = orderfile.Properties.shouldLoadOrderfile()
+ orderfile.Properties.ShouldProfileModule = !orderfile.Properties.shouldLoadOrderfile()
+ orderfile.Properties.OrderfileInstrLink = orderfile.orderfileEnabled() && !orderfile.Properties.shouldLoadOrderfile()
+}
+
+func (orderfile *orderfile) flags(ctx ModuleContext, flags Flags) Flags {
+ props := orderfile.Properties
+ // Add flags to load the orderfile using the path in its Android.bp
+ if orderfile.Properties.OrderfileLoad {
+ flags = props.addLoadFlags(ctx, flags)
+ return flags
+ }
+
+ // Add flags to profile this module
+ if props.ShouldProfileModule {
+ flags = props.addInstrumentationProfileGatherFlags(ctx, flags)
+ return flags
+ }
+
+ return flags
+}
+
+// Propagate profile orderfile flags down from binaries and shared libraries
+// We do not allow propagation for load flags because the orderfile is specific
+// to the module (binary / shared library)
+func orderfileDepsMutator(mctx android.TopDownMutatorContext) {
+ if m, ok := mctx.Module().(*Module); ok {
+ if !m.orderfile.orderfileLinkEnabled() {
+ return
+ }
+ mctx.WalkDeps(func(dep android.
+ Module, parent android.Module) bool {
+ tag := mctx.OtherModuleDependencyTag(dep)
+ libTag, isLibTag := tag.(libraryDependencyTag)
+
+ // Do not recurse down non-static dependencies
+ if isLibTag {
+ if !libTag.static() {
+ return false
+ }
+ } else {
+ if tag != objDepTag && tag != reuseObjTag {
+ return false
+ }
+ }
+
+ if dep, ok := dep.(*Module); ok {
+ if m.orderfile.Properties.OrderfileInstrLink {
+ dep.orderfile.Properties.OrderfileInstrLink = true;
+ }
+ }
+
+ return true
+ })
+ }
+}
+
+// Create orderfile variants for modules that need them
+func orderfileMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*Module); ok && m.orderfile != nil {
+ if !m.static() && m.orderfile.orderfileEnabled() {
+ mctx.SetDependencyVariation("orderfile")
+ return
+ }
+
+ variationNames := []string{""}
+ if m.orderfile.Properties.OrderfileInstrLink {
+ variationNames = append(variationNames, "orderfile")
+ }
+
+ if len(variationNames) > 1 {
+ modules := mctx.CreateVariations(variationNames...)
+ for i, name := range variationNames {
+ if name == "" {
+ continue
+ }
+ variation := modules[i].(*Module)
+ variation.Properties.PreventInstall = true
+ variation.Properties.HideFromMake = true
+ variation.orderfile.Properties.ShouldProfileModule = true
+ variation.orderfile.Properties.OrderfileLoad = false
+ }
+ }
+ }
+}
diff --git a/cc/orderfile_test.go b/cc/orderfile_test.go
new file mode 100644
index 000000000..f68457d32
--- /dev/null
+++ b/cc/orderfile_test.go
@@ -0,0 +1,470 @@
+// 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 cc
+
+import (
+ "testing"
+ "strings"
+
+ "android/soong/android"
+)
+
+func TestOrderfileProfileSharedLibrary(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: false,
+ order_file_path: "",
+ },
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-forder-file-instrumentation"
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+
+ // Check cFlags of orderfile-enabled module
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check ldFlags of orderfile-enabled module
+ ldFlags := libTest.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
+ }
+}
+
+func TestOrderfileLoadSharedLibrary(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: true,
+ order_file_path: "libTest.orderfile",
+ },
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"),
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile"
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+
+ // Check ldFlags of orderfile-enabled module
+ ldFlags := libTest.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
+ }
+}
+
+func TestOrderfileProfileBinary(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_binary {
+ name: "test",
+ srcs: ["test.c"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: false,
+ order_file_path: "",
+ },
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-forder-file-instrumentation"
+
+ test := result.ModuleForTests("test", "android_arm64_armv8-a")
+
+ // Check cFlags of orderfile-enabled module
+ cFlags := test.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check ldFlags of orderfile-enabled module
+ ldFlags := test.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, expectedCFlag) {
+ t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
+ }
+}
+
+func TestOrderfileLoadBinary(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_binary {
+ name: "test",
+ srcs: ["test.c"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: true,
+ order_file_path: "test.orderfile",
+ },
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
+
+ test := result.ModuleForTests("test", "android_arm64_armv8-a")
+
+ // Check ldFlags of orderfile-enabled module
+ ldFlags := test.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, expectedCFlag) {
+ t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags)
+ }
+}
+
+// Profile flags should propagate through static libraries
+func TestOrderfileProfilePropagateStaticDeps(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: false,
+ order_file_path: "",
+ },
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ static_libs: ["libBar"],
+ }
+
+ cc_library_static {
+ name: "libBar",
+ srcs: ["bar.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-forder-file-instrumentation"
+
+ // Check cFlags of orderfile-enabled module
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check cFlags of orderfile variant static libraries
+ libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
+ libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
+
+ cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBarOfVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edge from orderfile-enabled module to orderfile variant static libraries
+ if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) {
+ t.Errorf("libTest missing dependency on orderfile variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) {
+ t.Errorf("libTest missing dependency on orderfile variant of libBar")
+ }
+
+ // Check cFlags of the non-orderfile variant static libraries
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+
+ cFlags = libFoo.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries
+ if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest has dependency on non-orderfile variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libTest has dependency on non-orderfile variant of libBar")
+ }
+}
+
+// Load flags should never propagate
+func TestOrderfileLoadPropagateStaticDeps(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: true,
+ order_file_path: "test.orderfile",
+ },
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ static_libs: ["libBar"],
+ }
+
+ cc_library_static {
+ name: "libBar",
+ srcs: ["bar.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"),
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
+
+ // Check ldFlags of orderfile-enabled module
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+
+ ldFlags := libTest.Rule("ld").Args["ldFlags"]
+ if !strings.Contains(ldFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags)
+ }
+
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+
+ // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
+ if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
+ }
+
+ // Make sure no orderfile variants are created for static libraries because the flags were not propagated
+ libFooVariants := result.ModuleVariantsForTests("libFoo")
+ for _, v := range libFooVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
+ }
+ }
+
+ libBarVariants := result.ModuleVariantsForTests("libBar")
+ for _, v := range libBarVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
+ }
+ }
+}
+
+// Profile flags should not propagate through shared libraries
+func TestOrderfileProfilePropagateSharedDeps(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ shared_libs: ["libFoo"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: false,
+ order_file_path: "",
+ },
+ }
+
+ cc_library_shared {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ static_libs: ["libBar"],
+ }
+
+ cc_library_static {
+ name: "libBar",
+ srcs: ["bar.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-forder-file-instrumentation"
+
+ // Check cFlags of orderfile-enabled module
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check cFlags of the static and shared libraries
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+
+ cFlags = libFoo.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
+ if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
+ }
+
+ // Make sure no orderfile variants are created for libraries because the flags were not propagated
+ libFooVariants := result.ModuleVariantsForTests("libFoo")
+ for _, v := range libFooVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
+ }
+ }
+
+ libBarVariants := result.ModuleVariantsForTests("libBar")
+ for _, v := range libBarVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
+ }
+ }
+}
+
+// Profile flags should not work or be propagated if orderfile flags start at a static library
+func TestOrderfileProfileStaticLibrary(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_static {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ orderfile : {
+ instrumentation: true,
+ load_order_file: false,
+ order_file_path: "",
+ },
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ static_libs: ["libBar"],
+ }
+
+ cc_library_static {
+ name: "libBar",
+ srcs: ["bar.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlag := "-forder-file-instrumentation"
+
+ // Check cFlags of module
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static")
+
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check cFlags of the static libraries
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+
+ cFlags = libFoo.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edge from orderfile-enabled module to non-orderfile variant libraries
+ if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libTest missing dependency on non-orderfile variant of libBar")
+ }
+
+ // Make sure no orderfile variants are created for static libraries because the flags were not propagated
+ libFooVariants := result.ModuleVariantsForTests("libFoo")
+ for _, v := range libFooVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v)
+ }
+ }
+
+ libBarVariants := result.ModuleVariantsForTests("libBar")
+ for _, v := range libBarVariants {
+ if strings.Contains(v, "orderfile") {
+ t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
+ }
+ }
+} \ No newline at end of file
diff --git a/cc/rs.go b/cc/rs.go
index 65072591f..93acdc7db 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -101,11 +101,12 @@ func rsGenerateCpp(ctx android.ModuleContext, rsFiles android.Paths, rsFlags str
func rsFlags(ctx ModuleContext, flags Flags, properties *BaseCompilerProperties) Flags {
targetApi := String(properties.Renderscript.Target_api)
if targetApi == "" && ctx.useSdk() {
- switch ctx.sdkVersion() {
- case "current", "system_current", "test_current":
- // Nothing
- default:
- targetApi = android.GetNumericSdkVersion(ctx.sdkVersion())
+ targetApiLevel := android.ApiLevelOrPanic(ctx, ctx.sdkVersion())
+ if targetApiLevel.IsCurrent() || targetApiLevel.IsPreview() {
+ // If the target level is current or preview, leave the 'target-api' unset.
+ // This signals to llvm-rs-cc that the development API should be used.
+ } else {
+ targetApi = targetApiLevel.String()
}
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 62e31d1ca..30bce9bff 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -56,10 +56,6 @@ var (
// higher number of "optimized out" stack variables.
// b/112437883.
"-instcombine-lower-dbg-declare=0",
- // TODO(b/159343917): HWASan and GlobalISel don't play nicely, and
- // GlobalISel is the default at -O0 on aarch64.
- "--aarch64-enable-global-isel-at-O=-1",
- "-fast-isel=false",
"-hwasan-use-after-scope=1",
"-dom-tree-reachability-max-bbs-to-explore=128",
}
@@ -91,6 +87,8 @@ var (
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all", "-ftrap-function=abort"}
+
+ noSanitizeLinkRuntimeFlag = "-fno-sanitize-link-runtime"
)
type SanitizerType int
@@ -411,6 +409,8 @@ func init() {
exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
+ exportedVars.ExportStringList("MinimalRuntimeFlags", minimalRuntimeFlags)
+
// Leave out "-flto" from the slices exported to bazel, as we will use the
// dedicated LTO feature for this. For C Flags and Linker Flags, also leave
// out the cross DSO flag which will be added separately under the correct conditions.
@@ -426,6 +426,8 @@ func init() {
exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
+ exportedVars.ExportString("NoSanitizeLinkRuntimeFlag", noSanitizeLinkRuntimeFlag)
+
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
}
@@ -646,10 +648,6 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
s.Scs = nil
}
- // ...but temporarily globally disabled on riscv64 (http://b/277909695).
- if ctx.Arch().ArchType == android.Riscv64 {
- s.Scs = nil
- }
// Memtag_heap is only implemented on AArch64.
// Memtag ABI is Android specific for now, so disable for host.
@@ -931,7 +929,7 @@ func (s *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
// Bionic and musl sanitizer runtimes have already been added as dependencies so that
// the right variant of the runtime will be used (with the "-android" or "-musl"
// suffixes), so don't let clang the runtime library.
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-link-runtime")
+ flags.Local.LdFlags = append(flags.Local.LdFlags, noSanitizeLinkRuntimeFlag)
} else {
// Host sanitizers only link symbols in the final executable, so
// there will always be undefined symbols in intermediate libraries.
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index a5729dfc0..bb1331051 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -100,6 +100,7 @@ const (
snapshotBinarySuffix = "_binary."
snapshotObjectSuffix = "_object."
SnapshotRlibSuffix = "_rlib."
+ SnapshotDylibSuffix = "_dylib."
)
type SnapshotProperties struct {
@@ -107,6 +108,7 @@ type SnapshotProperties struct {
Static_libs []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
Rlibs []string `android:"arch_variant"`
+ Dylibs []string `android:"arch_variant"`
Vndk_libs []string `android:"arch_variant"`
Binaries []string `android:"arch_variant"`
Objects []string `android:"arch_variant"`
@@ -186,6 +188,7 @@ func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) {
staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, SnapshotStaticSuffix)
sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, SnapshotSharedSuffix)
rlibs := collectSnapshotMap(s.properties.Rlibs, snapshotSuffix, SnapshotRlibSuffix)
+ dylibs := collectSnapshotMap(s.properties.Dylibs, snapshotSuffix, SnapshotDylibSuffix)
vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix)
for k, v := range vndkLibs {
sharedLibs[k] = v
@@ -198,11 +201,12 @@ func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) {
StaticLibs: staticLibs,
SharedLibs: sharedLibs,
Rlibs: rlibs,
+ Dylibs: dylibs,
})
}
type SnapshotInfo struct {
- HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs map[string]string
+ HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs, Dylibs map[string]string
}
var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps")
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index cf4617da3..1ee120eb8 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -57,6 +57,14 @@ func (m *Module) SnapshotStaticLibs() []string {
return m.Properties.SnapshotStaticLibs
}
+func (m *Module) SnapshotRlibs() []string {
+ return []string{}
+}
+
+func (m *Module) SnapshotDylibs() []string {
+ return []string{}
+}
+
// snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots.
type snapshotLibraryInterface interface {
libraryInterface
diff --git a/cc/stl.go b/cc/stl.go
index f1433efbf..8f92dcb40 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -80,8 +80,7 @@ func (stl *stl) begin(ctx BaseModuleContext) {
return ""
}
s = deduplicateStlInput(s)
- archHasNDKStl := ctx.Arch().ArchType != android.Riscv64
- if ctx.useSdk() && ctx.Device() && archHasNDKStl {
+ if ctx.useSdk() && ctx.Device() {
switch s {
case "", "system":
return "ndk_system"
@@ -120,11 +119,6 @@ func (stl *stl) begin(ctx BaseModuleContext) {
}()
}
-func needsLibAndroidSupport(ctx BaseModuleContext) bool {
- version := nativeApiLevelOrPanic(ctx, ctx.sdkVersion())
- return version.LessThan(android.FirstNonLibAndroidSupportVersion)
-}
-
func staticUnwinder(ctx android.BaseModuleContext) string {
vndkVersion := ctx.Module().(*Module).VndkVersion()
@@ -184,11 +178,6 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
} else {
deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
}
- if needsLibAndroidSupport(ctx) {
- // Use LateStaticLibs for ndk_libandroid_support so that its include directories
- // come after ndk_libc++_static or ndk_libc++_shared.
- deps.LateStaticLibs = append(deps.LateStaticLibs, "ndk_libandroid_support")
- }
deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
default:
panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
diff --git a/cc/test.go b/cc/test.go
index 3f5f71007..0be230151 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -267,7 +267,7 @@ func (test *testDecorator) gtest() bool {
return BoolDefault(test.LinkerProperties.Gtest, true)
}
-func (test *testDecorator) isolated(ctx BaseModuleContext) bool {
+func (test *testDecorator) isolated(ctx android.EarlyModuleContext) bool {
return BoolDefault(test.LinkerProperties.Isolated, false)
}
@@ -641,14 +641,27 @@ type ccTestBazelHandler struct {
var _ BazelHandler = (*ccTestBazelHandler)(nil)
+// The top level target named $label is a test_suite target,
+// not the internal cc_test executable target.
+//
+// This is to ensure `b test //$label` runs the test_suite target directly,
+// which depends on tradefed_test targets, instead of the internal cc_test
+// target, which doesn't have tradefed integrations.
+//
+// However, for cquery, we want the internal cc_test executable target, which
+// has the suffix "__tf_internal".
+func mixedBuildsTestLabel(label string) string {
+ return label + "__tf_internal"
+}
+
func (handler *ccTestBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
+ bazelCtx.QueueBazelRequest(mixedBuildsTestLabel(label), cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
}
func (handler *ccTestBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
+ info, err := bazelCtx.GetCcUnstrippedInfo(mixedBuildsTestLabel(label), android.GetConfigKey(ctx))
if err != nil {
ctx.ModuleErrorf(err.Error())
return
@@ -669,8 +682,7 @@ func (handler *ccTestBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleC
type testBinaryAttributes struct {
binaryAttributes
- Gtest bool
- Isolated bool
+ Gtest *bool
tidyAttributes
tradefed.TestConfigAttributes
@@ -708,13 +720,15 @@ func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
- for _, propIntf := range m.GetProperties() {
- if testLinkerProps, ok := propIntf.(*TestLinkerProperties); ok {
- testBinaryAttrs.Gtest = proptools.BoolDefault(testLinkerProps.Gtest, true)
- testBinaryAttrs.Isolated = proptools.BoolDefault(testLinkerProps.Isolated, true)
- break
- }
- }
+ testBinary := m.linker.(*testBinary)
+ gtest := testBinary.gtest()
+ gtestIsolated := testBinary.isolated(ctx)
+ // Use the underling bool pointer for Gtest in attrs
+ // This ensures that if this property is not set in Android.bp file, it will not be set in BUILD file either
+ // cc_test macro will default gtest to True
+ testBinaryAttrs.Gtest = testBinary.LinkerProperties.Gtest
+
+ addImplicitGtestDeps(ctx, &testBinaryAttrs, gtest, gtestIsolated)
for _, testProps := range m.GetProperties() {
if p, ok := testProps.(*TestBinaryProperties); ok {
@@ -727,7 +741,7 @@ func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
p.Auto_gen_config,
p.Test_options.Test_suite_tag,
p.Test_config_template,
- getTradefedConfigOptions(ctx, p, testBinaryAttrs.Isolated),
+ getTradefedConfigOptions(ctx, p, gtestIsolated),
&testInstallBase,
)
testBinaryAttrs.TestConfigAttributes = testConfigAttributes
@@ -747,3 +761,28 @@ func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
},
&testBinaryAttrs)
}
+
+// cc_test that builds using gtest needs some additional deps
+// addImplicitGtestDeps makes these deps explicit in the generated BUILD files
+func addImplicitGtestDeps(ctx android.BazelConversionPathContext, attrs *testBinaryAttributes, gtest, gtestIsolated bool) {
+ addDepsAndDedupe := func(lla *bazel.LabelListAttribute, modules []string) {
+ moduleLabels := android.BazelLabelForModuleDeps(ctx, modules)
+ lla.Value.Append(moduleLabels)
+ // Dedupe
+ lla.Value = bazel.FirstUniqueBazelLabelList(lla.Value)
+ }
+ // this must be kept in sync with Soong's implementation in:
+ // https://cs.android.com/android/_/android/platform/build/soong/+/460fb2d6d546b5ab493a7e5479998c4933a80f73:cc/test.go;l=300-313;drc=ec7314336a2b35ea30ce5438b83949c28e3ac429;bpv=1;bpt=0
+ if gtest {
+ // TODO - b/244433197: Handle canUseSdk
+ if gtestIsolated {
+ addDepsAndDedupe(&attrs.Deps, []string{"libgtest_isolated_main"})
+ addDepsAndDedupe(&attrs.Dynamic_deps, []string{"liblog"})
+ } else {
+ addDepsAndDedupe(&attrs.Deps, []string{
+ "libgtest_main",
+ "libgtest",
+ })
+ }
+ }
+}
diff --git a/cc/testing.go b/cc/testing.go
index d346739bd..d1632aaa6 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -423,11 +423,6 @@ func commonDefaultModules() string {
export_include_dirs: ["ndk_libc++_shared"],
}
- ndk_prebuilt_static_stl {
- name: "ndk_libandroid_support",
- export_include_dirs: ["ndk_libandroid_support"],
- }
-
cc_library_static {
name: "libgoogle-benchmark",
sdk_version: "current",
@@ -573,16 +568,15 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
// Additional files needed in tests that disallow non-existent source.
android.MockFS{
- "defaults/cc/common/libc.map.txt": nil,
- "defaults/cc/common/libdl.map.txt": nil,
- "defaults/cc/common/libm.map.txt": nil,
- "defaults/cc/common/ndk_libandroid_support": nil,
- "defaults/cc/common/ndk_libc++_shared": nil,
- "defaults/cc/common/crtbegin_so.c": nil,
- "defaults/cc/common/crtbegin.c": nil,
- "defaults/cc/common/crtend_so.c": nil,
- "defaults/cc/common/crtend.c": nil,
- "defaults/cc/common/crtbrand.c": nil,
+ "defaults/cc/common/libc.map.txt": nil,
+ "defaults/cc/common/libdl.map.txt": nil,
+ "defaults/cc/common/libm.map.txt": nil,
+ "defaults/cc/common/ndk_libc++_shared": nil,
+ "defaults/cc/common/crtbegin_so.c": nil,
+ "defaults/cc/common/crtbegin.c": nil,
+ "defaults/cc/common/crtend_so.c": nil,
+ "defaults/cc/common/crtend.c": nil,
+ "defaults/cc/common/crtbrand.c": nil,
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil,
diff --git a/cc/util.go b/cc/util.go
index 6d8ac435f..c93646b98 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -28,8 +28,8 @@ func includeDirsToFlags(dirs android.Paths) string {
return android.JoinWithPrefix(dirs.Strings(), "-I")
}
-var indexList = android.IndexList
-var inList = android.InList
+var indexList = android.IndexList[string]
+var inList = android.InList[string]
var filterList = android.FilterList
var removeListFromList = android.RemoveListFromList
var removeFromList = android.RemoveFromList
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index d2531c03d..9ea337b8d 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -108,10 +108,10 @@ func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietar
return false
}
}
- if sanitizable.Static() {
+ if sanitizable.Static() || sanitizable.Rlib() {
return sanitizable.OutputFile().Valid() && !isPrivate(image, m)
}
- if sanitizable.Shared() || sanitizable.Rlib() {
+ if sanitizable.Shared() || sanitizable.Dylib() {
if !sanitizable.OutputFile().Valid() {
return false
}
@@ -153,6 +153,8 @@ type snapshotJsonFlags struct {
SharedLibs []string `json:",omitempty"`
StaticLibs []string `json:",omitempty"`
RuntimeLibs []string `json:",omitempty"`
+ Dylibs []string `json:",omitempty"`
+ Rlibs []string `json:",omitempty"`
// extra config files
InitRc []string `json:",omitempty"`
@@ -283,8 +285,17 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS
if m.Shared() {
prop.SharedLibs = m.SnapshotSharedLibs()
}
- // static libs dependencies are required to collect the NOTICE files.
+
+ // dylibs collect both shared and dylib dependencies.
+ if m.Dylib() {
+ prop.SharedLibs = m.SnapshotSharedLibs()
+ prop.Dylibs = m.SnapshotDylibs()
+ }
+
+ // static and rlib libs dependencies are required to collect the NOTICE files.
prop.StaticLibs = m.SnapshotStaticLibs()
+ prop.Rlibs = m.SnapshotRlibs()
+
if sanitizable, ok := m.(PlatformSanitizeable); ok {
if sanitizable.Static() && sanitizable.SanitizePropDefined() {
prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded()
@@ -299,13 +310,15 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS
libType = "shared"
} else if m.Rlib() {
libType = "rlib"
+ } else if m.Dylib() {
+ libType = "dylib"
} else {
libType = "header"
}
var stem string
- // install .a or .so
+ // install .a, .rlib, .dylib.so, or .so
if libType != "header" {
libPath := m.OutputFile().Path()
stem = libPath.Base()
@@ -328,6 +341,12 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS
}
}
}
+ if m.Rlib() && m.RlibStd() {
+ // rlibs produce both rlib-std and dylib-std variants
+ ext := filepath.Ext(stem)
+ stem = strings.TrimSuffix(stem, ext) + ".rlib-std" + ext
+ prop.ModuleName += ".rlib-std"
+ }
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, m.RelativeInstallPath(), stem)
ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake))
} else {
@@ -341,8 +360,12 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS
prop.StaticExecutable = m.StaticExecutable()
prop.InstallInRoot = m.InstallInRoot()
prop.SharedLibs = m.SnapshotSharedLibs()
- // static libs dependencies are required to collect the NOTICE files.
+ prop.Dylibs = m.SnapshotDylibs()
+
+ // static and rlib dependencies are required to collect the NOTICE files.
prop.StaticLibs = m.SnapshotStaticLibs()
+ prop.Rlibs = m.SnapshotRlibs()
+
// install bin
binPath := m.OutputFile().Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
diff --git a/cc/vndk.go b/cc/vndk.go
index 7a2286eb1..95a5a4f47 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -39,25 +39,34 @@ const (
vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
)
-func VndkLibrariesTxtModules(vndkVersion string) []string {
+func VndkLibrariesTxtModules(vndkVersion string, ctx android.BaseModuleContext) []string {
if vndkVersion == "current" {
- return []string{
- llndkLibrariesTxt,
+ result := []string{
vndkCoreLibrariesTxt,
vndkSpLibrariesTxt,
vndkPrivateLibrariesTxt,
vndkProductLibrariesTxt,
}
+
+ // TODO(b/290159430) This part will not be required once deprecation of VNDK
+ // is handled with 'ro.vndk.version' property
+ if !ctx.Config().IsVndkDeprecated() {
+ result = append(result, llndkLibrariesTxt)
+ }
+
+ return result
}
// Snapshot vndks have their own *.libraries.VER.txt files.
// Note that snapshots don't have "vndkcorevariant.libraries.VER.txt"
- return []string{
- insertVndkVersion(llndkLibrariesTxt, vndkVersion),
+ result := []string{
insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
insertVndkVersion(vndkProductLibrariesTxt, vndkVersion),
+ insertVndkVersion(llndkLibrariesTxt, vndkVersion),
}
+
+ return result
}
type VndkProperties struct {
@@ -519,11 +528,15 @@ func insertVndkVersion(filename string, vndkVersion string) string {
}
func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- var filename string
- if BoolDefault(txt.properties.Insert_vndk_version, true) {
+ filename := txt.Name()
+
+ shouldInsertVndkVersion := BoolDefault(txt.properties.Insert_vndk_version, true)
+ // llndk.libraries.txt file installed in the system image should not contain version info.
+ if ctx.Config().IsVndkDeprecated() && txt.Name() == llndkLibrariesTxt {
+ shouldInsertVndkVersion = false
+ }
+ if shouldInsertVndkVersion {
filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
- } else {
- filename = txt.Name()
}
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index e3d1179b4..a70a9d158 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -122,7 +122,7 @@ func (be ZipEntryFromBuffer) Size() uint64 {
}
func (be ZipEntryFromBuffer) WriteToZip(dest string, zw *zip.Writer) error {
- w, err := zw.CreateHeader(be.fh)
+ w, err := zw.CreateHeaderAndroid(be.fh)
if err != nil {
return err
}
@@ -562,6 +562,8 @@ func mergeZips(inputZips []InputZip, writer *zip.Writer, manifest, pyMain string
}
}
+ var jarServices jar.Services
+
// Finally, add entries from all the input zips.
for _, inputZip := range inputZips {
_, copyFully := zipsToNotStrip[inputZip.Name()]
@@ -570,6 +572,14 @@ func mergeZips(inputZips []InputZip, writer *zip.Writer, manifest, pyMain string
}
for i, entry := range inputZip.Entries() {
+ if emulateJar && jarServices.IsServiceFile(entry) {
+ // If this is a jar, collect service files to combine instead of adding them to the zip.
+ err := jarServices.AddServiceFile(entry)
+ if err != nil {
+ return err
+ }
+ continue
+ }
if copyFully || !out.isEntryExcluded(entry.Name) {
if err := out.copyEntry(inputZip, i); err != nil {
return err
@@ -585,6 +595,16 @@ func mergeZips(inputZips []InputZip, writer *zip.Writer, manifest, pyMain string
}
if emulateJar {
+ // Combine all the service files into a single list of combined service files and add them to the zip.
+ for _, serviceFile := range jarServices.ServiceFiles() {
+ _, err := out.addZipEntry(serviceFile.Name, ZipEntryFromBuffer{
+ fh: serviceFile.FileHeader,
+ content: serviceFile.Contents,
+ })
+ if err != nil {
+ return err
+ }
+ }
return out.writeEntries(out.jarSorted())
} else if sortEntries {
return out.writeEntries(out.alphanumericSorted())
diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go
index cb5843607..767d4e61f 100644
--- a/cmd/merge_zips/merge_zips_test.go
+++ b/cmd/merge_zips/merge_zips_test.go
@@ -17,6 +17,7 @@ package main
import (
"bytes"
"fmt"
+ "hash/crc32"
"os"
"strconv"
"strings"
@@ -27,28 +28,34 @@ import (
)
type testZipEntry struct {
- name string
- mode os.FileMode
- data []byte
+ name string
+ mode os.FileMode
+ data []byte
+ method uint16
}
var (
- A = testZipEntry{"A", 0755, []byte("foo")}
- a = testZipEntry{"a", 0755, []byte("foo")}
- a2 = testZipEntry{"a", 0755, []byte("FOO2")}
- a3 = testZipEntry{"a", 0755, []byte("Foo3")}
- bDir = testZipEntry{"b/", os.ModeDir | 0755, nil}
- bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil}
- bbb = testZipEntry{"b/b/b", 0755, nil}
- ba = testZipEntry{"b/a", 0755, []byte("foob")}
- bc = testZipEntry{"b/c", 0755, []byte("bar")}
- bd = testZipEntry{"b/d", 0700, []byte("baz")}
- be = testZipEntry{"b/e", 0700, []byte("")}
-
- metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil}
- manifestFile = testZipEntry{jar.ManifestFile, 0755, []byte("manifest")}
- manifestFile2 = testZipEntry{jar.ManifestFile, 0755, []byte("manifest2")}
- moduleInfoFile = testZipEntry{jar.ModuleInfoClass, 0755, []byte("module-info")}
+ A = testZipEntry{"A", 0755, []byte("foo"), zip.Deflate}
+ a = testZipEntry{"a", 0755, []byte("foo"), zip.Deflate}
+ a2 = testZipEntry{"a", 0755, []byte("FOO2"), zip.Deflate}
+ a3 = testZipEntry{"a", 0755, []byte("Foo3"), zip.Deflate}
+ bDir = testZipEntry{"b/", os.ModeDir | 0755, nil, zip.Deflate}
+ bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil, zip.Deflate}
+ bbb = testZipEntry{"b/b/b", 0755, nil, zip.Deflate}
+ ba = testZipEntry{"b/a", 0755, []byte("foo"), zip.Deflate}
+ bc = testZipEntry{"b/c", 0755, []byte("bar"), zip.Deflate}
+ bd = testZipEntry{"b/d", 0700, []byte("baz"), zip.Deflate}
+ be = testZipEntry{"b/e", 0700, []byte(""), zip.Deflate}
+
+ service1a = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\n"), zip.Store}
+ service1b = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass3\n"), zip.Deflate}
+ service1combined = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\nclass3\n"), zip.Store}
+ service2 = testZipEntry{"META-INF/services/service2", 0755, []byte("class1\nclass2\n"), zip.Deflate}
+
+ metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil, zip.Deflate}
+ manifestFile = testZipEntry{jar.ManifestFile, 0755, []byte("manifest"), zip.Deflate}
+ manifestFile2 = testZipEntry{jar.ManifestFile, 0755, []byte("manifest2"), zip.Deflate}
+ moduleInfoFile = testZipEntry{jar.ModuleInfoClass, 0755, []byte("module-info"), zip.Deflate}
)
type testInputZip struct {
@@ -236,6 +243,15 @@ func TestMergeZips(t *testing.T) {
"in1": true,
},
},
+ {
+ name: "services",
+ in: [][]testZipEntry{
+ {service1a, service2},
+ {service1b},
+ },
+ jar: true,
+ out: []testZipEntry{service1combined, service2},
+ },
}
for _, test := range testCases {
@@ -256,7 +272,7 @@ func TestMergeZips(t *testing.T) {
closeErr := writer.Close()
if closeErr != nil {
- t.Fatal(err)
+ t.Fatal(closeErr)
}
if test.err != "" {
@@ -266,12 +282,16 @@ func TestMergeZips(t *testing.T) {
t.Fatal("incorrect err, want:", test.err, "got:", err)
}
return
+ } else if err != nil {
+ t.Fatal("unexpected err: ", err)
}
if !bytes.Equal(want, out.Bytes()) {
t.Error("incorrect zip output")
t.Errorf("want:\n%s", dumpZip(want))
t.Errorf("got:\n%s", dumpZip(out.Bytes()))
+ os.WriteFile("/tmp/got.zip", out.Bytes(), 0755)
+ os.WriteFile("/tmp/want.zip", want, 0755)
}
})
}
@@ -286,8 +306,14 @@ func testZipEntriesToBuf(entries []testZipEntry) []byte {
Name: e.name,
}
fh.SetMode(e.mode)
+ fh.Method = e.method
+ fh.UncompressedSize64 = uint64(len(e.data))
+ fh.CRC32 = crc32.ChecksumIEEE(e.data)
+ if fh.Method == zip.Store {
+ fh.CompressedSize64 = fh.UncompressedSize64
+ }
- w, err := zw.CreateHeader(&fh)
+ w, err := zw.CreateHeaderAndroid(&fh)
if err != nil {
panic(err)
}
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index ba0648d19..3fb445480 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -556,7 +556,8 @@ var bpTemplate = template.Must(template.New("bp").Parse(`
{{- end}}
{{- end}}
{{- if .IsApk}}
- presigned: true
+ preprocessed: true,
+ presigned: true,
{{- end}}
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 22d64a2ed..20e366e8a 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -121,6 +121,10 @@ func runMixedModeBuild(ctx *android.Context, extraNinjaDeps []string) string {
defer ctx.EventHandler.End("mixed_build")
bazelHook := func() error {
+ err := ctx.Config().BazelContext.QueueBazelSandwichCqueryRequests(ctx.Config())
+ if err != nil {
+ return err
+ }
return ctx.Config().BazelContext.InvokeBazel(ctx.Config(), ctx)
}
ctx.SetBeforePrepareBuildActionsHook(bazelHook)
@@ -225,7 +229,7 @@ func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string {
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
// Create soong_injection repository
- soongInjectionFiles, err := bp2build.CreateSoongInjectionDirFiles(codegenContext, bp2build.CreateCodegenMetrics())
+ soongInjectionFiles, workspaceFiles, err := bp2build.CreateSoongInjectionDirFiles(codegenContext, bp2build.CreateCodegenMetrics())
maybeQuit(err, "")
absoluteSoongInjectionDir := shared.JoinPath(topDir, ctx.Config().SoongOutDir(), bazel.SoongInjectionDirName)
for _, file := range soongInjectionFiles {
@@ -236,6 +240,9 @@ func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string {
// to allow users to edit/experiment in the synthetic workspace.
writeReadWriteFile(absoluteSoongInjectionDir, file)
}
+ for _, file := range workspaceFiles {
+ writeReadWriteFile(absoluteApiBp2buildDir, file)
+ }
workspace := shared.JoinPath(ctx.Config().SoongOutDir(), "api_bp2build")
// Create the symlink forest
@@ -807,9 +814,7 @@ func runBp2Build(ctx *android.Context, extraNinjaDeps []string, metricsDir strin
// Run the code-generation phase to convert BazelTargetModules to BUILD files
// and print conversion codegenMetrics to the user.
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.Bp2Build, topDir)
- ctx.EventHandler.Do("codegen", func() {
- codegenMetrics = bp2build.Codegen(codegenContext)
- })
+ codegenMetrics = bp2build.Codegen(codegenContext)
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 67cb6cfc8..5c2316a31 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -15,7 +15,6 @@
package main
import (
- "android/soong/starlark_import"
"io/fs"
"io/ioutil"
"os"
@@ -23,6 +22,7 @@ import (
"android/soong/android"
"android/soong/bp2build"
+ "android/soong/starlark_import"
)
// A helper function to generate a Read-only Bazel workspace in outDir
@@ -35,8 +35,7 @@ func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string, generateF
panic(err)
}
- filesToWrite := bp2build.CreateBazelFiles(ctx.Config(), ruleShims, res.BuildDirToTargets(),
- ctx.Mode())
+ filesToWrite := bp2build.CreateBazelFiles(ruleShims, res.BuildDirToTargets(), ctx.Mode())
bazelRcFiles, err2 := CopyBazelRcFiles()
if err2 != nil {
return err2
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 682fb75c3..4097e8a3f 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -218,6 +218,11 @@ func main() {
trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
+ log.Verbose("Command Line: ")
+ for i, arg := range os.Args {
+ log.Verbosef(" [%d] %s", i, arg)
+ }
+
defer func() {
stat.Finish()
criticalPath.WriteToMetrics(met)
diff --git a/cmd/zip2zip/BUILD.bazel b/cmd/zip2zip/BUILD.bazel
deleted file mode 100644
index 1915a2dbf..000000000
--- a/cmd/zip2zip/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2022 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.
-
-alias(
- name = "zip2zip",
- actual = "//prebuilts/build-tools:linux-x86/bin/zip2zip",
-)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index bb83dc842..ba41f4a66 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -45,7 +45,8 @@ type GlobalConfig struct {
BootJars android.ConfiguredJarList // modules for jars that form the boot class path
ApexBootJars android.ConfiguredJarList // jars within apex that form the boot class path
- ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX
+ ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX
+ TestOnlyArtBootImageJars android.ConfiguredJarList // modules for jars to be included in the ART boot image for testing
SystemServerJars android.ConfiguredJarList // system_server classpath jars on the platform
SystemServerApps []string // apps that are loaded into system server
@@ -700,6 +701,7 @@ func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
BootJars: android.EmptyConfiguredJarList(),
ApexBootJars: android.EmptyConfiguredJarList(),
ArtApexJars: android.EmptyConfiguredJarList(),
+ TestOnlyArtBootImageJars: android.EmptyConfiguredJarList(),
SystemServerJars: android.EmptyConfiguredJarList(),
SystemServerApps: nil,
ApexSystemServerJars: android.EmptyConfiguredJarList(),
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 6ed0736f7..147a56231 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -111,6 +111,13 @@ func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer {
})
}
+// FixtureSetTestOnlyArtBootImageJars enables dexpreopt and sets the TestOnlyArtBootImageJars property.
+func FixtureSetTestOnlyArtBootImageJars(bootJars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.TestOnlyArtBootImageJars = android.CreateTestConfiguredJarList(bootJars)
+ })
+}
+
// FixtureSetBootJars enables dexpreopt and sets the BootJars property.
func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index ada47128c..94b795f4d 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -371,6 +371,8 @@ type FuzzConfig struct {
// Specifies whether fuzz target should check presubmitted code changes for crashes.
// Defaults to false.
Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
+ // Specify which paths to exclude from fuzzing coverage reports
+ Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"`
}
type FuzzFrameworks struct {
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index c767685bc..afa52cc7b 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -56,7 +56,6 @@ var (
"RSTest-rscript",
"BluetoothGeneratedDumpsysBinarySchema_bfbs",
"TracingVMProtoStub_h",
- "FrontendStub_h",
"VehicleServerProtoStub_cc",
"AudioFocusControlProtoStub_cc",
"AudioFocusControlProtoStub_h",
@@ -98,9 +97,6 @@ var (
"BlueberryFacadeGeneratedStub_cc",
"BlueberryFacadeGeneratedStub_h",
"BluetoothGeneratedDumpsysDataSchema_h",
- "FrontendStub_cc",
- "OpenwrtControlServerProto_cc",
- "OpenwrtControlServerProto_h",
"c2hal_test_genc++",
"c2hal_test_genc++_headers",
"hidl2aidl_test_gen_aidl",
@@ -117,6 +113,28 @@ var (
"nos_app_weaver_service_genc++_headers",
"nos_app_weaver_service_genc++_mock",
"nos_generator_test_service_genc++",
+ "aidl_camera_build_version",
+ "cronet_aml_base_android_runtime_unchecked_jni_headers",
+ "cronet_aml_base_android_runtime_jni_headers",
+ "aidl-golden-test-build-hook-gen",
+ "PacketStreamerStub_h",
+ "FrontendStub_cc",
+ "FrontendStub_h",
+ "PacketStreamerStub_cc",
+ "pixelstatsatoms.h",
+ "pixelatoms_defs.h",
+ "pixelstatsatoms.cpp",
+ "hidl_java_impl_test_gen",
+ "cronet_aml_base_android_runtime_jni_headers__testing",
+ "cronet_aml_base_android_runtime_unchecked_jni_headers__testing",
+ "hidl_cpp_impl_test_gen-sources",
+ "fdt_test_tree_multiple_memory_ranges_dtb",
+ "fdt_test_tree_one_memory_range_dtb",
+ "fdt_test_tree_empty_memory_range_dtb",
+ "ltp_config_arm_64_lowmem",
+ "ltp_config_arm_64_lowmem_hwasan",
+ "ltp_config_x86",
+ "libbssl_sys_src_nostd",
}
SandboxingDenyPathList = []string{
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b29e2c96a..aa4295d64 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -151,6 +151,9 @@ type generatorProperties struct {
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
+
+ // Enable restat to update the output only if the output is changed
+ Write_if_changed *bool
}
type Module struct {
@@ -293,6 +296,9 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
for _, dir := range g.properties.Export_include_dirs {
g.exportedIncludeDirs = append(g.exportedIncludeDirs,
android.PathForModuleGen(ctx, g.subDir, ctx.ModuleDir(), dir))
+ // Also export without ModuleDir for consistency with Export_include_dirs not being set
+ g.exportedIncludeDirs = append(g.exportedIncludeDirs,
+ android.PathForModuleGen(ctx, g.subDir, dir))
}
} else {
g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForModuleGen(ctx, g.subDir))
@@ -435,6 +441,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
cmd = g.CmdModifier(ctx, cmd)
}
+ var extraInputs android.Paths
// Generate tasks, either from genrule or gensrcs.
for i, task := range g.taskGenerator(ctx, cmd, srcFiles) {
if len(task.out) == 0 {
@@ -442,7 +449,6 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
return
}
- var extraInputs android.Paths
// Only handle extra inputs once as these currently are the same across all tasks
if i == 0 {
for name, values := range task.extraInputs {
@@ -467,6 +473,9 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
// Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
+ if Bool(g.properties.Write_if_changed) {
+ rule.Restat()
+ }
cmd := rule.Command()
for _, out := range task.out {
@@ -860,7 +869,7 @@ type bazelGensrcsAttributes struct {
Srcs bazel.LabelListAttribute
Output_extension *string
Tools bazel.LabelListAttribute
- Cmd string
+ Cmd bazel.StringAttribute
Data bazel.LabelListAttribute
}
@@ -908,7 +917,7 @@ type bazelGenruleAttributes struct {
Srcs bazel.LabelListAttribute
Outs []string
Tools bazel.LabelListAttribute
- Cmd string
+ Cmd bazel.StringAttribute
}
// ConvertWithBp2build converts a Soong module -> Bazel target.
@@ -958,14 +967,13 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
}
}
- // Replace in and out variables with $< and $@
- var cmd string
- if m.properties.Cmd != nil {
+ replaceVariables := func(cmd string) string {
+ // Replace in and out variables with $< and $@
if ctx.ModuleType() == "gensrcs" {
- cmd = strings.ReplaceAll(*m.properties.Cmd, "$(in)", "$(SRC)")
+ cmd = strings.ReplaceAll(cmd, "$(in)", "$(SRC)")
cmd = strings.ReplaceAll(cmd, "$(out)", "$(OUT)")
} else {
- cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
+ cmd = strings.Replace(cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
}
cmd = strings.Replace(cmd, "$(genDir)", "$(RULEDIR)", -1)
@@ -981,10 +989,26 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
cmd = strings.Replace(cmd, bpLoc, bazelLoc, -1)
cmd = strings.Replace(cmd, bpLocs, bazelLocs, -1)
}
+ return cmd
+ }
+
+ var cmdProp bazel.StringAttribute
+ cmdProp.SetValue(replaceVariables(proptools.String(m.properties.Cmd)))
+ allProductVariableProps := android.ProductVariableProperties(ctx, m)
+ if productVariableProps, ok := allProductVariableProps["Cmd"]; ok {
+ for productVariable, value := range productVariableProps {
+ var cmd string
+ if strValue, ok := value.(*string); ok && strValue != nil {
+ cmd = *strValue
+ }
+ cmd = replaceVariables(cmd)
+ cmdProp.SetSelectValue(productVariable.ConfigurationAxis(), productVariable.SelectKey(), &cmd)
+ }
}
tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
+ bazelName := m.Name()
if ctx.ModuleType() == "gensrcs" {
props := bazel.BazelTargetModuleProperties{
Rule_class: "gensrcs",
@@ -993,7 +1017,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
attrs := &bazelGensrcsAttributes{
Srcs: srcs,
Output_extension: outputExtension,
- Cmd: cmd,
+ Cmd: cmdProp,
Tools: tools,
Data: data,
}
@@ -1002,17 +1026,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Tags: tags,
}, attrs)
} else {
- // The Out prop is not in an immediately accessible field
- // in the Module struct, so use GetProperties and cast it
- // to the known struct prop.
- var outs []string
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*genRuleProperties); ok {
- outs = props.Out
- break
- }
- }
- bazelName := m.Name()
+ outs := m.RawOutputFiles(ctx)
for _, out := range outs {
if out == bazelName {
// This is a workaround to circumvent a Bazel warning where a genrule's
@@ -1026,7 +1040,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
attrs := &bazelGenruleAttributes{
Srcs: srcs,
Outs: outs,
- Cmd: cmd,
+ Cmd: cmdProp,
Tools: tools,
}
props := bazel.BazelTargetModuleProperties{
@@ -1037,6 +1051,72 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
Tags: tags,
}, attrs)
}
+
+ if m.needsCcLibraryHeadersBp2build() {
+ includeDirs := make([]string, len(m.properties.Export_include_dirs)*2)
+ for i, dir := range m.properties.Export_include_dirs {
+ includeDirs[i*2] = dir
+ includeDirs[i*2+1] = filepath.Clean(filepath.Join(ctx.ModuleDir(), dir))
+ }
+ attrs := &ccHeaderLibraryAttrs{
+ Hdrs: []string{":" + bazelName},
+ Export_includes: includeDirs,
+ }
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_headers",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
+ }
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: m.Name() + genruleHeaderLibrarySuffix,
+ Tags: tags,
+ }, attrs)
+ }
+}
+
+const genruleHeaderLibrarySuffix = "__header_library"
+
+func (m *Module) needsCcLibraryHeadersBp2build() bool {
+ return len(m.properties.Export_include_dirs) > 0
+}
+
+// GenruleCcHeaderMapper is a bazel.LabelMapper function to map genrules to a cc_library_headers
+// target when they export multiple include directories.
+func GenruleCcHeaderLabelMapper(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+ mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
+ if !exists {
+ return label.Label, false
+ }
+ if m, ok := mod.(*Module); ok {
+ if m.needsCcLibraryHeadersBp2build() {
+ return label.Label + genruleHeaderLibrarySuffix, true
+ }
+ }
+ return label.Label, false
+}
+
+type ccHeaderLibraryAttrs struct {
+ Hdrs []string
+
+ Export_includes []string
+}
+
+// RawOutputFfiles returns the raw outputs specified in Android.bp
+// This does not contain the fully resolved path relative to the top of the tree
+func (g *Module) RawOutputFiles(ctx android.BazelConversionContext) []string {
+ if ctx.Config().BuildMode != android.Bp2build {
+ ctx.ModuleErrorf("RawOutputFiles is only supported in bp2build mode")
+ }
+ // The Out prop is not in an immediately accessible field
+ // in the Module struct, so use GetProperties and cast it
+ // to the known struct prop.
+ var outs []string
+ for _, propIntf := range g.GetProperties() {
+ if props, ok := propIntf.(*genRuleProperties); ok {
+ outs = props.Out
+ break
+ }
+ }
+ return outs
}
var Bool = proptools.Bool
@@ -1090,6 +1170,7 @@ func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSet
}
}).(*sandboxingAllowlistSets)
}
+
func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
if !ctx.DeviceConfig().GenruleSandboxing() {
return r.SandboxTools()
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 7c17db1be..7c14531bd 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -18,6 +18,7 @@ import (
"fmt"
"os"
"regexp"
+ "strconv"
"testing"
"android/soong/android"
@@ -557,10 +558,12 @@ func TestGenSrcs(t *testing.T) {
allowMissingDependencies bool
- err string
- cmds []string
- deps []string
- files []string
+ err string
+ cmds []string
+ deps []string
+ files []string
+ shards int
+ inputs []string
}{
{
name: "gensrcs",
@@ -627,9 +630,29 @@ func TestGenSrcs(t *testing.T) {
"out/soong/.intermediates/gen/gen/gensrcs/in2.h",
"out/soong/.intermediates/gen/gen/gensrcs/in3.h",
},
+ shards: 2,
+ inputs: []string{
+ "baz.txt",
+ },
},
}
+ checkInputs := func(t *testing.T, rule android.TestingBuildParams, inputs []string) {
+ t.Helper()
+ if len(inputs) == 0 {
+ return
+ }
+ inputBaseNames := map[string]bool{}
+ for _, f := range rule.Implicits {
+ inputBaseNames[f.Base()] = true
+ }
+ for _, f := range inputs {
+ if _, ok := inputBaseNames[f]; !ok {
+ t.Errorf("Expected to find input file %q for %q, but did not", f, rule.Description)
+ }
+ }
+ }
+
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
bp := "gensrcs {\n"
@@ -647,10 +670,21 @@ func TestGenSrcs(t *testing.T) {
ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
RunTestWithBp(t, testGenruleBp()+bp)
+ mod := result.ModuleForTests("gen", "")
if expectedErrors != nil {
return
}
+ if test.shards > 0 {
+ for i := 0; i < test.shards; i++ {
+ r := mod.Rule("generator" + strconv.Itoa(i))
+ checkInputs(t, r, test.inputs)
+ }
+ } else {
+ r := mod.Rule("generator")
+ checkInputs(t, r, test.inputs)
+ }
+
gen := result.Module("gen", "").(*Module)
android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
@@ -811,6 +845,49 @@ func TestGenruleOutputFiles(t *testing.T) {
result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
}
+func TestGenruleInterface(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "package-dir/Android.bp": []byte(`
+ genrule {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.proto",
+ ],
+ out: ["proto.h", "bar/proto.h"],
+ export_include_dirs: [".", "bar"],
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDirs := []string{
+ "out/soong/.intermediates/package-dir/module-name/gen/package-dir",
+ "out/soong/.intermediates/package-dir/module-name/gen",
+ "out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
+ "out/soong/.intermediates/package-dir/module-name/gen/bar",
+ }
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ exportedIncludeDirs,
+ gen.GeneratedHeaderDirs(),
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ "out/soong/.intermediates/package-dir/module-name/gen/proto.h",
+ "out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
+ },
+ gen.GeneratedSourceFiles(),
+ )
+}
+
func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForGenRuleTest,
diff --git a/jar/Android.bp b/jar/Android.bp
index 46113d877..c03e49174 100644
--- a/jar/Android.bp
+++ b/jar/Android.bp
@@ -21,6 +21,7 @@ bootstrap_go_package {
pkgPath: "android/soong/jar",
srcs: [
"jar.go",
+ "services.go",
],
testSrcs: [
"jar_test.go",
diff --git a/jar/services.go b/jar/services.go
new file mode 100644
index 000000000..d06a6dc99
--- /dev/null
+++ b/jar/services.go
@@ -0,0 +1,128 @@
+// 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 jar
+
+import (
+ "android/soong/third_party/zip"
+ "bufio"
+ "hash/crc32"
+ "sort"
+ "strings"
+)
+
+const servicesPrefix = "META-INF/services/"
+
+// Services is used to collect service files from multiple zip files and produce a list of ServiceFiles containing
+// the unique lines from all the input zip entries with the same name.
+type Services struct {
+ services map[string]*ServiceFile
+}
+
+// ServiceFile contains the combined contents of all input zip entries with a single name.
+type ServiceFile struct {
+ Name string
+ FileHeader *zip.FileHeader
+ Contents []byte
+ Lines []string
+}
+
+// IsServiceFile returns true if the zip entry is in the META-INF/services/ directory.
+func (Services) IsServiceFile(entry *zip.File) bool {
+ return strings.HasPrefix(entry.Name, servicesPrefix)
+}
+
+// AddServiceFile adds a zip entry in the META-INF/services/ directory to the list of service files that need
+// to be combined.
+func (j *Services) AddServiceFile(entry *zip.File) error {
+ if j.services == nil {
+ j.services = map[string]*ServiceFile{}
+ }
+
+ service := entry.Name
+ serviceFile := j.services[service]
+ fh := entry.FileHeader
+ if serviceFile == nil {
+ serviceFile = &ServiceFile{
+ Name: service,
+ FileHeader: &fh,
+ }
+ j.services[service] = serviceFile
+ }
+
+ f, err := entry.Open()
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if line != "" {
+ serviceFile.Lines = append(serviceFile.Lines, line)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ServiceFiles returns the list of combined service files, each containing all the unique lines from the
+// corresponding service files in the input zip entries.
+func (j *Services) ServiceFiles() []ServiceFile {
+ services := make([]ServiceFile, 0, len(j.services))
+
+ for _, serviceFile := range j.services {
+ serviceFile.Lines = dedupServicesLines(serviceFile.Lines)
+ serviceFile.Lines = append(serviceFile.Lines, "")
+ serviceFile.Contents = []byte(strings.Join(serviceFile.Lines, "\n"))
+
+ serviceFile.FileHeader.UncompressedSize64 = uint64(len(serviceFile.Contents))
+ serviceFile.FileHeader.CRC32 = crc32.ChecksumIEEE(serviceFile.Contents)
+ if serviceFile.FileHeader.Method == zip.Store {
+ serviceFile.FileHeader.CompressedSize64 = serviceFile.FileHeader.UncompressedSize64
+ }
+
+ services = append(services, *serviceFile)
+ }
+
+ sort.Slice(services, func(i, j int) bool {
+ return services[i].Name < services[j].Name
+ })
+
+ return services
+}
+
+func dedupServicesLines(in []string) []string {
+ writeIndex := 0
+outer:
+ for readIndex := 0; readIndex < len(in); readIndex++ {
+ for compareIndex := 0; compareIndex < writeIndex; compareIndex++ {
+ if interface{}(in[readIndex]) == interface{}(in[compareIndex]) {
+ // The value at readIndex already exists somewhere in the output region
+ // of the slice before writeIndex, skip it.
+ continue outer
+ }
+ }
+ if readIndex != writeIndex {
+ in[writeIndex] = in[readIndex]
+ }
+ writeIndex++
+ }
+ return in[0:writeIndex]
+}
diff --git a/java/Android.bp b/java/Android.bp
index e07986975..4450c4275 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -80,6 +80,7 @@ bootstrap_go_package {
],
testSrcs: [
"aar_test.go",
+ "android_manifest_test.go",
"androidmk_test.go",
"app_import_test.go",
"app_set_test.go",
diff --git a/java/aapt2.go b/java/aapt2.go
index 7845a0b23..3bb70b53f 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -146,20 +146,25 @@ func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
blueprint.RuleParams{
- Command: `rm -rf $genDir && ` +
- `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
- `--output-text-symbols ${rTxt} $inFlags && ` +
- `${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
- `${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
+ Command: `$preamble` +
+ `${config.Aapt2Cmd} link -o $out $flags --proguard $proguardOptions ` +
+ `--output-text-symbols ${rTxt} $inFlags` +
+ `$postamble`,
CommandDeps: []string{
"${config.Aapt2Cmd}",
"${config.SoongZipCmd}",
- "${config.ExtractJarPackagesCmd}",
},
Restat: true,
},
- "flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
+ "flags", "inFlags", "proguardOptions", "rTxt", "extraPackages", "preamble", "postamble")
+
+var aapt2ExtractExtraPackagesRule = pctx.AndroidStaticRule("aapt2ExtractExtraPackages",
+ blueprint.RuleParams{
+ Command: `${config.ExtractJarPackagesCmd} -i $in -o $out --prefix '--extra-packages '`,
+ CommandDeps: []string{"${config.ExtractJarPackagesCmd}"},
+ Restat: true,
+ })
var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
blueprint.RuleParams{
@@ -175,12 +180,10 @@ var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
})
func aapt2Link(ctx android.ModuleContext,
- packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
+ packageRes, genJar, proguardOptions, rTxt android.WritablePath,
flags []string, deps android.Paths,
compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
- genDir := android.PathForModuleGen(ctx, "aapt2", "R")
-
var inFlags []string
if len(compiledRes) > 0 {
@@ -217,7 +220,7 @@ func aapt2Link(ctx android.ModuleContext,
}
// Set auxiliary outputs as implicit outputs to establish correct dependency chains.
- implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
+ implicitOutputs := append(splitPackages, proguardOptions, rTxt)
linkOutput := packageRes
// AAPT2 ignores assets in overlays. Merge them after linking.
@@ -232,25 +235,49 @@ func aapt2Link(ctx android.ModuleContext,
})
}
+ // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
+ // values via the flags parameter when it wants to split outputs.
+ // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
+ // tidy.
+ args := map[string]string{
+ "flags": strings.Join(flags, " "),
+ "inFlags": strings.Join(inFlags, " "),
+ "proguardOptions": proguardOptions.String(),
+ "rTxt": rTxt.String(),
+ }
+
+ if genJar != nil {
+ // Generating java source files from aapt2 was requested, use aapt2LinkAndGenRule and pass it
+ // genJar and genDir args.
+ genDir := android.PathForModuleGen(ctx, "aapt2", "R")
+ ctx.Variable(pctx, "aapt2GenDir", genDir.String())
+ ctx.Variable(pctx, "aapt2GenJar", genJar.String())
+ implicitOutputs = append(implicitOutputs, genJar)
+ args["preamble"] = `rm -rf $aapt2GenDir && `
+ args["postamble"] = `&& ${config.SoongZipCmd} -write_if_changed -jar -o $aapt2GenJar -C $aapt2GenDir -D $aapt2GenDir && ` +
+ `rm -rf $aapt2GenDir`
+ args["flags"] += " --java $aapt2GenDir"
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: aapt2LinkRule,
Description: "aapt2 link",
Implicits: deps,
Output: linkOutput,
ImplicitOutputs: implicitOutputs,
- // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
- // values via the flags parameter when it wants to split outputs.
- // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
- // tidy.
- Args: map[string]string{
- "flags": strings.Join(flags, " "),
- "inFlags": strings.Join(inFlags, " "),
- "proguardOptions": proguardOptions.String(),
- "genDir": genDir.String(),
- "genJar": genJar.String(),
- "rTxt": rTxt.String(),
- "extraPackages": extraPackages.String(),
- },
+ Args: args,
+ })
+}
+
+// aapt2ExtractExtraPackages takes a srcjar generated by aapt2 or a classes jar generated by ResourceProcessorBusyBox
+// and converts it to a text file containing a list of --extra_package arguments for passing to Make modules so they
+// correctly generate R.java entries for packages provided by transitive dependencies.
+func aapt2ExtractExtraPackages(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aapt2ExtractExtraPackagesRule,
+ Description: "aapt2 extract extra packages",
+ Input: in,
+ Output: out,
})
}
diff --git a/java/aar.go b/java/aar.go
index 29e86e678..308a48cac 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -23,6 +23,7 @@ import (
"android/soong/android"
"android/soong/bazel"
"android/soong/dexpreopt"
+ "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -31,10 +32,9 @@ import (
type AndroidLibraryDependency interface {
LibraryDependency
ExportPackage() android.Path
- ExportedRRODirs() []rroDir
- ExportedStaticPackages() android.Paths
- ExportedManifests() android.Paths
- ExportedAssets() android.OptionalPath
+ ResourcesNodeDepSet() *android.DepSet[*resourcesNode]
+ RRODirsDepSet() *android.DepSet[rroDir]
+ ManifestsDepSet() *android.DepSet[android.Path]
SetRROEnforcedForDependent(enforce bool)
IsRROEnforced(ctx android.BaseModuleContext) bool
}
@@ -89,35 +89,49 @@ type aaptProperties struct {
// do not include AndroidManifest from dependent libraries
Dont_merge_manifests *bool
+ // If use_resource_processor is set, use Bazel's resource processor instead of aapt2 to generate R.class files.
+ // The resource processor produces more optimal R.class files that only list resources in the package of the
+ // library that provided them, as opposed to aapt2 which produces R.java files for every package containing
+ // every resource. Using the resource processor can provide significant build time speedups, but requires
+ // fixing the module to use the correct package to reference each resource, and to avoid having any other
+ // libraries in the tree that use the same package name. Defaults to false, but will default to true in the
+ // future.
+ Use_resource_processor *bool
+
// true if RRO is enforced for any of the dependent modules
RROEnforcedForDependent bool `blueprint:"mutated"`
}
type aapt struct {
- aaptSrcJar android.Path
- exportPackage android.Path
- manifestPath android.Path
- transitiveManifestPaths android.Paths
- proguardOptionsFile android.Path
- rroDirs []rroDir
- rTxt android.Path
- extraAaptPackagesFile android.Path
- mergedManifestFile android.Path
- noticeFile android.OptionalPath
- assetPackage android.OptionalPath
- isLibrary bool
- defaultManifestVersion string
- useEmbeddedNativeLibs bool
- useEmbeddedDex bool
- usesNonSdkApis bool
- hasNoCode bool
- LoggingParent string
- resourceFiles android.Paths
+ aaptSrcJar android.Path
+ transitiveAaptRJars android.Paths
+ transitiveAaptResourcePackages android.Paths
+ exportPackage android.Path
+ manifestPath android.Path
+ proguardOptionsFile android.Path
+ rTxt android.Path
+ rJar android.Path
+ extraAaptPackagesFile android.Path
+ mergedManifestFile android.Path
+ noticeFile android.OptionalPath
+ assetPackage android.OptionalPath
+ isLibrary bool
+ defaultManifestVersion string
+ useEmbeddedNativeLibs bool
+ useEmbeddedDex bool
+ usesNonSdkApis bool
+ hasNoCode bool
+ LoggingParent string
+ resourceFiles android.Paths
splitNames []string
splits []split
aaptProperties aaptProperties
+
+ resourcesNodesDepSet *android.DepSet[*resourcesNode]
+ rroDirsDepSet *android.DepSet[rroDir]
+ manifestsDepSet *android.DepSet[android.Path]
}
type split struct {
@@ -138,20 +152,23 @@ func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
}
}
+func (a *aapt) useResourceProcessorBusyBox() bool {
+ return BoolDefault(a.aaptProperties.Use_resource_processor, false)
+}
+
func (a *aapt) ExportPackage() android.Path {
return a.exportPackage
}
-
-func (a *aapt) ExportedRRODirs() []rroDir {
- return a.rroDirs
+func (a *aapt) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.resourcesNodesDepSet
}
-func (a *aapt) ExportedManifests() android.Paths {
- return a.transitiveManifestPaths
+func (a *aapt) RRODirsDepSet() *android.DepSet[rroDir] {
+ return a.rroDirsDepSet
}
-func (a *aapt) ExportedAssets() android.OptionalPath {
- return a.assetPackage
+func (a *aapt) ManifestsDepSet() *android.DepSet[android.Path] {
+ return a.manifestsDepSet
}
func (a *aapt) SetRROEnforcedForDependent(enforce bool) {
@@ -175,8 +192,6 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkConte
// Flags specified in Android.bp
linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
- linkFlags = append(linkFlags, "--no-static-lib-packages")
-
// Find implicit or explicit asset and resource dirs
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
@@ -291,7 +306,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
- transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
+ staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedDeps, libFlags :=
aaptLibs(ctx, sdkContext, classLoaderContexts)
// Exclude any libraries from the supplied list.
@@ -314,13 +329,20 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
})
+ staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
+
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
- a.transitiveManifestPaths = append(android.Paths{manifestPath}, additionalManifests...)
- a.transitiveManifestPaths = append(a.transitiveManifestPaths, transitiveStaticLibManifests...)
-
- if len(a.transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
- a.mergedManifestFile = manifestMerger(ctx, a.transitiveManifestPaths[0], a.transitiveManifestPaths[1:], a.isLibrary)
+ transitiveManifestPaths := append(android.Paths{manifestPath}, additionalManifests...)
+ // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
+ // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
+ // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
+ // android_library_import modules. If this is fixed, staticManifestsDepSet can be dropped completely in favor of
+ // staticResourcesNodesDepSet.manifests()
+ transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...)
+
+ if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
+ a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], transitiveManifestPaths[1:], a.isLibrary)
if !a.isLibrary {
// Only use the merged manifest for applications. For libraries, the transitive closure of manifests
// will be propagated to the final application and merged there. The merged manifest for libraries is
@@ -333,21 +355,34 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
- rroDirs = append(rroDirs, staticRRODirs...)
linkFlags = append(linkFlags, libFlags...)
- linkDeps = append(linkDeps, libDeps...)
+ linkDeps = append(linkDeps, sharedDeps...)
+ linkDeps = append(linkDeps, staticDeps.resPackages()...)
linkFlags = append(linkFlags, extraLinkFlags...)
if a.isLibrary {
linkFlags = append(linkFlags, "--static-lib")
}
+ if a.isLibrary && a.useResourceProcessorBusyBox() {
+ // When building an android_library using ResourceProcessorBusyBox the resources are merged into
+ // package-res.apk with --merge-only, but --no-static-lib-packages is not used so that R.txt only
+ // contains resources from this library.
+ linkFlags = append(linkFlags, "--merge-only")
+ } else {
+ // When building and app or when building an android_library without ResourceProcessorBusyBox
+ // --no-static-lib-packages is used to put all the resources into the app. If ResourceProcessorBusyBox
+ // is used then the app's R.txt will be post-processed along with the R.txt files from dependencies to
+ // sort resources into the right packages in R.class.
+ linkFlags = append(linkFlags, "--no-static-lib-packages")
+ }
+
packageRes := android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
rTxt := android.PathForModuleOut(ctx, "R.txt")
// This file isn't used by Soong, but is generated for exporting
extraPackages := android.PathForModuleOut(ctx, "extra_packages")
+ var transitiveRJars android.Paths
+ var srcJar android.WritablePath
var compiledResDirs []android.Paths
for _, dir := range resDirs {
@@ -363,7 +398,27 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
var compiledRes, compiledOverlay android.Paths
- compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
+ // AAPT2 overlays are in lowest to highest priority order, reverse the topological order
+ // of transitiveStaticLibs.
+ transitiveStaticLibs := android.ReversePaths(staticDeps.resPackages())
+
+ if a.isLibrary && a.useResourceProcessorBusyBox() {
+ // When building an android_library with ResourceProcessorBusyBox enabled treat static library dependencies
+ // as imports. The resources from dependencies will not be merged into this module's package-res.apk, and
+ // instead modules depending on this module will reference package-res.apk from all transitive static
+ // dependencies.
+ for _, staticDep := range staticDeps {
+ linkDeps = append(linkDeps, staticDep.resPackage)
+ linkFlags = append(linkFlags, "-I "+staticDep.resPackage.String())
+ if staticDep.usedResourceProcessor {
+ transitiveRJars = append(transitiveRJars, staticDep.rJar)
+ }
+ }
+ } else {
+ // When building an app or building a library without ResourceProcessorBusyBox enabled all static
+ // dependencies are compiled into this module's package-res.apk as overlays.
+ compiledOverlay = append(compiledOverlay, transitiveStaticLibs...)
+ }
if len(transitiveStaticLibs) > 0 {
// If we are using static android libraries, every source file becomes an overlay.
@@ -404,12 +459,22 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
})
}
- aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
- linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
+ if !a.useResourceProcessorBusyBox() {
+ // the subdir "android" is required to be filtered by package names
+ srcJar = android.PathForModuleGen(ctx, "android", "R.srcjar")
+ }
+ // No need to specify assets from dependencies to aapt2Link for libraries, all transitive assets will be
+ // provided to the final app aapt2Link step.
+ var transitiveAssets android.Paths
+ if !a.isLibrary {
+ transitiveAssets = android.ReverseSliceInPlace(staticDeps.assets())
+ }
+ aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
+ linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages)
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
- if android.PrefixInList(linkFlags, "-A ") || len(assetPackages) > 0 {
+ if android.PrefixInList(linkFlags, "-A ") {
assets := android.PathForModuleOut(ctx, "assets.zip")
ctx.Build(pctx, android.BuildParams{
Rule: extractAssetsRule,
@@ -420,21 +485,145 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon
a.assetPackage = android.OptionalPathForPath(assets)
}
+ if a.useResourceProcessorBusyBox() {
+ rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary)
+ aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
+ transitiveRJars = append(transitiveRJars, rJar)
+ a.rJar = rJar
+ } else {
+ aapt2ExtractExtraPackages(ctx, extraPackages, srcJar)
+ }
+
a.aaptSrcJar = srcJar
+ a.transitiveAaptRJars = transitiveRJars
+ a.transitiveAaptResourcePackages = staticDeps.resPackages()
a.exportPackage = packageRes
a.manifestPath = manifestPath
a.proguardOptionsFile = proguardOptionsFile
- a.rroDirs = rroDirs
a.extraAaptPackagesFile = extraPackages
a.rTxt = rTxt
a.splits = splits
+ a.resourcesNodesDepSet = android.NewDepSetBuilder[*resourcesNode](android.TOPOLOGICAL).
+ Direct(&resourcesNode{
+ resPackage: a.exportPackage,
+ manifest: a.manifestPath,
+ additionalManifests: additionalManifests,
+ rTxt: a.rTxt,
+ rJar: a.rJar,
+ assets: a.assetPackage,
+
+ usedResourceProcessor: a.useResourceProcessorBusyBox(),
+ }).
+ Transitive(staticResourcesNodesDepSet).Build()
+ a.rroDirsDepSet = android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL).
+ Direct(rroDirs...).
+ Transitive(staticRRODirsDepSet).Build()
+ a.manifestsDepSet = android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).
+ Direct(a.manifestPath).
+ DirectSlice(additionalManifests).
+ Transitive(staticManifestsDepSet).Build()
+}
+
+var resourceProcessorBusyBox = pctx.AndroidStaticRule("resourceProcessorBusyBox",
+ blueprint.RuleParams{
+ Command: "${config.JavaCmd} -cp ${config.ResourceProcessorBusyBox} " +
+ "com.google.devtools.build.android.ResourceProcessorBusyBox --tool=GENERATE_BINARY_R -- @${out}.args && " +
+ "if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out}; fi",
+ CommandDeps: []string{"${config.ResourceProcessorBusyBox}"},
+ Rspfile: "${out}.args",
+ RspfileContent: "--primaryRTxt ${rTxt} --primaryManifest ${manifest} --classJarOutput ${out}.tmp ${args}",
+ Restat: true,
+ }, "rTxt", "manifest", "args")
+
+// resourceProcessorBusyBoxGenerateBinaryR converts the R.txt file produced by aapt2 into R.class files
+// using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
+// supports producing classes for static dependencies that only include resources from that dependency.
+func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
+ rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool) {
+
+ var args []string
+ var deps android.Paths
+
+ if !isLibrary {
+ // When compiling an app, pass all R.txt and AndroidManifest.xml from transitive static library dependencies
+ // to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each
+ // package.
+ args, deps = transitiveDeps.resourceProcessorDeps()
+ } else {
+ // When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this
+ // library. Pass --finalFields=false so that the R.class file contains non-final fields so they don't get
+ // inlined into the library before the final IDs are assigned during app compilation.
+ args = append(args, "--finalFields=false")
+ }
+
+ deps = append(deps, rTxt, manifest)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: resourceProcessorBusyBox,
+ Output: rJar,
+ Implicits: deps,
+ Description: "ResourceProcessorBusyBox",
+ Args: map[string]string{
+ "rTxt": rTxt.String(),
+ "manifest": manifest.String(),
+ "args": strings.Join(args, " "),
+ },
+ })
+}
+
+type resourcesNode struct {
+ resPackage android.Path
+ manifest android.Path
+ additionalManifests android.Paths
+ rTxt android.Path
+ rJar android.Path
+ assets android.OptionalPath
+
+ usedResourceProcessor bool
+}
+
+type transitiveAarDeps []*resourcesNode
+
+func (t transitiveAarDeps) resPackages() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ paths = append(paths, dep.resPackage)
+ }
+ return paths
+}
+
+func (t transitiveAarDeps) manifests() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ paths = append(paths, dep.manifest)
+ paths = append(paths, dep.additionalManifests...)
+ }
+ return paths
+}
+
+func (t transitiveAarDeps) resourceProcessorDeps() (args []string, deps android.Paths) {
+ for _, dep := range t {
+ args = append(args, "--library="+dep.rTxt.String()+","+dep.manifest.String())
+ deps = append(deps, dep.rTxt, dep.manifest)
+ }
+ return args, deps
+}
+
+func (t transitiveAarDeps) assets() android.Paths {
+ paths := make(android.Paths, 0, len(t))
+ for _, dep := range t {
+ if dep.assets.Valid() {
+ paths = append(paths, dep.assets.Path())
+ }
+ }
+ return paths
}
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
- transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
-
- var sharedLibs android.Paths
+ staticResourcesNodes *android.DepSet[*resourcesNode], staticRRODirs *android.DepSet[rroDir],
+ staticManifests *android.DepSet[android.Path], sharedLibs android.Paths, flags []string) {
if classLoaderContexts == nil {
// Not all callers need to compute class loader context, those who don't just pass nil.
@@ -447,6 +636,10 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
+ var resourcesNodeDepSets []*android.DepSet[*resourcesNode]
+ rroDirsDepSetBuilder := android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL)
+ manifestsDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL)
+
ctx.VisitDirectDeps(func(module android.Module) {
depTag := ctx.OtherModuleDependencyTag(module)
@@ -469,32 +662,28 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
}
case staticLibTag:
if exportPackage != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
- transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
- transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
- if aarDep.ExportedAssets().Valid() {
- assets = append(assets, aarDep.ExportedAssets().Path())
- }
-
- outer:
- for _, d := range aarDep.ExportedRRODirs() {
- for _, e := range staticRRODirs {
- if d.path == e.path {
- continue outer
- }
- }
- staticRRODirs = append(staticRRODirs, d)
- }
+ resourcesNodeDepSets = append(resourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
+ rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet())
+ manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet())
}
}
addCLCFromDep(ctx, module, classLoaderContexts)
})
- deps = append(deps, sharedLibs...)
- deps = append(deps, transitiveStaticLibs...)
+ // AAPT2 overlays are in lowest to highest priority order, the topological order will be reversed later.
+ // Reverse the dependency order now going into the depset so that it comes out in order after the second
+ // reverse later.
+ // NOTE: this is legacy and probably incorrect behavior, for most other cases (e.g. conflicting classes in
+ // dependencies) the highest priority dependency is listed first, but for resources the highest priority
+ // dependency has to be listed last.
+ staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
+ android.ReverseSliceInPlace(resourcesNodeDepSets))
- if len(transitiveStaticLibs) > 0 {
+ staticRRODirs = rroDirsDepSetBuilder.Build()
+ staticManifests = manifestsDepSetBuilder.Build()
+
+ if len(staticResourcesNodes.ToList()) > 0 {
flags = append(flags, "--auto-add-overlay")
}
@@ -502,10 +691,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
flags = append(flags, "-I "+sharedLib.String())
}
- transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
- transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
-
- return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags
+ return staticResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
}
type AndroidLibrary struct {
@@ -516,8 +702,6 @@ type AndroidLibrary struct {
androidLibraryProperties androidLibraryProperties
aarFile android.WritablePath
-
- exportedStaticPackages android.Paths
}
var _ android.OutputFileProducer = (*AndroidLibrary)(nil)
@@ -532,10 +716,6 @@ func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
}
}
-func (a *AndroidLibrary) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
-}
-
var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -554,9 +734,15 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
- ctx.CheckbuildFile(a.proguardOptionsFile)
- ctx.CheckbuildFile(a.exportPackage)
- ctx.CheckbuildFile(a.aaptSrcJar)
+ a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+
+ ctx.CheckbuildFile(a.aapt.proguardOptionsFile)
+ ctx.CheckbuildFile(a.aapt.exportPackage)
+ if a.useResourceProcessorBusyBox() {
+ ctx.CheckbuildFile(a.aapt.rJar)
+ } else {
+ ctx.CheckbuildFile(a.aapt.aaptSrcJar)
+ }
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -568,7 +754,22 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
a.proguardOptionsFile)
- a.Module.compile(ctx, a.aaptSrcJar)
+ var extraSrcJars android.Paths
+ var extraCombinedJars android.Paths
+ var extraClasspathJars android.Paths
+ if a.useResourceProcessorBusyBox() {
+ // When building a library with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox for this
+ // library and each of the transitive static android_library dependencies has already created an
+ // R.class file for the appropriate package. Add all of those R.class files to the classpath.
+ extraClasspathJars = a.transitiveAaptRJars
+ } else {
+ // When building a library without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
+ // R.java files for the library's package and the packages from all transitive static android_library
+ // dependencies. Compile the srcjar alongside the rest of the sources.
+ extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
+ }
+
+ a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
var res android.Paths
@@ -579,19 +780,15 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles,
android.PathsForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files)...)
+
ctx.VisitDirectDeps(func(m android.Module) {
if ctx.OtherModuleDependencyTag(m) == staticLibTag {
if lib, ok := m.(LibraryDependency); ok {
a.exportedProguardFlagFiles = append(a.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...)
}
- if alib, ok := m.(AndroidLibraryDependency); ok {
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportPackage())
- a.exportedStaticPackages = append(a.exportedStaticPackages, alib.ExportedStaticPackages()...)
- }
}
})
a.exportedProguardFlagFiles = android.FirstUniquePaths(a.exportedProguardFlagFiles)
- a.exportedStaticPackages = android.FirstUniquePaths(a.exportedStaticPackages)
prebuiltJniPackages := android.Paths{}
ctx.VisitDirectDeps(func(module android.Module) {
@@ -674,14 +871,18 @@ type AARImport struct {
properties AARImportProperties
- classpathFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
- extraAaptPackagesFile android.WritablePath
- manifest android.WritablePath
- assetsPackage android.WritablePath
+ classpathFile android.WritablePath
+ proguardFlags android.WritablePath
+ exportPackage android.WritablePath
+ transitiveAaptResourcePackages android.Paths
+ extraAaptPackagesFile android.WritablePath
+ manifest android.WritablePath
+ assetsPackage android.WritablePath
+ rTxt android.WritablePath
+ rJar android.WritablePath
- exportedStaticPackages android.Paths
+ resourcesNodesDepSet *android.DepSet[*resourcesNode]
+ manifestsDepSet *android.DepSet[android.Path]
hideApexVariantFromMake bool
@@ -738,25 +939,20 @@ var _ AndroidLibraryDependency = (*AARImport)(nil)
func (a *AARImport) ExportPackage() android.Path {
return a.exportPackage
}
-
func (a *AARImport) ExportedProguardFlagFiles() android.Paths {
return android.Paths{a.proguardFlags}
}
-func (a *AARImport) ExportedRRODirs() []rroDir {
- return nil
+func (a *AARImport) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.resourcesNodesDepSet
}
-func (a *AARImport) ExportedStaticPackages() android.Paths {
- return a.exportedStaticPackages
+func (a *AARImport) RRODirsDepSet() *android.DepSet[rroDir] {
+ return android.NewDepSet[rroDir](android.TOPOLOGICAL, nil, nil)
}
-func (a *AARImport) ExportedManifests() android.Paths {
- return android.Paths{a.manifest}
-}
-
-func (a *AARImport) ExportedAssets() android.OptionalPath {
- return android.OptionalPathForPath(a.assetsPackage)
+func (a *AARImport) ManifestsDepSet() *android.DepSet[android.Path] {
+ return a.manifestsDepSet
}
// RRO enforcement is not available on aar_import since its RRO dirs are not
@@ -852,12 +1048,13 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
+ aarRTxt := extractedAARDir.Join(ctx, "R.txt")
a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
ctx.Build(pctx, android.BuildParams{
Rule: unzipAAR,
Input: a.aarPath,
- Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage},
+ Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, aarRTxt},
Description: "unzip AAR",
Args: map[string]string{
"outDir": extractedAARDir.String(),
@@ -874,49 +1071,73 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
- // the subdir "android" is required to be filtered by package names
- srcJar := android.PathForModuleGen(ctx, "android", "R.srcjar")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
- rTxt := android.PathForModuleOut(ctx, "R.txt")
+ a.rTxt = android.PathForModuleOut(ctx, "R.txt")
a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
var linkDeps android.Paths
linkFlags := []string{
"--static-lib",
- "--no-static-lib-packages",
+ "--merge-only",
"--auto-add-overlay",
}
linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
linkDeps = append(linkDeps, a.manifest)
- transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
+ staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags :=
aaptLibs(ctx, android.SdkContext(a), nil)
- _ = staticLibManifests
- _ = staticRRODirs
+ _ = staticRRODirsDepSet
+ staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
- linkDeps = append(linkDeps, libDeps...)
+ linkDeps = append(linkDeps, sharedLibs...)
+ linkDeps = append(linkDeps, staticDeps.resPackages()...)
linkFlags = append(linkFlags, libFlags...)
- overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
+ overlayRes := android.Paths{flata}
- aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
+ // Treat static library dependencies of static libraries as imports.
+ transitiveStaticLibs := staticDeps.resPackages()
+ linkDeps = append(linkDeps, transitiveStaticLibs...)
+ for _, staticLib := range transitiveStaticLibs {
+ linkFlags = append(linkFlags, "-I "+staticLib.String())
+ }
+
+ transitiveAssets := android.ReverseSliceInPlace(staticDeps.assets())
+ aapt2Link(ctx, a.exportPackage, nil, proguardOptionsFile, a.rTxt,
linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
- // Merge this import's assets with its dependencies' assets (if there are any).
- if len(transitiveAssets) > 0 {
- mergedAssets := android.PathForModuleOut(ctx, "merged-assets.zip")
- inputZips := append(android.Paths{a.assetsPackage}, transitiveAssets...)
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeAssetsRule,
- Inputs: inputZips,
- Output: mergedAssets,
- Description: "merge assets from dependencies and self",
- })
- a.assetsPackage = mergedAssets
- }
+ a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true)
+
+ aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
+
+ resourcesNodesDepSetBuilder := android.NewDepSetBuilder[*resourcesNode](android.TOPOLOGICAL)
+ resourcesNodesDepSetBuilder.Direct(&resourcesNode{
+ resPackage: a.exportPackage,
+ manifest: a.manifest,
+ rTxt: a.rTxt,
+ rJar: a.rJar,
+ assets: android.OptionalPathForPath(a.assetsPackage),
+
+ usedResourceProcessor: true,
+ })
+ resourcesNodesDepSetBuilder.Transitive(staticResourcesNodesDepSet)
+ a.resourcesNodesDepSet = resourcesNodesDepSetBuilder.Build()
+
+ manifestDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(a.manifest)
+ // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
+ // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
+ // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
+ // android_library_import modules. If this is fixed, AndroidLibraryDependency.ManifestsDepSet can be dropped
+ // completely in favor of AndroidLibraryDependency.ResourceNodesDepSet.manifest
+ //manifestDepSetBuilder.Transitive(transitiveStaticDeps.manifests)
+ _ = staticManifestsDepSet
+ a.manifestsDepSet = manifestDepSetBuilder.Build()
+
+ a.transitiveAaptResourcePackages = staticDeps.resPackages()
a.collectTransitiveHeaderJars(ctx)
ctx.SetProvider(JavaInfoProvider, JavaInfo{
@@ -925,6 +1146,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
ImplementationJars: android.PathsIfNonNil(a.classpathFile),
+ // TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
if proptools.Bool(a.properties.Extract_jni) {
@@ -1007,6 +1229,8 @@ func AARImportFactory() android.Module {
type bazelAapt struct {
Manifest bazel.Label
Resource_files bazel.LabelListAttribute
+ Assets_dir bazel.StringAttribute
+ Assets bazel.LabelListAttribute
}
type bazelAndroidLibrary struct {
@@ -1021,7 +1245,7 @@ type bazelAndroidLibraryImport struct {
Sdk_version bazel.StringAttribute
}
-func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
+func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) (*bazelAapt, bool) {
manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
resourceFiles := bazel.LabelList{
@@ -1031,10 +1255,30 @@ func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *
files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
resourceFiles.Includes = append(resourceFiles.Includes, files...)
}
+
+ assetsDir := bazel.StringAttribute{}
+ var assets bazel.LabelList
+ for i, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") {
+ if i > 0 {
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "multiple asset_dirs")
+ return &bazelAapt{}, false
+ }
+ // Assets_dirs are relative to the module dir when specified, but if the default in used in
+ // PathsWithOptionalDefaultForModuleSrc, then dir is relative to the top.
+ assetsRelDir, error := filepath.Rel(ctx.ModuleDir(), dir.Rel())
+ if error != nil {
+ assetsRelDir = dir.Rel()
+ }
+ assetsDir.Value = proptools.StringPtr(assetsRelDir)
+ assets = bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir)))
+
+ }
return &bazelAapt{
android.BazelLabelForModuleSrcSingle(ctx, manifest),
bazel.MakeLabelListAttribute(resourceFiles),
- }
+ assetsDir,
+ bazel.MakeLabelListAttribute(assets),
+ }, true
}
func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
@@ -1091,7 +1335,11 @@ func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperti
}
func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2buildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
+
depLabels := bp2buildInfo.DepLabels
deps := depLabels.Deps
@@ -1103,6 +1351,10 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext)
name := a.Name()
props := AndroidLibraryBazelTargetModuleProperties()
+ aaptAttrs, supported := a.convertAaptAttrsWithBp2Build(ctx)
+ if !supported {
+ return
+ }
ctx.CreateBazelTargetModule(
props,
android.CommonAttributes{Name: name},
@@ -1112,7 +1364,7 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext)
Deps: deps,
Exports: depLabels.StaticDeps,
},
- a.convertAaptAttrsWithBp2Build(ctx),
+ aaptAttrs,
},
)
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
new file mode 100644
index 000000000..b12d77896
--- /dev/null
+++ b/java/android_manifest_test.go
@@ -0,0 +1,103 @@
+// 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 java
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestManifestMerger(t *testing.T) {
+ bp := `
+ android_app {
+ name: "app",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ resource_dirs: ["app/res"],
+ manifest: "app/AndroidManifest.xml",
+ additional_manifests: ["app/AndroidManifest2.xml"],
+ static_libs: ["direct", "direct_import"],
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ additional_manifests: ["direct/AndroidManifest2.xml"],
+ static_libs: ["transitive", "transitive_import"],
+ }
+
+ android_library {
+ name: "transitive",
+ sdk_version: "current",
+ srcs: ["transitive/transitive.java"],
+ resource_dirs: ["transitive/res"],
+ manifest: "transitive/AndroidManifest.xml",
+ additional_manifests: ["transitive/AndroidManifest2.xml"],
+ }
+
+ android_library_import {
+ name: "direct_import",
+ sdk_version: "current",
+ aars: ["direct_import.aar"],
+ static_libs: ["direct_import_dep"],
+ }
+
+ android_library_import {
+ name: "direct_import_dep",
+ sdk_version: "current",
+ aars: ["direct_import_dep.aar"],
+ }
+
+ android_library_import {
+ name: "transitive_import",
+ sdk_version: "current",
+ aars: ["transitive_import.aar"],
+ static_libs: ["transitive_import_dep"],
+ }
+
+ android_library_import {
+ name: "transitive_import_dep",
+ sdk_version: "current",
+ aars: ["transitive_import_dep.aar"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithOverlayBuildComponents,
+ ).RunTestWithBp(t, bp)
+
+ manifestMergerRule := result.ModuleForTests("app", "android_common").Rule("manifestMerger")
+ android.AssertPathRelativeToTopEquals(t, "main manifest",
+ "out/soong/.intermediates/app/android_common/manifest_fixer/AndroidManifest.xml",
+ manifestMergerRule.Input)
+ android.AssertPathsRelativeToTopEquals(t, "lib manifests",
+ []string{
+ "app/AndroidManifest2.xml",
+ "out/soong/.intermediates/direct/android_common/manifest_fixer/AndroidManifest.xml",
+ "direct/AndroidManifest2.xml",
+ "out/soong/.intermediates/transitive/android_common/manifest_fixer/AndroidManifest.xml",
+ "transitive/AndroidManifest2.xml",
+ "out/soong/.intermediates/transitive_import/android_common/aar/AndroidManifest.xml",
+ "out/soong/.intermediates/direct_import/android_common/aar/AndroidManifest.xml",
+ // TODO(b/288358614): Soong has historically not merged manifests from dependencies of
+ // android_library_import modules.
+
+ },
+ manifestMergerRule.Implicits)
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index 9c21633fb..82505e9e3 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -123,6 +123,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
if library.dexpreopter.configPath != nil {
entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
}
+
+ entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles().ToList())
},
},
})
@@ -220,6 +222,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -244,6 +247,7 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
}
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -265,10 +269,12 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
+ entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackages)
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -295,6 +301,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
if len(binary.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
}
+ entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles().ToList())
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -340,6 +347,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
// App module names can be overridden.
entries.SetString("LOCAL_MODULE", app.installApkName)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall)
+ if app.headerJarFile != nil {
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", app.headerJarFile)
+ }
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage)
if app.dexJarFile.IsSet() {
entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile.Path())
@@ -368,8 +378,13 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
filterRRO := func(filter overlayType) android.Paths {
var paths android.Paths
- for _, d := range app.rroDirs {
+ seen := make(map[android.Path]bool)
+ for _, d := range app.rroDirsDepSet.ToList() {
if d.overlayType == filter {
+ if seen[d.path] {
+ continue
+ }
+ seen[d.path] = true
paths = append(paths, d.path)
}
}
@@ -432,6 +447,10 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
}
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
+
+ if app.Name() != "framework-res" {
+ entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles().ToList())
+ }
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -450,11 +469,6 @@ func (a *AndroidApp) getOverriddenPackages() []string {
if len(a.overridableAppProperties.Overrides) > 0 {
overridden = append(overridden, a.overridableAppProperties.Overrides...)
}
- // When APK name is overridden via PRODUCT_PACKAGE_NAME_OVERRIDES
- // ensure that the original name is overridden.
- if a.Stem() != a.installApkName {
- overridden = append(overridden, a.Stem())
- }
return overridden
}
@@ -508,10 +522,12 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
}
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.exportPackage)
+ entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", a.transitiveAaptResourcePackages)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", a.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles().ToList())
})
return entriesList
@@ -684,6 +700,7 @@ func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
if Bool(a.properties.Export_package_resources) {
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
}
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
},
},
}}
@@ -717,6 +734,7 @@ func (r *RuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_CERTIFICATE", r.certificate.AndroidMkString())
entries.SetPath("LOCAL_MODULE_PATH", r.installDir)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", r.properties.Overrides...)
+ // TODO: LOCAL_ACONFIG_FILES -- Might eventually need aconfig flags?
},
},
}}
@@ -734,6 +752,7 @@ func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_APK_SET_INSTALL_FILE", apkSet.PackedAdditionalOutputs())
entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts -- Both declarations and values
},
},
},
diff --git a/java/app.go b/java/app.go
index d9272e4fc..1d1ea97f9 100755
--- a/java/app.go
+++ b/java/app.go
@@ -204,8 +204,8 @@ func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
return nil
}
-func (a *AndroidApp) ExportedStaticPackages() android.Paths {
- return nil
+func (a *AndroidApp) ResourcesNodeDepSet() *android.DepSet[*resourcesNode] {
+ return a.aapt.resourcesNodesDepSet
}
func (a *AndroidApp) OutputFile() android.Path {
@@ -521,7 +521,23 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.preventInstall = a.appProperties.PreventInstall
if ctx.ModuleName() != "framework-res" {
- a.Module.compile(ctx, a.aaptSrcJar)
+ var extraSrcJars android.Paths
+ var extraClasspathJars android.Paths
+ var extraCombinedJars android.Paths
+ if a.useResourceProcessorBusyBox() {
+ // When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already
+ // created R.class files that provide IDs for resources in busybox/R.jar. Pass that file in the
+ // classpath when compiling everything else, and add it to the final classes jar.
+ extraClasspathJars = android.Paths{a.aapt.rJar}
+ extraCombinedJars = android.Paths{a.aapt.rJar}
+ } else {
+ // When building an app without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
+ // R.java files for the app's package and the packages from all transitive static android_library
+ // dependencies. Compile the srcjar alongside the rest of the sources.
+ extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
+ }
+
+ a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
}
return a.dexJarFile.PathOrNil()
@@ -666,8 +682,17 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx)
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
+ // Unlike installApkName, a.stem should respect base module name for override_android_app.
+ // Therefore, use ctx.ModuleName() instead of a.Name().
+ a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+
// Check if the install APK name needs to be overridden.
- a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Stem())
+ // Both android_app and override_android_app module are expected to possess
+ // its module bound apk path. However, override_android_app inherits ctx.ModuleName()
+ // from the base module. Therefore, use a.Name() which represents
+ // the module name for both android_app and override_android_app.
+ a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(
+ proptools.StringDefault(a.overridableDeviceProperties.Stem, a.Name()))
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
@@ -997,7 +1022,13 @@ func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
case ".aapt.proguardOptionsFile":
return []android.Path{a.proguardOptionsFile}, nil
case ".aapt.srcjar":
- return []android.Path{a.aaptSrcJar}, nil
+ if a.aaptSrcJar != nil {
+ return []android.Path{a.aaptSrcJar}, nil
+ }
+ case ".aapt.jar":
+ if a.rJar != nil {
+ return []android.Path{a.rJar}, nil
+ }
case ".export-package.apk":
return []android.Path{a.exportPackage}, nil
}
@@ -1571,7 +1602,9 @@ func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *An
}
type manifestValueAttribute struct {
- MinSdkVersion *string
+ MinSdkVersion *string
+ MaxSdkVersion *string
+ TargetSdkVersion *string
}
type bazelAndroidAppAttributes struct {
@@ -1586,14 +1619,19 @@ type bazelAndroidAppAttributes struct {
// ConvertWithBp2build is used to convert android_app to Bazel.
func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2BuildInfo := a.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
deps.Append(depLabels.StaticDeps)
- aapt := a.convertAaptAttrsWithBp2Build(ctx)
-
+ aapt, supported := a.convertAaptAttrsWithBp2Build(ctx)
+ if !supported {
+ return
+ }
certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
manifestValues := &manifestValueAttribute{}
@@ -1601,12 +1639,25 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
// MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
minSdkVersion := a.MinSdkVersion(ctx)
if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
- minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx)
- if err == nil {
+ if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil {
manifestValues.MinSdkVersion = &minSdkStr
}
}
+ maxSdkVersion := a.MaxSdkVersion(ctx)
+ if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() {
+ if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil {
+ manifestValues.MaxSdkVersion = &maxSdkStr
+ }
+ }
+
+ targetSdkVersion := a.TargetSdkVersion(ctx)
+ if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() {
+ if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil {
+ manifestValues.TargetSdkVersion = &targetSdkStr
+ }
+ }
+
appAttrs := &bazelAndroidAppAttributes{
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
Custom_package: a.overridableAppProperties.Package_name,
diff --git a/java/app_builder.go b/java/app_builder.go
index d20a6bfe4..d397ff7f5 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -225,8 +225,6 @@ func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePat
})
}
-const jniJarOutputPathString = "jniJarOutput.zip"
-
func TransformJniLibsToJar(
ctx android.ModuleContext,
outputFile android.WritablePath,
@@ -258,7 +256,10 @@ func TransformJniLibsToJar(
rule = zipRE
args["implicits"] = strings.Join(deps.Strings(), ",")
}
- jniJarPath := android.PathForModuleOut(ctx, jniJarOutputPathString)
+ var jniJarPath android.WritablePath = android.PathForModuleOut(ctx, "jniJarOutput.zip")
+ if len(prebuiltJniPackages) == 0 {
+ jniJarPath = outputFile
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "zip jni libs",
@@ -266,12 +267,26 @@ func TransformJniLibsToJar(
Implicits: deps,
Args: args,
})
- ctx.Build(pctx, android.BuildParams{
- Rule: mergeAssetsRule,
- Description: "merge prebuilt JNI packages",
- Inputs: append(prebuiltJniPackages, jniJarPath),
- Output: outputFile,
- })
+ if len(prebuiltJniPackages) > 0 {
+ var mergeJniJarPath android.WritablePath = android.PathForModuleOut(ctx, "mergeJniJarOutput.zip")
+ if !uncompressJNI {
+ mergeJniJarPath = outputFile
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: mergeAssetsRule,
+ Description: "merge prebuilt JNI packages",
+ Inputs: append(prebuiltJniPackages, jniJarPath),
+ Output: mergeJniJarPath,
+ })
+
+ if uncompressJNI {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: uncompressEmbeddedJniLibsRule,
+ Input: mergeJniJarPath,
+ Output: outputFile,
+ })
+ }
+ }
}
func (a *AndroidApp) generateJavaUsedByApex(ctx android.ModuleContext) {
diff --git a/java/app_import.go b/java/app_import.go
index 9c0196039..ad1765e9d 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -17,6 +17,7 @@ package java
// This file contains the module implementations for android_app_import and android_test_import.
import (
+ "fmt"
"reflect"
"github.com/google/blueprint"
@@ -50,9 +51,9 @@ var (
Description: "Uncompress dex files",
})
- checkJniAndDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-and-dex-libs-are-uncompressed", blueprint.RuleParams{
+ checkDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-dex-libs-are-uncompressed", blueprint.RuleParams{
// grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
- Command: "if (zipinfo $in 'lib/*.so' '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
+ Command: "if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
"echo $in: Contains compressed JNI libraries and/or dex files >&2;" +
"exit 1; " +
"else " +
@@ -60,6 +61,17 @@ var (
"fi",
Description: "Check for compressed JNI libs or dex files",
})
+
+ checkJniLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-libs-are-uncompressed", blueprint.RuleParams{
+ // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
+ Command: "if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
+ "echo $in: Contains compressed JNI libraries >&2;" +
+ "exit 1; " +
+ "else " +
+ "touch $out; " +
+ "fi",
+ Description: "Check for compressed JNI libs or dex files",
+ })
)
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -334,11 +346,19 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
// Sign or align the package if package has not been preprocessed
if proptools.Bool(a.properties.Preprocessed) {
- output := srcApk
+ var output android.WritablePath
if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
- writableOutput := android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
- a.validatePreprocessedApk(ctx, srcApk, writableOutput)
- output = writableOutput
+ output = android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
+ a.validatePreprocessedApk(ctx, srcApk, output)
+ } else {
+ // If using the input APK unmodified, still make a copy of it so that the output filename has the
+ // right basename.
+ output = android.PathForModuleOut(ctx, apkFilename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: output,
+ })
}
a.outputFile = output
a.certificate = PresignedCertificate
@@ -375,26 +395,40 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
}
func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) {
+ var validations android.Paths
+
alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp")
ctx.Build(pctx, android.BuildParams{
Rule: checkZipAlignment,
Input: srcApk,
Output: alignmentStamp,
})
- compressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "compression.stamp")
+
+ validations = append(validations, alignmentStamp)
+ jniCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "jni_compression.stamp")
ctx.Build(pctx, android.BuildParams{
- Rule: checkJniAndDexLibsAreUncompressedRule,
+ Rule: checkJniLibsAreUncompressedRule,
Input: srcApk,
- Output: compressionStamp,
+ Output: jniCompressionStamp,
})
+ validations = append(validations, jniCompressionStamp)
+
+ if a.Privileged() {
+ // It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+ dexCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "dex_compression.stamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: checkDexLibsAreUncompressedRule,
+ Input: srcApk,
+ Output: dexCompressionStamp,
+ })
+ validations = append(validations, dexCompressionStamp)
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: srcApk,
- Output: dstApk,
- Validations: []android.Path{
- alignmentStamp,
- compressionStamp,
- },
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: dstApk,
+ Validations: validations,
})
}
@@ -410,6 +444,15 @@ func (a *AndroidAppImport) OutputFile() android.Path {
return a.outputFile
}
+func (a *AndroidAppImport) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return []android.Path{a.outputFile}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
return nil
}
diff --git a/java/app_test.go b/java/app_test.go
index 0f98416d2..8474ea7d6 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -599,7 +599,7 @@ func TestLibraryAssets(t *testing.T) {
android_library {
name: "lib3",
sdk_version: "current",
- static_libs: ["lib4"],
+ static_libs: ["lib4", "import"],
}
android_library {
@@ -607,6 +607,12 @@ func TestLibraryAssets(t *testing.T) {
sdk_version: "current",
asset_dirs: ["assets_b"],
}
+
+ android_library_import {
+ name: "import",
+ sdk_version: "current",
+ aars: ["import.aar"],
+ }
`
testCases := []struct {
@@ -616,11 +622,12 @@ func TestLibraryAssets(t *testing.T) {
}{
{
name: "foo",
- // lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
+ // lib1 has its own assets. lib3 doesn't have any, but lib4 and import have assets.
assetPackages: []string{
"out/soong/.intermediates/foo/android_common/aapt2/package-res.apk",
"out/soong/.intermediates/lib1/android_common/assets.zip",
- "out/soong/.intermediates/lib3/android_common/assets.zip",
+ "out/soong/.intermediates/lib4/android_common/assets.zip",
+ "out/soong/.intermediates/import/android_common/assets.zip",
},
},
{
@@ -632,10 +639,6 @@ func TestLibraryAssets(t *testing.T) {
},
{
name: "lib3",
- assetPackages: []string{
- "out/soong/.intermediates/lib3/android_common/aapt2/package-res.apk",
- "out/soong/.intermediates/lib4/android_common/assets.zip",
- },
},
{
name: "lib4",
@@ -717,7 +720,514 @@ func TestAppJavaResources(t *testing.T) {
}
}
-func TestAndroidResources(t *testing.T) {
+func TestAndroidResourceProcessor(t *testing.T) {
+ testCases := []struct {
+ name string
+ appUsesRP bool
+ directLibUsesRP bool
+ transitiveLibUsesRP bool
+
+ dontVerifyApp bool
+ appResources []string
+ appOverlays []string
+ appImports []string
+ appSrcJars []string
+ appClasspath []string
+ appCombined []string
+
+ dontVerifyDirect bool
+ directResources []string
+ directOverlays []string
+ directImports []string
+ directSrcJars []string
+ directClasspath []string
+ directCombined []string
+
+ dontVerifyTransitive bool
+ transitiveResources []string
+ transitiveOverlays []string
+ transitiveImports []string
+ transitiveSrcJars []string
+ transitiveClasspath []string
+ transitiveCombined []string
+
+ dontVerifyDirectImport bool
+ directImportResources []string
+ directImportOverlays []string
+ directImportImports []string
+
+ dontVerifyTransitiveImport bool
+ transitiveImportResources []string
+ transitiveImportOverlays []string
+ transitiveImportImports []string
+ }{
+ {
+ // Test with all modules set to use_resource_processor: false (except android_library_import modules,
+ // which always use resource processor).
+ name: "legacy",
+ appUsesRP: false,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: false,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
+ },
+ directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: []string{"out/soong/.intermediates/transitive/android_common/gen/android/R.srcjar"},
+ transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
+ transitiveCombined: nil,
+
+ directImportResources: nil,
+ directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
+ directImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ },
+
+ transitiveImportResources: nil,
+ transitiveImportOverlays: []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
+ transitiveImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ },
+ },
+ {
+ // Test with all modules set to use_resource_processor: true.
+ name: "resource_processor",
+ appUsesRP: true,
+ directLibUsesRP: true,
+ transitiveLibUsesRP: true,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: nil,
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
+ directImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ },
+ directSrcJars: nil,
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: nil,
+ transitiveClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ },
+ transitiveCombined: nil,
+
+ directImportResources: nil,
+ directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
+ directImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ },
+
+ transitiveImportResources: nil,
+ transitiveImportOverlays: []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
+ transitiveImportImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ },
+ }, {
+ // Test an app building with resource processor enabled but with dependencies built without
+ // resource processor.
+ name: "app_resource_processor",
+ appUsesRP: true,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: false,
+
+ appResources: nil,
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: nil,
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ // R.jar has to come before direct.jar
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ dontVerifyDirect: true,
+ dontVerifyTransitive: true,
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ {
+ // Test an app building without resource processor enabled but with a dependency built with
+ // resource processor.
+ name: "app_dependency_lib_resource_processor",
+ appUsesRP: false,
+ directLibUsesRP: true,
+ transitiveLibUsesRP: false,
+
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
+ directImports: []string{
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ },
+ directSrcJars: nil,
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+
+ dontVerifyTransitive: true,
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ {
+ // Test a library building without resource processor enabled but with a dependency built with
+ // resource processor.
+ name: "lib_dependency_lib_resource_processor",
+ appUsesRP: false,
+ directLibUsesRP: false,
+ transitiveLibUsesRP: true,
+
+ appOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/direct_import/android_common/package-res.apk",
+ "out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
+ },
+ appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
+ appClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+ appCombined: []string{
+ "out/soong/.intermediates/app/android_common/javac/app.jar",
+ "out/soong/.intermediates/direct/android_common/combined/direct.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ },
+
+ directResources: nil,
+ directOverlays: []string{
+ "out/soong/.intermediates/transitive/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
+ "out/soong/.intermediates/transitive_import/android_common/package-res.apk",
+ "out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
+ },
+ directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
+ directClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+ directCombined: []string{
+ "out/soong/.intermediates/direct/android_common/javac/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ },
+
+ transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
+ transitiveOverlays: nil,
+ transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ transitiveSrcJars: nil,
+ transitiveClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ },
+ transitiveCombined: nil,
+
+ dontVerifyDirectImport: true,
+ dontVerifyTransitiveImport: true,
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "app",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ resource_dirs: ["app/res"],
+ manifest: "app/AndroidManifest.xml",
+ static_libs: ["direct", "direct_import"],
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ static_libs: ["transitive", "transitive_import"],
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "transitive",
+ sdk_version: "current",
+ srcs: ["transitive/transitive.java"],
+ resource_dirs: ["transitive/res"],
+ manifest: "transitive/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
+ android_library_import {
+ name: "direct_import",
+ sdk_version: "current",
+ aars: ["direct_import.aar"],
+ static_libs: ["direct_import_dep"],
+ }
+
+ android_library_import {
+ name: "direct_import_dep",
+ sdk_version: "current",
+ aars: ["direct_import_dep.aar"],
+ }
+
+ android_library_import {
+ name: "transitive_import",
+ sdk_version: "current",
+ aars: ["transitive_import.aar"],
+ static_libs: ["transitive_import_dep"],
+ }
+
+ android_library_import {
+ name: "transitive_import_dep",
+ sdk_version: "current",
+ aars: ["transitive_import_dep.aar"],
+ }
+ `, testCase.appUsesRP, testCase.directLibUsesRP, testCase.transitiveLibUsesRP)
+
+ fs := android.MockFS{
+ "app/res/values/strings.xml": nil,
+ "direct/res/values/strings.xml": nil,
+ "transitive/res/values/strings.xml": nil,
+ }
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithOverlayBuildComponents,
+ fs.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ type aaptInfo struct {
+ resources, overlays, imports, srcJars, classpath, combined android.Paths
+ }
+
+ getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) {
+ mod := result.ModuleForTests(moduleName, "android_common")
+ resourceListRule := mod.MaybeOutput("aapt2/res.list")
+ overlayListRule := mod.MaybeOutput("aapt2/overlay.list")
+ aaptRule := mod.Rule("aapt2Link")
+ javacRule := mod.MaybeRule("javac")
+ combinedRule := mod.MaybeOutput("combined/" + moduleName + ".jar")
+
+ aaptInfo.resources = resourceListRule.Inputs
+ aaptInfo.overlays = overlayListRule.Inputs
+
+ aaptFlags := strings.Split(aaptRule.Args["flags"], " ")
+ for i, flag := range aaptFlags {
+ if flag == "-I" && i+1 < len(aaptFlags) {
+ aaptInfo.imports = append(aaptInfo.imports, android.PathForTesting(aaptFlags[i+1]))
+ }
+ }
+
+ if len(javacRule.Args["srcJars"]) > 0 {
+ aaptInfo.srcJars = android.PathsForTesting(strings.Split(javacRule.Args["srcJars"], " ")...)
+ }
+
+ if len(javacRule.Args["classpath"]) > 0 {
+ classpathArg := strings.TrimPrefix(javacRule.Args["classpath"], "-classpath ")
+ aaptInfo.classpath = android.PathsForTesting(strings.Split(classpathArg, ":")...)
+ }
+
+ aaptInfo.combined = combinedRule.Inputs
+ return
+ }
+
+ app := getAaptInfo("app")
+ direct := getAaptInfo("direct")
+ transitive := getAaptInfo("transitive")
+ directImport := getAaptInfo("direct_import")
+ transitiveImport := getAaptInfo("transitive_import")
+
+ if !testCase.dontVerifyApp {
+ android.AssertPathsRelativeToTopEquals(t, "app resources", testCase.appResources, app.resources)
+ android.AssertPathsRelativeToTopEquals(t, "app overlays", testCase.appOverlays, app.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "app imports", testCase.appImports, app.imports)
+ android.AssertPathsRelativeToTopEquals(t, "app srcjars", testCase.appSrcJars, app.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "app classpath", testCase.appClasspath, app.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "app combined", testCase.appCombined, app.combined)
+ }
+
+ if !testCase.dontVerifyDirect {
+ android.AssertPathsRelativeToTopEquals(t, "direct resources", testCase.directResources, direct.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct overlays", testCase.directOverlays, direct.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct imports", testCase.directImports, direct.imports)
+ android.AssertPathsRelativeToTopEquals(t, "direct srcjars", testCase.directSrcJars, direct.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "direct classpath", testCase.directClasspath, direct.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "direct combined", testCase.directCombined, direct.combined)
+ }
+
+ if !testCase.dontVerifyTransitive {
+ android.AssertPathsRelativeToTopEquals(t, "transitive resources", testCase.transitiveResources, transitive.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive overlays", testCase.transitiveOverlays, transitive.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive imports", testCase.transitiveImports, transitive.imports)
+ android.AssertPathsRelativeToTopEquals(t, "transitive srcjars", testCase.transitiveSrcJars, transitive.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "transitive classpath", testCase.transitiveClasspath, transitive.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "transitive combined", testCase.transitiveCombined, transitive.combined)
+ }
+
+ if !testCase.dontVerifyDirectImport {
+ android.AssertPathsRelativeToTopEquals(t, "direct_import resources", testCase.directImportResources, directImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import overlays", testCase.directImportOverlays, directImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "direct_import imports", testCase.directImportImports, directImport.imports)
+ }
+
+ if !testCase.dontVerifyTransitiveImport {
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import resources", testCase.transitiveImportResources, transitiveImport.resources)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import overlays", testCase.transitiveImportOverlays, transitiveImport.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "transitive_import imports", testCase.transitiveImportImports, transitiveImport.imports)
+ }
+ })
+ }
+}
+
+func TestAndroidResourceOverlays(t *testing.T) {
testCases := []struct {
name string
enforceRROTargets []string
@@ -943,7 +1453,7 @@ func TestAndroidResources(t *testing.T) {
overlayFiles = resourceListToFiles(module, android.PathsRelativeToTop(overlayList.Inputs))
}
- for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
+ for _, d := range module.Module().(AndroidLibraryDependency).RRODirsDepSet().ToList() {
var prefix string
if d.overlayType == device {
prefix = "device:"
@@ -1232,7 +1742,7 @@ func TestJNIABI(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output(jniJarOutputPathString)
+ jniLibZip := app.Output("jnilibs.zip")
var abis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
@@ -1365,7 +1875,7 @@ func TestJNIPackaging(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.MaybeOutput(jniJarOutputPathString)
+ jniLibZip := app.MaybeOutput("jnilibs.zip")
if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
t.Errorf("expected jni packaged %v, got %v", w, g)
}
@@ -1456,7 +1966,7 @@ func TestJNISDK(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.MaybeOutput(jniJarOutputPathString)
+ jniLibZip := app.MaybeOutput("jnilibs.zip")
if len(jniLibZip.Implicits) != 1 {
t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
}
@@ -2476,7 +2986,7 @@ func TestStl(t *testing.T) {
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common")
- jniLibZip := app.Output(jniJarOutputPathString)
+ jniLibZip := app.Output("jnilibs.zip")
var jnis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
for i := 0; i < len(args); i++ {
diff --git a/java/base.go b/java/base.go
index f2ad5c2cf..f5eb01c4b 100644
--- a/java/base.go
+++ b/java/base.go
@@ -21,6 +21,7 @@ import (
"strings"
"android/soong/ui/metrics/bp2build_metrics_proto"
+
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
@@ -500,6 +501,21 @@ type Module struct {
maxSdkVersion android.ApiLevel
sourceExtensions []string
+
+ annoSrcJars android.Paths
+
+ // output file name based on Stem property.
+ // This should be set in every ModuleWithStem's GenerateAndroidBuildActions
+ // or the module should override Stem().
+ stem string
+
+ // Aconfig "cache files" that went directly into this module. Transitive ones are
+ // tracked via JavaInfo.TransitiveAconfigFiles
+ // TODO: Extract to something standalone to propagate tags via GeneratedJavaLibraryModule
+ aconfigIntermediates android.Paths
+
+ // Aconfig files for all transitive deps. Also exposed via JavaInfo
+ transitiveAconfigFiles *android.DepSet[android.Path]
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -1049,7 +1065,7 @@ func (module *Module) addGeneratedSrcJars(path android.Path) {
module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path)
}
-func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
+func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
deps := j.collectDeps(ctx)
@@ -1087,9 +1103,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
srcJars := srcFiles.FilterByExt(".srcjar")
srcJars = append(srcJars, deps.srcJars...)
- if aaptSrcJar != nil {
- srcJars = append(srcJars, aaptSrcJar)
- }
+ srcJars = append(srcJars, extraSrcJars...)
srcJars = append(srcJars, j.properties.Generated_srcjars...)
srcFiles = srcFiles.FilterOutByExt(".srcjar")
@@ -1097,7 +1111,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
}
- jarName := ctx.ModuleName() + ".jar"
+ jarName := j.Stem() + ".jar"
var uniqueJavaFiles android.Paths
set := make(map[string]bool)
@@ -1132,6 +1146,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
var kotlinJars android.Paths
var kotlinHeaderJars android.Paths
+ // Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
+ // any dependencies so that it can override any non-final R classes from dependencies with the
+ // final R classes from the app.
+ flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...)
+
if srcFiles.HasExt(".kt") {
// When using kotlin sources turbine is used to generate annotation processor sources,
// including for annotation processors that generate API, so we can use turbine for
@@ -1225,8 +1244,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
+ extraJars := append(android.CopyOf(extraCombinedJars), kotlinHeaderJars...)
headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
if ctx.Failed() {
return
}
@@ -1255,8 +1275,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// this module, or else we could have duplicated errorprone messages.
errorproneFlags := enableErrorproneFlags(flags)
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+ errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
- transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1376,6 +1397,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
jars = append(jars, servicesJar)
}
+ jars = append(android.CopyOf(extraCombinedJars), jars...)
+
// 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
@@ -1468,7 +1491,13 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.implementationJarFile = outputFile
if j.headerJarFile == nil {
- j.headerJarFile = j.implementationJarFile
+ // If this module couldn't generate a header jar (for example due to api generating annotation processors)
+ // then use the implementation jar. Run it through zip2zip first to remove any files in META-INF/services
+ // so that javac on modules that depend on this module don't pick up annotation processors (which may be
+ // missing their implementations) from META-INF/services/javax.annotation.processing.Processor.
+ headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
+ convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
+ j.headerJarFile = headerJarFile
}
// enforce syntax check to jacoco filters for any build (http://b/183622051)
@@ -1614,6 +1643,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
ctx.CheckbuildFile(outputFile)
+ j.collectTransitiveAconfigFiles(ctx)
+
ctx.SetProvider(JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
@@ -1628,6 +1659,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
ExportedPluginClasses: j.exportedPluginClasses,
ExportedPluginDisableTurbine: j.exportedDisableTurbine,
JacocoReportClassesFile: j.jacocoReportClassesFile,
+ TransitiveAconfigFiles: j.transitiveAconfigFiles,
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1657,13 +1689,15 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
kzipName := pathtools.ReplaceExtension(jarName, "kzip")
+ annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
if idx >= 0 {
kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
+ annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar")
jarName += strconv.Itoa(idx)
}
classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
- TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
+ TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
if ctx.Config().EmitXrefRules() {
extractionFile := android.PathForModuleOut(ctx, kzipName)
@@ -1671,6 +1705,10 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
j.kytheFiles = append(j.kytheFiles, extractionFile)
}
+ if len(flags.processorPath) > 0 {
+ j.annoSrcJars = append(j.annoSrcJars, annoSrcJar)
+ }
+
return classes
}
@@ -1850,6 +1888,7 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
func (j *Module) CompilerDeps() []string {
@@ -1887,7 +1926,10 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi
}
func (j *Module) Stem() string {
- return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name())
+ if j.stem == "" {
+ panic("Stem() called before stem property was set")
+ }
+ return j.stem
}
func (j *Module) JacocoReportClassesFile() android.Path {
@@ -1898,6 +1940,34 @@ func (j *Module) IsInstallable() bool {
return Bool(j.properties.Installable)
}
+func (j *Module) collectTransitiveAconfigFiles(ctx android.ModuleContext) {
+ // Aconfig files from this module
+ mine := j.aconfigIntermediates
+
+ // Aconfig files from transitive dependencies
+ fromDeps := []*android.DepSet[android.Path]{}
+ ctx.VisitDirectDeps(func(module android.Module) {
+ dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep.TransitiveAconfigFiles != nil {
+ fromDeps = append(fromDeps, dep.TransitiveAconfigFiles)
+ }
+ })
+
+ // DepSet containing aconfig files myself and from dependencies
+ j.transitiveAconfigFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
+}
+
+func (j *Module) AddAconfigIntermediate(path android.Path) {
+ j.aconfigIntermediates = append(j.aconfigIntermediates, path)
+}
+
+func (j *Module) getTransitiveAconfigFiles() *android.DepSet[android.Path] {
+ if j.transitiveAconfigFiles == nil {
+ panic(fmt.Errorf("java.Moduile: getTransitiveAconfigFiles called before collectTransitiveAconfigFiles module=%s", j.Name()))
+ }
+ return j.transitiveAconfigFiles
+}
+
type sdkLinkType int
const (
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index f4cef7fa6..c7dc3afae 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -77,7 +77,7 @@ func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyN
// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
var variations []blueprint.Variation
- if apex != "platform" && apex != "system_ext" {
+ if !android.IsConfiguredJarForPlatform(apex) {
// Pick the correct apex variant.
variations = []blueprint.Variation{
{Mutator: "apex", Variation: apex},
@@ -185,6 +185,9 @@ var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{}
// The tag used for dependencies onto bootclasspath_fragments.
var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"}
+// The tag used for dependencies onto platform_bootclasspath.
+var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"}
+
// BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
// bootclasspath that are nested within the main BootclasspathAPIProperties.
type BootclasspathNestedAPIProperties struct {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 50429b07a..dcc2dece7 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -242,7 +242,7 @@ type BootclasspathFragmentModule struct {
modulePaths []string
// Path to the boot image profile.
- profilePath android.Path
+ profilePath android.WritablePath
}
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -256,16 +256,6 @@ type commonBootclasspathFragment interface {
// versioned sdk.
produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
- // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
- // predefined in the bootImageConfig.
- //
- // If it could not create the files then it will return nil. Otherwise, it will return a map from
- // android.ArchType to the predefined paths of the boot image files.
- produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs
-
- // getImageName returns the `image_name` property of this fragment.
- getImageName() *string
-
// getProfilePath returns the path to the boot image profile.
getProfilePath() android.Path
}
@@ -295,9 +285,6 @@ func bootclasspathFragmentFactory() android.Module {
return
}
}
-
- // Initialize the contents property from the image_name.
- bootclasspathFragmentInitContentsFromImage(ctx, m)
})
return m
}
@@ -308,9 +295,7 @@ func testBootclasspathFragmentFactory() android.Module {
return m
}
-// bootclasspathFragmentInitContentsFromImage will initialize the contents property from the image_name if
-// necessary.
-func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext, m *BootclasspathFragmentModule) {
+func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.EarlyModuleContext) {
contents := m.properties.Contents
if len(contents) == 0 {
ctx.PropertyErrorf("contents", "required property is missing")
@@ -332,6 +317,18 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext,
// too early in the Soong processing for that to work.
global := dexpreopt.GetGlobalConfig(ctx)
modules := global.ArtApexJars
+ configuredJars := modules.CopyOfJars()
+
+ // Skip the check if the configured jars list is empty as that is a common configuration when
+ // building targets that do not result in a system image.
+ if len(configuredJars) == 0 {
+ return
+ }
+
+ if !reflect.DeepEqual(configuredJars, contents) {
+ ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
+ configuredJars, contents)
+ }
// Make sure that the apex specified in the configuration is consistent and is one for which
// this boot image is available.
@@ -357,42 +354,11 @@ func bootclasspathFragmentInitContentsFromImage(ctx android.EarlyModuleContext,
}
}
-// bootclasspathImageNameContentsConsistencyCheck checks that the configuration that applies to this
-// module (if any) matches the contents.
-//
-// This should be a noop as if image_name="art" then the contents will be set from the ArtApexJars
-// config by bootclasspathFragmentInitContentsFromImage so it will be guaranteed to match. However,
-// in future this will not be the case.
-func (b *BootclasspathFragmentModule) bootclasspathImageNameContentsConsistencyCheck(ctx android.BaseModuleContext) {
- imageName := proptools.String(b.properties.Image_name)
- if imageName == "art" {
- // Get the configuration for the art apex jars.
- modules := b.getImageConfig(ctx).modules
- configuredJars := modules.CopyOfJars()
-
- // Skip the check if the configured jars list is empty as that is a common configuration when
- // building targets that do not result in a system image.
- if len(configuredJars) == 0 {
- return
- }
-
- contents := b.properties.Contents
- if !reflect.DeepEqual(configuredJars, contents) {
- ctx.ModuleErrorf("inconsistency in specification of contents. ArtApexJars configuration specifies %#v, contents property specifies %#v",
- configuredJars, contents)
- }
- }
-}
-
var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{})
// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
// apex contents.
type BootclasspathFragmentApexContentInfo struct {
- // The configured modules, will be empty if this is from a bootclasspath_fragment that does not
- // set image_name: "art".
- modules android.ConfiguredJarList
-
// Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the
// hidden API encoded dex jar path.
contentModuleDexJarPaths bootDexJarByModule
@@ -405,10 +371,6 @@ type BootclasspathFragmentApexContentInfo struct {
profileInstallPathInApex string
}
-func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList {
- return i.modules
-}
-
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
@@ -503,7 +465,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
// unused prebuilt that was created without instrumentation from breaking an instrumentation
// build.
if isActiveModule(ctx.Module()) {
- b.bootclasspathImageNameContentsConsistencyCheck(ctx)
+ b.bootclasspathFragmentPropertyCheck(ctx)
}
// Generate classpaths.proto config
@@ -523,34 +485,15 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
- // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a
- // prebuilt which will not use the image config.
- imageConfig := b.getImageConfig(ctx)
-
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
- var bootImageFiles bootImageOutputs
- if imageConfig != nil {
- // Delegate the production of the boot image files to a module type specific method.
- common := ctx.Module().(commonBootclasspathFragment)
- bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
- b.profilePath = bootImageFiles.profile
-
- if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
- // Zip the boot image files up, if available. This will generate the zip file in a
- // predefined location.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
-
- // Copy the dex jars of this fragment's content modules to their predefined locations.
- copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
- }
- }
-
- // A prebuilt fragment cannot contribute to an apex.
- if !android.IsModulePrebuilt(ctx.Module()) {
- // Provide the apex content info.
- b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
+ if android.IsModulePrebuilt(ctx.Module()) {
+ b.profilePath = ctx.Module().(*PrebuiltBootclasspathFragmentModule).produceBootImageProfile(ctx)
+ } else {
+ b.profilePath = b.produceBootImageProfileFromSource(ctx, contents, hiddenAPIOutput.EncodedBootDexFilesByModule)
+ // Provide the apex content info. A prebuilt fragment cannot contribute to an apex.
+ b.provideApexContentInfo(ctx, hiddenAPIOutput, b.profilePath)
}
// In order for information about bootclasspath_fragment modules to be added to module-info.json
@@ -564,45 +507,37 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
}
}
-// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
-// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest
-// of the build.
-//
-// This ensures that only a single module will copy its files to the image configuration.
-func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool {
- // Bootclasspath fragment modules that are for the platform do not produce boot related files.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if apexInfo.IsForPlatform() {
- return false
+// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
+// empty string if this module should not provide a boot image profile.
+func (b *BootclasspathFragmentModule) getProfileProviderApex(ctx android.BaseModuleContext) string {
+ // Only use the profile from the module that is preferred.
+ if !isActiveModule(ctx.Module()) {
+ return ""
}
- // If the image configuration has no modules specified then it means that the build has been
- // configured to build something other than a boot image, e.g. an sdk, so do not try and copy the
- // files.
- if imageConfig.modules.Len() == 0 {
- return false
+ // Bootclasspath fragment modules that are for the platform do not produce boot related files.
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ for _, apex := range apexInfo.InApexVariants {
+ if isProfileProviderApex(ctx, apex) {
+ return apex
+ }
}
- // Only copy files from the module that is preferred.
- return isActiveModule(ctx.Module())
+ return ""
}
// provideApexContentInfo creates, initializes and stores the apex content info for use by other
// modules.
-func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) {
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, hiddenAPIOutput *HiddenAPIOutput, profile android.WritablePath) {
// Construct the apex content info from the config.
info := BootclasspathFragmentApexContentInfo{
// Populate the apex content info with paths to the dex jars.
contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule,
}
- if imageConfig != nil {
- info.modules = imageConfig.modules
- global := dexpreopt.GetGlobalConfig(ctx)
- if !global.DisableGenerateProfile {
- info.profilePathOnHost = bootImageFiles.profile
- info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
- }
+ if profile != nil {
+ info.profilePathOnHost = profile
+ info.profileInstallPathInApex = profileInstallPathInApex
}
// Make the apex content info available for other modules.
@@ -623,12 +558,12 @@ func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx and
}
func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
+ global := dexpreopt.GetGlobalConfig(ctx)
+
if "art" == proptools.String(b.properties.Image_name) {
- return b.getImageConfig(ctx).modules
+ return global.ArtApexJars
}
- global := dexpreopt.GetGlobalConfig(ctx)
-
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
@@ -654,25 +589,6 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext)
return jars
}
-func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
- // Get a map of the image configs that are supported.
- imageConfigs := genBootImageConfigs(ctx)
-
- // Retrieve the config for this image.
- imageNamePtr := b.properties.Image_name
- if imageNamePtr == nil {
- return nil
- }
-
- imageName := *imageNamePtr
- imageConfig := imageConfigs[imageName]
- if imageConfig == nil {
- ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedKeys(imageConfigs), ", "))
- return nil
- }
- return imageConfig
-}
-
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput {
@@ -855,48 +771,22 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC
return output
}
-// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- // Only generate the boot image if the configuration does not skip it.
- return b.generateBootImageBuildActions(ctx, imageConfig)
-}
-
-// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
-// module.
-//
-// If it could not create the files then it will return nil. Otherwise, it will return a map from
-// android.ArchType to the predefined paths of the boot image files.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return bootImageOutputs{}
- }
-
- // Bootclasspath fragment modules that are for the platform do not produce a boot image.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if apexInfo.IsForPlatform() {
- return bootImageOutputs{}
+// produceBootImageProfileFromSource builds the boot image profile from the source if it is required.
+func (b *BootclasspathFragmentModule) produceBootImageProfileFromSource(ctx android.ModuleContext, contents []android.Module, modules bootDexJarByModule) android.WritablePath {
+ apex := b.getProfileProviderApex(ctx)
+ if apex == "" {
+ return nil
}
- // Build a profile for the image config and then use that to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
-
- // If dexpreopt of boot image jars should be skipped, generate only a profile.
- if SkipDexpreoptBootJars(ctx) {
- return bootImageOutputs{
- profile: profile,
- }
+ dexPaths := make(android.Paths, 0, len(contents))
+ dexLocations := make([]string, 0, len(contents))
+ for _, module := range contents {
+ dexPaths = append(dexPaths, modules[module.Name()])
+ dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name() + ".jar"))
}
- // Build boot image files for the host variants.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
- // Build boot image files for the android variants.
- bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
- // Return the boot image files for the android variants for inclusion in an APEX and to be zipped
- // up for the dist.
- return bootImageFiles
+ // Build a profile for the modules in this fragment.
+ return bootImageProfileRuleCommon(ctx, b.Name(), dexPaths, dexLocations)
}
func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -919,10 +809,6 @@ func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntr
return entriesList
}
-func (b *BootclasspathFragmentModule) getImageName() *string {
- return b.properties.Image_name
-}
-
func (b *BootclasspathFragmentModule) getProfilePath() android.Path {
return b.profilePath
}
@@ -1192,39 +1078,19 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
return &output
}
-// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
- if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
- return bootImageOutputs{}
+// produceBootImageProfile extracts the boot image profile from the APEX if available.
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath {
+ // This module does not provide a boot image profile.
+ if module.getProfileProviderApex(ctx) == "" {
+ return nil
}
di := android.FindDeapexerProviderForModule(ctx)
if di == nil {
- return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule.
+ return nil // An error has been reported by FindDeapexerProviderForModule.
}
- profile := (android.WritablePath)(nil)
- if imageConfig.profileInstallPathInApex != "" {
- profile = di.PrebuiltExportPath(imageConfig.profileInstallPathInApex)
- }
-
- // Build the boot image files for the host variants. These are always built from the dex files
- // provided by the contents of this module as prebuilt versions of the host boot image files are
- // not available, i.e. there is no host specific prebuilt apex containing them. This has to be
- // built without a profile as the prebuilt modules do not provide a profile.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-
- if profile == nil && imageConfig.isProfileGuided() {
- ctx.ModuleErrorf("Unable to produce boot image files: profiles not found in the prebuilt apex")
- return bootImageOutputs{}
- }
- // Build boot image files for the android variants from the dex files provided by the contents
- // of this module.
- return buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-}
-
-func (b *PrebuiltBootclasspathFragmentModule) getImageName() *string {
- return b.properties.Image_name
+ return di.PrebuiltExportPath(profileInstallPathInApex)
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
@@ -1239,14 +1105,10 @@ var _ commonBootclasspathFragment = (*PrebuiltBootclasspathFragmentModule)(nil)
// If there is no image config associated with this fragment then it returns nil. Otherwise, it
// returns the files that are listed in the image config.
func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
- imageConfig := module.getImageConfig(ctx)
- if imageConfig != nil {
- files := []string{}
- if imageConfig.profileInstallPathInApex != "" {
- // Add the boot image profile.
- files = append(files, imageConfig.profileInstallPathInApex)
+ for _, apex := range module.ApexProperties.Apex_available {
+ if isProfileProviderApex(ctx, apex) {
+ return []string{profileInstallPathInApex}
}
- return files
}
return nil
}
@@ -1262,9 +1124,5 @@ func prebuiltBootclasspathFragmentFactory() android.Module {
android.InitApexModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
- // Initialize the contents property from the image_name.
- android.AddLoadHook(m, func(ctx android.LoadHookContext) {
- bootclasspathFragmentInitContentsFromImage(ctx, &m.BootclasspathFragmentModule)
- })
return m
}
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 2541f14ff..888caad16 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -40,6 +40,12 @@ func TestBootclasspathFragment_UnknownImageName(t *testing.T) {
image_name: "unknown",
contents: ["foo"],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
`)
}
@@ -53,6 +59,11 @@ func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) {
image_name: "unknown",
contents: ["foo"],
}
+
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ }
`)
}
@@ -72,6 +83,18 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T
"apex",
],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ installable: true,
+ }
`)
}
@@ -92,6 +115,18 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin
"apex2",
],
}
+
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ installable: true,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ installable: true,
+ }
`)
}
diff --git a/java/builder.go b/java/builder.go
index c4395e91d..debf49a00 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -42,7 +42,8 @@ var (
// TODO(b/143658984): goma can't handle the --system argument to javac.
javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac",
blueprint.RuleParams{
- Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" "$out" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
+ Command: `rm -rf "$outDir" "$annoDir" "$annoSrcJar.tmp" "$srcJarDir" "$out.tmp" && ` +
+ `mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
`${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
@@ -50,14 +51,18 @@ var (
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
- `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
- `rm -rf "$srcJarDir"`,
+ `$annoSrcJarTemplate${config.SoongZipCmd} -jar -o $annoSrcJar.tmp -C $annoDir -D $annoDir && ` +
+ `$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
+ `if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
+ `if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
+ `rm -rf "$srcJarDir" "$outDir"`,
CommandDeps: []string{
"${config.JavacCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
+ Restat: true,
Rspfile: "$out.rsp",
RspfileContent: "$in",
}, map[string]*remoteexec.REParams{
@@ -69,12 +74,19 @@ var (
"$zipTemplate": &remoteexec.REParams{
Labels: map[string]string{"type": "tool", "name": "soong_zip"},
Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
- OutputFiles: []string{"$out"},
+ OutputFiles: []string{"$out.tmp"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$annoSrcJarTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$annoDir"},
+ OutputFiles: []string{"$annoSrcJar.tmp"},
ExecStrategy: "${config.REJavacExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
- "outDir", "annoDir", "javaVersion"}, nil)
+ "outDir", "annoDir", "annoSrcJar", "javaVersion"}, nil)
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
@@ -259,6 +271,12 @@ var (
Description: "Check zip alignment",
},
)
+
+ convertImplementationJarToHeaderJarRule = pctx.AndroidStaticRule("convertImplementationJarToHeaderJar",
+ blueprint.RuleParams{
+ Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
+ CommandDeps: []string{"${config.Zip2ZipCmd}"},
+ })
)
func init() {
@@ -312,7 +330,7 @@ func DefaultJavaBuilderFlags() javaBuilderFlags {
}
func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
+ srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath, flags javaBuilderFlags, deps android.Paths) {
// Compile java sources into .class files
desc := "javac"
@@ -320,7 +338,7 @@ func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
desc += strconv.Itoa(shardIdx)
}
- transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc)
+ transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, annoSrcJar, flags, deps, "javac", desc)
}
// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
@@ -494,7 +512,7 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
// suffix will be appended to various intermediate files and directories to avoid collisions when
// this function is called twice in the same module directory.
func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- shardIdx int, srcFiles, srcJars android.Paths,
+ shardIdx int, srcFiles, srcJars android.Paths, annoSrcJar android.WritablePath,
flags javaBuilderFlags, deps android.Paths,
intermediatesDir, desc string) {
@@ -541,11 +559,12 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
rule = javacRE
}
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: desc,
- Output: outputFile,
- Inputs: srcFiles,
- Implicits: deps,
+ Rule: rule,
+ Description: desc,
+ Output: outputFile,
+ ImplicitOutput: annoSrcJar,
+ Inputs: srcFiles,
+ Implicits: deps,
Args: map[string]string{
"javacFlags": flags.javacFlags,
"bootClasspath": bootClasspath,
@@ -556,6 +575,7 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
"srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
"outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
"annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
+ "annoSrcJar": annoSrcJar.String(),
"javaVersion": flags.javaVersion.String(),
},
})
@@ -619,6 +639,15 @@ func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePa
})
}
+func convertImplementationJarToHeaderJar(ctx android.ModuleContext, implementationJarFile android.Path,
+ headerJarFile android.WritablePath) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: convertImplementationJarToHeaderJarRule,
+ Input: implementationJarFile,
+ Output: headerJarFile,
+ })
+}
+
func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
classesJar android.Path, rulesFile android.Path) {
ctx.Build(pctx, android.BuildParams{
diff --git a/java/config/config.go b/java/config/config.go
index 195dae16b..83c27d309 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -148,6 +148,8 @@ func init() {
pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
+ pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
+
pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index eadd9c697..4380f4f5c 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -55,6 +55,19 @@ java_library {
],
}
+java_api_library {
+ name: "core.current.stubs.from-text",
+ api_surface: "core",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "conscrypt.module.public.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+}
+
java_library {
name: "core.current.stubs",
defaults: [
@@ -146,12 +159,42 @@ java_system_modules {
],
}
+java_defaults {
+ name: "core.module_lib.stubs.defaults",
+ visibility: ["//visibility:private"],
+ sdk_version: "none",
+ system_modules: "none",
+}
+
// A stubs target containing the parts of the public SDK & @SystemApi(MODULE_LIBRARIES) API
// provided by the core libraries.
//
// Don't use this directly, use "sdk_version: module_current".
java_library {
name: "core.module_lib.stubs",
+ defaults: [
+ "core.module_lib.stubs.defaults",
+ ],
+ static_libs: [
+ "core.module_lib.stubs.from-source",
+ ],
+ product_variables: {
+ build_from_text_stub: {
+ static_libs: [
+ "core.module_lib.stubs.from-text",
+ ],
+ exclude_static_libs: [
+ "core.module_lib.stubs.from-source",
+ ],
+ },
+ },
+}
+
+java_library {
+ name: "core.module_lib.stubs.from-source",
+ defaults: [
+ "core.module_lib.stubs.defaults",
+ ],
static_libs: [
"art.module.public.api.stubs.module_lib",
@@ -161,9 +204,6 @@ java_library {
"conscrypt.module.public.api.stubs",
"i18n.module.public.api.stubs",
],
- sdk_version: "none",
- system_modules: "none",
- visibility: ["//visibility:private"],
}
// Produces a dist file that is used by the
@@ -237,6 +277,32 @@ java_library {
],
}
+java_defaults {
+ name: "android_core_platform_stubs_current_contributions",
+ api_surface: "core_platform",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "art.module.public.api.stubs.source.system.api.contribution",
+ "art.module.public.api.stubs.source.module_lib.api.contribution",
+ "conscrypt.module.platform.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+}
+
+java_api_library {
+ name: "legacy.core.platform.api.stubs.from-text",
+ api_surface: "core_platform",
+ defaults: [
+ "android_core_platform_stubs_current_contributions",
+ ],
+ api_contributions: [
+ "legacy.i18n.module.platform.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+}
+
java_library {
name: "legacy.core.platform.api.stubs",
visibility: core_platform_visibility,
@@ -249,10 +315,10 @@ java_library {
product_variables: {
build_from_text_stub: {
static_libs: [
- "stable.core.platform.api.stubs.from-text",
+ "legacy.core.platform.api.stubs.from-text",
],
exclude_static_libs: [
- "stable.core.platform.api.stubs.from-source",
+ "legacy.core.platform.api.stubs.from-source",
],
},
},
@@ -300,6 +366,20 @@ java_library {
],
}
+java_api_library {
+ name: "stable.core.platform.api.stubs.from-text",
+ api_surface: "core_platform",
+ defaults: [
+ "android_core_platform_stubs_current_contributions",
+ ],
+ api_contributions: [
+ "stable.i18n.module.platform.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+}
+
java_library {
name: "stable.core.platform.api.stubs",
visibility: core_platform_visibility,
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
index 0cf0f360b..c46f8b8ea 100644
--- a/java/core-libraries/TxtStubLibraries.bp
+++ b/java/core-libraries/TxtStubLibraries.bp
@@ -57,19 +57,23 @@ java_library {
],
}
-java_library {
+java_api_library {
name: "core.module_lib.stubs.from-text",
- static_libs: [
- "art.module.public.api.stubs.module_lib.from-text",
+ api_surface: "module-lib",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "art.module.public.api.stubs.source.system.api.contribution",
+ "art.module.public.api.stubs.source.module_lib.api.contribution",
- // Replace the following with the module-lib correspondence when Conscrypt or i18N module
+ // Add the module-lib correspondence when Conscrypt or i18N module
// provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
// @SystemApi(MODULE_LIBRARIES).
- "conscrypt.module.public.api.stubs.from-text",
- "i18n.module.public.api.stubs.from-text",
+ "conscrypt.module.public.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
],
- sdk_version: "none",
- system_modules: "none",
visibility: ["//visibility:private"],
}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 3581040f8..5460dc993 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -143,6 +143,8 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont
ResourceJars: d.resourceJars,
SrcJarArgs: d.srcJarArgs,
SrcJarDeps: d.srcJarDeps,
+ // TODO: Not sure if aconfig flags that have been moved between device and host variants
+ // make sense.
})
}
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
index 3c9a0f3f1..3413da03d 100644
--- a/java/device_host_converter_test.go
+++ b/java/device_host_converter_test.go
@@ -135,6 +135,7 @@ func TestHostForDevice(t *testing.T) {
hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String())
hostJavac := hostModule.Output("javac/host_module.jar")
+ hostJavacHeader := hostModule.Output("javac-header/host_module.jar")
hostRes := hostModule.Output("res/host_module.jar")
hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOSCommonTarget.String())
@@ -148,7 +149,7 @@ func TestHostForDevice(t *testing.T) {
// check classpath of device module with dependency on host_for_device_module
expectedClasspath := "-classpath " + strings.Join(android.Paths{
- hostJavac.Output,
+ hostJavacHeader.Output,
hostImportCombined.Output,
}.Strings(), ":")
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 2b0f57e82..003f2de22 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,7 +16,6 @@ package java
import (
"path/filepath"
- "sort"
"strings"
"android/soong/android"
@@ -224,6 +223,11 @@ var artApexNames = []string{
"com.google.android.art.testing",
}
+var (
+ dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
+ dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+)
+
func init() {
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
@@ -241,6 +245,9 @@ type bootImageConfig struct {
// Image name (used in directory names and ninja rule names).
name string
+ // If the module with the given name exists, this config is enabled.
+ enabledIfExists string
+
// Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
stem string
@@ -257,10 +264,6 @@ type bootImageConfig struct {
// the location is relative to "/".
installDir string
- // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
- // needed.
- profileInstallPathInApex string
-
// A list of (location, jar) pairs for the Java modules in this image.
modules android.ConfiguredJarList
@@ -296,10 +299,9 @@ type bootImageConfig struct {
// The "--single-image" argument.
singleImage bool
- // Profiles imported from other boot image configs. Each element must represent a
- // `bootclasspath_fragment` of an APEX (i.e., the `name` field of each element must refer to the
- // `image_name` property of a `bootclasspath_fragment`).
- profileImports []*bootImageConfig
+ // Profiles imported from APEXes, in addition to the profile at the default path. Each entry must
+ // be the name of an APEX module.
+ profileImports []string
}
// Target-dependent description of a boot image.
@@ -384,7 +386,7 @@ func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string
m := image.modules.Jar(idx)
name := image.stem
if idx != 0 || image.extends != nil {
- name += "-" + android.ModuleStem(m)
+ name += "-" + android.ModuleStem(ctx.Config(), image.modules.Apex(idx), m)
}
return name
}
@@ -458,18 +460,26 @@ func (image *bootImageConfig) isProfileGuided() bool {
return image.compilerFilter == "speed-profile"
}
+func (image *bootImageConfig) isEnabled(ctx android.BaseModuleContext) bool {
+ return ctx.OtherModuleExists(image.enabledIfExists)
+}
+
func dexpreoptBootJarsFactory() android.SingletonModule {
m := &dexpreoptBootJars{}
- android.InitAndroidModule(m)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
+ ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator).Parallel()
+ })
}
func SkipDexpreoptBootJars(ctx android.PathContext) bool {
- return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages
+ global := dexpreopt.GetGlobalConfig(ctx)
+ return global.DisablePreoptBootImages || !shouldBuildBootImages(ctx.Config(), global)
}
// Singleton module for generating boot image build rules.
@@ -492,39 +502,90 @@ type dexpreoptBootJars struct {
dexpreoptConfigForMake android.WritablePath
}
-// Provide paths to boot images for use by modules that depend upon them.
-//
-// The build rules are created in GenerateSingletonBuildActions().
-func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Placeholder for now.
-}
-
-// Generate build rules for boot images.
-func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
- // No module has enabled dexpreopting, so we assume there will be no boot image to make.
+func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
+ if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
return
}
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- d.dexpreoptConfigForMake = android.PathForOutput(ctx, toDexpreoptDirName(archType), "dexpreopt.config")
- writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
}
- defaultImageConfig := defaultBootImageConfig(ctx)
- d.defaultBootImage = defaultImageConfig
imageConfigs := genBootImageConfigs(ctx)
- d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
for _, config := range imageConfigs {
- if config != defaultImageConfig {
+ if !config.isEnabled(ctx) {
+ continue
+ }
+ // For accessing the boot jars.
+ addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ }
+
+ if ctx.OtherModuleExists("platform-bootclasspath") {
+ // For accessing all bootclasspath fragments.
+ addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag)
+ } else if ctx.OtherModuleExists("art-bootclasspath-fragment") {
+ // For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where
+ // platform-bootclasspath doesn't exist.
+ addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag)
+ }
+}
+
+func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
+ return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
+ fragments := make(map[string]android.Module)
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if !isActiveModule(child) {
+ return false
+ }
+ tag := ctx.OtherModuleDependencyTag(child)
+ if tag == platformBootclasspathDepTag {
+ return true
+ }
+ if tag == bootclasspathFragmentDepTag {
+ apexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+ for _, apex := range apexInfo.InApexVariants {
+ fragments[apex] = child
+ }
+ return false
+ }
+ return false
+ })
+ return fragments
+ }).(map[string]android.Module)
+}
+
+func getBootclasspathFragmentByApex(ctx android.ModuleContext, apexName string) android.Module {
+ return gatherBootclasspathFragments(ctx)[apexName]
+}
+
+// GenerateAndroidBuildActions generates the build rules for boot images.
+func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ imageConfigs := genBootImageConfigs(ctx)
+ d.defaultBootImage = defaultBootImageConfig(ctx)
+ d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
+ for _, name := range getImageNames() {
+ config := imageConfigs[name]
+ if config != d.defaultBootImage {
d.otherImages = append(d.otherImages, config)
}
+ if !config.isEnabled(ctx) {
+ continue
+ }
+ generateBootImage(ctx, config)
+ if config == d.defaultBootImage {
+ bootFrameworkProfileRule(ctx, config)
+ }
}
}
+// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
+func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+ d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config")
+ writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
+}
+
// shouldBuildBootImages determines whether boot images should be built.
func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool {
// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
@@ -537,6 +598,101 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig
return true
}
+func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) {
+ apexJarModulePairs := getModulesForImage(ctx, imageConfig)
+
+ // Copy module dex jars to their predefined locations.
+ bootDexJarsByModule := extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx, apexJarModulePairs)
+ copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
+
+ // Build a profile for the image config from the profile at the default path. The profile will
+ // then be used along with profiles imported from APEXes to build the boot image.
+ profile := bootImageProfileRule(ctx, imageConfig)
+
+ // If dexpreopt of boot image jars should be skipped, stop after generating a profile.
+ if SkipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ // Build boot image files for the android variants.
+ androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+
+ // Zip the android variant boot image files up.
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
+
+ // Build boot image files for the host variants. There are use directly by ART host side tests.
+ buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
+
+ // Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes.
+ dumpOatRules(ctx, imageConfig)
+}
+
+type apexJarModulePair struct {
+ apex string
+ jarModule android.Module
+}
+
+func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []apexJarModulePair {
+ modules := make([]apexJarModulePair, 0, imageConfig.modules.Len())
+ for i := 0; i < imageConfig.modules.Len(); i++ {
+ found := false
+ for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) {
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ if name == imageConfig.modules.Jar(i) {
+ modules = append(modules, apexJarModulePair{
+ apex: imageConfig.modules.Apex(i),
+ jarModule: module,
+ })
+ found = true
+ break
+ }
+ }
+ if !found && !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf(
+ "Boot image '%s' module '%s' not added as a dependency of dex_bootjars",
+ imageConfig.name,
+ imageConfig.modules.Jar(i))
+ return []apexJarModulePair{}
+ }
+ }
+ return modules
+}
+
+// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for
+// the given modules.
+func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule {
+ encodedDexJarsByModuleName := bootDexJarByModule{}
+ for _, pair := range apexJarModulePairs {
+ var path android.Path
+ if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
+ // This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
+ // files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
+ // a source APEX because there is no guarantee that it is the same as the jar packed into the
+ // APEX. In practice, they are the same when we are building from a full source tree, but they
+ // are different when we are building from a thin manifest (e.g., master-art), where there is
+ // no monolithic hidden API files at all.
+ path = retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
+ } else {
+ // Use exactly the same jar that is packed into the APEX.
+ fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
+ "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
+ pair.jarModule.Name(),
+ pair.apex)
+ }
+ bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragment, BootclasspathFragmentApexContentInfoProvider).(BootclasspathFragmentApexContentInfo)
+ jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+ path = jar
+ }
+ encodedDexJarsByModuleName.addPath(pair.jarModule, path)
+ }
+ return encodedDexJarsByModuleName
+}
+
// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
// paths in the global config.
func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
@@ -687,10 +843,12 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
rule.Command().Text("rm").Flag("-f").
Flag(symbolsDir.Join(ctx, "*.art").String()).
Flag(symbolsDir.Join(ctx, "*.oat").String()).
+ Flag(symbolsDir.Join(ctx, "*.vdex").String()).
Flag(symbolsDir.Join(ctx, "*.invocation").String())
rule.Command().Text("rm").Flag("-f").
Flag(outputDir.Join(ctx, "*.art").String()).
Flag(outputDir.Join(ctx, "*.oat").String()).
+ Flag(outputDir.Join(ctx, "*.vdex").String()).
Flag(outputDir.Join(ctx, "*.invocation").String())
cmd := rule.Command()
@@ -712,36 +870,31 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
- if profile != nil {
- cmd.FlagWithInput("--profile-file=", profile)
- }
-
- fragments := make(map[string]commonBootclasspathFragment)
- ctx.VisitDirectDepsWithTag(bootclasspathFragmentDepTag, func(child android.Module) {
- fragment := child.(commonBootclasspathFragment)
- if fragment.getImageName() != nil && android.IsModulePreferred(child) {
- fragments[*fragment.getImageName()] = fragment
+ if image.isProfileGuided() && !global.DisableGenerateProfile {
+ if profile != nil {
+ cmd.FlagWithInput("--profile-file=", profile)
}
- })
- for _, profileImport := range image.profileImports {
- fragment := fragments[profileImport.name]
- if fragment == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
- "bootclasspath_fragment with image name '%[2]s' doesn't exist or is not added as a "+
- "dependency of '%[1]s'",
- image.name,
- profileImport.name)
- return bootImageVariantOutputs{}
- }
- if fragment.getProfilePath() == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
- "doesn't provide a profile",
- image.name,
- profileImport.name)
- return bootImageVariantOutputs{}
+ for _, apex := range image.profileImports {
+ fragment := getBootclasspathFragmentByApex(ctx, apex)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
+ "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
+ "dependency of dex_bootjars",
+ image.name,
+ apex)
+ return bootImageVariantOutputs{}
+ }
+ importedProfile := fragment.(commonBootclasspathFragment).getProfilePath()
+ if importedProfile == nil {
+ ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
+ "doesn't provide a profile",
+ image.name,
+ apex)
+ return bootImageVariantOutputs{}
+ }
+ cmd.FlagWithInput("--profile-file=", importedProfile)
}
- cmd.FlagWithInput("--profile-file=", fragment.getProfilePath())
}
dirtyImageFile := "frameworks/base/config/dirty-image-objects"
@@ -885,11 +1038,7 @@ const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
-func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
- if !image.isProfileGuided() {
- return nil
- }
-
+func bootImageProfileRuleCommon(ctx android.ModuleContext, name string, dexFiles android.Paths, dexLocations []string) android.WritablePath {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -916,28 +1065,39 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and
if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() {
profiles = append(profiles, path.Path())
}
- bootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
+ bootImageProfile := android.PathForModuleOut(ctx, name, "boot-image-profile.txt")
rule.Command().Text("cat").Inputs(profiles).Text(">").Output(bootImageProfile)
- profile := image.dir.Join(ctx, "boot.prof")
+ profile := android.PathForModuleOut(ctx, name, "boot.prof")
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
Tool(globalSoong.Profman).
Flag("--output-profile-type=boot").
FlagWithInput("--create-profile-from=", bootImageProfile).
- FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
+ FlagForEachInput("--apk=", dexFiles).
+ FlagForEachArg("--dex-location=", dexLocations).
FlagWithOutput("--reference-profile-file=", profile)
+ rule.Build("bootJarsProfile_"+name, "profile boot jars "+name)
+
+ return profile
+}
+
+func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+ if !image.isProfileGuided() {
+ return nil
+ }
+
+ profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps)
+
if image == defaultBootImageConfig(ctx) {
+ rule := android.NewRuleBuilder(pctx, ctx)
rule.Install(profile, "/system/etc/boot-image.prof")
image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
}
- rule.Build("bootJarsProfile", "profile boot jars")
-
return profile
}
@@ -976,6 +1136,8 @@ func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig)
func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
var allPhonies android.Paths
+ name := image.name
+ global := dexpreopt.GetGlobalConfig(ctx)
for _, image := range image.variants {
arch := image.target.Arch.ArchType
suffix := arch.String()
@@ -984,36 +1146,39 @@ func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
suffix = "host-" + suffix
}
// Create a rule to call oatdump.
- output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
+ output := android.PathForOutput(ctx, name+"."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder(pctx, ctx)
imageLocationsOnHost, _ := image.imageLocations()
- rule.Command().
+ cmd := rule.Command().
BuiltTool("oatdump").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
- rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
+ if global.EnableUffdGc && image.target.Os == android.Android {
+ cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ }
+ rule.Build("dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
// Create a phony rule that depends on the output file and prints the path.
- phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
+ phony := android.PathForPhony(ctx, "dump-oat-"+name+"-"+suffix)
rule = android.NewRuleBuilder(pctx, ctx)
rule.Command().
Implicit(output).
ImplicitOutput(phony).
Text("echo").FlagWithArg("Output in ", output.String())
- rule.Build("phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
+ rule.Build("phony-dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
allPhonies = append(allPhonies, phony)
}
- phony := android.PathForPhony(ctx, "dump-oat-boot")
+ phony := android.PathForPhony(ctx, "dump-oat-"+name)
ctx.Build(pctx, android.BuildParams{
Rule: android.Phony,
Output: phony,
Inputs: allPhonies,
- Description: "dump-oat-boot",
+ Description: "dump-oat-"+name,
})
}
@@ -1048,11 +1213,9 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
- var imageNames []string
// The primary ART boot image is exposed to Make for testing (gtests) and benchmarking
// (golem) purposes.
for _, current := range append(d.otherImages, image) {
- imageNames = append(imageNames, current.name)
for _, variant := range current.variants {
suffix := ""
if variant.target.Os.Class == android.Host {
@@ -1073,8 +1236,6 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
}
- // Ensure determinism.
- sort.Strings(imageNames)
- ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
+ ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(getImageNames(), " "))
}
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 28f50d7e3..0f4bd9b34 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -40,57 +40,67 @@ func dexpreoptTargets(ctx android.PathContext) []android.Target {
}
var (
- bootImageConfigKey = android.NewOnceKey("bootImageConfig")
- bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
- artBootImageName = "art"
- frameworkBootImageName = "boot"
- mainlineBootImageName = "mainline"
- bootImageStem = "boot"
+ bootImageConfigKey = android.NewOnceKey("bootImageConfig")
+ bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
+ frameworkBootImageName = "boot"
+ mainlineBootImageName = "mainline"
+ bootImageStem = "boot"
+ profileInstallPathInApex = "etc/boot-image.prof"
)
+// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be
+// deterministic. The names listed here must match the map keys returned by genBootImageConfigs.
+func getImageNames() []string {
+ return []string{"art", "boot", "mainline"}
+}
+
func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigRawKey, func() interface{} {
global := dexpreopt.GetGlobalConfig(ctx)
- artModules := global.ArtApexJars
- frameworkModules := global.BootJars // This includes `artModules`.
+ artBootImageName := "art" // Keep this local to avoid accidental references.
+ frameworkModules := global.BootJars // This includes `global.ArtApexJars`.
mainlineBcpModules := global.ApexBootJars
frameworkSubdir := "system/framework"
- // ART config for the primary boot image in the ART apex.
- // It includes the Core Libraries.
+ profileImports := []string{"com.android.art"}
+
+ // ART boot image for testing only. Do not rely on it to make any build-time decision.
artCfg := bootImageConfig{
- name: artBootImageName,
- stem: bootImageStem,
- installDir: "apex/art_boot_images/javalib",
- profileInstallPathInApex: "etc/boot-image.prof",
- modules: artModules,
- preloadedClassesFile: "art/build/boot/preloaded-classes",
- compilerFilter: "speed-profile",
- singleImage: false,
+ name: artBootImageName,
+ enabledIfExists: "art-bootclasspath-fragment",
+ stem: bootImageStem,
+ installDir: "apex/art_boot_images/javalib",
+ modules: global.TestOnlyArtBootImageJars,
+ preloadedClassesFile: "art/build/boot/preloaded-classes",
+ compilerFilter: "speed-profile",
+ singleImage: false,
+ profileImports: profileImports,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
frameworkCfg := bootImageConfig{
name: frameworkBootImageName,
+ enabledIfExists: "platform-bootclasspath",
stem: bootImageStem,
installDir: frameworkSubdir,
modules: frameworkModules,
preloadedClassesFile: "frameworks/base/config/preloaded-classes",
compilerFilter: "speed-profile",
singleImage: false,
- profileImports: []*bootImageConfig{&artCfg},
+ profileImports: profileImports,
}
mainlineCfg := bootImageConfig{
- extends: &frameworkCfg,
- name: mainlineBootImageName,
- stem: bootImageStem,
- installDir: frameworkSubdir,
- modules: mainlineBcpModules,
- compilerFilter: "verify",
- singleImage: true,
+ extends: &frameworkCfg,
+ name: mainlineBootImageName,
+ enabledIfExists: "platform-bootclasspath",
+ stem: bootImageStem,
+ installDir: frameworkSubdir,
+ modules: mainlineBcpModules,
+ compilerFilter: "verify",
+ singleImage: true,
}
return map[string]*bootImageConfig{
@@ -105,8 +115,7 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
targets := dexpreoptTargets(ctx)
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- deviceDir := android.PathForOutput(ctx, toDexpreoptDirName(archType))
+ deviceDir := android.PathForOutput(ctx, getDexpreoptDirName(ctx))
configs := genBootImageConfigRaw(ctx)
@@ -181,10 +190,6 @@ func calculateDepsRecursive(c *bootImageConfig, targets []android.Target, visite
}
}
-func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
- return genBootImageConfigs(ctx)[artBootImageName]
-}
-
func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
return genBootImageConfigs(ctx)[frameworkBootImageName]
}
@@ -193,6 +198,18 @@ func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig {
return genBootImageConfigs(ctx)[mainlineBootImageName]
}
+// isProfileProviderApex returns true if this apex provides a boot image profile.
+func isProfileProviderApex(ctx android.PathContext, apexName string) bool {
+ for _, config := range genBootImageConfigs(ctx) {
+ for _, profileImport := range config.profileImports {
+ if profileImport == apexName {
+ return true
+ }
+ }
+ }
+ return false
+}
+
// Apex boot config allows to access build/install paths of apex boot jars without going
// through the usual trouble of registering dependencies on those modules and extracting build paths
// from those dependencies.
@@ -218,8 +235,7 @@ var updatableBootConfigKey = android.NewOnceKey("apexBootConfig")
func GetApexBootConfig(ctx android.PathContext) apexBootConfig {
return ctx.Config().Once(updatableBootConfigKey, func() interface{} {
apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
- archType := ctx.Config().Targets[android.Android][0].Arch.ArchType
- dir := android.PathForOutput(ctx, toDexpreoptDirName(archType), "apex_bootjars")
+ dir := android.PathForOutput(ctx, getDexpreoptDirName(ctx), "apex_bootjars")
dexPaths := apexBootJars.BuildPaths(ctx, dir)
dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir)
@@ -258,6 +274,11 @@ func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
}
-func toDexpreoptDirName(arch android.ArchType) string {
- return "dexpreopt_" + arch.String()
+func getDexpreoptDirName(ctx android.PathContext) string {
+ prefix := "dexpreopt_"
+ targets := ctx.Config().Targets[android.Android]
+ if len(targets) > 0 {
+ return prefix+targets[0].Arch.ArchType.String()
+ }
+ return prefix+"unknown_target"
}
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index cd7f295c8..44d2127fd 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -16,6 +16,7 @@ package java
import (
"runtime"
+ "sort"
"testing"
"android/soong/android"
@@ -35,3 +36,22 @@ func TestBootImageConfig(t *testing.T) {
CheckFrameworkBootImageConfig(t, result)
CheckMainlineBootImageConfig(t, result)
}
+
+func TestImageNames(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForBootImageConfigTest,
+ ).RunTest(t)
+
+ names := getImageNames()
+ sort.Strings(names)
+
+ ctx := &android.TestPathContext{TestResult: result}
+ configs := genBootImageConfigs(ctx)
+ namesFromConfigs := make([]string, 0, len(configs))
+ for name, _ := range configs {
+ namesFromConfigs = append(namesFromConfigs, name)
+ }
+ sort.Strings(namesFromConfigs)
+
+ android.AssertArrayString(t, "getImageNames vs genBootImageConfigs", names, namesFromConfigs)
+}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 6f3aa2be8..176c251fd 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -29,6 +29,7 @@ import (
"testing"
"android/soong/android"
+ "android/soong/dexpreopt"
)
// PrepareForBootImageConfigTest is the minimal set of preparers that are needed to be able to use
@@ -36,7 +37,17 @@ import (
var PrepareForBootImageConfigTest = android.GroupFixturePreparers(
android.PrepareForTestWithArchMutator,
android.PrepareForTestAccessingMakeVars,
+ PrepareForTestWithDexpreopt,
FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"),
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:core1", "com.android.art:core2", "platform:extra1"),
+ android.FixtureAddTextFile("extra1/Android.bp", `
+ java_library {
+ name: "extra1",
+ srcs: ["extra1.java"],
+ installable: true,
+ }
+ `),
+ android.FixtureAddFile("extra1/extra1.java", nil),
)
var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
@@ -44,18 +55,18 @@ var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
var PrepareApexBootJarConfigsAndModules = android.GroupFixturePreparers(
PrepareApexBootJarConfigs,
- prepareApexBootJarModule("com.android.foo", "framework-foo"),
- prepareApexBootJarModule("com.android.bar", "framework-bar"),
+ PrepareApexBootJarModule("com.android.foo", "framework-foo"),
+ PrepareApexBootJarModule("com.android.bar", "framework-bar"),
)
var ApexBootJarFragmentsForPlatformBootclasspath = fmt.Sprintf(`
{
apex: "%[1]s",
- module: "%[1]s-bootclasspathfragment",
+ module: "%[1]s-bootclasspath-fragment",
},
{
apex: "%[2]s",
- module: "%[2]s-bootclasspathfragment",
+ module: "%[2]s-bootclasspath-fragment",
},
`, "com.android.foo", "com.android.bar")
@@ -64,15 +75,22 @@ var ApexBootJarDexJarPaths = []string{
"out/soong/.intermediates/packages/modules/com.android.foo/framework-foo/android_common_apex10000/aligned/framework-foo.jar",
}
-func prepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
+func PrepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
moduleSourceDir := fmt.Sprintf("packages/modules/%s", apexName)
+ fragmentName := apexName+"-bootclasspath-fragment"
+ imageNameProp := ""
+ if apexName == "com.android.art" {
+ fragmentName = "art-bootclasspath-fragment"
+ imageNameProp = `image_name: "art",`
+ }
+
return android.GroupFixturePreparers(
android.FixtureAddTextFile(moduleSourceDir+"/Android.bp", fmt.Sprintf(`
apex {
name: "%[1]s",
key: "%[1]s.key",
bootclasspath_fragments: [
- "%[1]s-bootclasspathfragment",
+ "%[3]s",
],
updatable: false,
}
@@ -84,7 +102,8 @@ func prepareApexBootJarModule(apexName string, moduleName string) android.Fixtur
}
bootclasspath_fragment {
- name: "%[1]s-bootclasspathfragment",
+ name: "%[3]s",
+ %[4]s
contents: ["%[2]s"],
apex_available: ["%[1]s"],
hidden_api: {
@@ -100,7 +119,7 @@ func prepareApexBootJarModule(apexName string, moduleName string) android.Fixtur
compile_dex: true,
apex_available: ["%[1]s"],
}
- `, apexName, moduleName)),
+ `, apexName, moduleName, fragmentName, imageNameProp)),
android.FixtureMergeMockFs(android.MockFS{
fmt.Sprintf("%s/apex_manifest.json", moduleSourceDir): nil,
fmt.Sprintf("%s/%s.avbpubkey", moduleSourceDir, apexName): nil,
@@ -192,7 +211,7 @@ func CheckArtBootImageConfig(t *testing.T, result *android.TestResult) {
// getArtImageConfig gets the ART bootImageConfig that was created during the test.
func getArtImageConfig(result *android.TestResult) *bootImageConfig {
pathCtx := &android.TestPathContext{TestResult: result}
- imageConfig := artBootImageConfig(pathCtx)
+ imageConfig := genBootImageConfigs(pathCtx)["art"]
return imageConfig
}
@@ -210,15 +229,15 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
symbolsDir: "out/soong/dexpreopt_arm64/dex_artjars_unstripped",
installDir: "apex/art_boot_images/javalib",
profileInstallPathInApex: "etc/boot-image.prof",
- modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2"}),
- dexPaths: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
- dexPathsDeps: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar"},
+ modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2", "platform:extra1"}),
+ dexPaths: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
+ dexPathsDeps: []string{"out/soong/dexpreopt_arm64/dex_artjars_input/core1.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/core2.jar", "out/soong/dexpreopt_arm64/dex_artjars_input/extra1.jar"},
zip: "out/soong/dexpreopt_arm64/dex_artjars/art.zip",
variants: []*expectedVariant{
{
archType: android.Arm64,
- dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/arm64/boot.art",
imagesDeps: []string{
@@ -228,6 +247,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -246,6 +268,14 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.art",
+ },
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -256,6 +286,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -266,13 +300,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.Arm,
- dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar", "/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/arm/boot.art",
imagesDeps: []string{
@@ -282,6 +320,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -300,6 +341,14 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.art",
+ },
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -310,6 +359,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/arm/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -320,13 +373,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.X86_64,
- dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/x86_64/boot.art",
imagesDeps: []string{
@@ -336,6 +393,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -352,6 +412,13 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.art",
+ }, {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -362,6 +429,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -372,13 +443,17 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
{
archType: android.X86,
- dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
- dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar", "host/linux-x86/system/framework/extra1.jar"},
imagePathOnHost: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
imagePathOnDevice: "/apex/art_boot_images/javalib/x86/boot.art",
imagesDeps: []string{
@@ -388,6 +463,9 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
"out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
},
installs: []normalizedInstall{
{
@@ -404,6 +482,13 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.art",
+ }, {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ },
},
vdexInstalls: []normalizedInstall{
{
@@ -414,6 +499,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
to: "/apex/art_boot_images/javalib/x86/boot-core2.vdex",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.vdex",
+ },
},
unstrippedInstalls: []normalizedInstall{
{
@@ -424,6 +513,10 @@ func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated b
from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
},
+ {
+ from: "out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-extra1.oat",
+ },
},
licenseMetadataFile: expectedLicenseMetadataFile,
},
@@ -805,8 +898,8 @@ func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mut
},
},
profileInstalls: []normalizedInstall{
+ {from: "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", to: "/system/etc/boot-image.prof"},
{from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"},
- {from: "out/soong/dexpreopt_arm64/dex_bootjars/boot.prof", to: "/system/etc/boot-image.prof"},
},
profileLicenseMetadataFile: expectedLicenseMetadataFile,
}
@@ -1136,7 +1229,6 @@ func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expe
android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir)
android.AssertPathRelativeToTopEquals(t, "symbolsDir", expected.symbolsDir, imageConfig.symbolsDir)
android.AssertStringEquals(t, "installDir", expected.installDir, imageConfig.installDir)
- android.AssertStringEquals(t, "profileInstallPathInApex", expected.profileInstallPathInApex, imageConfig.profileInstallPathInApex)
android.AssertDeepEquals(t, "modules", expected.modules, imageConfig.modules)
android.AssertPathsRelativeToTopEquals(t, "dexPaths", expected.dexPaths, imageConfig.dexPaths.Paths())
android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths())
@@ -1195,10 +1287,10 @@ DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/dexpreopt_arm64/dex_bootjars_input/c
DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS=/apex/com.android.art/javalib/core1.jar /apex/com.android.art/javalib/core2.jar /system/framework/framework.jar
DEXPREOPT_BOOT_JARS_MODULES=com.android.art:core1:com.android.art:core2:platform:framework
DEXPREOPT_GEN=out/host/linux-x86/bin/dexpreopt_gen
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art:/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art:/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art:/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art:/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art:/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art:/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art:/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art:/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art:/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art:/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art:/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1207,10 +1299,10 @@ DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm64/dex_mainl
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art:/system/framework/arm64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art:/system/framework/x86/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art:/system/framework/x86_64/boot-framework-foo.art out/soong/dexpreopt_arm64/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.art out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
DEXPREOPT_IMAGE_DEPS_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex
@@ -1223,14 +1315,14 @@ DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/apex/art_boot_images/javalib/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework-foo.art
@@ -1238,12 +1330,12 @@ DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/dexpreopt_arm64/dex_artjars/andro
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
DEXPREOPT_IMAGE_NAMES=art boot mainline
-DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/dexpreopt_arm64/dex_bootjars/boot.prof:/system/etc/boot-image.prof
-DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
-DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof
+DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.oat:/apex/art_boot_images/javalib/x86_64/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot.oat:/system/framework/arm/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-core2.oat:/system/framework/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot.oat:/system/framework/arm64/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-core2.oat:/system/framework/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot.oat:/system/framework/x86/boot.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-core2.oat:/system/framework/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
@@ -1252,10 +1344,10 @@ DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm=out/soong/dexpreopt_arm6
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86_64=out/soong/dexpreopt_arm64/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex
-DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-extra1.vdex:/apex/art_boot_images/javalib/arm/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-extra1.vdex:/apex/art_boot_images/javalib/arm64/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.vdex:/apex/art_boot_images/javalib/x86/boot-extra1.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex:/apex/art_boot_images/javalib/x86_64/boot-extra1.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot.vdex:/system/framework/arm/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-core2.vdex:/system/framework/arm/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm/boot-framework.vdex:/system/framework/arm/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.vdex:/system/framework/arm64/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-core2.vdex:/system/framework/arm64/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot.vdex:/system/framework/x86/boot.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-core2.vdex:/system/framework/x86/boot-core2.vdex out/soong/dexpreopt_arm64/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex
diff --git a/java/droiddoc.go b/java/droiddoc.go
index d4ead12c8..3ba306554 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -699,7 +699,6 @@ func javadocCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs andro
cmd := rule.Command().
BuiltTool("soong_javac_wrapper").Tool(config.JavadocCmd(ctx)).
Flag(config.JavacVmFlags).
- FlagWithArg("-encoding ", "UTF-8").
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "javadoc.rsp"), srcs).
FlagWithInput("@", srcJarList)
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 151c94a43..f05ef1fdd 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -512,21 +512,19 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
- FlagWithArg("-source ", javaVersion.String()).
+ FlagWithArg("--java-source ", javaVersion.String()).
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
FlagWithInput("@", srcJarList)
- if len(bootclasspath) > 0 {
- cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":")
+ // Metalava does not differentiate between bootclasspath and classpath and has not done so for
+ // years, so it is unlikely to change any time soon.
+ combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
+ combinedPaths = append(combinedPaths, classpath.Paths()...)
+ if len(combinedPaths) > 0 {
+ cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
- if len(classpath) > 0 {
- cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":")
- }
-
- cmd.Flag("--no-banner").
- Flag("--color").
+ cmd.Flag("--color").
Flag("--quiet").
Flag("--format=v2").
FlagWithArg("--repeat-errors-max ", "10").
@@ -696,6 +694,13 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cmd.FlagWithArg("--error-message:compatibility:released ", msg)
}
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
+ // Pass the current API file into metalava so it can use it as the basis for determining how to
+ // generate the output signature files (both api and removed).
+ currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
+ cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
+ }
+
if generateStubs {
rule.Command().
BuiltTool("soong_zip").
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index dd1e96b3e..f29c91327 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -71,8 +71,8 @@ func TestJavaFuzz(t *testing.T) {
}
baz := result.ModuleForTests("baz", osCommonTarget).Rule("javac").Output.String()
- barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac", "bar.jar")
- bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac", "baz.jar")
+ barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac-header", "bar.jar")
+ bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac-header", "baz.jar")
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barOut)
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazOut)
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index 1b3de9fe0..f9baa85e4 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -30,7 +30,7 @@ type GeneratedJavaLibraryCallbacks interface {
// Called from inside GenerateAndroidBuildActions. Add the build rules to
// make the srcjar, and return the path to it.
- GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path
+ GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path
}
// GeneratedJavaLibraryModuleFactory provides a utility for modules that are generated
@@ -88,7 +88,7 @@ func (module *GeneratedJavaLibraryModule) GenerateAndroidBuildActions(ctx androi
checkPropertyEmpty(ctx, module, "plugins", module.Library.properties.Plugins)
checkPropertyEmpty(ctx, module, "exported_plugins", module.Library.properties.Exported_plugins)
- srcJarPath := module.callbacks.GenerateSourceJarBuildActions(ctx)
+ srcJarPath := module.callbacks.GenerateSourceJarBuildActions(module, ctx)
module.Library.properties.Generated_srcjars = append(module.Library.properties.Generated_srcjars, srcJarPath)
module.Library.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go
index 68f1f7edd..7f52fd108 100644
--- a/java/generated_java_library_test.go
+++ b/java/generated_java_library_test.go
@@ -36,7 +36,8 @@ type JavaGenLibTestCallbacks struct {
func (callbacks *JavaGenLibTestCallbacks) DepsMutator(module *GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
}
-func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
+ module.AddAconfigIntermediate(android.PathForOutput(ctx, "aconfig_cache_file"))
return android.PathForOutput(ctx, "blah.srcjar")
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index d25096b15..4d08b8307 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -106,7 +106,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJ
h.uncompressDexState = uncompressedDexState
// If hiddenapi processing is disabled treat this as inactive.
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index c6b921bb2..f31f5d1a8 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1236,7 +1236,6 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix s
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("metalava").
- Flag("--no-banner").
Inputs(removedTxtFiles).
FlagWithOutput("--dex-api ", output)
rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index d4ee4fc9f..8ec17971a 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -121,8 +121,8 @@ type hiddenAPISingleton struct {
// hiddenAPI singleton rules
func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
- // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ // Don't run any hiddenapi rules if hiddenapi checks are disabled
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
@@ -166,7 +166,7 @@ func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Modu
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
- if requiredApex == "platform" || requiredApex == "system_ext" {
+ if android.IsConfiguredJarForPlatform(requiredApex) {
if len(apexInfo.InApexVariants) != 0 {
// A platform variant is required but this is for an apex so ignore it.
return false
diff --git a/java/java.go b/java/java.go
index 50d48ab6d..70aba8e2c 100644
--- a/java/java.go
+++ b/java/java.go
@@ -26,6 +26,7 @@ import (
"android/soong/bazel"
"android/soong/bazel/cquery"
"android/soong/remoteexec"
+ "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -274,7 +275,14 @@ type JavaInfo struct {
// instrumented by jacoco.
JacocoReportClassesFile android.Path
- // TODO: Add device config declarations here?
+ // set of aconfig flags for all transitive libs deps
+ // TODO(joeo): It would be nice if this were over in the aconfig package instead of here.
+ // In order to do that, generated_java_library would need a way doing
+ // collectTransitiveAconfigFiles with one of the callbacks, and having that automatically
+ // propagated. If we were to clean up more of the stuff on JavaInfo that's not part of
+ // core java rules (e.g. AidlIncludeDirs), then maybe adding more framework to do that would be
+ // worth it.
+ TransitiveAconfigFiles *android.DepSet[android.Path]
}
var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
@@ -676,6 +684,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.minSdkVersion = j.MinSdkVersion(ctx)
j.maxSdkVersion = j.MaxSdkVersion(ctx)
+ j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
@@ -690,7 +700,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
}
- j.compile(ctx, nil)
+ j.compile(ctx, nil, nil, nil)
// Collect the module directory for IDE info in java/jdeps.go.
j.modulePaths = append(j.modulePaths, ctx.ModuleDir())
@@ -728,6 +738,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
})
j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles)
+
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1468,6 +1479,8 @@ func (j *Binary) HostToolPath() android.OptionalPath {
}
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+
if ctx.Arch().ArchType == android.Common {
// Compile the jar
if j.binaryProperties.Main_class != nil {
@@ -1670,6 +1683,9 @@ type JavaApiLibraryProperties struct {
// extracting the compiled class files provided by the
// full_api_surface_stub module.
Full_api_surface_stub *string
+
+ // Version of previously released API file for compatibility check.
+ Previous_api *string `android:"path"`
}
func ApiLibraryFactory() android.Module {
@@ -1713,11 +1729,9 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
- FlagWithArg("-encoding ", "UTF-8").
FlagWithInputList("--source-files ", srcs, " ")
- cmd.Flag("--no-banner").
- Flag("--color").
+ cmd.Flag("--color").
Flag("--quiet").
Flag("--format=v2").
Flag("--include-annotations").
@@ -1801,6 +1815,28 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
+// API signature file names sorted from
+// the narrowest api scope to the widest api scope
+var scopeOrderedSourceFileNames = allApiScopes.Strings(
+ func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
+
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths {
+ sortedSrcFiles := android.Paths{}
+
+ for _, scopeSourceFileName := range scopeOrderedSourceFileNames {
+ for _, sourceFileName := range srcFiles {
+ if sourceFileName.Base() == scopeSourceFileName {
+ sortedSrcFiles = append(sortedSrcFiles, sourceFileName)
+ }
+ }
+ }
+ if len(srcFiles) != len(sortedSrcFiles) {
+ ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles)
+ }
+
+ return sortedSrcFiles
+}
+
func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
rule := android.NewRuleBuilder(pctx, ctx)
@@ -1851,10 +1887,18 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
}
+ srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles)
+
cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
al.stubsFlags(ctx, cmd, stubsDir)
+ migratingNullability := String(al.properties.Previous_api) != ""
+ if migratingNullability {
+ previousApi := android.PathForModuleSrc(ctx, String(al.properties.Previous_api))
+ cmd.FlagWithInput("--migrate-nullness ", previousApi)
+ }
+
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
@@ -1878,8 +1922,10 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
flags.classpath = classpath(classPaths)
+ annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
+
TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
- android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+ android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{})
}
builder := android.NewRuleBuilder(pctx, ctx)
@@ -1911,6 +1957,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
ImplementationJars: android.PathsIfNonNil(al.stubsJar),
AidlIncludeDirs: android.Paths{},
+ // No aconfig libraries on api libraries
})
}
@@ -2232,6 +2279,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile),
AidlIncludeDirs: j.exportAidlIncludeDirs,
+ // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
}
@@ -2652,7 +2700,7 @@ func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonC
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
-var inList = android.InList
+var inList = android.InList[string]
// Add class loader context (CLC) of a given dependency to the current CLC.
func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
@@ -2766,11 +2814,12 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte
type javaCommonAttributes struct {
*javaResourcesAttributes
*kotlinAttributes
- Srcs bazel.LabelListAttribute
- Plugins bazel.LabelListAttribute
- Javacopts bazel.StringListAttribute
- Sdk_version bazel.StringAttribute
- Java_version bazel.StringAttribute
+ Srcs bazel.LabelListAttribute
+ Plugins bazel.LabelListAttribute
+ Javacopts bazel.StringListAttribute
+ Sdk_version bazel.StringAttribute
+ Java_version bazel.StringAttribute
+ Errorprone_force_enable bazel.BoolAttribute
}
type javaDependencyLabels struct {
@@ -2803,12 +2852,8 @@ type bp2BuildJavaInfo struct {
hasKotlin bool
}
-// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-java
-func xsdConfigJavaTarget(ctx android.BazelConversionPathContext, mod blueprint.Module) string {
- callback := func(xsd android.XsdConfigBp2buildTargets) string {
- return xsd.JavaBp2buildTargetName()
- }
- return android.XsdConfigBp2buildTarget(ctx, mod, callback)
+func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string {
+ return xsd.JavaBp2buildTargetName()
}
// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
@@ -2816,24 +2861,21 @@ func xsdConfigJavaTarget(ctx android.BazelConversionPathContext, mod blueprint.M
// which has other non-attribute information needed for bp2build conversion
// that needs different handling depending on the module types, and thus needs
// to be returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) {
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) {
var srcs bazel.LabelListAttribute
var deps bazel.LabelListAttribute
- var staticDeps bazel.LabelList
+ var staticDeps bazel.LabelListAttribute
archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
for axis, configToProps := range archVariantProps {
for config, _props := range configToProps {
if archProps, ok := _props.(*CommonProperties); ok {
- srcsNonXsd, srcsXsd := android.PartitionXsdSrcs(ctx, archProps.Srcs)
- excludeSrcsNonXsd, _ := android.PartitionXsdSrcs(ctx, archProps.Exclude_srcs)
- archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, srcsNonXsd, excludeSrcsNonXsd)
+ archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
srcs.SetSelectValue(axis, config, archSrcs)
-
- // Add to static deps
- xsdJavaConfigLibraryLabels := android.BazelLabelForModuleDepsWithFn(ctx, srcsXsd, xsdConfigJavaTarget)
- staticDeps.Append(xsdJavaConfigLibraryLabels)
-
+ if archProps.Jarjar_rules != nil {
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "jarjar_rules")
+ return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
+ }
}
}
}
@@ -2841,6 +2883,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
javaSrcPartition := "java"
protoSrcPartition := "proto"
+ xsdSrcPartition := "xsd"
logtagSrcPartition := "logtag"
aidlSrcPartition := "aidl"
kotlinPartition := "kotlin"
@@ -2849,6 +2892,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
protoSrcPartition: android.ProtoSrcLabelPartition,
aidlSrcPartition: android.AidlSrcLabelPartition,
+ xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(javaXsdTargetName)},
kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}},
})
@@ -2856,6 +2900,8 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
kotlinSrcs := srcPartitions[kotlinPartition]
javaSrcs.Append(kotlinSrcs)
+ staticDeps.Append(srcPartitions[xsdSrcPartition])
+
if !srcPartitions[logtagSrcPartition].IsEmpty() {
logtagsLibName := m.Name() + "_logtags"
ctx.CreateBazelTargetModule(
@@ -2909,29 +2955,38 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
},
)
- staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName})
+ staticDeps.Append(bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + javaAidlLibName}))
}
- var javacopts []string
+ var javacopts bazel.StringListAttribute //[]string
+ plugins := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
+ )
if m.properties.Javacflags != nil {
- javacopts = append(javacopts, m.properties.Javacflags...)
+ javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
}
epEnabled := m.properties.Errorprone.Enabled
- //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
- if Bool(epEnabled) {
- javacopts = append(javacopts, m.properties.Errorprone.Javacflags...)
+ epJavacflags := m.properties.Errorprone.Javacflags
+ var errorproneForceEnable bazel.BoolAttribute
+ if epEnabled == nil {
+ //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
+ } else if *epEnabled {
+ plugins.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Errorprone.Extra_check_modules)))
+ javacopts.Append(bazel.MakeStringListAttribute(epJavacflags))
+ errorproneForceEnable.Value = epEnabled
+ } else {
+ javacopts.Append(bazel.MakeStringListAttribute([]string{"-XepDisableAllChecks"}))
}
commonAttrs := &javaCommonAttributes{
Srcs: javaSrcs,
javaResourcesAttributes: m.convertJavaResourcesAttributes(ctx),
- Plugins: bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
- ),
- Javacopts: bazel.MakeStringListAttribute(javacopts),
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+ Plugins: plugins,
+ Javacopts: javacopts,
+ Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+ Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+ Errorprone_force_enable: errorproneForceEnable,
}
for axis, configToProps := range archVariantProps {
@@ -2955,7 +3010,9 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
// by protoc are included directly in the resulting JAR. Thus upstream dependencies
// that depend on a java_library with proto sources can link directly to the protobuf API,
// and so this should be a static dependency.
- staticDeps.Add(protoDepLabel)
+ if protoDepLabel != nil {
+ staticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel))
+ }
depLabels := &javaDependencyLabels{}
depLabels.Deps = deps
@@ -2970,7 +3027,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
}
}
}
- depLabels.StaticDeps.Value.Append(staticDeps)
+ depLabels.StaticDeps.Append(staticDeps)
hasKotlin := !kotlinSrcs.IsEmpty()
commonAttrs.kotlinAttributes = &kotlinAttributes{
@@ -2986,7 +3043,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
hasKotlin: hasKotlin,
}
- return commonAttrs, bp2BuildInfo
+ return commonAttrs, bp2BuildInfo, true
}
type javaLibraryAttributes struct {
@@ -3016,7 +3073,10 @@ func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties
}
func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
- commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
@@ -3063,7 +3123,10 @@ type javaBinaryHostAttributes struct {
// JavaBinaryHostBp2Build is for java_binary_host bp2build.
func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
- commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
@@ -3140,13 +3203,17 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
type javaTestHostAttributes struct {
*javaCommonAttributes
+ Srcs bazel.LabelListAttribute
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)
+ commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
@@ -3176,8 +3243,10 @@ func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) {
hasKotlin: bp2BuildInfo.hasKotlin,
}
libName := createLibraryTarget(ctx, libInfo)
- attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
+ attrs.Srcs = commonAttrs.Srcs
+ attrs.Deps = deps
+ attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
// Create the BazelTargetModule.
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
@@ -3290,7 +3359,8 @@ func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile),
ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile),
- //TODO(b/240308299) include AIDL information from Bazel
+ // TODO(b/240308299) include AIDL information from Bazel
+ // TODO: aconfig files?
})
i.maybeInstall(ctx, jarName, outputFile)
diff --git a/java/java_test.go b/java/java_test.go
index 473830464..6110e21cb 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1864,12 +1864,12 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
ctx, _ := testJavaWithFS(t, `
@@ -1897,11 +1897,11 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) {
}{
{
moduleName: "bar1",
- sourceTextFileDirs: []string{"a/foo1.txt"},
+ sourceTextFileDirs: []string{"a/current.txt"},
},
{
moduleName: "bar2",
- sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt", "api1/current.txt", "api2/current.txt"},
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt"},
},
}
for _, c := range testcases {
@@ -1918,25 +1918,25 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
provider_bp_c := `
java_api_contribution {
name: "foo3",
- api_file: "foo3.txt",
+ api_file: "current.txt",
}
`
provider_bp_d := `
java_api_contribution {
name: "foo4",
- api_file: "foo4.txt",
+ api_file: "current.txt",
}
`
ctx, _ := testJavaWithFS(t, `
@@ -1985,15 +1985,15 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
}{
{
moduleName: "bar1",
- sourceTextFileDirs: []string{"a/foo1.txt"},
+ sourceTextFileDirs: []string{"a/current.txt"},
},
{
moduleName: "bar2",
- sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
},
{
moduleName: "bar3",
- sourceTextFileDirs: []string{"c/foo3.txt", "a/foo1.txt", "b/foo2.txt", "d/foo4.txt", "api1/current.txt", "api2/current.txt"},
+ sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"},
},
}
for _, c := range testcases {
@@ -2010,13 +2010,13 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
ctx, _ := testJavaWithFS(t, `
@@ -2063,13 +2063,13 @@ func TestJavaApiLibraryLibsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
lib_bp_a := `
@@ -2138,13 +2138,13 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
lib_bp_a := `
@@ -2212,13 +2212,13 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
provider_bp_a := `
java_api_contribution {
name: "foo1",
- api_file: "foo1.txt",
+ api_file: "current.txt",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
- api_file: "foo2.txt",
+ api_file: "current.txt",
}
`
lib_bp_a := `
@@ -2351,3 +2351,22 @@ func TestJavaExcludeStaticLib(t *testing.T) {
`stable.core.platform.api.stubs`,
})
}
+
+func TestJavaLibraryWithResourcesStem(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ java_library {
+ name: "foo",
+ java_resource_dirs: ["test-jar"],
+ stem: "test",
+ }
+ `,
+ map[string][]byte{
+ "test-jar/test/resource.txt": nil,
+ })
+
+ m := ctx.ModuleForTests("foo", "android_common")
+ outputs := fmt.Sprint(m.AllOutputs())
+ if !strings.Contains(outputs, "test.jar") {
+ t.Errorf("Module output does not contain expected jar %s", "test.jar")
+ }
+}
diff --git a/java/kotlin.go b/java/kotlin.go
index f28d6c737..3637e2e71 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -42,7 +42,7 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports
` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` +
`${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` +
- `rm -rf "$srcJarDir"`,
+ `rm -rf "$srcJarDir" "$classesDir" "$headerClassesDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 1bb49962c..8494d029e 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -122,3 +122,17 @@
--warning_check RemoteViewLayout
--warning_check SupportAnnotationUsage
--warning_check UniqueConstants
+
+# TODO(b/294098365): these checks fail in AOSP, but pass downstream
+--warning_check ForegroundServiceType
+--warning_check MutableImplicitPendingIntent
+
+--warning_check ExactAlarm
+--warning_check ExpiredTargetSdkVersion
+--warning_check ForegroundServicePermission
+--warning_check ObsoleteSdkInt
+--warning_check ScheduleExactAlarm
+--warning_check StartActivityAndCollapseDeprecated
+--warning_check UnspecifiedRegisterReceiverFlag
+--warning_check WearMaterialTheme
+--warning_check WearStandaloneAppFlag
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 0d4db7ca1..ade739552 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -113,7 +113,7 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon
}
func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ if ctx.Config().DisableHiddenApiChecks() {
return
}
@@ -123,15 +123,15 @@ func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpM
}
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies on all the modules configured in the "art" boot image.
- artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
- addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
+ // Add dependencies on all the ART jars.
+ global := dexpreopt.GetGlobalConfig(ctx)
+ addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
- // Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
- // not include modules configured in the "art" boot image.
+ // Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
+ // APEXes.
addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
- // Add dependencies on all the apex jars.
+ // Add dependencies on all the updatable jars, except the ART jars.
apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
@@ -186,7 +186,6 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo
bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
- b.generateBootImageBuildActions(ctx)
b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
}
@@ -218,7 +217,8 @@ func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext)
}
func (b *platformBootclasspathModule) platformJars(ctx android.PathContext) android.ConfiguredJarList {
- return defaultBootImageConfig(ctx).modules.RemoveList(artBootImageConfig(ctx).modules)
+ global := dexpreopt.GetGlobalConfig(ctx)
+ return global.BootJars.RemoveList(global.ArtApexJars)
}
// checkPlatformModules ensures that the non-updatable modules supplied are not part of an
@@ -275,10 +275,10 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
bootDexJarByModule := extractBootDexJarsFromModules(ctx, modules)
- // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true. This is a performance
+ // Don't run any hiddenapi rules if hidden api checks are disabled. This is a performance
// optimization that can be used to reduce the incremental build time but as its name suggests it
// can be unsafe to use, e.g. when the changes affect anything that goes on the bootclasspath.
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ if ctx.Config().DisableHiddenApiChecks() {
paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
for _, path := range paths {
ctx.Build(pctx, android.BuildParams{
@@ -399,78 +399,9 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
}
-// generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext) {
- // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
- // GenerateSingletonBuildActions method as it cannot create it for itself.
- dexpreopt.GetGlobalSoongConfig(ctx)
-
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return
- }
-
- frameworkBootImageConfig := defaultBootImageConfig(ctx)
- bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
- b.generateBootImage(ctx, frameworkBootImageName)
- b.generateBootImage(ctx, mainlineBootImageName)
- dumpOatRules(ctx, frameworkBootImageConfig)
-}
-
-func (b *platformBootclasspathModule) generateBootImage(ctx android.ModuleContext, imageName string) {
- imageConfig := genBootImageConfigs(ctx)[imageName]
-
- modules := b.getModulesForImage(ctx, imageConfig)
-
- // Copy module dex jars to their predefined locations.
- bootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, modules)
- copyBootJarsToPredefinedLocations(ctx, bootDexJarsByModule, imageConfig.dexPathsByModule)
-
- // Build a profile for the image config and then use that to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
-
- // If dexpreopt of boot image jars should be skipped, generate only a profile.
- global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisablePreoptBootImages {
- return
- }
-
- // Build boot image files for the android variants.
- androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
-
- // Zip the android variant boot image files up.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
-
- // Build boot image files for the host variants. There are use directly by ART host side tests.
- buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
-}
-
// Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps.
func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) {
config := GetApexBootConfig(ctx)
apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules)
copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule)
}
-
-func (b *platformBootclasspathModule) getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig) []android.Module {
- modules := make([]android.Module, 0, imageConfig.modules.Len())
- for i := 0; i < imageConfig.modules.Len(); i++ {
- found := false
- for _, module := range b.configuredModules {
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- if name == imageConfig.modules.Jar(i) {
- modules = append(modules, module)
- found = true
- break
- }
- }
- if !found && !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf(
- "Boot image '%s' module '%s' not added as a dependency of platform_bootclasspath",
- imageConfig.name,
- imageConfig.modules.Jar(i))
- return []android.Module{}
- }
- }
- return modules
-}
diff --git a/java/plugin.go b/java/plugin.go
index 731dfda00..51272981b 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -66,7 +66,10 @@ type pluginAttributes struct {
// ConvertWithBp2build is used to convert android_app to Bazel.
func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
pluginName := p.Name()
- commonAttrs, bp2BuildInfo := p.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo, supported := p.convertLibraryAttrsBp2Build(ctx)
+ if !supported {
+ return
+ }
depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
diff --git a/java/sdk_library.go b/java/sdk_library.go
index dbb2f0247..b1ddde093 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -387,6 +387,23 @@ var (
apiScopeModuleLib,
apiScopeSystemServer,
}
+ apiLibraryAdditionalProperties = map[string]struct {
+ FullApiSurfaceStubLib string
+ AdditionalApiContribution string
+ }{
+ "legacy.i18n.module.platform.api": {
+ FullApiSurfaceStubLib: "legacy.core.platform.api.stubs",
+ AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
+ },
+ "stable.i18n.module.platform.api": {
+ FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
+ AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
+ },
+ "conscrypt.module.platform.api": {
+ FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
+ AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution",
+ },
+ }
)
var (
@@ -1513,6 +1530,29 @@ func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool {
return exists
}
+// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the
+// api surface that the module contribute to. For example, the public droidstubs and java_library
+// do not contribute to the public api surface, but contributes to the core platform api surface.
+// This method returns the full api surface stub lib that
+// the generated java_api_library should depend on.
+func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string {
+ if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
+ return val.FullApiSurfaceStubLib
+ }
+ return ""
+}
+
+// The listed modules' stubs contents do not match the corresponding txt files,
+// but require additional api contributions to generate the full stubs.
+// This method returns the name of the additional api contribution module
+// for corresponding sdk_library modules.
+func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string {
+ if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
+ return val.AdditionalApiContribution
+ }
+ return ""
+}
+
func childModuleVisibility(childVisibility []string) []string {
if childVisibility == nil {
// No child visibility set. The child will use the visibility of the sdk_library.
@@ -1778,7 +1818,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx)
}
-func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) {
props := struct {
Name *string
Visibility []string
@@ -1801,13 +1841,22 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext,
apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
scope = scope.extends
}
+ if apiScope == apiScopePublic {
+ additionalApiContribution := module.apiLibraryAdditionalApiContribution()
+ if additionalApiContribution != "" {
+ apiContributions = append(apiContributions, additionalApiContribution)
+ }
+ }
props.Api_contributions = apiContributions
props.Libs = module.properties.Libs
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
props.Libs = append(props.Libs, "stub-annotations")
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
- props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text")
+ props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName())
+ if alternativeFullApiSurfaceStub != "" {
+ props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub)
+ }
// android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
// Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
@@ -2062,9 +2111,13 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
module.createStubsLibrary(mctx, scope)
- contributesToApiSurface := module.contributesToApiSurface(mctx.Config())
+ alternativeFullApiSurfaceStubLib := ""
+ if scope == apiScopePublic {
+ alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib()
+ }
+ contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != ""
if contributesToApiSurface {
- module.createApiLibrary(mctx, scope)
+ module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib)
}
module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index c22b9809b..118f8b68c 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -1449,17 +1449,17 @@ func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
{
scope: apiScopePublic,
apiContributions: []string{"foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_stubs_current.from-text",
+ fullApiSurfaceStub: "android_stubs_current",
},
{
scope: apiScopeSystem,
apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_system_stubs_current.from-text",
+ fullApiSurfaceStub: "android_system_stubs_current",
},
{
scope: apiScopeTest,
apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_test_stubs_current.from-text",
+ fullApiSurfaceStub: "android_test_stubs_current",
},
{
scope: apiScopeModuleLib,
diff --git a/python/bp2build.go b/python/bp2build.go
index cd3f2a1a8..41e9f4974 100644
--- a/python/bp2build.go
+++ b/python/bp2build.go
@@ -73,7 +73,6 @@ func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownM
if !partitionedSrcs["proto"].IsEmpty() {
protoInfo, _ := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, partitionedSrcs["proto"])
- protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
pyProtoLibraryName := m.Name() + "_py_proto"
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
@@ -82,7 +81,7 @@ func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownM
}, android.CommonAttributes{
Name: pyProtoLibraryName,
}, &bazelPythonProtoLibraryAttributes{
- Deps: bazel.MakeSingleLabelListAttribute(protoLabel),
+ Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs),
})
attrs.Deps.Add(bazel.MakeLabelAttribute(":" + pyProtoLibraryName))
@@ -223,7 +222,8 @@ func (p *PythonTestModule) ConvertWithBp2build(ctx android.TopDownMutatorContext
props := bazel.BazelTargetModuleProperties{
// Use the native py_binary rule.
- Rule_class: "py_test",
+ Rule_class: "py_test",
+ Bzl_load_location: "//build/bazel/rules/python:py_test.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
diff --git a/python/builder.go b/python/builder.go
index 106649398..2553a7714 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -73,14 +73,14 @@ var (
precompile = pctx.AndroidStaticRule("precompilePython", blueprint.RuleParams{
Command: `LD_LIBRARY_PATH="$ldLibraryPath" ` +
- `PYTHONPATH=$stdlibZip/internal/stdlib ` +
+ `PYTHONPATH=$stdlibZip/internal/$stdlibPkg ` +
`$launcher build/soong/python/scripts/precompile_python.py $in $out`,
CommandDeps: []string{
"$stdlibZip",
"$launcher",
"build/soong/python/scripts/precompile_python.py",
},
- }, "stdlibZip", "launcher", "ldLibraryPath")
+ }, "stdlibZip", "stdlibPkg", "launcher", "ldLibraryPath")
)
func init() {
diff --git a/python/proto.go b/python/proto.go
index 400e72c99..ad2b786e2 100644
--- a/python/proto.go
+++ b/python/proto.go
@@ -19,7 +19,8 @@ import (
)
func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path {
- srcsZipFile := android.PathForModuleGen(ctx, protoFile.Base()+".srcszip")
+ // Using protoFile.Base() would generate duplicate source errors in some cases, so we use Rel() instead
+ srcsZipFile := android.PathForModuleGen(ctx, protoFile.Rel()+".srcszip")
outDir := srcsZipFile.ReplaceExtension(ctx, "tmp")
depFile := srcsZipFile.ReplaceExtension(ctx, "srcszip.d")
diff --git a/python/python.go b/python/python.go
index 8fde638b4..6c837a888 100644
--- a/python/python.go
+++ b/python/python.go
@@ -169,6 +169,7 @@ type pythonDependency interface {
getDataPathMappings() []pathMapping
getSrcsZip() android.Path
getPrecompiledSrcsZip() android.Path
+ getPkgPath() string
}
// getSrcsPathMappings gets this module's path mapping of src source path : runfiles destination
@@ -191,6 +192,11 @@ func (p *PythonLibraryModule) getPrecompiledSrcsZip() android.Path {
return p.precompiledSrcsZip
}
+// getPkgPath returns the pkg_path value
+func (p *PythonLibraryModule) getPkgPath() string {
+ return String(p.properties.Pkg_path)
+}
+
func (p *PythonLibraryModule) getBaseProperties() *BaseProperties {
return &p.properties
}
@@ -370,7 +376,20 @@ func (p *PythonLibraryModule) AddDepsOnPythonLauncherAndStdlib(ctx android.Botto
launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
case pyVersion3:
- stdLib = "py3-stdlib"
+ var prebuiltStdLib bool
+ if targetForDeps.Os.Bionic() {
+ prebuiltStdLib = false
+ } else if ctx.Config().VendorConfig("cpython3").Bool("force_build_host") {
+ prebuiltStdLib = false
+ } else {
+ prebuiltStdLib = true
+ }
+
+ if prebuiltStdLib {
+ stdLib = "py3-stdlib-prebuilt"
+ } else {
+ stdLib = "py3-stdlib"
+ }
launcherModule = "py3-launcher"
if autorun {
@@ -461,14 +480,19 @@ func (p *PythonLibraryModule) genModulePathMappings(ctx android.ModuleContext, p
destToPySrcs := make(map[string]string)
destToPyData := make(map[string]string)
+ // Disable path checks for the stdlib, as it includes a "." in the version string
+ isInternal := proptools.BoolDefault(p.properties.Is_internal, false)
+
for _, s := range expandedSrcs {
if s.Ext() != pyExt && s.Ext() != protoExt {
ctx.PropertyErrorf("srcs", "found non (.py|.proto) file: %q!", s.String())
continue
}
runfilesPath := filepath.Join(pkgPath, s.Rel())
- if err := isValidPythonPath(runfilesPath); err != nil {
- ctx.PropertyErrorf("srcs", err.Error())
+ if !isInternal {
+ if err := isValidPythonPath(runfilesPath); err != nil {
+ ctx.PropertyErrorf("srcs", err.Error())
+ }
}
if !checkForDuplicateOutputPath(ctx, destToPySrcs, runfilesPath, s.String(), p.Name(), p.Name()) {
p.srcsPathMappings = append(p.srcsPathMappings, pathMapping{dest: runfilesPath, src: s})
@@ -591,13 +615,16 @@ func (p *PythonLibraryModule) precompileSrcs(ctx android.ModuleContext) android.
// "cross compiling" for device here purely by virtue of host and device python bytecode
// being the same.
var stdLib android.Path
+ var stdLibPkg string
var launcher android.Path
- if ctx.ModuleName() == "py3-stdlib" || ctx.ModuleName() == "py2-stdlib" {
+ if proptools.BoolDefault(p.properties.Is_internal, false) {
stdLib = p.srcsZip
+ stdLibPkg = p.getPkgPath()
} else {
ctx.VisitDirectDepsWithTag(hostStdLibTag, func(module android.Module) {
if dep, ok := module.(pythonDependency); ok {
stdLib = dep.getPrecompiledSrcsZip()
+ stdLibPkg = dep.getPkgPath()
}
})
}
@@ -636,6 +663,7 @@ func (p *PythonLibraryModule) precompileSrcs(ctx android.ModuleContext) android.
Description: "Precompile the python sources of " + ctx.ModuleName(),
Args: map[string]string{
"stdlibZip": stdLib.String(),
+ "stdlibPkg": stdLibPkg,
"launcher": launcher.String(),
"ldLibraryPath": strings.Join(ldLibraryPath, ":"),
},
diff --git a/python/tests/par_test.py b/python/tests/par_test.py
index 1e03f1669..96b42ae83 100644
--- a/python/tests/par_test.py
+++ b/python/tests/par_test.py
@@ -33,6 +33,8 @@ if fileName.endswith('.pyc'):
assert_equal("os.path.basename(__file__)", fileName, "par_test.py")
archive = os.path.dirname(__file__)
+major = sys.version_info.major
+minor = sys.version_info.minor
assert_equal("__package__", __package__, "")
assert_equal("sys.argv[0]", sys.argv[0], archive)
@@ -42,10 +44,11 @@ assert_equal("sys.prefix", sys.prefix, archive)
assert_equal("__loader__.archive", __loader__.archive, archive)
assert_equal("site.ENABLE_USER_SITE", site.ENABLE_USER_SITE, None)
-assert_equal("len(sys.path)", len(sys.path), 3)
+assert_equal("len(sys.path)", len(sys.path), 4)
assert_equal("sys.path[0]", sys.path[0], archive)
-assert_equal("sys.path[1]", sys.path[1], os.path.join(archive, "internal"))
-assert_equal("sys.path[2]", sys.path[2], os.path.join(archive, "internal", "stdlib"))
+assert_equal("sys.path[1]", sys.path[1], os.path.join(archive, "internal", f"python{major}{minor}.zip"))
+assert_equal("sys.path[2]", sys.path[2], os.path.join(archive, "internal", f"python{major}.{minor}"))
+assert_equal("sys.path[3]", sys.path[3], os.path.join(archive, "internal", f"python{major}.{minor}", "lib-dynload"))
if os.getenv('ARGTEST', False):
assert_equal("len(sys.argv)", len(sys.argv), 3)
diff --git a/python/tests/py-cmd_test.py b/python/tests/py-cmd_test.py
index c7ba0ab4b..8aed78289 100644
--- a/python/tests/py-cmd_test.py
+++ b/python/tests/py-cmd_test.py
@@ -55,22 +55,22 @@ assert_equal("sys.exec_prefix", sys.exec_prefix, sys.executable)
assert_equal("sys.prefix", sys.prefix, sys.executable)
assert_equal("site.ENABLE_USER_SITE", site.ENABLE_USER_SITE, None)
-if sys.version_info[0] == 2:
+major = sys.version_info.major
+minor = sys.version_info.minor
+
+if major == 2:
assert_equal("len(sys.path)", len(sys.path), 4)
assert_equal("sys.path[0]", sys.path[0], os.path.abspath(os.path.dirname(__file__)))
assert_equal("sys.path[1]", sys.path[1], "/extra")
assert_equal("sys.path[2]", sys.path[2], os.path.join(sys.executable, "internal"))
assert_equal("sys.path[3]", sys.path[3], os.path.join(sys.executable, "internal", "stdlib"))
else:
- assert_equal("len(sys.path)", len(sys.path), 8)
+ assert_equal("len(sys.path)", len(sys.path), 5)
assert_equal("sys.path[0]", sys.path[0], os.path.abspath(os.path.dirname(__file__)))
assert_equal("sys.path[1]", sys.path[1], "/extra")
- assert_equal("sys.path[2]", sys.path[2], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + str(sys.version_info[1]) + '.zip'))
- assert_equal("sys.path[3]", sys.path[3], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1]), '..'))
- assert_equal("sys.path[4]", sys.path[4], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1])))
- assert_equal("sys.path[5]", sys.path[5], os.path.join(sys.executable, 'lib', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1]), 'lib-dynload'))
- assert_equal("sys.path[6]", sys.path[6], os.path.join(sys.executable, "internal"))
- assert_equal("sys.path[7]", sys.path[7], os.path.join(sys.executable, "internal", "stdlib"))
+ assert_equal("sys.path[2]", sys.path[2], os.path.join(sys.executable, 'internal', 'python' + str(sys.version_info[0]) + str(sys.version_info[1]) + '.zip'))
+ assert_equal("sys.path[3]", sys.path[3], os.path.join(sys.executable, 'internal', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1])))
+ assert_equal("sys.path[4]", sys.path[4], os.path.join(sys.executable, 'internal', 'python' + str(sys.version_info[0]) + '.' + str(sys.version_info[1]), 'lib-dynload'))
if failed:
sys.exit(1)
diff --git a/rust/binary.go b/rust/binary.go
index 2de92c17f..e6f153996 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -158,9 +158,6 @@ func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoD
// Binaries default to dylib dependencies for device, rlib for host.
if binary.preferRlib() {
return rlibAutoDep
- } else if mod, ok := ctx.Module().(*Module); ok && mod.InVendor() {
- // Vendor Rust binaries should prefer rlibs.
- return rlibAutoDep
} else if ctx.Device() {
return dylibAutoDep
} else {
@@ -171,8 +168,6 @@ func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoD
func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
if binary.preferRlib() {
return RlibLinkage
- } else if ctx.RustModule().InVendor() {
- return RlibLinkage
}
return binary.baseCompiler.stdLinkage(ctx)
}
diff --git a/rust/binary_test.go b/rust/binary_test.go
index dd4f99314..fc4c56037 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -21,6 +21,27 @@ import (
"android/soong/android"
)
+// Test that rustlibs default linkage is always rlib for host binaries.
+func TestBinaryHostLinkage(t *testing.T) {
+ ctx := testRust(t, `
+ rust_binary_host {
+ name: "fizz-buzz",
+ srcs: ["foo.rs"],
+ rustlibs: ["libfoo"],
+ }
+ rust_library {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ host_supported: true,
+ }
+ `)
+ fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ if !android.InList("libfoo.rlib-std", fizzBuzz.Properties.AndroidMkRlibs) {
+ t.Errorf("rustlibs dependency libfoo should be an rlib dep for host binaries")
+ }
+}
+
// Test that rustlibs default linkage is correct for binaries.
func TestBinaryLinkage(t *testing.T) {
ctx := testRust(t, `
@@ -54,6 +75,12 @@ func TestBinaryLinkage(t *testing.T) {
if !android.InList("libfoo", fizzBuzzDevice.Properties.AndroidMkDylibs) {
t.Errorf("rustlibs dependency libfoo should be an dylib dep for device modules")
}
+
+ rlibLinkDevice := ctx.ModuleForTests("rlib_linked", "android_arm64_armv8-a").Module().(*Module)
+
+ if !android.InList("libfoo.rlib-std", rlibLinkDevice.Properties.AndroidMkRlibs) {
+ t.Errorf("rustlibs dependency libfoo should be an rlib dep for device modules when prefer_rlib is set")
+ }
}
// Test that prefer_rlib links in libstd statically as well as rustlibs.
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 96645b075..407f2754f 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@ var (
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r487747c"
+ bindgenClangVersion = "clang-r498229"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
@@ -61,15 +61,18 @@ var (
"${cc_config.ClangBase}/${bindgenHostPrebuiltTag}/${bindgenClangVersion}/${bindgenClangLibdir}")
//TODO(ivanlozano) Switch this to RuleBuilder
+ //
+ //TODO Pass the flag files directly to bindgen e.g. with @file when it supports that.
+ //See https://github.com/rust-lang/rust-bindgen/issues/2508.
bindgen = pctx.AndroidStaticRule("bindgen",
blueprint.RuleParams{
Command: "CLANG_PATH=$bindgenClang LIBCLANG_PATH=$bindgenLibClang RUSTFMT=${config.RustBin}/rustfmt " +
- "$cmd $flags $in -o $out -- -MD -MF $out.d $cflags",
+ "$cmd $flags $$(cat $flagfiles) $in -o $out -- -MD -MF $out.d $cflags",
CommandDeps: []string{"$cmd"},
Deps: blueprint.DepsGCC,
Depfile: "$out.d",
},
- "cmd", "flags", "cflags")
+ "cmd", "flags", "flagfiles", "cflags")
)
func init() {
@@ -90,6 +93,9 @@ type BindgenProperties struct {
// list of bindgen-specific flags and options
Bindgen_flags []string `android:"arch_variant"`
+ // list of files containing extra bindgen flags
+ Bindgen_flag_files []string `android:"arch_variant"`
+
// module name of a custom binary/script which should be used instead of the 'bindgen' binary. This custom
// binary must expect arguments in a similar fashion to bindgen, e.g.
//
@@ -216,6 +222,14 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
bindgenFlags := defaultBindgenFlags
bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
+ // cat reads from stdin if its command line is empty,
+ // so we pass in /dev/null if there are no other flag files
+ bindgenFlagFiles := []string{"/dev/null"}
+ for _, flagFile := range b.Properties.Bindgen_flag_files {
+ bindgenFlagFiles = append(bindgenFlagFiles, android.PathForModuleSrc(ctx, flagFile).String())
+ implicits = append(implicits, android.PathForModuleSrc(ctx, flagFile))
+ }
+
wrapperFile := android.OptionalPathForModuleSrc(ctx, b.Properties.Wrapper_src)
if !wrapperFile.Valid() {
ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source")
@@ -247,7 +261,7 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
var cmd, cmdDesc string
if b.Properties.Custom_bindgen != "" {
- cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(*Module).HostToolPath().String()
+ cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(android.HostToolProvider).HostToolPath().String()
cmdDesc = b.Properties.Custom_bindgen
} else {
cmd = "$bindgenCmd"
@@ -261,9 +275,10 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
Input: wrapperFile.Path(),
Implicits: implicits,
Args: map[string]string{
- "cmd": cmd,
- "flags": strings.Join(bindgenFlags, " "),
- "cflags": strings.Join(cflags, " "),
+ "cmd": cmd,
+ "flags": strings.Join(bindgenFlags, " "),
+ "flagfiles": strings.Join(bindgenFlagFiles, " "),
+ "cflags": strings.Join(cflags, " "),
},
})
@@ -279,7 +294,7 @@ func (b *bindgenDecorator) SourceProviderProps() []interface{} {
// rust_bindgen generates Rust FFI bindings to C libraries using bindgen given a wrapper header as the primary input.
// Bindgen has a number of flags to control the generated source, and additional flags can be passed to clang to ensure
// the header and generated source is appropriately handled. It is recommended to add it as a dependency in the
-// rlibs, dylibs or rustlibs property. It may also be added in the srcs property for external crates, using the ":"
+// rlibs or rustlibs property. It may also be added in the srcs property for external crates, using the ":"
// prefix.
func RustBindgenFactory() android.Module {
module, _ := NewRustBindgen(android.HostAndDeviceSupported)
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index af04cfc89..12cdb3cb4 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -168,3 +168,28 @@ func TestBindgenDisallowedFlags(t *testing.T) {
}
`)
}
+
+func TestBindgenFlagFile(t *testing.T) {
+ ctx := testRust(t, `
+ rust_bindgen {
+ name: "libbindgen",
+ wrapper_src: "src/any.h",
+ crate_name: "bindgen",
+ stem: "libbindgen",
+ source_stem: "bindings",
+ bindgen_flag_files: [
+ "flag_file.txt",
+ ],
+ }
+ `)
+ libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+
+ if !strings.Contains(libbindgen.Args["flagfiles"], "/dev/null") {
+ t.Errorf("missing /dev/null in rust_bindgen rule: flags %#v", libbindgen.Args["flagfiles"])
+ }
+ if !strings.Contains(libbindgen.Args["flagfiles"], "flag_file.txt") {
+ t.Errorf("missing bindgen flags file in rust_bindgen rule: flags %#v", libbindgen.Args["flagfiles"])
+ }
+ // TODO: The best we can do right now is check $flagfiles. Once bindgen.go switches to RuleBuilder,
+ // we may be able to check libbinder.RuleParams.Command to see if it contains $(cat /dev/null flag_file.txt)
+}
diff --git a/rust/builder.go b/rust/builder.go
index c31bc88d1..b1f049d15 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -45,9 +45,9 @@ var (
"rustcFlags", "libFlags", "envVars")
rustLink = pctx.AndroidStaticRule("rustLink",
blueprint.RuleParams{
- Command: "${config.RustLinker} -o $out ${crtBegin} ${config.RustLinkerArgs} @$in ${linkFlags} ${crtEnd}",
+ Command: "${config.RustLinker} -o $out ${crtBegin} ${earlyLinkFlags} @$in ${linkFlags} ${crtEnd}",
},
- "linkFlags", "crtBegin", "crtEnd")
+ "earlyLinkFlags", "linkFlags", "crtBegin", "crtEnd")
_ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
rustdoc = pctx.AndroidStaticRule("rustdoc",
@@ -228,11 +228,26 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
pkgVersion := ctx.RustModule().compiler.CargoPkgVersion()
if pkgVersion != "" {
envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
+
+ // Ensure the version is in the form of "x.y.z" (approximately semver compliant).
+ //
+ // For our purposes, we don't care to enforce that these are integers since they may
+ // include other characters at times (e.g. sometimes the patch version is more than an integer).
+ if strings.Count(pkgVersion, ".") == 2 {
+ var semver_parts = strings.Split(pkgVersion, ".")
+ envVars = append(envVars, "CARGO_PKG_VERSION_MAJOR="+semver_parts[0])
+ envVars = append(envVars, "CARGO_PKG_VERSION_MINOR="+semver_parts[1])
+ envVars = append(envVars, "CARGO_PKG_VERSION_PATCH="+semver_parts[2])
+ }
}
}
envVars = append(envVars, "AR=${cc_config.ClangBin}/llvm-ar")
+ if ctx.Darwin() {
+ envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
+ }
+
return envVars
}
@@ -243,6 +258,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
var implicits, linkImplicits, linkOrderOnly android.Paths
var output buildOutput
var rustcFlags, linkFlags []string
+ var earlyLinkFlags string
output.outputFile = outputFile
crateName := ctx.RustModule().CrateName()
@@ -281,6 +297,10 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
}
// Collect linker flags
+ if !ctx.Darwin() {
+ earlyLinkFlags = "-Wl,--as-needed"
+ }
+
linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
linkFlags = append(linkFlags, flags.LinkFlags...)
@@ -380,9 +400,10 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
Implicits: linkImplicits,
OrderOnly: linkOrderOnly,
Args: map[string]string{
- "linkFlags": strings.Join(linkFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
+ "earlyLinkFlags": earlyLinkFlags,
+ "linkFlags": strings.Join(linkFlags, " "),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
},
})
}
diff --git a/rust/compiler.go b/rust/compiler.go
index 06ae12f79..e6a7a9356 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -91,10 +91,8 @@ type BaseCompilerProperties struct {
// list of rust rlib crate dependencies
Rlibs []string `android:"arch_variant"`
- // list of rust dylib crate dependencies
- Dylibs []string `android:"arch_variant"`
-
- // list of rust automatic crate dependencies
+ // list of rust automatic crate dependencies.
+ // Rustlibs linkage is rlib for host targets and dylib for device targets.
Rustlibs []string `android:"arch_variant"`
// list of rust proc_macro crate dependencies
@@ -320,6 +318,15 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag
flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
}
+ if !ctx.toolchain().Bionic() && ctx.Os() != android.LinuxMusl && !ctx.Windows() {
+ // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
+ // builds. This is irrelevant for the Windows target as these are Posix specific.
+ flags.LinkFlags = append(flags.LinkFlags,
+ "-ldl",
+ "-lpthread",
+ "-lm",
+ )
+ }
return flags
}
@@ -359,7 +366,6 @@ func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath {
func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
- deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index ae783e8dd..08ac2ef7d 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -26,11 +26,18 @@ var (
Arm64LinkFlags = []string{}
Arm64ArchVariantRustFlags = map[string][]string{
- "armv8-a": []string{},
- "armv8-a-branchprot": []string{},
- "armv8-2a": []string{},
- "armv8-2a-dotprod": []string{},
- "armv9-a": []string{},
+ "armv8-a": []string{},
+ "armv8-a-branchprot": []string{
+ // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
+ "-Z branch-protection=bti,pac-ret",
+ },
+ "armv8-2a": []string{},
+ "armv8-2a-dotprod": []string{},
+ "armv9-a": []string{
+ // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
}
)
diff --git a/rust/config/global.go b/rust/config/global.go
index d844a252b..86eb2d1cb 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@ import (
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.70.0"
+ RustDefaultVersion = "1.71.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -102,7 +102,6 @@ func init() {
pctx.ImportAs("cc_config", "android/soong/cc/config")
pctx.StaticVariable("RustLinker", "${cc_config.ClangBin}/clang++")
- pctx.StaticVariable("RustLinkerArgs", "-Wl,--as-needed")
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
diff --git a/rust/fuzz.go b/rust/fuzz.go
index c2b940525..235f51779 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -25,6 +25,7 @@ import (
func init() {
android.RegisterModuleType("rust_fuzz", RustFuzzFactory)
+ android.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
}
type fuzzDecorator struct {
@@ -43,6 +44,11 @@ func RustFuzzFactory() android.Module {
return module.Init()
}
+func RustFuzzHostFactory() android.Module {
+ module, _ := NewRustFuzz(android.HostSupported)
+ return module.Init()
+}
+
func NewRustFuzz(hod android.HostOrDeviceSupported) (*Module, *fuzzDecorator) {
module, binary := NewRustBinary(hod)
fuzz := &fuzzDecorator{
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index 0aecf617e..ee28c6d3a 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -34,6 +34,10 @@ func TestRustFuzz(t *testing.T) {
srcs: ["foo.rs"],
rustlibs: ["libtest_fuzzing"],
}
+ rust_fuzz_host {
+ name: "host_fuzzer",
+ srcs: ["foo.rs"],
+ }
`)
// Check that appropriate dependencies are added and that the rustlib linkage is correct.
@@ -50,7 +54,13 @@ func TestRustFuzz(t *testing.T) {
if !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") {
t.Errorf("rust_fuzz module does not contain the expected flags (sancov-module, cfg fuzzing).")
+ }
+ // Check that host modules support fuzzing.
+ host_fuzzer := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
+ if !strings.Contains(host_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") ||
+ !strings.Contains(host_fuzzer.Args["rustcFlags"], "--cfg fuzzing") {
+ t.Errorf("rust_fuzz_host module does not contain the expected flags (sancov-module, cfg fuzzing).")
}
// Check that dependencies have 'fuzzer' variants produced for them as well.
diff --git a/rust/image.go b/rust/image.go
index 50bf02a4a..c2e250cf0 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -220,9 +220,6 @@ func (mod *Module) SetImageVariation(ctx android.BaseModuleContext, variant stri
}
func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
- // Rust does not support installing to the product image yet.
- vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
-
if Bool(mod.VendorProperties.Double_loadable) {
mctx.PropertyErrorf("double_loadable",
"Rust modules do not yet support double loading")
@@ -232,16 +229,6 @@ func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
mctx.PropertyErrorf("vendor_ramdisk_available", "cannot be set for rust_ffi or rust_ffi_shared modules.")
}
}
- if vendorSpecific {
- if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
- mctx.PropertyErrorf("vendor", "Vendor-only dylibs are not yet supported, use rust_library_rlib.")
- }
- }
- if mctx.ProductSpecific() {
- if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
- mctx.PropertyErrorf("product", "Product-only dylibs are not yet supported, use rust_library_rlib.")
- }
- }
cc.MutateImage(mctx, mod)
diff --git a/rust/library.go b/rust/library.go
index 331763a50..419fcfca2 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -21,7 +21,6 @@ import (
"android/soong/android"
"android/soong/cc"
- "android/soong/snapshot"
)
var (
@@ -236,10 +235,7 @@ func (library *libraryDecorator) setSource() {
}
func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
- if ctx.Module().(*Module).InVendor() {
- // Vendor modules should statically link libstd.
- return rlibAutoDep
- } else if library.preferRlib() {
+ if library.preferRlib() {
return rlibAutoDep
} else if library.rlib() || library.static() {
return rlibAutoDep
@@ -251,10 +247,7 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut
}
func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
- if ctx.RustModule().InVendor() {
- // Vendor modules should statically link libstd.
- return RlibLinkage
- } else if library.static() || library.MutatedProperties.VariantIsStaticStd {
+ if library.static() || library.MutatedProperties.VariantIsStaticStd {
return RlibLinkage
} else if library.baseCompiler.preferRlib() {
return RlibLinkage
@@ -473,7 +466,15 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
}
if library.shared() {
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ if ctx.Darwin() {
+ flags.LinkFlags = append(
+ flags.LinkFlags,
+ "-dynamic_lib",
+ "-install_name @rpath/"+library.sharedLibFilename(ctx),
+ )
+ } else {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ }
}
return flags
@@ -693,24 +694,6 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) {
v.(*Module).Disable()
}
- variation := v.(*Module).ModuleBase.ImageVariation().Variation
- if strings.HasPrefix(variation, cc.VendorVariationPrefix) {
- // TODO(b/204303985)
- // Disable vendor dylibs until they are supported
- v.(*Module).Disable()
- }
-
- if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
- m.HasVendorVariant() &&
- !snapshot.IsVendorProprietaryModule(mctx) &&
- strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
-
- // cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
- // produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for
- // non-vendor proprietary modules.
- v.(*Module).Disable()
- }
-
case "source":
v.(*Module).compiler.(libraryInterface).setSource()
// The source variant does not produce any library.
@@ -747,10 +730,9 @@ func LibstdMutator(mctx android.BottomUpMutatorContext) {
dylib := modules[1].(*Module)
rlib.compiler.(libraryInterface).setRlibStd()
dylib.compiler.(libraryInterface).setDylibStd()
- if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation ||
- strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) {
+ if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
// TODO(b/165791368)
- // Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib
+ // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib
// variants are properly supported.
dylib.Disable()
}
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 0cf6e8c97..a14ebeaab 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -243,7 +243,7 @@ func (proto *protobufDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) D
// rust_protobuf generates protobuf rust code from the provided proto file. This uses the protoc-gen-rust plugin for
// protoc. Additional flags to the protoc command can be passed via the proto_flags property. This module type will
-// create library variants that can be used as a crate dependency by adding it to the rlibs, dylibs, and rustlibs
+// create library variants that can be used as a crate dependency by adding it to the rlibs and rustlibs
// properties of other modules.
func RustProtobufFactory() android.Module {
module, _ := NewRustProtobuf(android.HostAndDeviceSupported)
diff --git a/rust/rust.go b/rust/rust.go
index e524c9fb6..fc8db8655 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -43,6 +43,7 @@ func init() {
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
})
+ pctx.Import("android/soong/android")
pctx.Import("android/soong/rust/config")
pctx.ImportAs("cc_config", "android/soong/cc/config")
android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory)
@@ -91,6 +92,8 @@ type BaseProperties struct {
// Used by vendor snapshot to record dependencies from snapshot modules.
SnapshotSharedLibs []string `blueprint:"mutated"`
SnapshotStaticLibs []string `blueprint:"mutated"`
+ SnapshotRlibs []string `blueprint:"mutated"`
+ SnapshotDylibs []string `blueprint:"mutated"`
// Make this module available when building for ramdisk.
// On device without a dedicated recovery partition, the module is only
@@ -258,6 +261,15 @@ func (mod *Module) Dylib() bool {
return false
}
+func (mod *Module) RlibStd() bool {
+ if mod.compiler != nil {
+ if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() {
+ return library.rlibStd()
+ }
+ }
+ panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName()))
+}
+
func (mod *Module) Rlib() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
@@ -601,6 +613,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
&cc.RustBindgenClangProperties{},
&ClippyProperties{},
&SanitizeProperties{},
+ &fuzz.FuzzProperties{},
)
android.InitDefaultsModule(module)
@@ -1212,6 +1225,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
if _, exists := skipModuleList[depName]; exists {
return
}
+
+ if depTag == android.DarwinUniversalVariantTag {
+ return
+ }
+
if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
//Handle Rust Modules
makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
@@ -1225,6 +1243,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
directDylibDeps = append(directDylibDeps, rustDep)
mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
+ mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
+
case rlibDepTag:
rlib, ok := rustDep.compiler.(libraryInterface)
@@ -1234,6 +1254,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
directRlibDeps = append(directRlibDeps, rustDep)
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
+ mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
+
case procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, rustDep)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
@@ -1290,12 +1312,17 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
}
}
linkObject := ccDep.OutputFile()
- linkPath := linkPathFromFilePath(linkObject.Path())
-
if !linkObject.Valid() {
- ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+ } else {
+ ctx.AddMissingDependencies([]string{depName})
+ }
+ return
}
+ linkPath := linkPathFromFilePath(linkObject.Path())
+
exportDep := false
switch {
case cc.IsStaticDepTag(depTag):
@@ -1340,6 +1367,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// Re-get linkObject as ChooseStubOrImpl actually tells us which
// object (either from stub or non-stub) to use.
linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
+ if !linkObject.Valid() {
+ if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
+ } else {
+ ctx.AddMissingDependencies([]string{depName})
+ }
+ return
+ }
linkPath = linkPathFromFilePath(linkObject.Path())
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
@@ -1518,10 +1553,10 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
// dylibs
- actx.AddVariationDependencies(
- append(commonDepVariations, []blueprint.Variation{
- {Mutator: "rust_libraries", Variation: dylibVariation}}...),
- dylibDepTag, deps.Dylibs...)
+ dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation})
+ for _, lib := range deps.Dylibs {
+ addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
+ }
// rustlibs
if deps.Rustlibs != nil && !mod.compiler.Disabled() {
@@ -1536,8 +1571,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
// otherwise select the rlib variant.
autoDepVariations := append(commonDepVariations,
blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
- if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) {
- actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
+
+ replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
+
+ if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) {
+ addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag)
} else {
// If there's no dylib dependency available, try to add the rlib dependency instead.
addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
@@ -1549,16 +1587,14 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if deps.Stdlibs != nil {
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
for _, lib := range deps.Stdlibs {
- depTag := rlibDepTag
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
-
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
- depTag, lib)
+ rlibDepTag, lib)
}
} else {
- actx.AddVariationDependencies(
- append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}),
- dylibDepTag, deps.Stdlibs...)
+ for _, lib := range deps.Stdlibs {
+ addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag)
+ }
}
}
@@ -1636,6 +1672,11 @@ func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Mod
actx.AddVariationDependencies(variations, rlibDepTag, lib)
}
+func addDylibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation, depTag dependencyTag) {
+ lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Dylibs)
+ actx.AddVariationDependencies(variations, depTag, lib)
+}
+
func BeginMutator(ctx android.BottomUpMutatorContext) {
if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
mod.beginMutator(ctx)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 64f90b6e0..704bfe785 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -79,14 +79,18 @@ func testRustVndk(t *testing.T, bp string) *android.TestContext {
}
const (
- sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared"
- rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
- sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared"
- rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std"
- binaryCoreVariant = "android_arm64_armv8-a"
- binaryVendorVariant = "android_vendor.29_arm64_armv8-a"
- binaryProductVariant = "android_product.29_arm64_armv8-a"
- binaryRecoveryVariant = "android_recovery_arm64_armv8-a"
+ sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared"
+ rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+ rlibDylibStdVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+ dylibVendorVariant = "android_vendor.29_arm64_armv8-a_dylib"
+ sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared"
+ rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_dylib-std"
+ rlibRlibStdRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std"
+ dylibRecoveryVariant = "android_recovery_arm64_armv8-a_dylib"
+ binaryCoreVariant = "android_arm64_armv8-a"
+ binaryVendorVariant = "android_vendor.29_arm64_armv8-a"
+ binaryProductVariant = "android_product.29_arm64_armv8-a"
+ binaryRecoveryVariant = "android_recovery_arm64_armv8-a"
)
func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
@@ -228,11 +232,6 @@ func TestDepsTracking(t *testing.T) {
srcs: ["foo.rs"],
crate_name: "shared",
}
- rust_library_host_dylib {
- name: "libdylib",
- srcs: ["foo.rs"],
- crate_name: "dylib",
- }
rust_library_host_rlib {
name: "librlib",
srcs: ["foo.rs"],
@@ -248,7 +247,6 @@ func TestDepsTracking(t *testing.T) {
}
rust_binary_host {
name: "fizz-buzz",
- dylibs: ["libdylib"],
rlibs: ["librlib"],
proc_macros: ["libpm"],
static_libs: ["libstatic"],
@@ -261,10 +259,6 @@ func TestDepsTracking(t *testing.T) {
rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustLink")
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
- if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
- t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)")
- }
-
if !android.InList("librlib.rlib-std", module.Properties.AndroidMkRlibs) {
t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)")
}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 0f7cf6e5f..cc19e6e61 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -209,8 +209,8 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) {
}
// TODO:(b/178369775)
- // For now sanitizing is only supported on devices
- if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
+ // For now sanitizing is only supported on non-windows targets
+ if ctx.Os() != android.Windows && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
sanitize.Properties.SanitizerEnabled = true
}
}
@@ -223,12 +223,22 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (
if !sanitize.Properties.SanitizerEnabled {
return flags, deps
}
+
if Bool(sanitize.Properties.Sanitize.Fuzzer) {
flags.RustFlags = append(flags.RustFlags, fuzzerFlags...)
- } else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+ }
+
+ if Bool(sanitize.Properties.Sanitize.Hwaddress) {
flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
- } else if Bool(sanitize.Properties.Sanitize.Address) {
+ }
+
+ if Bool(sanitize.Properties.Sanitize.Address) {
flags.RustFlags = append(flags.RustFlags, asanFlags...)
+ if ctx.Host() {
+ // -nodefaultlibs (provided with libc++) prevents the driver from linking
+ // libraries needed with -fsanitize=address. http://b/18650275 (WAI)
+ flags.LinkFlags = append(flags.LinkFlags, []string{"-Wl,--no-as-needed"}...)
+ }
}
return flags, deps
}
@@ -267,14 +277,19 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) {
var depTag blueprint.DependencyTag
var deps []string
- if mod.IsSanitizerEnabled(cc.Asan) ||
- (mod.IsSanitizerEnabled(cc.Fuzzer) && (mctx.Arch().ArchType != android.Arm64 || !mctx.Os().Bionic())) {
- variations = append(variations,
- blueprint.Variation{Mutator: "link", Variation: "shared"})
- depTag = cc.SharedDepTag()
- deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
- } else if mod.IsSanitizerEnabled(cc.Hwasan) ||
- (mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64 && mctx.Os().Bionic()) {
+ if mod.IsSanitizerEnabled(cc.Asan) {
+ if mod.Host() {
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "static"})
+ depTag = cc.StaticDepTag(false)
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan.static")}
+ } else {
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "shared"})
+ depTag = cc.SharedDepTag()
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
+ }
+ } else if mod.IsSanitizerEnabled(cc.Hwasan) {
// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
if binary, ok := mod.compiler.(binaryInterface); ok {
if binary.staticallyLinked() {
@@ -388,7 +403,8 @@ func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.Andro
}
func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
- if mod.Host() {
+ // Sanitizers are not supported on Windows targets.
+ if mod.Os() == android.Windows {
return false
}
switch t {
@@ -414,7 +430,8 @@ func (mod *Module) IsSanitizerEnabled(t cc.SanitizerType) bool {
}
func (mod *Module) IsSanitizerExplicitlyDisabled(t cc.SanitizerType) bool {
- if mod.Host() {
+ // Sanitizers are not supported on Windows targets.
+ if mod.Os() == android.Windows {
return true
}
diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go
index 2f79cc5c3..32d391629 100644
--- a/rust/snapshot_prebuilt.go
+++ b/rust/snapshot_prebuilt.go
@@ -21,10 +21,6 @@ import (
"github.com/google/blueprint/proptools"
)
-const (
- snapshotRlibSuffix = "_rlib."
-)
-
type snapshotLibraryDecorator struct {
cc.BaseSnapshotDecorator
*libraryDecorator
@@ -44,6 +40,8 @@ func init() {
func registerRustSnapshotModules(ctx android.RegistrationContext) {
cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
"vendor_snapshot_rlib", VendorSnapshotRlibFactory)
+ cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
+ "vendor_snapshot_dylib", VendorSnapshotDylibFactory)
cc.RecoverySnapshotImageSingleton.RegisterAdditionalModule(ctx,
"recovery_snapshot_rlib", RecoverySnapshotRlibFactory)
}
@@ -77,12 +75,11 @@ func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags,
variant = cc.SnapshotSharedSuffix
} else if library.rlib() {
variant = cc.SnapshotRlibSuffix
+ } else if library.dylib() {
+ variant = cc.SnapshotDylibSuffix
}
- if !library.dylib() {
- // TODO(184042776): Remove this check when dylibs are supported in snapshots.
- library.SetSnapshotAndroidMkSuffix(ctx, variant)
- }
+ library.SetSnapshotAndroidMkSuffix(ctx, variant)
if !library.MatchesWithDevice(ctx.DeviceConfig()) {
return buildOutput{}
@@ -107,6 +104,17 @@ func VendorSnapshotRlibFactory() android.Module {
return module.Init()
}
+// vendor_snapshot_dylib is a special prebuilt dylib library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_dylib
+// overrides the vendor variant of the rust dylib library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotDylibFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotDylibSuffix)
+ prebuilt.libraryDecorator.BuildOnlyDylib()
+ prebuilt.libraryDecorator.setNoStdlibs()
+ return module.Init()
+}
+
func RecoverySnapshotRlibFactory() android.Module {
module, prebuilt := snapshotLibraryFactory(cc.RecoverySnapshotImageSingleton, cc.SnapshotRlibSuffix)
prebuilt.libraryDecorator.BuildOnlyRlib()
diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go
index 8dabd9bf6..55c85e668 100644
--- a/rust/snapshot_utils.go
+++ b/rust/snapshot_utils.go
@@ -42,8 +42,7 @@ func (mod *Module) ExcludeFromRecoverySnapshot() bool {
func (mod *Module) IsSnapshotLibrary() bool {
if lib, ok := mod.compiler.(libraryInterface); ok {
- // Rust-native dylibs are not snapshot supported yet. Only snapshot the rlib-std variants of rlibs.
- return lib.shared() || lib.static() || (lib.rlib() && lib.rlibStd())
+ return lib.shared() || lib.static() || lib.rlib() || lib.dylib()
}
return false
}
@@ -61,6 +60,14 @@ func (mod *Module) SnapshotStaticLibs() []string {
return mod.Properties.SnapshotStaticLibs
}
+func (mod *Module) SnapshotRlibs() []string {
+ return mod.Properties.SnapshotRlibs
+}
+
+func (mod *Module) SnapshotDylibs() []string {
+ return mod.Properties.SnapshotDylibs
+}
+
func (mod *Module) Symlinks() []string {
// TODO update this to return the list of symlinks when Rust supports defining symlinks
return nil
diff --git a/rust/testing.go b/rust/testing.go
index 7f3056954..3fe751e17 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -182,6 +182,7 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
ctx.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
ctx.RegisterModuleType("rust_fuzz", RustFuzzFactory)
+ ctx.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 2e7a33027..387d17043 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -48,15 +48,13 @@ func TestVendorSnapshotCapture(t *testing.T) {
crate_name: "rustvendor_available",
srcs: ["lib.rs"],
vendor_available: true,
- include_dirs: ["rust_headers/"],
}
- rust_library_rlib {
+ rust_library {
name: "librustvendor",
crate_name: "rustvendor",
srcs: ["lib.rs"],
vendor: true,
- include_dirs: ["rust_headers/"],
}
rust_binary {
@@ -116,7 +114,7 @@ func TestVendorSnapshotCapture(t *testing.T) {
filepath.Join(staticDir, "libffivendor.a.json"))
// For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant)
@@ -125,6 +123,25 @@ func TestVendorSnapshotCapture(t *testing.T) {
jsonFiles = append(jsonFiles,
filepath.Join(rlibDir, "librustvendor.rlib.json"))
+ // For rlib libraries, all rlib-std variants vendor:true and vendor_available modules (including VNDK) are captured.
+ rlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibStdVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib-std.rlib", rlibDir, rlibStdVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librustvendor.rlib.json"))
+
+ // For dylib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.dylib.so", dylibDir, dylibVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
+ jsonFiles = append(jsonFiles,
+ filepath.Join(dylibDir, "librustvendor.dylib.so.json"))
+
// For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
@@ -209,21 +226,32 @@ func TestVendorSnapshotDirected(t *testing.T) {
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
+ rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+ dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
// Included modules
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib-std.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json"))
// Excluded modules. Modules not included in the directed vendor snapshot
// are still include as fake modules.
cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.dylib.so", dylibDir, dylibVariant)
cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib-std.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_exclude.dylib.so.json"))
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.so.json"))
}
@@ -274,7 +302,7 @@ func TestVendorSnapshotExclude(t *testing.T) {
vendor_available: true,
}
- rust_library_rlib {
+ rust_library {
name: "librust_exclude",
crate_name: "rust_exclude",
srcs: ["exclude.rs"],
@@ -308,6 +336,14 @@ func TestVendorSnapshotExclude(t *testing.T) {
cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant)
cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibDylibStdVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibDylibStdVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibDylibStdVendorVariant)
+
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, dylibVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, dylibVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, dylibVendorVariant)
+
// Verify the content of the vendor snapshot.
snapshotDir := "vendor-snapshot"
@@ -327,14 +363,22 @@ func TestVendorSnapshotExclude(t *testing.T) {
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
+ rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+ dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
// Included modules
cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib-std.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.dylib.so", dylibDir, dylibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librust_include.dylib.so.json"))
// Excluded modules
cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
@@ -345,6 +389,12 @@ func TestVendorSnapshotExclude(t *testing.T) {
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json"))
cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.rlib-std.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.dylib.so", dylibDir, dylibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_exclude.dylib.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.dylib.so", dylibDir, dylibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_available_exclude.dylib.so.json"))
}
// Verify that each json file for an included module has a rule.
@@ -525,7 +575,7 @@ func TestVendorSnapshotUse(t *testing.T) {
srcs: ["client.rs"],
}
- rust_library_rlib {
+ rust_library {
name: "libclient_rust",
crate_name: "client_rust",
vendor: true,
@@ -572,6 +622,11 @@ func TestVendorSnapshotUse(t *testing.T) {
rlibs: [
"libstd",
"librust_vendor_available",
+ "librust_vendor_available.rlib-std"
+ ],
+ dylibs: [
+ "libstd",
+ "librust_vendor_available",
],
binaries: [
"bin",
@@ -600,6 +655,10 @@ func TestVendorSnapshotUse(t *testing.T) {
"libstd",
"librust_vendor_available",
],
+ dylibs: [
+ "libstd",
+ "librust_vendor_available",
+ ],
binaries: [
"bin32",
],
@@ -679,6 +738,52 @@ func TestVendorSnapshotUse(t *testing.T) {
},
}
+ vendor_snapshot_rlib {
+ name: "librust_vendor_available.rlib-std",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "librust_vendor_available.rlib-std.rlib",
+ },
+ arm: {
+ src: "librust_vendor_available.rlib-std.rlib",
+ },
+ },
+ }
+
+ vendor_snapshot_dylib {
+ name: "libstd",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ sysroot: true,
+ arch: {
+ arm64: {
+ src: "libstd.dylib.so",
+ },
+ arm: {
+ src: "libstd.dylib.so",
+ },
+ },
+ }
+
+ vendor_snapshot_dylib {
+ name: "librust_vendor_available",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "librust_vendor_available.dylib.so",
+ },
+ arm: {
+ src: "librust_vendor_available.dylib.so",
+ },
+ },
+ }
+
vendor_snapshot_object {
name: "crtend_android",
version: "30",
@@ -921,6 +1026,9 @@ func TestVendorSnapshotUse(t *testing.T) {
"vendor/liblog.so": nil,
"vendor/libstd.rlib": nil,
"vendor/librust_vendor_available.rlib": nil,
+ "vendor/librust_vendor_available.rlib-std.rlib": nil,
+ "vendor/libstd.dylib.so": nil,
+ "vendor/librust_vendor_available.dylib.so": nil,
"vendor/crtbegin_so.o": nil,
"vendor/crtend_so.o": nil,
"vendor/libclang_rt.builtins-aarch64-android.a": nil,
@@ -931,7 +1039,9 @@ func TestVendorSnapshotUse(t *testing.T) {
}
sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
- rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
+ rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_dylib-std"
+ rlibRlibStdVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
+ dylibVariant := "android_vendor.30_arm64_armv8-a_dylib"
staticVariant := "android_vendor.30_arm64_armv8-a_static"
binaryVariant := "android_vendor.30_arm64_armv8-a"
@@ -963,14 +1073,9 @@ func TestVendorSnapshotUse(t *testing.T) {
t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
}
- libclientAndroidMkRlibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
- }
-
libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs
- if len(libclientAndroidMkDylibs) > 0 {
- t.Errorf("wanted libclient libclientAndroidMkDylibs [], got %q", libclientAndroidMkDylibs)
+ if g, w := libclientAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient libclientAndroidMkDylibs %q, got %q", w, libclientAndroidMkDylibs)
}
libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
@@ -979,22 +1084,39 @@ func TestVendorSnapshotUse(t *testing.T) {
}
libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
+ if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
+ }
+
+ libclientRlibStdRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibRlibStdVariant).Module().(*Module).Properties.AndroidMkRlibs
+ if g, w := libclientRlibStdRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
+ }
+
+ libclientRustDylibAndroidMkDylibs := ctx.ModuleForTests("libclient_rust", dylibVariant).Module().(*Module).Properties.AndroidMkDylibs
+ if g, w := libclientRustDylibAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted dylib libclient libclientRustDylibAndroidMkDylibs %q, got %q", w, g)
}
// rust vendor snapshot must have ".vendor" suffix in AndroidMk
librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module()
librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
- expectedRustVendorSnapshotName := "librust_vendor_available.vendor.rlib-std"
+ expectedRustVendorSnapshotName := "librust_vendor_available.vendor"
if librustVendorSnapshotMkName != expectedRustVendorSnapshotName {
t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName)
}
+ librustVendorAvailableDylibSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_dylib.30.arm64", dylibVariant).Module()
+ librustVendorSnapshotDylibMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableDylibSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
+ expectedRustVendorDylibSnapshotName := "librust_vendor_available.vendor"
+ if librustVendorSnapshotDylibMkName != expectedRustVendorDylibSnapshotName {
+ t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotDylibMkName, expectedRustVendorDylibSnapshotName)
+ }
+
rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module()
- rustVendorBinMkRlibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_RLIB_LIBRARIES"][0]
- if rustVendorBinMkRlibName != expectedRustVendorSnapshotName {
- t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkRlibName, expectedRustVendorSnapshotName)
+ rustVendorBinMkDylibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_DYLIB_LIBRARIES"][0]
+ if rustVendorBinMkDylibName != expectedRustVendorSnapshotName {
+ t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName)
}
binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"]
@@ -1051,18 +1173,18 @@ func TestRecoverySnapshotCapture(t *testing.T) {
crate_name: "recovery_available",
}
- rust_library_rlib {
- name: "librecovery_rlib",
+ rust_library {
+ name: "librecovery_rustlib",
recovery: true,
srcs: ["foo.rs"],
- crate_name: "recovery_rlib",
+ crate_name: "recovery_rustlib",
}
- rust_library_rlib {
- name: "librecovery_available_rlib",
+ rust_library {
+ name: "librecovery_available_rustlib",
recovery_available: true,
srcs: ["foo.rs"],
- crate_name: "recovery_available_rlib",
+ crate_name: "recovery_available_rustlib",
}
rust_binary {
@@ -1113,13 +1235,29 @@ func TestRecoverySnapshotCapture(t *testing.T) {
filepath.Join(staticDir, "librecovery_available.a.json"))
// For rlib libraries, all recovery:true and recovery_available modules are captured.
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librecovery_rlib.rlib.json"),
- filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json"))
+ filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"),
+ filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
+
+ rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"),
+ filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
+
+ // For dylib libraries, all recovery:true and recovery_available modules are captured.
+ dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"),
+ filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
// For binary executables, all recovery:true and recovery_available modules are captured.
if archType == "arm64" {
@@ -1169,25 +1307,25 @@ func TestRecoverySnapshotExclude(t *testing.T) {
exclude_from_recovery_snapshot: true,
crate_name: "available_exclude",
}
- rust_library_rlib {
- name: "libinclude_rlib",
+ rust_library {
+ name: "libinclude_rustlib",
srcs: ["src/include.rs"],
recovery_available: true,
- crate_name: "include_rlib",
+ crate_name: "include_rustlib",
}
- rust_library_rlib {
- name: "libexclude_rlib",
+ rust_library {
+ name: "libexclude_rustlib",
srcs: ["src/exclude.rs"],
recovery: true,
exclude_from_recovery_snapshot: true,
- crate_name: "exclude_rlib",
+ crate_name: "exclude_rustlib",
}
- rust_library_rlib {
- name: "libavailable_exclude_rlib",
+ rust_library {
+ name: "libavailable_exclude_rustlib",
srcs: ["src/exclude.rs"],
recovery_available: true,
exclude_from_recovery_snapshot: true,
- crate_name: "available_exclude_rlib",
+ crate_name: "available_exclude_rustlib",
}
`
@@ -1198,11 +1336,11 @@ func TestRecoverySnapshotExclude(t *testing.T) {
recovery: true,
crate_name: "recovery",
}
- rust_library_rlib {
- name: "librecovery_rlib",
+ rust_library {
+ name: "librecovery_rustlib",
srcs: ["recovery.rs"],
recovery: true,
- crate_name: "recovery_rlib",
+ crate_name: "recovery_rustlib",
}
`
@@ -1220,14 +1358,25 @@ func TestRecoverySnapshotExclude(t *testing.T) {
cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, sharedRecoveryVariant)
cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, sharedRecoveryVariant)
cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, sharedRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rlib", false, rlibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rlib", true, rlibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rlib", true, rlibRecoveryVariant)
+
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
+
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRlibStdRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRlibStdRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
+
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, dylibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, dylibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, dylibRecoveryVariant)
// A recovery module is excluded, but by its path not the exclude_from_recovery_snapshot property
// ('device/' and 'vendor/' are default excluded). See snapshot/recovery_snapshot.go for more detail.
cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, sharedRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rlib", false, rlibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRlibStdRecoveryVariant)
+ cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, dylibRecoveryVariant)
// Verify the content of the recovery snapshot.
@@ -1246,15 +1395,21 @@ func TestRecoverySnapshotExclude(t *testing.T) {
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
+ rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
// Included modules
+
cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rlib", "libinclude_rlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rlib.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib", rlibDir, rlibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib-std.rlib.json"))
// Excluded modules
cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
@@ -1263,12 +1418,27 @@ func TestRecoverySnapshotExclude(t *testing.T) {
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rlib", "libexclude_rlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rlib.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rlib", "libavailable_exclude_rlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rlib.rlib.json"))
+
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib", rlibDir, rlibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib", rlibDir, rlibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib.json"))
+
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib-std.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib-std.rlib.json"))
+
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.dylib.so", dylibDir, dylibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.dylib.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.dylib.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.dylib.so", dylibDir, dylibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.dylib.so.json"))
}
// Verify that each json file for an included module has a rule.
@@ -1302,15 +1472,15 @@ func TestRecoverySnapshotDirected(t *testing.T) {
srcs: ["foo.rs"],
}
- rust_library_rlib {
- name: "librecovery_rlib",
+ rust_library {
+ name: "librecovery_rustlib",
recovery: true,
crate_name: "recovery",
srcs: ["foo.rs"],
}
- rust_library_rlib {
- name: "librecovery_available_rlib",
+ rust_library {
+ name: "librecovery_available_rustlib",
recovery_available: true,
crate_name: "recovery_available",
srcs: ["foo.rs"],
@@ -1335,7 +1505,7 @@ func TestRecoverySnapshotDirected(t *testing.T) {
ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "current", "29", "current")
ctx.Config().TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery"] = true
- ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rlib"] = true
+ ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rustlib"] = true
ctx.Config().TestProductVariables.DirectedRecoverySnapshot = true
// Check recovery snapshot output.
@@ -1353,15 +1523,22 @@ func TestRecoverySnapshotDirected(t *testing.T) {
archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
+ rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
+ dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+ dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
// Included modules
cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"))
// TODO: When Rust supports the "prefer" property for prebuilts, perform this check.
/*
@@ -1374,8 +1551,12 @@ func TestRecoverySnapshotDirected(t *testing.T) {
// are still included as fake modules.
cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json"))
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
}
// Verify that each json file for an included module has a rule.
diff --git a/scripts/mkcratersp.py b/scripts/mkcratersp.py
index 86b4aa3fb..6ef01ebcc 100755
--- a/scripts/mkcratersp.py
+++ b/scripts/mkcratersp.py
@@ -48,6 +48,8 @@ for i, arg in enumerate(sys.argv):
linkdirs.append(sys.argv[i+1])
if arg.startswith('-l') or arg == '-shared':
libs.append(arg)
+ if os.getenv('ANDROID_RUST_DARWIN') and (arg == '-dylib' or arg == '-dynamiclib'):
+ libs.append(arg)
if arg.startswith('-Wl,--version-script='):
version_script = arg[21:]
if arg[0] == '-':
@@ -64,9 +66,13 @@ create_archive(f'{out}.whole.a', objects, [])
create_archive(f'{out}.a', [], temp_archives)
with open(out, 'w') as f:
- print(f'-Wl,--whole-archive', file=f)
- print(f'{out}.whole.a', file=f)
- print(f'-Wl,--no-whole-archive', file=f)
+ if os.getenv("ANDROID_RUST_DARWIN"):
+ print(f'-force_load', file=f)
+ print(f'{out}.whole.a', file=f)
+ else:
+ print(f'-Wl,--whole-archive', file=f)
+ print(f'{out}.whole.a', file=f)
+ print(f'-Wl,--no-whole-archive', file=f)
print(f'{out}.a', file=f)
for a in archives:
print(a, file=f)
diff --git a/scripts/unpack-prebuilt-apex.sh b/scripts/unpack-prebuilt-apex.sh
index 2a20e452a..18f4da236 100755
--- a/scripts/unpack-prebuilt-apex.sh
+++ b/scripts/unpack-prebuilt-apex.sh
@@ -17,7 +17,7 @@ set -eu
# limitations under the License.
# Tool to unpack an apex file and verify that the required files were extracted.
-if [ $# -lt 7 ]; then
+if [ $# -lt 6 ]; then
echo "usage: $0 <deapaxer_path> <debugfs_path> <fsck.erofs_path> <apex file> <output_dir> <required_files>+" >&2
exit 1
fi
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index d830968f6..ee1b5dbf6 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -86,27 +86,27 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(
- "com.android.art", "mybootclasspathfragment", java.ApexBootJarFragmentsForPlatformBootclasspath),
+ "com.android.art", "art-bootclasspath-fragment", java.ApexBootJarFragmentsForPlatformBootclasspath),
java.PrepareForBootImageConfigTest,
java.PrepareApexBootJarConfigsAndModules,
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
- bootclasspath_fragments: ["mybootclasspathfragment"],
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
apex {
name: "com.android.art",
key: "com.android.art.key",
bootclasspath_fragments: [
- "mybootclasspathfragment",
+ "art-bootclasspath-fragment",
],
updatable: false,
}
bootclasspath_fragment {
- name: "mybootclasspathfragment",
+ name: "art-bootclasspath-fragment",
image_name: "art",
contents: ["core1", "core2"],
apex_available: ["com.android.art"],
@@ -142,18 +142,18 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
).RunTest(t)
// A preparer to update the test fixture used when processing an unpackage snapshot.
- preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "mybootclasspathfragment")
+ preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "art-bootclasspath-fragment")
// Check that source on its own configures the bootImageConfig correctly.
- java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic")
- java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
prebuilt_bootclasspath_fragment {
- name: "mybootclasspathfragment",
+ name: "art-bootclasspath-fragment",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["com.android.art"],
@@ -189,12 +189,12 @@ java_import {
}
`),
checkAllCopyRules(`
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
+.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar
`),
@@ -213,24 +213,24 @@ java_import {
java.ApexBootJarDexJarPaths...,
)...,
)
- java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/mybootclasspathfragment/android_common_com.android.art/meta_lic")
- java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
}),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
// Check the behavior of the snapshot when the source is preferred.
snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
- java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic")
- java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
}),
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
// Check the behavior of the snapshot when it is preferred.
snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) {
- java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/prebuilt_mybootclasspathfragment/android_common_com.android.art/meta_lic")
- java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic")
}),
)
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index c018671ee..680494f3a 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -160,7 +160,7 @@ java_import {
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/myjavalib.jar
+.intermediates/myjavalib/linux_glibc_common/javac-header/myjavalib.jar -> java/myjavalib.jar
aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
`),
)
@@ -206,7 +206,7 @@ java_import {
`),
checkAllCopyRules(`
.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/android/myjavalib.jar
-.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/linux_glibc/myjavalib.jar
+.intermediates/myjavalib/linux_glibc_common/javac-header/myjavalib.jar -> java/linux_glibc/myjavalib.jar
`),
)
}
@@ -799,7 +799,7 @@ java_system_modules_import {
libs: ["mysdk_system-module"],
}
`),
- checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac/system-module.jar -> java/system-module.jar"),
+ checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac-header/system-module.jar -> java/system-module.jar"),
)
}
@@ -879,7 +879,7 @@ java_import {
}
`),
checkAllCopyRules(`
-.intermediates/hostjavalib/linux_glibc_common/javac/hostjavalib.jar -> java/hostjavalib.jar
+.intermediates/hostjavalib/linux_glibc_common/javac-header/hostjavalib.jar -> java/hostjavalib.jar
.intermediates/androidjavalib/android_common/turbine-combined/androidjavalib.jar -> java/androidjavalib.jar
.intermediates/myjavalib/android_common/javac/myjavalib.jar -> java/android/myjavalib.jar
.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/linux_glibc/myjavalib.jar
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
index 42095075c..0224bcf93 100644
--- a/starlark_fmt/format.go
+++ b/starlark_fmt/format.go
@@ -16,6 +16,7 @@ package starlark_fmt
import (
"fmt"
+ "reflect"
"sort"
"strconv"
"strings"
@@ -33,6 +34,72 @@ func Indention(level int) string {
return strings.Repeat(" ", level*indent)
}
+func PrintAny(value any, indentLevel int) string {
+ return printAnyRecursive(reflect.ValueOf(value), indentLevel)
+}
+
+func printAnyRecursive(value reflect.Value, indentLevel int) string {
+ switch value.Type().Kind() {
+ case reflect.String:
+ val := value.String()
+ if strings.Contains(val, "\"") || strings.Contains(val, "\n") {
+ return `'''` + val + `'''`
+ }
+ return `"` + val + `"`
+ case reflect.Bool:
+ if value.Bool() {
+ return "True"
+ } else {
+ return "False"
+ }
+ case reflect.Int:
+ return fmt.Sprintf("%d", value.Int())
+ case reflect.Slice:
+ if value.Len() == 0 {
+ return "[]"
+ } else if value.Len() == 1 {
+ return "[" + printAnyRecursive(value.Index(0), indentLevel) + "]"
+ }
+ list := make([]string, 0, value.Len()+2)
+ list = append(list, "[")
+ innerIndent := Indention(indentLevel + 1)
+ for i := 0; i < value.Len(); i++ {
+ list = append(list, innerIndent+printAnyRecursive(value.Index(i), indentLevel+1)+`,`)
+ }
+ list = append(list, Indention(indentLevel)+"]")
+ return strings.Join(list, "\n")
+ case reflect.Map:
+ if value.Len() == 0 {
+ return "{}"
+ }
+ items := make([]string, 0, value.Len())
+ for _, key := range value.MapKeys() {
+ items = append(items, fmt.Sprintf(`%s%s: %s,`, Indention(indentLevel+1), printAnyRecursive(key, indentLevel+1), printAnyRecursive(value.MapIndex(key), indentLevel+1)))
+ }
+ sort.Strings(items)
+ return fmt.Sprintf(`{
+%s
+%s}`, strings.Join(items, "\n"), Indention(indentLevel))
+ case reflect.Struct:
+ if value.NumField() == 0 {
+ return "struct()"
+ }
+ items := make([]string, 0, value.NumField()+2)
+ items = append(items, "struct(")
+ for i := 0; i < value.NumField(); i++ {
+ if value.Type().Field(i).Anonymous {
+ panic("anonymous fields aren't supported")
+ }
+ name := value.Type().Field(i).Name
+ items = append(items, fmt.Sprintf(`%s%s = %s,`, Indention(indentLevel+1), name, printAnyRecursive(value.Field(i), indentLevel+1)))
+ }
+ items = append(items, Indention(indentLevel)+")")
+ return strings.Join(items, "\n")
+ default:
+ panic("Unhandled kind: " + value.Kind().String())
+ }
+}
+
// PrintBool returns a Starlark compatible bool string.
func PrintBool(item bool) string {
if item {
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
index 1b5443782..b2434712b 100644
--- a/starlark_import/unmarshal.go
+++ b/starlark_import/unmarshal.go
@@ -25,13 +25,18 @@ import (
)
func Unmarshal[T any](value starlark.Value) (T, error) {
- var zero T
- x, err := UnmarshalReflect(value, reflect.TypeOf(zero))
+ x, err := UnmarshalReflect(value, reflect.TypeOf((*T)(nil)).Elem())
return x.Interface().(T), err
}
func UnmarshalReflect(value starlark.Value, ty reflect.Type) (reflect.Value, error) {
+ if ty == reflect.TypeOf((*starlark.Value)(nil)).Elem() {
+ return reflect.ValueOf(value), nil
+ }
zero := reflect.Zero(ty)
+ if value == nil {
+ panic("nil value")
+ }
var result reflect.Value
if ty.Kind() == reflect.Interface {
var err error
@@ -286,3 +291,14 @@ func typeOfStarlarkValue(value starlark.Value) (reflect.Type, error) {
return nil, fmt.Errorf("unimplemented starlark type: %s", value.Type())
}
}
+
+// UnmarshalNoneable is like Unmarshal, but it will accept None as the top level (but not nested)
+// starlark value. If the value is None, a nil pointer will be returned, otherwise a pointer
+// to the result of Unmarshal will be returned.
+func UnmarshalNoneable[T any](value starlark.Value) (*T, error) {
+ if _, ok := value.(starlark.NoneType); ok {
+ return nil, nil
+ }
+ ret, err := Unmarshal[T](value)
+ return &ret, err
+}
diff --git a/starlark_import/unmarshal_test.go b/starlark_import/unmarshal_test.go
index ee7a9e340..bc0ea4c49 100644
--- a/starlark_import/unmarshal_test.go
+++ b/starlark_import/unmarshal_test.go
@@ -30,7 +30,7 @@ func createStarlarkValue(t *testing.T, code string) starlark.Value {
return result["x"]
}
-func TestUnmarshallConcreteType(t *testing.T) {
+func TestUnmarshalConcreteType(t *testing.T) {
x, err := Unmarshal[string](createStarlarkValue(t, `"foo"`))
if err != nil {
t.Error(err)
@@ -41,7 +41,7 @@ func TestUnmarshallConcreteType(t *testing.T) {
}
}
-func TestUnmarshallConcreteTypeWithInterfaces(t *testing.T) {
+func TestUnmarshalConcreteTypeWithInterfaces(t *testing.T) {
x, err := Unmarshal[map[string]map[string]interface{}](createStarlarkValue(t,
`{"foo": {"foo2": "foo3"}, "bar": {"bar2": ["bar3"]}}`))
if err != nil {
@@ -57,7 +57,22 @@ func TestUnmarshallConcreteTypeWithInterfaces(t *testing.T) {
}
}
-func TestUnmarshall(t *testing.T) {
+func TestUnmarshalToStarlarkValue(t *testing.T) {
+ x, err := Unmarshal[map[string]starlark.Value](createStarlarkValue(t,
+ `{"foo": "Hi", "bar": None}`))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if x["foo"].(starlark.String).GoString() != "Hi" {
+ t.Errorf("Expected \"Hi\", got: %q", x["foo"].(starlark.String).GoString())
+ }
+ if x["bar"].Type() != "NoneType" {
+ t.Errorf("Expected \"NoneType\", got: %q", x["bar"].Type())
+ }
+}
+
+func TestUnmarshal(t *testing.T) {
testCases := []struct {
input string
expected interface{}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0edbb7c37..a2c0fb731 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -24,6 +24,7 @@ import (
"sync"
"android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -410,7 +411,7 @@ type ccLibraryProperties struct {
Apex_available []string
Min_sdk_version *string
Bazel_module struct {
- Bp2build_available *bool
+ Label *string
}
}
@@ -428,6 +429,9 @@ type javaLibraryProperties struct {
SyspropPublicStub string
Apex_available []string
Min_sdk_version *string
+ Bazel_module struct {
+ Bp2build_available *bool
+ }
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -473,6 +477,14 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
}
+ var label *string
+ if b, ok := ctx.Module().(android.Bazelable); ok && b.ShouldConvertWithBp2build(ctx) {
+ // TODO: b/295566168 - this will need to change once build files are checked in to account for
+ // checked in modules in mixed builds
+ label = proptools.StringPtr(
+ fmt.Sprintf("//%s:%s", ctx.ModuleDir(), m.CcImplementationModuleName()))
+ }
+
// Generate a C++ implementation library.
// cc_library can receive *.sysprop files as their srcs, generating sources itself.
ccProps := ccLibraryProperties{}
@@ -492,11 +504,7 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
- // A Bazel macro handles this, so this module does not need to be handled
- // in bp2build
- // TODO(b/237810289) perhaps do something different here so that we aren't
- // also disabling these modules in mixed builds
- ccProps.Bazel_module.Bp2build_available = proptools.BoolPtr(false)
+ ccProps.Bazel_module.Label = label
ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal"
@@ -541,6 +549,11 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
SyspropPublicStub: publicStub,
Apex_available: m.ApexProperties.Apex_available,
Min_sdk_version: m.properties.Java.Min_sdk_version,
+ Bazel_module: struct {
+ Bp2build_available *bool
+ }{
+ Bp2build_available: proptools.BoolPtr(false),
+ },
})
if publicStub != "" {
@@ -558,6 +571,11 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
Sdk_version: proptools.StringPtr("core_current"),
Libs: []string{javaSyspropStub},
Stem: proptools.StringPtr(m.BaseModuleName()),
+ Bazel_module: struct {
+ Bp2build_available *bool
+ }{
+ Bp2build_available: proptools.BoolPtr(false),
+ },
})
}
diff --git a/tests/genrule_sandbox_test.py b/tests/genrule_sandbox_test.py
index a9f0c9b50..0cebc2aa0 100755
--- a/tests/genrule_sandbox_test.py
+++ b/tests/genrule_sandbox_test.py
@@ -17,34 +17,37 @@
import argparse
import collections
import json
-import os.path
+import os
import subprocess
+import sys
import tempfile
-SRC_ROOT_DIR = os.path.abspath(__file__ + "/../../../..")
+def get_top() -> str:
+ path = '.'
+ while not os.path.isfile(os.path.join(path, 'build/soong/tests/genrule_sandbox_test.py')):
+ if os.path.abspath(path) == '/':
+ sys.exit('Could not find android source tree root.')
+ path = os.path.join(path, '..')
+ return os.path.abspath(path)
-
-def _module_graph_path(out_dir):
- return os.path.join(SRC_ROOT_DIR, out_dir, "soong", "module-actions.json")
-
-
-def _build_with_soong(targets, target_product, out_dir, extra_env={}):
+def _build_with_soong(targets, target_product, *, keep_going = False, extra_env={}):
env = {
+ **os.environ,
"TARGET_PRODUCT": target_product,
"TARGET_BUILD_VARIANT": "userdebug",
}
- env.update(os.environ)
env.update(extra_env)
args = [
"build/soong/soong_ui.bash",
"--make-mode",
"--skip-soong-tests",
]
+ if keep_going:
+ args.append("-k")
args.extend(targets)
try:
- out = subprocess.check_output(
+ subprocess.check_output(
args,
- cwd=SRC_ROOT_DIR,
env=env,
)
except subprocess.CalledProcessError as e:
@@ -55,14 +58,13 @@ def _build_with_soong(targets, target_product, out_dir, extra_env={}):
def _find_outputs_for_modules(modules, out_dir, target_product):
- module_path = os.path.join(
- SRC_ROOT_DIR, out_dir, "soong", "module-actions.json"
- )
+ module_path = os.path.join(out_dir, "soong", "module-actions.json")
if not os.path.exists(module_path):
- _build_with_soong(["json-module-graph"], target_product, out_dir)
+ _build_with_soong(["json-module-graph"], target_product)
- action_graph = json.load(open(_module_graph_path(out_dir)))
+ with open(module_path) as f:
+ action_graph = json.load(f)
module_to_outs = collections.defaultdict(set)
for mod in action_graph:
@@ -74,50 +76,15 @@ def _find_outputs_for_modules(modules, out_dir, target_product):
return module_to_outs
-def _store_outputs_to_tmp(output_files):
- try:
- tempdir = tempfile.TemporaryDirectory()
- for f in output_files:
- out = subprocess.check_output(
- ["cp", "--parents", f, tempdir.name],
- cwd=SRC_ROOT_DIR,
- )
- return tempdir
- except subprocess.CalledProcessError as e:
- print(e)
- print(e.stdout)
- print(e.stderr)
-
-
-def _diff_outs(file1, file2, show_diff):
- output = None
- base_args = ["diff"]
- if not show_diff:
- base_args.append("--brief")
- try:
- args = base_args + [file1, file2]
- output = subprocess.check_output(
- args,
- cwd=SRC_ROOT_DIR,
- )
- except subprocess.CalledProcessError as e:
- if e.returncode == 1:
- if show_diff:
- return output
- return True
- return None
-
-
-def _compare_outputs(module_to_outs, tempdir, show_diff):
+def _compare_outputs(module_to_outs, tempdir) -> dict[str, list[str]]:
different_modules = collections.defaultdict(list)
for module, outs in module_to_outs.items():
for out in outs:
- output = None
- diff = _diff_outs(os.path.join(tempdir.name, out), out, show_diff)
- if diff:
- different_modules[module].append(diff)
+ try:
+ subprocess.check_output(["diff", os.path.join(tempdir, out), out])
+ except subprocess.CalledProcessError as e:
+ different_modules[module].append(e.stdout)
- tempdir.cleanup()
return different_modules
@@ -138,53 +105,56 @@ def main():
"--show-diff",
"-d",
action="store_true",
- required=False,
help="whether to display differing files",
)
parser.add_argument(
"--output-paths-only",
"-o",
action="store_true",
- required=False,
help="Whether to only return the output paths per module",
)
args = parser.parse_args()
+ os.chdir(get_top())
out_dir = os.environ.get("OUT_DIR", "out")
- target_product = args.target_product
- modules = set(args.modules)
- module_to_outs = _find_outputs_for_modules(modules, out_dir, target_product)
+ print("finding output files for the modules...")
+ module_to_outs = _find_outputs_for_modules(set(args.modules), out_dir, args.target_product)
if not module_to_outs:
- print("No outputs found")
- exit(1)
+ sys.exit("No outputs found")
if args.output_paths_only:
for m, o in module_to_outs.items():
print(f"{m} outputs: {o}")
- exit(0)
-
- all_outs = set()
- for outs in module_to_outs.values():
- all_outs.update(outs)
- print("build without sandboxing")
- _build_with_soong(list(all_outs), target_product, out_dir)
- tempdir = _store_outputs_to_tmp(all_outs)
- print("build with sandboxing")
- _build_with_soong(
- list(all_outs),
- target_product,
- out_dir,
- extra_env={"GENRULE_SANDBOXING": "true"},
- )
- diffs = _compare_outputs(module_to_outs, tempdir, args.show_diff)
- if len(diffs) == 0:
- print("All modules are correct")
- elif args.show_diff:
- for m, d in diffs.items():
- print(f"Module {m} has diffs {d}")
- else:
- print(f"Modules {list(diffs.keys())} have diffs")
+ sys.exit(0)
+
+ all_outs = list(set.union(*module_to_outs.values()))
+
+ print("building without sandboxing...")
+ _build_with_soong(all_outs, args.target_product)
+ with tempfile.TemporaryDirectory() as tempdir:
+ for f in all_outs:
+ subprocess.check_call(["cp", "--parents", f, tempdir])
+
+ print("building with sandboxing...")
+ _build_with_soong(
+ all_outs,
+ args.target_product,
+ # We've verified these build without sandboxing already, so do the sandboxing build
+ # with keep_going = True so that we can find all the genrules that fail to build with
+ # sandboxing.
+ keep_going = True,
+ extra_env={"GENRULE_SANDBOXING": "true"},
+ )
+
+ diffs = _compare_outputs(module_to_outs, tempdir)
+ if len(diffs) == 0:
+ print("All modules are correct")
+ elif args.show_diff:
+ for m, d in diffs.items():
+ print(f"Module {m} has diffs {d}")
+ else:
+ print(f"Modules {list(diffs.keys())} have diffs")
if __name__ == "__main__":
diff --git a/tests/lib.sh b/tests/lib.sh
index 4aaf272a7..f3db76f8b 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -52,6 +52,10 @@ function copy_directory {
cp -R "$REAL_TOP/$dir" "$MOCK_TOP/$parent"
}
+function delete_directory {
+ rm -rf "$MOCK_TOP/$1"
+}
+
function symlink_file {
local file="$1"
@@ -138,6 +142,9 @@ function create_mock_bazel {
copy_directory build/bazel
copy_directory build/bazel_common_rules
+ # This requires pulling more tools into the mock top to build partitions
+ delete_directory build/bazel/examples/partitions
+
symlink_directory packages/modules/common/build
symlink_directory prebuilts/bazel
symlink_directory prebuilts/clang
@@ -147,6 +154,8 @@ function create_mock_bazel {
symlink_directory external/bazelbuild-rules_go
symlink_directory external/bazelbuild-rules_license
symlink_directory external/bazelbuild-kotlin-rules
+ symlink_directory external/bazelbuild-rules_python
+ symlink_directory external/bazelbuild-rules_java
symlink_file WORKSPACE
symlink_file BUILD
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 43a9f0fed..6b9ff8b93 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -10,7 +10,7 @@ TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/persistent_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
"$TOP/build/soong/tests/stale_metrics_files_test.sh"
-"$TOP/build/bazel/ci/rbc_regression_test.sh" aosp_arm64-userdebug
+"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug
# The following tests build against the full source tree and don't rely on the
# mock client.
@@ -22,7 +22,5 @@ TEST_BAZEL=true extra_build_params=--bazel-mode-staging "$TOP/build/soong/tests/
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_arm" "armv7-a"
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_cf_arm64_phone" "armv8-a" "cortex-a53"
-"$TOP/build/soong/tests/sbom_test.sh"
-
"$TOP/build/bazel/ci/b_test.sh"
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 19987f204..9801a8e4f 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -85,32 +85,32 @@ function test_sbom_aosp_cf_x86_64_phone {
lz4=$out_dir/host/linux-x86/bin/lz4
declare -A diff_excludes
- diff_excludes[vendor]="-I /vendor/lib64/libkeystore2_crypto.so"
+ diff_excludes[vendor]="\
+ -I /vendor/lib64/libkeystore2_crypto.so \
+ -I /vendor/lib64/libvsock_utils.so"
diff_excludes[system]="\
- -I /bin \
- -I /bugreports \
- -I /cache \
- -I /d \
- -I /etc \
- -I /init \
- -I /odm/app \
- -I /odm/bin \
- -I /odm_dlkm/etc \
- -I /odm/etc \
- -I /odm/firmware \
- -I /odm/framework \
- -I /odm/lib \
- -I /odm/lib64 \
- -I /odm/overlay \
- -I /odm/priv-app \
- -I /odm/usr \
- -I /sdcard \
+ -I /system/bin/assemble_cvd \
+ -I /system/bin/console_forwarder \
+ -I /system/bin/kernel_log_monitor \
+ -I /system/bin/logcat_receiver \
+ -I /system/bin/mkenvimage_slim \
+ -I /system/bin/run_cvd \
+ -I /system/bin/simg2img \
+ -I /system/bin/log_tee \
-I /system/lib64/android.hardware.confirmationui@1.0.so \
-I /system/lib64/android.hardware.confirmationui-V1-ndk.so \
-I /system/lib64/android.hardware.keymaster@4.1.so \
-I /system/lib64/android.hardware.security.rkp-V3-ndk.so \
-I /system/lib64/android.hardware.security.sharedsecret-V1-ndk.so \
-I /system/lib64/android.security.compat-ndk.so \
+ -I /system/lib64/libcuttlefish_allocd_utils.so \
+ -I /system/lib64/libcuttlefish_device_config_proto.so \
+ -I /system/lib64/libcuttlefish_device_config.so \
+ -I /system/lib64/libcuttlefish_fs.so \
+ -I /system/lib64/libcuttlefish_kernel_log_monitor_utils.so \
+ -I /system/lib64/libcuttlefish_utils.so \
+ -I /system/lib64/libfruit.so \
+ -I /system/lib64/libgflags.so \
-I /system/lib64/libkeymaster4_1support.so \
-I /system/lib64/libkeymaster4support.so \
-I /system/lib64/libkeymint.so \
@@ -124,8 +124,7 @@ function test_sbom_aosp_cf_x86_64_phone {
-I /system/lib64/vndk-sp-29 \
-I /system/lib/vndk-29 \
-I /system/lib/vndk-sp-29 \
- -I /system/usr/icu \
- -I /vendor_dlkm/etc"
+ -I /system/usr/icu"
# Example output of dump.erofs is as below, and the data used in the test start
# at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
@@ -219,8 +218,104 @@ function test_sbom_aosp_cf_x86_64_phone {
diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
done
+ verify_package_verification_code "$product_out/sbom.spdx"
+
+ # Teardown
+ cleanup "${out_dir}"
+}
+
+function verify_package_verification_code {
+ local sbom_file="$1"; shift
+
+ local -a file_checksums
+ local package_product_found=
+ while read -r line;
+ do
+ if grep -q 'PackageVerificationCode' <<<"$line"
+ then
+ package_product_found=true
+ fi
+ if [ -n "$package_product_found" ]
+ then
+ if grep -q 'FileChecksum' <<< "$line"
+ then
+ checksum=$(echo $line | sed 's/^.*: //')
+ file_checksums+=("$checksum")
+ fi
+ fi
+ done <<< "$(grep -E 'PackageVerificationCode|FileChecksum' $sbom_file)"
+ IFS=$'\n' file_checksums=($(sort <<<"${file_checksums[*]}")); unset IFS
+ IFS= expected_package_verification_code=$(printf "${file_checksums[*]}" | sha1sum | sed 's/[[:space:]]*-//'); unset IFS
+
+ actual_package_verification_code=$(grep PackageVerificationCode $sbom_file | sed 's/PackageVerificationCode: //g')
+ if [ $actual_package_verification_code = $expected_package_verification_code ]
+ then
+ echo "Package verification code is correct."
+ else
+ echo "Unexpected package verification code."
+ exit 1
+ fi
+}
+
+function test_sbom_unbundled_apex {
+ # Setup
+ out_dir="$(setup)"
+
+ # run_soong to build com.android.adbd.apex
+ run_soong "module_arm64" "${out_dir}" "sbom deapexer" "com.android.adbd"
+
+ deapexer=${out_dir}/host/linux-x86/bin/deapexer
+ debugfs=${out_dir}/host/linux-x86/bin/debugfs_static
+ apex_file=${out_dir}/target/product/module_arm64/system/apex/com.android.adbd.apex
+ echo "============ Diffing files in $apex_file and SBOM"
+ set +e
+ # deapexer prints the list of all files and directories
+ # sed extracts the file/directory names
+ # grep removes directories
+ # sed removes leading ./ in file names
+ diff -I /system/apex/com.android.adbd.apex -I apex_manifest.pb \
+ <($deapexer --debugfs_path=$debugfs list --extents ${apex_file} | sed -E 's#(.*) \[.*\]$#\1#' | grep -v "/$" | sed -E 's#^\./(.*)#\1#' | sort -n) \
+ <(grep '"fileName": ' ${apex_file}.spdx.json | sed -E 's/.*"fileName": "(.*)",/\1/' | sort -n )
+
+ if [ $? != "0" ]; then
+ echo "Diffs found in $apex_file and SBOM"
+ exit 1
+ else
+ echo "No diffs."
+ fi
+ set -e
+
+ # Teardown
+ cleanup "${out_dir}"
+}
+
+function test_sbom_unbundled_apk {
+ # Setup
+ out_dir="$(setup)"
+
+ # run_soong to build Browser2.apk
+ run_soong "module_arm64" "${out_dir}" "sbom" "Browser2"
+
+ sbom_file=${out_dir}/target/product/module_arm64/system/product/app/Browser2/Browser2.apk.spdx.json
+ echo "============ Diffing files in Browser2.apk and SBOM"
+ set +e
+ # There is only one file in SBOM of APKs
+ diff \
+ <(echo "/system/product/app/Browser2/Browser2.apk" ) \
+ <(grep '"fileName": ' ${sbom_file} | sed -E 's/.*"fileName": "(.*)",/\1/' )
+
+ if [ $? != "0" ]; then
+ echo "Diffs found in $sbom_file"
+ exit 1
+ else
+ echo "No diffs."
+ fi
+ set -e
+
# Teardown
cleanup "${out_dir}"
}
-test_sbom_aosp_cf_x86_64_phone \ No newline at end of file
+test_sbom_aosp_cf_x86_64_phone
+test_sbom_unbundled_apex
+test_sbom_unbundled_apk \ No newline at end of file
diff --git a/third_party/zip/android.go b/third_party/zip/android.go
index f8e45c56d..0f41f6200 100644
--- a/third_party/zip/android.go
+++ b/third_party/zip/android.go
@@ -170,7 +170,7 @@ func (w *Writer) CreateCompressedHeader(fh *FileHeader) (io.WriteCloser, error)
func (w *Writer) CreateHeaderAndroid(fh *FileHeader) (io.Writer, error) {
writeDataDescriptor := fh.Method != Store
if writeDataDescriptor {
- fh.Flags &= DataDescriptorFlag
+ fh.Flags |= DataDescriptorFlag
} else {
fh.Flags &= ^uint16(DataDescriptorFlag)
}
diff --git a/ui/build/config.go b/ui/build/config.go
index fb5f7dd58..5d1505abc 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -15,7 +15,6 @@
package build
import (
- "context"
"encoding/json"
"errors"
"fmt"
@@ -40,9 +39,6 @@ import (
const (
envConfigDir = "vendor/google/tools/soong_config"
jsonSuffix = "json"
-
- configFetcher = "vendor/google/tools/soong/expconfigfetcher"
- envConfigFetchTimeout = 20 * time.Second
)
var (
@@ -174,87 +170,6 @@ func checkTopDir(ctx Context) {
}
}
-// fetchEnvConfig optionally fetches a configuration file that can then subsequently be
-// loaded into Soong environment to control certain aspects of build behavior (e.g., enabling RBE).
-// If a configuration file already exists on disk, the fetch is run in the background
-// so as to NOT block the rest of the build execution.
-func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
- configName := envConfigName + "." + jsonSuffix
- expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
- defer func() {
- ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
- }()
- if !config.GoogleProdCredsExist() {
- status := smpb.ExpConfigFetcher_MISSING_GCERT
- expConfigFetcher.Status = &status
- return nil
- }
-
- s, err := os.Stat(configFetcher)
- if err != nil {
- if os.IsNotExist(err) {
- return nil
- }
- return err
- }
- if s.Mode()&0111 == 0 {
- status := smpb.ExpConfigFetcher_ERROR
- expConfigFetcher.Status = &status
- return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
- }
-
- configExists := false
- outConfigFilePath := filepath.Join(config.OutDir(), configName)
- if _, err := os.Stat(outConfigFilePath); err == nil {
- configExists = true
- }
-
- tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
- fetchStart := time.Now()
- cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
- "-output_config_name", configName)
- if err := cmd.Start(); err != nil {
- status := smpb.ExpConfigFetcher_ERROR
- expConfigFetcher.Status = &status
- return err
- }
-
- fetchCfg := func() error {
- if err := cmd.Wait(); err != nil {
- status := smpb.ExpConfigFetcher_ERROR
- expConfigFetcher.Status = &status
- return err
- }
- fetchEnd := time.Now()
- expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
- expConfigFetcher.Filename = proto.String(outConfigFilePath)
-
- if _, err := os.Stat(outConfigFilePath); err != nil {
- status := smpb.ExpConfigFetcher_NO_CONFIG
- expConfigFetcher.Status = &status
- return err
- }
- status := smpb.ExpConfigFetcher_CONFIG
- expConfigFetcher.Status = &status
- return nil
- }
-
- // If a config file does not exist, wait for the config file to be fetched. Otherwise
- // fetch the config file in the background and return immediately.
- if !configExists {
- defer cancel()
- return fetchCfg()
- }
-
- go func() {
- defer cancel()
- if err := fetchCfg(); err != nil {
- ctx.Verbosef("Failed to fetch config file %v: %v\n", configName, err)
- }
- }()
- return nil
-}
-
func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
if bc == "" {
return nil
@@ -368,12 +283,14 @@ func NewConfig(ctx Context, args ...string) Config {
bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
if bc != "" {
- if err := fetchEnvConfig(ctx, ret, bc); err != nil {
- ctx.Verbosef("Failed to fetch config file: %v\n", err)
- }
if err := loadEnvConfig(ctx, ret, bc); err != nil {
ctx.Fatalln("Failed to parse env config files: %v", err)
}
+ if !ret.canSupportRBE() {
+ // Explicitly set USE_RBE env variable to false when we cannot run
+ // an RBE build to avoid ninja local execution pool issues.
+ ret.environ.Set("USE_RBE", "false")
+ }
}
if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
@@ -520,6 +437,11 @@ func NewConfig(ctx Context, args ...string) Config {
ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
+ // b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
+ // to unzip to enable zipbomb detection that incorrectly handle zip64 and data descriptors and fail on large
+ // zip files produced by soong_zip. Disable zipbomb detection.
+ ret.environ.Set("UNZIP_DISABLE_ZIPBOMB_DETECTION", "TRUE")
+
if ret.MultitreeBuild() {
ret.environ.Set("MULTITREE_BUILD", "true")
}
@@ -1374,18 +1296,26 @@ func (c *configImpl) StartGoma() bool {
return true
}
+func (c *configImpl) canSupportRBE() bool {
+ // Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
+ // its unlikely that we will be able to obtain necessary creds without stubby.
+ authType, _ := c.rbeAuth()
+ if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
+ return false
+ }
+ return true
+}
+
func (c *configImpl) UseRBE() bool {
// These alternate modes of running Soong do not use RBE / reclient.
if c.Bp2Build() || c.Queryview() || c.ApiBp2build() || c.JsonModuleGraph() {
return false
}
- authType, _ := c.rbeAuth()
- // Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
- // its unlikely that we will be able to obtain necessary creds without stubby.
- if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
+ if !c.canSupportRBE() {
return false
}
+
if v, ok := c.Environment().Get("USE_RBE"); ok {
v = strings.TrimSpace(v)
if v != "" && v != "false" {
diff --git a/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto b/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
index 4aee88b68..5b4400225 100644
--- a/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
+++ b/ui/metrics/bp2build_progress_metrics_proto/bp2build.proto
@@ -38,6 +38,9 @@ message Bp2buildConversionProgress {
// Total number of transitive dependencies.
int32 num_deps = 5;
+
+ // Unconverted reasons from heuristics
+ repeated string unconverted_reasons_from_heuristics = 6;
}
// Modules that the transitive dependencies were identified for.
diff --git a/zip/cmd/BUILD.bazel b/zip/cmd/BUILD.bazel
deleted file mode 100644
index e04a1e10d..000000000
--- a/zip/cmd/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 2022 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.
-
-# TODO(b/194644518): Switch to the source version when Bazel can build go
-# binaries.
-alias(
- name = "soong_zip",
- actual = "//prebuilts/build-tools:linux-x86/bin/soong_zip",
-)
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index a2ccc2011..5231faec9 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -173,6 +173,7 @@ func main() {
cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
traceFile := flags.String("trace", "", "write trace to file")
sha256Checksum := flags.Bool("sha256", false, "add a zip header to each file containing its SHA256 digest")
+ doNotWrite := flags.Bool("n", false, "Nothing is written to disk -- all other work happens")
flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
flags.Var(&listFiles{}, "l", "file containing list of files to zip")
@@ -236,6 +237,7 @@ func main() {
StoreSymlinks: *symlinks,
IgnoreMissingFiles: *ignoreMissingFiles,
Sha256Checksum: *sha256Checksum,
+ DoNotWrite: *doNotWrite,
})
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err.Error())
diff --git a/zip/zip.go b/zip/zip.go
index 5e1a10462..30a2ee762 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -282,6 +282,7 @@ type ZipArgs struct {
StoreSymlinks bool
IgnoreMissingFiles bool
Sha256Checksum bool
+ DoNotWrite bool
Stderr io.Writer
Filesystem pathtools.FileSystem
@@ -400,7 +401,9 @@ func Zip(args ZipArgs) error {
var zipErr error
- if !args.WriteIfChanged {
+ if args.DoNotWrite {
+ out = io.Discard
+ } else if !args.WriteIfChanged {
f, err := os.Create(args.OutputFilePath)
if err != nil {
return err
@@ -421,7 +424,7 @@ func Zip(args ZipArgs) error {
return zipErr
}
- if args.WriteIfChanged {
+ if args.WriteIfChanged && !args.DoNotWrite {
err := pathtools.WriteFileIfChanged(args.OutputFilePath, buf.Bytes(), 0666)
if err != nil {
return err