Merge "Enforce mainline modules to have latest target sdk version by default."
diff --git a/android/Android.bp b/android/Android.bp
index e0ad58f..29a88f2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -30,6 +30,7 @@
srcs: [
"androidmk.go",
"apex.go",
+ "api_domain.go",
"api_levels.go",
"arch.go",
"arch_list.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index cad9ec7..f2b05dd 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -147,6 +147,7 @@
"external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
"external/minijail": Bp2BuildDefaultTrueRecursively,
"external/openscreen": Bp2BuildDefaultTrueRecursively,
+ "external/objenesis": Bp2BuildDefaultTrueRecursively,
"external/pcre": Bp2BuildDefaultTrueRecursively,
"external/protobuf": Bp2BuildDefaultTrueRecursively,
"external/python/six": Bp2BuildDefaultTrueRecursively,
@@ -296,6 +297,8 @@
"system/tools/sysprop": Bp2BuildDefaultTrue,
"system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
+ "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
+
"tools/apksig": Bp2BuildDefaultTrue,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
@@ -310,7 +313,7 @@
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
"build/pesto":/* recursive = */ true,
- "build/soong/ui/metrics/bp2build_progress_metrics_proto":/* recursive = */ true,
+ "build/soong":/* recursive = */ true,
// 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
@@ -321,6 +324,10 @@
"external/guava":/* recursive = */ true,
"external/jsr305":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
+
+ // this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
+ "external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
+
"frameworks/base/tools/codegen":/* recursive = */ true,
"frameworks/ex/common":/* recursive = */ true,
@@ -352,6 +359,7 @@
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec.certificate",
"com.android.media.swcodec.key",
+ "com.android.neuralnetworks",
"com.android.neuralnetworks-androidManifest",
"com.android.neuralnetworks.certificate",
"com.android.neuralnetworks.key",
@@ -380,12 +388,14 @@
"libgrallocusage",
"libgralloctypes",
"libnativewindow",
+ "libneuralnetworks",
"libgraphicsenv",
"libhardware",
"libhardware_headers",
"libnativeloader-headers",
"libnativewindow_headers",
"libneuralnetworks_headers",
+ "libneuralnetworks_packageinfo",
"libopus",
"libpdx_headers",
"libprocpartition",
@@ -425,14 +435,19 @@
"neuralnetworks_types",
"neuralnetworks_utils_hal_aidl",
"neuralnetworks_utils_hal_common",
+ "neuralnetworks_utils_hal_service",
"neuralnetworks_utils_hal_1_0",
"neuralnetworks_utils_hal_1_1",
"neuralnetworks_utils_hal_1_2",
"neuralnetworks_utils_hal_1_3",
"libneuralnetworks_common",
+ // packagemanager_aidl_interface is created implicitly in packagemanager_aidl module
+ "packagemanager_aidl_interface",
"philox_random",
"philox_random_headers",
"server_configurable_flags",
+ "statslog_neuralnetworks.cpp",
+ "statslog_neuralnetworks.h",
"tensorflow_headers",
"libgui_headers",
@@ -452,6 +467,10 @@
"libavb",
"avb_headers",
+ //external/libxml2
+ "xmllint",
+ "libxml2",
+
//external/fec
"libfec_rs",
@@ -502,17 +521,83 @@
//frameworks/native/cmds/cmd
"libcmd",
+
+ //system/core/fs_mgr/libdm
+ "libdm",
+
+ //system/core/fs_mgr/libfiemap
+ "libfiemap_headers",
+ "libfiemap_passthrough_srcs",
+ "libfiemap_srcs",
+
+ //system/gsid
+ "libgsi",
+ "libgsi_headers",
+
+ //system/core/libkeyutils
+ "libkeyutils",
+
+ //bootable/recovery/minadbd
+ "libminadbd_headers",
+
+ //bootable/recovery/otautil
+ "libotautil",
+
+ //system/vold
+ "libvold_headers",
+
+ //system/extras/libfscrypt
+ "libfscrypt",
+
+ //system/core/fs_mgr
+ "libfstab",
+
+ //bootable/recovery/fuse_sideload
+ "libfusesideload",
+
+ //system/core/fs_mgr/libfs_avb
+ "libfs_avb",
+
+ //system/core/fs_mgr
+ "libfs_mgr",
+
+ "libcodec2_hidl@1.0",
+ "libcodec2_hidl@1.1",
+ "libcodec2_hidl@1.2",
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_hidl_plugin",
+ "libstagefright_bufferqueue_helper_novndk",
+ "libgui_bufferqueue_static",
+ "libGLESv2",
+ "libEGL",
+ "libcodec2_vndk",
+ "libnativeloader_lazy",
+ "libnativeloader",
+ "libEGL_getProcAddress",
+ "libEGL_blobCache",
+
+ "protoc-gen-cppstream",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
+ "aidl_interface_headers",
+ "api_domain",
"license",
"linker_config",
"java_import",
"java_import_host",
+ "ndk_headers",
+ "ndk_library",
"sysprop_library",
- "aidl_interface_headers",
}
+ // Add the names of modules that bp2build should never convert, if it is
+ // in the package allowlist. An error will be thrown if a module must
+ // not be here and in the alwaysConvert lists.
+ //
+ // For prebuilt modules (e.g. android_library_import), remember to add
+ // the "prebuilt_" prefix to the name, so that it's differentiable from
+ // the source versions within Soong's module graph.
Bp2buildModuleDoNotConvertList = []string{
// cc bugs
"libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library
@@ -550,33 +635,26 @@
"prebuilt_car-ui-androidx-core-common", // TODO(b/224773339), genrule dependency creates an .aar, not a .jar
"prebuilt_platform-robolectric-4.4-prebuilt", // aosp/1999250, needs .aar support in Jars
"prebuilt_platform-robolectric-4.5.1-prebuilt", // aosp/1999250, needs .aar support in Jars
-
- // proto support
- "libstats_proto_host", // TODO(b/236055697): handle protos from other packages
+ // ERROR: The dependencies for the following 1 jar(s) are not complete.
+ // 1.bazel-out/android_target-fastbuild/bin/prebuilts/tools/common/m2/_aar/robolectric-monitor-1.0.2-alpha1/classes_and_libs_merged.jar
+ "prebuilt_robolectric-monitor-1.0.2-alpha1",
// path property for filegroups
"conscrypt", // TODO(b/210751803), we don't handle path property for filegroups
"conscrypt-for-host", // TODO(b/210751803), we don't handle path property for filegroups
"host-libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
- "libprotobuf-internal-protos", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-internal-python-srcs", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-java-util-full", // TODO(b/210751803), we don't handle path property for filegroups
"auto_value_plugin_resources", // TODO(b/210751803), we don't handle path property for filegroups
// go deps:
- "aapt2-protos", // depends on soong_zip, a go binary
- "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
- "apex-protos", // depends on soong_zip, a go binary
- "generated_android_icu4j_src_files", "generated_android_icu4j_test_files", "icu4c_test_data", // depends on unconverted modules: soong_zip
- "host_bionic_linker_asm", // depends on extract_linker, a go binary.
- "host_bionic_linker_script", // depends on extract_linker, a go binary.
- "libc_musl_sysroot_bionic_arch_headers", // depends on soong_zip
- "libc_musl_sysroot_bionic_headers", // 218405924, depends on soong_zip and generates duplicate srcs
- "libc_musl_sysroot_libc++_headers", "libc_musl_sysroot_libc++abi_headers", // depends on soong_zip, zip2zip
- "libc_musl_sysroot_zlib_headers", // depends on soong_zip and zip2zip
- "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
- "robolectric_tzdata", // depends on soong_zip, a go binary
+ "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
+ "host_bionic_linker_asm", // depends on extract_linker, a go binary.
+ "host_bionic_linker_script", // depends on extract_linker, a go binary.
+
+ // in cmd attribute of genrule rule //system/timezone/output_data:robolectric_tzdata: label '//system/timezone/output_data:iana/tzdata' in $(location) expression is not a declared prerequisite of this rule
+ "robolectric_tzdata",
// rust support
"libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
@@ -592,8 +670,8 @@
"com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
"currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
"dex2oat-script", // depends on unconverted modules: dex2oat
- "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
- "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
+ "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
+ "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
"host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano
"jacoco-stubs", // b/245767077, depends on droidstubs
"libapexutil", // depends on unconverted modules: apex-info-list-tinyxml
@@ -618,15 +696,12 @@
"libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
"pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
- "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
- "static_crasher", // depends on unconverted modules: libdebuggerd_handler
- "stats-log-api-gen", // depends on unconverted modules: libstats_proto_host
- "statslog.cpp", "statslog.h", "statslog.rs", // depends on unconverted modules: stats-log-api-gen
- "statslog_art.cpp", "statslog_art.h", "statslog_header.rs", // depends on unconverted modules: stats-log-api-gen
- "test_fips", // depends on unconverted modules: adb
- "timezone-host", // depends on unconverted modules: art.module.api.annotations
- "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
- "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+ "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
+ "static_crasher", // depends on unconverted modules: libdebuggerd_handler
+ "test_fips", // depends on unconverted modules: adb
+ "timezone-host", // depends on unconverted modules: art.module.api.annotations
+ "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
+ "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
"toybox-static",
@@ -634,6 +709,10 @@
// aidl files not created
"overlayable_policy_aidl_interface",
+ //prebuilts/tools/common/m2
+ // depends on //external/okio:okio-lib, which uses kotlin
+ "wire-runtime",
+
// cc_test related.
// Failing host cc_tests
"memunreachable_unit_test",
@@ -1088,6 +1167,12 @@
"libtest_with_dependency_loop_b_tmp",
"libtest_with_dependency_loop_c",
"libtestshared",
+
+ // depends on unconverted libprotobuf-java-nano
+ "dnsresolverprotosnano",
+ "launcherprotosnano",
+ "datastallprotosnano",
+ "devicepolicyprotosnano",
}
Bp2buildCcLibraryStaticOnlyList = []string{}
@@ -1136,6 +1221,20 @@
"prebuilt_platform-robolectric-4.4-prebuilt",
"prebuilt_platform-robolectric-4.5.1-prebuilt",
"prebuilt_currysrc_org.eclipse",
+
+ // TODO(b/247782695 and/or b/242847534) Fix mixed build between unconverted gensrcs and converted filegroup
+ "libstats_atom_enum_protos",
+ "data_stall_event_proto",
+ "device_policy_proto",
+ "dns_resolver_proto",
+ "launcher_proto",
+ "network_stack_proto",
+ "srcs_bluetooth_protos",
+ "srcs_bluetooth_leaudio_protos",
+ "style_proto",
+ "tethering_proto",
+ "text_classifier_proto",
+ "libstats_atom_message_protos",
}
ProdMixedBuildsEnabledList = []string{
diff --git a/android/api_domain.go b/android/api_domain.go
new file mode 100644
index 0000000..8ff4752
--- /dev/null
+++ b/android/api_domain.go
@@ -0,0 +1,122 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "github.com/google/blueprint"
+
+ "android/soong/bazel"
+)
+
+func init() {
+ RegisterApiDomainBuildComponents(InitRegistrationContext)
+}
+
+func RegisterApiDomainBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("api_domain", ApiDomainFactory)
+}
+
+type ApiSurface int
+
+// TODO(b/246656800): Reconcile with android.SdkKind
+const (
+ PublicApi ApiSurface = iota
+ SystemApi
+ VendorApi
+)
+
+func (a ApiSurface) String() string {
+ switch a {
+ case PublicApi:
+ return "publicapi"
+ case SystemApi:
+ return "systemapi"
+ case VendorApi:
+ return "vendorapi"
+ default:
+ return "invalid"
+ }
+}
+
+type apiDomain struct {
+ ModuleBase
+ BazelModuleBase
+
+ properties apiDomainProperties
+}
+
+type apiDomainProperties struct {
+ // cc library contributions (.h files/.map.txt) of this API domain
+ // This dependency is a no-op in Soong, but the corresponding Bazel target in the bp2build workspace will provide a `CcApiContributionInfo` provider
+ Cc_api_contributions []string
+}
+
+func ApiDomainFactory() Module {
+ m := &apiDomain{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, DeviceSupported, MultilibBoth)
+ InitBazelModule(m)
+ return m
+}
+
+func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) {
+ for _, cc := range a.properties.Cc_api_contributions {
+ // Use FarVariationDependencies since the variants of api_domain is a subset of the variants of the dependency cc module
+ // Creating a dependency on the first variant is ok since this is a no-op in Soong
+ // The primary function of this dependency is to create a connected graph in the corresponding bp2build workspace
+ ctx.AddFarVariationDependencies([]blueprint.Variation{}, nil, cc)
+ }
+}
+
+// API domain does not have any builld actions yet
+func (a *apiDomain) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+const (
+ apiContributionSuffix = ".contribution"
+)
+
+// ApiContributionTargetName returns the name of the bp2build target (e.g. cc_api_contribution) of contribution modules (e.g. ndk_library)
+// A suffix is necessary to prevent a name collision with the base target in the same bp2build bazel package
+func ApiContributionTargetName(moduleName string) string {
+ return moduleName + apiContributionSuffix
+}
+
+// For each contributing cc_library, format the name to its corresponding contribution bazel target in the bp2build workspace
+func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []string) bazel.LabelListAttribute {
+ addSuffix := func(ctx BazelConversionPathContext, module blueprint.Module) string {
+ baseLabel := BazelModuleLabel(ctx, module)
+ return ApiContributionTargetName(baseLabel)
+ }
+ bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix)
+ return bazel.MakeLabelListAttribute(bazelLabels)
+}
+
+type bazelApiDomainAttributes struct {
+ Cc_api_contributions bazel.LabelListAttribute
+}
+
+func (a *apiDomain) ConvertWithBp2build(ctx TopDownMutatorContext) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "api_domain",
+ Bzl_load_location: "//build/bazel/rules/apis:api_domain.bzl",
+ }
+ attrs := &bazelApiDomainAttributes{
+ Cc_api_contributions: contributionBazelAttributes(ctx, a.properties.Cc_api_contributions),
+ }
+ ctx.CreateBazelTargetModule(props, CommonAttributes{
+ Name: ctx.ModuleName(),
+ }, attrs)
+}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index bbdae96..9c50098 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -202,20 +202,26 @@
return labels
}
-// Returns true if a prefix + components[:i] + /Android.bp exists
-// TODO(b/185358476) Could check for BUILD file instead of checking for Android.bp file, or ensure BUILD is always generated?
-func directoryHasBlueprint(fs pathtools.FileSystem, prefix string, components []string, componentIndex int) bool {
- blueprintPath := prefix
- if blueprintPath != "" {
- blueprintPath = blueprintPath + "/"
- }
- blueprintPath = blueprintPath + strings.Join(components[:componentIndex+1], "/")
- blueprintPath = blueprintPath + "/Android.bp"
- if exists, _, _ := fs.Exists(blueprintPath); exists {
+// Returns true if a prefix + components[:i] is a package boundary.
+//
+// A package boundary is determined by a BUILD file in the directory. This can happen in 2 cases:
+//
+// 1. An Android.bp exists, which bp2build will always convert to a sibling BUILD file.
+// 2. An Android.bp doesn't exist, but a checked-in BUILD/BUILD.bazel file exists, and that file
+// is allowlisted by the bp2build configuration to be merged into the symlink forest workspace.
+func isPackageBoundary(config Config, prefix string, components []string, componentIndex int) bool {
+ prefix = filepath.Join(prefix, filepath.Join(components[:componentIndex+1]...))
+ if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "Android.bp")); exists {
return true
- } else {
- return false
+ } else if config.Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(prefix) {
+ if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD")); exists {
+ return true
+ } else if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD.bazel")); exists {
+ return true
+ }
}
+
+ return false
}
// Transform a path (if necessary) to acknowledge package boundaries
@@ -242,17 +248,37 @@
newPath.Label = path.Label
return newPath
}
-
- newLabel := ""
+ if strings.HasPrefix(path.Label, "./") {
+ // Drop "./" for consistent handling of paths.
+ // Specifically, to not let "." be considered a package boundary.
+ // Say `inputPath` is `x/Android.bp` and that file has some module
+ // with `srcs=["y/a.c", "z/b.c"]`.
+ // And say the directory tree is:
+ // x
+ // ├── Android.bp
+ // ├── y
+ // │ ├── a.c
+ // │ └── Android.bp
+ // └── z
+ // └── b.c
+ // Then bazel equivalent labels in srcs should be:
+ // //x/y:a.c, x/z/b.c
+ // The above should still be the case if `x/Android.bp` had
+ // srcs=["./y/a.c", "./z/b.c"]
+ // However, if we didn't strip "./", we'd get
+ // //x/./y:a.c, //x/.:z/b.c
+ path.Label = strings.TrimPrefix(path.Label, "./")
+ }
pathComponents := strings.Split(path.Label, "/")
- foundBlueprint := false
+ newLabel := ""
+ foundPackageBoundary := false
// Check the deepest subdirectory first and work upwards
for i := len(pathComponents) - 1; i >= 0; i-- {
pathComponent := pathComponents[i]
var sep string
- if !foundBlueprint && directoryHasBlueprint(ctx.Config().fs, ctx.ModuleDir(), pathComponents, i) {
+ if !foundPackageBoundary && isPackageBoundary(ctx.Config(), ctx.ModuleDir(), pathComponents, i) {
sep = ":"
- foundBlueprint = true
+ foundPackageBoundary = true
} else {
sep = "/"
}
@@ -262,7 +288,7 @@
newLabel = pathComponent + sep + newLabel
}
}
- if foundBlueprint {
+ if foundPackageBoundary {
// Ensure paths end up looking like //bionic/... instead of //./bionic/...
moduleDir := ctx.ModuleDir()
if strings.HasPrefix(moduleDir, ".") {
diff --git a/android/bazel_paths_test.go b/android/bazel_paths_test.go
index b047511..450bf76 100644
--- a/android/bazel_paths_test.go
+++ b/android/bazel_paths_test.go
@@ -17,6 +17,10 @@
import (
"path/filepath"
"testing"
+
+ "android/soong/bazel"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/pathtools"
)
type TestBazelPathContext struct{}
@@ -29,7 +33,7 @@
return cfg
}
-func (*TestBazelPathContext) AddNinjaFileDeps(deps ...string) {
+func (*TestBazelPathContext) AddNinjaFileDeps(...string) {
panic("Unimplemented")
}
@@ -106,3 +110,74 @@
t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
}
}
+
+type TestBazelConversionPathContext struct {
+ TestBazelConversionContext
+ moduleDir string
+ cfg Config
+}
+
+func (ctx *TestBazelConversionPathContext) AddNinjaFileDeps(...string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) GlobWithDeps(string, []string) ([]string, error) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) PropertyErrorf(string, string, ...interface{}) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) GetDirectDep(string) (blueprint.Module, blueprint.DependencyTag) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) ModuleFromName(string) (blueprint.Module, bool) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) AddUnconvertedBp2buildDep(string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) AddMissingBp2buildDep(string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) Module() Module {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) Config() Config {
+ return ctx.cfg
+}
+
+func (ctx *TestBazelConversionPathContext) ModuleDir() string {
+ return ctx.moduleDir
+}
+
+func TestTransformSubpackagePath(t *testing.T) {
+ cfg := NullConfig("out", "out/soong")
+ cfg.fs = pathtools.MockFs(map[string][]byte{
+ "x/Android.bp": nil,
+ "x/y/Android.bp": nil,
+ })
+
+ var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
+ moduleDir: "x",
+ cfg: cfg,
+ }
+ pairs := map[string]string{
+ "y/a.c": "//x/y:a.c",
+ "./y/a.c": "//x/y:a.c",
+ "z/b.c": "z/b.c",
+ "./z/b.c": "z/b.c",
+ }
+ for in, out := range pairs {
+ actual := transformSubpackagePath(ctx, bazel.Label{Label: in}).Label
+ if actual != out {
+ t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
+ }
+ }
+}
diff --git a/android/config.go b/android/config.go
index 745410f..ee432a2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1619,6 +1619,14 @@
return uncheckedFinalApiLevel(apiLevel)
}
+func (c *deviceConfig) BuildBrokenClangAsFlags() bool {
+ return c.config.productVariables.BuildBrokenClangAsFlags
+}
+
+func (c *deviceConfig) BuildBrokenClangCFlags() bool {
+ return c.config.productVariables.BuildBrokenClangCFlags
+}
+
func (c *deviceConfig) BuildBrokenClangProperty() bool {
return c.config.productVariables.BuildBrokenClangProperty
}
diff --git a/android/module.go b/android/module.go
index 5d520f4..1617259 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1231,22 +1231,17 @@
}
}
- required := depsToLabelList(mod.commonProperties.Required)
+ // The required property can contain the module itself. This causes a cycle
+ // when generated as the 'data' label list attribute in Bazel. Remove it if
+ // it exists. See b/247985196.
+ _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), mod.commonProperties.Required)
+ required := depsToLabelList(requiredWithoutCycles)
archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
for axis, configToProps := range archVariantProps {
for config, _props := range configToProps {
if archProps, ok := _props.(*commonProperties); ok {
- // TODO(b/234748998) Remove this requiredFiltered workaround when aapt2 converts successfully
- requiredFiltered := archProps.Required
- if attrs.Name == "apexer" {
- requiredFiltered = make([]string, 0, len(archProps.Required))
- for _, req := range archProps.Required {
- if req != "aapt2" && req != "apexer" {
- requiredFiltered = append(requiredFiltered, req)
- }
- }
- }
- required.SetSelectValue(axis, config, depsToLabelList(requiredFiltered).Value)
+ _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), archProps.Required)
+ required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
if !neitherHostNorDevice {
if archProps.Enabled != nil {
if axis != bazel.OsConfigurationAxis || osSupport[config] {
diff --git a/android/sdk.go b/android/sdk.go
index a477cba..bd2f5d1 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -74,6 +74,26 @@
sdkAwareWithoutModule
}
+// minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
+type minApiLevelForSdkSnapshot interface {
+ MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+}
+
+// MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module.
+//
+// If the module does not provide a min_sdk_version then it defaults to 1.
+func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel {
+ minApiLevel := NoneApiLevel
+ if m, ok := module.(minApiLevelForSdkSnapshot); ok {
+ minApiLevel = m.MinSdkVersion(ctx).ApiLevel
+ }
+ if minApiLevel == NoneApiLevel {
+ // The default min API level is 1.
+ minApiLevel = uncheckedFinalApiLevel(1)
+ }
+ return minApiLevel
+}
+
// SdkRef refers to a version of an SDK
type SdkRef struct {
Name string
@@ -715,8 +735,13 @@
// have common values. Those fields are cleared and the common value added to the common
// properties.
//
- // A field annotated with a tag of `sdk:"keep"` will be treated as if it
- // was not capitalized, i.e. not optimized for common values.
+ // A field annotated with a tag of `sdk:"ignore"` will be treated as if it
+ // was not capitalized, i.e. ignored and not optimized for common values.
+ //
+ // A field annotated with a tag of `sdk:"keep"` will not be cleared even if the value is common
+ // across multiple structs. Common values will still be copied into the common property struct.
+ // So, if the same value is placed in all structs populated from variants that value would be
+ // copied into all common property structs and so be available in every instance.
//
// A field annotated with a tag of `android:"arch_variant"` will be allowed to have
// values that differ by arch, fields not tagged as such must have common values across
@@ -903,18 +928,18 @@
// the locations of any of their prebuilt files in the snapshot by os type to prevent them
// from colliding. See OsPrefix().
//
- // This property is the same for all variants of a member and so would be optimized away
- // if it was not explicitly kept.
- Os_count int `sdk:"keep"`
+ // Ignore this property during optimization. This is needed because this property is the same for
+ // all variants of a member and so would be optimized away if it was not ignored.
+ Os_count int `sdk:"ignore"`
// The os type for which these properties refer.
//
// Provided to allow a member to differentiate between os types in the locations of their
// prebuilt files when it supports more than one os type.
//
- // This property is the same for all os type specific variants of a member and so would be
- // optimized away if it was not explicitly kept.
- Os OsType `sdk:"keep"`
+ // Ignore this property during optimization. This is needed because this property is the same for
+ // all variants of a member and so would be optimized away if it was not ignored.
+ Os OsType `sdk:"ignore"`
// The setting to use for the compile_multilib property.
Compile_multilib string `android:"arch_variant"`
diff --git a/android/variable.go b/android/variable.go
index b156051..37ecab5 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -430,6 +430,8 @@
ShippingApiLevel *string `json:",omitempty"`
+ BuildBrokenClangAsFlags bool `json:",omitempty"`
+ BuildBrokenClangCFlags bool `json:",omitempty"`
BuildBrokenClangProperty bool `json:",omitempty"`
BuildBrokenDepfile *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1805291..a69faeb 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7241,6 +7241,11 @@
ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@TEST.BUILD_ID$")
ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@TEST.BUILD_ID$")
ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
+
+ // Ensure that canned_fs_config has an entry for the app set zip file
+ generateFsRule := mod.Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+ ensureContains(t, cmd, "AppSet.zip")
}
func TestAppSetBundlePrebuilt(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index b95b3bd..cb09e35 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1087,7 +1087,7 @@
}
} else if f.class == appSet {
appSetDirs = append(appSetDirs, f.installDir)
- appSetFiles[f.installDir] = f.builtFile
+ appSetFiles[f.installDir] = f.module.(*java.AndroidAppSet).PackedAdditionalOutputs()
} else {
readOnlyPaths = append(readOnlyPaths, pathInApex)
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index cf8e9f7..3b06f85 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -158,63 +158,30 @@
# NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
pass
-returns = [
- outputFiles,
- ccObjectFiles,
- sharedLibraries,
- staticLibraries,
- includes,
- system_includes,
- headers,
- rootStaticArchives,
- rootSharedLibraries,
- [toc_file]
-]
+return json_encode({
+ "OutputFiles": outputFiles,
+ "CcObjectFiles": ccObjectFiles,
+ "CcSharedLibraryFiles": sharedLibraries,
+ "CcStaticLibraryFiles": staticLibraries,
+ "Includes": includes,
+ "SystemIncludes": system_includes,
+ "Headers": headers,
+ "RootStaticArchives": rootStaticArchives,
+ "RootDynamicLibraries": rootSharedLibraries,
+ "TocFile": toc_file
+})`
-return "|".join([", ".join(r) for r in returns])`
}
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
- const expectedLen = 10
- splitString := strings.Split(rawString, "|")
- if len(splitString) != expectedLen {
- return CcInfo{}, fmt.Errorf("expected %d items, got %q", expectedLen, splitString)
- }
- outputFilesString := splitString[0]
- ccObjectsString := splitString[1]
- ccSharedLibrariesString := splitString[2]
- ccStaticLibrariesString := splitString[3]
- includesString := splitString[4]
- systemIncludesString := splitString[5]
- headersString := splitString[6]
- rootStaticArchivesString := splitString[7]
- rootDynamicLibrariesString := splitString[8]
- tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't
-
- outputFiles := splitOrEmpty(outputFilesString, ", ")
- ccObjects := splitOrEmpty(ccObjectsString, ", ")
- ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ")
- ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ")
- includes := splitOrEmpty(includesString, ", ")
- systemIncludes := splitOrEmpty(systemIncludesString, ", ")
- headers := splitOrEmpty(headersString, ", ")
- rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ")
- rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ")
- return CcInfo{
- OutputFiles: outputFiles,
- CcObjectFiles: ccObjects,
- CcSharedLibraryFiles: ccSharedLibraries,
- CcStaticLibraryFiles: ccStaticLibraries,
- Includes: includes,
- SystemIncludes: systemIncludes,
- Headers: headers,
- RootStaticArchives: rootStaticArchives,
- RootDynamicLibraries: rootDynamicLibraries,
- TocFile: tocFile,
- }, nil
+ var ccInfo CcInfo
+ decoder := json.NewDecoder(strings.NewReader(rawString))
+ decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
+ err := decoder.Decode(&ccInfo)
+ return ccInfo, err
}
// Query Bazel for the artifacts generated by the apex modules.
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 46eb0b6..afe478b 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -1,9 +1,8 @@
package cquery
import (
- "fmt"
+ "encoding/json"
"reflect"
- "strings"
"testing"
)
@@ -63,74 +62,48 @@
}
func TestGetCcInfoParseResults(t *testing.T) {
- const expectedSplits = 10
- noResult := strings.Repeat("|", expectedSplits-1)
testCases := []struct {
- description string
- input string
- expectedOutput CcInfo
- expectedErrorMessage string
+ description string
+ inputCcInfo CcInfo
+ expectedOutput CcInfo
}{
{
- description: "no result",
- input: noResult,
- expectedOutput: CcInfo{
- OutputFiles: []string{},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "",
- },
+ description: "no result",
+ inputCcInfo: CcInfo{},
+ expectedOutput: CcInfo{},
},
{
description: "only output",
- input: "test" + noResult,
+ inputCcInfo: CcInfo{
+ OutputFiles: []string{"test", "test3"},
+ },
expectedOutput: CcInfo{
- OutputFiles: []string{"test"},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "",
+ OutputFiles: []string{"test", "test3"},
},
},
{
description: "only ToC",
- input: noResult + "test",
+ inputCcInfo: CcInfo{
+ TocFile: "test",
+ },
expectedOutput: CcInfo{
- OutputFiles: []string{},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "test",
+ TocFile: "test",
},
},
{
description: "all items set",
- input: "out1, out2" +
- "|object1, object2" +
- "|shared_lib1, shared_lib2" +
- "|static_lib1, static_lib2" +
- "|., dir/subdir" +
- "|system/dir, system/other/dir" +
- "|dir/subdir/hdr.h" +
- "|rootstaticarchive1" +
- "|rootdynamiclibrary1" +
- "|lib.so.toc",
+ inputCcInfo: CcInfo{
+ OutputFiles: []string{"out1", "out2"},
+ CcObjectFiles: []string{"object1", "object2"},
+ CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"},
+ CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
+ Includes: []string{".", "dir/subdir"},
+ SystemIncludes: []string{"system/dir", "system/other/dir"},
+ Headers: []string{"dir/subdir/hdr.h"},
+ RootStaticArchives: []string{"rootstaticarchive1"},
+ RootDynamicLibraries: []string{"rootdynamiclibrary1"},
+ TocFile: "lib.so.toc",
+ },
expectedOutput: CcInfo{
OutputFiles: []string{"out1", "out2"},
CcObjectFiles: []string{"object1", "object2"},
@@ -144,24 +117,12 @@
TocFile: "lib.so.toc",
},
},
- {
- description: "too few result splits",
- input: "|",
- expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, []string{"", ""}),
- },
- {
- description: "too many result splits",
- input: strings.Repeat("|", expectedSplits+1), // 2 too many
- expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
- },
}
for _, tc := range testCases {
- actualOutput, err := GetCcInfo.ParseResult(tc.input)
- if (err == nil && tc.expectedErrorMessage != "") ||
- (err != nil && err.Error() != tc.expectedErrorMessage) {
- t.Errorf("%q:\n%12s: %q\n%12s: %q", tc.description, "expect Error", tc.expectedErrorMessage, "but got", err)
+ jsonInput, _ := json.Marshal(tc.inputCcInfo)
+ actualOutput, err := GetCcInfo.ParseResult(string(jsonInput))
+ if err != nil {
+ t.Errorf("%q:\n test case get error: %q", tc.description, err)
} else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput)
}
diff --git a/bp2build/api_domain_conversion_test.go b/bp2build/api_domain_conversion_test.go
new file mode 100644
index 0000000..fc9d1d5
--- /dev/null
+++ b/bp2build/api_domain_conversion_test.go
@@ -0,0 +1,68 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func registerApiDomainModuleTypes(ctx android.RegistrationContext) {
+ android.RegisterApiDomainBuildComponents(ctx)
+ cc.RegisterNdkModuleTypes(ctx)
+ cc.RegisterLibraryBuildComponents(ctx)
+}
+
+func TestApiDomainContributionsTest(t *testing.T) {
+ bp := `
+ api_domain {
+ name: "system",
+ cc_api_contributions: [
+ "libfoo.ndk",
+ "libbar",
+ ],
+ }
+ `
+ fs := map[string]string{
+ "libfoo/Android.bp": `
+ ndk_library {
+ name: "libfoo",
+ }
+ `,
+ "libbar/Android.bp": `
+ cc_library {
+ name: "libbar",
+ }
+ `,
+ }
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "api_domain",
+ "system",
+ AttrNameToString{
+ "cc_api_contributions": `[
+ "//libfoo:libfoo.ndk.contribution",
+ "//libbar:libbar.contribution",
+ ]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunBp2BuildTestCase(t, registerApiDomainModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ Filesystem: fs,
+ })
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ee162b2..36c3a48 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -242,6 +242,7 @@
// Simple metrics tracking for bp2build
metrics := CodegenMetrics{
ruleClassCount: make(map[string]uint64),
+ convertedModulePathMap: make(map[string]string),
convertedModuleTypeCount: make(map[string]uint64),
totalModuleTypeCount: make(map[string]uint64),
}
@@ -272,20 +273,21 @@
// target in a BUILD file, we don't autoconvert them.
// Log the module.
- metrics.AddConvertedModule(m, moduleType, Handcrafted)
+ metrics.AddConvertedModule(m, moduleType, dir, Handcrafted)
} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
// Handle modules converted to generated targets.
// Log the module.
- metrics.AddConvertedModule(aModule, moduleType, Generated)
+ metrics.AddConvertedModule(aModule, moduleType, dir, Generated)
// Handle modules with unconverted deps. By default, emit a warning.
if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
msg := fmt.Sprintf("%s %s:%s depends on unconverted modules: %s",
moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- if ctx.unconvertedDepMode == warnUnconvertedDeps {
+ switch ctx.unconvertedDepMode {
+ case warnUnconvertedDeps:
metrics.moduleWithUnconvertedDepsMsgs = append(metrics.moduleWithUnconvertedDepsMsgs, msg)
- } else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
+ case errorModulesUnconvertedDeps:
errs = append(errs, fmt.Errorf(msg))
return
}
@@ -293,9 +295,10 @@
if unconvertedDeps := aModule.GetMissingBp2buildDeps(); len(unconvertedDeps) > 0 {
msg := fmt.Sprintf("%s %s:%s depends on missing modules: %s",
moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- if ctx.unconvertedDepMode == warnUnconvertedDeps {
+ switch ctx.unconvertedDepMode {
+ case warnUnconvertedDeps:
metrics.moduleWithMissingDepsMsgs = append(metrics.moduleWithMissingDepsMsgs, msg)
- } else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
+ case errorModulesUnconvertedDeps:
errs = append(errs, fmt.Errorf(msg))
return
}
@@ -348,7 +351,7 @@
// TODO(b/198619163): We should change this to export_files(glob(["**/*"])) instead, but doing that causes these errors:
// "Error in exports_files: generated label '//external/avb:avbtool' conflicts with existing py_binary rule"
// So we need to solve all the "target ... is both a rule and a file" warnings first.
- for dir, _ := range dirs {
+ for dir := range dirs {
buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{
name: "bp2build_all_srcs",
content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`,
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index dd28c3c..d29eb9c 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -971,6 +971,24 @@
},
},
{
+ Description: "filegroup with dot-slash-prefixed srcs",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["./a", "./b"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a",
+ "b",
+ ]`,
+ }),
+ },
+ },
+ {
Description: "filegroup with excludes srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
@@ -987,57 +1005,6 @@
},
},
{
- Description: "filegroup with glob",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "other/a.txt",
- "other/b.txt",
- "other/subdir/a.txt",
- ]`,
- }),
- },
- Filesystem: map[string]string{
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- },
- {
- Description: "filegroup with glob in subdir",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Dir: "other",
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "subdir/a.txt",
- ]`,
- }),
- },
- },
- {
Description: "depends_on_other_dir_module",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
@@ -1086,6 +1053,29 @@
}`,
},
},
+ {
+ Description: "depends_on_other_missing_module_error",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ UnconvertedDepsMode: errorModulesUnconvertedDeps,
+ Blueprint: `filegroup {
+ name: "foobar",
+ srcs: [
+ "c",
+ "//other:foo",
+ "//other:goo",
+ ],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`),
+ Filesystem: map[string]string{"other/Android.bp": `filegroup {
+ name: "foo",
+ srcs: ["a"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ },
+ },
}
for _, testCase := range testCases {
@@ -1095,8 +1085,6 @@
}
}
-type bp2buildMutator = func(android.TopDownMutatorContext)
-
func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
testCases := []struct {
moduleTypeUnderTest string
@@ -1429,6 +1417,226 @@
}
}
+func TestGlob(t *testing.T) {
+ testCases := []Bp2buildTestCase{
+ {
+ Description: "filegroup with glob",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "other/a.txt",
+ "other/b.txt",
+ "other/subdir/a.txt",
+ ]`,
+ }),
+ },
+ Filesystem: map[string]string{
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ },
+ {
+ Description: "filegroup with glob in subdir",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Dir: "other",
+ Filesystem: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "subdir/a.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with no kept BUILD files",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ // empty
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "foo/a.txt",
+ "foo/bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with kept BUILD file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ "foo",
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo:bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with kept BUILD.bazel file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ "foo",
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD.bazel": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD.bazel": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo:bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with Android.bp file as boundary",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/Android.bp": "",
+ "foo/a.txt": "",
+ "foo/bar/Android.bp": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo/bar:b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob in subdir with kept BUILD and BUILD.bazel file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Dir: "other",
+ KeepBuildFileForDirs: []string{
+ "other/foo",
+ "other/foo/bar",
+ // deliberately not other/foo/baz/BUILD.
+ },
+ Filesystem: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/foo/BUILD": "",
+ "other/foo/a.txt": "",
+ "other/foo/bar/BUILD.bazel": "",
+ "other/foo/bar/b.txt": "",
+ "other/foo/baz/BUILD": "",
+ "other/foo/baz/c.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//other/foo:a.txt",
+ "//other/foo/bar:b.txt",
+ "//other/foo:baz/c.txt",
+ ]`,
+ }),
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.Description, func(t *testing.T) {
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+ }
+}
+
func TestGlobExcludeSrcs(t *testing.T) {
testCases := []Bp2buildTestCase{
{
@@ -1518,6 +1726,22 @@
},
},
{
+ Description: "Required into data test, cyclic self reference is filtered out",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
+filegroup {
+ name: "fg_foo",
+ required: ["reqd", "fg_foo"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "data": `[":reqd"]`,
+ }),
+ },
+ },
+ {
Description: "Required via arch into data test",
ModuleTypeUnderTest: "python_library",
ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 1c9fba2..c23779e 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -676,3 +676,77 @@
},
})
}
+
+func TestCcBinaryWithSyspropSrcs(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with sysprop sources",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ targets: []testBazelTarget{
+ {"sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }},
+ {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }},
+ {"cc_binary", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with sysprop sources in some configs but not others",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ targets: []testBazelTarget{
+ {"sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }},
+ {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }},
+ {"cc_binary", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index ffa6b3f..1b8e9b4 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -3112,3 +3112,139 @@
},
})
}
+
+func TestCcLibraryWithSyspropSrcs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with sysprop sources",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with sysprop sources in some configs but not others",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ host_supported: true,
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithAidlAndSharedLibs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_aidl_library depends on shared libs from parent cc_library_static",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ shared_libs: [
+ "bar",
+ "baz",
+ ],
+ export_shared_lib_headers: [
+ "baz",
+ ],
+}` +
+ simpleModuleDoNotConvertBp2build("cc_library", "bar") +
+ simpleModuleDoNotConvertBp2build("cc_library", "baz"),
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ }),
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":foo_aidl_library"]`,
+ "implementation_dynamic_deps": `[
+ ":baz",
+ ":bar",
+ ]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "dynamic_deps": `[":baz"]`,
+ "implementation_dynamic_deps": `[":bar"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 48515c8..b1a9240 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -488,22 +488,21 @@
`,
},
Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "has_stubs": `True`,
- }),
- makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library": `":a"`,
- "stubs_symbol_file": `"a.map.txt"`,
- "stubs_versions": `[
+ ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{
+ "soname": `"a.so"`,
+ "source_library": `":a"`,
+ "stubs_symbol_file": `"a.map.txt"`,
+ "stubs_versions": `[
"28",
"29",
"current",
]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "has_stubs": `True`,
}),
},
- },
- )
+ })
}
func TestCcLibrarySharedSystemSharedLibsSharedEmpty(t *testing.T) {
@@ -728,3 +727,77 @@
},
})
}
+
+func TestCcLibrarySharedWithSyspropSrcs(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared with sysprop sources",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared with sysprop sources in some configs but not others",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 37722ed..e3ea9a0 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1629,3 +1629,77 @@
},
})
}
+
+func TestCcLibraryStaticWithSyspropSrcs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static with sysprop sources",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static with sysprop sources in some configs but not others",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index b6190c6..522c10e 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -34,6 +34,12 @@
files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
+ convertedModulePathMap, err := json.MarshalIndent(metrics.convertedModulePathMap, "", "\t")
+ if err != nil {
+ panic(err)
+ }
+ files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
+
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
files = append(files, newFile("product_config", "arch_configuration.bzl", android.StarlarkArchConfigurations()))
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 0cb711c..b696a98 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -116,6 +116,10 @@
basename: "converted_modules.txt",
},
{
+ dir: "metrics",
+ basename: "converted_modules_path_map.json",
+ },
+ {
dir: "product_config",
basename: "soong_config_variables.bzl",
},
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index a8bfecd..160395b 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -61,7 +61,7 @@
{
moduleType: "genrule",
factory: genrule.GenRuleFactory,
- genDir: "$(GENDIR)",
+ genDir: "$(RULEDIR)",
},
{
moduleType: "cc_genrule",
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 3a21c34..0b45996 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,6 +9,7 @@
"android/soong/android"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
+
"github.com/google/blueprint"
)
@@ -38,6 +39,9 @@
// List of converted modules
convertedModules []string
+ // Map of converted modules and paths to call
+ convertedModulePathMap map[string]string
+
// Counts of converted modules by module type.
convertedModuleTypeCount map[string]uint64
@@ -147,10 +151,11 @@
Handcrafted
)
-func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, conversionType ConversionType) {
+func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string, conversionType ConversionType) {
// Undo prebuilt_ module name prefix modifications
moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
metrics.convertedModules = append(metrics.convertedModules, moduleName)
+ metrics.convertedModulePathMap[moduleName] = "//" + dir
metrics.convertedModuleTypeCount[moduleType] += 1
metrics.totalModuleTypeCount[moduleType] += 1
diff --git a/bp2build/ndk_library_conversion_test.go b/bp2build/ndk_library_conversion_test.go
new file mode 100644
index 0000000..244ce20
--- /dev/null
+++ b/bp2build/ndk_library_conversion_test.go
@@ -0,0 +1,77 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/cc"
+)
+
+func TestNdkLibraryContributionSymbolFile(t *testing.T) {
+ bp := `
+ ndk_library {
+ name: "libfoo",
+ symbol_file: "libfoo.map.txt",
+ }
+ `
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_contribution",
+ "libfoo.ndk.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "api_surfaces": `["publicapi"]`,
+ "library_name": `"libfoo"`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+}
+
+func TestNdkLibraryContributionHeaders(t *testing.T) {
+ bp := `
+ ndk_library {
+ name: "libfoo",
+ symbol_file: "libfoo.map.txt",
+ export_header_libs: ["libfoo_headers"],
+ }
+ `
+ fs := map[string]string{
+ "header_directory/Android.bp": `
+ ndk_headers {
+ name: "libfoo_headers",
+ }
+ `,
+ }
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_contribution",
+ "libfoo.ndk.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "api_surfaces": `["publicapi"]`,
+ "library_name": `"libfoo"`,
+ "hdrs": `["//header_directory:libfoo_headers.contribution"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ Filesystem: fs,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 8ce8bb2..c2c1b19 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -30,13 +30,6 @@
)
var (
- // A default configuration for tests to not have to specify bp2build_available on top level targets.
- bp2buildConfig = android.NewBp2BuildAllowlist().SetDefaultConfig(
- allowlists.Bp2BuildConfig{
- android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
- },
- )
-
buildDir string
)
@@ -87,6 +80,11 @@
// An error with a string contained within the string of the expected error
ExpectedErr error
UnconvertedDepsMode unconvertedDepsMode
+
+ // For every directory listed here, the BUILD file for that directory will
+ // be merged with the generated BUILD file. This allows custom BUILD targets
+ // to be used in tests, or use BUILD files to draw package boundaries.
+ KeepBuildFileForDirs []string
}
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
@@ -107,6 +105,18 @@
registerModuleTypes(ctx)
ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
+
+ // A default configuration for tests to not have to specify bp2build_available on top level targets.
+ bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
+ allowlists.Bp2BuildConfig{
+ android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ )
+ for _, f := range tc.KeepBuildFileForDirs {
+ bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
+ f: /*recursive=*/ false,
+ })
+ }
ctx.RegisterBp2BuildConfig(bp2buildConfig)
ctx.RegisterForBazelConversion()
diff --git a/cc/Android.bp b/cc/Android.bp
index 91a3fb0..8860f78 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -45,6 +45,7 @@
"snapshot_utils.go",
"stl.go",
"strip.go",
+ "sysprop.go",
"tidy.go",
"util.go",
"vendor_snapshot.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 95ac598..9b85ec4 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -28,14 +28,15 @@
)
const (
- cSrcPartition = "c"
- asSrcPartition = "as"
- asmSrcPartition = "asm"
- lSrcPartition = "l"
- llSrcPartition = "ll"
- cppSrcPartition = "cpp"
- protoSrcPartition = "proto"
- aidlSrcPartition = "aidl"
+ cSrcPartition = "c"
+ asSrcPartition = "as"
+ asmSrcPartition = "asm"
+ lSrcPartition = "l"
+ llSrcPartition = "ll"
+ cppSrcPartition = "cpp"
+ protoSrcPartition = "proto"
+ aidlSrcPartition = "aidl"
+ syspropSrcPartition = "sysprop"
stubsSuffix = "_stub_libs_current"
)
@@ -104,7 +105,8 @@
llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}},
// 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},
+ cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+ syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}},
}
return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
@@ -320,6 +322,9 @@
llSrcs bazel.LabelListAttribute
lexopts bazel.StringListAttribute
+ // Sysprop sources
+ syspropSrcs bazel.LabelListAttribute
+
hdrs bazel.LabelListAttribute
rtti bazel.BoolAttribute
@@ -482,6 +487,7 @@
ca.asmSrcs = partitionedSrcs[asmSrcPartition]
ca.lSrcs = partitionedSrcs[lSrcPartition]
ca.llSrcs = partitionedSrcs[llSrcPartition]
+ ca.syspropSrcs = partitionedSrcs[syspropSrcPartition]
ca.absoluteIncludes.DeduplicateAxesFromBase()
ca.localIncludes.DeduplicateAxesFromBase()
@@ -719,7 +725,7 @@
(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
- aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs)
+ aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs)
if aidlDep != nil {
if lib, ok := module.linker.(*libraryDecorator); ok {
if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
@@ -734,6 +740,10 @@
(&compilerAttrs).srcs.Add(&convertedLSrcs.srcName)
(&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName)
+ if !compilerAttrs.syspropSrcs.IsEmpty() {
+ (&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs))
+ }
+
features := compilerAttrs.features.Clone().Append(linkerAttrs.features)
features.DeduplicateAxesFromBase()
@@ -750,6 +760,7 @@
ctx android.Bp2buildMutatorContext,
m *Module,
aidlLabelList bazel.LabelListAttribute,
+ linkerAttrs linkerAttributes,
) *bazel.LabelAttribute {
if !aidlLabelList.IsEmpty() {
aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
@@ -777,6 +788,16 @@
if !aidlLibs.IsEmpty() {
ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+ // Since cc_aidl_library only needs the dynamic deps (aka shared libs) from the parent cc library for compiling,
+ // we err on the side of not re-exporting the headers of the dynamic deps from cc_aidl_lirary
+ // because the parent cc library already has all the dynamic deps
+ implementationDynamicDeps := bazel.MakeLabelListAttribute(
+ bazel.AppendBazelLabelLists(
+ linkerAttrs.dynamicDeps.Value,
+ linkerAttrs.implementationDynamicDeps.Value,
+ ),
+ )
+
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "cc_aidl_library",
@@ -784,7 +805,8 @@
},
android.CommonAttributes{Name: ccAidlLibrarylabel},
&ccAidlLibraryAttributes{
- Deps: aidlLibs,
+ Deps: aidlLibs,
+ Implementation_dynamic_deps: implementationDynamicDeps,
},
)
label := &bazel.LabelAttribute{
@@ -1208,10 +1230,14 @@
return exported
}
+func BazelLabelNameForStaticModule(baseLabel string) string {
+ return baseLabel + "_bp2build_cc_library_static"
+}
+
func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := android.BazelModuleLabel(ctx, m)
if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(m.Name()) {
- label += "_bp2build_cc_library_static"
+ return BazelLabelNameForStaticModule(label)
}
return label
}
diff --git a/cc/cc.go b/cc/cc.go
index d42ab6d..1c845f6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3650,6 +3650,7 @@
sharedLibrary
headerLibrary
testBin // testBinary already declared
+ ndkLibrary
)
func (c *Module) typ() moduleType {
@@ -3686,6 +3687,8 @@
return staticLibrary
}
return sharedLibrary
+ } else if c.isNDKStubLibrary() {
+ return ndkLibrary
}
return unknownType
}
@@ -3726,6 +3729,8 @@
} else {
sharedOrStaticLibraryBp2Build(ctx, c, false)
}
+ case ndkLibrary:
+ ndkLibraryBp2build(ctx, c)
}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 5d569cc..01ac133 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4386,3 +4386,93 @@
})
}
}
+
+func TestCcBuildBrokenClangAsFlags(t *testing.T) {
+ tests := []struct {
+ name string
+ clangAsFlags []string
+ BuildBrokenClangAsFlags bool
+ err string
+ }{
+ {
+ name: "error when clang_asflags is set",
+ clangAsFlags: []string{"-a", "-b"},
+ err: "clang_asflags: property is deprecated",
+ },
+ {
+ name: "no error when BuildBrokenClangAsFlags is explicitly set to true",
+ clangAsFlags: []string{"-a", "-b"},
+ BuildBrokenClangAsFlags: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ cc_library {
+ name: "foo",
+ clang_asflags: %s,
+ }`, `["`+strings.Join(test.clangAsFlags, `","`)+`"]`)
+
+ if test.err == "" {
+ android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if test.BuildBrokenClangAsFlags {
+ variables.BuildBrokenClangAsFlags = test.BuildBrokenClangAsFlags
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ } else {
+ prepareForCcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
+ RunTestWithBp(t, bp)
+ }
+ })
+ }
+}
+
+func TestCcBuildBrokenClangCFlags(t *testing.T) {
+ tests := []struct {
+ name string
+ clangCFlags []string
+ BuildBrokenClangCFlags bool
+ err string
+ }{
+ {
+ name: "error when clang_cflags is set",
+ clangCFlags: []string{"-a", "-b"},
+ err: "clang_cflags: property is deprecated",
+ },
+ {
+ name: "no error when BuildBrokenClangCFlags is explicitly set to true",
+ clangCFlags: []string{"-a", "-b"},
+ BuildBrokenClangCFlags: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ cc_library {
+ name: "foo",
+ clang_cflags: %s,
+ }`, `["`+strings.Join(test.clangCFlags, `","`)+`"]`)
+
+ if test.err == "" {
+ android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if test.BuildBrokenClangCFlags {
+ variables.BuildBrokenClangCFlags = test.BuildBrokenClangCFlags
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ } else {
+ prepareForCcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
+ RunTestWithBp(t, bp)
+ }
+ })
+ }
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index f9f7b6f..a751754 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -441,12 +441,24 @@
// TODO: debug
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Release.Cflags)...)
- CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
- CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+ if !ctx.DeviceConfig().BuildBrokenClangCFlags() && len(compiler.Properties.Clang_cflags) != 0 {
+ ctx.PropertyErrorf("clang_cflags", "property is deprecated, see Changes.md file")
+ } else {
+ CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+ }
+ if !ctx.DeviceConfig().BuildBrokenClangAsFlags() && len(compiler.Properties.Clang_asflags) != 0 {
+ ctx.PropertyErrorf("clang_asflags", "property is deprecated, see Changes.md file")
+ } else {
+ CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+ }
flags.Local.CFlags = config.ClangFilterUnknownCflags(flags.Local.CFlags)
- flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Clang_cflags)...)
- flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+ if !ctx.DeviceConfig().BuildBrokenClangCFlags() {
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Clang_cflags)...)
+ }
+ if !ctx.DeviceConfig().BuildBrokenClangAsFlags() {
+ flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+ }
flags.Local.CppFlags = config.ClangFilterUnknownCflags(flags.Local.CppFlags)
flags.Local.ConlyFlags = config.ClangFilterUnknownCflags(flags.Local.ConlyFlags)
flags.Local.LdFlags = config.ClangFilterUnknownCflags(flags.Local.LdFlags)
diff --git a/cc/gen.go b/cc/gen.go
index 08b49c9..dfbb177 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -229,6 +229,34 @@
return cppFile, headers.Paths()
}
+func bp2buildCcSysprop(ctx android.Bp2buildMutatorContext, moduleName string, minSdkVersion *string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
+ labels := SyspropLibraryLabels{
+ SyspropLibraryLabel: moduleName + "_sysprop_library",
+ StaticLibraryLabel: moduleName + "_cc_sysprop_library_static",
+ }
+ Bp2buildSysprop(ctx, labels, srcs, minSdkVersion)
+ return createLabelAttributeCorrespondingToSrcs(":"+labels.StaticLibraryLabel, srcs)
+}
+
+// Creates a LabelAttribute for a given label where the value is only set for
+// the same config values that have values in a given LabelListAttribute
+func createLabelAttributeCorrespondingToSrcs(baseLabelName string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
+ baseLabel := bazel.Label{Label: baseLabelName}
+ label := bazel.LabelAttribute{}
+ if !srcs.Value.IsNil() && !srcs.Value.IsEmpty() {
+ label.Value = &baseLabel
+ return &label
+ }
+ for axis, configToSrcs := range srcs.ConfigurableValues {
+ for config, val := range configToSrcs {
+ if !val.IsNil() && !val.IsEmpty() {
+ label.SetSelectValue(axis, config, baseLabel)
+ }
+ }
+ }
+ return &label
+}
+
// Used to communicate information from the genSources method back to the library code that uses
// it.
type generatedSourceInfo struct {
diff --git a/cc/library.go b/cc/library.go
index 83a2c68..441eb79 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -276,7 +276,8 @@
}
type ccAidlLibraryAttributes struct {
- Deps bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Implementation_dynamic_deps bazel.LabelListAttribute
}
type stripAttributes struct {
@@ -2704,6 +2705,7 @@
modType = "cc_library_static"
} else {
modType = "cc_library_shared"
+ createStubsBazelTargetIfNeeded(ctx, module, compilerAttrs, exportedIncludes, baseAttributes)
}
props := bazel.BazelTargetModuleProperties{
Rule_class: modType,
@@ -2711,8 +2713,6 @@
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
-
- createStubsBazelTargetIfNeeded(ctx, module, compilerAttrs, exportedIncludes, baseAttributes)
}
// TODO(b/199902614): Can this be factored to share with the other Attributes?
diff --git a/cc/lto.go b/cc/lto.go
index b3e5e74..581856b 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -15,9 +15,9 @@
package cc
import (
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
// LTO (link-time optimization) allows the compiler to optimize and generate
@@ -49,9 +49,12 @@
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
- FullDep bool `blueprint:"mutated"`
- ThinDep bool `blueprint:"mutated"`
- NoLtoDep bool `blueprint:"mutated"`
+ FullEnabled bool `blueprint:"mutated"`
+ ThinEnabled bool `blueprint:"mutated"`
+ NoLtoEnabled bool `blueprint:"mutated"`
+ FullDep bool `blueprint:"mutated"`
+ ThinDep bool `blueprint:"mutated"`
+ NoLtoDep bool `blueprint:"mutated"`
// Use clang lld instead of gnu ld.
Use_clang_lld *bool
@@ -70,7 +73,7 @@
func (lto *lto) begin(ctx BaseModuleContext) {
if ctx.Config().IsEnvTrue("DISABLE_LTO") {
- lto.Properties.Lto.Never = proptools.BoolPtr(true)
+ lto.Properties.NoLtoEnabled = true
}
}
@@ -151,15 +154,15 @@
}
func (lto *lto) FullLTO() bool {
- return lto != nil && Bool(lto.Properties.Lto.Full)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Full) || lto.Properties.FullEnabled)
}
func (lto *lto) ThinLTO() bool {
- return lto != nil && Bool(lto.Properties.Lto.Thin)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Thin) || lto.Properties.ThinEnabled)
}
func (lto *lto) Never() bool {
- return lto != nil && Bool(lto.Properties.Lto.Never)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Never) || lto.Properties.NoLtoEnabled)
}
func GlobalThinLTO(ctx android.BaseModuleContext) bool {
@@ -255,13 +258,13 @@
// LTO properties for dependencies
if name == "lto-full" {
- variation.lto.Properties.Lto.Full = proptools.BoolPtr(true)
+ variation.lto.Properties.FullEnabled = true
}
if name == "lto-thin" {
- variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true)
+ variation.lto.Properties.ThinEnabled = true
}
if name == "lto-none" {
- variation.lto.Properties.Lto.Never = proptools.BoolPtr(true)
+ variation.lto.Properties.NoLtoEnabled = true
}
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 5e06948..08e2a39 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -147,16 +147,6 @@
}
}
-const (
- apiContributionSuffix = ".contribution"
-)
-
-// apiContributionTargetName returns the name of the cc_api(headers|contribution) bp2build target of ndk modules
-// A suffix is necessary to prevent a name collision with the base ndk_(library|header) target in the same bp2build bazel package
-func apiContributionTargetName(moduleName string) string {
- return moduleName + apiContributionSuffix
-}
-
// TODO(b/243196151): Populate `system` and `arch` metadata
type bazelCcApiHeadersAttributes struct {
Hdrs bazel.LabelListAttribute
@@ -179,7 +169,7 @@
Include_dir: include_dir,
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: apiContributionTargetName(ctx.ModuleName()),
+ Name: android.ApiContributionTargetName(ctx.ModuleName()),
}, attrs)
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index e2b9682..06ded3f 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,6 +25,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/cc/config"
)
@@ -568,5 +569,43 @@
func NdkLibraryFactory() android.Module {
module := newStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
+ android.InitBazelModule(module)
return module
}
+
+type bazelCcApiContributionAttributes struct {
+ Api bazel.LabelAttribute
+ Api_surfaces bazel.StringListAttribute
+ Hdrs bazel.LabelListAttribute
+ Library_name string
+}
+
+// Names of the cc_api_header targets in the bp2build workspace
+func (s *stubDecorator) apiHeaderLabels(ctx android.TopDownMutatorContext) bazel.LabelList {
+ addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string {
+ label := android.BazelModuleLabel(ctx, module)
+ return android.ApiContributionTargetName(label)
+ }
+ return android.BazelLabelForModuleDepsWithFn(ctx, s.properties.Export_header_libs, addSuffix)
+}
+
+func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_contribution",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ stubLibrary := m.compiler.(*stubDecorator)
+ attrs := &bazelCcApiContributionAttributes{
+ Library_name: stubLibrary.implementationModuleName(m.Name()),
+ Api_surfaces: bazel.MakeStringListAttribute(
+ []string{android.PublicApi.String()}),
+ }
+ if symbolFile := stubLibrary.properties.Symbol_file; symbolFile != nil {
+ apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label
+ attrs.Api = *bazel.MakeLabelAttribute(apiLabel)
+ }
+ apiHeaders := stubLibrary.apiHeaderLabels(ctx)
+ attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders)
+ apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName())
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs)
+}
diff --git a/cc/sysprop.go b/cc/sysprop.go
new file mode 100644
index 0000000..2b1e354
--- /dev/null
+++ b/cc/sysprop.go
@@ -0,0 +1,71 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+)
+
+// TODO(b/240463568): Additional properties will be added for API validation
+type bazelSyspropLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+}
+
+type bazelCcSyspropLibraryAttributes struct {
+ Dep bazel.LabelAttribute
+ Min_sdk_version *string
+}
+
+type SyspropLibraryLabels struct {
+ SyspropLibraryLabel string
+ SharedLibraryLabel string
+ StaticLibraryLabel string
+}
+
+func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "sysprop_library",
+ Bzl_load_location: "//build/bazel/rules/sysprop:sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.SyspropLibraryLabel},
+ &bazelSyspropLibraryAttributes{
+ Srcs: srcs,
+ })
+
+ attrs := &bazelCcSyspropLibraryAttributes{
+ Dep: *bazel.MakeLabelAttribute(":" + labels.SyspropLibraryLabel),
+ Min_sdk_version: minSdkVersion,
+ }
+
+ if labels.SharedLibraryLabel != "" {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_sysprop_library_shared",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.SharedLibraryLabel},
+ attrs)
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_sysprop_library_static",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.StaticLibraryLabel},
+ attrs)
+}
diff --git a/cmd/zip2zip/BUILD.bazel b/cmd/zip2zip/BUILD.bazel
new file mode 100644
index 0000000..1915a2d
--- /dev/null
+++ b/cmd/zip2zip/BUILD.bazel
@@ -0,0 +1,18 @@
+# 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/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 7520f58..362a8ef 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -678,9 +678,10 @@
Filename_from_src bazel.BoolAttribute
}
-// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
-// All prebuilt_* modules are PrebuiltEtc, which we treat uniformily as *PrebuiltFile*
-func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+// Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion
+// of prebuilt_* modules. bazelPrebuiltFileAttributes has the common attributes
+// used by both prebuilt_etc_xml and other prebuilt_* moodules
+func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) *bazelPrebuiltFileAttributes {
var src bazel.LabelAttribute
for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
for config, p := range configToProps {
@@ -727,10 +728,6 @@
}
var dir = module.installDirBase
- // prebuilt_file supports only `etc` or `usr/share`
- if !(dir == "etc" || dir == "usr/share") {
- return
- }
if subDir := module.subdirProperties.Sub_dir; subDir != nil {
dir = dir + "/" + *subDir
}
@@ -752,6 +749,22 @@
attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
}
+ return attrs
+
+}
+
+// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
+// prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc,
+// which we treat as *PrebuiltFile*
+func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ var dir = module.installDirBase
+ // prebuilt_file supports only `etc` or `usr/share`
+ if !(dir == "etc" || dir == "usr/share") {
+ return
+ }
+
+ attrs := module.Bp2buildHelper(ctx)
+
props := bazel.BazelTargetModuleProperties{
Rule_class: "prebuilt_file",
Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 7a0dac3..d4ed363 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -909,12 +909,7 @@
cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
}
-
- genDir := "$(GENDIR)"
- if t := ctx.ModuleType(); t == "cc_genrule" || t == "java_genrule" || t == "java_genrule_host" {
- genDir = "$(RULEDIR)"
- }
- cmd = strings.Replace(cmd, "$(genDir)", genDir, -1)
+ cmd = strings.Replace(cmd, "$(genDir)", "$(RULEDIR)", -1)
if len(tools.Value.Includes) > 0 {
cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Value.Includes[0].Label), -1)
cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Value.Includes[0].Label), -1)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index cd941cc..63f8fa9 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -790,6 +790,94 @@
result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
}
+func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: ["baz/baz.proto", "bar.proto"],
+ }
+ `),
+ "package-dir/Android.bp": []byte(`
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.proto",
+ ":external-protos",
+ ],
+ output_extension: "proto.h",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/package-dir/src/foo.proto.h",
+ exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
+func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
+ bp := `
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ ":external-protos",
+ ],
+ output_extension: "proto.h",
+ }
+ `
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: ["foo/foo.proto", "bar.proto"],
+ }
+ `),
+ }),
+ ).RunTestWithBp(t, bp)
+
+ exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
func TestPrebuiltTool(t *testing.T) {
testcases := []struct {
name string
diff --git a/java/Android.bp b/java/Android.bp
index 9df4ab4..8510e04 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -64,6 +64,7 @@
"plugin.go",
"prebuilt_apis.go",
"proto.go",
+ "resourceshrinker.go",
"robolectric.go",
"rro.go",
"sdk.go",
diff --git a/java/aapt2.go b/java/aapt2.go
index 5346ddf..7845a0b 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -256,17 +256,21 @@
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
+ Command: `${config.Aapt2Cmd} convert --output-format $format $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
- })
+ }, "format",
+)
// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto
// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
-func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
+func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path, format string) {
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,
Input: in,
Output: out,
- Description: "convert to proto",
+ Description: "convert to " + format,
+ Args: map[string]string{
+ "format": format,
+ },
})
}
diff --git a/java/app.go b/java/app.go
index b8edf37..1955e2a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -689,10 +689,9 @@
if lineage := String(a.overridableAppProperties.Lineage); lineage != "" {
lineageFile = android.PathForModuleSrc(ctx, lineage)
}
-
rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
+ CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, Bool(a.dexProperties.Optimize.Shrink_resources))
a.outputFile = packageFile
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -721,7 +720,7 @@
if v4SigningRequested {
v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
}
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, false)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
diff --git a/java/app_builder.go b/java/app_builder.go
index 18a9751..d20a6bf 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -52,7 +52,7 @@
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string, shrinkResources bool) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -65,7 +65,6 @@
if jniJarFile != nil {
inputs = append(inputs, jniJarFile)
}
-
ctx.Build(pctx, android.BuildParams{
Rule: combineApk,
Inputs: inputs,
@@ -73,6 +72,11 @@
Implicits: deps,
})
+ if shrinkResources {
+ shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
+ ShrinkResources(ctx, unsignedApk, shrunkenApk)
+ unsignedApk = shrunkenApk
+ }
SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
}
@@ -84,7 +88,6 @@
certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
deps = append(deps, c.Pem, c.Key)
}
-
outputFiles := android.WritablePaths{signedApk}
var flags []string
if v4SignatureFile != nil {
@@ -182,7 +185,7 @@
packageFile, jniJarFile, dexJarFile android.Path) {
protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
- aapt2Convert(ctx, protoResJarFile, packageFile)
+ aapt2Convert(ctx, protoResJarFile, packageFile, "proto")
var zips android.Paths
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 8e1e565..f5b5f99 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -257,7 +257,7 @@
// Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the
// module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a
// versioned sdk.
- produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
+ 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.
@@ -759,7 +759,7 @@
// Delegate the production of the hidden API all-flags.csv file to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- output := common.produceHiddenAPIOutput(ctx, contents, input)
+ output := common.produceHiddenAPIOutput(ctx, contents, fragments, input)
// If the source or prebuilts module does not provide a signature patterns file then generate one
// from the flags.
@@ -767,7 +767,7 @@
// their own.
if output.SignaturePatternsPath == nil {
output.SignaturePatternsPath = buildRuleSignaturePatternsFile(
- ctx, output.AllFlagsPath, []string{"*"}, nil, nil)
+ ctx, output.AllFlagsPath, []string{"*"}, nil, nil, "")
}
// Initialize a HiddenAPIInfo structure.
@@ -841,12 +841,12 @@
return b.testFragment
}
-// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
-// for the fragment as well as encoding the flags in the boot dex jars.
-func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+// generateHiddenApiFlagRules generates rules to generate hidden API flags and compute the signature
+// patterns file.
+func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput {
// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
// paths to the created files.
- output := hiddenAPIRulesForBootclasspathFragment(ctx, contents, input)
+ flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix)
// If the module specifies split_packages or package_prefixes then use those to generate the
// signature patterns.
@@ -854,8 +854,8 @@
packagePrefixes := input.PackagePrefixes
singlePackages := input.SinglePackages
if splitPackages != nil || packagePrefixes != nil || singlePackages != nil {
- output.SignaturePatternsPath = buildRuleSignaturePatternsFile(
- ctx, output.AllFlagsPath, splitPackages, packagePrefixes, singlePackages)
+ flagOutput.SignaturePatternsPath = buildRuleSignaturePatternsFile(
+ ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages, suffix)
} else if !b.isTestFragment() {
ctx.ModuleErrorf(`Must specify at least one of the split_packages, package_prefixes and single_packages properties
If this is a new bootclasspath_fragment or you are unsure what to do add the
@@ -867,6 +867,68 @@
should specify here. If you are happy with its suggestions then you can add
the --fix option and it will fix them for you.`, b.BaseModuleName())
}
+ return flagOutput
+}
+
+// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
+// for the fragment as well as encoding the flags in the boot dex jars.
+func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+ // Gather information about the boot dex files for the boot libraries provided by this fragment.
+ bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
+
+ // Generate the flag file needed to encode into the dex files.
+ flagOutput := b.generateHiddenApiFlagRules(ctx, contents, input, bootDexInfoByModule, "")
+
+ // Encode those flags into the dex files of the contents of this fragment.
+ encodedBootDexFilesByModule := hiddenAPIEncodeRulesForBootclasspathFragment(ctx, bootDexInfoByModule, flagOutput.AllFlagsPath)
+
+ // Store that information for return for use by other rules.
+ output := &HiddenAPIOutput{
+ HiddenAPIFlagOutput: flagOutput,
+ EncodedBootDexFilesByModule: encodedBootDexFilesByModule,
+ }
+
+ // Get the ApiLevel associated with SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE, defaulting to current
+ // if not set.
+ config := ctx.Config()
+ targetApiLevel := android.ApiLevelOrPanic(ctx,
+ config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "current"))
+
+ // Filter the contents list to remove any modules that do not support the target build release.
+ // The current build release supports all the modules.
+ contentsForSdkSnapshot := []android.Module{}
+ for _, module := range contents {
+ // If the module has a min_sdk_version that is higher than the target build release then it will
+ // not work on the target build release and so must not be included in the sdk snapshot.
+ minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module)
+ if minApiLevel.GreaterThan(targetApiLevel) {
+ continue
+ }
+
+ contentsForSdkSnapshot = append(contentsForSdkSnapshot, module)
+ }
+
+ var flagFilesByCategory FlagFilesByCategory
+ if len(contentsForSdkSnapshot) != len(contents) {
+ // The sdk snapshot has different contents to the runtime fragment so it is not possible to
+ // reuse the hidden API information generated for the fragment. So, recompute that information
+ // for the sdk snapshot.
+ filteredInput := b.createHiddenAPIFlagInput(ctx, contentsForSdkSnapshot, fragments)
+
+ // Gather information about the boot dex files for the boot libraries provided by this fragment.
+ filteredBootDexInfoByModule := extractBootDexInfoFromModules(ctx, contentsForSdkSnapshot)
+ flagOutput = b.generateHiddenApiFlagRules(ctx, contentsForSdkSnapshot, filteredInput, filteredBootDexInfoByModule, "-for-sdk-snapshot")
+ flagFilesByCategory = filteredInput.FlagFilesByCategory
+ } else {
+ // The sdk snapshot has the same contents as the runtime fragment so reuse that information.
+ flagFilesByCategory = input.FlagFilesByCategory
+ }
+
+ // Make the information available for the sdk snapshot.
+ ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
+ FlagFilesByCategory: flagFilesByCategory,
+ HiddenAPIFlagOutput: flagOutput,
+ })
return output
}
@@ -1032,7 +1094,7 @@
// Get the hidden API information from the module.
mctx := ctx.SdkModuleContext()
- hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk)
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
// Copy all the generated file paths.
@@ -1174,7 +1236,7 @@
}
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
if src == nil {
return defaultPath
diff --git a/java/config/config.go b/java/config/config.go
index 03288fe..ea44aaa 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -165,6 +165,7 @@
pctx.HostBinToolVariable("ApiCheckCmd", "apicheck")
pctx.HostBinToolVariable("D8Cmd", "d8")
pctx.HostBinToolVariable("R8Cmd", "r8")
+ pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker")
pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi")
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {
diff --git a/java/dex.go b/java/dex.go
index a44d792..de36b18 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -63,6 +63,8 @@
// classes referenced by the app manifest. Defaults to false.
No_aapt_flags *bool
+ Shrink_resources *bool
+
// Flags to pass to proguard.
Proguard_flags []string
@@ -200,6 +202,16 @@
"--verbose")
}
+ // Supplying the platform build flag disables various features like API modeling and desugaring.
+ // For targets with a stable min SDK version (i.e., when the min SDK is both explicitly specified
+ // and managed+versioned), we suppress this flag to ensure portability.
+ // Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
+ // services.jar), are not classified as stable, which is WAI.
+ // TODO(b/232073181): Expand to additional min SDK cases after validation.
+ if !minSdkVersion.Stable() {
+ flags = append(flags, "--android-platform-build")
+ }
+
effectiveVersion, err := minSdkVersion.EffectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
diff --git a/java/dex_test.go b/java/dex_test.go
index a3e2ded..6617873 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -30,6 +30,19 @@
platform_apis: true,
}
+ android_app {
+ name: "stable_app",
+ srcs: ["foo.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ }
+
+ android_app {
+ name: "core_platform_app",
+ srcs: ["foo.java"],
+ sdk_version: "core_platform",
+ }
+
java_library {
name: "lib",
srcs: ["foo.java"],
@@ -42,11 +55,15 @@
`)
app := result.ModuleForTests("app", "android_common")
+ stableApp := result.ModuleForTests("stable_app", "android_common")
+ corePlatformApp := result.ModuleForTests("core_platform_app", "android_common")
lib := result.ModuleForTests("lib", "android_common")
staticLib := result.ModuleForTests("static_lib", "android_common")
appJavac := app.Rule("javac")
appR8 := app.Rule("r8")
+ stableAppR8 := stableApp.Rule("r8")
+ corePlatformAppR8 := corePlatformApp.Rule("r8")
libHeader := lib.Output("turbine-combined/lib.jar").Output
staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
@@ -61,6 +78,12 @@
appR8.Args["r8Flags"], staticLibHeader.String())
android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
appR8.Args["r8Flags"], "-ignorewarnings")
+ android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
+ appR8.Args["r8Flags"], "--android-platform-build")
+ android.AssertStringDoesNotContain(t, "expected no --android-platform-build in stable_app r8 flags",
+ stableAppR8.Args["r8Flags"], "--android-platform-build")
+ android.AssertStringDoesContain(t, "expected --android-platform-build in core_platform_app r8 flags",
+ corePlatformAppR8.Args["r8Flags"], "--android-platform-build")
}
func TestR8Flags(t *testing.T) {
@@ -88,7 +111,8 @@
appR8.Args["r8Flags"], "-dontobfuscate")
android.AssertStringDoesNotContain(t, "expected no -ignorewarnings in app r8 flags",
appR8.Args["r8Flags"], "-ignorewarnings")
-
+ android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
+ appR8.Args["r8Flags"], "--android-platform-build")
}
func TestD8(t *testing.T) {
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 7b67803..5474ae1 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -594,6 +594,23 @@
var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
+// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
+// by the sdk snapshot.
+//
+// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
+// processing.
+type HiddenAPIInfoForSdk struct {
+ // FlagFilesByCategory maps from the flag file category to the paths containing information for
+ // that category.
+ FlagFilesByCategory FlagFilesByCategory
+
+ // The output from the hidden API processing needs to be made available to other modules.
+ HiddenAPIFlagOutput
+}
+
+// Provides hidden API info for the sdk snapshot.
+var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
+
// ModuleStubDexJars contains the stub dex jars provided by a single module.
//
// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
@@ -1024,8 +1041,11 @@
// patterns that will select a subset of the monolithic flags.
func buildRuleSignaturePatternsFile(
ctx android.ModuleContext, flagsPath android.Path,
- splitPackages []string, packagePrefixes []string, singlePackages []string) android.Path {
- patternsFile := android.PathForModuleOut(ctx, "modular-hiddenapi", "signature-patterns.csv")
+ splitPackages []string, packagePrefixes []string, singlePackages []string,
+ suffix string) android.Path {
+ hiddenApiSubDir := "modular-hiddenapi" + suffix
+
+ patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
// Create a rule to validate the output from the following rule.
rule := android.NewRuleBuilder(pctx, ctx)
@@ -1042,7 +1062,7 @@
FlagForEachArg("--package-prefix ", packagePrefixes).
FlagForEachArg("--single-package ", singlePackages).
FlagWithOutput("--output ", patternsFile)
- rule.Build("hiddenAPISignaturePatterns", "hidden API signature patterns")
+ rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
return patternsFile
}
@@ -1116,8 +1136,8 @@
return validFile
}
-// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
-// bootclasspath and then encode the flags into the boot dex files.
+// hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the
+// bootclasspath.
//
// It takes:
// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
@@ -1130,31 +1150,27 @@
// * metadata.csv
// * index.csv
// * all-flags.csv
-// * encoded boot dex files
-func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
- hiddenApiSubDir := "modular-hiddenapi"
-
- // Gather information about the boot dex files for the boot libraries provided by this fragment.
- bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
+func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
+ hiddenApiSubDir := "modular-hiddenapi" + suffix
// Generate the stub-flags.csv.
stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
- buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
// Extract the classes jars from the contents.
classesJars := extractClassesJarsFromModules(contents)
// Generate the set of flags from the annotations in the source code.
annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
- buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
+ buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
// Generate the metadata from the annotations in the source code.
metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
- buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
+ buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
// Generate the index file from the CSV files in the classes jars.
indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
- buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
+ buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
// Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
// containing dex signatures of all the removed APIs. In the monolithic files that is done by
@@ -1162,15 +1178,44 @@
// signatures, see the combined-removed-dex module. This does that automatically by using the
// *removed.txt files retrieved from the java_sdk_library modules that are specified in the
// stub_libs and contents properties of a bootclasspath_fragment.
- removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
+ removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
// files.
allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
- buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
+ // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
+ // compared against the monolithic stub flags.
+ filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
+ "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
+ HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
+
+ // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
+ // against the monolithic flags.
+ filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
+ "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
+ HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
+
+ // Store the paths in the info for use by other modules and sdk snapshot generation.
+ return HiddenAPIFlagOutput{
+ AnnotationFlagsPath: annotationFlagsCSV,
+ MetadataPath: metadataCSV,
+ IndexPath: indexCSV,
+ StubFlagsPath: stubFlagsCSV,
+ AllFlagsPath: allFlagsCSV,
+ FilteredStubFlagsPath: filteredStubFlagsCSV,
+ FilteredFlagsPath: filteredFlagsCSV,
+ }
+}
+
+// hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the
+// dex jars in bootDexInfoByModule.
+func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule {
// Encode the flags into the boot dex files.
- encodedBootDexJarsByModule := map[string]android.Path{}
+ encodedBootDexJarsByModule := bootDexJarByModule{}
outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
for _, name := range android.SortedStringKeys(bootDexInfoByModule) {
bootDexInfo := bootDexInfoByModule[name]
@@ -1178,43 +1223,15 @@
encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir)
encodedBootDexJarsByModule[name] = encodedDex
}
-
- // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
- // compared against the monolithic stub flags.
- filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
- buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags",
- "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV,
- HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
-
- // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
- // against the monolithic flags.
- filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
- buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags",
- "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV,
- HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
-
- // Store the paths in the info for use by other modules and sdk snapshot generation.
- output := HiddenAPIOutput{
- HiddenAPIFlagOutput: HiddenAPIFlagOutput{
- AnnotationFlagsPath: annotationFlagsCSV,
- MetadataPath: metadataCSV,
- IndexPath: indexCSV,
- StubFlagsPath: stubFlagsCSV,
- AllFlagsPath: allFlagsCSV,
- FilteredStubFlagsPath: filteredStubFlagsCSV,
- FilteredFlagsPath: filteredFlagsCSV,
- },
- EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
- }
- return &output
+ return encodedBootDexJarsByModule
}
-func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
+func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
if len(removedTxtFiles) == 0 {
return android.OptionalPath{}
}
- output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
+ output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
@@ -1222,7 +1239,7 @@
Flag("--no-banner").
Inputs(removedTxtFiles).
FlagWithOutput("--dex-api ", output)
- rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
+ rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
return android.OptionalPathForPath(output)
}
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 01e7e6e..bff7221 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -91,6 +91,7 @@
--warning_check StringFormatInvalid # 148 occurences in 11 modules
--warning_check StringFormatMatches # 4800 occurences in 30 modules
--warning_check UnknownId # 8 occurences in 7 modules
+--warning_check UnspecifiedImmutableFlag
--warning_check ValidFragment # 12 occurences in 5 modules
--warning_check ValidRestrictions # 5 occurences in 1 modules
--warning_check WebViewLayout # 3 occurences in 1 modules
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 9449707..c6acd55 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -255,12 +255,11 @@
if p.properties.Extensions_dir != nil {
extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
for k, v := range getLatest(extensionApiFiles) {
- if v.version > mctx.Config().PlatformBaseSdkExtensionVersion() {
- if _, exists := latest[k]; !exists {
- mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
- }
- latest[k] = v
+ if _, exists := latest[k]; !exists {
+ mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
}
+ // The extension version is always at least as new as the last sdk int version (potentially identical)
+ latest[k] = v
}
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 75422ad..2b84353 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -61,7 +61,7 @@
}
func TestPrebuiltApis_WithExtensions(t *testing.T) {
- runTestWithBaseExtensionLevel := func(v int) (foo_input string, bar_input string) {
+ runTestWithBaseExtensionLevel := func(v int) (foo_input, bar_input, baz_input string) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -69,7 +69,7 @@
}),
FixtureWithPrebuiltApisAndExtensions(map[string][]string{
"31": {"foo"},
- "32": {"foo", "bar"},
+ "32": {"foo", "bar", "baz"},
"current": {"foo", "bar"},
}, map[string][]string{
"1": {"foo"},
@@ -78,15 +78,24 @@
).RunTest(t)
foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+ baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String()
return
}
- // Here, the base extension level is 1, so extension level 2 is the latest
- foo_input, bar_input := runTestWithBaseExtensionLevel(1)
- android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
- android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ // Extension 2 is the latest for both foo and bar, finalized after the base extension version.
+ foo_input, bar_input, baz_input := runTestWithBaseExtensionLevel(1)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
- // Here, the base extension level is 2, so 2 is not later than 32.
- foo_input, bar_input = runTestWithBaseExtensionLevel(2)
- android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/foo.txt", foo_input)
- android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/bar.txt", bar_input)
+ // Extension 2 is the latest for both foo and bar, finalized together with 32
+ foo_input, bar_input, baz_input = runTestWithBaseExtensionLevel(2)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
+
+ // Extension 3 is the current extension, but it has not yet been finalized.
+ foo_input, bar_input, baz_input = runTestWithBaseExtensionLevel(3)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
}
diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go
new file mode 100644
index 0000000..6d59601
--- /dev/null
+++ b/java/resourceshrinker.go
@@ -0,0 +1,43 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
+ blueprint.RuleParams{
+ Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`,
+ CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
+ }, "raw_resources")
+
+func ShrinkResources(ctx android.ModuleContext, apk android.Path, outputFile android.WritablePath) {
+ protoFile := android.PathForModuleOut(ctx, apk.Base()+".proto.apk")
+ aapt2Convert(ctx, protoFile, apk, "proto")
+ strictModeFile := android.PathForSource(ctx, "prebuilts/cmdline-tools/shrinker.xml")
+ protoOut := android.PathForModuleOut(ctx, apk.Base()+".proto.out.apk")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: shrinkResources,
+ Input: protoFile,
+ Output: protoOut,
+ Args: map[string]string{
+ "raw_resources": strictModeFile.String(),
+ },
+ })
+ aapt2Convert(ctx, outputFile, protoOut, "binary")
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 8f499b1..d188133 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -539,7 +539,7 @@
}
// TODO: determines whether to create HTML doc or not
- //Html_doc *bool
+ // Html_doc *bool
}
// Paths to outputs from java_sdk_library and java_sdk_library_import.
@@ -1354,7 +1354,7 @@
// Provide additional information for inclusion in an sdk's generated .info file.
additionalSdkInfo := map[string]interface{}{}
additionalSdkInfo["dist_stem"] = module.distStem()
- baseModuleName := module.BaseModuleName()
+ baseModuleName := module.distStem()
scopes := map[string]interface{}{}
additionalSdkInfo["scopes"] = scopes
for scope, scopePaths := range module.scopePaths {
@@ -2904,6 +2904,18 @@
type sdkLibrarySdkMemberProperties struct {
android.SdkMemberPropertiesBase
+ // Stem name for files in the sdk snapshot.
+ //
+ // This is used to construct the path names of various sdk library files in the sdk snapshot to
+ // make sure that they match the finalized versions of those files in prebuilts/sdk.
+ //
+ // This property is marked as keep so that it will be kept in all instances of this struct, will
+ // not be cleared but will be copied to common structs. That is needed because this field is used
+ // to construct many file names for other parts of this struct and so it needs to be present in
+ // all structs. If it was not marked as keep then it would be cleared in some structs and so would
+ // be unavailable for generating file names if there were other properties that were still set.
+ Stem string `sdk:"keep"`
+
// Scope to per scope properties.
Scopes map[*apiScope]*scopeProperties
@@ -2965,6 +2977,9 @@
func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
sdk := variant.(*SdkLibrary)
+ // Copy the stem name for files in the sdk snapshot.
+ s.Stem = sdk.distStem()
+
s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range allApiScopes {
paths := sdk.findScopePaths(apiScope)
@@ -3017,6 +3032,8 @@
propertySet.AddProperty("permitted_packages", s.Permitted_packages)
}
+ stem := s.Stem
+
for _, apiScope := range allApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
@@ -3025,7 +3042,7 @@
var jars []string
for _, p := range properties.Jars {
- dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar")
+ dest := filepath.Join(scopeDir, stem+"-stubs.jar")
ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
jars = append(jars, dest)
}
@@ -3033,31 +3050,31 @@
if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") {
// Copy the stubs source jar into the snapshot zip as is.
- srcJarSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".srcjar")
+ srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar")
ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath)
scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath})
} else {
// Merge the stubs source jar into the snapshot zip so that when it is unpacked
// the source files are also unpacked.
- snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
+ snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources")
ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
}
if properties.CurrentApiFile != nil {
- currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(ctx.Name())
+ currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem)
ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
scopeSet.AddProperty("current_api", currentApiSnapshotPath)
}
if properties.RemovedApiFile != nil {
- removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(ctx.Name())
+ removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem)
ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
}
if properties.AnnotationsZip != nil {
- annotationsSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"_annotations.zip")
+ annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip")
ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath)
scopeSet.AddProperty("annotations", annotationsSnapshotPath)
}
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 75154f9..61b17bf 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -42,7 +42,7 @@
license_kind {
name: "SPDX-license-identifier-0BSD",
- conditions: ["unencumbered"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/0BSD",
}
@@ -933,7 +933,7 @@
license_kind {
name: "SPDX-license-identifier-MIT-0",
- conditions: ["notice"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/MIT-0.html",
}
diff --git a/python/Android.bp b/python/Android.bp
index e49fa6a..99c02bd 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -27,3 +27,15 @@
],
pluginFor: ["soong_build"],
}
+
+// We're transitioning all of these flags to be true by default.
+// This is a defaults flag that can be used to easily add all of them to
+// certain modules.
+python_defaults {
+ name: "modern_python_path_defaults",
+ dont_add_top_level_directories_to_path: true,
+ dont_add_entrypoint_folder_to_path: true,
+ proto: {
+ respect_pkg_path: true,
+ },
+}
diff --git a/python/binary.go b/python/binary.go
index af29bb6..e6324a3 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -116,6 +116,22 @@
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config *bool
+
+ // Currently, both the root of the zipfile and all the directories 1 level
+ // below that are added to the python path. When this flag is set to true,
+ // only the root of the zipfile will be added to the python path. This flag
+ // will be removed after all the python modules in the tree have been updated
+ // to support it. When using embedded_launcher: true, this is already the
+ // behavior. The default is currently false.
+ Dont_add_top_level_directories_to_path *bool
+
+ // Setting this to true will mimic Python 3.11+'s PYTHON_SAFE_PATH environment
+ // variable or -P flag, even on older python versions. This is a temporary
+ // flag while modules are changed to support it, eventually true will be the
+ // default and the flag will be removed. The default is currently false. It
+ // is only applicable when embedded_launcher is false, when embedded_launcher
+ // is true this is already implied.
+ Dont_add_entrypoint_folder_to_path *bool
}
type binaryDecorator struct {
@@ -128,10 +144,6 @@
IntermPathForModuleOut() android.OptionalPath
}
-var (
- StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt"
-)
-
func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
module := newModule(hod, android.MultilibFirst)
decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
@@ -180,9 +192,13 @@
})
}
+ addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, false)
+ dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, false)
+
binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
+ main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...),
+ addTopDirectoriesToPath, dontAddEntrypointFolderToPath)
return android.OptionalPathForPath(binFile)
}
diff --git a/python/builder.go b/python/builder.go
index 7d7239c..f7f9a99 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -20,7 +20,6 @@
"strings"
"android/soong/android"
-
"github.com/google/blueprint"
_ "github.com/google/blueprint/bootstrap"
)
@@ -44,13 +43,25 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
+ Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
`echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
- `$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` +
- `chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
- CommandDeps: []string{"$mergeParCmd"},
+ `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips && ` +
+ `chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix)`,
+ CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/stub_template_host.txt"},
},
- "interp", "main", "template", "stub", "srcsZips")
+ "interp", "main", "srcsZips", "addTopDirectoriesToPath")
+
+ hostParWithoutAddingEntrypointFolderToPath = pctx.AndroidStaticRule("hostParWithoutAddingEntrypointFolderToPath",
+ blueprint.RuleParams{
+ Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
+ "sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " +
+ "$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " +
+ `echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
+ `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips $out.entrypoint_zip && ` +
+ "chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)",
+ CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"},
+ },
+ "interp", "main", "srcsZips", "addTopDirectoriesToPath")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
@@ -58,7 +69,7 @@
`sed 's/ENTRY_POINT/$main/' build/soong/python/scripts/main.py >$out.main &&` +
`$mergeParCmd -p -pm $out.main --prefix $launcher $out $srcsZips && ` +
`chmod +x $out && rm -rf $out.main`,
- CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/main.py"},
+ CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/main.py"},
},
"main", "srcsZips", "launcher")
@@ -81,7 +92,7 @@
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
launcherPath android.OptionalPath, interpreter, main, binName string,
- srcsZips android.Paths) android.Path {
+ srcsZips android.Paths, addTopDirectoriesToPath bool, dontAddEntrypointFolderToPath bool) android.Path {
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
@@ -90,26 +101,37 @@
implicits := srcsZips
if !embeddedLauncher {
- // the path of stub_template_host.txt from source tree.
- template := android.PathForSource(ctx, StubTemplateHost)
- implicits = append(implicits, template)
-
- // intermediate output path for __main__.py
- stub := android.PathForModuleOut(ctx, mainFileName).String()
-
- ctx.Build(pctx, android.BuildParams{
- Rule: hostPar,
- Description: "host python archive",
- Output: binFile,
- Implicits: implicits,
- Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(main, "/", `\/`, -1),
- "template": template.String(),
- "stub": stub,
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- },
- })
+ addDirsString := "False"
+ if addTopDirectoriesToPath {
+ addDirsString = "True"
+ }
+ if dontAddEntrypointFolderToPath {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hostParWithoutAddingEntrypointFolderToPath,
+ Description: "host python archive",
+ Output: binFile,
+ Implicits: implicits,
+ Args: map[string]string{
+ "interp": strings.Replace(interpreter, "/", `\/`, -1),
+ "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
+ "srcsZips": strings.Join(srcsZips.Strings(), " "),
+ "addTopDirectoriesToPath": addDirsString,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hostPar,
+ Description: "host python archive",
+ Output: binFile,
+ Implicits: implicits,
+ Args: map[string]string{
+ "interp": strings.Replace(interpreter, "/", `\/`, -1),
+ "main": strings.Replace(main, "/", `\/`, -1),
+ "srcsZips": strings.Join(srcsZips.Strings(), " "),
+ "addTopDirectoriesToPath": addDirsString,
+ },
+ })
+ }
} else if launcherPath.Valid() {
// added launcherPath to the implicits Ninja dependencies.
implicits = append(implicits, launcherPath.Path())
diff --git a/python/defaults.go b/python/defaults.go
index dba23a7..c54e7d0 100644
--- a/python/defaults.go
+++ b/python/defaults.go
@@ -31,15 +31,12 @@
}
func defaultsFactory() android.Module {
- return DefaultsFactory()
-}
-
-func DefaultsFactory(props ...interface{}) android.Module {
module := &Defaults{}
- module.AddProperties(props...)
module.AddProperties(
&BaseProperties{},
+ &android.ProtoProperties{},
+ &BinaryProperties{},
)
android.InitDefaultsModule(module)
diff --git a/python/python.go b/python/python.go
index 8364169..f6029c2 100644
--- a/python/python.go
+++ b/python/python.go
@@ -120,6 +120,15 @@
// whether the binary is required to be built with embedded launcher for this actual_version.
// this is set by the python version mutator based on version-specific properties
Embedded_launcher *bool `blueprint:"mutated"`
+
+ Proto struct {
+ // Whether generated python protos should include the pkg_path in
+ // their import statements. This is a temporary flag to help transition to
+ // the new behavior where this is always true. It will be removed after all
+ // usages of protos with pkg_path have been updated. The default is currently
+ // false.
+ Respect_pkg_path *bool
+ }
}
type baseAttributes struct {
@@ -347,10 +356,6 @@
protoExt = ".proto"
pyVersion2 = "PY2"
pyVersion3 = "PY3"
- initFileName = "__init__.py"
- mainFileName = "__main__.py"
- entryPointFile = "entry_point.txt"
- parFileExt = ".zip"
internalPath = "internal"
)
@@ -672,8 +677,26 @@
protoFlags := android.GetProtoFlags(ctx, &p.protoProperties)
protoFlags.OutTypeFlag = "--python_out"
+ // TODO(b/247578564): Change the default to true, and then eventually remove respect_pkg_path
+ protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, false)
+ pkgPathForProtos := pkgPath
+ if pkgPathForProtos != "" && protosRespectPkgPath {
+ pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ var stagedProtoSrcs android.Paths
+ for _, srcFile := range protoSrcs {
+ stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel())
+ rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String()))
+ rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc)
+ stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc)
+ }
+ rule.Build("stage_protos_for_pkg_path", "Stage protos for pkg_path")
+ protoSrcs = stagedProtoSrcs
+ pkgPathForProtos = ""
+ }
+
for _, srcFile := range protoSrcs {
- zip := genProto(ctx, srcFile, protoFlags, pkgPath)
+ zip := genProto(ctx, srcFile, protoFlags, pkgPathForProtos)
zips = append(zips, zip)
}
}
diff --git a/python/python_test.go b/python/python_test.go
index f57f504..42a1ffb 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -300,8 +300,6 @@
filepath.Join("dir", "file2.py"): nil,
filepath.Join("dir", "bin.py"): nil,
filepath.Join("dir", "file4.py"): nil,
- StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
- MAIN_FILE = '%main%'`),
},
expectedBinaries: []pyModule{
{
diff --git a/python/scripts/main_non_embedded.py b/python/scripts/main_non_embedded.py
new file mode 100644
index 0000000..ffbaaa8
--- /dev/null
+++ b/python/scripts/main_non_embedded.py
@@ -0,0 +1,6 @@
+import runpy
+
+# The purpose of this file is to implement python 3.11+'s
+# PYTHON_SAFE_PATH / -P option on older python versions.
+
+runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index 23897b3..a0ddffe 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -1,7 +1,6 @@
#!/usr/bin/env '%interpreter%'
import os
-import re
import tempfile
import shutil
import sys
@@ -15,56 +14,31 @@
# Don't imply 'import site' on initialization
PYTHON_ARG = '-S'
-def SearchPathEnv(name):
- search_path = os.getenv('PATH', os.defpath).split(os.pathsep)
- for directory in search_path:
- if directory == '': continue
- path = os.path.join(directory, name)
- # Check if path is actual executable file.
- if os.path.isfile(path) and os.access(path, os.X_OK):
- return path
- return None
-
-def FindPythonBinary():
- if PYTHON_BINARY.startswith('/'):
- # Case 1: Python interpreter is directly provided with absolute path.
- return PYTHON_BINARY
- else:
- # Case 2: Find Python interpreter through environment variable: PATH.
- return SearchPathEnv(PYTHON_BINARY)
-
-# Create the runfiles tree by extracting the zip file
-def ExtractRunfiles():
- temp_dir = tempfile.mkdtemp("", "Soong.python_")
- zf = zipfile.ZipFile(os.path.dirname(__file__))
- zf.extractall(temp_dir)
- return temp_dir
-
def Main():
args = sys.argv[1:]
- new_env = {}
- runfiles_path = None
-
+ runfiles_path = tempfile.mkdtemp(prefix="Soong.python_")
try:
- runfiles_path = ExtractRunfiles()
+ zf = zipfile.ZipFile(os.path.dirname(__file__))
+ zf.extractall(runfiles_path)
+ zf.close()
# Add runfiles path to PYTHONPATH.
python_path_entries = [runfiles_path]
- # Add top dirs within runfiles path to PYTHONPATH.
- top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)]
- top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)]
- python_path_entries += top_pkg_dirs
+ if ADD_TOP_DIRECTORIES_TO_PATH:
+ # Add top dirs within runfiles path to PYTHONPATH.
+ top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)]
+ top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)]
+ python_path_entries += top_pkg_dirs
+ new_python_path = ":".join(python_path_entries)
old_python_path = os.environ.get(PYTHON_PATH)
- separator = ':'
- new_python_path = separator.join(python_path_entries)
- # Copy old PYTHONPATH.
if old_python_path:
- new_python_path += separator + old_python_path
- new_env[PYTHON_PATH] = new_python_path
+ os.environ.update({PYTHON_PATH: new_python_path + ":" + old_python_path})
+ else:
+ os.environ.update({PYTHON_PATH: new_python_path})
# Now look for main python source file.
main_filepath = os.path.join(runfiles_path, MAIN_FILE)
@@ -73,23 +47,14 @@
assert os.access(main_filepath, os.R_OK), \
'Cannot exec() %r: file not readable.' % main_filepath
- python_program = FindPythonBinary()
- if python_program is None:
- raise AssertionError('Could not find python binary: ' + PYTHON_BINARY)
- args = [python_program, PYTHON_ARG, main_filepath] + args
-
- os.environ.update(new_env)
+ args = [PYTHON_BINARY, PYTHON_ARG, main_filepath] + args
sys.stdout.flush()
# close_fds=False so that you can run binaries with files provided on the command line:
# my_python_app --file <(echo foo)
- retCode = subprocess.call(args, close_fds=False)
- sys.exit(retCode)
- except:
- raise
+ sys.exit(subprocess.call(args, close_fds=False))
finally:
- if runfiles_path is not None:
- shutil.rmtree(runfiles_path, True)
+ shutil.rmtree(runfiles_path, ignore_errors=True)
if __name__ == '__main__':
Main()
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
new file mode 100644
index 0000000..fc62813
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -0,0 +1,23 @@
+python_test_host {
+ name: "py_dont_import_folder_of_entrypoint_test",
+ main: "mypkg/main.py",
+ srcs: [
+ "mypkg/main.py",
+ "mypkg/mymodule.py",
+ ],
+ defaults: ["modern_python_path_defaults"],
+}
+
+python_test_host {
+ name: "py_dont_import_folder_of_entrypoint_test_embedded_launcher",
+ main: "mypkg/main.py",
+ srcs: [
+ "mypkg/main.py",
+ "mypkg/mymodule.py",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py
new file mode 100644
index 0000000..c6a36ed
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py
@@ -0,0 +1,15 @@
+import unittest
+import sys
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_cant_import_mymodule_directly(self):
+ with self.assertRaises(ImportError):
+ import mymodule
+
+ def test_can_import_mymodule_by_parent_package(self):
+ import mypkg.mymodule
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py
diff --git a/python/tests/proto_pkg_path/Android.bp b/python/tests/proto_pkg_path/Android.bp
new file mode 100644
index 0000000..ef79850
--- /dev/null
+++ b/python/tests/proto_pkg_path/Android.bp
@@ -0,0 +1,17 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_test_host {
+ name: "py_proto_pkg_path_test",
+ main: "main.py",
+ srcs: [
+ "main.py",
+ "proto/*.proto",
+ ],
+ pkg_path: "mylib/subpackage",
+ proto: {
+ canonical_path_from_root: false,
+ respect_pkg_path: true,
+ },
+}
diff --git a/python/tests/proto_pkg_path/main.py b/python/tests/proto_pkg_path/main.py
new file mode 100644
index 0000000..c4acdde
--- /dev/null
+++ b/python/tests/proto_pkg_path/main.py
@@ -0,0 +1,18 @@
+import sys
+
+import unittest
+import mylib.subpackage.proto.test_pb2 as test_pb2
+import mylib.subpackage.proto.common_pb2 as common_pb2
+
+print(sys.path)
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_main(self):
+ x = test_pb2.MyMessage(name="foo",
+ common = common_pb2.MyCommonMessage(common="common"))
+ self.assertEqual(x.name, "foo")
+ self.assertEqual(x.common.common, "common")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/proto_pkg_path/proto/common.proto b/python/tests/proto_pkg_path/proto/common.proto
new file mode 100644
index 0000000..b24b8ea
--- /dev/null
+++ b/python/tests/proto_pkg_path/proto/common.proto
@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+message MyCommonMessage {
+ string common = 1;
+}
diff --git a/python/tests/proto_pkg_path/proto/test.proto b/python/tests/proto_pkg_path/proto/test.proto
new file mode 100644
index 0000000..55f3b17
--- /dev/null
+++ b/python/tests/proto_pkg_path/proto/test.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+import "mylib/subpackage/proto/common.proto";
+
+message MyMessage {
+ string name = 1;
+ MyCommonMessage common = 2;
+}
diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp
new file mode 100644
index 0000000..0b15ce7
--- /dev/null
+++ b/python/tests/top_level_dirs/Android.bp
@@ -0,0 +1,9 @@
+python_test_host {
+ name: "py_dont_add_top_level_dirs_test",
+ main: "main.py",
+ srcs: [
+ "main.py",
+ "mypkg/mymodule.py",
+ ],
+ dont_add_top_level_directories_to_path: true,
+}
diff --git a/python/tests/top_level_dirs/main.py b/python/tests/top_level_dirs/main.py
new file mode 100644
index 0000000..9f30bfa
--- /dev/null
+++ b/python/tests/top_level_dirs/main.py
@@ -0,0 +1,17 @@
+import unittest
+import sys
+
+print(sys.path, file=sys.stderr)
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_cant_import_mymodule_directly(self):
+ with self.assertRaises(ImportError):
+ import mymodule
+
+ def test_can_import_mymodule_by_parent_package(self):
+ import mypkg.mymodule
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/top_level_dirs/mypkg/mymodule.py b/python/tests/top_level_dirs/mypkg/mymodule.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/tests/top_level_dirs/mypkg/mymodule.py
diff --git a/rust/config/global.go b/rust/config/global.go
index e676837..81aec7e 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.63.0"
+ RustDefaultVersion = "1.64.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 3f4f9c0..7b003fd 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -1,5 +1,4 @@
per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com
-per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
-per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
\ No newline at end of file
+per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
deleted file mode 100755
index 1a16f7c..0000000
--- a/scripts/build-aml-prebuilts.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash -e
-
-# This script is similar to "m" but builds in --soong-only mode, and handles
-# special cases to make that mode work. All arguments are passed on to
-# build/soong/soong_ui.bash.
-#
-# --soong-only bypasses the kati step and hence the make logic that e.g. doesn't
-# handle more than two device architectures. It is particularly intended for use
-# with TARGET_PRODUCT=mainline_sdk to build 'sdk' and 'module_export' Soong
-# modules in TARGET_ARCH_SUITE=mainline_sdk mode so that they get all four
-# device architectures (artifacts get installed in $OUT_DIR/soong/mainline-sdks
-# - cf PathForMainlineSdksInstall in android/paths.go).
-#
-# TODO(b/174315599): Replace this script completely with a 'soong_ui.bash
-# --soong-only' invocation. For now it is still necessary to set up
-# build_number.txt.
-
-if [ ! -e build/soong/soong_ui.bash ]; then
- echo "$0 must be run from the top of the tree"
- exit 1
-fi
-
-export OUT_DIR=${OUT_DIR:-out}
-
-if [ -e ${OUT_DIR}/soong/.soong.kati_enabled ]; then
- # If ${OUT_DIR} has been created without --soong-only, Soong will create an
- # ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
- # expected to be supplied by the .mk files, and that might cause errors in
- # "m --soong-only" below. We therefore default to a different out dir
- # location in that case.
- AML_OUT_DIR=out/aml
- echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
- OUT_DIR=${AML_OUT_DIR}
-fi
-
-mkdir -p ${OUT_DIR}/soong
-
-# The --dumpvars-mode invocation will run Soong in normal make mode where it
-# creates .soong.kati_enabled. That would clobber our real out directory, so we
-# need to use a different OUT_DIR.
-vars="$(OUT_DIR=${OUT_DIR}/dumpvars_mode build/soong/soong_ui.bash \
- --dumpvars-mode --vars=BUILD_NUMBER)"
-# Assign to a variable and eval that, since bash ignores any error status
-# from the command substitution if it's directly on the eval line.
-eval $vars
-
-# Some Soong build rules may require this, and the failure mode if it's missing
-# is confusing (b/172548608).
-echo -n ${BUILD_NUMBER} > ${OUT_DIR}/soong/build_number.txt
-
-build/soong/soong_ui.bash --make-mode --soong-only "$@"
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index c93055a..4be0ace 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -895,3 +895,222 @@
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
}
+
+func testSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T, targetBuildRelease string,
+ expectedSdkSnapshot string,
+ expectedCopyRules string,
+ expectedStubFlagsInputs []string,
+ suffix string) {
+
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"),
+ java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"),
+ prepareForSdkTestWithApex,
+
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
+ }),
+
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "S",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ apex_available: ["myapex"],
+ contents: [
+ "mysdklibrary",
+ "mynewsdklibrary",
+ ],
+
+ hidden_api: {
+ split_packages: [],
+ },
+ }
+
+ java_sdk_library {
+ name: "mysdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ shared_library: false,
+ public: {enabled: true},
+ min_sdk_version: "S",
+ }
+
+ java_sdk_library {
+ name: "mynewsdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ min_sdk_version: "Tiramisu",
+ permitted_packages: ["mynewsdklibrary"],
+ }
+ `),
+ ).RunTest(t)
+
+ bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common")
+ rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv")
+ android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", expectedStubFlagsInputs, rule.Implicits)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(expectedSdkSnapshot),
+ checkAllCopyRules(expectedCopyRules),
+ )
+}
+
+func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) {
+ t.Run("target S build", func(t *testing.T) {
+ expectedSnapshot := `
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ contents: ["mysdklibrary"],
+ hidden_api: {
+ 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",
+ },
+}
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+`
+ expectedCopyRules := `
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/stub-flags.csv -> hiddenapi/stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/all-flags.csv -> hiddenapi/all-flags.csv
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+`
+
+ // On S the stub flags should only be generated from mysdklibrary as mynewsdklibrary is not part
+ // of the snapshot.
+ expectedStubFlagsInputs := []string{
+ "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ }
+
+ testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S",
+ expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "-for-sdk-snapshot")
+ })
+
+ t.Run("target-Tiramisu-build", func(t *testing.T) {
+ expectedSnapshot := `
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ contents: [
+ "mysdklibrary",
+ "mynewsdklibrary",
+ ],
+ hidden_api: {
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ signature_patterns: "hiddenapi/signature-patterns.csv",
+ filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv",
+ filtered_flags: "hiddenapi/filtered-flags.csv",
+ },
+}
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_sdk_library_import {
+ name: "mynewsdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: true,
+ compile_dex: true,
+ permitted_packages: ["mynewsdklibrary"],
+ public: {
+ jars: ["sdk_library/public/mynewsdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mynewsdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mynewsdklibrary.txt",
+ removed_api: "sdk_library/public/mynewsdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+`
+ expectedCopyRules := `
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mynewsdklibrary.stubs/android_common/javac/mynewsdklibrary.stubs.jar -> sdk_library/public/mynewsdklibrary-stubs.jar
+.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt
+.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt
+`
+
+ // On tiramisu the stub flags should be generated from both mynewsdklibrary and mysdklibrary as
+ // they are both part of the snapshot.
+ expectedStubFlagsInputs := []string{
+ "out/soong/.intermediates/mynewsdklibrary.stubs/android_common/dex/mynewsdklibrary.stubs.jar",
+ "out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar",
+ "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ }
+
+ testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu",
+ expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "")
+ })
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 7ab5285..51903ce3 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -889,6 +889,56 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_DistStem(t *testing.T) {
+ result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib-foo"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib-foo",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ public: {
+ enabled: true,
+ },
+ dist_stem: "myjavalib",
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "myjavalib-foo",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavalib-foo.stubs/android_common/javac/myjavalib-foo.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+`),
+ checkMergeZips(
+ ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+ ),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_UseSrcJar(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
@@ -1004,7 +1054,7 @@
java_sdk_library {
name: "myjavalib",
srcs: ["Test.java"],
- sdk_version: "current",
+ sdk_version: "S",
shared_library: false,
annotations_enabled: true,
public: {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 1ec12c3..2f9aee9 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -218,15 +218,16 @@
}
type testPropertiesStruct struct {
- name string
- private string
- Public_Kept string `sdk:"keep"`
- S_Common string
- S_Different string `android:"arch_variant"`
- A_Common []string
- A_Different []string `android:"arch_variant"`
- F_Common *bool
- F_Different *bool `android:"arch_variant"`
+ name string
+ private string
+ Public_Ignore string `sdk:"ignore"`
+ Public_Keep string `sdk:"keep"`
+ S_Common string
+ S_Different string `android:"arch_variant"`
+ A_Common []string
+ A_Different []string `android:"arch_variant"`
+ F_Common *bool
+ F_Different *bool `android:"arch_variant"`
EmbeddedPropertiesStruct
}
@@ -244,30 +245,32 @@
common := &testPropertiesStruct{name: "common"}
structs := []propertiesContainer{
&testPropertiesStruct{
- name: "struct-0",
- private: "common",
- Public_Kept: "common",
- S_Common: "common",
- S_Different: "upper",
- A_Common: []string{"first", "second"},
- A_Different: []string{"alpha", "beta"},
- F_Common: proptools.BoolPtr(false),
- F_Different: proptools.BoolPtr(false),
+ name: "struct-0",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "upper",
+ A_Common: []string{"first", "second"},
+ A_Different: []string{"alpha", "beta"},
+ F_Common: proptools.BoolPtr(false),
+ F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_upper",
},
},
&testPropertiesStruct{
- name: "struct-1",
- private: "common",
- Public_Kept: "common",
- S_Common: "common",
- S_Different: "lower",
- A_Common: []string{"first", "second"},
- A_Different: []string{"alpha", "delta"},
- F_Common: proptools.BoolPtr(false),
- F_Different: proptools.BoolPtr(true),
+ name: "struct-1",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "lower",
+ A_Common: []string{"first", "second"},
+ A_Different: []string{"alpha", "delta"},
+ F_Common: proptools.BoolPtr(false),
+ F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_lower",
@@ -282,15 +285,16 @@
android.AssertDeepEquals(t, "common properties not correct",
&testPropertiesStruct{
- name: "common",
- private: "",
- Public_Kept: "",
- S_Common: "common",
- S_Different: "",
- A_Common: []string{"first", "second"},
- A_Different: []string(nil),
- F_Common: proptools.BoolPtr(false),
- F_Different: nil,
+ name: "common",
+ private: "",
+ Public_Ignore: "",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "",
+ A_Common: []string{"first", "second"},
+ A_Different: []string(nil),
+ F_Common: proptools.BoolPtr(false),
+ F_Different: nil,
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "",
@@ -300,15 +304,16 @@
android.AssertDeepEquals(t, "updated properties[0] not correct",
&testPropertiesStruct{
- name: "struct-0",
- private: "common",
- Public_Kept: "common",
- S_Common: "",
- S_Different: "upper",
- A_Common: nil,
- A_Different: []string{"alpha", "beta"},
- F_Common: nil,
- F_Different: proptools.BoolPtr(false),
+ name: "struct-0",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "",
+ S_Different: "upper",
+ A_Common: nil,
+ A_Different: []string{"alpha", "beta"},
+ F_Common: nil,
+ F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_upper",
@@ -318,15 +323,16 @@
android.AssertDeepEquals(t, "updated properties[1] not correct",
&testPropertiesStruct{
- name: "struct-1",
- private: "common",
- Public_Kept: "common",
- S_Common: "",
- S_Different: "lower",
- A_Common: nil,
- A_Different: []string{"alpha", "delta"},
- F_Common: nil,
- F_Different: proptools.BoolPtr(true),
+ name: "struct-1",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "",
+ S_Different: "lower",
+ A_Common: nil,
+ A_Different: []string{"alpha", "delta"},
+ F_Common: nil,
+ F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_lower",
@@ -482,6 +488,7 @@
name: "mysdklibrary",
srcs: ["Test.java"],
compile_dex: true,
+ sdk_version: "S",
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
}
diff --git a/sdk/update.go b/sdk/update.go
index 5c9376b..92a13fa 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -211,11 +211,14 @@
container = parent.(android.SdkAware)
}
+ minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child)
+
export := memberTag.ExportMember()
s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
sdkVariant: s,
memberType: memberType,
variant: child.(android.SdkAware),
+ minApiLevel: minApiLevel,
container: container,
export: export,
exportedComponentsInfo: exportedComponentsInfo,
@@ -332,10 +335,28 @@
// <arch>/lib/
// libFoo.so : a stub library
+func (s sdk) targetBuildRelease(ctx android.ModuleContext) *buildRelease {
+ config := ctx.Config()
+ targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name)
+ targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv)
+ if err != nil {
+ ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err)
+ targetBuildRelease = buildReleaseCurrent
+ }
+
+ return targetBuildRelease
+}
+
// buildSnapshot is the main function in this source file. It creates rules to copy
// the contents (header files, stub libraries, etc) into the zip file.
func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) {
+ targetBuildRelease := s.targetBuildRelease(ctx)
+ targetApiLevel, err := android.ApiLevelFromUser(ctx, targetBuildRelease.name)
+ if err != nil {
+ targetApiLevel = android.FutureApiLevel
+ }
+
// Aggregate all the sdkMemberVariantDep instances from all the sdk variants.
hasLicenses := false
var memberVariantDeps []sdkMemberVariantDep
@@ -346,12 +367,18 @@
// Filter out any sdkMemberVariantDep that is a component of another.
memberVariantDeps = filterOutComponents(ctx, memberVariantDeps)
- // Record the names of all the members, both explicitly specified and implicitly
- // included.
+ // Record the names of all the members, both explicitly specified and implicitly included. Also,
+ // record the names of any members that should be excluded from this snapshot.
allMembersByName := make(map[string]struct{})
exportedMembersByName := make(map[string]struct{})
+ excludedMembersByName := make(map[string]struct{})
- addMember := func(name string, export bool) {
+ addMember := func(name string, export bool, exclude bool) {
+ if exclude {
+ excludedMembersByName[name] = struct{}{}
+ return
+ }
+
allMembersByName[name] = struct{}{}
if export {
exportedMembersByName[name] = struct{}{}
@@ -362,11 +389,15 @@
name := memberVariantDep.variant.Name()
export := memberVariantDep.export
- addMember(name, export)
+ // If the minApiLevel of the member is greater than the target API level then exclude it from
+ // this snapshot.
+ exclude := memberVariantDep.minApiLevel.GreaterThan(targetApiLevel)
+
+ addMember(name, export, exclude)
// Add any components provided by the module.
for _, component := range memberVariantDep.exportedComponentsInfo.Components {
- addMember(component, export)
+ addMember(component, export, exclude)
}
if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
@@ -382,18 +413,9 @@
modules: make(map[string]*bpModule),
}
- config := ctx.Config()
-
// Always add -current to the end
snapshotFileSuffix := "-current"
- targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name)
- targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv)
- if err != nil {
- ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err)
- targetBuildRelease = buildReleaseCurrent
- }
-
builder := &snapshotBuilder{
ctx: ctx,
sdk: s,
@@ -404,6 +426,7 @@
prebuiltModules: make(map[string]*bpModule),
allMembersByName: allMembersByName,
exportedMembersByName: exportedMembersByName,
+ excludedMembersByName: excludedMembersByName,
targetBuildRelease: targetBuildRelease,
}
s.builderForTests = builder
@@ -437,6 +460,10 @@
}
name := member.name
+ if _, ok := excludedMembersByName[name]; ok {
+ continue
+ }
+
requiredTraits := traits[name]
if requiredTraits == nil {
requiredTraits = android.EmptySdkMemberTraitSet()
@@ -1034,6 +1061,9 @@
// The set of exported members by name.
exportedMembersByName map[string]struct{}
+ // The set of members which have been excluded from this snapshot; by name.
+ excludedMembersByName map[string]struct{}
+
// The target build release for which the snapshot is to be generated.
targetBuildRelease *buildRelease
@@ -1218,6 +1248,9 @@
func (s *snapshotBuilder) snapshotSdkMemberNames(members []string, required bool) []string {
var references []string = nil
for _, m := range members {
+ if _, ok := s.excludedMembersByName[m]; ok {
+ continue
+ }
references = append(references, s.snapshotSdkMemberName(m, required))
}
return references
@@ -1260,6 +1293,9 @@
// The names of additional component modules provided by the variant.
exportedComponentsInfo android.ExportedComponentsInfo
+
+ // The minimum API level on which this module is supported.
+ minApiLevel android.ApiLevel
}
var _ android.SdkMember = (*sdkMember)(nil)
@@ -2136,6 +2172,11 @@
// Retrieves the value on which common value optimization will be performed.
getter fieldAccessorFunc
+ // True if the field should never be cleared.
+ //
+ // This is set to true if and only if the field is annotated with `sdk:"keep"`.
+ keep bool
+
// The empty value for the field.
emptyValue reflect.Value
@@ -2181,8 +2222,8 @@
continue
}
- // Ignore fields whose value should be kept.
- if proptools.HasTag(field, "sdk", "keep") {
+ // Ignore fields tagged with sdk:"ignore".
+ if proptools.HasTag(field, "sdk", "ignore") {
continue
}
@@ -2200,6 +2241,8 @@
}
}
+ keep := proptools.HasTag(field, "sdk", "keep")
+
// Save a copy of the field index for use in the function.
fieldIndex := f
@@ -2239,6 +2282,7 @@
name,
filter,
fieldGetter,
+ keep,
reflect.Zero(field.Type),
proptools.HasTag(field, "android", "arch_variant"),
}
@@ -2358,11 +2402,13 @@
if commonValue != nil {
emptyValue := property.emptyValue
fieldGetter(commonStructValue).Set(*commonValue)
- for i := 0; i < sliceValue.Len(); i++ {
- container := sliceValue.Index(i).Interface().(propertiesContainer)
- itemValue := reflect.ValueOf(container.optimizableProperties())
- fieldValue := fieldGetter(itemValue)
- fieldValue.Set(emptyValue)
+ if !property.keep {
+ for i := 0; i < sliceValue.Len(); i++ {
+ container := sliceValue.Index(i).Interface().(propertiesContainer)
+ itemValue := reflect.ValueOf(container.optimizableProperties())
+ fieldValue := fieldGetter(itemValue)
+ fieldValue.Set(emptyValue)
+ }
}
}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 578dc2b..1f0d28d 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -573,43 +573,14 @@
}
// TODO(b/240463568): Additional properties will be added for API validation
-type bazelSyspropLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
-}
-
-type bazelCcSyspropLibraryAttributes struct {
- Dep bazel.LabelAttribute
- Min_sdk_version *string
-}
-
func (m *syspropLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "sysprop_library",
- Bzl_load_location: "//build/bazel/rules/sysprop:sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.Name()},
- &bazelSyspropLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)),
- })
-
- attrs := &bazelCcSyspropLibraryAttributes{
- Dep: *bazel.MakeLabelAttribute(":" + m.Name()),
- Min_sdk_version: m.properties.Cpp.Min_sdk_version,
+ labels := cc.SyspropLibraryLabels{
+ SyspropLibraryLabel: m.BaseModuleName(),
+ SharedLibraryLabel: m.CcImplementationModuleName(),
+ StaticLibraryLabel: cc.BazelLabelNameForStaticModule(m.CcImplementationModuleName()),
}
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.CcImplementationModuleName()},
- attrs)
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.CcImplementationModuleName() + "_bp2build_cc_library_static"},
- attrs)
+ cc.Bp2buildSysprop(ctx,
+ labels,
+ bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)),
+ m.properties.Cpp.Min_sdk_version)
}
diff --git a/sysprop/sysprop_library_conversion_test.go b/sysprop/sysprop_library_conversion_test.go
index c72faf3..89adf7d 100644
--- a/sysprop/sysprop_library_conversion_test.go
+++ b/sysprop/sysprop_library_conversion_test.go
@@ -41,7 +41,7 @@
`,
ExpectedBazelTargets: []string{
bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo_sysprop_library",
+ "sysprop_foo",
bp2build.AttrNameToString{
"srcs": `[
"foo.sysprop",
@@ -51,12 +51,12 @@
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
"libsysprop_foo",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
}),
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
"libsysprop_foo_bp2build_cc_library_static",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
}),
},
})
@@ -86,7 +86,7 @@
`,
ExpectedBazelTargets: []string{
bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo_sysprop_library",
+ "sysprop_foo",
bp2build.AttrNameToString{
"srcs": `[
"foo.sysprop",
@@ -96,13 +96,13 @@
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
"libsysprop_foo",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
"min_sdk_version": `"5"`,
}),
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
"libsysprop_foo_bp2build_cc_library_static",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
"min_sdk_version": `"5"`,
}),
},
diff --git a/ui/build/build.go b/ui/build/build.go
index ff2d5f2..ab8cd56 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -249,41 +249,7 @@
SetupPath(ctx, config)
- what := RunAll
- if config.Checkbuild() {
- what |= RunBuildTests
- }
- if config.SkipConfig() {
- ctx.Verboseln("Skipping Config as requested")
- what = what &^ RunProductConfig
- }
- if config.SkipKati() {
- ctx.Verboseln("Skipping Kati as requested")
- what = what &^ RunKati
- }
- if config.SkipKatiNinja() {
- ctx.Verboseln("Skipping use of Kati ninja as requested")
- what = what &^ RunKatiNinja
- }
- if config.SkipSoong() {
- ctx.Verboseln("Skipping use of Soong as requested")
- what = what &^ RunSoong
- }
-
- if config.SkipNinja() {
- ctx.Verboseln("Skipping Ninja as requested")
- what = what &^ RunNinja
- }
-
- if !config.SoongBuildInvocationNeeded() {
- // This means that the output of soong_build is not needed and thus it would
- // run unnecessarily. In addition, if this code wasn't there invocations
- // with only special-cased target names like "m bp2build" would result in
- // passing Ninja the empty target list and it would then build the default
- // targets which is not what the user asked for.
- what = what &^ RunNinja
- what = what &^ RunKati
- }
+ what := evaluateWhatToRun(config, ctx.Verboseln)
if config.StartGoma() {
startGoma(ctx, config)
@@ -359,6 +325,46 @@
}
}
+func evaluateWhatToRun(config Config, verboseln func(v ...interface{})) int {
+ //evaluate what to run
+ what := RunAll
+ if config.Checkbuild() {
+ what |= RunBuildTests
+ }
+ if config.SkipConfig() {
+ verboseln("Skipping Config as requested")
+ what = what &^ RunProductConfig
+ }
+ if config.SkipKati() {
+ verboseln("Skipping Kati as requested")
+ what = what &^ RunKati
+ }
+ if config.SkipKatiNinja() {
+ verboseln("Skipping use of Kati ninja as requested")
+ what = what &^ RunKatiNinja
+ }
+ if config.SkipSoong() {
+ verboseln("Skipping use of Soong as requested")
+ what = what &^ RunSoong
+ }
+
+ if config.SkipNinja() {
+ verboseln("Skipping Ninja as requested")
+ what = what &^ RunNinja
+ }
+
+ if !config.SoongBuildInvocationNeeded() {
+ // This means that the output of soong_build is not needed and thus it would
+ // run unnecessarily. In addition, if this code wasn't there invocations
+ // with only special-cased target names like "m bp2build" would result in
+ // passing Ninja the empty target list and it would then build the default
+ // targets which is not what the user asked for.
+ what = what &^ RunNinja
+ what = what &^ RunKati
+ }
+ return what
+}
+
var distWaitGroup sync.WaitGroup
// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
diff --git a/xml/Android.bp b/xml/Android.bp
index 1542930..d4753de 100644
--- a/xml/Android.bp
+++ b/xml/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-bp2build",
"soong-android",
"soong-etc",
],
@@ -18,6 +19,7 @@
],
testSrcs: [
"xml_test.go",
+ "xml_conversion_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/xml/xml.go b/xml/xml.go
index c281078..8c0c072 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/bazel"
"android/soong/etc"
"github.com/google/blueprint"
@@ -67,6 +68,8 @@
}
type prebuiltEtcXml struct {
+ android.BazelModuleBase
+
etc.PrebuiltEtc
properties prebuiltEtcXmlProperties
@@ -129,5 +132,40 @@
etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitBazelModule(module)
return module
}
+
+type bazelPrebuiltEtcXmlAttributes struct {
+ Src bazel.LabelAttribute
+ Filename bazel.LabelAttribute
+ Dir string
+ Installable bazel.BoolAttribute
+ Filename_from_src bazel.BoolAttribute
+ Schema *string
+}
+
+func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ baseAttrs := p.PrebuiltEtc.Bp2buildHelper(ctx)
+
+ var schema *string
+ if p.properties.Schema != nil {
+ schema = p.properties.Schema
+ }
+
+ attrs := &bazelPrebuiltEtcXmlAttributes{
+ Src: baseAttrs.Src,
+ Filename: baseAttrs.Filename,
+ Dir: baseAttrs.Dir,
+ Installable: baseAttrs.Installable,
+ Filename_from_src: baseAttrs.Filename_from_src,
+ Schema: schema,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "prebuilt_xml",
+ Bzl_load_location: "//build/bazel/rules/prebuilt_xml.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: p.Name()}, attrs)
+}
diff --git a/xml/xml_conversion_test.go b/xml/xml_conversion_test.go
new file mode 100644
index 0000000..6606ddc
--- /dev/null
+++ b/xml/xml_conversion_test.go
@@ -0,0 +1,129 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xml
+
+import (
+ "android/soong/android"
+ "android/soong/bp2build"
+
+ "testing"
+)
+
+func runXmlPrebuiltEtcTestCase(t *testing.T, tc bp2build.Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "prebuilt_etc_xml"
+ (&tc).ModuleTypeUnderTestFactory = PrebuiltEtcXmlFactory
+ bp2build.RunBp2BuildTestCase(t, registerXmlModuleTypes, tc)
+}
+
+func registerXmlModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestXmlPrebuiltEtcSimple(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - simple example",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename: "fooFileName",
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooFileName"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFilenameFromSrc(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - filenameFromSrc True ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename_from_src: true,
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooSrc"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFilenameAndFilenameFromSrc(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - filename provided and filenameFromSrc True ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename: "fooFileName",
+ filename_from_src: true,
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooFileName"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFileNameFromSrcMultipleSrcs(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ filename_from_src: true,
+ arch: {
+ arm: {
+ src: "barSrc",
+ },
+ arm64: {
+ src: "bazSrc",
+ },
+ }
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "filename_from_src": `True`,
+ "dir": `"etc"`,
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "barSrc",
+ "//build/bazel/platforms/arch:arm64": "bazSrc",
+ "//conditions:default": None,
+ })`,
+ })}})
+}
diff --git a/zip/cmd/BUILD.bazel b/zip/cmd/BUILD.bazel
new file mode 100644
index 0000000..e04a1e1
--- /dev/null
+++ b/zip/cmd/BUILD.bazel
@@ -0,0 +1,20 @@
+# 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",
+)