Merge "Move variable assignment handling to generation context"
diff --git a/android/Android.bp b/android/Android.bp
index c072ac2..87b021f 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -19,6 +19,7 @@
"soong-shared",
"soong-starlark-format",
"soong-ui-metrics_proto",
+ "soong-android-allowlists",
"golang-protobuf-proto",
"golang-protobuf-encoding-prototext",
@@ -36,6 +37,7 @@
"bazel_handler.go",
"bazel_paths.go",
"config.go",
+ "config_bp2build.go",
"csuite_config.go",
"deapexer.go",
"defaults.go",
@@ -96,6 +98,7 @@
"bazel_handler_test.go",
"bazel_test.go",
"config_test.go",
+ "config_bp2build_test.go",
"csuite_config_test.go",
"defaults_test.go",
"depset_test.go",
diff --git a/android/allowlists/Android.bp b/android/allowlists/Android.bp
new file mode 100644
index 0000000..05cffc1
--- /dev/null
+++ b/android/allowlists/Android.bp
@@ -0,0 +1,25 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-android-allowlists",
+ pkgPath: "android/soong/android/allowlists",
+ srcs: [
+ "allowlists.go",
+ ],
+}
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
new file mode 100644
index 0000000..72961e6
--- /dev/null
+++ b/android/allowlists/allowlists.go
@@ -0,0 +1,414 @@
+// 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 allowlists
+
+// Configuration to decide if modules in a directory should default to true/false for bp2build_available
+type Bp2BuildConfig map[string]BazelConversionConfigEntry
+type BazelConversionConfigEntry int
+
+const (
+ // iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map,
+ // which can also mean that the key doesn't exist in a lookup.
+
+ // all modules in this package and subpackages default to bp2build_available: true.
+ // allows modules to opt-out.
+ Bp2BuildDefaultTrueRecursively BazelConversionConfigEntry = iota + 1
+
+ // all modules in this package (not recursively) default to bp2build_available: true.
+ // allows modules to opt-out.
+ Bp2BuildDefaultTrue
+
+ // all modules in this package (not recursively) default to bp2build_available: false.
+ // allows modules to opt-in.
+ Bp2BuildDefaultFalse
+)
+
+var (
+ Bp2buildDefaultConfig = Bp2BuildConfig{
+ "art/libartpalette": Bp2BuildDefaultTrueRecursively,
+ "art/libdexfile": Bp2BuildDefaultTrueRecursively,
+ "art/runtime": Bp2BuildDefaultTrueRecursively,
+ "art/tools": Bp2BuildDefaultTrue,
+ "bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
+ "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
+ "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
+ "build/make/tools/signapk": Bp2BuildDefaultTrue,
+ "build/make/target/product/security": Bp2BuildDefaultTrue,
+ "build/soong": Bp2BuildDefaultTrue,
+ "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
+ "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
+ "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
+ "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
+ "build/soong/scripts": Bp2BuildDefaultTrueRecursively,
+ "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+ "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
+ "development/apps/Fallback": Bp2BuildDefaultTrue,
+ "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
+ "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
+ "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
+ "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
+ "development/samples/Compass": Bp2BuildDefaultTrue,
+ "development/samples/ContactManager": Bp2BuildDefaultTrue,
+ "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
+ "development/samples/HelloEffects": Bp2BuildDefaultTrue,
+ "development/samples/Home": Bp2BuildDefaultTrue,
+ "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
+ "development/samples/JetBoy": Bp2BuildDefaultTrue,
+ "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
+ "development/samples/LceDemo": Bp2BuildDefaultTrue,
+ "development/samples/LunarLander": Bp2BuildDefaultTrue,
+ "development/samples/MultiResolution": Bp2BuildDefaultTrue,
+ "development/samples/MultiWindow": Bp2BuildDefaultTrue,
+ "development/samples/NotePad": Bp2BuildDefaultTrue,
+ "development/samples/Obb": Bp2BuildDefaultTrue,
+ "development/samples/RSSReader": Bp2BuildDefaultTrue,
+ "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
+ "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
+ "development/samples/SipDemo": Bp2BuildDefaultTrue,
+ "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
+ "development/samples/Snake": Bp2BuildDefaultTrue,
+ "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
+ "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
+ "development/samples/ToyVpn": Bp2BuildDefaultTrue,
+ "development/samples/TtsEngine": Bp2BuildDefaultTrue,
+ "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
+ "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
+ "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
+ "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
+ "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
+ "development/sdk": Bp2BuildDefaultTrueRecursively,
+ "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+ "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
+ "external/auto/common": Bp2BuildDefaultTrueRecursively,
+ "external/auto/service": Bp2BuildDefaultTrueRecursively,
+ "external/boringssl": Bp2BuildDefaultTrueRecursively,
+ "external/bouncycastle": Bp2BuildDefaultTrue,
+ "external/brotli": Bp2BuildDefaultTrue,
+ "external/conscrypt": Bp2BuildDefaultTrue,
+ "external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
+ "external/error_prone": Bp2BuildDefaultTrueRecursively,
+ "external/fmtlib": Bp2BuildDefaultTrueRecursively,
+ "external/google-benchmark": Bp2BuildDefaultTrueRecursively,
+ "external/googletest": Bp2BuildDefaultTrueRecursively,
+ "external/gwp_asan": Bp2BuildDefaultTrueRecursively,
+ "external/icu": Bp2BuildDefaultTrueRecursively,
+ "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/javapoet": Bp2BuildDefaultTrueRecursively,
+ "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
+ "external/jsoncpp": Bp2BuildDefaultTrueRecursively,
+ "external/libcap": Bp2BuildDefaultTrueRecursively,
+ "external/libcxx": Bp2BuildDefaultTrueRecursively,
+ "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
+ "external/libevent": Bp2BuildDefaultTrueRecursively,
+ "external/libpng": Bp2BuildDefaultTrueRecursively,
+ "external/lz4/lib": Bp2BuildDefaultTrue,
+ "external/lzma/C": Bp2BuildDefaultTrueRecursively,
+ "external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
+ "external/minijail": Bp2BuildDefaultTrueRecursively,
+ "external/pcre": Bp2BuildDefaultTrueRecursively,
+ "external/protobuf": Bp2BuildDefaultTrueRecursively,
+ "external/python/six": Bp2BuildDefaultTrueRecursively,
+ "external/scudo": Bp2BuildDefaultTrueRecursively,
+ "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
+ "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
+ "external/zlib": Bp2BuildDefaultTrueRecursively,
+ "external/zstd": Bp2BuildDefaultTrueRecursively,
+ "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
+ "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
+ "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
+ "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
+ "libnativehelper": Bp2BuildDefaultTrueRecursively,
+ "packages/apps/DevCamera": Bp2BuildDefaultTrue,
+ "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
+ "packages/apps/Protips": Bp2BuildDefaultTrue,
+ "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb": Bp2BuildDefaultTrue,
+ "packages/modules/adb/apex": Bp2BuildDefaultTrue,
+ "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/pairing_auth": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
+ "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue,
+ "packages/screensavers/Basic": Bp2BuildDefaultTrue,
+ "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
+ "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
+ "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
+ "system/apex/proto": Bp2BuildDefaultTrueRecursively,
+ "system/apex/libs": Bp2BuildDefaultTrueRecursively,
+ "system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
+ "system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
+ "system/core/libasyncio": Bp2BuildDefaultTrue,
+ "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libcutils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively,
+ "system/core/libprocessgroup": Bp2BuildDefaultTrue,
+ "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
+ "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
+ "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
+ "system/core/libutils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
+ "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
+ "system/libbase": Bp2BuildDefaultTrueRecursively,
+ "system/libprocinfo": Bp2BuildDefaultTrue,
+ "system/libziparchive": Bp2BuildDefaultTrueRecursively,
+ "system/logging/liblog": Bp2BuildDefaultTrueRecursively,
+ "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/apex": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
+ "system/unwinding/libbacktrace": Bp2BuildDefaultTrueRecursively,
+ "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
+ "tools/apksig": Bp2BuildDefaultTrue,
+ "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
+ }
+
+ Bp2buildKeepExistingBuildFile = map[string]bool{
+ // This is actually build/bazel/build.BAZEL symlinked to ./BUILD
+ ".":/*recursive = */ false,
+
+ // build/bazel/examples/apex/... BUILD files should be generated, so
+ // build/bazel is not recursive. Instead list each subdirectory under
+ // build/bazel explicitly.
+ "build/bazel":/* recursive = */ false,
+ "build/bazel/ci/dist":/* recursive = */ false,
+ "build/bazel/examples/android_app":/* recursive = */ true,
+ "build/bazel/examples/java":/* recursive = */ true,
+ "build/bazel/bazel_skylib":/* recursive = */ true,
+ "build/bazel/rules":/* recursive = */ true,
+ "build/bazel/rules_cc":/* recursive = */ true,
+ "build/bazel/scripts":/* recursive = */ true,
+ "build/bazel/tests":/* recursive = */ true,
+ "build/bazel/platforms":/* recursive = */ true,
+ "build/bazel/product_variables":/* recursive = */ true,
+ "build/bazel/vendor/google":/* recursive = */ true,
+ "build/bazel_common_rules":/* recursive = */ true,
+ // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
+ "build/make/tools":/* recursive = */ false,
+ "build/pesto":/* 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
+ "external/bazelbuild-rules_android":/* recursive = */ true,
+ "external/bazel-skylib":/* recursive = */ true,
+ "external/guava":/* recursive = */ true,
+ "external/jsr305":/* recursive = */ true,
+ "frameworks/ex/common":/* recursive = */ true,
+
+ "packages/apps/Music":/* recursive = */ true,
+ "packages/apps/QuickSearchBox":/* recursive = */ true,
+ "packages/apps/WallpaperPicker":/* recursive = */ false,
+
+ "prebuilts/bundletool":/* recursive = */ true,
+ "prebuilts/gcc":/* recursive = */ true,
+ "prebuilts/build-tools":/* recursive = */ false,
+ "prebuilts/jdk/jdk11":/* recursive = */ false,
+ "prebuilts/sdk":/* recursive = */ false,
+ "prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
+ "prebuilts/sdk/current/support":/* recursive = */ false,
+ "prebuilts/sdk/tools":/* recursive = */ false,
+ "prebuilts/r8":/* recursive = */ false,
+ }
+
+ Bp2buildModuleAlwaysConvertList = []string{
+ //external/avb
+ "avbtool",
+ "libavb",
+ "avb_headers",
+
+ //external/fec
+ "libfec_rs",
+
+ //system/core/libsparse
+ "libsparse",
+
+ //system/extras/ext4_utils
+ "libext4_utils",
+
+ //system/extras/libfec
+ "libfec",
+
+ //system/extras/squashfs_utils
+ "libsquashfs_utils",
+
+ //system/extras/verity/fec
+ "fec",
+
+ //packages/apps/Car/libs/car-ui-lib/car-ui-androidx
+ // genrule dependencies for java_imports
+ "car-ui-androidx-annotation-nodeps",
+ "car-ui-androidx-collection-nodeps",
+ "car-ui-androidx-core-common-nodeps",
+ "car-ui-androidx-lifecycle-common-nodeps",
+ "car-ui-androidx-constraintlayout-solver-nodeps",
+ }
+
+ Bp2buildModuleTypeAlwaysConvertList = []string{
+ "java_import",
+ "java_import_host",
+ }
+
+ Bp2buildModuleDoNotConvertList = []string{
+ // cc bugs
+ "libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules
+ "libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library
+ "gen-kotlin-build-file.py", // TODO(b/198619163) module has same name as source
+ "libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support.
+ "linkerconfig", "mdnsd", // TODO(b/202876379): has arch-variant static_executable
+ "linker", // TODO(b/228316882): cc_binary uses link_crt
+ "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
+ "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
+
+ // java bugs
+ "libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+
+ // python protos
+ "libprotobuf-python", // TODO(b/196084681): contains .proto sources
+ "apex_build_info_proto", "apex_manifest_proto", // TODO(b/196084681): a python lib with proto sources
+ "linker_config_proto", // TODO(b/196084681): contains .proto sources
+
+ // genrule incompatibilities
+ "brotli-fuzzer-corpus", // TODO(b/202015218): outputs are in location incompatible with bazel genrule handling.
+ "platform_tools_properties", "build_tools_source_properties", // TODO(b/203369847): multiple genrules in the same package creating the same file
+
+ // aar support
+ "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
+
+ // 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
+
+ // go deps:
+ "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
+ "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
+ "robolectric_tzdata", // depends on soong_zip, a go binary
+
+ // rust support
+ "libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
+
+ // unconverted deps
+ "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
+ "abb", // depends on unconverted modules: libcmd, libbinder
+ "adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
+ "android_icu4j_srcgen", // depends on unconverted modules: currysrc
+ "android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc
+ "apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full
+ "art-script", // depends on unconverted modules: dalvikvm, dex2oat
+ "bin2c_fastdeployagent", // depends on unconverted modules: deployagent
+ "chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol
+ "com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
+ "conv_linker_config", // depends on unconverted modules: linker_config_proto
+ "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
+ "host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano
+ "libadb_host", // depends on unconverted modules: AdbWinApi, libopenscreen-discovery, libopenscreen-platform-impl, libusb
+ "libart", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
+ "libart-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libartbase-art-gtest
+ "libart_headers", // depends on unconverted modules: art_libartbase_headers
+ "libartd", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
+ "libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
+ "libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
+ "libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
+ "libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
+ "libdexfile_static", // depends on unconverted modules: libartbase, libdexfile
+ "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
+ "libfastdeploy_host", // depends on unconverted modules: libandroidfw, libusb, AdbWinApi
+ "libgmock_main_ndk", // depends on unconverted modules: libgtest_ndk_c++
+ "libgmock_ndk", // depends on unconverted modules: libgtest_ndk_c++
+ "libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
+ "libnativetesthelper_jni", // depends on unconverted modules: libgtest_ndk_c++
+ "libprotobuf-java-nano", // b/220869005, depends on non-public_current SDK
+ "libstatslog", // depends on unconverted modules: libstatspull, statsd-aidl-ndk, libbinder_ndk
+ "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
+ "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
+ }
+
+ Bp2buildCcLibraryStaticOnlyList = []string{}
+
+ MixedBuildsDisabledList = []string{
+ "art_libdexfile_dex_instruction_list_header", // breaks libart_mterp.armng, header not found
+
+ "libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
+ "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
+
+ "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
+
+ // Depends on libprotobuf-cpp-*
+ "libadb_pairing_connection",
+ "libadb_pairing_connection_static",
+ "libadb_pairing_server", "libadb_pairing_server_static",
+
+ // TODO(b/204811222) support suffix in cc_binary
+ "acvp_modulewrapper",
+ "android.hardware.media.c2@1.0-service-v4l2",
+ "app_process",
+ "bar_test",
+ "bench_cxa_atexit",
+ "bench_noop",
+ "bench_noop_nostl",
+ "bench_noop_static",
+ "boringssl_self_test",
+ "boringssl_self_test_vendor",
+ "bssl",
+ "cavp",
+ "crash_dump",
+ "crasher",
+ "libcxx_test_template",
+ "linker",
+ "memory_replay",
+ "native_bridge_guest_linker",
+ "native_bridge_stub_library_defaults",
+ "noop",
+ "simpleperf_ndk",
+ "toybox-static",
+ "zlib_bench",
+ }
+)
diff --git a/android/apex.go b/android/apex.go
index cf1bcfe..b127f74 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -113,9 +113,6 @@
for _, sdk := range i.RequiredSdks {
name += "_" + sdk.Name + "_" + sdk.Version
}
- if i.UsePlatformApis {
- name += "_private"
- }
return name
}
@@ -546,10 +543,9 @@
merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...)
merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
- if merged[index].UsePlatformApis != apexInfo.UsePlatformApis {
- panic(fmt.Errorf("variants having different UsePlatformApis can't be merged"))
- }
- merged[index].UsePlatformApis = apexInfo.UsePlatformApis
+ // Platform APIs is allowed for this module only when all APEXes containing
+ // the module are with `use_platform_apis: true`.
+ merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
} else {
seen[mergedName] = len(merged)
apexInfo.ApexVariationName = mergedName
diff --git a/android/apex_test.go b/android/apex_test.go
index 60a639b..1e2f3bd 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -118,17 +118,30 @@
},
},
{
- name: "don't merge different UsePlatformApis",
+ name: "merge different UsePlatformApis but don't allow using platform api",
in: []ApexInfo{
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
{"bar", FutureApiLevel, false, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
},
wantMerged: []ApexInfo{
- {"apex10000_private", FutureApiLevel, false, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
- {"apex10000", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, false, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
},
wantAliases: [][2]string{
- {"bar", "apex10000_private"},
+ {"bar", "apex10000"},
+ {"foo", "apex10000"},
+ },
+ },
+ {
+ name: "merge same UsePlatformApis and allow using platform api",
+ in: []ApexInfo{
+ {"foo", FutureApiLevel, false, true, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"bar", FutureApiLevel, false, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ },
+ wantMerged: []ApexInfo{
+ {"apex10000", FutureApiLevel, false, true, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ },
+ wantAliases: [][2]string{
+ {"bar", "apex10000"},
{"foo", "apex10000"},
},
},
diff --git a/android/api_levels.go b/android/api_levels.go
index 27a3b7f..8163894 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -19,6 +19,7 @@
"fmt"
"strconv"
+ "android/soong/bazel"
"android/soong/starlark_fmt"
)
@@ -393,10 +394,10 @@
}
func StarlarkApiLevelConfigs(config Config) string {
- return fmt.Sprintf(`# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+ return fmt.Sprintf(bazel.GeneratedBazelFileWarning+`
_api_levels = %s
api_levels = _api_levels
`, printApiLevelsStarlarkDict(config),
)
-}
\ No newline at end of file
+}
diff --git a/android/bazel.go b/android/bazel.go
index af5de12..4ef8d78 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -24,6 +24,15 @@
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android/allowlists"
+)
+
+const (
+ // A sentinel value to be used as a key in Bp2BuildConfig for modules with
+ // no package path. This is also the module dir for top level Android.bp
+ // modules.
+ Bp2BuildTopLevel = "."
)
type bazelModuleProperties struct {
@@ -87,7 +96,7 @@
HandcraftedLabel() string
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
ShouldConvertWithBp2build(ctx BazelConversionContext) bool
- shouldConvertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool
+ shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool
GetBazelBuildFileContents(c Config, path, name string) (string, error)
ConvertWithBp2build(ctx TopDownMutatorContext)
@@ -161,231 +170,13 @@
return "" // no label for unconverted module
}
-// Configuration to decide if modules in a directory should default to true/false for bp2build_available
-type Bp2BuildConfig map[string]BazelConversionConfigEntry
-type BazelConversionConfigEntry int
+type bp2BuildConversionAllowlist struct {
+ // Configure modules in these directories to enable bp2build_available: true or false by default.
+ defaultConfig allowlists.Bp2BuildConfig
-const (
- // A sentinel value to be used as a key in Bp2BuildConfig for modules with
- // no package path. This is also the module dir for top level Android.bp
- // modules.
- BP2BUILD_TOPLEVEL = "."
-
- // iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map,
- // which can also mean that the key doesn't exist in a lookup.
-
- // all modules in this package and subpackages default to bp2build_available: true.
- // allows modules to opt-out.
- Bp2BuildDefaultTrueRecursively BazelConversionConfigEntry = iota + 1
-
- // all modules in this package (not recursively) default to bp2build_available: true.
- // allows modules to opt-out.
- Bp2BuildDefaultTrue
-
- // all modules in this package (not recursively) default to bp2build_available: false.
- // allows modules to opt-in.
- Bp2BuildDefaultFalse
-)
-
-var (
// Keep any existing BUILD files (and do not generate new BUILD files) for these directories
// in the synthetic Bazel workspace.
- bp2buildKeepExistingBuildFile = map[string]bool{
- // This is actually build/bazel/build.BAZEL symlinked to ./BUILD
- ".":/*recursive = */ false,
-
- // build/bazel/examples/apex/... BUILD files should be generated, so
- // build/bazel is not recursive. Instead list each subdirectory under
- // build/bazel explicitly.
- "build/bazel":/* recursive = */ false,
- "build/bazel/ci/dist":/* recursive = */ false,
- "build/bazel/examples/android_app":/* recursive = */ true,
- "build/bazel/examples/java":/* recursive = */ true,
- "build/bazel/bazel_skylib":/* recursive = */ true,
- "build/bazel/rules":/* recursive = */ true,
- "build/bazel/rules_cc":/* recursive = */ true,
- "build/bazel/scripts":/* recursive = */ true,
- "build/bazel/tests":/* recursive = */ true,
- "build/bazel/platforms":/* recursive = */ true,
- "build/bazel/product_variables":/* recursive = */ true,
- "build/bazel/vendor/google":/* recursive = */ true,
- "build/bazel_common_rules":/* recursive = */ true,
- // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
- "build/make/tools":/* recursive = */ false,
- "build/pesto":/* 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
- "external/bazelbuild-rules_android":/* recursive = */ true,
- "external/bazel-skylib":/* recursive = */ true,
- "external/guava":/* recursive = */ true,
- "external/jsr305":/* recursive = */ true,
- "frameworks/ex/common":/* recursive = */ true,
-
- "packages/apps/Music":/* recursive = */ true,
- "packages/apps/QuickSearchBox":/* recursive = */ true,
- "packages/apps/WallpaperPicker":/* recursive = */ false,
-
- "prebuilts/bundletool":/* recursive = */ true,
- "prebuilts/gcc":/* recursive = */ true,
- "prebuilts/build-tools":/* recursive = */ false,
- "prebuilts/jdk/jdk11":/* recursive = */ false,
- "prebuilts/sdk":/* recursive = */ false,
- "prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
- "prebuilts/sdk/current/support":/* recursive = */ false,
- "prebuilts/sdk/tools":/* recursive = */ false,
- "prebuilts/r8":/* recursive = */ false,
- }
-
- // Configure modules in these directories to enable bp2build_available: true or false by default.
- bp2buildDefaultConfig = Bp2BuildConfig{
- "art/libartpalette": Bp2BuildDefaultTrueRecursively,
- "art/libdexfile": Bp2BuildDefaultTrueRecursively,
- "art/runtime": Bp2BuildDefaultTrueRecursively,
- "art/tools": Bp2BuildDefaultTrue,
- "bionic": Bp2BuildDefaultTrueRecursively,
- "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
- "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
- "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
- "build/make/tools/signapk": Bp2BuildDefaultTrue,
- "build/make/target/product/security": Bp2BuildDefaultTrue,
- "build/soong": Bp2BuildDefaultTrue,
- "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
- "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
- "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
- "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
- "build/soong/scripts": Bp2BuildDefaultTrueRecursively,
- "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
- "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
- "development/apps/Fallback": Bp2BuildDefaultTrue,
- "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
- "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
- "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
- "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
- "development/samples/Compass": Bp2BuildDefaultTrue,
- "development/samples/ContactManager": Bp2BuildDefaultTrue,
- "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
- "development/samples/HelloEffects": Bp2BuildDefaultTrue,
- "development/samples/Home": Bp2BuildDefaultTrue,
- "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
- "development/samples/JetBoy": Bp2BuildDefaultTrue,
- "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
- "development/samples/LceDemo": Bp2BuildDefaultTrue,
- "development/samples/LunarLander": Bp2BuildDefaultTrue,
- "development/samples/MultiResolution": Bp2BuildDefaultTrue,
- "development/samples/MultiWindow": Bp2BuildDefaultTrue,
- "development/samples/NotePad": Bp2BuildDefaultTrue,
- "development/samples/Obb": Bp2BuildDefaultTrue,
- "development/samples/RSSReader": Bp2BuildDefaultTrue,
- "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
- "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
- "development/samples/SipDemo": Bp2BuildDefaultTrue,
- "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
- "development/samples/Snake": Bp2BuildDefaultTrue,
- "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
- "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
- "development/samples/ToyVpn": Bp2BuildDefaultTrue,
- "development/samples/TtsEngine": Bp2BuildDefaultTrue,
- "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
- "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
- "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
- "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
- "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
- "development/sdk": Bp2BuildDefaultTrueRecursively,
- "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
- "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
- "external/auto/common": Bp2BuildDefaultTrueRecursively,
- "external/auto/service": Bp2BuildDefaultTrueRecursively,
- "external/boringssl": Bp2BuildDefaultTrueRecursively,
- "external/bouncycastle": Bp2BuildDefaultTrue,
- "external/brotli": Bp2BuildDefaultTrue,
- "external/conscrypt": Bp2BuildDefaultTrue,
- "external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
- "external/error_prone": Bp2BuildDefaultTrueRecursively,
- "external/fmtlib": Bp2BuildDefaultTrueRecursively,
- "external/google-benchmark": Bp2BuildDefaultTrueRecursively,
- "external/googletest": Bp2BuildDefaultTrueRecursively,
- "external/gwp_asan": Bp2BuildDefaultTrueRecursively,
- "external/icu": Bp2BuildDefaultTrueRecursively,
- "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/javapoet": Bp2BuildDefaultTrueRecursively,
- "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
- "external/jsoncpp": Bp2BuildDefaultTrueRecursively,
- "external/libcap": Bp2BuildDefaultTrueRecursively,
- "external/libcxx": Bp2BuildDefaultTrueRecursively,
- "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
- "external/libevent": Bp2BuildDefaultTrueRecursively,
- "external/libpng": Bp2BuildDefaultTrueRecursively,
- "external/lz4/lib": Bp2BuildDefaultTrue,
- "external/lzma/C": Bp2BuildDefaultTrueRecursively,
- "external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
- "external/minijail": Bp2BuildDefaultTrueRecursively,
- "external/pcre": Bp2BuildDefaultTrueRecursively,
- "external/protobuf": Bp2BuildDefaultTrueRecursively,
- "external/python/six": Bp2BuildDefaultTrueRecursively,
- "external/scudo": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
- "external/zlib": Bp2BuildDefaultTrueRecursively,
- "external/zstd": Bp2BuildDefaultTrueRecursively,
- "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
- "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
- "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
- "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
- "libnativehelper": Bp2BuildDefaultTrueRecursively,
- "packages/apps/DevCamera": Bp2BuildDefaultTrue,
- "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
- "packages/apps/Protips": Bp2BuildDefaultTrue,
- "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb": Bp2BuildDefaultTrue,
- "packages/modules/adb/apex": Bp2BuildDefaultTrue,
- "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_auth": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
- "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue,
- "packages/screensavers/Basic": Bp2BuildDefaultTrue,
- "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
- "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
- "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
- "prebuilts/sdk/tools/jetifier/jetifier-standalone": Bp2BuildDefaultTrue,
- "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
- "system/apex/proto": Bp2BuildDefaultTrueRecursively,
- "system/apex/libs": Bp2BuildDefaultTrueRecursively,
- "system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
- "system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
- "system/core/libasyncio": Bp2BuildDefaultTrue,
- "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
- "system/core/libcutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively,
- "system/core/libprocessgroup": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
- "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
- "system/core/libutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
- "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
- "system/libbase": Bp2BuildDefaultTrueRecursively,
- "system/libprocinfo": Bp2BuildDefaultTrue,
- "system/libziparchive": Bp2BuildDefaultTrueRecursively,
- "system/logging/liblog": Bp2BuildDefaultTrueRecursively,
- "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
- "system/timezone/apex": Bp2BuildDefaultTrueRecursively,
- "system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
- "system/unwinding/libbacktrace": Bp2BuildDefaultTrueRecursively,
- "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
- "tools/apksig": Bp2BuildDefaultTrue,
- "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
- }
+ keepExistingBuildFile map[string]bool
// Per-module allowlist to always opt modules in of both bp2build and mixed builds.
// These modules are usually in directories with many other modules that are not ready for
@@ -393,278 +184,150 @@
//
// A module can either be in this list or its directory allowlisted entirely
// in bp2buildDefaultConfig, but not both at the same time.
- bp2buildModuleAlwaysConvertList = []string{
- //external/avb
- "avbtool",
- "libavb",
- "avb_headers",
-
- //external/fec
- "libfec_rs",
-
- //system/core/libsparse
- "libsparse",
-
- //system/extras/ext4_utils
- "libext4_utils",
-
- //system/extras/libfec
- "libfec",
-
- //system/extras/squashfs_utils
- "libsquashfs_utils",
-
- //system/extras/verity/fec
- "fec",
-
- //packages/apps/Car/libs/car-ui-lib/car-ui-androidx
- // genrule dependencies for java_imports
- "car-ui-androidx-annotation-nodeps",
- "car-ui-androidx-collection-nodeps",
- "car-ui-androidx-core-common-nodeps",
- "car-ui-androidx-lifecycle-common-nodeps",
- "car-ui-androidx-constraintlayout-solver-nodeps",
- }
+ moduleAlwaysConvert map[string]bool
// Per-module-type allowlist to always opt modules in to both bp2build and mixed builds
// when they have the same type as one listed.
- bp2buildModuleTypeAlwaysConvertList = []string{
- "java_import",
- "java_import_host",
- }
+ moduleTypeAlwaysConvert map[string]bool
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
- bp2buildModuleDoNotConvertList = []string{
- "libnativehelper_compat_libc", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99
-
- "libart", // depends on unconverted modules: art_operator_srcs, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libcpu_features, libdexfile, libartpalette, libbacktrace, libnativebridge, libnativeloader, libsigchain, libunwindstack, libartbase, libprofile, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, libstatssocket, heapprofd_client_api
- "libart-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libbacktrace, libartbase-art-gtest
- "libart_headers", // depends on unconverted modules: art_libartbase_headers
- "libartd", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, libstatssocket, heapprofd_client_api, art_operator_srcs, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libcpu_features, libdexfiled, libartpalette, libbacktrace, libnativebridge, libnativeloader, libsigchain, libunwindstack, libartbased, libprofiled, cpp-define-generator-asm-support
- "libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libbacktrace, libartbased-art-gtest
- "libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
- "statslog_art.h", "statslog_art.cpp", // depends on unconverted modules: stats-log-api-gen
-
- "libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
- "libcmd", // depends on unconverted modules: libbinder
-
- "libdexfile_support_static", // Depends on unconverted module: libdexfile_external_headers
- "libunwindstack_local", "libunwindstack_utils", "libc_malloc_debug", "libfdtrack", // Depends on unconverted module: libunwindstack
-
- "libdexfile_support", // TODO(b/210546943): Enabled based on product variables.
- "libdexfile_external_headers", // TODO(b/210546943): Enabled based on product variables.
-
- "libunwindstack", // Depends on unconverted module libdexfile_support.
- "libnativehelper_compat_libc++", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99
-
- "chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol
-
- "libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules
-
- "gen-kotlin-build-file.py", // module has same name as source
-
- "libactivitymanager_aidl", // TODO(b/207426160): Depends on activity_manager_procstate_aidl, which is an aidl filegroup.
-
- "libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libgmock_ndk
- "libnativetesthelper_jni", "libgmock_main_ndk", "libgmock_ndk", // depends on unconverted module: libgtest_ndk_c++
-
- "statslog-framework-java-gen", "statslog.cpp", "statslog.h", "statslog.rs", "statslog_header.rs", // depends on unconverted modules: stats-log-api-gen
-
- "stats-log-api-gen", // depends on unconverted modules: libstats_proto_host, libprotobuf-cpp-full
-
- "libstatslog", // depends on unconverted modules: statslog.cpp, statslog.h, ...
-
- "cmd", // depends on unconverted module packagemanager_aidl-cpp, of unsupported type aidl_interface
- "servicedispatcher", // depends on unconverted module android.debug_aidl, of unsupported type aidl_interface
- "libutilscallstack", // depends on unconverted module libbacktrace
- "libbacktrace", // depends on unconverted module libunwindstack
- "libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
- "libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
- "unwind_for_offline", // depends on unconverted module libunwindstack_utils
- "libdebuggerd", // depends on unconverted modules libdexfile_support, libunwindstack, gwp_asan_crash_handler, libtombstone_proto, libprotobuf-cpp-lite
- "libdexfile_static", // depends on libartpalette, libartbase, libdexfile, which are of unsupported type: art_cc_library.
-
- "static_crasher", // depends on unconverted modules: libdebuggerd_handler
-
- "pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
-
- "libbase_ndk", // http://b/186826477, fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
-
- "libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups
- "libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups
- "libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
- "host-libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
- "libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups
- "apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full
- "conscrypt", // b/210751803, we don't handle path property for filegroups
- "conscrypt-for-host", // b/210751803, we don't handle path property for filegroups
-
- "libprotobuf-java-nano", // b/220869005, depends on non-public_current SDK
- "host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano
-
- "libc_musl_sysroot_bionic_arch_headers", // b/218405924, depends on soong_zip
- "libc_musl_sysroot_bionic_headers", // b/218405924, depends on soong_zip and generates duplicate srcs
-
- // python protos
- "libprotobuf-python", // contains .proto sources
- "conv_linker_config", // depends on linker_config_proto, a python lib with proto sources
- "apex_build_info_proto", "apex_manifest_proto", // a python lib with proto sources
- "linker_config_proto", // contains .proto sources
-
- "brotli-fuzzer-corpus", // b/202015218: outputs are in location incompatible with bazel genrule handling.
-
- // python modules
- "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
-
- // b/203369847: multiple genrules in the same package creating the same file
- // //development/sdk/...
- "platform_tools_properties",
- "build_tools_source_properties",
-
- // APEX support
- "com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
-
- "libgtest_ndk_c++", // b/201816222: Requires sdk_version support.
- "libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support.
-
- "abb", // depends on unconverted modules: libcmd, libbinder
- "adb", // depends on unconverted modules: AdbWinApi, libadb_host, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
- "libadb_host", // depends on unconverted modules: libopenscreen-discovery, libopenscreen-platform-impl, libusb, AdbWinApi
- "libfastdeploy_host", // depends on unconverted modules: libandroidfw, libusb, AdbWinApi
- "linker", // depends on unconverted modules: libdebuggerd_handler_fallback
- "linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
- "versioner", // depends on unconverted modules: libclang_cxx_host, libLLVM_host, of unsupported type llvm_host_prebuilt_library_shared
-
- "linkerconfig", // http://b/202876379 has arch-variant static_executable
- "mdnsd", // http://b/202876379 has arch-variant static_executable
-
- "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
-
- "libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
- "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
-
- // go deps:
- "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.
- "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
- "robolectric_tzdata", // depends on soong_zip, a go binary
- "libc_musl_sysroot_libc++_headers", "libc_musl_sysroot_libc++abi_headers", // depends on soong_zip, zip2zip
-
- "android_icu4j_srcgen_binary", // Bazel build error: deps not allowed without srcs; move to runtime_deps
- "core-icu4j-for-host", // Bazel build error: deps not allowed without srcs; move to runtime_deps
-
- // java deps
- "android_icu4j_srcgen", // depends on unconverted modules: currysrc
- "bin2c_fastdeployagent", // depends on deployagent, a java binary
- "currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
- "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
- "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
-
- "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
-
- "art-script", // depends on unconverted modules: dalvikvm, dex2oat
- "dex2oat-script", // depends on unconverted modules: dex2oat
-
- "prebuilt_car-ui-androidx-core-common", // 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
-
- "libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
- }
+ moduleDoNotConvert map[string]bool
// Per-module denylist of cc_library modules to only generate the static
// variant if their shared variant isn't ready or buildable by Bazel.
- bp2buildCcLibraryStaticOnlyList = []string{}
+ ccLibraryStaticOnly map[string]bool
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
- mixedBuildsDisabledList = []string{
- "art_libdexfile_dex_instruction_list_header", // breaks libart_mterp.armng, header not found
+ mixedBuildsDisabled map[string]bool
+}
- "libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
- "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
-
- "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
- "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
- "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
-
- // Depends on libprotobuf-cpp-*
- "libadb_pairing_connection",
- "libadb_pairing_connection_static",
- "libadb_pairing_server", "libadb_pairing_server_static",
-
- // TODO(b/204811222) support suffix in cc_binary
- "acvp_modulewrapper",
- "android.hardware.media.c2@1.0-service-v4l2",
- "app_process",
- "bar_test",
- "bench_cxa_atexit",
- "bench_noop",
- "bench_noop_nostl",
- "bench_noop_static",
- "boringssl_self_test",
- "boringssl_self_test_vendor",
- "bssl",
- "cavp",
- "crash_dump",
- "crasher",
- "libcxx_test_template",
- "linker",
- "memory_replay",
- "native_bridge_guest_linker",
- "native_bridge_stub_library_defaults",
- "noop",
- "simpleperf_ndk",
- "toybox-static",
- "zlib_bench",
- }
-
- // Used for quicker lookups
- bp2buildModuleDoNotConvert = map[string]bool{}
- bp2buildModuleAlwaysConvert = map[string]bool{}
- bp2buildModuleTypeAlwaysConvert = map[string]bool{}
- bp2buildCcLibraryStaticOnly = map[string]bool{}
- mixedBuildsDisabled = map[string]bool{}
-)
-
-func init() {
- for _, moduleName := range bp2buildModuleAlwaysConvertList {
- bp2buildModuleAlwaysConvert[moduleName] = true
- }
-
- for _, moduleType := range bp2buildModuleTypeAlwaysConvertList {
- bp2buildModuleTypeAlwaysConvert[moduleType] = true
- }
-
- for _, moduleName := range bp2buildModuleDoNotConvertList {
- bp2buildModuleDoNotConvert[moduleName] = true
- }
-
- for _, moduleName := range bp2buildCcLibraryStaticOnlyList {
- bp2buildCcLibraryStaticOnly[moduleName] = true
- }
-
- for _, moduleName := range mixedBuildsDisabledList {
- mixedBuildsDisabled[moduleName] = true
+// NewBp2BuildAllowlist creates a new, empty bp2BuildConversionAllowlist
+// which can be populated using builder pattern Set* methods
+func NewBp2BuildAllowlist() bp2BuildConversionAllowlist {
+ return bp2BuildConversionAllowlist{
+ allowlists.Bp2BuildConfig{},
+ map[string]bool{},
+ map[string]bool{},
+ map[string]bool{},
+ map[string]bool{},
+ map[string]bool{},
+ map[string]bool{},
}
}
+// SetDefaultConfig copies the entries from defaultConfig into the allowlist
+func (a bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) bp2BuildConversionAllowlist {
+ if a.defaultConfig == nil {
+ a.defaultConfig = allowlists.Bp2BuildConfig{}
+ }
+ for k, v := range defaultConfig {
+ a.defaultConfig[k] = v
+ }
+
+ return a
+}
+
+// SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist
+func (a bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) bp2BuildConversionAllowlist {
+ if a.keepExistingBuildFile == nil {
+ a.keepExistingBuildFile = map[string]bool{}
+ }
+ for k, v := range keepExistingBuildFile {
+ a.keepExistingBuildFile[k] = v
+ }
+
+ return a
+}
+
+// SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist
+func (a bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) bp2BuildConversionAllowlist {
+ if a.moduleAlwaysConvert == nil {
+ a.moduleAlwaysConvert = map[string]bool{}
+ }
+ for _, m := range moduleAlwaysConvert {
+ a.moduleAlwaysConvert[m] = true
+ }
+
+ return a
+}
+
+// SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist
+func (a bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) bp2BuildConversionAllowlist {
+ if a.moduleTypeAlwaysConvert == nil {
+ a.moduleTypeAlwaysConvert = map[string]bool{}
+ }
+ for _, m := range moduleTypeAlwaysConvert {
+ a.moduleTypeAlwaysConvert[m] = true
+ }
+
+ return a
+}
+
+// SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist
+func (a bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) bp2BuildConversionAllowlist {
+ if a.moduleDoNotConvert == nil {
+ a.moduleDoNotConvert = map[string]bool{}
+ }
+ for _, m := range moduleDoNotConvert {
+ a.moduleDoNotConvert[m] = true
+ }
+
+ return a
+}
+
+// SetCcLibraryStaticOnlyList copies the entries from ccLibraryStaticOnly into the allowlist
+func (a bp2BuildConversionAllowlist) SetCcLibraryStaticOnlyList(ccLibraryStaticOnly []string) bp2BuildConversionAllowlist {
+ if a.ccLibraryStaticOnly == nil {
+ a.ccLibraryStaticOnly = map[string]bool{}
+ }
+ for _, m := range ccLibraryStaticOnly {
+ a.ccLibraryStaticOnly[m] = true
+ }
+
+ return a
+}
+
+// SetMixedBuildsDisabledList copies the entries from mixedBuildsDisabled into the allowlist
+func (a bp2BuildConversionAllowlist) SetMixedBuildsDisabledList(mixedBuildsDisabled []string) bp2BuildConversionAllowlist {
+ if a.mixedBuildsDisabled == nil {
+ a.mixedBuildsDisabled = map[string]bool{}
+ }
+ for _, m := range mixedBuildsDisabled {
+ a.mixedBuildsDisabled[m] = true
+ }
+
+ return a
+}
+
+var bp2buildAllowlist = NewBp2BuildAllowlist().
+ SetDefaultConfig(allowlists.Bp2buildDefaultConfig).
+ SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile).
+ SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList).
+ SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList).
+ SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList).
+ SetCcLibraryStaticOnlyList(allowlists.Bp2buildCcLibraryStaticOnlyList).
+ SetMixedBuildsDisabledList(allowlists.MixedBuildsDisabledList)
+
+// GenerateCcLibraryStaticOnly returns whether a cc_library module should only
+// generate a static version of itself based on the current global configuration.
func GenerateCcLibraryStaticOnly(moduleName string) bool {
- return bp2buildCcLibraryStaticOnly[moduleName]
+ return bp2buildAllowlist.ccLibraryStaticOnly[moduleName]
}
+// ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be
+// added to the build symlink forest based on the current global configuration.
func ShouldKeepExistingBuildFileForDir(dir string) bool {
- if _, ok := bp2buildKeepExistingBuildFile[dir]; ok {
+ return shouldKeepExistingBuildFileForDir(bp2buildAllowlist, dir)
+}
+
+func shouldKeepExistingBuildFileForDir(allowlist bp2BuildConversionAllowlist, dir string) bool {
+ if _, ok := allowlist.keepExistingBuildFile[dir]; ok {
// Exact dir match
return true
}
// Check if subtree match
- for prefix, recursive := range bp2buildKeepExistingBuildFile {
+ for prefix, recursive := range allowlist.keepExistingBuildFile {
if recursive {
if strings.HasPrefix(dir, prefix+"/") {
return true
@@ -698,7 +361,7 @@
// variants of a cc_library.
return false
}
- return !mixedBuildsDisabled[ctx.Module().Name()]
+ return !bp2buildAllowlist.mixedBuildsDisabled[ctx.Module().Name()]
}
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
@@ -710,53 +373,66 @@
return b.shouldConvertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
}
-// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
+// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx BazelConversionContext) bool {
return b.shouldConvertWithBp2build(ctx, ctx.Module())
}
-func (b *BazelModuleBase) shouldConvertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool {
- moduleName := module.Name()
- moduleNameAllowed := bp2buildModuleAlwaysConvert[moduleName]
- moduleTypeAllowed := bp2buildModuleTypeAlwaysConvert[ctx.OtherModuleType(module)]
- allowlistConvert := moduleNameAllowed || moduleTypeAllowed
- if moduleNameAllowed && moduleTypeAllowed {
- ctx.(BaseModuleContext).ModuleErrorf("A module cannot be in bp2buildModuleAlwaysConvert and also be" +
- " in bp2buildModuleTypeAlwaysConvert")
- }
+type bazelOtherModuleContext interface {
+ ModuleErrorf(format string, args ...interface{})
+ Config() Config
+ OtherModuleType(m blueprint.Module) string
+ OtherModuleName(m blueprint.Module) string
+ OtherModuleDir(m blueprint.Module) string
+}
- if bp2buildModuleDoNotConvert[moduleName] {
- if moduleNameAllowed {
- ctx.(BaseModuleContext).ModuleErrorf("a module cannot be in bp2buildModuleDoNotConvert" +
- " and also be in bp2buildModuleAlwaysConvert")
- }
- return false
- }
-
+func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool {
if !b.bazelProps().Bazel_module.CanConvertToBazel {
return false
}
propValue := b.bazelProperties.Bazel_module.Bp2build_available
packagePath := ctx.OtherModuleDir(module)
+
// Modules in unit tests which are enabled in the allowlist by type or name
// trigger this conditional because unit tests run under the "." package path
- isTestModule := packagePath == "." && proptools.BoolDefault(propValue, false)
- if allowlistConvert && !isTestModule && ShouldKeepExistingBuildFileForDir(packagePath) {
+ isTestModule := packagePath == Bp2BuildTopLevel && proptools.BoolDefault(propValue, false)
+ if isTestModule {
+ return true
+ }
+
+ moduleName := module.Name()
+ allowlist := ctx.Config().bp2buildPackageConfig
+ moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
+ moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[ctx.OtherModuleType(module)]
+ allowlistConvert := moduleNameAllowed || moduleTypeAllowed
+ if moduleNameAllowed && moduleTypeAllowed {
+ ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert")
+ return false
+ }
+
+ if allowlist.moduleDoNotConvert[moduleName] {
if moduleNameAllowed {
- ctx.(BaseModuleContext).ModuleErrorf("A module cannot be in a directory listed in bp2buildKeepExistingBuildFile"+
- " and also be in bp2buildModuleAlwaysConvert. Directory: '%s'", packagePath)
+ ctx.ModuleErrorf("a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert")
}
return false
}
- config := ctx.Config().bp2buildPackageConfig
- // This is a tristate value: true, false, or unset.
- if bp2buildDefaultTrueRecursively(packagePath, config) {
+ if allowlistConvert && shouldKeepExistingBuildFileForDir(allowlist, packagePath) {
if moduleNameAllowed {
- ctx.(BaseModuleContext).ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
- " or Bp2BuildDefaultTrueRecursively and also be in bp2buildModuleAlwaysConvert. Directory: '%s'",
- packagePath)
+ ctx.ModuleErrorf("A module cannot be in a directory listed in keepExistingBuildFile"+
+ " and also be in moduleAlwaysConvert. Directory: '%s'", packagePath)
+ return false
+ }
+ }
+
+ // This is a tristate value: true, false, or unset.
+ if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
+ if moduleNameAllowed {
+ ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
+ " or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'",
+ directoryPath)
+ return false
}
// Allow modules to explicitly opt-out.
@@ -777,14 +453,16 @@
//
// This function will also return false if the package doesn't match anything in
// the config.
-func bp2buildDefaultTrueRecursively(packagePath string, config Bp2BuildConfig) bool {
- ret := false
-
+//
+// This function will also return the allowlist entry which caused a particular
+// package to be enabled. Since packages can be enabled via a recursive declaration,
+// the path returned will not always be the same as the one provided.
+func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2BuildConfig) (bool, string) {
// Check if the package path has an exact match in the config.
- if config[packagePath] == Bp2BuildDefaultTrue || config[packagePath] == Bp2BuildDefaultTrueRecursively {
- return true
- } else if config[packagePath] == Bp2BuildDefaultFalse {
- return false
+ if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
+ return true, packagePath
+ } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse {
+ return false, packagePath
}
// If not, check for the config recursively.
@@ -792,15 +470,15 @@
// e.g. for x/y/z, iterate over x, x/y, then x/y/z, taking the final value from the allowlist.
for _, part := range strings.Split(packagePath, "/") {
packagePrefix += part
- if config[packagePrefix] == Bp2BuildDefaultTrueRecursively {
+ if config[packagePrefix] == allowlists.Bp2BuildDefaultTrueRecursively {
// package contains this prefix and this prefix should convert all modules
- return true
+ return true, packagePrefix
}
// Continue to the next part of the package dir.
packagePrefix += "/"
}
- return ret
+ return false, packagePath
}
// GetBazelBuildFileContents returns the file contents of a hand-crafted BUILD file if available or
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index f353a9d..fa10f62 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -79,6 +79,7 @@
OtherModuleType(m blueprint.Module) string
OtherModuleName(m blueprint.Module) string
OtherModuleDir(m blueprint.Module) string
+ ModuleErrorf(format string, args ...interface{})
}
// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
diff --git a/android/bazel_test.go b/android/bazel_test.go
index e5d8fbb..482df2a 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -13,59 +13,67 @@
// limitations under the License.
package android
-import "testing"
+import (
+ "android/soong/android/allowlists"
+ "android/soong/bazel"
+ "fmt"
+ "testing"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
func TestConvertAllModulesInPackage(t *testing.T) {
testCases := []struct {
- prefixes Bp2BuildConfig
+ prefixes allowlists.Bp2BuildConfig
packageDir string
}{
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a",
},
{
- prefixes: Bp2BuildConfig{
- "a/b": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a/b": Bp2BuildDefaultTrueRecursively,
- "a/b/c": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultTrueRecursively,
- "d/e/f": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultFalse,
- "a/b": Bp2BuildDefaultTrueRecursively,
- "a/b/c": Bp2BuildDefaultFalse,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalse,
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b/c": allowlists.Bp2BuildDefaultFalse,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultTrueRecursively,
- "a/b": Bp2BuildDefaultFalse,
- "a/b/c": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b": allowlists.Bp2BuildDefaultFalse,
+ "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a",
},
}
for _, test := range testCases {
- if !bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes) {
+ if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); !ok {
t.Errorf("Expected to convert all modules in %s based on %v, but failed.", test.packageDir, test.prefixes)
}
}
@@ -73,62 +81,308 @@
func TestModuleOptIn(t *testing.T) {
testCases := []struct {
- prefixes Bp2BuildConfig
+ prefixes allowlists.Bp2BuildConfig
packageDir string
}{
{
- prefixes: Bp2BuildConfig{
- "a/b": Bp2BuildDefaultFalse,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a/b": allowlists.Bp2BuildDefaultFalse,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultFalse,
- "a/b": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalse,
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a",
},
{
- prefixes: Bp2BuildConfig{
- "a/b": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a", // opt-in by default
},
{
- prefixes: Bp2BuildConfig{
- "a/b/c": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultTrueRecursively,
- "d/e/f": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "foo/bar",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultTrueRecursively,
- "a/b": Bp2BuildDefaultFalse,
- "a/b/c": Bp2BuildDefaultTrueRecursively,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b": allowlists.Bp2BuildDefaultFalse,
+ "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
},
packageDir: "a/b",
},
{
- prefixes: Bp2BuildConfig{
- "a": Bp2BuildDefaultFalse,
- "a/b": Bp2BuildDefaultTrueRecursively,
- "a/b/c": Bp2BuildDefaultFalse,
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalse,
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b/c": allowlists.Bp2BuildDefaultFalse,
},
packageDir: "a",
},
}
for _, test := range testCases {
- if bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes) {
+ if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); ok {
t.Errorf("Expected to allow module opt-in in %s based on %v, but failed.", test.packageDir, test.prefixes)
}
}
}
+
+type TestBazelModule struct {
+ bazel.TestModuleInfo
+ BazelModuleBase
+}
+
+var _ blueprint.Module = TestBazelModule{}
+
+func (m TestBazelModule) Name() string {
+ return m.TestModuleInfo.ModuleName
+}
+
+func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) {
+}
+
+type TestBazelConversionContext struct {
+ omc bazel.OtherModuleTestContext
+ allowlist bp2BuildConversionAllowlist
+ errors []string
+}
+
+var _ bazelOtherModuleContext = &TestBazelConversionContext{}
+
+func (bcc *TestBazelConversionContext) OtherModuleType(m blueprint.Module) string {
+ return bcc.omc.OtherModuleType(m)
+}
+
+func (bcc *TestBazelConversionContext) OtherModuleName(m blueprint.Module) string {
+ return bcc.omc.OtherModuleName(m)
+}
+
+func (bcc *TestBazelConversionContext) OtherModuleDir(m blueprint.Module) string {
+ return bcc.omc.OtherModuleDir(m)
+}
+
+func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...interface{}) {
+ bcc.errors = append(bcc.errors, fmt.Sprintf(format, args...))
+}
+
+func (bcc *TestBazelConversionContext) Config() Config {
+ return Config{
+ &config{
+ bp2buildPackageConfig: bcc.allowlist,
+ },
+ }
+}
+
+var bazelableBazelModuleBase = BazelModuleBase{
+ bazelProperties: properties{
+ Bazel_module: bazelModuleProperties{
+ CanConvertToBazel: true,
+ },
+ },
+}
+
+func TestBp2BuildAllowlist(t *testing.T) {
+ testCases := []struct {
+ description string
+ shouldConvert bool
+ expectedErrors []string
+ module TestBazelModule
+ allowlist bp2BuildConversionAllowlist
+ }{
+ {
+ description: "allowlist enables module",
+ shouldConvert: true,
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "dir1",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ },
+ },
+ {
+ description: "module in name allowlist and type allowlist fails",
+ shouldConvert: false,
+ expectedErrors: []string{"A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "dir1",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ moduleTypeAlwaysConvert: map[string]bool{
+ "rule1": true,
+ },
+ },
+ },
+ {
+ description: "module in allowlist and denylist fails",
+ shouldConvert: false,
+ expectedErrors: []string{"a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "dir1",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ moduleDoNotConvert: map[string]bool{
+ "foo": true,
+ },
+ },
+ },
+ {
+ description: "module in allowlist and existing BUILD file",
+ shouldConvert: false,
+ expectedErrors: []string{"A module cannot be in a directory listed in keepExistingBuildFile and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "existing/build/dir",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ keepExistingBuildFile: map[string]bool{
+ "existing/build/dir": true,
+ },
+ },
+ },
+ {
+ description: "module allowlist and enabled directory",
+ shouldConvert: false,
+ expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "existing/build/dir",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ defaultConfig: allowlists.Bp2BuildConfig{
+ "existing/build/dir": allowlists.Bp2BuildDefaultTrue,
+ },
+ },
+ },
+ {
+ description: "module allowlist and enabled subdirectory",
+ shouldConvert: false,
+ expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: "existing/build/dir/subdir",
+ },
+ BazelModuleBase: bazelableBazelModuleBase,
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ defaultConfig: allowlists.Bp2BuildConfig{
+ "existing/build/dir": allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ },
+ },
+ {
+ description: "module enabled in unit test short-circuits other allowlists",
+ shouldConvert: true,
+ module: TestBazelModule{
+ TestModuleInfo: bazel.TestModuleInfo{
+ ModuleName: "foo",
+ Typ: "rule1",
+ Dir: ".",
+ },
+ BazelModuleBase: BazelModuleBase{
+ bazelProperties: properties{
+ Bazel_module: bazelModuleProperties{
+ CanConvertToBazel: true,
+ Bp2build_available: proptools.BoolPtr(true),
+ },
+ },
+ },
+ },
+ allowlist: bp2BuildConversionAllowlist{
+ moduleAlwaysConvert: map[string]bool{
+ "foo": true,
+ },
+ moduleDoNotConvert: map[string]bool{
+ "foo": true,
+ },
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.description, func(t *testing.T) {
+ bcc := &TestBazelConversionContext{
+ omc: bazel.OtherModuleTestContext{
+ Modules: []bazel.TestModuleInfo{
+ test.module.TestModuleInfo,
+ },
+ },
+ allowlist: test.allowlist,
+ }
+
+ shouldConvert := test.module.shouldConvertWithBp2build(bcc, test.module.TestModuleInfo)
+ if test.shouldConvert != shouldConvert {
+ t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert)
+ }
+
+ errorsMatch := true
+ if len(test.expectedErrors) != len(bcc.errors) {
+ errorsMatch = false
+ } else {
+ for i, err := range test.expectedErrors {
+ if err != bcc.errors[i] {
+ errorsMatch = false
+ }
+ }
+ }
+ if !errorsMatch {
+ t.Errorf("Expected errors to be: %v, but were: %v", test.expectedErrors, bcc.errors)
+ }
+ })
+ }
+}
diff --git a/android/config.go b/android/config.go
index 5c41ee8..cb2fc61 100644
--- a/android/config.go
+++ b/android/config.go
@@ -158,7 +158,7 @@
mockBpList string
runningAsBp2Build bool
- bp2buildPackageConfig Bp2BuildConfig
+ bp2buildPackageConfig bp2BuildConversionAllowlist
Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
@@ -550,7 +550,7 @@
}
config.BazelContext, err = NewBazelContext(config)
- config.bp2buildPackageConfig = bp2buildDefaultConfig
+ config.bp2buildPackageConfig = bp2buildAllowlist
return Config{config}, err
}
@@ -1360,6 +1360,10 @@
return "", false
}
+func (c *deviceConfig) ApexGlobalMinSdkVersionOverride() string {
+ return String(c.config.productVariables.ApexGlobalMinSdkVersionOverride)
+}
+
func (c *config) IntegerOverflowDisabledForPath(path string) bool {
if len(c.productVariables.IntegerOverflowExcludePaths) == 0 {
return false
diff --git a/android/config_bp2build.go b/android/config_bp2build.go
new file mode 100644
index 0000000..748be62
--- /dev/null
+++ b/android/config_bp2build.go
@@ -0,0 +1,487 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "reflect"
+ "regexp"
+ "sort"
+ "strings"
+
+ "android/soong/bazel"
+ "android/soong/starlark_fmt"
+
+ "github.com/google/blueprint"
+)
+
+// BazelVarExporter is a collection of configuration variables that can be exported for use in Bazel rules
+type BazelVarExporter interface {
+ // asBazel expands strings of configuration variables into their concrete values
+ asBazel(Config, ExportedStringVariables, ExportedStringListVariables, ExportedConfigDependingVariables) []bazelConstant
+}
+
+// ExportedVariables is a collection of interdependent configuration variables
+type ExportedVariables struct {
+ // Maps containing toolchain variables that are independent of the
+ // environment variables of the build.
+ exportedStringVars ExportedStringVariables
+ exportedStringListVars ExportedStringListVariables
+ exportedStringListDictVars ExportedStringListDictVariables
+
+ exportedVariableReferenceDictVars ExportedVariableReferenceDictVariables
+
+ /// Maps containing variables that are dependent on the build config.
+ exportedConfigDependingVars ExportedConfigDependingVariables
+
+ pctx PackageContext
+}
+
+// NewExportedVariables creats an empty ExportedVariables struct with non-nil maps
+func NewExportedVariables(pctx PackageContext) ExportedVariables {
+ return ExportedVariables{
+ exportedStringVars: ExportedStringVariables{},
+ exportedStringListVars: ExportedStringListVariables{},
+ exportedStringListDictVars: ExportedStringListDictVariables{},
+ exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{},
+ exportedConfigDependingVars: ExportedConfigDependingVariables{},
+ pctx: pctx,
+ }
+}
+
+func (ev ExportedVariables) asBazel(config Config,
+ stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
+ ret := []bazelConstant{}
+ ret = append(ret, ev.exportedStringVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
+ ret = append(ret, ev.exportedStringListVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
+ ret = append(ret, ev.exportedStringListDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
+ // Note: ExportedVariableReferenceDictVars collections can only contain references to other variables and must be printed last
+ ret = append(ret, ev.exportedVariableReferenceDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
+ return ret
+}
+
+// ExportStringStaticVariable declares a static string variable and exports it to
+// Bazel's toolchain.
+func (ev ExportedVariables) ExportStringStaticVariable(name string, value string) {
+ ev.pctx.StaticVariable(name, value)
+ ev.exportedStringVars.set(name, value)
+}
+
+// ExportStringListStaticVariable declares a static variable and exports it to
+// Bazel's toolchain.
+func (ev ExportedVariables) ExportStringListStaticVariable(name string, value []string) {
+ ev.pctx.StaticVariable(name, strings.Join(value, " "))
+ ev.exportedStringListVars.set(name, value)
+}
+
+// ExportVariableConfigMethod declares a variable whose value is evaluated at
+// runtime via a function with access to the Config and exports it to Bazel's
+// toolchain.
+func (ev ExportedVariables) ExportVariableConfigMethod(name string, method interface{}) blueprint.Variable {
+ ev.exportedConfigDependingVars.set(name, method)
+ return ev.pctx.VariableConfigMethod(name, method)
+}
+
+// ExportSourcePathVariable declares a static "source path" variable and exports
+// it to Bazel's toolchain.
+func (ev ExportedVariables) ExportSourcePathVariable(name string, value string) {
+ ev.pctx.SourcePathVariable(name, value)
+ ev.exportedStringVars.set(name, value)
+}
+
+// ExportVariableFuncVariable declares a variable whose value is evaluated at
+// runtime via a function and exports it to Bazel's toolchain.
+func (ev ExportedVariables) ExportVariableFuncVariable(name string, f func() string) {
+ ev.exportedConfigDependingVars.set(name, func(config Config) string {
+ return f()
+ })
+ ev.pctx.VariableFunc(name, func(PackageVarContext) string {
+ return f()
+ })
+}
+
+// ExportString only exports a variable to Bazel, but does not declare it in Soong
+func (ev ExportedVariables) ExportString(name string, value string) {
+ ev.exportedStringVars.set(name, value)
+}
+
+// ExportStringList only exports a variable to Bazel, but does not declare it in Soong
+func (ev ExportedVariables) ExportStringList(name string, value []string) {
+ ev.exportedStringListVars.set(name, value)
+}
+
+// ExportStringListDict only exports a variable to Bazel, but does not declare it in Soong
+func (ev ExportedVariables) ExportStringListDict(name string, value map[string][]string) {
+ ev.exportedStringListDictVars.set(name, value)
+}
+
+// ExportVariableReferenceDict only exports a variable to Bazel, but does not declare it in Soong
+func (ev ExportedVariables) ExportVariableReferenceDict(name string, value map[string]string) {
+ ev.exportedVariableReferenceDictVars.set(name, value)
+}
+
+// ExportedConfigDependingVariables is a mapping of variable names to functions
+// of type func(config Config) string which return the runtime-evaluated string
+// value of a particular variable
+type ExportedConfigDependingVariables map[string]interface{}
+
+func (m ExportedConfigDependingVariables) set(k string, v interface{}) {
+ m[k] = v
+}
+
+// Ensure that string s has no invalid characters to be generated into the bzl file.
+func validateCharacters(s string) string {
+ for _, c := range []string{`\n`, `"`, `\`} {
+ if strings.Contains(s, c) {
+ panic(fmt.Errorf("%s contains illegal character %s", s, c))
+ }
+ }
+ return s
+}
+
+type bazelConstant struct {
+ variableName string
+ internalDefinition string
+ sortLast bool
+}
+
+// ExportedStringVariables is a mapping of variable names to string values
+type ExportedStringVariables map[string]string
+
+func (m ExportedStringVariables) set(k string, v string) {
+ m[k] = v
+}
+
+func (m ExportedStringVariables) asBazel(config Config,
+ stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for k, variableValue := range m {
+ expandedVar, err := expandVar(config, variableValue, stringVars, stringListVars, cfgDepVars)
+ if err != nil {
+ panic(fmt.Errorf("error expanding config variable %s: %s", k, err))
+ }
+ if len(expandedVar) > 1 {
+ panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
+ }
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
+ })
+ }
+ return ret
+}
+
+// ExportedStringListVariables is a mapping of variable names to a list of strings
+type ExportedStringListVariables map[string][]string
+
+func (m ExportedStringListVariables) set(k string, v []string) {
+ m[k] = v
+}
+
+func (m ExportedStringListVariables) asBazel(config Config,
+ stringScope ExportedStringVariables, stringListScope ExportedStringListVariables,
+ exportedVars ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ // For each exported variable, recursively expand elements in the variableValue
+ // list to ensure that interpolated variables are expanded according to their values
+ // in the variable scope.
+ for k, variableValue := range m {
+ var expandedVars []string
+ for _, v := range variableValue {
+ expandedVar, err := expandVar(config, v, stringScope, stringListScope, exportedVars)
+ if err != nil {
+ panic(fmt.Errorf("Error expanding config variable %s=%s: %s", k, v, err))
+ }
+ expandedVars = append(expandedVars, expandedVar...)
+ }
+ // Assign the list as a bzl-private variable; this variable will be exported
+ // out through a constants struct later.
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
+ })
+ }
+ return ret
+}
+
+// ExportedStringListDictVariables is a mapping from variable names to a
+// dictionary which maps keys to lists of strings
+type ExportedStringListDictVariables map[string]map[string][]string
+
+func (m ExportedStringListDictVariables) set(k string, v map[string][]string) {
+ m[k] = v
+}
+
+// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
+func (m ExportedStringListDictVariables) asBazel(_ Config, _ ExportedStringVariables,
+ _ ExportedStringListVariables, _ ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for k, dict := range m {
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: starlark_fmt.PrintStringListDict(dict, 0),
+ })
+ }
+ return ret
+}
+
+// ExportedVariableReferenceDictVariables is a mapping from variable names to a
+// dictionary which references previously defined variables. This is used to
+// create a Starlark output such as:
+// string_var1 = "string1
+// var_ref_dict_var1 = {
+// "key1": string_var1
+// }
+// This type of variable collection must be expanded last so that it recognizes
+// previously defined variables.
+type ExportedVariableReferenceDictVariables map[string]map[string]string
+
+func (m ExportedVariableReferenceDictVariables) set(k string, v map[string]string) {
+ m[k] = v
+}
+
+func (m ExportedVariableReferenceDictVariables) asBazel(_ Config, _ ExportedStringVariables,
+ _ ExportedStringListVariables, _ ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for n, dict := range m {
+ for k, v := range dict {
+ matches, err := variableReference(v)
+ if err != nil {
+ panic(err)
+ } else if !matches.matches {
+ panic(fmt.Errorf("Expected a variable reference, got %q", v))
+ } else if len(matches.fullVariableReference) != len(v) {
+ panic(fmt.Errorf("Expected only a variable reference, got %q", v))
+ }
+ dict[k] = "_" + matches.variable
+ }
+ ret = append(ret, bazelConstant{
+ variableName: n,
+ internalDefinition: starlark_fmt.PrintDict(dict, 0),
+ sortLast: true,
+ })
+ }
+ return ret
+}
+
+// BazelToolchainVars expands an ExportedVariables collection and returns a string
+// of formatted Starlark variable definitions
+func BazelToolchainVars(config Config, exportedVars ExportedVariables) string {
+ results := exportedVars.asBazel(
+ config,
+ exportedVars.exportedStringVars,
+ exportedVars.exportedStringListVars,
+ exportedVars.exportedConfigDependingVars,
+ )
+
+ sort.Slice(results, func(i, j int) bool {
+ if results[i].sortLast != results[j].sortLast {
+ return !results[i].sortLast
+ }
+ return results[i].variableName < results[j].variableName
+ })
+
+ definitions := make([]string, 0, len(results))
+ constants := make([]string, 0, len(results))
+ for _, b := range results {
+ definitions = append(definitions,
+ fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
+ constants = append(constants,
+ fmt.Sprintf("%[1]s%[2]s = _%[2]s,", starlark_fmt.Indention(1), b.variableName))
+ }
+
+ // Build the exported constants struct.
+ ret := bazel.GeneratedBazelFileWarning
+ ret += "\n\n"
+ ret += strings.Join(definitions, "\n\n")
+ ret += "\n\n"
+ ret += "constants = struct(\n"
+ ret += strings.Join(constants, "\n")
+ ret += "\n)"
+
+ return ret
+}
+
+type match struct {
+ matches bool
+ fullVariableReference string
+ variable string
+}
+
+func variableReference(input string) (match, error) {
+ // e.g. "${ExternalCflags}"
+ r := regexp.MustCompile(`\${(?:config\.)?([a-zA-Z0-9_]+)}`)
+
+ matches := r.FindStringSubmatch(input)
+ if len(matches) == 0 {
+ return match{}, nil
+ }
+ if len(matches) != 2 {
+ return match{}, fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", input, len(matches)-1)
+ }
+ return match{
+ matches: true,
+ fullVariableReference: matches[0],
+ // Index 1 of FindStringSubmatch contains the subexpression match
+ // (variable name) of the capture group.
+ variable: matches[1],
+ }, nil
+}
+
+// expandVar recursively expand interpolated variables in the exportedVars scope.
+//
+// We're using a string slice to track the seen variables to avoid
+// stackoverflow errors with infinite recursion. it's simpler to use a
+// string slice than to handle a pass-by-referenced map, which would make it
+// quite complex to track depth-first interpolations. It's also unlikely the
+// interpolation stacks are deep (n > 1).
+func expandVar(config Config, toExpand string, stringScope ExportedStringVariables,
+ stringListScope ExportedStringListVariables, exportedVars ExportedConfigDependingVariables) ([]string, error) {
+
+ // Internal recursive function.
+ var expandVarInternal func(string, map[string]bool) (string, error)
+ expandVarInternal = func(toExpand string, seenVars map[string]bool) (string, error) {
+ var ret string
+ remainingString := toExpand
+ for len(remainingString) > 0 {
+ matches, err := variableReference(remainingString)
+ if err != nil {
+ panic(err)
+ }
+ if !matches.matches {
+ return ret + remainingString, nil
+ }
+ matchIndex := strings.Index(remainingString, matches.fullVariableReference)
+ ret += remainingString[:matchIndex]
+ remainingString = remainingString[matchIndex+len(matches.fullVariableReference):]
+
+ variable := matches.variable
+ // toExpand contains a variable.
+ if _, ok := seenVars[variable]; ok {
+ return ret, fmt.Errorf(
+ "Unbounded recursive interpolation of variable: %s", variable)
+ }
+ // A map is passed-by-reference. Create a new map for
+ // this scope to prevent variables seen in one depth-first expansion
+ // to be also treated as "seen" in other depth-first traversals.
+ newSeenVars := map[string]bool{}
+ for k := range seenVars {
+ newSeenVars[k] = true
+ }
+ newSeenVars[variable] = true
+ if unexpandedVars, ok := stringListScope[variable]; ok {
+ expandedVars := []string{}
+ for _, unexpandedVar := range unexpandedVars {
+ expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
+ if err != nil {
+ return ret, err
+ }
+ expandedVars = append(expandedVars, expandedVar)
+ }
+ ret += strings.Join(expandedVars, " ")
+ } else if unexpandedVar, ok := stringScope[variable]; ok {
+ expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
+ if err != nil {
+ return ret, err
+ }
+ ret += expandedVar
+ } else if unevaluatedVar, ok := exportedVars[variable]; ok {
+ evalFunc := reflect.ValueOf(unevaluatedVar)
+ validateVariableMethod(variable, evalFunc)
+ evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
+ evaluatedValue := evaluatedResult[0].Interface().(string)
+ expandedVar, err := expandVarInternal(evaluatedValue, newSeenVars)
+ if err != nil {
+ return ret, err
+ }
+ ret += expandedVar
+ } else {
+ return "", fmt.Errorf("Unbound config variable %s", variable)
+ }
+ }
+ return ret, nil
+ }
+ var ret []string
+ stringFields := splitStringKeepingQuotedSubstring(toExpand, ' ')
+ for _, v := range stringFields {
+ val, err := expandVarInternal(v, map[string]bool{})
+ if err != nil {
+ return ret, err
+ }
+ ret = append(ret, val)
+ }
+
+ return ret, nil
+}
+
+// splitStringKeepingQuotedSubstring splits a string on a provided separator,
+// but it will not split substrings inside unescaped double quotes. If the double
+// quotes are escaped, then the returned string will only include the quote, and
+// not the escape.
+func splitStringKeepingQuotedSubstring(s string, delimiter byte) []string {
+ var ret []string
+ quote := byte('"')
+
+ var substring []byte
+ quoted := false
+ escaped := false
+
+ for i := range s {
+ if !quoted && s[i] == delimiter {
+ ret = append(ret, string(substring))
+ substring = []byte{}
+ continue
+ }
+
+ characterIsEscape := i < len(s)-1 && s[i] == '\\' && s[i+1] == quote
+ if characterIsEscape {
+ escaped = true
+ continue
+ }
+
+ if s[i] == quote {
+ if !escaped {
+ quoted = !quoted
+ }
+ escaped = false
+ }
+
+ substring = append(substring, s[i])
+ }
+
+ ret = append(ret, string(substring))
+
+ return ret
+}
+
+func validateVariableMethod(name string, methodValue reflect.Value) {
+ methodType := methodValue.Type()
+ if methodType.Kind() != reflect.Func {
+ panic(fmt.Errorf("method given for variable %s is not a function",
+ name))
+ }
+ if n := methodType.NumIn(); n != 1 {
+ panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)",
+ name, n))
+ }
+ if n := methodType.NumOut(); n != 1 {
+ panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)",
+ name, n))
+ }
+ if kind := methodType.Out(0).Kind(); kind != reflect.String {
+ panic(fmt.Errorf("method for variable %s does not return a string",
+ name))
+ }
+}
diff --git a/android/config_bp2build_test.go b/android/config_bp2build_test.go
new file mode 100644
index 0000000..1a0ba7b
--- /dev/null
+++ b/android/config_bp2build_test.go
@@ -0,0 +1,454 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "android/soong/bazel"
+ "testing"
+)
+
+func TestExpandVars(t *testing.T) {
+ android_arm64_config := TestConfig("out", nil, "", nil)
+ android_arm64_config.BuildOS = Android
+ android_arm64_config.BuildArch = Arm64
+
+ testCases := []struct {
+ description string
+ config Config
+ stringScope ExportedStringVariables
+ stringListScope ExportedStringListVariables
+ configVars ExportedConfigDependingVariables
+ toExpand string
+ expectedValues []string
+ }{
+ {
+ description: "no expansion for non-interpolated value",
+ toExpand: "foo",
+ expectedValues: []string{"foo"},
+ },
+ {
+ description: "single level expansion for string var",
+ stringScope: ExportedStringVariables{
+ "foo": "bar",
+ },
+ toExpand: "${foo}",
+ expectedValues: []string{"bar"},
+ },
+ {
+ description: "single level expansion with short-name for string var",
+ stringScope: ExportedStringVariables{
+ "foo": "bar",
+ },
+ toExpand: "${config.foo}",
+ expectedValues: []string{"bar"},
+ },
+ {
+ description: "single level expansion string list var",
+ stringListScope: ExportedStringListVariables{
+ "foo": []string{"bar"},
+ },
+ toExpand: "${foo}",
+ expectedValues: []string{"bar"},
+ },
+ {
+ description: "mixed level expansion for string list var",
+ stringScope: ExportedStringVariables{
+ "foo": "${bar}",
+ "qux": "hello",
+ },
+ stringListScope: ExportedStringListVariables{
+ "bar": []string{"baz", "${qux}"},
+ },
+ toExpand: "${foo}",
+ expectedValues: []string{"baz hello"},
+ },
+ {
+ description: "double level expansion",
+ stringListScope: ExportedStringListVariables{
+ "foo": []string{"${bar}"},
+ "bar": []string{"baz"},
+ },
+ toExpand: "${foo}",
+ expectedValues: []string{"baz"},
+ },
+ {
+ description: "double level expansion with a literal",
+ stringListScope: ExportedStringListVariables{
+ "a": []string{"${b}", "c"},
+ "b": []string{"d"},
+ },
+ toExpand: "${a}",
+ expectedValues: []string{"d c"},
+ },
+ {
+ description: "double level expansion, with two variables in a string",
+ stringListScope: ExportedStringListVariables{
+ "a": []string{"${b} ${c}"},
+ "b": []string{"d"},
+ "c": []string{"e"},
+ },
+ toExpand: "${a}",
+ expectedValues: []string{"d e"},
+ },
+ {
+ description: "triple level expansion with two variables in a string",
+ stringListScope: ExportedStringListVariables{
+ "a": []string{"${b} ${c}"},
+ "b": []string{"${c}", "${d}"},
+ "c": []string{"${d}"},
+ "d": []string{"foo"},
+ },
+ toExpand: "${a}",
+ expectedValues: []string{"foo foo foo"},
+ },
+ {
+ description: "expansion with config depending vars",
+ configVars: ExportedConfigDependingVariables{
+ "a": func(c Config) string { return c.BuildOS.String() },
+ "b": func(c Config) string { return c.BuildArch.String() },
+ },
+ config: android_arm64_config,
+ toExpand: "${a}-${b}",
+ expectedValues: []string{"android-arm64"},
+ },
+ {
+ description: "double level multi type expansion",
+ stringListScope: ExportedStringListVariables{
+ "platform": []string{"${os}-${arch}"},
+ "const": []string{"const"},
+ },
+ configVars: ExportedConfigDependingVariables{
+ "os": func(c Config) string { return c.BuildOS.String() },
+ "arch": func(c Config) string { return c.BuildArch.String() },
+ "foo": func(c Config) string { return "foo" },
+ },
+ config: android_arm64_config,
+ toExpand: "${const}/${platform}/${foo}",
+ expectedValues: []string{"const/android-arm64/foo"},
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.description, func(t *testing.T) {
+ output, _ := expandVar(testCase.config, testCase.toExpand, testCase.stringScope, testCase.stringListScope, testCase.configVars)
+ if len(output) != len(testCase.expectedValues) {
+ t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output))
+ }
+ for i, actual := range output {
+ expectedValue := testCase.expectedValues[i]
+ if actual != expectedValue {
+ t.Errorf("Actual value '%s' doesn't match expected value '%s'", actual, expectedValue)
+ }
+ }
+ })
+ }
+}
+
+func TestBazelToolchainVars(t *testing.T) {
+ testCases := []struct {
+ name string
+ config Config
+ vars ExportedVariables
+ expectedOut string
+ }{
+ {
+ name: "exports strings",
+ vars: ExportedVariables{
+ exportedStringVars: ExportedStringVariables{
+ "a": "b",
+ "c": "d",
+ },
+ },
+ expectedOut: bazel.GeneratedBazelFileWarning + `
+
+_a = "b"
+
+_c = "d"
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "exports string lists",
+ vars: ExportedVariables{
+ exportedStringListVars: ExportedStringListVariables{
+ "a": []string{"b1", "b2"},
+ "c": []string{"d1", "d2"},
+ },
+ },
+ expectedOut: bazel.GeneratedBazelFileWarning + `
+
+_a = [
+ "b1",
+ "b2",
+]
+
+_c = [
+ "d1",
+ "d2",
+]
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "exports string lists dicts",
+ vars: ExportedVariables{
+ exportedStringListDictVars: ExportedStringListDictVariables{
+ "a": map[string][]string{"b1": {"b2"}},
+ "c": map[string][]string{"d1": {"d2"}},
+ },
+ },
+ expectedOut: bazel.GeneratedBazelFileWarning + `
+
+_a = {
+ "b1": ["b2"],
+}
+
+_c = {
+ "d1": ["d2"],
+}
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "exports dict with var refs",
+ vars: ExportedVariables{
+ exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{
+ "a": map[string]string{"b1": "${b2}"},
+ "c": map[string]string{"d1": "${config.d2}"},
+ },
+ },
+ expectedOut: bazel.GeneratedBazelFileWarning + `
+
+_a = {
+ "b1": _b2,
+}
+
+_c = {
+ "d1": _d2,
+}
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "sorts across types with variable references last",
+ vars: ExportedVariables{
+ exportedStringVars: ExportedStringVariables{
+ "b": "b-val",
+ "d": "d-val",
+ },
+ exportedStringListVars: ExportedStringListVariables{
+ "c": []string{"c-val"},
+ "e": []string{"e-val"},
+ },
+ exportedStringListDictVars: ExportedStringListDictVariables{
+ "a": map[string][]string{"a1": {"a2"}},
+ "f": map[string][]string{"f1": {"f2"}},
+ },
+ exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{
+ "aa": map[string]string{"b1": "${b}"},
+ "cc": map[string]string{"d1": "${config.d}"},
+ },
+ },
+ expectedOut: bazel.GeneratedBazelFileWarning + `
+
+_a = {
+ "a1": ["a2"],
+}
+
+_b = "b-val"
+
+_c = ["c-val"]
+
+_d = "d-val"
+
+_e = ["e-val"]
+
+_f = {
+ "f1": ["f2"],
+}
+
+_aa = {
+ "b1": _b,
+}
+
+_cc = {
+ "d1": _d,
+}
+
+constants = struct(
+ a = _a,
+ b = _b,
+ c = _c,
+ d = _d,
+ e = _e,
+ f = _f,
+ aa = _aa,
+ cc = _cc,
+)`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ out := BazelToolchainVars(tc.config, tc.vars)
+ if out != tc.expectedOut {
+ t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
+ }
+ })
+ }
+}
+
+func TestSplitStringKeepingQuotedSubstring(t *testing.T) {
+ testCases := []struct {
+ description string
+ s string
+ delimiter byte
+ split []string
+ }{
+ {
+ description: "empty string returns single empty string",
+ s: "",
+ delimiter: ' ',
+ split: []string{
+ "",
+ },
+ },
+ {
+ description: "string with single space returns two empty strings",
+ s: " ",
+ delimiter: ' ',
+ split: []string{
+ "",
+ "",
+ },
+ },
+ {
+ description: "string with two spaces returns three empty strings",
+ s: " ",
+ delimiter: ' ',
+ split: []string{
+ "",
+ "",
+ "",
+ },
+ },
+ {
+ description: "string with four words returns four word string",
+ s: "hello world with words",
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ "world",
+ "with",
+ "words",
+ },
+ },
+ {
+ description: "string with words and nested quote returns word strings and quote string",
+ s: `hello "world with" words`,
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ `"world with"`,
+ "words",
+ },
+ },
+ {
+ description: "string with escaped quote inside real quotes",
+ s: `hello \"world "with\" words"`,
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ `"world`,
+ `"with" words"`,
+ },
+ },
+ {
+ description: "string with words and escaped quotes returns word strings",
+ s: `hello \"world with\" words`,
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ `"world`,
+ `with"`,
+ "words",
+ },
+ },
+ {
+ description: "string which is single quoted substring returns only substring",
+ s: `"hello world with words"`,
+ delimiter: ' ',
+ split: []string{
+ `"hello world with words"`,
+ },
+ },
+ {
+ description: "string starting with quote returns quoted string",
+ s: `"hello world with" words`,
+ delimiter: ' ',
+ split: []string{
+ `"hello world with"`,
+ "words",
+ },
+ },
+ {
+ description: "string with starting quote and no ending quote returns quote to end of string",
+ s: `hello "world with words`,
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ `"world with words`,
+ },
+ },
+ {
+ description: "quoted string is treated as a single \"word\" unless separated by delimiter",
+ s: `hello "world"with words`,
+ delimiter: ' ',
+ split: []string{
+ "hello",
+ `"world"with`,
+ "words",
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ split := splitStringKeepingQuotedSubstring(tc.s, tc.delimiter)
+ if len(split) != len(tc.split) {
+ t.Fatalf("number of split string elements (%d) differs from expected (%d): split string (%v), expected (%v)",
+ len(split), len(tc.split), split, tc.split,
+ )
+ }
+ for i := range split {
+ if split[i] != tc.split[i] {
+ t.Errorf("split string element (%d), %v, differs from expected, %v", i, split[i], tc.split[i])
+ }
+ }
+ })
+ }
+}
diff --git a/android/testing.go b/android/testing.go
index a9632e9..ac02db9 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -211,7 +211,7 @@
ctx.finalDeps = append(ctx.finalDeps, f)
}
-func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConfig) {
+func (ctx *TestContext) RegisterBp2BuildConfig(config bp2BuildConversionAllowlist) {
ctx.config.bp2buildPackageConfig = config
}
diff --git a/android/variable.go b/android/variable.go
index 4ed0507..077b810 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -389,6 +389,8 @@
CertificateOverrides []string `json:",omitempty"`
PackageNameOverrides []string `json:",omitempty"`
+ ApexGlobalMinSdkVersionOverride *string `json:",omitempty"`
+
EnforceSystemCertificate *bool `json:",omitempty"`
EnforceSystemCertificateAllowList []string `json:",omitempty"`
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 2176361..afde68b 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1690,6 +1690,21 @@
}
`,
},
+ {
+ desc: "convert android_app to android_test when having test_suites",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_COMPATIBILITY_SUITE := bar
+include $(BUILD_PACKAGE)
+ `,
+ expected: `
+android_test {
+ name: "foo",
+ test_suites: ["bar"],
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/Android.bp b/apex/Android.bp
index b9b5428..41224ec 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -14,6 +14,7 @@
"soong-cc",
"soong-filesystem",
"soong-java",
+ "soong-provenance",
"soong-python",
"soong-rust",
"soong-sh",
diff --git a/apex/apex.go b/apex/apex.go
index 2fe17da..a7b0a4f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2450,20 +2450,43 @@
android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
}
+// Returns apex's min_sdk_version string value, honoring overrides
+func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
+ // Only override the minSdkVersion value on Apexes which already specify
+ // a min_sdk_version (it's optional for non-updatable apexes), and that its
+ // min_sdk_version value is lower than the one to override with.
+ overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
+ overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
+ originalMinApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
+ isMinSdkSet := a.properties.Min_sdk_version != nil
+ isOverrideValueHigher := overrideApiLevel.CompareTo(originalMinApiLevel) > 0
+ if overrideMinSdkValue != "" && isMinSdkSet && isOverrideValueHigher {
+ return overrideMinSdkValue
+ }
+
+ return proptools.String(a.properties.Min_sdk_version)
+}
+
+// Returns apex's min_sdk_version SdkSpec, honoring overrides
func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return android.SdkSpec{
Kind: android.SdkNone,
ApiLevel: a.minSdkVersion(ctx),
- Raw: String(a.properties.Min_sdk_version),
+ Raw: a.minSdkVersionValue(ctx),
}
}
+// Returns apex's min_sdk_version ApiLevel, honoring overrides
func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- ver := proptools.String(a.properties.Min_sdk_version)
- if ver == "" {
+ return minSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
+}
+
+// Construct ApiLevel object from min_sdk_version string value
+func minSdkVersionFromValue(ctx android.EarlyModuleContext, value string) android.ApiLevel {
+ if value == "" {
return android.NoneApiLevel
}
- apiLevel, err := android.ApiLevelFromUser(ctx, ver)
+ apiLevel, err := android.ApiLevelFromUser(ctx, value)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
return android.NoneApiLevel
@@ -2518,7 +2541,7 @@
// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes.
func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
if a.Updatable() {
- if String(a.properties.Min_sdk_version) == "" {
+ if a.minSdkVersionValue(ctx) == "" {
ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
}
if a.UsePlatformApis() {
@@ -3398,6 +3421,8 @@
fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.properties.File_contexts))
}
+ // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
+ // given it's coming via config, we probably don't want to put it in here.
var minSdkVersion *string
if a.properties.Min_sdk_version != nil {
minSdkVersion = a.properties.Min_sdk_version
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5706a2c..77cbb58 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -113,6 +113,12 @@
})
}
+func withApexGlobalMinSdkVersionOverride(minSdkOverride *string) android.FixturePreparer {
+ return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.ApexGlobalMinSdkVersionOverride = minSdkOverride
+ })
+}
+
var withBinder32bit = android.FixtureModifyProductVariables(
func(variables android.FixtureProductVariables) {
variables.Binder32bit = proptools.BoolPtr(true)
@@ -168,44 +174,42 @@
"system/sepolicy/apex/otherapex-file_contexts": nil,
"system/sepolicy/apex/com.android.vndk-file_contexts": nil,
"system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
- "mylib.cpp": nil,
- "mytest.cpp": nil,
- "mytest1.cpp": nil,
- "mytest2.cpp": nil,
- "mytest3.cpp": nil,
- "myprebuilt": nil,
- "my_include": nil,
- "foo/bar/MyClass.java": nil,
- "prebuilt.jar": nil,
- "prebuilt.so": nil,
- "vendor/foo/devkeys/test.x509.pem": nil,
- "vendor/foo/devkeys/test.pk8": nil,
- "testkey.x509.pem": nil,
- "testkey.pk8": nil,
- "testkey.override.x509.pem": nil,
- "testkey.override.pk8": nil,
- "vendor/foo/devkeys/testkey.avbpubkey": nil,
- "vendor/foo/devkeys/testkey.pem": nil,
- "NOTICE": nil,
- "custom_notice": nil,
- "custom_notice_for_static_lib": nil,
- "testkey2.avbpubkey": nil,
- "testkey2.pem": nil,
- "myapex-arm64.apex": nil,
- "myapex-arm.apex": nil,
- "myapex.apks": nil,
- "frameworks/base/api/current.txt": nil,
- "framework/aidl/a.aidl": nil,
- "build/make/core/proguard.flags": nil,
- "build/make/core/proguard_basic_keeps.flags": nil,
- "dummy.txt": nil,
- "baz": nil,
- "bar/baz": nil,
- "testdata/baz": nil,
- "AppSet.apks": nil,
- "foo.rs": nil,
- "libfoo.jar": nil,
- "libbar.jar": nil,
+ "mylib.cpp": nil,
+ "mytest.cpp": nil,
+ "mytest1.cpp": nil,
+ "mytest2.cpp": nil,
+ "mytest3.cpp": nil,
+ "myprebuilt": nil,
+ "my_include": nil,
+ "foo/bar/MyClass.java": nil,
+ "prebuilt.jar": nil,
+ "prebuilt.so": nil,
+ "vendor/foo/devkeys/test.x509.pem": nil,
+ "vendor/foo/devkeys/test.pk8": nil,
+ "testkey.x509.pem": nil,
+ "testkey.pk8": nil,
+ "testkey.override.x509.pem": nil,
+ "testkey.override.pk8": nil,
+ "vendor/foo/devkeys/testkey.avbpubkey": nil,
+ "vendor/foo/devkeys/testkey.pem": nil,
+ "NOTICE": nil,
+ "custom_notice": nil,
+ "custom_notice_for_static_lib": nil,
+ "testkey2.avbpubkey": nil,
+ "testkey2.pem": nil,
+ "myapex-arm64.apex": nil,
+ "myapex-arm.apex": nil,
+ "myapex.apks": nil,
+ "frameworks/base/api/current.txt": nil,
+ "framework/aidl/a.aidl": nil,
+ "dummy.txt": nil,
+ "baz": nil,
+ "bar/baz": nil,
+ "testdata/baz": nil,
+ "AppSet.apks": nil,
+ "foo.rs": nil,
+ "libfoo.jar": nil,
+ "libbar.jar": nil,
},
),
@@ -1032,10 +1036,10 @@
// Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because
// of the platform_apis: true)
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000_private").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000_private").Rule("rustc").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
}
@@ -3889,7 +3893,7 @@
}),
withBinder32bit,
withTargets(map[android.OsType][]android.Target{
- android.Android: []android.Target{
+ android.Android: {
{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
},
@@ -4570,12 +4574,20 @@
}
`)
- prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
+ testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ prebuilt := testingModule.Module().(*Prebuilt)
expectedInput := "myapex-arm64.apex"
if prebuilt.inputApex.String() != expectedInput {
t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
}
+ android.AssertStringDoesContain(t, "Invalid provenance metadata file",
+ prebuilt.ProvenanceMetaDataFile().String(), "soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto")
+ rule := testingModule.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "myapex-arm64.apex", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.apex", rule.Args["install_path"])
}
func TestPrebuiltMissingSrc(t *testing.T) {
@@ -4595,12 +4607,18 @@
}
`)
- p := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
+ testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ p := testingModule.Module().(*Prebuilt)
expected := "notmyapex.apex"
if p.installFilename != expected {
t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename)
}
+ rule := testingModule.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/apex/notmyapex.apex", rule.Args["install_path"])
}
func TestApexSetFilenameOverride(t *testing.T) {
@@ -4643,13 +4661,19 @@
}
`)
- p := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt").Module().(*Prebuilt)
+ testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt")
+ p := testingModule.Module().(*Prebuilt)
expected := []string{"myapex"}
actual := android.AndroidMkEntriesForTest(t, ctx, p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
if !reflect.DeepEqual(actual, expected) {
t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
}
+ rule := testingModule.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex.prebuilt/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "myapex.prebuilt", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.prebuilt.apex", rule.Args["install_path"])
}
func TestPrebuiltApexName(t *testing.T) {
@@ -6294,6 +6318,124 @@
ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
}
+func TestMinSdkVersionOverride(t *testing.T) {
+ // Override from 29 to 31
+ minSdkOverride31 := "31"
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ updatable: true,
+ min_sdk_version: "29"
+ }
+
+ override_apex {
+ name: "override_myapex",
+ base: "myapex",
+ logging_parent: "com.foo.bar",
+ package_name: "test.overridden.package"
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ runtime_libs: ["libbar"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "apex_inherit"
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "apex_inherit"
+ }
+
+ `, withApexGlobalMinSdkVersionOverride(&minSdkOverride31))
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that direct non-stubs dep is always included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+
+ // Ensure that runtime_libs dep in included
+ ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
+
+ // Ensure libraries target overridden min_sdk_version value
+ ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_apex31")
+}
+
+func TestMinSdkVersionOverrideToLowerVersionNoOp(t *testing.T) {
+ // Attempt to override from 31 to 29, should be a NOOP
+ minSdkOverride29 := "29"
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ updatable: true,
+ min_sdk_version: "31"
+ }
+
+ override_apex {
+ name: "override_myapex",
+ base: "myapex",
+ logging_parent: "com.foo.bar",
+ package_name: "test.overridden.package"
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ runtime_libs: ["libbar"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "apex_inherit"
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "apex_inherit"
+ }
+
+ `, withApexGlobalMinSdkVersionOverride(&minSdkOverride29))
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that direct non-stubs dep is always included
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+
+ // Ensure that runtime_libs dep in included
+ ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
+
+ // Ensure libraries target the original min_sdk_version value rather than the overridden
+ ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_apex31")
+}
+
func TestLegacyAndroid10Support(t *testing.T) {
ctx := testApex(t, `
apex {
diff --git a/apex/builder.go b/apex/builder.go
index ea61e1a..293f388 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -994,7 +994,7 @@
return !externalDep
})
- a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, proptools.String(a.properties.Min_sdk_version), depInfos)
+ a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).Raw, depInfos)
ctx.Build(pctx, android.BuildParams{
Rule: android.Phony,
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 158c804..187e0df 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -23,7 +23,7 @@
"android/soong/android"
"android/soong/java"
-
+ "android/soong/provenance"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -482,6 +482,8 @@
properties PrebuiltProperties
inputApex android.Path
+
+ provenanceMetaDataFile android.OutputPath
}
type ApexFileProperties struct {
@@ -778,9 +780,14 @@
if p.installable() {
p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks.Paths()...)
+ p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
}
}
+func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath {
+ return p.provenanceMetaDataFile
+}
+
// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex
// module. It extracts the correct apex to use and makes it available for use by apex_set.
type prebuiltApexExtractorModule struct {
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 80af2bd..9e7edc7 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -10,11 +10,11 @@
"configurability.go",
"constants.go",
"properties.go",
+ "testing.go",
],
testSrcs: [
"aquery_test.go",
"properties_test.go",
- "testing.go",
],
pluginFor: [
"soong_build",
diff --git a/bazel/constants.go b/bazel/constants.go
index 6beb496..b10f256 100644
--- a/bazel/constants.go
+++ b/bazel/constants.go
@@ -21,7 +21,7 @@
SoongInjectionDirName = "soong_injection"
- GeneratedBazelFileWarning = "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT"
+ GeneratedBazelFileWarning = "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT."
)
// String returns the name of the run.
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index c7f9776..7b76b74 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -329,7 +329,7 @@
func TestPartitionLabelListAttribute(t *testing.T) {
testCases := []struct {
name string
- ctx *otherModuleTestContext
+ ctx *OtherModuleTestContext
labelList LabelListAttribute
filters LabelPartitions
expected PartitionToLabelListAttribute
@@ -337,7 +337,7 @@
}{
{
name: "no configurable values",
- ctx: &otherModuleTestContext{},
+ ctx: &OtherModuleTestContext{},
labelList: LabelListAttribute{
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
},
@@ -354,7 +354,7 @@
},
{
name: "no configurable values, remainder partition",
- ctx: &otherModuleTestContext{},
+ ctx: &OtherModuleTestContext{},
labelList: LabelListAttribute{
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
},
@@ -371,7 +371,7 @@
},
{
name: "no configurable values, empty partition",
- ctx: &otherModuleTestContext{},
+ ctx: &OtherModuleTestContext{},
labelList: LabelListAttribute{
Value: makeLabelList([]string{"a.a", "c.c"}, []string{}),
},
@@ -387,8 +387,8 @@
},
{
name: "no configurable values, has map",
- ctx: &otherModuleTestContext{
- modules: []testModuleInfo{testModuleInfo{name: "srcs", typ: "fg", dir: "dir"}},
+ ctx: &OtherModuleTestContext{
+ Modules: []TestModuleInfo{{ModuleName: "srcs", Typ: "fg", Dir: "dir"}},
},
labelList: LabelListAttribute{
Value: makeLabelList([]string{"a.a", "srcs", "b.b", "c.c"}, []string{}),
@@ -406,7 +406,7 @@
},
{
name: "configurable values, keeps empty if excludes",
- ctx: &otherModuleTestContext{},
+ ctx: &OtherModuleTestContext{},
labelList: LabelListAttribute{
ConfigurableValues: configurableLabelLists{
ArchConfigurationAxis: labelListSelectValues{
@@ -450,7 +450,7 @@
},
{
name: "error for multiple partitions same value",
- ctx: &otherModuleTestContext{},
+ ctx: &OtherModuleTestContext{},
labelList: LabelListAttribute{
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
},
diff --git a/bazel/testing.go b/bazel/testing.go
index 23c8350..9a43b61 100644
--- a/bazel/testing.go
+++ b/bazel/testing.go
@@ -20,86 +20,86 @@
"github.com/google/blueprint"
)
-// testModuleInfo implements blueprint.Module interface with sufficient information to mock a subset of
+// TestModuleInfo implements blueprint.Module interface with sufficient information to mock a subset of
// a blueprint ModuleContext
-type testModuleInfo struct {
- name string
- typ string
- dir string
+type TestModuleInfo struct {
+ ModuleName string
+ Typ string
+ Dir string
}
// Name returns name for testModuleInfo -- required to implement blueprint.Module
-func (mi testModuleInfo) Name() string {
- return mi.name
+func (mi TestModuleInfo) Name() string {
+ return mi.ModuleName
}
// GenerateBuildActions unused, but required to implmeent blueprint.Module
-func (mi testModuleInfo) GenerateBuildActions(blueprint.ModuleContext) {}
+func (mi TestModuleInfo) GenerateBuildActions(blueprint.ModuleContext) {}
-func (mi testModuleInfo) equals(other testModuleInfo) bool {
- return mi.name == other.name && mi.typ == other.typ && mi.dir == other.dir
+func (mi TestModuleInfo) equals(other TestModuleInfo) bool {
+ return mi.ModuleName == other.ModuleName && mi.Typ == other.Typ && mi.Dir == other.Dir
}
// ensure testModuleInfo implements blueprint.Module
-var _ blueprint.Module = testModuleInfo{}
+var _ blueprint.Module = TestModuleInfo{}
-// otherModuleTestContext is a mock context that implements OtherModuleContext
-type otherModuleTestContext struct {
- modules []testModuleInfo
+// OtherModuleTestContext is a mock context that implements OtherModuleContext
+type OtherModuleTestContext struct {
+ Modules []TestModuleInfo
errors []string
}
// ModuleFromName retrieves the testModuleInfo corresponding to name, if it exists
-func (omc *otherModuleTestContext) ModuleFromName(name string) (blueprint.Module, bool) {
- for _, m := range omc.modules {
- if m.name == name {
+func (omc *OtherModuleTestContext) ModuleFromName(name string) (blueprint.Module, bool) {
+ for _, m := range omc.Modules {
+ if m.ModuleName == name {
return m, true
}
}
- return testModuleInfo{}, false
+ return TestModuleInfo{}, false
}
// testModuleInfo returns the testModuleInfo corresponding to a blueprint.Module if it exists in omc
-func (omc *otherModuleTestContext) testModuleInfo(m blueprint.Module) (testModuleInfo, bool) {
- mi, ok := m.(testModuleInfo)
+func (omc *OtherModuleTestContext) testModuleInfo(m blueprint.Module) (TestModuleInfo, bool) {
+ mi, ok := m.(TestModuleInfo)
if !ok {
- return testModuleInfo{}, false
+ return TestModuleInfo{}, false
}
- for _, other := range omc.modules {
+ for _, other := range omc.Modules {
if other.equals(mi) {
return mi, true
}
}
- return testModuleInfo{}, false
+ return TestModuleInfo{}, false
}
// OtherModuleType returns type of m if it exists in omc
-func (omc *otherModuleTestContext) OtherModuleType(m blueprint.Module) string {
+func (omc *OtherModuleTestContext) OtherModuleType(m blueprint.Module) string {
if mi, ok := omc.testModuleInfo(m); ok {
- return mi.typ
+ return mi.Typ
}
return ""
}
// OtherModuleName returns name of m if it exists in omc
-func (omc *otherModuleTestContext) OtherModuleName(m blueprint.Module) string {
+func (omc *OtherModuleTestContext) OtherModuleName(m blueprint.Module) string {
if mi, ok := omc.testModuleInfo(m); ok {
- return mi.name
+ return mi.ModuleName
}
return ""
}
// OtherModuleDir returns dir of m if it exists in omc
-func (omc *otherModuleTestContext) OtherModuleDir(m blueprint.Module) string {
+func (omc *OtherModuleTestContext) OtherModuleDir(m blueprint.Module) string {
if mi, ok := omc.testModuleInfo(m); ok {
- return mi.dir
+ return mi.Dir
}
return ""
}
-func (omc *otherModuleTestContext) ModuleErrorf(format string, args ...interface{}) {
+func (omc *OtherModuleTestContext) ModuleErrorf(format string, args ...interface{}) {
omc.errors = append(omc.errors, fmt.Sprintf(format, args...))
}
// Ensure otherModuleTestContext implements OtherModuleContext
-var _ OtherModuleContext = &otherModuleTestContext{}
+var _ OtherModuleContext = &OtherModuleTestContext{}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 8a171d4..8f78968 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -18,6 +18,7 @@
],
deps: [
"soong-android",
+ "soong-android-allowlists",
"soong-android-soongconfig",
"soong-shared",
"soong-apex",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 1d3b105..a96a3fc 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -580,7 +580,9 @@
elements = append(elements, val)
}
}
- return starlark_fmt.PrintList(elements, indent, "%s"), nil
+ return starlark_fmt.PrintList(elements, indent, func(s string) string {
+ return "%s"
+ }), nil
case reflect.Struct:
// Special cases where the bp2build sends additional information to the codegenerator
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index b21a477..0f3ca79 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -20,6 +20,7 @@
"testing"
"android/soong/android"
+ "android/soong/android/allowlists"
"android/soong/python"
)
@@ -922,7 +923,7 @@
moduleTypeUnderTestFactory android.ModuleFactory
expectedCount map[string]int
description string
- bp2buildConfig android.Bp2BuildConfig
+ bp2buildConfig allowlists.Bp2BuildConfig
checkDir string
fs map[string]string
}{
@@ -937,10 +938,10 @@
"not_migrated": 0,
"also_not_migrated": 0,
},
- bp2buildConfig: android.Bp2BuildConfig{
- "migrated": android.Bp2BuildDefaultTrueRecursively,
- "migrated/but_not_really": android.Bp2BuildDefaultFalse,
- "not_migrated": android.Bp2BuildDefaultFalse,
+ bp2buildConfig: allowlists.Bp2BuildConfig{
+ "migrated": allowlists.Bp2BuildDefaultTrueRecursively,
+ "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
+ "not_migrated": allowlists.Bp2BuildDefaultFalse,
},
fs: map[string]string{
"migrated/Android.bp": `filegroup { name: "a" }`,
@@ -960,9 +961,9 @@
"package-opt-out": 1,
"package-opt-out/subpackage": 0,
},
- bp2buildConfig: android.Bp2BuildConfig{
- "package-opt-in": android.Bp2BuildDefaultFalse,
- "package-opt-out": android.Bp2BuildDefaultTrueRecursively,
+ bp2buildConfig: allowlists.Bp2BuildConfig{
+ "package-opt-in": allowlists.Bp2BuildDefaultFalse,
+ "package-opt-out": allowlists.Bp2BuildDefaultTrueRecursively,
},
fs: map[string]string{
"package-opt-in/Android.bp": `
@@ -1004,7 +1005,8 @@
config := android.TestConfig(buildDir, nil, "", fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildConfig(testCase.bp2buildConfig)
+ allowlist := android.NewBp2BuildAllowlist().SetDefaultConfig(testCase.bp2buildConfig)
+ ctx.RegisterBp2BuildConfig(allowlist)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 91e614d..1790dd7 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -7,7 +7,8 @@
"strings"
"android/soong/android"
- "android/soong/cc/config"
+ cc_config "android/soong/cc/config"
+ java_config "android/soong/java/config"
"github.com/google/blueprint/proptools"
)
@@ -22,7 +23,10 @@
var files []BazelFile
files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
- files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars(cfg)))
+ files = append(files, newFile("cc_toolchain", "constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
+
+ files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package.
+ files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg)))
files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index d65ece8..e49d855 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -95,6 +95,14 @@
basename: "constants.bzl",
},
{
+ dir: "java_toolchain",
+ basename: GeneratedBuildFileName,
+ },
+ {
+ dir: "java_toolchain",
+ basename: "constants.bzl",
+ },
+ {
dir: "metrics",
basename: "converted_modules.txt",
},
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 4b75e3b..ccc52ef 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -219,3 +219,35 @@
},
})
}
+
+func TestJavaLibraryLogTags(t *testing.T) {
+ runJavaLibraryTestCase(t, bp2buildTestCase{
+ description: "Java library - logtags creates separate dependency",
+ moduleTypeUnderTest: "java_library",
+ moduleTypeUnderTestFactory: java.LibraryFactory,
+ blueprint: `java_library {
+ name: "example_lib",
+ srcs: [
+ "a.java",
+ "b.java",
+ "a.logtag",
+ "b.logtag",
+ ],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("event_log_tags", "example_lib_logtags", attrNameToString{
+ "srcs": `[
+ "a.logtag",
+ "b.logtag",
+ ]`,
+ }),
+ makeBazelTarget("java_library", "example_lib", attrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.java",
+ ":example_lib_logtags",
+ ]`,
+ }),
+ }})
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 53b60fa..156e082 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -25,14 +25,17 @@
"testing"
"android/soong/android"
+ "android/soong/android/allowlists"
"android/soong/bazel"
)
var (
// A default configuration for tests to not have to specify bp2build_available on top level targets.
- bp2buildConfig = android.Bp2BuildConfig{
- android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
- }
+ bp2buildConfig = android.NewBp2BuildAllowlist().SetDefaultConfig(
+ allowlists.Bp2BuildConfig{
+ android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ )
buildDir string
)
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 4f7d88c..94b28dc 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -449,6 +449,7 @@
}
hasInstrumentationFor := hasNonEmptyLiteralStringProperty(mod, "instrumentation_for")
+ hasTestSuites := hasNonEmptyLiteralListProperty(mod, "test_suites")
tags, _ := getLiteralListPropertyValue(mod, "tags")
var hasTestsTag bool
@@ -458,7 +459,7 @@
}
}
- isTest := hasInstrumentationFor || hasTestsTag
+ isTest := hasInstrumentationFor || hasTestsTag || hasTestSuites
if isTest {
switch mod.Type {
@@ -470,13 +471,7 @@
mod.Type = "java_test"
case "java_library_host":
mod.Type = "java_test_host"
- }
- }
-
- // when a cc_binary module has a nonempty test_suites field, modify the type to cc_test
- if mod.Type == "cc_binary" {
- hasTestSuites := hasNonEmptyLiteralListProperty(mod, "test_suites")
- if hasTestSuites {
+ case "cc_binary":
mod.Type = "cc_test"
}
}
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 17b3c24..672e852 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -1436,6 +1436,38 @@
}
`,
},
+ {
+ name: "android_app with android_test",
+ in: `
+ android_app {
+ name: "foo",
+ srcs: ["srcs"],
+ test_suites: ["test_suite1"],
+ }
+ `,
+ out: `
+ android_test {
+ name: "foo",
+ srcs: ["srcs"],
+ test_suites: ["test_suite1"],
+ }
+ `,
+ },
+ {
+ name: "android_app without test_suites",
+ in: `
+ android_app {
+ name: "foo",
+ srcs: ["srcs"],
+ }
+ `,
+ out: `
+ android_app {
+ name: "foo",
+ srcs: ["srcs"],
+ }
+ `,
+ },
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
diff --git a/cc/afdo.go b/cc/afdo.go
index c888213..66e9732 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -45,6 +45,8 @@
}
type AfdoProperties struct {
+ // Afdo allows developers self-service enroll for
+ // automatic feedback-directed optimization using profile data.
Afdo bool
AfdoTarget *string `blueprint:"mutated"`
diff --git a/cc/cc.go b/cc/cc.go
index ac6da05..00b82d5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1218,6 +1218,17 @@
return c.VendorProperties.IsVendorPublicLibrary
}
+func (c *Module) IsVndkPrebuiltLibrary() bool {
+ if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ return true
+ }
+ return false
+}
+
+func (c *Module) SdkAndPlatformVariantVisibleToMake() bool {
+ return c.Properties.SdkAndPlatformVariantVisibleToMake
+}
+
func (c *Module) HasLlndkStubs() bool {
lib := moduleLibraryInterface(c)
return lib != nil && lib.hasLLNDKStubs()
@@ -1699,7 +1710,7 @@
return nil
}
-func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string {
+func getNameSuffixWithVndkVersion(ctx android.ModuleContext, c LinkableInterface) string {
// Returns the name suffix for product and vendor variants. If the VNDK version is not
// "current", it will append the VNDK version to the name suffix.
var vndkVersion string
@@ -1719,19 +1730,19 @@
if vndkVersion == "current" {
vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
}
- if c.Properties.VndkVersion != vndkVersion && c.Properties.VndkVersion != "" {
+ if c.VndkVersion() != vndkVersion && c.VndkVersion() != "" {
// add version suffix only if the module is using different vndk version than the
// version in product or vendor partition.
- nameSuffix += "." + c.Properties.VndkVersion
+ nameSuffix += "." + c.VndkVersion()
}
return nameSuffix
}
-func (c *Module) setSubnameProperty(actx android.ModuleContext) {
- c.Properties.SubName = ""
+func GetSubnameProperty(actx android.ModuleContext, c LinkableInterface) string {
+ var subName = ""
if c.Target().NativeBridge == android.NativeBridgeEnabled {
- c.Properties.SubName += NativeBridgeSuffix
+ subName += NativeBridgeSuffix
}
llndk := c.IsLlndk()
@@ -1739,25 +1750,27 @@
// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
// added for product variant only when we have vendor and product variants with core
// variant. The suffix is not added for vendor-only or product-only module.
- c.Properties.SubName += c.getNameSuffixWithVndkVersion(actx)
+ subName += getNameSuffixWithVndkVersion(actx, c)
} else if c.IsVendorPublicLibrary() {
- c.Properties.SubName += vendorPublicLibrarySuffix
- } else if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ subName += vendorPublicLibrarySuffix
+ } else if c.IsVndkPrebuiltLibrary() {
// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
- c.Properties.SubName += VendorSuffix
+ subName += VendorSuffix
} else if c.InRamdisk() && !c.OnlyInRamdisk() {
- c.Properties.SubName += RamdiskSuffix
+ subName += RamdiskSuffix
} else if c.InVendorRamdisk() && !c.OnlyInVendorRamdisk() {
- c.Properties.SubName += VendorRamdiskSuffix
+ subName += VendorRamdiskSuffix
} else if c.InRecovery() && !c.OnlyInRecovery() {
- c.Properties.SubName += RecoverySuffix
- } else if c.IsSdkVariant() && (c.Properties.SdkAndPlatformVariantVisibleToMake || c.SplitPerApiLevel()) {
- c.Properties.SubName += sdkSuffix
+ subName += RecoverySuffix
+ } else if c.IsSdkVariant() && (c.SdkAndPlatformVariantVisibleToMake() || c.SplitPerApiLevel()) {
+ subName += sdkSuffix
if c.SplitPerApiLevel() {
- c.Properties.SubName += "." + c.SdkVersion()
+ subName += "." + c.SdkVersion()
}
}
+
+ return subName
}
// Returns true if Bazel was successfully used for the analysis of this module.
@@ -1795,7 +1808,7 @@
return
}
- c.setSubnameProperty(actx)
+ c.Properties.SubName = GetSubnameProperty(actx, c)
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {
c.hideApexVariantFromMake = true
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index e1b0605..1a21c13 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -11,7 +11,6 @@
"soong-starlark-format",
],
srcs: [
- "bp2build.go",
"clang.go",
"global.go",
"tidy.go",
@@ -33,7 +32,6 @@
"arm64_linux_host.go",
],
testSrcs: [
- "bp2build_test.go",
"tidy_test.go",
],
}
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 4d0ae1a..dfe143f 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -98,28 +98,28 @@
pctx.SourcePathVariable("Arm64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
- exportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
- exportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
+ exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
+ exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
- exportStringListStaticVariable("Arm64Cflags", arm64Cflags)
- exportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
+ exportedVars.ExportStringListStaticVariable("Arm64Cflags", arm64Cflags)
+ exportedVars.ExportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
- exportedVariableReferenceDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflagsVar)
- exportedVariableReferenceDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflagsVar)
- exportedVariableReferenceDictVars.Set("Arm64CpuVariantLdflags", arm64CpuVariantLdflags)
+ exportedVars.ExportVariableReferenceDict("Arm64ArchVariantCflags", arm64ArchVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("Arm64CpuVariantCflags", arm64CpuVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("Arm64CpuVariantLdflags", arm64CpuVariantLdflags)
- exportStringListStaticVariable("Arm64Armv8ACflags", arm64ArchVariantCflags["armv8-a"])
- exportStringListStaticVariable("Arm64Armv8ABranchProtCflags", arm64ArchVariantCflags["armv8-a-branchprot"])
- exportStringListStaticVariable("Arm64Armv82ACflags", arm64ArchVariantCflags["armv8-2a"])
- exportStringListStaticVariable("Arm64Armv82ADotprodCflags", arm64ArchVariantCflags["armv8-2a-dotprod"])
+ exportedVars.ExportStringListStaticVariable("Arm64Armv8ACflags", arm64ArchVariantCflags["armv8-a"])
+ exportedVars.ExportStringListStaticVariable("Arm64Armv8ABranchProtCflags", arm64ArchVariantCflags["armv8-a-branchprot"])
+ exportedVars.ExportStringListStaticVariable("Arm64Armv82ACflags", arm64ArchVariantCflags["armv8-2a"])
+ exportedVars.ExportStringListStaticVariable("Arm64Armv82ADotprodCflags", arm64ArchVariantCflags["armv8-2a-dotprod"])
- exportStringListStaticVariable("Arm64CortexA53Cflags", arm64CpuVariantCflags["cortex-a53"])
- exportStringListStaticVariable("Arm64CortexA55Cflags", arm64CpuVariantCflags["cortex-a55"])
- exportStringListStaticVariable("Arm64KryoCflags", arm64CpuVariantCflags["kryo"])
- exportStringListStaticVariable("Arm64ExynosM1Cflags", arm64CpuVariantCflags["exynos-m1"])
- exportStringListStaticVariable("Arm64ExynosM2Cflags", arm64CpuVariantCflags["exynos-m2"])
+ exportedVars.ExportStringListStaticVariable("Arm64CortexA53Cflags", arm64CpuVariantCflags["cortex-a53"])
+ exportedVars.ExportStringListStaticVariable("Arm64CortexA55Cflags", arm64CpuVariantCflags["cortex-a55"])
+ exportedVars.ExportStringListStaticVariable("Arm64KryoCflags", arm64CpuVariantCflags["kryo"])
+ exportedVars.ExportStringListStaticVariable("Arm64ExynosM1Cflags", arm64CpuVariantCflags["exynos-m1"])
+ exportedVars.ExportStringListStaticVariable("Arm64ExynosM2Cflags", arm64CpuVariantCflags["exynos-m2"])
- exportStringListStaticVariable("Arm64FixCortexA53Ldflags", []string{"-Wl,--fix-cortex-a53-843419"})
+ exportedVars.ExportStringListStaticVariable("Arm64FixCortexA53Ldflags", []string{"-Wl,--fix-cortex-a53-843419"})
}
var (
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 4466632..d702c61 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -178,41 +178,41 @@
pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
// Just exported. Not created as a Ninja static variable.
- exportedStringVars.Set("ArmClangTriple", clangTriple)
+ exportedVars.ExportString("ArmClangTriple", clangTriple)
- exportStringListStaticVariable("ArmLdflags", armLdflags)
- exportStringListStaticVariable("ArmLldflags", armLldflags)
+ exportedVars.ExportStringListStaticVariable("ArmLdflags", armLdflags)
+ exportedVars.ExportStringListStaticVariable("ArmLldflags", armLldflags)
- exportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
- exportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
+ exportedVars.ExportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
+ exportedVars.ExportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
// Clang cflags
- exportStringListStaticVariable("ArmToolchainCflags", armToolchainCflags)
- exportStringListStaticVariable("ArmCflags", armCflags)
- exportStringListStaticVariable("ArmCppflags", armCppflags)
+ exportedVars.ExportStringListStaticVariable("ArmToolchainCflags", armToolchainCflags)
+ exportedVars.ExportStringListStaticVariable("ArmCflags", armCflags)
+ exportedVars.ExportStringListStaticVariable("ArmCppflags", armCppflags)
// Clang ARM vs. Thumb instruction set cflags
- exportStringListStaticVariable("ArmArmCflags", armArmCflags)
- exportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
+ exportedVars.ExportStringListStaticVariable("ArmArmCflags", armArmCflags)
+ exportedVars.ExportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
- exportedVariableReferenceDictVars.Set("ArmArchVariantCflags", armArchVariantCflagsVar)
- exportedVariableReferenceDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("ArmArchVariantCflags", armArchVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("ArmCpuVariantCflags", armCpuVariantCflagsVar)
// Clang arch variant cflags
- exportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
- exportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
- exportStringListStaticVariable("ArmArmv8ACflags", armArchVariantCflags["armv8-a"])
- exportStringListStaticVariable("ArmArmv82ACflags", armArchVariantCflags["armv8-2a"])
+ exportedVars.ExportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
+ exportedVars.ExportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
+ exportedVars.ExportStringListStaticVariable("ArmArmv8ACflags", armArchVariantCflags["armv8-a"])
+ exportedVars.ExportStringListStaticVariable("ArmArmv82ACflags", armArchVariantCflags["armv8-2a"])
// Clang cpu variant cflags
- exportStringListStaticVariable("ArmGenericCflags", armCpuVariantCflags[""])
- exportStringListStaticVariable("ArmCortexA7Cflags", armCpuVariantCflags["cortex-a7"])
- exportStringListStaticVariable("ArmCortexA8Cflags", armCpuVariantCflags["cortex-a8"])
- exportStringListStaticVariable("ArmCortexA15Cflags", armCpuVariantCflags["cortex-a15"])
- exportStringListStaticVariable("ArmCortexA53Cflags", armCpuVariantCflags["cortex-a53"])
- exportStringListStaticVariable("ArmCortexA55Cflags", armCpuVariantCflags["cortex-a55"])
- exportStringListStaticVariable("ArmKraitCflags", armCpuVariantCflags["krait"])
- exportStringListStaticVariable("ArmKryoCflags", armCpuVariantCflags["kryo"])
+ exportedVars.ExportStringListStaticVariable("ArmGenericCflags", armCpuVariantCflags[""])
+ exportedVars.ExportStringListStaticVariable("ArmCortexA7Cflags", armCpuVariantCflags["cortex-a7"])
+ exportedVars.ExportStringListStaticVariable("ArmCortexA8Cflags", armCpuVariantCflags["cortex-a8"])
+ exportedVars.ExportStringListStaticVariable("ArmCortexA15Cflags", armCpuVariantCflags["cortex-a15"])
+ exportedVars.ExportStringListStaticVariable("ArmCortexA53Cflags", armCpuVariantCflags["cortex-a53"])
+ exportedVars.ExportStringListStaticVariable("ArmCortexA55Cflags", armCpuVariantCflags["cortex-a55"])
+ exportedVars.ExportStringListStaticVariable("ArmKraitCflags", armCpuVariantCflags["krait"])
+ exportedVars.ExportStringListStaticVariable("ArmKryoCflags", armCpuVariantCflags["kryo"])
}
var (
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
deleted file mode 100644
index 73f65f5..0000000
--- a/cc/config/bp2build.go
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package config
-
-import (
- "fmt"
- "reflect"
- "regexp"
- "sort"
- "strings"
-
- "android/soong/android"
- "android/soong/starlark_fmt"
-
- "github.com/google/blueprint"
-)
-
-type bazelVarExporter interface {
- asBazel(android.Config, exportedStringVariables, exportedStringListVariables, exportedConfigDependingVariables) []bazelConstant
-}
-
-// Helpers for exporting cc configuration information to Bazel.
-var (
- // Maps containing toolchain variables that are independent of the
- // environment variables of the build.
- exportedStringListVars = exportedStringListVariables{}
- exportedStringVars = exportedStringVariables{}
- exportedStringListDictVars = exportedStringListDictVariables{}
- // Note: these can only contain references to other variables and must be printed last
- exportedVariableReferenceDictVars = exportedVariableReferenceDictVariables{}
-
- /// Maps containing variables that are dependent on the build config.
- exportedConfigDependingVars = exportedConfigDependingVariables{}
-)
-
-type exportedConfigDependingVariables map[string]interface{}
-
-func (m exportedConfigDependingVariables) Set(k string, v interface{}) {
- m[k] = v
-}
-
-// Ensure that string s has no invalid characters to be generated into the bzl file.
-func validateCharacters(s string) string {
- for _, c := range []string{`\n`, `"`, `\`} {
- if strings.Contains(s, c) {
- panic(fmt.Errorf("%s contains illegal character %s", s, c))
- }
- }
- return s
-}
-
-type bazelConstant struct {
- variableName string
- internalDefinition string
- sortLast bool
-}
-
-type exportedStringVariables map[string]string
-
-func (m exportedStringVariables) Set(k string, v string) {
- m[k] = v
-}
-
-func (m exportedStringVariables) asBazel(config android.Config,
- stringVars exportedStringVariables, stringListVars exportedStringListVariables, cfgDepVars exportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for k, variableValue := range m {
- expandedVar, err := expandVar(config, variableValue, stringVars, stringListVars, cfgDepVars)
- if err != nil {
- panic(fmt.Errorf("error expanding config variable %s: %s", k, err))
- }
- if len(expandedVar) > 1 {
- panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
- }
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
- })
- }
- return ret
-}
-
-// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
-func exportStringStaticVariable(name string, value string) {
- pctx.StaticVariable(name, value)
- exportedStringVars.Set(name, value)
-}
-
-type exportedStringListVariables map[string][]string
-
-func (m exportedStringListVariables) Set(k string, v []string) {
- m[k] = v
-}
-
-func (m exportedStringListVariables) asBazel(config android.Config,
- stringScope exportedStringVariables, stringListScope exportedStringListVariables,
- exportedVars exportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- // For each exported variable, recursively expand elements in the variableValue
- // list to ensure that interpolated variables are expanded according to their values
- // in the variable scope.
- for k, variableValue := range m {
- var expandedVars []string
- for _, v := range variableValue {
- expandedVar, err := expandVar(config, v, stringScope, stringListScope, exportedVars)
- if err != nil {
- panic(fmt.Errorf("Error expanding config variable %s=%s: %s", k, v, err))
- }
- expandedVars = append(expandedVars, expandedVar...)
- }
- // Assign the list as a bzl-private variable; this variable will be exported
- // out through a constants struct later.
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
- })
- }
- return ret
-}
-
-// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain.
-func exportVariableConfigMethod(name string, method interface{}) blueprint.Variable {
- exportedConfigDependingVars.Set(name, method)
- return pctx.VariableConfigMethod(name, method)
-}
-
-// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain.
-func exportSourcePathVariable(name string, value string) {
- pctx.SourcePathVariable(name, value)
- exportedStringVars.Set(name, value)
-}
-
-// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
-func exportStringListStaticVariable(name string, value []string) {
- pctx.StaticVariable(name, strings.Join(value, " "))
- exportedStringListVars.Set(name, value)
-}
-
-func ExportStringList(name string, value []string) {
- exportedStringListVars.Set(name, value)
-}
-
-type exportedStringListDictVariables map[string]map[string][]string
-
-func (m exportedStringListDictVariables) Set(k string, v map[string][]string) {
- m[k] = v
-}
-
-// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
-func (m exportedStringListDictVariables) asBazel(_ android.Config, _ exportedStringVariables,
- _ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for k, dict := range m {
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: starlark_fmt.PrintStringListDict(dict, 0),
- })
- }
- return ret
-}
-
-type exportedVariableReferenceDictVariables map[string]map[string]string
-
-func (m exportedVariableReferenceDictVariables) Set(k string, v map[string]string) {
- m[k] = v
-}
-
-func (m exportedVariableReferenceDictVariables) asBazel(_ android.Config, _ exportedStringVariables,
- _ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for n, dict := range m {
- for k, v := range dict {
- matches, err := variableReference(v)
- if err != nil {
- panic(err)
- } else if !matches.matches {
- panic(fmt.Errorf("Expected a variable reference, got %q", v))
- } else if len(matches.fullVariableReference) != len(v) {
- panic(fmt.Errorf("Expected only a variable reference, got %q", v))
- }
- dict[k] = "_" + matches.variable
- }
- ret = append(ret, bazelConstant{
- variableName: n,
- internalDefinition: starlark_fmt.PrintDict(dict, 0),
- sortLast: true,
- })
- }
- return ret
-}
-
-// BazelCcToolchainVars generates bzl file content containing variables for
-// Bazel's cc_toolchain configuration.
-func BazelCcToolchainVars(config android.Config) string {
- return bazelToolchainVars(
- config,
- exportedStringListDictVars,
- exportedStringListVars,
- exportedStringVars,
- exportedVariableReferenceDictVars)
-}
-
-func bazelToolchainVars(config android.Config, vars ...bazelVarExporter) string {
- ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"
-
- results := []bazelConstant{}
- for _, v := range vars {
- results = append(results, v.asBazel(config, exportedStringVars, exportedStringListVars, exportedConfigDependingVars)...)
- }
-
- sort.Slice(results, func(i, j int) bool {
- if results[i].sortLast != results[j].sortLast {
- return !results[i].sortLast
- }
- return results[i].variableName < results[j].variableName
- })
-
- definitions := make([]string, 0, len(results))
- constants := make([]string, 0, len(results))
- for _, b := range results {
- definitions = append(definitions,
- fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
- constants = append(constants,
- fmt.Sprintf("%[1]s%[2]s = _%[2]s,", starlark_fmt.Indention(1), b.variableName))
- }
-
- // Build the exported constants struct.
- ret += strings.Join(definitions, "\n\n")
- ret += "\n\n"
- ret += "constants = struct(\n"
- ret += strings.Join(constants, "\n")
- ret += "\n)"
-
- return ret
-}
-
-type match struct {
- matches bool
- fullVariableReference string
- variable string
-}
-
-func variableReference(input string) (match, error) {
- // e.g. "${ExternalCflags}"
- r := regexp.MustCompile(`\${(?:config\.)?([a-zA-Z0-9_]+)}`)
-
- matches := r.FindStringSubmatch(input)
- if len(matches) == 0 {
- return match{}, nil
- }
- if len(matches) != 2 {
- return match{}, fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", input, len(matches)-1)
- }
- return match{
- matches: true,
- fullVariableReference: matches[0],
- // Index 1 of FindStringSubmatch contains the subexpression match
- // (variable name) of the capture group.
- variable: matches[1],
- }, nil
-}
-
-// expandVar recursively expand interpolated variables in the exportedVars scope.
-//
-// We're using a string slice to track the seen variables to avoid
-// stackoverflow errors with infinite recursion. it's simpler to use a
-// string slice than to handle a pass-by-referenced map, which would make it
-// quite complex to track depth-first interpolations. It's also unlikely the
-// interpolation stacks are deep (n > 1).
-func expandVar(config android.Config, toExpand string, stringScope exportedStringVariables,
- stringListScope exportedStringListVariables, exportedVars exportedConfigDependingVariables) ([]string, error) {
-
- // Internal recursive function.
- var expandVarInternal func(string, map[string]bool) (string, error)
- expandVarInternal = func(toExpand string, seenVars map[string]bool) (string, error) {
- var ret string
- remainingString := toExpand
- for len(remainingString) > 0 {
- matches, err := variableReference(remainingString)
- if err != nil {
- panic(err)
- }
- if !matches.matches {
- return ret + remainingString, nil
- }
- matchIndex := strings.Index(remainingString, matches.fullVariableReference)
- ret += remainingString[:matchIndex]
- remainingString = remainingString[matchIndex+len(matches.fullVariableReference):]
-
- variable := matches.variable
- // toExpand contains a variable.
- if _, ok := seenVars[variable]; ok {
- return ret, fmt.Errorf(
- "Unbounded recursive interpolation of variable: %s", variable)
- }
- // A map is passed-by-reference. Create a new map for
- // this scope to prevent variables seen in one depth-first expansion
- // to be also treated as "seen" in other depth-first traversals.
- newSeenVars := map[string]bool{}
- for k := range seenVars {
- newSeenVars[k] = true
- }
- newSeenVars[variable] = true
- if unexpandedVars, ok := stringListScope[variable]; ok {
- expandedVars := []string{}
- for _, unexpandedVar := range unexpandedVars {
- expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
- if err != nil {
- return ret, err
- }
- expandedVars = append(expandedVars, expandedVar)
- }
- ret += strings.Join(expandedVars, " ")
- } else if unexpandedVar, ok := stringScope[variable]; ok {
- expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
- if err != nil {
- return ret, err
- }
- ret += expandedVar
- } else if unevaluatedVar, ok := exportedVars[variable]; ok {
- evalFunc := reflect.ValueOf(unevaluatedVar)
- validateVariableMethod(variable, evalFunc)
- evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
- evaluatedValue := evaluatedResult[0].Interface().(string)
- expandedVar, err := expandVarInternal(evaluatedValue, newSeenVars)
- if err != nil {
- return ret, err
- }
- ret += expandedVar
- } else {
- return "", fmt.Errorf("Unbound config variable %s", variable)
- }
- }
- return ret, nil
- }
- var ret []string
- for _, v := range strings.Split(toExpand, " ") {
- val, err := expandVarInternal(v, map[string]bool{})
- if err != nil {
- return ret, err
- }
- ret = append(ret, val)
- }
-
- return ret, nil
-}
-
-func validateVariableMethod(name string, methodValue reflect.Value) {
- methodType := methodValue.Type()
- if methodType.Kind() != reflect.Func {
- panic(fmt.Errorf("method given for variable %s is not a function",
- name))
- }
- if n := methodType.NumIn(); n != 1 {
- panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)",
- name, n))
- }
- if n := methodType.NumOut(); n != 1 {
- panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)",
- name, n))
- }
- if kind := methodType.Out(0).Kind(); kind != reflect.String {
- panic(fmt.Errorf("method for variable %s does not return a string",
- name))
- }
-}
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
deleted file mode 100644
index 9a8178a..0000000
--- a/cc/config/bp2build_test.go
+++ /dev/null
@@ -1,324 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package config
-
-import (
- "testing"
-
- "android/soong/android"
-)
-
-func TestExpandVars(t *testing.T) {
- android_arm64_config := android.TestConfig("out", nil, "", nil)
- android_arm64_config.BuildOS = android.Android
- android_arm64_config.BuildArch = android.Arm64
-
- testCases := []struct {
- description string
- config android.Config
- stringScope exportedStringVariables
- stringListScope exportedStringListVariables
- configVars exportedConfigDependingVariables
- toExpand string
- expectedValues []string
- }{
- {
- description: "no expansion for non-interpolated value",
- toExpand: "foo",
- expectedValues: []string{"foo"},
- },
- {
- description: "single level expansion for string var",
- stringScope: exportedStringVariables{
- "foo": "bar",
- },
- toExpand: "${foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "single level expansion with short-name for string var",
- stringScope: exportedStringVariables{
- "foo": "bar",
- },
- toExpand: "${config.foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "single level expansion string list var",
- stringListScope: exportedStringListVariables{
- "foo": []string{"bar"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "mixed level expansion for string list var",
- stringScope: exportedStringVariables{
- "foo": "${bar}",
- "qux": "hello",
- },
- stringListScope: exportedStringListVariables{
- "bar": []string{"baz", "${qux}"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"baz hello"},
- },
- {
- description: "double level expansion",
- stringListScope: exportedStringListVariables{
- "foo": []string{"${bar}"},
- "bar": []string{"baz"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"baz"},
- },
- {
- description: "double level expansion with a literal",
- stringListScope: exportedStringListVariables{
- "a": []string{"${b}", "c"},
- "b": []string{"d"},
- },
- toExpand: "${a}",
- expectedValues: []string{"d c"},
- },
- {
- description: "double level expansion, with two variables in a string",
- stringListScope: exportedStringListVariables{
- "a": []string{"${b} ${c}"},
- "b": []string{"d"},
- "c": []string{"e"},
- },
- toExpand: "${a}",
- expectedValues: []string{"d e"},
- },
- {
- description: "triple level expansion with two variables in a string",
- stringListScope: exportedStringListVariables{
- "a": []string{"${b} ${c}"},
- "b": []string{"${c}", "${d}"},
- "c": []string{"${d}"},
- "d": []string{"foo"},
- },
- toExpand: "${a}",
- expectedValues: []string{"foo foo foo"},
- },
- {
- description: "expansion with config depending vars",
- configVars: exportedConfigDependingVariables{
- "a": func(c android.Config) string { return c.BuildOS.String() },
- "b": func(c android.Config) string { return c.BuildArch.String() },
- },
- config: android_arm64_config,
- toExpand: "${a}-${b}",
- expectedValues: []string{"android-arm64"},
- },
- {
- description: "double level multi type expansion",
- stringListScope: exportedStringListVariables{
- "platform": []string{"${os}-${arch}"},
- "const": []string{"const"},
- },
- configVars: exportedConfigDependingVariables{
- "os": func(c android.Config) string { return c.BuildOS.String() },
- "arch": func(c android.Config) string { return c.BuildArch.String() },
- "foo": func(c android.Config) string { return "foo" },
- },
- config: android_arm64_config,
- toExpand: "${const}/${platform}/${foo}",
- expectedValues: []string{"const/android-arm64/foo"},
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- output, _ := expandVar(testCase.config, testCase.toExpand, testCase.stringScope, testCase.stringListScope, testCase.configVars)
- if len(output) != len(testCase.expectedValues) {
- t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output))
- }
- for i, actual := range output {
- expectedValue := testCase.expectedValues[i]
- if actual != expectedValue {
- t.Errorf("Actual value '%s' doesn't match expected value '%s'", actual, expectedValue)
- }
- }
- })
- }
-}
-
-func TestBazelToolchainVars(t *testing.T) {
- testCases := []struct {
- name string
- config android.Config
- vars []bazelVarExporter
- expectedOut string
- }{
- {
- name: "exports strings",
- vars: []bazelVarExporter{
- exportedStringVariables{
- "a": "b",
- "c": "d",
- },
- },
- expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
-
-_a = "b"
-
-_c = "d"
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports string lists",
- vars: []bazelVarExporter{
- exportedStringListVariables{
- "a": []string{"b1", "b2"},
- "c": []string{"d1", "d2"},
- },
- },
- expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
-
-_a = [
- "b1",
- "b2",
-]
-
-_c = [
- "d1",
- "d2",
-]
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports string lists dicts",
- vars: []bazelVarExporter{
- exportedStringListDictVariables{
- "a": map[string][]string{"b1": []string{"b2"}},
- "c": map[string][]string{"d1": []string{"d2"}},
- },
- },
- expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
-
-_a = {
- "b1": ["b2"],
-}
-
-_c = {
- "d1": ["d2"],
-}
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports dict with var refs",
- vars: []bazelVarExporter{
- exportedVariableReferenceDictVariables{
- "a": map[string]string{"b1": "${b2}"},
- "c": map[string]string{"d1": "${config.d2}"},
- },
- },
- expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
-
-_a = {
- "b1": _b2,
-}
-
-_c = {
- "d1": _d2,
-}
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "sorts across types with variable references last",
- vars: []bazelVarExporter{
- exportedStringVariables{
- "b": "b-val",
- "d": "d-val",
- },
- exportedStringListVariables{
- "c": []string{"c-val"},
- "e": []string{"e-val"},
- },
- exportedStringListDictVariables{
- "a": map[string][]string{"a1": []string{"a2"}},
- "f": map[string][]string{"f1": []string{"f2"}},
- },
- exportedVariableReferenceDictVariables{
- "aa": map[string]string{"b1": "${b}"},
- "cc": map[string]string{"d1": "${config.d}"},
- },
- },
- expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
-
-_a = {
- "a1": ["a2"],
-}
-
-_b = "b-val"
-
-_c = ["c-val"]
-
-_d = "d-val"
-
-_e = ["e-val"]
-
-_f = {
- "f1": ["f2"],
-}
-
-_aa = {
- "b1": _b,
-}
-
-_cc = {
- "d1": _d,
-}
-
-constants = struct(
- a = _a,
- b = _b,
- c = _c,
- d = _d,
- e = _e,
- f = _f,
- aa = _aa,
- cc = _cc,
-)`,
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- out := bazelToolchainVars(tc.config, tc.vars...)
- if out != tc.expectedOut {
- t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
- }
- })
- }
-}
diff --git a/cc/config/global.go b/cc/config/global.go
index 0f31931..9c71683 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -23,6 +23,9 @@
)
var (
+ pctx = android.NewPackageContext("android/soong/cc/config")
+ exportedVars = android.NewExportedVariables(pctx)
+
// Flags used by lots of devices. Putting them in package static variables
// will save bytes in build.ninja so they aren't repeated for every file
commonGlobalCflags = []string{
@@ -222,9 +225,7 @@
"-Wno-misleading-indentation", // http://b/153746954
"-Wno-zero-as-null-pointer-constant", // http://b/68236239
"-Wno-deprecated-anon-enum-enum-conversion", // http://b/153746485
- "-Wno-deprecated-enum-enum-conversion", // http://b/153746563
"-Wno-string-compare", // http://b/153764102
- "-Wno-enum-enum-conversion", // http://b/154138986
"-Wno-pessimizing-move", // http://b/154270751
// New warnings to be fixed after clang-r399163
"-Wno-non-c-typedef-for-linkage", // http://b/161304145
@@ -298,20 +299,28 @@
WarningAllowedOldProjects = []string{}
)
-var pctx = android.NewPackageContext("android/soong/cc/config")
+// BazelCcToolchainVars generates bzl file content containing variables for
+// Bazel's cc_toolchain configuration.
+func BazelCcToolchainVars(config android.Config) string {
+ return android.BazelToolchainVars(config, exportedVars)
+}
+
+func ExportStringList(name string, value []string) {
+ exportedVars.ExportStringList(name, value)
+}
func init() {
if runtime.GOOS == "linux" {
commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
}
- exportStringListStaticVariable("CommonGlobalConlyflags", commonGlobalConlyflags)
- exportStringListStaticVariable("DeviceGlobalCppflags", deviceGlobalCppflags)
- exportStringListStaticVariable("DeviceGlobalLdflags", deviceGlobalLdflags)
- exportStringListStaticVariable("DeviceGlobalLldflags", deviceGlobalLldflags)
- exportStringListStaticVariable("HostGlobalCppflags", hostGlobalCppflags)
- exportStringListStaticVariable("HostGlobalLdflags", hostGlobalLdflags)
- exportStringListStaticVariable("HostGlobalLldflags", hostGlobalLldflags)
+ exportedVars.ExportStringListStaticVariable("CommonGlobalConlyflags", commonGlobalConlyflags)
+ exportedVars.ExportStringListStaticVariable("DeviceGlobalCppflags", deviceGlobalCppflags)
+ exportedVars.ExportStringListStaticVariable("DeviceGlobalLdflags", deviceGlobalLdflags)
+ exportedVars.ExportStringListStaticVariable("DeviceGlobalLldflags", deviceGlobalLldflags)
+ exportedVars.ExportStringListStaticVariable("HostGlobalCppflags", hostGlobalCppflags)
+ exportedVars.ExportStringListStaticVariable("HostGlobalLdflags", hostGlobalLdflags)
+ exportedVars.ExportStringListStaticVariable("HostGlobalLldflags", hostGlobalLldflags)
// Export the static default CommonGlobalCflags to Bazel.
// TODO(187086342): handle cflags that are set in VariableFuncs.
@@ -322,7 +331,7 @@
"-ftrivial-auto-var-init=zero",
"-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang",
}...)
- exportedStringListVars.Set("CommonGlobalCflags", bazelCommonGlobalCflags)
+ exportedVars.ExportStringList("CommonGlobalCflags", bazelCommonGlobalCflags)
pctx.VariableFunc("CommonGlobalCflags", func(ctx android.PackageVarContext) string {
flags := commonGlobalCflags
@@ -351,17 +360,17 @@
// Export the static default DeviceGlobalCflags to Bazel.
// TODO(187086342): handle cflags that are set in VariableFuncs.
- exportedStringListVars.Set("DeviceGlobalCflags", deviceGlobalCflags)
+ exportedVars.ExportStringList("DeviceGlobalCflags", deviceGlobalCflags)
pctx.VariableFunc("DeviceGlobalCflags", func(ctx android.PackageVarContext) string {
return strings.Join(deviceGlobalCflags, " ")
})
- exportStringListStaticVariable("HostGlobalCflags", hostGlobalCflags)
- exportStringListStaticVariable("NoOverrideGlobalCflags", noOverrideGlobalCflags)
- exportStringListStaticVariable("NoOverrideExternalGlobalCflags", noOverrideExternalGlobalCflags)
- exportStringListStaticVariable("CommonGlobalCppflags", commonGlobalCppflags)
- exportStringListStaticVariable("ExternalCflags", extraExternalCflags)
+ exportedVars.ExportStringListStaticVariable("HostGlobalCflags", hostGlobalCflags)
+ exportedVars.ExportStringListStaticVariable("NoOverrideGlobalCflags", noOverrideGlobalCflags)
+ exportedVars.ExportStringListStaticVariable("NoOverrideExternalGlobalCflags", noOverrideExternalGlobalCflags)
+ exportedVars.ExportStringListStaticVariable("CommonGlobalCppflags", commonGlobalCppflags)
+ exportedVars.ExportStringListStaticVariable("ExternalCflags", extraExternalCflags)
// Everything in these lists is a crime against abstraction and dependency tracking.
// Do not add anything to this list.
@@ -376,11 +385,11 @@
"frameworks/native/opengl/include",
"frameworks/av/include",
}
- exportedStringListVars.Set("CommonGlobalIncludes", commonGlobalIncludes)
+ exportedVars.ExportStringList("CommonGlobalIncludes", commonGlobalIncludes)
pctx.PrefixedExistentPathsForSourcesVariable("CommonGlobalIncludes", "-I", commonGlobalIncludes)
- exportStringStaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
- exportStringStaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
+ exportedVars.ExportStringStaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
+ exportedVars.ExportStringStaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
pctx.StaticVariableWithEnvOverride("ClangBase", "LLVM_PREBUILTS_BASE", ClangDefaultBase)
pctx.StaticVariableWithEnvOverride("ClangVersion", "LLVM_PREBUILTS_VERSION", ClangDefaultVersion)
@@ -420,7 +429,7 @@
pctx.StaticVariableWithEnvOverride("REAbiLinkerExecStrategy", "RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
}
-var HostPrebuiltTag = exportVariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+var HostPrebuiltTag = exportedVars.ExportVariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
func ClangPath(ctx android.PathContext, file string) android.SourcePath {
type clangToolKey string
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 164e7a6..aebda0b 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -91,26 +91,26 @@
pctx.SourcePathVariable("X86_64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
- exportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
- exportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
+ exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
+ exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
- exportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
- exportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)
+ exportedVars.ExportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
+ exportedVars.ExportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)
// Clang cflags
- exportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
- exportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
+ exportedVars.ExportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
+ exportedVars.ExportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
// Yasm flags
- exportStringListStaticVariable("X86_64YasmFlags", []string{
+ exportedVars.ExportStringListStaticVariable("X86_64YasmFlags", []string{
"-f elf64",
"-m amd64",
})
// Extended cflags
- exportedStringListDictVars.Set("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
- exportedStringListDictVars.Set("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)
+ exportedVars.ExportStringListDict("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
+ exportedVars.ExportStringListDict("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)
// Architecture variant cflags
for variant, cflags := range x86_64ArchVariantCflags {
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index e32e1bd..421b083 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -98,25 +98,25 @@
pctx.SourcePathVariable("X86GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
- exportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
- exportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
+ exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
+ exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
- exportStringListStaticVariable("X86Ldflags", x86Ldflags)
- exportStringListStaticVariable("X86Lldflags", x86Ldflags)
+ exportedVars.ExportStringListStaticVariable("X86Ldflags", x86Ldflags)
+ exportedVars.ExportStringListStaticVariable("X86Lldflags", x86Ldflags)
// Clang cflags
- exportStringListStaticVariable("X86Cflags", x86Cflags)
- exportStringListStaticVariable("X86Cppflags", x86Cppflags)
+ exportedVars.ExportStringListStaticVariable("X86Cflags", x86Cflags)
+ exportedVars.ExportStringListStaticVariable("X86Cppflags", x86Cppflags)
// Yasm flags
- exportStringListStaticVariable("X86YasmFlags", []string{
+ exportedVars.ExportStringListStaticVariable("X86YasmFlags", []string{
"-f elf32",
"-m x86",
})
// Extended cflags
- exportedStringListDictVars.Set("X86ArchVariantCflags", x86ArchVariantCflags)
- exportedStringListDictVars.Set("X86ArchFeatureCflags", x86ArchFeatureCflags)
+ exportedVars.ExportStringListDict("X86ArchVariantCflags", x86ArchVariantCflags)
+ exportedVars.ExportStringListDict("X86ArchFeatureCflags", x86ArchFeatureCflags)
// Architecture variant cflags
for variant, cflags := range x86ArchVariantCflags {
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index e1659d3..4e8fd77 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -121,40 +121,40 @@
)
func init() {
- exportStringStaticVariable("LinuxGccVersion", linuxGccVersion)
- exportStringStaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
+ exportedVars.ExportStringStaticVariable("LinuxGccVersion", linuxGccVersion)
+ exportedVars.ExportStringStaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
// Most places use the full GCC version. A few only use up to the first two numbers.
if p := strings.Split(linuxGccVersion, "."); len(p) > 2 {
- exportStringStaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
+ exportedVars.ExportStringStaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
} else {
- exportStringStaticVariable("ShortLinuxGccVersion", linuxGccVersion)
+ exportedVars.ExportStringStaticVariable("ShortLinuxGccVersion", linuxGccVersion)
}
- exportSourcePathVariable("LinuxGccRoot",
+ exportedVars.ExportSourcePathVariable("LinuxGccRoot",
"prebuilts/gcc/linux-x86/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}")
- exportStringListStaticVariable("LinuxGccTriple", []string{"x86_64-linux"})
+ exportedVars.ExportStringListStaticVariable("LinuxGccTriple", []string{"x86_64-linux"})
- exportStringListStaticVariable("LinuxCflags", linuxCflags)
- exportStringListStaticVariable("LinuxLdflags", linuxLdflags)
- exportStringListStaticVariable("LinuxLldflags", linuxLdflags)
- exportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags)
- exportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags)
- exportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags)
- exportStringListStaticVariable("LinuxMuslCflags", linuxMuslCflags)
- exportStringListStaticVariable("LinuxMuslLdflags", linuxMuslLdflags)
- exportStringListStaticVariable("LinuxMuslLldflags", linuxMuslLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxCflags", linuxCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxLdflags", linuxLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxLldflags", linuxLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxMuslCflags", linuxMuslCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxMuslLdflags", linuxMuslLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxMuslLldflags", linuxMuslLdflags)
- exportStringListStaticVariable("LinuxX86Cflags", linuxX86Cflags)
- exportStringListStaticVariable("LinuxX8664Cflags", linuxX8664Cflags)
- exportStringListStaticVariable("LinuxX86Ldflags", linuxX86Ldflags)
- exportStringListStaticVariable("LinuxX86Lldflags", linuxX86Ldflags)
- exportStringListStaticVariable("LinuxX8664Ldflags", linuxX8664Ldflags)
- exportStringListStaticVariable("LinuxX8664Lldflags", linuxX8664Ldflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX86Cflags", linuxX86Cflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX8664Cflags", linuxX8664Cflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX86Ldflags", linuxX86Ldflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX86Lldflags", linuxX86Ldflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX8664Ldflags", linuxX8664Ldflags)
+ exportedVars.ExportStringListStaticVariable("LinuxX8664Lldflags", linuxX8664Ldflags)
// Yasm flags
- exportStringListStaticVariable("LinuxX86YasmFlags", []string{"-f elf32 -m x86"})
- exportStringListStaticVariable("LinuxX8664YasmFlags", []string{"-f elf64 -m amd64"})
+ exportedVars.ExportStringListStaticVariable("LinuxX86YasmFlags", []string{"-f elf32 -m x86"})
+ exportedVars.ExportStringListStaticVariable("LinuxX8664YasmFlags", []string{"-f elf64 -m amd64"})
}
type toolchainLinux struct {
diff --git a/cc/linkable.go b/cc/linkable.go
index d4b4770..6bec30c 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -176,10 +176,14 @@
IsVndk() bool
IsVndkExt() bool
IsVndkPrivate() bool
+ IsVendorPublicLibrary() bool
+ IsVndkPrebuiltLibrary() bool
HasVendorVariant() bool
HasProductVariant() bool
HasNonSystemVariants() bool
+ ProductSpecific() bool
InProduct() bool
+ SdkAndPlatformVariantVisibleToMake() bool
// SubName returns the modules SubName, used for image and NDK/SDK variations.
SubName() string
diff --git a/cc/pgo.go b/cc/pgo.go
index aa0feae..0632c15 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -32,8 +32,8 @@
}
globalPgoProfileProjects = []string{
- "toolchain/pgo-profiles",
- "vendor/google_data/pgo_profile",
+ "toolchain/pgo-profiles/pgo",
+ "vendor/google_data/pgo_profile/pgo",
}
)
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 418826c..4f7451d 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -203,23 +203,19 @@
// createCommandScript will create and return an exec.Cmd that runs rawCommand.
//
// rawCommand is executed via a script in the sandbox.
-// tempDir is the temporary where the script is created.
-// toDirInSandBox is the path containing the script in the sbox environment.
-// toDirInSandBox is the path containing the script in the sbox environment.
-// seed is a unique integer used to distinguish different scripts that might be at location.
+// scriptPath is the temporary where the script is created.
+// scriptPathInSandbox is the path to the script in the sbox environment.
//
// returns an exec.Cmd that can be ran from within sbox context if no error, or nil if error.
// caller must ensure script is cleaned up if function succeeds.
//
-func createCommandScript(rawCommand string, tempDir, toDirInSandbox string, seed int) (*exec.Cmd, error) {
- scriptName := fmt.Sprintf("sbox_command.%d.bash", seed)
- scriptPathAndName := joinPath(tempDir, scriptName)
- err := os.WriteFile(scriptPathAndName, []byte(rawCommand), 0644)
+func createCommandScript(rawCommand, scriptPath, scriptPathInSandbox string) (*exec.Cmd, error) {
+ err := os.WriteFile(scriptPath, []byte(rawCommand), 0644)
if err != nil {
return nil, fmt.Errorf("failed to write command %s... to %s",
- rawCommand[0:40], scriptPathAndName)
+ rawCommand[0:40], scriptPath)
}
- return exec.Command("bash", joinPath(toDirInSandbox, filepath.Base(scriptName))), nil
+ return exec.Command("bash", scriptPathInSandbox), nil
}
// readManifest reads an sbox manifest from a textproto file.
@@ -289,7 +285,10 @@
return "", err
}
- cmd, err := createCommandScript(rawCommand, tempDir, pathToTempDirInSbox, commandIndex)
+ scriptName := fmt.Sprintf("sbox_command.%d.bash", commandIndex)
+ scriptPath := joinPath(tempDir, scriptName)
+ scriptPathInSandbox := joinPath(pathToTempDirInSbox, scriptName)
+ cmd, err := createCommandScript(rawCommand, scriptPath, scriptPathInSandbox)
if err != nil {
return "", err
}
@@ -327,9 +326,9 @@
fmt.Fprintf(os.Stderr,
"The failing command was run inside an sbox sandbox in temporary directory\n"+
"%s\n"+
- "The failing command line was:\n"+
+ "The failing command line can be found in\n"+
"%s\n",
- tempDir, rawCommand)
+ tempDir, scriptPath)
}
// Write the command's combined stdout/stderr.
@@ -751,7 +750,7 @@
return false
}
defer fileA.Close()
- fileB, err := os.Open(a)
+ fileB, err := os.Open(b)
if err != nil {
return false
}
diff --git a/cmd/sbox/sbox_test.go b/cmd/sbox/sbox_test.go
new file mode 100644
index 0000000..3f13d2f
--- /dev/null
+++ b/cmd/sbox/sbox_test.go
@@ -0,0 +1,127 @@
+// 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 main
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+func Test_filesHaveSameContents(t *testing.T) {
+
+ tests := []struct {
+ name string
+ a string
+ b string
+ missingA bool
+ missingB bool
+
+ equal bool
+ }{
+ {
+ name: "empty",
+ a: "",
+ b: "",
+ equal: true,
+ },
+ {
+ name: "equal",
+ a: "foo",
+ b: "foo",
+ equal: true,
+ },
+ {
+ name: "unequal",
+ a: "foo",
+ b: "bar",
+ equal: false,
+ },
+ {
+ name: "unequal different sizes",
+ a: "foo",
+ b: "foobar",
+ equal: false,
+ },
+ {
+ name: "equal large",
+ a: strings.Repeat("a", 2*1024*1024),
+ b: strings.Repeat("a", 2*1024*1024),
+ equal: true,
+ },
+ {
+ name: "equal large unaligned",
+ a: strings.Repeat("a", 2*1024*1024+10),
+ b: strings.Repeat("a", 2*1024*1024+10),
+ equal: true,
+ },
+ {
+ name: "unequal large",
+ a: strings.Repeat("a", 2*1024*1024),
+ b: strings.Repeat("a", 2*1024*1024-1) + "b",
+ equal: false,
+ },
+ {
+ name: "unequal large unaligned",
+ a: strings.Repeat("a", 2*1024*1024+10),
+ b: strings.Repeat("a", 2*1024*1024+9) + "b",
+ equal: false,
+ },
+ {
+ name: "missing a",
+ missingA: true,
+ b: "foo",
+ equal: false,
+ },
+ {
+ name: "missing b",
+ a: "foo",
+ missingB: true,
+ equal: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tempDir, err := os.MkdirTemp("", "testFilesHaveSameContents")
+ if err != nil {
+ t.Fatalf("failed to create temp dir: %s", err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ fileA := filepath.Join(tempDir, "a")
+ fileB := filepath.Join(tempDir, "b")
+
+ if !tt.missingA {
+ err := ioutil.WriteFile(fileA, []byte(tt.a), 0666)
+ if err != nil {
+ t.Fatalf("failed to write %s: %s", fileA, err)
+ }
+ }
+
+ if !tt.missingB {
+ err := ioutil.WriteFile(fileB, []byte(tt.b), 0666)
+ if err != nil {
+ t.Fatalf("failed to write %s: %s", fileB, err)
+ }
+ }
+
+ if got := filesHaveSameContents(fileA, fileB); got != tt.equal {
+ t.Errorf("filesHaveSameContents() = %v, want %v", got, tt.equal)
+ }
+ })
+ }
+}
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index e85163e..72af3e0 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -25,6 +25,7 @@
"golang-protobuf-android",
"soong",
"soong-android",
+ "soong-provenance",
"soong-bp2build",
"soong-ui-metrics_proto",
],
diff --git a/cmd/symbols_map/elf.go b/cmd/symbols_map/elf.go
index b38896a..950e3b2 100644
--- a/cmd/symbols_map/elf.go
+++ b/cmd/symbols_map/elf.go
@@ -18,8 +18,10 @@
"debug/elf"
"encoding/binary"
"encoding/hex"
+ "errors"
"fmt"
"io"
+ "os"
)
const gnuBuildID = "GNU\x00"
@@ -27,12 +29,33 @@
// elfIdentifier extracts the elf build ID from an elf file. If allowMissing is true it returns
// an empty identifier if the file exists but the build ID note does not.
func elfIdentifier(filename string, allowMissing bool) (string, error) {
- f, err := elf.Open(filename)
+ f, err := os.Open(filename)
if err != nil {
return "", fmt.Errorf("failed to open %s: %w", filename, err)
}
defer f.Close()
+ return elfIdentifierFromReaderAt(f, filename, allowMissing)
+}
+
+// elfIdentifierFromReaderAt extracts the elf build ID from a ReaderAt. If allowMissing is true it
+// returns an empty identifier if the file exists but the build ID note does not.
+func elfIdentifierFromReaderAt(r io.ReaderAt, filename string, allowMissing bool) (string, error) {
+ f, err := elf.NewFile(r)
+ if err != nil {
+ if allowMissing {
+ if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
+ return "", nil
+ }
+ if _, ok := err.(*elf.FormatError); ok {
+ // The file was not an elf file.
+ return "", nil
+ }
+ }
+ return "", fmt.Errorf("failed to parse elf file %s: %w", filename, err)
+ }
+ defer f.Close()
+
buildIDNote := f.Section(".note.gnu.build-id")
if buildIDNote == nil {
if allowMissing {
diff --git a/cmd/symbols_map/elf_test.go b/cmd/symbols_map/elf_test.go
index e616228..a94c87f 100644
--- a/cmd/symbols_map/elf_test.go
+++ b/cmd/symbols_map/elf_test.go
@@ -16,11 +16,50 @@
import (
"bytes"
+ "debug/elf"
"encoding/binary"
"reflect"
"testing"
)
+func Test_elfIdentifierFromReaderAt_BadElfFile(t *testing.T) {
+ tests := []struct {
+ name string
+ contents string
+ }{
+ {
+ name: "empty",
+ contents: "",
+ },
+ {
+ name: "text",
+ contents: "#!/bin/bash\necho foobar",
+ },
+ {
+ name: "empty elf",
+ contents: emptyElfFile(),
+ },
+ {
+ name: "short section header",
+ contents: shortSectionHeaderElfFile(),
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ buf := bytes.NewReader([]byte(tt.contents))
+ _, err := elfIdentifierFromReaderAt(buf, "<>", false)
+ if err == nil {
+ t.Errorf("expected error reading bad elf file without allowMissing")
+ }
+ _, err = elfIdentifierFromReaderAt(buf, "<>", true)
+ if err != nil {
+ t.Errorf("expected no error reading bad elf file with allowMissing, got %q", err.Error())
+ }
+ })
+ }
+}
+
func Test_readNote(t *testing.T) {
note := []byte{
0x04, 0x00, 0x00, 0x00,
@@ -43,3 +82,71 @@
t.Errorf("incorrect return, want %#v got %#v", expectedDescs, descs)
}
}
+
+// emptyElfFile returns an elf file header with no program headers or sections.
+func emptyElfFile() string {
+ ident := [elf.EI_NIDENT]byte{}
+ identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT])
+ binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF"))
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64)
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB)
+ binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT)
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX)
+ binary.Write(identBuf, binary.LittleEndian, make([]byte, 8))
+
+ header := elf.Header64{
+ Ident: ident,
+ Type: uint16(elf.ET_EXEC),
+ Machine: uint16(elf.EM_X86_64),
+ Version: uint32(elf.EV_CURRENT),
+ Entry: 0,
+ Phoff: uint64(binary.Size(elf.Header64{})),
+ Shoff: uint64(binary.Size(elf.Header64{})),
+ Flags: 0,
+ Ehsize: uint16(binary.Size(elf.Header64{})),
+ Phentsize: 0x38,
+ Phnum: 0,
+ Shentsize: 0x40,
+ Shnum: 0,
+ Shstrndx: 0,
+ }
+
+ buf := &bytes.Buffer{}
+ binary.Write(buf, binary.LittleEndian, header)
+ return buf.String()
+}
+
+// shortSectionHeader returns an elf file header with a section header that extends past the end of
+// the file.
+func shortSectionHeaderElfFile() string {
+ ident := [elf.EI_NIDENT]byte{}
+ identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT])
+ binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF"))
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64)
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB)
+ binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT)
+ binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX)
+ binary.Write(identBuf, binary.LittleEndian, make([]byte, 8))
+
+ header := elf.Header64{
+ Ident: ident,
+ Type: uint16(elf.ET_EXEC),
+ Machine: uint16(elf.EM_X86_64),
+ Version: uint32(elf.EV_CURRENT),
+ Entry: 0,
+ Phoff: uint64(binary.Size(elf.Header64{})),
+ Shoff: uint64(binary.Size(elf.Header64{})),
+ Flags: 0,
+ Ehsize: uint16(binary.Size(elf.Header64{})),
+ Phentsize: 0x38,
+ Phnum: 0,
+ Shentsize: 0x40,
+ Shnum: 1,
+ Shstrndx: 0,
+ }
+
+ buf := &bytes.Buffer{}
+ binary.Write(buf, binary.LittleEndian, header)
+ binary.Write(buf, binary.LittleEndian, []byte{0})
+ return buf.String()
+}
diff --git a/java/Android.bp b/java/Android.bp
index 4bcae4f..df0d1eb 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -15,6 +15,7 @@
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-provenance",
"soong-python",
"soong-remoteexec",
"soong-tradefed",
diff --git a/java/app.go b/java/app.go
index 21ee34e..2b52eab 100755
--- a/java/app.go
+++ b/java/app.go
@@ -638,7 +638,21 @@
}
certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx)
- a.certificate = certificates[0]
+
+ // This can be reached with an empty certificate list if AllowMissingDependencies is set
+ // and the certificate property for this module is a module reference to a missing module.
+ if len(certificates) > 0 {
+ a.certificate = certificates[0]
+ } else {
+ if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 {
+ panic("Should only get here if AllowMissingDependencies set and there are missing dependencies")
+ }
+ // Set a certificate to avoid panics later when accessing it.
+ a.certificate = Certificate{
+ Key: android.PathForModuleOut(ctx, "missing.pk8"),
+ Pem: android.PathForModuleOut(ctx, "missing.pem"),
+ }
+ }
// Build a final signed app package.
packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
diff --git a/java/app_import.go b/java/app_import.go
index 3e5f972..b017eca 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -22,6 +22,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/provenance"
)
func init() {
@@ -57,6 +58,8 @@
installPath android.InstallPath
hideApexVariantFromMake bool
+
+ provenanceMetaDataFile android.OutputPath
}
type AndroidAppImportProperties struct {
@@ -343,6 +346,8 @@
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
+ a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
// TODO: androidmk converter jni libs
@@ -368,6 +373,10 @@
return a.certificate
}
+func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath {
+ return a.provenanceMetaDataFile
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
@@ -457,7 +466,7 @@
// apk: "prebuilts/example_xhdpi.apk",
// },
// },
-// certificate: "PRESIGNED",
+// presigned: true,
// }
func AndroidAppImportFactory() android.Module {
module := &AndroidAppImport{}
diff --git a/java/app_import_test.go b/java/app_import_test.go
index efa52c1..8f6c75f 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -53,6 +53,11 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
@@ -74,6 +79,12 @@
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_Presigned(t *testing.T) {
@@ -102,6 +113,12 @@
if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
t.Errorf("can't find aligning rule")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineage(t *testing.T) {
@@ -137,6 +154,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
@@ -163,6 +186,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
@@ -192,6 +221,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DpiVariants(t *testing.T) {
@@ -214,40 +249,46 @@
}
`
testCases := []struct {
- name string
- aaptPreferredConfig *string
- aaptPrebuiltDPI []string
- expected string
+ name string
+ aaptPreferredConfig *string
+ aaptPrebuiltDPI []string
+ expected string
+ expectedProvenanceMetaDataArtifactPath string
}{
{
- name: "no preferred",
- aaptPreferredConfig: nil,
- aaptPrebuiltDPI: []string{},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no preferred",
+ aaptPreferredConfig: nil,
+ aaptPrebuiltDPI: []string{},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
{
- name: "AAPTPreferredConfig matches",
- aaptPreferredConfig: proptools.StringPtr("xhdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "AAPTPreferredConfig matches",
+ aaptPreferredConfig: proptools.StringPtr("xhdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ name: "AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
},
{
- name: "non-first AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "non-first AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "no matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
}
@@ -270,6 +311,12 @@
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+
+ provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
}
}
@@ -290,16 +337,25 @@
`)
testCases := []struct {
- name string
- expected string
+ name string
+ expected string
+ onDevice string
+ expectedArtifactPath string
+ expectedMetaDataPath string
}{
{
- name: "foo",
- expected: "foo.apk",
+ name: "foo",
+ expected: "foo.apk",
+ onDevice: "/system/app/foo/foo.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
},
{
- name: "bar",
- expected: "bar_sample.apk",
+ name: "bar",
+ expected: "bar_sample.apk",
+ onDevice: "/system/app/bar/bar_sample.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
},
}
@@ -316,15 +372,23 @@
t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
actualValues, expectedValues)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
}
}
func TestAndroidAppImport_ArchVariants(t *testing.T) {
// The test config's target arch is ARM64.
testCases := []struct {
- name string
- bp string
- expected string
+ name string
+ bp string
+ expected string
+ artifactPath string
+ metaDataPath string
+ installPath string
}{
{
name: "matching arch",
@@ -343,7 +407,9 @@
},
}
`,
- expected: "verify_uses_libraries/apk/app_arm64.apk",
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
+ artifactPath: "prebuilts/apk/app_arm64.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch",
@@ -362,7 +428,9 @@
},
}
`,
- expected: "verify_uses_libraries/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
+ artifactPath: "prebuilts/apk/app.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch without default",
@@ -380,7 +448,9 @@
},
}
`,
- expected: "",
+ expected: "",
+ artifactPath: "prebuilts/apk/app_arm.apk",
+ installPath: "/system/app/foo/foo.apk",
},
}
@@ -393,6 +463,8 @@
if variant.Module().Enabled() {
t.Error("module should have been disabled, but wasn't")
}
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
continue
}
jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
@@ -403,6 +475,11 @@
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
}
}
diff --git a/java/app_test.go b/java/app_test.go
index 08baf54..6a4508c 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2948,3 +2948,24 @@
android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
+
+func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ certificate: ":missing_certificate",
+ sdk_version: "current",
+ }`)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ fooApk := foo.Output("foo.apk")
+ if fooApk.Rule != android.ErrorRule {
+ t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
+ }
+ android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
+}
diff --git a/java/base.go b/java/base.go
index cc55394..5802099 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1108,23 +1108,13 @@
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
- useTurbineApt := len(flags.processorPath) > 0
- if useTurbineApt {
+ if len(flags.processorPath) > 0 {
// Use kapt for annotation processing
- kotlinTurbineAptHeaderJar := android.PathForModuleOut(ctx, "turbine-apt", "stubs-header.jar")
- kotlinTurbineAptSrcJar := android.PathForModuleOut(ctx, "turbine-apt", "anno-sources.jar")
- kotlinTurbineAptResJar := android.PathForModuleOut(ctx, "turbine-apt", "anno-res.jar")
- kotlinTurbineApt(ctx, kotlinTurbineAptHeaderJar, kotlinTurbineAptSrcJar, kotlinTurbineAptResJar,
- kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
- srcJars = append(srcJars, kotlinTurbineAptSrcJar)
- kotlinJars = append(kotlinJars, kotlinTurbineAptResJar)
- // When annotation processors are enabled we've already created java stubs for
- // kotlin files using kapt and compiled them in turbine-apt while running the
- // annotation processors, reuse the result as the kotlin header jar for the javac
- // action. It can't be used as the header jar for downstream modules to compile
- // against because it doesn't contain the kotlin-specific metadata that kotlinc
- // needs.
- flags.classpath = append(classpath{kotlinTurbineAptHeaderJar}, flags.classpath...)
+ kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
+ kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
+ kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ srcJars = append(srcJars, kaptSrcJar)
+ kotlinJars = append(kotlinJars, kaptResJar)
// Disable annotation processing in javac, it's already been handled by kapt
flags.processorPath = nil
flags.processors = nil
@@ -1137,13 +1127,11 @@
return
}
+ // Make javac rule depend on the kotlinc rule
+ flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
+
kotlinJars = append(kotlinJars, kotlinJar)
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
- if !useTurbineApt {
- // When annotation processors are not enabled use the kotlinc gen-jvm-abi plugin
- // output as the header jar for javac in this module.
- flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
- }
// Jar kotlin classes into the final jar after javac
if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
diff --git a/java/builder.go b/java/builder.go
index 0f6876e..c0fadd4 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -415,7 +415,7 @@
}
// TurbineApt produces a rule to run annotation processors using turbine.
-func TurbineApt(ctx android.ModuleContext, outputJar, outputSrcJar, outputResJar android.WritablePath,
+func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
turbineFlags, deps := turbineFlags(ctx, flags)
@@ -426,9 +426,8 @@
turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
turbineFlags += " --processors " + strings.Join(flags.processors, " ")
- outputs := android.WritablePaths{outputJar, outputSrcJar, outputResJar}
- outputFlags := "--output " + outputJar.String() + ".tmp " +
- "--gensrc_output " + outputSrcJar.String() + ".tmp " +
+ outputs := android.WritablePaths{outputSrcJar, outputResJar}
+ outputFlags := "--gensrc_output " + outputSrcJar.String() + ".tmp " +
"--resource_output " + outputResJar.String() + ".tmp"
rule := turbine
@@ -443,9 +442,7 @@
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
rule = turbineRE
args["implicits"] = strings.Join(deps.Strings(), ",")
- args["rbeOutputs"] = outputJar.String() + ".tmp," +
- outputSrcJar.String() + ".tmp," +
- outputResJar.String() + ".tmp"
+ args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
diff --git a/java/config/config.go b/java/config/config.go
index 262c531..95b841f 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -26,7 +26,8 @@
)
var (
- pctx = android.NewPackageContext("android/soong/java/config")
+ pctx = android.NewPackageContext("android/soong/java/config")
+ exportedVars = android.NewExportedVariables(pctx)
LegacyCorePlatformBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
LegacyCorePlatformSystemModules = "legacy-core-platform-api-stubs-system-modules"
@@ -53,25 +54,40 @@
}
)
-const (
- JavaVmFlags = `-XX:OnError="cat hs_err_pid%p.log" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads`
- JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1`
+var (
+ JavacVmFlags = strings.Join(javacVmFlagsList, " ")
+ javaVmFlagsList = []string{
+ `-XX:OnError="cat hs_err_pid%p.log"`,
+ "-XX:CICompilerCount=6",
+ "-XX:+UseDynamicNumberOfGCThreads",
+ }
+ javacVmFlagsList = []string{
+ `-J-XX:OnError="cat hs_err_pid%p.log"`,
+ "-J-XX:CICompilerCount=6",
+ "-J-XX:+UseDynamicNumberOfGCThreads",
+ "-J-XX:+TieredCompilation",
+ "-J-XX:TieredStopAtLevel=1",
+ }
)
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
- pctx.StaticVariable("JavacHeapSize", "2048M")
- pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
+ exportedVars.ExportStringStaticVariable("JavacHeapSize", "2048M")
+ exportedVars.ExportStringStaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
// ErrorProne can use significantly more memory than javac alone, give it a higher heap
// size (b/221480398).
- pctx.StaticVariable("ErrorProneHeapSize", "4096M")
- pctx.StaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "4096M")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
- pctx.StaticVariable("DexFlags", "-JXX:OnError='cat hs_err_pid%p.log' -JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads")
+ exportedVars.ExportStringListStaticVariable("DexFlags", []string{
+ `-JXX:OnError="cat hs_err_pid%p.log"`,
+ "-JXX:CICompilerCount=6",
+ "-JXX:+UseDynamicNumberOfGCThreads",
+ })
- pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
+ exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
`-Xmaxerrs 9999999`,
`-encoding UTF-8`,
`-sourcepath ""`,
@@ -85,10 +101,10 @@
// b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9
`-XDstringConcat=inline`,
- }, " "))
+ })
- pctx.StaticVariable("JavaVmFlags", JavaVmFlags)
- pctx.StaticVariable("JavacVmFlags", JavacVmFlags)
+ exportedVars.ExportStringListStaticVariable("JavaVmFlags", javaVmFlagsList)
+ exportedVars.ExportStringListStaticVariable("JavacVmFlags", javacVmFlagsList)
pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
@@ -184,6 +200,10 @@
hostJNIToolVariableWithSdkToolsPrebuilt("SignapkJniLibrary", "libconscrypt_openjdk_jni")
}
+func BazelJavaToolchainVars(config android.Config) string {
+ return android.BazelToolchainVars(config, exportedVars)
+}
+
func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
if ctx.Config().AlwaysUsePrebuiltSdks() {
diff --git a/java/config/error_prone.go b/java/config/error_prone.go
index 48681b5..5f853c8 100644
--- a/java/config/error_prone.go
+++ b/java/config/error_prone.go
@@ -16,8 +16,6 @@
import (
"strings"
-
- "android/soong/android"
)
var (
@@ -31,23 +29,23 @@
)
// Wrapper that grabs value of val late so it can be initialized by a later module's init function
-func errorProneVar(name string, val *[]string, sep string) {
- pctx.VariableFunc(name, func(android.PackageVarContext) string {
+func errorProneVar(val *[]string, sep string) func() string {
+ return func() string {
return strings.Join(*val, sep)
- })
+ }
}
func init() {
- errorProneVar("ErrorProneClasspath", &ErrorProneClasspath, ":")
- errorProneVar("ErrorProneChecksError", &ErrorProneChecksError, " ")
- errorProneVar("ErrorProneChecksWarning", &ErrorProneChecksWarning, " ")
- errorProneVar("ErrorProneChecksDefaultDisabled", &ErrorProneChecksDefaultDisabled, " ")
- errorProneVar("ErrorProneChecksOff", &ErrorProneChecksOff, " ")
- errorProneVar("ErrorProneFlags", &ErrorProneFlags, " ")
- pctx.StaticVariable("ErrorProneChecks", strings.Join([]string{
+ exportedVars.ExportVariableFuncVariable("ErrorProneClasspath", errorProneVar(&ErrorProneClasspath, ":"))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksError", errorProneVar(&ErrorProneChecksError, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksWarning", errorProneVar(&ErrorProneChecksWarning, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksDefaultDisabled", errorProneVar(&ErrorProneChecksDefaultDisabled, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneChecksOff", errorProneVar(&ErrorProneChecksOff, " "))
+ exportedVars.ExportVariableFuncVariable("ErrorProneFlags", errorProneVar(&ErrorProneFlags, " "))
+ exportedVars.ExportStringListStaticVariable("ErrorProneChecks", []string{
"${ErrorProneChecksOff}",
"${ErrorProneChecksError}",
"${ErrorProneChecksWarning}",
"${ErrorProneChecksDefaultDisabled}",
- }, " "))
+ })
}
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 95ded34..534a814 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -295,6 +295,12 @@
return dexJar.Path()
}
+// HIDDENAPI_STUB_FLAGS_IMPL_FLAGS is the set of flags that identify implementation only signatures,
+// i.e. those signatures that are not part of any API (including the hidden API).
+var HIDDENAPI_STUB_FLAGS_IMPL_FLAGS = []string{}
+
+var HIDDENAPI_FLAGS_CSV_IMPL_FLAGS = []string{"blocked"}
+
// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
@@ -345,7 +351,8 @@
// If there are stub flag files that have been generated by fragments on which this depends then
// use them to validate the stub flag file generated by the rules created by this method.
if len(stubFlagSubsets) > 0 {
- validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets)
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
+ HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
// Add the file that indicates that the file generated by this is valid.
//
@@ -904,7 +911,8 @@
// If there are flag files that have been generated by fragments on which this depends then use
// them to validate the flag file generated by the rules created by this method.
if len(flagSubsets) > 0 {
- validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets)
+ validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
+ HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
// Add the file that indicates that the file generated by this is valid.
//
@@ -968,13 +976,29 @@
return patternsFile
}
-// buildRuleRemoveBlockedFlag creates a rule that will remove entries from the input path which
-// only have blocked flags. It will not remove entries that have blocked as well as other flags,
-// e.g. blocked,core-platform-api.
-func buildRuleRemoveBlockedFlag(ctx android.BuilderContext, name string, desc string, inputPath android.Path, filteredPath android.WritablePath) {
+// buildRuleRemoveSignaturesWithImplementationFlags creates a rule that will remove signatures from
+// the input flags file which have only the implementation flags, i.e. are not part of an API.
+//
+// The implementationFlags specifies the set of default flags that identifies the signature of a
+// private, implementation only, member. Signatures that match those flags are removed from the
+// flags as they are implementation only.
+//
+// This is used to remove implementation only signatures from the signature files that are persisted
+// in the sdk snapshot as the sdk snapshots should not include implementation details. The
+// signatures generated by this method will be compared by the buildRuleValidateOverlappingCsvFiles
+// method which treats any missing signatures as if they were implementation only signatures.
+func buildRuleRemoveSignaturesWithImplementationFlags(ctx android.BuilderContext,
+ name string, desc string, inputPath android.Path, filteredPath android.WritablePath,
+ implementationFlags []string) {
+
rule := android.NewRuleBuilder(pctx, ctx)
+ implementationFlagPattern := ""
+ for _, implementationFlag := range implementationFlags {
+ implementationFlagPattern = implementationFlagPattern + "," + implementationFlag
+ }
rule.Command().
- Text(`grep -vE "^[^,]+,blocked$"`).Input(inputPath).Text(">").Output(filteredPath).
+ Text(`grep -vE "^[^,]+` + implementationFlagPattern + `$"`).Input(inputPath).
+ Text(">").Output(filteredPath).
// Grep's exit code depends on whether it finds anything. It is 0 (build success) when it finds
// something and 1 (build failure) when it does not and 2 (when it encounters an error).
// However, while it is unlikely it is not an error if this does not find any matches. The
@@ -986,7 +1010,14 @@
// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
-func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets) android.WritablePath {
+//
+// The implementationFlags specifies the set of default flags that identifies the signature of a
+// private, implementation only, member. A signature which is present in a monolithic flags subset
+// defined by SignatureCsvSubset but which is not present in the flags file from the corresponding
+// module is assumed to be an implementation only member and so must have these flags.
+func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string,
+ monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets,
+ implementationFlags []string) android.WritablePath {
// The file which is used to record that the flags file is valid.
validFile := pathForValidation(ctx, monolithicFilePath)
@@ -994,14 +1025,19 @@
rule := android.NewRuleBuilder(pctx, ctx)
command := rule.Command().
BuiltTool("verify_overlaps").
- Input(monolithicFilePath)
+ FlagWithInput("--monolithic-flags ", monolithicFilePath)
for _, subset := range csvSubsets {
command.
+ Flag("--module-flags ").
Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
}
+ for _, implementationFlag := range implementationFlags {
+ command.FlagWithArg("--implementation-flag ", implementationFlag)
+ }
+
// If validation passes then update the file that records that.
command.Text("&& touch").Output(validFile)
rule.Build(name+"Validation", desc+" validation")
@@ -1075,12 +1111,16 @@
// 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")
- buildRuleRemoveBlockedFlag(ctx, "modularHiddenApiFilteredStubFlags", "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV)
+ 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")
- buildRuleRemoveBlockedFlag(ctx, "modularHiddenApiFilteredFlags", "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV)
+ 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{
diff --git a/java/java.go b/java/java.go
index 713fe94..b34d6de 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2041,6 +2041,10 @@
// and also separates dependencies into dynamic dependencies and static dependencies.
// Each corresponding Bazel target type, can have a different method for handling
// dynamic vs. static dependencies, and so these are returned to the calling function.
+type eventLogTagsAttributes struct {
+ Srcs bazel.LabelListAttribute
+}
+
func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
var srcs bazel.LabelListAttribute
archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
@@ -2055,11 +2059,32 @@
javaSrcPartition := "java"
protoSrcPartition := "proto"
+ logtagSrcPartition := "logtag"
srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
- javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
- protoSrcPartition: android.ProtoSrcLabelPartition,
+ javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
+ logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
+ protoSrcPartition: android.ProtoSrcLabelPartition,
})
+ javaSrcs := srcPartitions[javaSrcPartition]
+
+ var logtagsSrcs bazel.LabelList
+ if !srcPartitions[logtagSrcPartition].IsEmpty() {
+ logtagsLibName := m.Name() + "_logtags"
+ logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "event_log_tags",
+ Bzl_load_location: "//build/make/tools:event_log_tags.bzl",
+ },
+ android.CommonAttributes{Name: logtagsLibName},
+ &eventLogTagsAttributes{
+ Srcs: srcPartitions[logtagSrcPartition],
+ },
+ )
+ }
+ javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
+
var javacopts []string
if m.properties.Javacflags != nil {
javacopts = append(javacopts, m.properties.Javacflags...)
@@ -2071,7 +2096,7 @@
}
commonAttrs := &javaCommonAttributes{
- Srcs: srcPartitions[javaSrcPartition],
+ Srcs: javaSrcs,
Plugins: bazel.MakeLabelListAttribute(
android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
),
diff --git a/java/kotlin.go b/java/kotlin.go
index 818bbd5..eff5bb5 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -163,11 +163,11 @@
"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
"kotlinBuildFile", "name", "classesJarOut")
-// kotlinTurbineApt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs
+// kotlinKapt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs
// annotation processors over all of them, producing a srcjar of generated code in outputFile. The srcjar should be
// added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing
// disabled.
-func kotlinTurbineApt(ctx android.ModuleContext, headerJarOutputFile, srcJarOutputFile, resJarOutputFile android.WritablePath,
+func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath,
srcFiles, commonSrcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
@@ -231,7 +231,7 @@
// Then run turbine to perform annotation processing on the stubs and any .java srcFiles.
javaSrcFiles := srcFiles.FilterByExt(".java")
turbineSrcJars := append(android.Paths{kaptStubsJar}, srcJars...)
- TurbineApt(ctx, headerJarOutputFile, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
+ TurbineApt(ctx, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
}
// kapt converts a list of key, value pairs into a base64 encoded Java serialization, which is what kapt expects.
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index f67a965..f9ff982 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -155,34 +155,22 @@
t.Errorf("expected %q in turbine-apt implicits %v", kaptStubs.Output.String(), kotlinc.Implicits.Strings())
}
- turbineAptSrcjarOutput := turbineApt.ImplicitOutputs[0]
-
// Test that the turbine-apt srcjar is a dependency of kotlinc and javac rules
- if !inList(turbineAptSrcjarOutput.String(), kotlinc.Implicits.Strings()) {
- t.Errorf("expected %q in kotlinc implicits %v", turbineAptSrcjarOutput.String(), kotlinc.Implicits.Strings())
+ if !inList(turbineApt.Output.String(), kotlinc.Implicits.Strings()) {
+ t.Errorf("expected %q in kotlinc implicits %v", turbineApt.Output.String(), kotlinc.Implicits.Strings())
}
- if !inList(turbineAptSrcjarOutput.String(), javac.Implicits.Strings()) {
- t.Errorf("expected %q in javac implicits %v", turbineAptSrcjarOutput.String(), javac.Implicits.Strings())
+ if !inList(turbineApt.Output.String(), javac.Implicits.Strings()) {
+ t.Errorf("expected %q in javac implicits %v", turbineApt.Output.String(), javac.Implicits.Strings())
}
// Test that the turbine-apt srcjar is extracted by the kotlinc and javac rules
- if kotlinc.Args["srcJars"] != turbineAptSrcjarOutput.String() {
- t.Errorf("expected %q in kotlinc srcjars %v", turbineAptSrcjarOutput.String(), kotlinc.Args["srcJars"])
+ if kotlinc.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in kotlinc srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
}
- if javac.Args["srcJars"] != turbineAptSrcjarOutput.String() {
- t.Errorf("expected %q in javac srcjars %v", turbineAptSrcjarOutput.String(), kotlinc.Args["srcJars"])
+ if javac.Args["srcJars"] != turbineApt.Output.String() {
+ t.Errorf("expected %q in javac srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
}
- // Test that the turbine-apt header jar is a dependency of the javac rules
- turbineAptHeaderjarOutput := turbineApt.Output
- android.AssertStringListContains(t, "javac dependency", javac.Implicits.Strings(), turbineAptHeaderjarOutput.String())
- android.AssertStringDoesContain(t, "javac classpath", javac.Args["classpath"], turbineAptHeaderjarOutput.String())
-
- // Test that the kotlinc header jar is a not a dependency of the javac rules
- kotlincHeaderJarOutput := kotlinc.ImplicitOutput
- android.AssertStringListDoesNotContain(t, "javac dependency", javac.Implicits.Strings(), kotlincHeaderJarOutput.String())
- android.AssertStringDoesNotContain(t, "javac classpath", javac.Args["classpath"], kotlincHeaderJarOutput.String())
-
// Test that the processors are passed to kapt
expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
" -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
diff --git a/java/testing.go b/java/testing.go
index 82aa29b..4000334 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -70,6 +70,10 @@
defaultJavaDir + "/framework/aidl": nil,
// Needed for various deps defined in GatherRequiredDepsForTest()
defaultJavaDir + "/a.java": nil,
+
+ // Needed for R8 rules on apps
+ "build/make/core/proguard.flags": nil,
+ "build/make/core/proguard_basic_keeps.flags": nil,
}.AddToFixture(),
// The java default module definitions.
android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 4cde7d1..8f4fea4 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -32,6 +32,7 @@
"os"
"path/filepath"
"regexp"
+ "sort"
"strconv"
"strings"
"text/scanner"
@@ -79,7 +80,7 @@
"copy-files": &simpleCallParser{name: baseName + ".copy_files", returnType: starlarkTypeList},
"dir": &simpleCallParser{name: baseName + ".dir", returnType: starlarkTypeString},
"dist-for-goals": &simpleCallParser{name: baseName + ".mkdist_for_goals", returnType: starlarkTypeVoid, addGlobals: true},
- "enforce-product-packages-exist": &simpleCallParser{name: baseName + ".enforce_product_packages_exist", returnType: starlarkTypeVoid},
+ "enforce-product-packages-exist": &simpleCallParser{name: baseName + ".enforce_product_packages_exist", returnType: starlarkTypeVoid, addHandle: true},
"error": &makeControlFuncParser{name: baseName + ".mkerror"},
"findstring": &simpleCallParser{name: baseName + ".findstring", returnType: starlarkTypeInt},
"find-copy-subdir-files": &simpleCallParser{name: baseName + ".find_and_copy", returnType: starlarkTypeList},
@@ -106,10 +107,11 @@
"my-dir": &myDirCallParser{},
"patsubst": &substCallParser{fname: "patsubst"},
"product-copy-files-by-pattern": &simpleCallParser{name: baseName + ".product_copy_files_by_pattern", returnType: starlarkTypeList},
- "require-artifacts-in-path": &simpleCallParser{name: baseName + ".require_artifacts_in_path", returnType: starlarkTypeVoid},
- "require-artifacts-in-path-relaxed": &simpleCallParser{name: baseName + ".require_artifacts_in_path_relaxed", returnType: starlarkTypeVoid},
+ "require-artifacts-in-path": &simpleCallParser{name: baseName + ".require_artifacts_in_path", returnType: starlarkTypeVoid, addHandle: true},
+ "require-artifacts-in-path-relaxed": &simpleCallParser{name: baseName + ".require_artifacts_in_path_relaxed", returnType: starlarkTypeVoid, addHandle: true},
// TODO(asmundak): remove it once all calls are removed from configuration makefiles. see b/183161002
"shell": &shellCallParser{},
+ "sort": &simpleCallParser{name: baseName + ".mksort", returnType: starlarkTypeList},
"strip": &simpleCallParser{name: baseName + ".mkstrip", returnType: starlarkTypeString},
"subst": &substCallParser{fname: "subst"},
"warning": &makeControlFuncParser{name: baseName + ".mkwarning"},
@@ -761,6 +763,16 @@
func (ctx *parseContext) handleSubConfig(
v mkparser.Node, pathExpr starlarkExpr, loadAlways bool, processModule func(inheritedModule) starlarkNode) []starlarkNode {
+ // Allow seeing $(sort $(wildcard realPathExpr)) or $(wildcard realPathExpr)
+ // because those are functionally the same as not having the sort/wildcard calls.
+ if ce, ok := pathExpr.(*callExpr); ok && ce.name == "rblf.mksort" && len(ce.args) == 1 {
+ if ce2, ok2 := ce.args[0].(*callExpr); ok2 && ce2.name == "rblf.expand_wildcard" && len(ce2.args) == 1 {
+ pathExpr = ce2.args[0]
+ }
+ } else if ce2, ok2 := pathExpr.(*callExpr); ok2 && ce2.name == "rblf.expand_wildcard" && len(ce2.args) == 1 {
+ pathExpr = ce2.args[0]
+ }
+
// In a simple case, the name of a module to inherit/include is known statically.
if path, ok := maybeString(pathExpr); ok {
// Note that even if this directive loads a module unconditionally, a module may be
@@ -768,6 +780,7 @@
moduleShouldExist := loadAlways && ctx.ifNestLevel == 0
if strings.Contains(path, "*") {
if paths, err := fs.Glob(ctx.script.sourceFS, path); err == nil {
+ sort.Strings(paths)
result := make([]starlarkNode, 0)
for _, p := range paths {
mi := ctx.newDependentModule(p, !moduleShouldExist)
@@ -1228,7 +1241,7 @@
}
name = words[0].Dump()
if len(words) < 2 {
- args = &mkparser.MakeString{}
+ args = mkparser.SimpleMakeString("", words[0].Pos())
} else {
args = words[1]
}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 33961f1..de75129 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -197,15 +197,31 @@
mkname: "path/product.mk",
in: `
$(call inherit-product, */font.mk)
+$(call inherit-product, $(sort $(wildcard */font.mk)))
+$(call inherit-product, $(wildcard */font.mk))
+
+include */font.mk
+include $(sort $(wildcard */font.mk))
+include $(wildcard */font.mk)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
-load("//foo:font.star", _font_init = "init")
-load("//bar:font.star", _font1_init = "init")
+load("//bar:font.star", _font_init = "init")
+load("//foo:font.star", _font1_init = "init")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.inherit(handle, "foo/font", _font_init)
- rblf.inherit(handle, "bar/font", _font1_init)
+ rblf.inherit(handle, "bar/font", _font_init)
+ rblf.inherit(handle, "foo/font", _font1_init)
+ rblf.inherit(handle, "bar/font", _font_init)
+ rblf.inherit(handle, "foo/font", _font1_init)
+ rblf.inherit(handle, "bar/font", _font_init)
+ rblf.inherit(handle, "foo/font", _font1_init)
+ _font_init(g, handle)
+ _font1_init(g, handle)
+ _font_init(g, handle)
+ _font1_init(g, handle)
+ _font_init(g, handle)
+ _font1_init(g, handle)
`,
},
{
@@ -757,10 +773,10 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.enforce_product_packages_exist("")
- rblf.enforce_product_packages_exist("foo")
- rblf.require_artifacts_in_path("foo", "bar")
- rblf.require_artifacts_in_path_relaxed("foo", "bar")
+ rblf.enforce_product_packages_exist(handle, "")
+ rblf.enforce_product_packages_exist(handle, "foo")
+ rblf.require_artifacts_in_path(handle, "foo", "bar")
+ rblf.require_artifacts_in_path_relaxed(handle, "foo", "bar")
rblf.mkdist_for_goals(g, "goal", "from:to")
rblf.add_product_dex_preopt_module_config(handle, "MyModule", "disable")
`,
@@ -1022,12 +1038,13 @@
`,
},
{
- desc: "strip function",
+ desc: "strip/sort functions",
mkname: "product.mk",
in: `
ifeq ($(filter hwaddress,$(PRODUCT_PACKAGES)),)
PRODUCT_PACKAGES := $(strip $(PRODUCT_PACKAGES) hwaddress)
endif
+MY_VAR := $(sort b a c)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -1036,6 +1053,7 @@
if "hwaddress" not in cfg.get("PRODUCT_PACKAGES", []):
rblf.setdefault(handle, "PRODUCT_PACKAGES")
cfg["PRODUCT_PACKAGES"] = (rblf.mkstrip("%s hwaddress" % " ".join(cfg.get("PRODUCT_PACKAGES", [])))).split()
+ g["MY_VAR"] = rblf.mksort("b a c")
`,
},
{
diff --git a/provenance/Android.bp b/provenance/Android.bp
new file mode 100644
index 0000000..6fd67aa
--- /dev/null
+++ b/provenance/Android.bp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-provenance",
+ pkgPath: "android/soong/provenance",
+ srcs: [
+ "provenance_singleton.go",
+ ],
+ deps: [
+ "soong-android",
+ ],
+ testSrcs: [
+ "provenance_singleton_test.go",
+ ],
+ pluginFor: [
+ "soong_build",
+ ],
+}
diff --git a/provenance/provenance_metadata_proto/Android.bp b/provenance/provenance_metadata_proto/Android.bp
new file mode 100644
index 0000000..7fc47a9
--- /dev/null
+++ b/provenance/provenance_metadata_proto/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_library_host {
+ name: "provenance_metadata_proto",
+ version: {
+ py3: {
+ enabled: true,
+ },
+ },
+ srcs: [
+ "provenance_metadata.proto",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/provenance/provenance_metadata_proto/provenance_metadata.proto b/provenance/provenance_metadata_proto/provenance_metadata.proto
new file mode 100644
index 0000000..f42aba7
--- /dev/null
+++ b/provenance/provenance_metadata_proto/provenance_metadata.proto
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package provenance_metadata_proto;
+option go_package = "android/soong/provenance/provenance_metadata_proto";
+
+// Provenance metadata of artifacts.
+message ProvenanceMetadata {
+ // Name of the module/target that creates the artifact.
+ // It is either a Soong module name or Bazel target label.
+ string module_name = 1;
+
+ // The path to the prebuilt artifacts, which is relative to the source tree
+ // directory. For example, “prebuilts/runtime/mainline/i18n/apex/com.android.i18n-arm.apex”.
+ string artifact_path = 2;
+
+ // The SHA256 hash of the artifact.
+ string artifact_sha256 = 3;
+
+ // The install path of the artifact in filesystem images.
+ // This is the absolute path of the artifact on the device.
+ string artifact_install_path = 4;
+
+ // Path of the attestation file of a prebuilt artifact, which is relative to
+ // the source tree directory. This is for prebuilt artifacts which have
+ // corresponding attestation files checked in the source tree.
+ string attestation_path = 5;
+}
+
+message ProvenanceMetaDataList {
+ repeated ProvenanceMetadata metadata = 1;
+}
\ No newline at end of file
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
new file mode 100644
index 0000000..ae96e1f
--- /dev/null
+++ b/provenance/provenance_singleton.go
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package provenance
+
+import (
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+var (
+ pctx = android.NewPackageContext("android/soong/provenance")
+ rule = pctx.HostBinToolVariable("gen_provenance_metadata", "gen_provenance_metadata")
+
+ genProvenanceMetaData = pctx.AndroidStaticRule("genProvenanceMetaData",
+ blueprint.RuleParams{
+ Command: `rm -rf "$out" && ` +
+ `${gen_provenance_metadata} --module_name=${module_name} ` +
+ `--artifact_path=$in --install_path=${install_path} --metadata_path=$out`,
+ CommandDeps: []string{"${gen_provenance_metadata}"},
+ }, "module_name", "install_path")
+
+ mergeProvenanceMetaData = pctx.AndroidStaticRule("mergeProvenanceMetaData",
+ blueprint.RuleParams{
+ Command: `rm -rf $out $out.temp && ` +
+ `echo -e "# proto-file: build/soong/provenance/proto/provenance_metadata.proto\n# proto-message: ProvenanceMetaDataList" > $out && ` +
+ `touch $out.temp && cat $out.temp $in | grep -v "^#.*" >> $out && rm -rf $out.temp`,
+ })
+)
+
+type ProvenanceMetadata interface {
+ ProvenanceMetaDataFile() android.OutputPath
+}
+
+func init() {
+ RegisterProvenanceSingleton(android.InitRegistrationContext)
+}
+
+func RegisterProvenanceSingleton(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("provenance_metadata_singleton", provenanceInfoSingletonFactory)
+}
+
+var PrepareForTestWithProvenanceSingleton = android.FixtureRegisterWithContext(RegisterProvenanceSingleton)
+
+func provenanceInfoSingletonFactory() android.Singleton {
+ return &provenanceInfoSingleton{}
+}
+
+type provenanceInfoSingleton struct {
+}
+
+func (b *provenanceInfoSingleton) GenerateBuildActions(context android.SingletonContext) {
+ allMetaDataFiles := make([]android.Path, 0)
+ context.VisitAllModulesIf(moduleFilter, func(module android.Module) {
+ if p, ok := module.(ProvenanceMetadata); ok {
+ allMetaDataFiles = append(allMetaDataFiles, p.ProvenanceMetaDataFile())
+ }
+ })
+ mergedMetaDataFile := android.PathForOutput(context, "provenance_metadata.textproto")
+ context.Build(pctx, android.BuildParams{
+ Rule: mergeProvenanceMetaData,
+ Description: "merge provenance metadata",
+ Inputs: allMetaDataFiles,
+ Output: mergedMetaDataFile,
+ })
+
+ context.Build(pctx, android.BuildParams{
+ Rule: blueprint.Phony,
+ Description: "phony rule of merge provenance metadata",
+ Inputs: []android.Path{mergedMetaDataFile},
+ Output: android.PathForPhony(context, "provenance_metadata"),
+ })
+}
+
+func moduleFilter(module android.Module) bool {
+ if !module.Enabled() || module.IsSkipInstall() {
+ return false
+ }
+ if p, ok := module.(ProvenanceMetadata); ok {
+ return p.ProvenanceMetaDataFile().String() != ""
+ }
+ return false
+}
+
+func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.OutputPath {
+ onDevicePathOfInstalledFile := android.InstallPathToOnDevicePath(ctx, installedFile)
+ artifactMetaDataFile := android.PathForIntermediates(ctx, "provenance_metadata", ctx.ModuleDir(), ctx.ModuleName(), "provenance_metadata.textproto")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: genProvenanceMetaData,
+ Description: "generate artifact provenance metadata",
+ Inputs: []android.Path{artifactPath},
+ Output: artifactMetaDataFile,
+ Args: map[string]string{
+ "module_name": ctx.ModuleName(),
+ "install_path": onDevicePathOfInstalledFile,
+ }})
+
+ return artifactMetaDataFile
+}
diff --git a/provenance/provenance_singleton_test.go b/provenance/provenance_singleton_test.go
new file mode 100644
index 0000000..0f1eae2
--- /dev/null
+++ b/provenance/provenance_singleton_test.go
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package provenance
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestProvenanceSingleton(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithProvenanceSingleton,
+ android.PrepareForTestWithAndroidMk).RunTestWithBp(t, "")
+
+ outputs := result.SingletonForTests("provenance_metadata_singleton").AllOutputs()
+ for _, output := range outputs {
+ testingBuildParam := result.SingletonForTests("provenance_metadata_singleton").Output(output)
+ switch {
+ case strings.Contains(output, "soong/provenance_metadata.textproto"):
+ android.AssertStringEquals(t, "Invalid build rule", "android/soong/provenance.mergeProvenanceMetaData", testingBuildParam.Rule.String())
+ android.AssertIntEquals(t, "Invalid input", len(testingBuildParam.Inputs), 0)
+ android.AssertStringDoesContain(t, "Invalid output path", output, "soong/provenance_metadata.textproto")
+ android.AssertIntEquals(t, "Invalid args", len(testingBuildParam.Args), 0)
+
+ case strings.HasSuffix(output, "provenance_metadata"):
+ android.AssertStringEquals(t, "Invalid build rule", "<builtin>:phony", testingBuildParam.Rule.String())
+ android.AssertStringEquals(t, "Invalid input", testingBuildParam.Inputs[0].String(), "out/soong/provenance_metadata.textproto")
+ android.AssertStringEquals(t, "Invalid output path", output, "provenance_metadata")
+ android.AssertIntEquals(t, "Invalid args", len(testingBuildParam.Args), 0)
+ }
+ }
+}
diff --git a/provenance/tools/Android.bp b/provenance/tools/Android.bp
new file mode 100644
index 0000000..0eddd76
--- /dev/null
+++ b/provenance/tools/Android.bp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_binary_host {
+ name: "gen_provenance_metadata",
+ srcs: [
+ "gen_provenance_metadata.py",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+ libs: [
+ "provenance_metadata_proto",
+ "libprotobuf-python",
+ ],
+}
+
+python_test_host {
+ name: "gen_provenance_metadata_test",
+ main: "gen_provenance_metadata_test.py",
+ srcs: [
+ "gen_provenance_metadata_test.py",
+ ],
+ data: [
+ ":gen_provenance_metadata",
+ ],
+ libs: [
+ "provenance_metadata_proto",
+ "libprotobuf-python",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/provenance/tools/gen_provenance_metadata.py b/provenance/tools/gen_provenance_metadata.py
new file mode 100644
index 0000000..b33f911
--- /dev/null
+++ b/provenance/tools/gen_provenance_metadata.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+import argparse
+import hashlib
+import sys
+
+import google.protobuf.text_format as text_format
+import provenance_metadata_pb2
+
+def Log(*info):
+ if args.verbose:
+ for i in info:
+ print(i)
+
+def ParseArgs(argv):
+ parser = argparse.ArgumentParser(description='Create provenance metadata for a prebuilt artifact')
+ parser.add_argument('-v', '--verbose', action='store_true', help='Print more information in execution')
+ parser.add_argument('--module_name', help='Module name', required=True)
+ parser.add_argument('--artifact_path', help='Relative path of the prebuilt artifact in source tree', required=True)
+ parser.add_argument('--install_path', help='Absolute path of the artifact in the filesystem images', required=True)
+ parser.add_argument('--metadata_path', help='Path of the provenance metadata file created for the artifact', required=True)
+ return parser.parse_args(argv)
+
+def main(argv):
+ global args
+ args = ParseArgs(argv)
+ Log("Args:", vars(args))
+
+ provenance_metadata = provenance_metadata_pb2.ProvenanceMetadata()
+ provenance_metadata.module_name = args.module_name
+ provenance_metadata.artifact_path = args.artifact_path
+ provenance_metadata.artifact_install_path = args.install_path
+
+ Log("Generating SHA256 hash")
+ h = hashlib.sha256()
+ with open(args.artifact_path, "rb") as artifact_file:
+ h.update(artifact_file.read())
+ provenance_metadata.artifact_sha256 = h.hexdigest()
+
+ text_proto = [
+ "# proto-file: build/soong/provenance/proto/provenance_metadata.proto",
+ "# proto-message: ProvenanceMetaData",
+ "",
+ text_format.MessageToString(provenance_metadata)
+ ]
+ with open(args.metadata_path, "wt") as metadata_file:
+ file_content = "\n".join(text_proto)
+ Log("Writing provenance metadata in textproto:", file_content)
+ metadata_file.write(file_content)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/provenance/tools/gen_provenance_metadata_test.py b/provenance/tools/gen_provenance_metadata_test.py
new file mode 100644
index 0000000..2fc04bf
--- /dev/null
+++ b/provenance/tools/gen_provenance_metadata_test.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+import hashlib
+import logging
+import os
+import subprocess
+import tempfile
+import unittest
+
+import google.protobuf.text_format as text_format
+import provenance_metadata_pb2
+
+logger = logging.getLogger(__name__)
+
+def run(args, verbose=None, **kwargs):
+ """Creates and returns a subprocess.Popen object.
+
+ Args:
+ args: The command represented as a list of strings.
+ verbose: Whether the commands should be shown. Default to the global
+ verbosity if unspecified.
+ kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
+ stdin, etc. stdout and stderr will default to subprocess.PIPE and
+ subprocess.STDOUT respectively unless caller specifies any of them.
+ universal_newlines will default to True, as most of the users in
+ releasetools expect string output.
+
+ Returns:
+ A subprocess.Popen object.
+ """
+ if 'stdout' not in kwargs and 'stderr' not in kwargs:
+ kwargs['stdout'] = subprocess.PIPE
+ kwargs['stderr'] = subprocess.STDOUT
+ if 'universal_newlines' not in kwargs:
+ kwargs['universal_newlines'] = True
+ if verbose:
+ logger.info(" Running: \"%s\"", " ".join(args))
+ return subprocess.Popen(args, **kwargs)
+
+
+def run_and_check_output(args, verbose=None, **kwargs):
+ """Runs the given command and returns the output.
+
+ Args:
+ args: The command represented as a list of strings.
+ verbose: Whether the commands should be shown. Default to the global
+ verbosity if unspecified.
+ kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
+ stdin, etc. stdout and stderr will default to subprocess.PIPE and
+ subprocess.STDOUT respectively unless caller specifies any of them.
+
+ Returns:
+ The output string.
+
+ Raises:
+ ExternalError: On non-zero exit from the command.
+ """
+ proc = run(args, verbose=verbose, **kwargs)
+ output, _ = proc.communicate()
+ if output is None:
+ output = ""
+ if verbose:
+ logger.info("%s", output.rstrip())
+ if proc.returncode != 0:
+ raise RuntimeError(
+ "Failed to run command '{}' (exit code {}):\n{}".format(
+ args, proc.returncode, output))
+ return output
+
+def run_host_command(args, verbose=None, **kwargs):
+ host_build_top = os.environ.get("ANDROID_BUILD_TOP")
+ if host_build_top:
+ host_command_dir = os.path.join(host_build_top, "out/host/linux-x86/bin")
+ args[0] = os.path.join(host_command_dir, args[0])
+ return run_and_check_output(args, verbose, **kwargs)
+
+def sha256(s):
+ h = hashlib.sha256()
+ h.update(bytearray(s, 'utf-8'))
+ return h.hexdigest()
+
+class ProvenanceMetaDataToolTest(unittest.TestCase):
+
+ def test_gen_provenance_metadata(self):
+ artifact_content = "test artifact"
+ artifact_file = tempfile.mktemp()
+ with open(artifact_file,"wt") as f:
+ f.write(artifact_content)
+ metadata_file = tempfile.mktemp()
+ cmd = ["gen_provenance_metadata"]
+ cmd.extend(["--module_name", "a"])
+ cmd.extend(["--artifact_path", artifact_file])
+ cmd.extend(["--install_path", "b"])
+ cmd.extend(["--metadata_path", metadata_file])
+ output = run_host_command(cmd)
+ self.assertEqual(output, "")
+
+ with open(metadata_file,"rt") as f:
+ data = f.read()
+ provenance_metadata = provenance_metadata_pb2.ProvenanceMetadata()
+ text_format.Parse(data, provenance_metadata)
+ self.assertEqual(provenance_metadata.module_name, "a")
+ self.assertEqual(provenance_metadata.artifact_path, artifact_file)
+ self.assertEqual(provenance_metadata.artifact_install_path, "b")
+ self.assertEqual(provenance_metadata.artifact_sha256, sha256(artifact_content))
+
+ os.remove(artifact_file)
+ os.remove(metadata_file)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
\ No newline at end of file
diff --git a/rust/builder.go b/rust/builder.go
index 00035b9..20ca5db 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -274,7 +274,7 @@
implicits = append(implicits, outputs.Paths()...)
}
- envVars = append(envVars, "ANDROID_RUST_VERSION="+config.RustDefaultVersion)
+ envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
if ctx.RustModule().compiler.CargoEnvCompat() {
if _, ok := ctx.RustModule().compiler.(*binaryDecorator); ok {
diff --git a/rust/config/global.go b/rust/config/global.go
index 1cf773e..2d5fa99 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -86,12 +86,7 @@
return "${RustDefaultBase}"
})
- pctx.VariableFunc("RustVersion", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("RUST_PREBUILTS_VERSION"); override != "" {
- return override
- }
- return RustDefaultVersion
- })
+ pctx.VariableFunc("RustVersion", getRustVersionPctx)
pctx.StaticVariable("RustPath", "${RustBase}/${HostPrebuiltTag}/${RustVersion}")
pctx.StaticVariable("RustBin", "${RustPath}/bin")
@@ -103,3 +98,14 @@
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
}
+
+func getRustVersionPctx(ctx android.PackageVarContext) string {
+ return GetRustVersion(ctx)
+}
+
+func GetRustVersion(ctx android.PathContext) string {
+ if override := ctx.Config().Getenv("RUST_PREBUILTS_VERSION"); override != "" {
+ return override
+ }
+ return RustDefaultVersion
+}
diff --git a/rust/rust.go b/rust/rust.go
index d627261..2a7bdcf 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -332,6 +332,20 @@
return false
}
+func (mod *Module) IsVndkPrebuiltLibrary() bool {
+ // Rust modules do not provide VNDK prebuilts
+ return false
+}
+
+func (mod *Module) IsVendorPublicLibrary() bool {
+ return mod.VendorProperties.IsVendorPublicLibrary
+}
+
+func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool {
+ // Rust modules to not provide Sdk variants
+ return false
+}
+
func (c *Module) IsVndkPrivate() bool {
return false
}
@@ -841,24 +855,7 @@
toolchain := mod.toolchain(ctx)
mod.makeLinkType = cc.GetMakeLinkType(actx, mod)
- // Differentiate static libraries that are vendor available
- if mod.UseVndk() {
- if mod.InProduct() && !mod.OnlyInProduct() {
- mod.Properties.SubName += cc.ProductSuffix
- } else {
- mod.Properties.SubName += cc.VendorSuffix
- }
- } else if mod.InRamdisk() && !mod.OnlyInRamdisk() {
- mod.Properties.SubName += cc.RamdiskSuffix
- } else if mod.InVendorRamdisk() && !mod.OnlyInVendorRamdisk() {
- mod.Properties.SubName += cc.VendorRamdiskSuffix
- } else if mod.InRecovery() && !mod.OnlyInRecovery() {
- mod.Properties.SubName += cc.RecoverySuffix
- }
-
- if mod.Target().NativeBridge == android.NativeBridgeEnabled {
- mod.Properties.SubName += cc.NativeBridgeSuffix
- }
+ mod.Properties.SubName = cc.GetSubnameProperty(actx, mod)
if !toolchain.Supported() {
// This toolchain's unsupported, there's nothing to do for this mod.
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
index e5214df..f985a49 100755
--- a/scripts/hiddenapi/verify_overlaps.py
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -23,13 +23,13 @@
from signature_trie import signature_trie
-def dict_reader(csvfile):
+def dict_reader(csv_file):
return csv.DictReader(
- csvfile, delimiter=",", quotechar="|", fieldnames=["signature"])
+ csv_file, delimiter=",", quotechar="|", fieldnames=["signature"])
def read_flag_trie_from_file(file):
- with open(file, "r") as stream:
+ with open(file, "r", encoding="utf8") as stream:
return read_flag_trie_from_stream(stream)
@@ -43,24 +43,24 @@
def extract_subset_from_monolithic_flags_as_dict_from_file(
- monolithicTrie, patternsFile):
+ monolithic_trie, patterns_file):
"""Extract a subset of flags from the dict of monolithic flags.
- :param monolithicFlagsDict: the dict containing all the monolithic flags.
- :param patternsFile: a file containing a list of signature patterns that
+ :param monolithic_trie: the trie containing all the monolithic flags.
+ :param patterns_file: a file containing a list of signature patterns that
define the subset.
:return: the dict from signature to row.
"""
- with open(patternsFile, "r") as stream:
+ with open(patterns_file, "r", encoding="utf8") as stream:
return extract_subset_from_monolithic_flags_as_dict_from_stream(
- monolithicTrie, stream)
+ monolithic_trie, stream)
def extract_subset_from_monolithic_flags_as_dict_from_stream(
- monolithicTrie, stream):
+ monolithic_trie, stream):
"""Extract a subset of flags from the trie of monolithic flags.
- :param monolithicTrie: the trie containing all the monolithic flags.
+ :param monolithic_trie: the trie containing all the monolithic flags.
:param stream: a stream containing a list of signature patterns that define
the subset.
:return: the dict from signature to row.
@@ -68,7 +68,7 @@
dict_signature_to_row = {}
for pattern in stream:
pattern = pattern.rstrip()
- rows = monolithicTrie.get_matching_rows(pattern)
+ rows = monolithic_trie.get_matching_rows(pattern)
for row in rows:
signature = row["signature"]
dict_signature_to_row[signature] = row
@@ -93,86 +93,110 @@
return dict_signature_to_row
-def read_signature_csv_from_file_as_dict(csvFile):
+def read_signature_csv_from_file_as_dict(csv_file):
"""Read the csvFile into a dict.
The first column is assumed to be the signature and used as the
key.
The whole row is stored as the value.
- :param csvFile: the csv file to read
+ :param csv_file: the csv file to read
:return: the dict from signature to row.
"""
- with open(csvFile, "r") as f:
+ with open(csv_file, "r", encoding="utf8") as f:
return read_signature_csv_from_stream_as_dict(f)
-def compare_signature_flags(monolithicFlagsDict, modularFlagsDict):
+def compare_signature_flags(monolithic_flags_dict, modular_flags_dict,
+ implementation_flags):
"""Compare the signature flags between the two dicts.
- :param monolithicFlagsDict: the dict containing the subset of the monolithic
- flags that should be equal to the modular flags.
- :param modularFlagsDict:the dict containing the flags produced by a single
+ :param monolithic_flags_dict: the dict containing the subset of the
+ monolithic flags that should be equal to the modular flags.
+ :param modular_flags_dict:the dict containing the flags produced by a single
bootclasspath_fragment module.
:return: list of mismatches., each mismatch is a tuple where the first item
is the signature, and the second and third items are lists of the flags from
modular dict, and monolithic dict respectively.
"""
- mismatchingSignatures = []
+ mismatching_signatures = []
# Create a sorted set of all the signatures from both the monolithic and
# modular dicts.
- allSignatures = sorted(
- set(chain(monolithicFlagsDict.keys(), modularFlagsDict.keys())))
- for signature in allSignatures:
- monolithicRow = monolithicFlagsDict.get(signature, {})
- monolithicFlags = monolithicRow.get(None, [])
- if signature in modularFlagsDict:
- modularRow = modularFlagsDict.get(signature, {})
- modularFlags = modularRow.get(None, [])
+ all_signatures = sorted(
+ set(chain(monolithic_flags_dict.keys(), modular_flags_dict.keys())))
+ for signature in all_signatures:
+ monolithic_row = monolithic_flags_dict.get(signature, {})
+ monolithic_flags = monolithic_row.get(None, [])
+ if signature in modular_flags_dict:
+ modular_row = modular_flags_dict.get(signature, {})
+ modular_flags = modular_row.get(None, [])
else:
- modularFlags = ["blocked"]
- if monolithicFlags != modularFlags:
- mismatchingSignatures.append(
- (signature, modularFlags, monolithicFlags))
- return mismatchingSignatures
+ modular_flags = implementation_flags
+ if monolithic_flags != modular_flags:
+ mismatching_signatures.append(
+ (signature, modular_flags, monolithic_flags))
+ return mismatching_signatures
def main(argv):
args_parser = argparse.ArgumentParser(
description="Verify that sets of hidden API flags are each a subset of "
- "the monolithic flag file.")
- args_parser.add_argument("monolithicFlags", help="The monolithic flag file")
+ "the monolithic flag file. For each module this uses the provided "
+ "signature patterns to select a subset of the monolithic flags and "
+ "then it compares that subset against the filtered flags provided by "
+ "the module. If the module's filtered flags does not contain flags for "
+ "a signature then it is assumed to have been filtered out because it "
+ "was not part of an API and so is assumed to have the implementation "
+ "flags.")
args_parser.add_argument(
- "modularFlags",
- nargs=argparse.REMAINDER,
- help="Flags produced by individual bootclasspath_fragment modules")
+ "--monolithic-flags", help="The monolithic flag file")
+ args_parser.add_argument(
+ "--module-flags",
+ action="append",
+ help="A colon separated pair of paths. The first is a path to a "
+ "filtered set of flags, and the second is a path to a set of "
+ "signature patterns that identify the set of classes belonging to "
+ "a single bootclasspath_fragment module. Specify once for each module "
+ "that needs to be checked.")
+ args_parser.add_argument(
+ "--implementation-flag",
+ action="append",
+ help="A flag in the set of flags that identifies a signature which is "
+ "not part of an API, i.e. is the signature of a private implementation "
+ "member. Specify as many times as necessary to define the "
+ "implementation flag set. If this is not specified then the "
+ "implementation flag set is empty.")
args = args_parser.parse_args(argv[1:])
# Read in all the flags into the trie
- monolithicFlagsPath = args.monolithicFlags
- monolithicTrie = read_flag_trie_from_file(monolithicFlagsPath)
+ monolithic_flags_path = args.monolithic_flags
+ monolithic_trie = read_flag_trie_from_file(monolithic_flags_path)
+
+ implementation_flags = args.implementation_flag or []
# For each subset specified on the command line, create dicts for the flags
# provided by the subset and the corresponding flags from the complete set
# of flags and compare them.
failed = False
- for modularPair in args.modularFlags:
- parts = modularPair.split(":")
- modularFlagsPath = parts[0]
- modularPatternsPath = parts[1]
- modularFlagsDict = read_signature_csv_from_file_as_dict(
- modularFlagsPath)
- monolithicFlagsSubsetDict = \
+ module_pairs = args.module_flags or []
+ for modular_pair in module_pairs:
+ parts = modular_pair.split(":")
+ modular_flags_path = parts[0]
+ modular_patterns_path = parts[1]
+ modular_flags_dict = read_signature_csv_from_file_as_dict(
+ modular_flags_path)
+ monolithic_flags_subset_dict = \
extract_subset_from_monolithic_flags_as_dict_from_file(
- monolithicTrie, modularPatternsPath)
- mismatchingSignatures = compare_signature_flags(
- monolithicFlagsSubsetDict, modularFlagsDict)
- if mismatchingSignatures:
+ monolithic_trie, modular_patterns_path)
+ mismatching_signatures = compare_signature_flags(
+ monolithic_flags_subset_dict, modular_flags_dict,
+ implementation_flags)
+ if mismatching_signatures:
failed = True
print("ERROR: Hidden API flags are inconsistent:")
- print("< " + modularFlagsPath)
- print("> " + monolithicFlagsPath)
- for mismatch in mismatchingSignatures:
+ print("< " + modular_flags_path)
+ print("> " + monolithic_flags_path)
+ for mismatch in mismatching_signatures:
signature = mismatch[0]
print()
print("< " + ",".join([signature] + mismatch[1]))
diff --git a/scripts/hiddenapi/verify_overlaps_test.py b/scripts/hiddenapi/verify_overlaps_test.py
index 8cf2959..0a489ee 100755
--- a/scripts/hiddenapi/verify_overlaps_test.py
+++ b/scripts/hiddenapi/verify_overlaps_test.py
@@ -17,24 +17,26 @@
import io
import unittest
-from verify_overlaps import * #pylint: disable=unused-wildcard-import,wildcard-import
+import verify_overlaps as vo
-#pylint: disable=line-too-long
class TestDetectOverlaps(unittest.TestCase):
- def read_flag_trie_from_string(self, csvdata):
+ @staticmethod
+ def read_flag_trie_from_string(csvdata):
with io.StringIO(csvdata) as f:
- return read_flag_trie_from_stream(f)
+ return vo.read_flag_trie_from_stream(f)
- def read_signature_csv_from_string_as_dict(self, csvdata):
+ @staticmethod
+ def read_signature_csv_from_string_as_dict(csvdata):
with io.StringIO(csvdata) as f:
- return read_signature_csv_from_stream_as_dict(f)
+ return vo.read_signature_csv_from_stream_as_dict(f)
+ @staticmethod
def extract_subset_from_monolithic_flags_as_dict_from_string(
- self, monolithic, patterns):
+ monolithic, patterns):
with io.StringIO(patterns) as f:
- return extract_subset_from_monolithic_flags_as_dict_from_stream(
+ return vo.extract_subset_from_monolithic_flags_as_dict_from_stream(
monolithic, f)
extractInput = """
@@ -50,14 +52,14 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'Ljava/lang/Object;->hashCode()I'
+ patterns = "Ljava/lang/Object;->hashCode()I"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Object;->hashCode()I': {
- None: ['public-api', 'system-api', 'test-api'],
- 'signature': 'Ljava/lang/Object;->hashCode()I',
+ "Ljava/lang/Object;->hashCode()I": {
+ None: ["public-api", "system-api", "test-api"],
+ "signature": "Ljava/lang/Object;->hashCode()I",
},
}
self.assertEqual(expected, subset)
@@ -66,18 +68,18 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'java/lang/Object'
+ patterns = "java/lang/Object"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Object;->hashCode()I': {
- None: ['public-api', 'system-api', 'test-api'],
- 'signature': 'Ljava/lang/Object;->hashCode()I',
+ "Ljava/lang/Object;->hashCode()I": {
+ None: ["public-api", "system-api", "test-api"],
+ "signature": "Ljava/lang/Object;->hashCode()I",
},
- 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
- None: ['blocked'],
- 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ "Ljava/lang/Object;->toString()Ljava/lang/String;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
},
}
self.assertEqual(expected, subset)
@@ -86,20 +88,20 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'java/lang/Character'
+ patterns = "java/lang/Character"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;':
- {
- None: ['blocked'],
- 'signature':
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
- },
- 'Ljava/lang/Character;->serialVersionUID:J': {
- None: ['sdk'],
- 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;",
+ },
+ "Ljava/lang/Character;->serialVersionUID:J": {
+ None: ["sdk"],
+ "signature": "Ljava/lang/Character;->serialVersionUID:J",
},
}
self.assertEqual(expected, subset)
@@ -108,17 +110,17 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'java/lang/Character$UnicodeScript'
+ patterns = "java/lang/Character$UnicodeScript"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;':
- {
- None: ['blocked'],
- 'signature':
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
- },
+ "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;",
+ },
}
self.assertEqual(expected, subset)
@@ -126,32 +128,32 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'java/lang/*'
+ patterns = "java/lang/*"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;':
- {
- None: ['blocked'],
- 'signature':
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
- },
- 'Ljava/lang/Character;->serialVersionUID:J': {
- None: ['sdk'],
- 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;",
},
- 'Ljava/lang/Object;->hashCode()I': {
- None: ['public-api', 'system-api', 'test-api'],
- 'signature': 'Ljava/lang/Object;->hashCode()I',
+ "Ljava/lang/Character;->serialVersionUID:J": {
+ None: ["sdk"],
+ "signature": "Ljava/lang/Character;->serialVersionUID:J",
},
- 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
- None: ['blocked'],
- 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ "Ljava/lang/Object;->hashCode()I": {
+ None: ["public-api", "system-api", "test-api"],
+ "signature": "Ljava/lang/Object;->hashCode()I",
},
- 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V': {
- None: ['blocked'],
- 'signature': 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V',
+ "Ljava/lang/Object;->toString()Ljava/lang/String;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ },
+ "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
},
}
self.assertEqual(expected, subset)
@@ -160,36 +162,36 @@
monolithic = self.read_flag_trie_from_string(
TestDetectOverlaps.extractInput)
- patterns = 'java/**'
+ patterns = "java/**"
subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
monolithic, patterns)
expected = {
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;':
- {
- None: ['blocked'],
- 'signature':
- 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
- },
- 'Ljava/lang/Character;->serialVersionUID:J': {
- None: ['sdk'],
- 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Character$UnicodeScript;"
+ "->of(I)Ljava/lang/Character$UnicodeScript;",
},
- 'Ljava/lang/Object;->hashCode()I': {
- None: ['public-api', 'system-api', 'test-api'],
- 'signature': 'Ljava/lang/Object;->hashCode()I',
+ "Ljava/lang/Character;->serialVersionUID:J": {
+ None: ["sdk"],
+ "signature": "Ljava/lang/Character;->serialVersionUID:J",
},
- 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
- None: ['blocked'],
- 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ "Ljava/lang/Object;->hashCode()I": {
+ None: ["public-api", "system-api", "test-api"],
+ "signature": "Ljava/lang/Object;->hashCode()I",
},
- 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V': {
- None: ['blocked'],
- 'signature': 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V',
+ "Ljava/lang/Object;->toString()Ljava/lang/String;": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
},
- 'Ljava/util/zip/ZipFile;-><clinit>()V': {
- None: ['blocked'],
- 'signature': 'Ljava/util/zip/ZipFile;-><clinit>()V',
+ "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V": {
+ None: ["blocked"],
+ "signature": "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
+ },
+ "Ljava/util/zip/ZipFile;-><clinit>()V": {
+ None: ["blocked"],
+ "signature": "Ljava/util/zip/ZipFile;-><clinit>()V",
},
}
self.assertEqual(expected, subset)
@@ -200,7 +202,7 @@
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->hashCode()I,blocked
""")
- self.assertTrue('Duplicate signature: Ljava/lang/Object;->hashCode()I'
+ self.assertTrue("Duplicate signature: Ljava/lang/Object;->hashCode()I"
in str(context.exception))
def test_read_trie_missing_member(self):
@@ -209,8 +211,8 @@
Ljava/lang/Object,public-api,system-api,test-api
""")
self.assertTrue(
- 'Invalid signature: Ljava/lang/Object, does not identify a specific member'
- in str(context.exception))
+ "Invalid signature: Ljava/lang/Object, "
+ "does not identify a specific member" in str(context.exception))
def test_match(self):
monolithic = self.read_signature_csv_from_string_as_dict("""
@@ -219,7 +221,8 @@
modular = self.read_signature_csv_from_string_as_dict("""
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
""")
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = []
self.assertEqual(expected, mismatches)
@@ -230,12 +233,13 @@
modular = self.read_signature_csv_from_string_as_dict("""
Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
""")
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = [
(
- 'Ljava/lang/Object;->toString()Ljava/lang/String;',
- ['public-api', 'system-api', 'test-api'],
- ['public-api'],
+ "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ ["public-api", "system-api", "test-api"],
+ ["public-api"],
),
]
self.assertEqual(expected, mismatches)
@@ -247,12 +251,13 @@
modular = self.read_signature_csv_from_string_as_dict("""
Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
""")
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = [
(
- 'Ljava/lang/Object;->toString()Ljava/lang/String;',
- ['public-api', 'system-api', 'test-api'],
- ['blocked'],
+ "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ ["public-api", "system-api", "test-api"],
+ ["blocked"],
),
]
self.assertEqual(expected, mismatches)
@@ -264,26 +269,28 @@
modular = self.read_signature_csv_from_string_as_dict("""
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
""")
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = [
(
- 'Ljava/lang/Object;->toString()Ljava/lang/String;',
- ['blocked'],
- ['public-api', 'system-api', 'test-api'],
+ "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ ["blocked"],
+ ["public-api", "system-api", "test-api"],
),
]
self.assertEqual(expected, mismatches)
def test_match_treat_missing_from_modular_as_blocked(self):
- monolithic = self.read_signature_csv_from_string_as_dict('')
+ monolithic = self.read_signature_csv_from_string_as_dict("")
modular = self.read_signature_csv_from_string_as_dict("""
Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
""")
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = [
(
- 'Ljava/lang/Object;->toString()Ljava/lang/String;',
- ['public-api', 'system-api', 'test-api'],
+ "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ ["public-api", "system-api", "test-api"],
[],
),
]
@@ -294,12 +301,13 @@
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
""")
modular = {}
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
expected = [
(
- 'Ljava/lang/Object;->hashCode()I',
- ['blocked'],
- ['public-api', 'system-api', 'test-api'],
+ "Ljava/lang/Object;->hashCode()I",
+ ["blocked"],
+ ["public-api", "system-api", "test-api"],
),
]
self.assertEqual(expected, mismatches)
@@ -309,12 +317,50 @@
Ljava/lang/Object;->hashCode()I,blocked
""")
modular = {}
- mismatches = compare_signature_flags(monolithic, modular)
+ mismatches = vo.compare_signature_flags(monolithic, modular,
+ ["blocked"])
+ expected = []
+ self.assertEqual(expected, mismatches)
+
+ def test_match_treat_missing_from_modular_as_empty(self):
+ monolithic = self.read_signature_csv_from_string_as_dict("")
+ modular = self.read_signature_csv_from_string_as_dict("""
+Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
+""")
+ mismatches = vo.compare_signature_flags(monolithic, modular, [])
+ expected = [
+ (
+ "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ ["public-api", "system-api", "test-api"],
+ [],
+ ),
+ ]
+ self.assertEqual(expected, mismatches)
+
+ def test_mismatch_treat_missing_from_modular_as_empty(self):
+ monolithic = self.read_signature_csv_from_string_as_dict("""
+Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
+""")
+ modular = {}
+ mismatches = vo.compare_signature_flags(monolithic, modular, [])
+ expected = [
+ (
+ "Ljava/lang/Object;->hashCode()I",
+ [],
+ ["public-api", "system-api", "test-api"],
+ ),
+ ]
+ self.assertEqual(expected, mismatches)
+
+ def test_empty_missing_from_modular(self):
+ monolithic = self.read_signature_csv_from_string_as_dict("""
+Ljava/lang/Object;->hashCode()I
+""")
+ modular = {}
+ mismatches = vo.compare_signature_flags(monolithic, modular, [])
expected = []
self.assertEqual(expected, mismatches)
-#pylint: enable=line-too-long
-
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/sdk/testing.go b/sdk/testing.go
index 294f1a5..062f200 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -25,6 +25,8 @@
"android/soong/cc"
"android/soong/genrule"
"android/soong/java"
+
+ "github.com/google/blueprint/proptools"
)
// Prepare for running an sdk test with an apex.
@@ -81,6 +83,11 @@
}
}),
+ // Add a build number file.
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildNumberFile = proptools.StringPtr(BUILD_NUMBER_FILE)
+ }),
+
// Make sure that every test provides all the source files.
android.PrepareForTestDisallowNonExistentPaths,
android.MockFS{
@@ -143,6 +150,8 @@
copyRules := &strings.Builder{}
otherCopyRules := &strings.Builder{}
snapshotDirPrefix := sdk.builderForTests.snapshotDir.String() + "/"
+
+ seenBuildNumberFile := false
for _, bp := range buildParams {
switch bp.Rule.String() {
case android.Cp.String():
@@ -152,8 +161,14 @@
src := android.NormalizePathForTesting(bp.Input)
// We differentiate between copy rules for the snapshot, and copy rules for the install file.
if strings.HasPrefix(output.String(), snapshotDirPrefix) {
- // Get source relative to build directory.
- _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
+ // Don't include the build-number.txt file in the copy rules as that would break lots of
+ // tests, just verify that it is copied here as it should appear in every snapshot.
+ if output.Base() == BUILD_NUMBER_FILE {
+ seenBuildNumberFile = true
+ } else {
+ // Get source relative to build directory.
+ _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
+ }
info.snapshotContents = append(info.snapshotContents, dest)
} else {
_, _ = fmt.Fprintf(otherCopyRules, "%s -> %s\n", src, dest)
@@ -189,6 +204,10 @@
}
}
+ if !seenBuildNumberFile {
+ panic(fmt.Sprintf("Every snapshot must include the %s file", BUILD_NUMBER_FILE))
+ }
+
info.copyRules = copyRules.String()
info.otherCopyRules = otherCopyRules.String()
diff --git a/sdk/update.go b/sdk/update.go
index 389e845..5db604b 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -281,6 +281,10 @@
return append(variants, newVariant)
}
+// BUILD_NUMBER_FILE is the name of the file in the snapshot zip that will contain the number of
+// the build from which the snapshot was produced.
+const BUILD_NUMBER_FILE = "snapshot-creation-build-number.txt"
+
// SDK directory structure
// <sdk_root>/
// Android.bp : definition of a 'sdk' module is here. This is a hand-made one.
@@ -479,6 +483,9 @@
bp.build(pctx, ctx, nil)
+ // Copy the build number file into the snapshot.
+ builder.CopyToSnapshot(ctx.Config().BuildNumberFile(ctx), BUILD_NUMBER_FILE)
+
filesToZip := builder.filesToZip
// zip them all
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
index 23eee59..3e51fa1 100644
--- a/starlark_fmt/format.go
+++ b/starlark_fmt/format.go
@@ -39,21 +39,26 @@
// PrintsStringList returns a Starlark-compatible string of a list of Strings/Labels.
func PrintStringList(items []string, indentLevel int) string {
- return PrintList(items, indentLevel, `"%s"`)
+ return PrintList(items, indentLevel, func(s string) string {
+ if strings.Contains(s, "\"") {
+ return `'''%s'''`
+ }
+ return `"%s"`
+ })
}
// PrintList returns a Starlark-compatible string of list formmated as requested.
-func PrintList(items []string, indentLevel int, formatString string) string {
+func PrintList(items []string, indentLevel int, formatString func(string) string) string {
if len(items) == 0 {
return "[]"
} else if len(items) == 1 {
- return fmt.Sprintf("["+formatString+"]", items[0])
+ return fmt.Sprintf("["+formatString(items[0])+"]", items[0])
}
list := make([]string, 0, len(items)+2)
list = append(list, "[")
innerIndent := Indention(indentLevel + 1)
for _, item := range items {
- list = append(list, fmt.Sprintf(`%s`+formatString+`,`, innerIndent, item))
+ list = append(list, fmt.Sprintf(`%s`+formatString(item)+`,`, innerIndent, item))
}
list = append(list, Indention(indentLevel)+"]")
return strings.Join(list, "\n")
diff --git a/starlark_fmt/format_test.go b/starlark_fmt/format_test.go
index 90f78ef..9450a31 100644
--- a/starlark_fmt/format_test.go
+++ b/starlark_fmt/format_test.go
@@ -18,6 +18,10 @@
"testing"
)
+func simpleFormat(s string) string {
+ return "%s"
+}
+
func TestPrintEmptyStringList(t *testing.T) {
in := []string{}
indentLevel := 0
@@ -54,7 +58,7 @@
func TestPrintEmptyList(t *testing.T) {
in := []string{}
indentLevel := 0
- out := PrintList(in, indentLevel, "%s")
+ out := PrintList(in, indentLevel, simpleFormat)
expectedOut := "[]"
if out != expectedOut {
t.Errorf("Expected %q, got %q", expectedOut, out)
@@ -64,7 +68,7 @@
func TestPrintSingleElementList(t *testing.T) {
in := []string{"1"}
indentLevel := 0
- out := PrintList(in, indentLevel, "%s")
+ out := PrintList(in, indentLevel, simpleFormat)
expectedOut := `[1]`
if out != expectedOut {
t.Errorf("Expected %q, got %q", expectedOut, out)
@@ -74,7 +78,7 @@
func TestPrintMultiElementList(t *testing.T) {
in := []string{"1", "2"}
indentLevel := 0
- out := PrintList(in, indentLevel, "%s")
+ out := PrintList(in, indentLevel, simpleFormat)
expectedOut := `[
1,
2,
@@ -87,7 +91,7 @@
func TestListWithNonZeroIndent(t *testing.T) {
in := []string{"1", "2"}
indentLevel := 1
- out := PrintList(in, indentLevel, "%s")
+ out := PrintList(in, indentLevel, simpleFormat)
expectedOut := `[
1,
2,
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index f935f06..88ef615 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -98,9 +98,6 @@
"build/soong/scripts/jar-wrapper.sh": nil,
- "build/make/core/proguard.flags": nil,
- "build/make/core/proguard_basic_keeps.flags": nil,
-
"jdk8/jre/lib/jce.jar": nil,
"jdk8/jre/lib/rt.jar": nil,
"jdk8/lib/tools.jar": nil,
diff --git a/ui/build/config.go b/ui/build/config.go
index dd5bd0c..e271bfc 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -144,6 +144,12 @@
// fetchEnvConfig optionally fetches environment config from an
// experiments system to control Soong features dynamically.
func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
+ configName := envConfigName + "." + jsonSuffix
+ expConfigFetcher := &smpb.ExpConfigFetcher{}
+ defer func() {
+ ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
+ }()
+
s, err := os.Stat(configFetcher)
if err != nil {
if os.IsNotExist(err) {
@@ -152,31 +158,38 @@
return err
}
if s.Mode()&0111 == 0 {
+ status := smpb.ExpConfigFetcher_ERROR
+ expConfigFetcher.Status = &status
return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
}
- configExists := false
- outConfigFilePath := filepath.Join(config.OutDir(), envConfigName+jsonSuffix)
- if _, err := os.Stat(outConfigFilePath); err == nil {
- configExists = true
- }
-
tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
defer cancel()
- cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir())
+ fetchStart := time.Now()
+ cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
+ "-output_config_name", configName)
if err := cmd.Start(); err != nil {
+ status := smpb.ExpConfigFetcher_ERROR
+ expConfigFetcher.Status = &status
return err
}
- // If a config file already exists, return immediately and run the config file
- // fetch in the background. Otherwise, wait for the config file to be fetched.
- if configExists {
- go cmd.Wait()
- return nil
- }
if err := cmd.Wait(); err != nil {
+ status := smpb.ExpConfigFetcher_ERROR
+ expConfigFetcher.Status = &status
return err
}
+ fetchEnd := time.Now()
+ expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
+ outConfigFilePath := filepath.Join(config.OutDir(), configName)
+ expConfigFetcher.Filename = proto.String(outConfigFilePath)
+ if _, err := os.Stat(outConfigFilePath); err == nil {
+ status := smpb.ExpConfigFetcher_CONFIG
+ expConfigFetcher.Status = &status
+ } else {
+ status := smpb.ExpConfigFetcher_NO_CONFIG
+ expConfigFetcher.Status = &status
+ }
return nil
}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 6f1ed60..0c62865 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -38,6 +38,7 @@
"time"
"android/soong/shared"
+
"google.golang.org/protobuf/proto"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -135,6 +136,11 @@
m.metrics.SystemResourceInfo = b
}
+// ExpConfigFetcher stores information about the expconfigfetcher.
+func (m *Metrics) ExpConfigFetcher(b *soong_metrics_proto.ExpConfigFetcher) {
+ m.metrics.ExpConfigFetcher = b
+}
+
// SetMetadataMetrics sets information about the build such as the target
// product, host architecture and out directory.
func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 26229c6..69f5689 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -217,6 +217,65 @@
return file_metrics_proto_rawDescGZIP(), []int{5, 0}
}
+type ExpConfigFetcher_ConfigStatus int32
+
+const (
+ ExpConfigFetcher_NO_CONFIG ExpConfigFetcher_ConfigStatus = 0
+ ExpConfigFetcher_CONFIG ExpConfigFetcher_ConfigStatus = 1
+ ExpConfigFetcher_ERROR ExpConfigFetcher_ConfigStatus = 2
+)
+
+// Enum value maps for ExpConfigFetcher_ConfigStatus.
+var (
+ ExpConfigFetcher_ConfigStatus_name = map[int32]string{
+ 0: "NO_CONFIG",
+ 1: "CONFIG",
+ 2: "ERROR",
+ }
+ ExpConfigFetcher_ConfigStatus_value = map[string]int32{
+ "NO_CONFIG": 0,
+ "CONFIG": 1,
+ "ERROR": 2,
+ }
+)
+
+func (x ExpConfigFetcher_ConfigStatus) Enum() *ExpConfigFetcher_ConfigStatus {
+ p := new(ExpConfigFetcher_ConfigStatus)
+ *p = x
+ return p
+}
+
+func (x ExpConfigFetcher_ConfigStatus) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ExpConfigFetcher_ConfigStatus) Descriptor() protoreflect.EnumDescriptor {
+ return file_metrics_proto_enumTypes[3].Descriptor()
+}
+
+func (ExpConfigFetcher_ConfigStatus) Type() protoreflect.EnumType {
+ return &file_metrics_proto_enumTypes[3]
+}
+
+func (x ExpConfigFetcher_ConfigStatus) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ExpConfigFetcher_ConfigStatus) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ExpConfigFetcher_ConfigStatus(num)
+ return nil
+}
+
+// Deprecated: Use ExpConfigFetcher_ConfigStatus.Descriptor instead.
+func (ExpConfigFetcher_ConfigStatus) EnumDescriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{9, 0}
+}
+
type MetricsBase struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -274,6 +333,8 @@
BuildCommand *string `protobuf:"bytes,26,opt,name=build_command,json=buildCommand" json:"build_command,omitempty"`
// The metrics for calling Bazel.
BazelRuns []*PerfInfo `protobuf:"bytes,27,rep,name=bazel_runs,json=bazelRuns" json:"bazel_runs,omitempty"`
+ // The metrics of the experiment config fetcher
+ ExpConfigFetcher *ExpConfigFetcher `protobuf:"bytes,28,opt,name=exp_config_fetcher,json=expConfigFetcher" json:"exp_config_fetcher,omitempty"`
}
// Default values for MetricsBase fields.
@@ -505,6 +566,13 @@
return nil
}
+func (x *MetricsBase) GetExpConfigFetcher() *ExpConfigFetcher {
+ if x != nil {
+ return x.ExpConfigFetcher
+ }
+ return nil
+}
+
type BuildConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1150,12 +1218,81 @@
return nil
}
+type ExpConfigFetcher struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The result of the call to expconfigfetcher
+ // NO_CONFIG - Not part of experiment
+ // CONFIG - Part of experiment, config copied successfully
+ // ERROR - expconfigfetcher failed
+ Status *ExpConfigFetcher_ConfigStatus `protobuf:"varint,1,opt,name=status,enum=soong_build_metrics.ExpConfigFetcher_ConfigStatus" json:"status,omitempty"`
+ // The output config filename
+ Filename *string `protobuf:"bytes,2,opt,name=filename" json:"filename,omitempty"`
+ // Time, in microseconds, taken by the expconfigfetcher
+ Micros *uint64 `protobuf:"varint,3,opt,name=micros" json:"micros,omitempty"`
+}
+
+func (x *ExpConfigFetcher) Reset() {
+ *x = ExpConfigFetcher{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ExpConfigFetcher) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExpConfigFetcher) ProtoMessage() {}
+
+func (x *ExpConfigFetcher) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ExpConfigFetcher.ProtoReflect.Descriptor instead.
+func (*ExpConfigFetcher) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *ExpConfigFetcher) GetStatus() ExpConfigFetcher_ConfigStatus {
+ if x != nil && x.Status != nil {
+ return *x.Status
+ }
+ return ExpConfigFetcher_NO_CONFIG
+}
+
+func (x *ExpConfigFetcher) GetFilename() string {
+ if x != nil && x.Filename != nil {
+ return *x.Filename
+ }
+ return ""
+}
+
+func (x *ExpConfigFetcher) GetMicros() uint64 {
+ if x != nil && x.Micros != nil {
+ return *x.Micros
+ }
+ return 0
+}
+
var File_metrics_proto protoreflect.FileDescriptor
var file_metrics_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x22, 0xd8, 0x0c, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0xad, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -1249,122 +1386,140 @@
0x64, 0x12, 0x3c, 0x0a, 0x0a, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x72, 0x75, 0x6e, 0x73, 0x18,
0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x73, 0x22,
- 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12,
- 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45,
- 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10,
- 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
- 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12,
- 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38,
- 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22,
- 0xd3, 0x01, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73,
- 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65,
- 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65,
- 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72,
- 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a,
- 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12,
- 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65,
- 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74,
- 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61,
- 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12,
- 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
- 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0x81, 0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49,
- 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61,
- 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73,
- 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x6c,
- 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x61,
- 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f,
- 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x6d,
- 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
- 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
- 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e,
- 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
- 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f,
- 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c,
- 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11,
- 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74,
- 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61,
- 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f,
- 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61,
- 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
- 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70,
- 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75,
- 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75,
- 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
- 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74,
- 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75,
- 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74,
- 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
- 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74,
- 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f,
- 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77,
- 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
- 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65,
- 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
- 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64,
- 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f,
- 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
- 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a,
- 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07,
- 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f,
- 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c,
- 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
- 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42,
- 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b,
- 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72,
- 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63,
- 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
- 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72,
- 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73,
- 0x22, 0xfa, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
- 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
- 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
- 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69,
- 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73,
- 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65,
- 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73,
- 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72,
- 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x28, 0x5a,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x52, 0x75, 0x6e, 0x73, 0x12,
+ 0x53, 0x0a, 0x12, 0x65, 0x78, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x65,
+ 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
+ 0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74,
+ 0x63, 0x68, 0x65, 0x72, 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72,
+ 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d,
+ 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a,
+ 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b,
+ 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41,
+ 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12,
+ 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f,
+ 0x36, 0x34, 0x10, 0x04, 0x22, 0xd3, 0x01, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12,
+ 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63,
+ 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24,
+ 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e,
+ 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69,
+ 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79,
+ 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+ 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63,
+ 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
+ 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76,
+ 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0x81, 0x02, 0x0a, 0x08,
+ 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d,
+ 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a,
+ 0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02,
+ 0x18, 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a,
+ 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
+ 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22,
+ 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75,
+ 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d,
+ 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
+ 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
+ 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b,
+ 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b,
+ 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69,
+ 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a,
+ 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c,
+ 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50,
+ 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
+ 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f,
+ 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76,
+ 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+ 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+ 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76,
+ 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+ 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74,
+ 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e,
+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b,
+ 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09,
+ 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b,
+ 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55,
+ 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65,
+ 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f,
+ 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65,
+ 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
+ 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42,
+ 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
+ 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a,
+ 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a,
+ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
+ 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68,
+ 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
+ 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65,
+ 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x73, 0x22, 0xc8, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
+ 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78,
+ 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61,
+ 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x34, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f,
+ 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47,
+ 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x42, 0x28, 0x5a,
0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
@@ -1382,46 +1537,50 @@
return file_metrics_proto_rawDescData
}
-var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
+var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_metrics_proto_goTypes = []interface{}{
(MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
(MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
(ModuleTypeInfo_BuildSystem)(0), // 2: soong_build_metrics.ModuleTypeInfo.BuildSystem
- (*MetricsBase)(nil), // 3: soong_build_metrics.MetricsBase
- (*BuildConfig)(nil), // 4: soong_build_metrics.BuildConfig
- (*SystemResourceInfo)(nil), // 5: soong_build_metrics.SystemResourceInfo
- (*PerfInfo)(nil), // 6: soong_build_metrics.PerfInfo
- (*ProcessResourceInfo)(nil), // 7: soong_build_metrics.ProcessResourceInfo
- (*ModuleTypeInfo)(nil), // 8: soong_build_metrics.ModuleTypeInfo
- (*CriticalUserJourneyMetrics)(nil), // 9: soong_build_metrics.CriticalUserJourneyMetrics
- (*CriticalUserJourneysMetrics)(nil), // 10: soong_build_metrics.CriticalUserJourneysMetrics
- (*SoongBuildMetrics)(nil), // 11: soong_build_metrics.SoongBuildMetrics
+ (ExpConfigFetcher_ConfigStatus)(0), // 3: soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ (*MetricsBase)(nil), // 4: soong_build_metrics.MetricsBase
+ (*BuildConfig)(nil), // 5: soong_build_metrics.BuildConfig
+ (*SystemResourceInfo)(nil), // 6: soong_build_metrics.SystemResourceInfo
+ (*PerfInfo)(nil), // 7: soong_build_metrics.PerfInfo
+ (*ProcessResourceInfo)(nil), // 8: soong_build_metrics.ProcessResourceInfo
+ (*ModuleTypeInfo)(nil), // 9: soong_build_metrics.ModuleTypeInfo
+ (*CriticalUserJourneyMetrics)(nil), // 10: soong_build_metrics.CriticalUserJourneyMetrics
+ (*CriticalUserJourneysMetrics)(nil), // 11: soong_build_metrics.CriticalUserJourneysMetrics
+ (*SoongBuildMetrics)(nil), // 12: soong_build_metrics.SoongBuildMetrics
+ (*ExpConfigFetcher)(nil), // 13: soong_build_metrics.ExpConfigFetcher
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
1, // 1: soong_build_metrics.MetricsBase.target_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 2: soong_build_metrics.MetricsBase.host_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 3: soong_build_metrics.MetricsBase.host_2nd_arch:type_name -> soong_build_metrics.MetricsBase.Arch
- 6, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
- 6, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
- 6, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
- 6, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
- 6, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
- 11, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
- 4, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
- 5, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
- 6, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
- 7, // 13: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
- 2, // 14: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
- 3, // 15: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
- 9, // 16: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
- 6, // 17: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
- 18, // [18:18] is the sub-list for method output_type
- 18, // [18:18] is the sub-list for method input_type
- 18, // [18:18] is the sub-list for extension type_name
- 18, // [18:18] is the sub-list for extension extendee
- 0, // [0:18] is the sub-list for field type_name
+ 7, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
+ 7, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
+ 7, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
+ 7, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
+ 7, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
+ 12, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
+ 5, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
+ 6, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
+ 7, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
+ 13, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
+ 8, // 14: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
+ 2, // 15: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
+ 4, // 16: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
+ 10, // 17: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
+ 7, // 18: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
+ 3, // 19: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ 20, // [20:20] is the sub-list for method output_type
+ 20, // [20:20] is the sub-list for method input_type
+ 20, // [20:20] is the sub-list for extension type_name
+ 20, // [20:20] is the sub-list for extension extendee
+ 0, // [0:20] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -1538,14 +1697,26 @@
return nil
}
}
+ file_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ExpConfigFetcher); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
- NumEnums: 3,
- NumMessages: 9,
+ NumEnums: 4,
+ NumMessages: 10,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 26e4d73..814eb67 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -108,6 +108,9 @@
// The metrics for calling Bazel.
repeated PerfInfo bazel_runs = 27;
+
+ // The metrics of the experiment config fetcher
+ optional ExpConfigFetcher exp_config_fetcher = 28;
}
message BuildConfig {
@@ -239,3 +242,22 @@
// Runtime metrics for soong_build execution.
repeated PerfInfo events = 6;
}
+
+message ExpConfigFetcher {
+ enum ConfigStatus {
+ NO_CONFIG = 0;
+ CONFIG = 1;
+ ERROR = 2;
+ }
+ // The result of the call to expconfigfetcher
+ // NO_CONFIG - Not part of experiment
+ // CONFIG - Part of experiment, config copied successfully
+ // ERROR - expconfigfetcher failed
+ optional ConfigStatus status = 1;
+
+ // The output config filename
+ optional string filename = 2;
+
+ // Time, in microseconds, taken by the expconfigfetcher
+ optional uint64 micros = 3;
+}