Merge "Revert "Disable stripping for riscv64""
diff --git a/.gitignore b/.gitignore
index 45884c4..5d2bc0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
/.idea
*.iml
+*.ipr
+*.iws
+
diff --git a/README.md b/README.md
index 87d6948..18cf7b2 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,33 @@
# Soong
-Soong is the replacement for the old Android make-based build system. It
-replaces Android.mk files with Android.bp files, which are JSON-like simple
-declarative descriptions of modules to build.
+Soong is one of the build systems used in Android. There are altogether three:
+* The legacy Make-based build system that is controlled by files called
+ `Android.mk`.
+* Soong, which is controlled by files called `Android.bp`.
+* The upcoming Bazel-based build system that is controlled by files called
+ `BUILD.bazel`.
+
+`Android.bp` file are JSON-like declarative descriptions of "modules" to build;
+a "module" is the basic unit of building that Soong understands, similarly to
+how "target" is the basic unit of building for Bazel (and Make, although the
+two kinds of "targets" are very different)
See [Simple Build
Configuration](https://source.android.com/compatibility/tests/development/blueprints)
on source.android.com to read how Soong is configured for testing.
+### Contributing
+
+Code reviews are handled through the usual code review system of Android,
+available [here](https://android-review.googlesource.com/dashboard/self).
+
+For simple changes (fixing typos, obvious optimizations, etc.), sending a code
+review request is enough. For more substantial changes, file a bug in our
+[bug tracker](https://issuetracker.google.com/issues/new?component=381517) or
+or write us at android-building@googlegroups.com .
+
+For Googlers, see our [internal documentation](http://go/soong).
+
## Android.bp file format
By design, Android.bp files are very simple. There are no conditionals or
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index b09b923..16f144e 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -33,6 +33,10 @@
// all modules in this package (not recursively) default to bp2build_available: false.
// allows modules to opt-in.
Bp2BuildDefaultFalse
+
+ // all modules in this package and subpackages default to bp2build_available: false.
+ // allows modules to opt-in.
+ Bp2BuildDefaultFalseRecursively
)
var (
@@ -45,6 +49,7 @@
"art/runtime": Bp2BuildDefaultTrueRecursively,
"art/tools": Bp2BuildDefaultTrue,
"bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/applypatch": Bp2BuildDefaultTrue,
"bootable/recovery/minadbd": Bp2BuildDefaultTrue,
"bootable/recovery/minui": Bp2BuildDefaultTrue,
"bootable/recovery/recovery_utils": Bp2BuildDefaultTrue,
@@ -52,6 +57,7 @@
"build/bazel": Bp2BuildDefaultTrueRecursively,
"build/make/target/product/security": Bp2BuildDefaultTrue,
+ "build/make/tools/releasetools": Bp2BuildDefaultTrue,
"build/make/tools/signapk": Bp2BuildDefaultTrue,
"build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively,
"build/soong": Bp2BuildDefaultTrue,
@@ -63,6 +69,9 @@
"build/soong/scripts": Bp2BuildDefaultTrueRecursively,
"cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+
+ "dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively,
+
"development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
"development/apps/Fallback": Bp2BuildDefaultTrue,
"development/apps/WidgetPreview": Bp2BuildDefaultTrue,
@@ -102,13 +111,15 @@
"external/aac": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
- "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto": Bp2BuildDefaultTrue,
+ "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto/common": Bp2BuildDefaultTrueRecursively,
"external/auto/service": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
+ "external/bsdiff": Bp2BuildDefaultTrueRecursively,
+ "external/bzip2": Bp2BuildDefaultTrueRecursively,
"external/conscrypt": Bp2BuildDefaultTrue,
"external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
"external/eigen": Bp2BuildDefaultTrueRecursively,
@@ -138,6 +149,7 @@
"external/libcap": Bp2BuildDefaultTrueRecursively,
"external/libcxx": Bp2BuildDefaultTrueRecursively,
"external/libcxxabi": Bp2BuildDefaultTrueRecursively,
+ "external/libdivsufsort": Bp2BuildDefaultTrueRecursively,
"external/libdrm": Bp2BuildDefaultTrue,
"external/libevent": Bp2BuildDefaultTrueRecursively,
"external/libgav1": Bp2BuildDefaultTrueRecursively,
@@ -148,6 +160,7 @@
"external/libvpx": Bp2BuildDefaultTrueRecursively,
"external/libyuv": Bp2BuildDefaultTrueRecursively,
"external/lz4/lib": Bp2BuildDefaultTrue,
+ "external/lz4/programs": Bp2BuildDefaultTrue,
"external/lzma/C": Bp2BuildDefaultTrueRecursively,
"external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
"external/minijail": Bp2BuildDefaultTrueRecursively,
@@ -166,18 +179,19 @@
"external/zopfli": Bp2BuildDefaultTrueRecursively,
"external/zstd": Bp2BuildDefaultTrueRecursively,
- "frameworks/av": Bp2BuildDefaultTrue,
- "frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av": Bp2BuildDefaultTrue,
"frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
"frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
"frameworks/base/tools/aapt2": Bp2BuildDefaultTrue,
+ "frameworks/base/tools/streaming_proto": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/gui": Bp2BuildDefaultTrue,
@@ -190,17 +204,17 @@
"frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
"frameworks/native/services/batteryservice": Bp2BuildDefaultTrue,
- "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
+ "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
"hardware/interfaces": Bp2BuildDefaultTrue,
"hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue,
@@ -238,6 +252,7 @@
"packages/apps/Protips": Bp2BuildDefaultTrue,
"packages/apps/SafetyRegulatoryInfo": Bp2BuildDefaultTrue,
"packages/apps/WallpaperPicker": Bp2BuildDefaultTrue,
+ "packages/modules/NeuralNetworks/driver/cache": Bp2BuildDefaultTrueRecursively,
"packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb": Bp2BuildDefaultTrue,
"packages/modules/adb/apex": Bp2BuildDefaultTrue,
@@ -248,7 +263,6 @@
"packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
"packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultFalse, // TODO(b/242834374)
- "packages/modules/NeuralNetworks/driver/cache": Bp2BuildDefaultTrueRecursively,
"packages/screensavers/Basic": Bp2BuildDefaultTrue,
"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321)
@@ -261,6 +275,9 @@
"prebuilts/tools": Bp2BuildDefaultTrue,
"prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
+ "sdk/dumpeventlog": Bp2BuildDefaultTrue,
+ "sdk/eventanalyzer": Bp2BuildDefaultTrue,
+
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
"system/apex/apexer": Bp2BuildDefaultTrue,
"system/apex/libs": Bp2BuildDefaultTrueRecursively,
@@ -282,6 +299,7 @@
"system/core/libsysutils": Bp2BuildDefaultTrueRecursively,
"system/core/libutils": Bp2BuildDefaultTrueRecursively,
"system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
+ "system/core/mkbootfs": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
"system/extras/toolchain-extras": Bp2BuildDefaultTrue,
@@ -315,11 +333,10 @@
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
"system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue,
+ "system/tools/mkbootimg": Bp2BuildDefaultTrueRecursively,
"system/tools/sysprop": Bp2BuildDefaultTrue,
"system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
- "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
-
"tools/apksig": Bp2BuildDefaultTrue,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
@@ -387,8 +404,10 @@
"com.android.neuralnetworks.certificate",
"com.android.neuralnetworks.key",
"flatbuffer_headers",
+ "framework-connectivity-protos",
"gemmlowp_headers",
"gl_headers",
+ "ipconnectivity-proto-src",
"libaidlcommonsupport",
"libandroid_runtime_lazy",
"libandroid_runtime_vm_headers",
@@ -464,6 +483,7 @@
"philox_random",
"philox_random_headers",
"server_configurable_flags",
+ "service-permission-streaming-proto-sources",
"statslog_neuralnetworks.cpp",
"statslog_neuralnetworks.h",
"tensorflow_headers",
@@ -472,8 +492,10 @@
"libstagefright_bufferpool@2.0.1",
"libSurfaceFlingerProp",
+ // prebuilts
+ "prebuilt_stats-log-api-gen",
+
// fastboot
- "bootimg_headers",
"fastboot",
"libfastboot",
"liblp",
@@ -506,6 +528,7 @@
//system/extras/verity/fec
"fec",
+ "boot_signer",
//packages/apps/Car/libs/car-ui-lib/car-ui-androidx
// genrule dependencies for java_imports
@@ -589,8 +612,6 @@
"libEGL_getProcAddress",
"libEGL_blobCache",
- "protoc-gen-cppstream",
-
"mediaswcodec",
"libmedia_headers",
"libmedia_codecserviceregistrant",
@@ -1244,6 +1265,33 @@
"launcherprotosnano",
"datastallprotosnano",
"devicepolicyprotosnano",
+ "ota_metadata_proto_java",
+ "merge_ota",
+
+ // releasetools
+ "releasetools_fsverity_metadata_generator",
+ "verity_utils",
+ "check_ota_package_signature",
+ "check_target_files_vintf",
+ "releasetools_check_target_files_vintf",
+ "releasetools_verity_utils",
+ "build_image",
+ "ota_from_target_files",
+ "releasetools_ota_from_target_files",
+ "releasetools_build_image",
+ "add_img_to_target_files",
+ "releasetools_add_img_to_target_files",
+ "fsverity_metadata_generator",
+ "sign_target_files_apks",
+
+ // depends on the support of yacc file
+ "libapplypatch",
+ "libapplypatch_modes",
+ "applypatch",
+
+ // TODO(b/254476335): disable the following due to this bug
+ "libapexinfo",
+ "libapexinfo_tests",
}
Bp2buildCcLibraryStaticOnlyList = []string{}
@@ -1292,23 +1340,14 @@
"prebuilt_platform-robolectric-4.4-prebuilt",
"prebuilt_platform-robolectric-4.5.1-prebuilt",
"prebuilt_currysrc_org.eclipse",
-
- // TODO(b/247782695 and/or b/242847534) Fix mixed build between unconverted gensrcs and converted filegroup
- "libstats_atom_enum_protos",
- "data_stall_event_proto",
- "device_policy_proto",
- "dns_resolver_proto",
- "launcher_proto",
- "network_stack_proto",
- "srcs_bluetooth_protos",
- "srcs_bluetooth_leaudio_protos",
- "style_proto",
- "tethering_proto",
- "text_classifier_proto",
- "libstats_atom_message_protos",
}
- ProdMixedBuildsEnabledList = []string{
- "com.android.adbd",
- }
+ // Bazel prod-mode allowlist. Modules in this list are built by Bazel
+ // in either prod mode or staging mode.
+ ProdMixedBuildsEnabledList = []string{}
+
+ // Staging-mode allowlist. Modules in this list are only built
+ // by Bazel with --bazel-mode-staging. This list should contain modules
+ // which will soon be added to the prod allowlist.
+ StagingMixedBuildsEnabledList = []string{"com.android.tzdata"}
)
diff --git a/android/api_domain.go b/android/api_domain.go
index 7876654..3265148 100644
--- a/android/api_domain.go
+++ b/android/api_domain.go
@@ -70,13 +70,11 @@
return m
}
+// Do not create any dependency edges in Soong for now to skip visibility checks for some systemapi libraries.
+// Currently, all api_domain modules reside in build/orchestrator/apis/Android.bp
+// However, cc libraries like libsigchain (com.android.art) restrict their visibility to art/*
+// When the api_domain module types are collocated with their contributions, this dependency edge can be restored
func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) {
- for _, cc := range a.properties.Cc_api_contributions {
- // Use FarVariationDependencies since the variants of api_domain is a subset of the variants of the dependency cc module
- // Creating a dependency on the first variant is ok since this is a no-op in Soong
- // The primary function of this dependency is to create a connected graph in the corresponding bp2build workspace
- ctx.AddFarVariationDependencies([]blueprint.Variation{}, nil, cc)
- }
}
// API domain does not have any builld actions yet
diff --git a/android/arch.go b/android/arch.go
index 75ee922..086e945 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1687,14 +1687,12 @@
abi []string
}
-// getNdkAbisConfig returns the list of archConfigs that are used for bulding
-// the API stubs and static libraries that are included in the NDK. These are
-// built *without Neon*, because non-Neon is still supported and building these
-// with Neon will break those users.
+// getNdkAbisConfig returns the list of archConfigs that are used for building
+// the API stubs and static libraries that are included in the NDK.
func getNdkAbisConfig() []archConfig {
return []archConfig{
{"arm64", "armv8-a-branchprot", "", []string{"arm64-v8a"}},
- {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
{"x86_64", "", "", []string{"x86_64"}},
{"x86", "", "", []string{"x86"}},
}
diff --git a/android/bazel.go b/android/bazel.go
index 7b227bd..d30cb80 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -489,21 +489,27 @@
// Check if the package path has an exact match in the config.
if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
return true, packagePath
- } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse {
+ } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively {
return false, packagePath
}
// If not, check for the config recursively.
- packagePrefix := ""
- // 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] == allowlists.Bp2BuildDefaultTrueRecursively {
+ packagePrefix := packagePath
+
+ // e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist.
+ for strings.Contains(packagePrefix, "/") {
+ dirIndex := strings.LastIndex(packagePrefix, "/")
+ packagePrefix = packagePrefix[:dirIndex]
+ switch value := config[packagePrefix]; value {
+ case allowlists.Bp2BuildDefaultTrueRecursively:
// package contains this prefix and this prefix should convert all modules
return true, packagePrefix
+ case allowlists.Bp2BuildDefaultFalseRecursively:
+ //package contains this prefix and this prefix should NOT convert any modules
+ return false, packagePrefix
}
// Continue to the next part of the package dir.
- packagePrefix += "/"
+
}
return false, packagePath
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index e81086d..eec78d2 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -142,7 +142,10 @@
GetPythonBinary(label string, cfgKey configKey) (string, error)
// Returns the results of the GetApexInfo query (including output files)
- GetApexInfo(label string, cfgkey configKey) (cquery.ApexCqueryInfo, error)
+ GetApexInfo(label string, cfgkey configKey) (cquery.ApexInfo, error)
+
+ // Returns the results of the GetCcUnstrippedInfo query
+ GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
// ** end Cquery Results Retrieval Functions
@@ -172,12 +175,13 @@
}
type bazelPaths struct {
- homeDir string
- bazelPath string
- outputBase string
- workspaceDir string
- soongOutDir string
- metricsDir string
+ homeDir string
+ bazelPath string
+ outputBase string
+ workspaceDir string
+ soongOutDir string
+ metricsDir string
+ bazelDepsFile string
}
// A context object which tracks queued requests that need to be made to Bazel,
@@ -222,7 +226,8 @@
LabelToOutputFiles map[string][]string
LabelToCcInfo map[string]cquery.CcInfo
LabelToPythonBinary map[string]string
- LabelToApexInfo map[string]cquery.ApexCqueryInfo
+ LabelToApexInfo map[string]cquery.ApexInfo
+ LabelToCcBinary map[string]cquery.CcUnstrippedInfo
}
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
@@ -244,8 +249,14 @@
return result, nil
}
-func (n MockBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryInfo, error) {
- panic("unimplemented")
+func (m MockBazelContext) GetApexInfo(label string, _ configKey) (cquery.ApexInfo, error) {
+ result, _ := m.LabelToApexInfo[label]
+ return result, nil
+}
+
+func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ result, _ := m.LabelToCcBinary[label]
+ return result, nil
}
func (m MockBazelContext) InvokeBazel(_ Config) error {
@@ -303,12 +314,20 @@
return "", fmt.Errorf("no bazel response found for %v", key)
}
-func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexCqueryInfo, error) {
+func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexInfo, error) {
key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString)), nil
+ return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString))
}
- return cquery.ApexCqueryInfo{}, fmt.Errorf("no bazel response found for %v", key)
+ return cquery.ApexInfo{}, fmt.Errorf("no bazel response found for %v", key)
+}
+
+func (bazelCtx *bazelContext) GetCcUnstrippedInfo(label string, cfgKey configKey) (cquery.CcUnstrippedInfo, error) {
+ key := makeCqueryKey(label, cquery.GetCcUnstrippedInfo, cfgKey)
+ if rawString, ok := bazelCtx.results[key]; ok {
+ return cquery.GetCcUnstrippedInfo.ParseResult(strings.TrimSpace(rawString))
+ }
+ return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
}
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
@@ -327,10 +346,15 @@
panic("unimplemented")
}
-func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryInfo, error) {
+func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
panic("unimplemented")
}
+func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func (n noopBazelContext) InvokeBazel(_ Config) error {
panic("unimplemented")
}
@@ -363,6 +387,15 @@
for _, enabledProdModule := range allowlists.ProdMixedBuildsEnabledList {
enabledModules[enabledProdModule] = true
}
+ case BazelStagingMode:
+ modulesDefaultToBazel = false
+ // Staging mode includes all prod modules plus all staging modules.
+ for _, enabledProdModule := range allowlists.ProdMixedBuildsEnabledList {
+ enabledModules[enabledProdModule] = true
+ }
+ for _, enabledStagingMode := range allowlists.StagingMixedBuildsEnabledList {
+ enabledModules[enabledStagingMode] = true
+ }
case BazelDevMode:
modulesDefaultToBazel = true
@@ -424,6 +457,11 @@
} else {
missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
}
+ if len(c.Getenv("BAZEL_DEPS_FILE")) > 1 {
+ p.bazelDepsFile = c.Getenv("BAZEL_DEPS_FILE")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_DEPS_FILE")
+ }
if len(missingEnvVars) > 0 {
return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
} else {
@@ -523,9 +561,7 @@
//
// The actual platform values here may be overridden by configuration
// transitions from the buildroot.
- fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_target"),
fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"),
-
// This should be parameterized on the host OS, but let's restrict to linux
// to keep things simple for now.
fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"),
@@ -535,7 +571,9 @@
// Suppress noise
"--ui_event_filters=-INFO",
- "--noshow_progress"}
+ "--noshow_progress",
+ "--norun_validations",
+ }
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
@@ -544,7 +582,7 @@
"HOME=" + paths.homeDir,
pwdPrefix(),
"BUILD_DIR=" + absolutePath(paths.soongOutDir),
- // Make OUT_DIR absolute here so tools/bazel.sh uses the correct
+ // Make OUT_DIR absolute here so build/bazel/bin/bazel uses the correct
// OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
"OUT_DIR=" + absolutePath(paths.outDir()),
// Disables local host detection of gcc; toolchain information is defined
@@ -894,7 +932,7 @@
//
// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
// proto sources, which would add a number of unnecessary dependencies.
- extraFlags := []string{"--output=jsonproto", "--include_file_write_contents"}
+ extraFlags := []string{"--output=proto", "--include_file_write_contents"}
if Bool(config.productVariables.ClangCoverage) {
extraFlags = append(extraFlags, "--collect_code_coverage")
paths := make([]string, 0, 2)
@@ -1050,7 +1088,7 @@
// Remove old outputs, as some actions might not rerun if the outputs are detected.
if len(buildStatement.OutputPaths) > 0 {
- cmd.Text("rm -f")
+ cmd.Text("rm -rf") // -r because outputs can be Bazel dir/tree artifacts.
for _, outputPath := range buildStatement.OutputPaths {
cmd.Text(fmt.Sprintf("'%s'", outputPath))
}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index dc2261c..6e3acd5 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -1,6 +1,7 @@
package android
import (
+ "encoding/json"
"os"
"path/filepath"
"reflect"
@@ -8,6 +9,9 @@
"testing"
"android/soong/bazel/cquery"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+ "google.golang.org/protobuf/proto"
)
var testConfig = TestConfig("out", nil, "", nil)
@@ -65,52 +69,56 @@
var testCases = []testCase{
{`
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_Id": 1,
+ "action_Key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_Ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`,
- "cd 'test/exec_root' && rm -f 'one' && touch foo",
+ "cd 'test/exec_root' && rm -rf 'one' && touch foo",
}, {`
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 10 },
- { "id": 2, "pathFragmentId": 20 }],
- "actions": [{
- "targetId": 100,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["bogus", "command"],
- "outputIds": [1, 2],
- "primaryOutputId": 1
- }],
- "pathFragments": [
- { "id": 10, "label": "one", "parentId": 30 },
- { "id": 20, "label": "one.d", "parentId": 30 },
- { "id": 30, "label": "parent" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 10 },
+ { "id": 2, "path_fragment_id": 20 }],
+ "actions": [{
+ "target_Id": 100,
+ "action_Key": "x",
+ "mnemonic": "x",
+ "arguments": ["bogus", "command"],
+ "output_Ids": [1, 2],
+ "primary_output_id": 1
+ }],
+ "path_fragments": [
+ { "id": 10, "label": "one", "parent_id": 30 },
+ { "id": 20, "label": "one.d", "parent_id": 30 },
+ { "id": 30, "label": "parent" }]
}`,
- `cd 'test/exec_root' && rm -f 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
+ `cd 'test/exec_root' && rm -rf 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
},
}
for i, testCase := range testCases {
+ data, err := JsonToActionGraphContainer(testCase.input)
+ if err != nil {
+ t.Error(err)
+ }
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: testCase.input})
+ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
- err := bazelContext.InvokeBazel(testConfig)
+ err = bazelContext.InvokeBazel(testConfig)
if err != nil {
t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
}
@@ -194,3 +202,14 @@
requests: map[cqueryKey]bool{},
}, p.soongOutDir
}
+
+// Transform the json format to ActionGraphContainer
+func JsonToActionGraphContainer(inputString string) ([]byte, error) {
+ var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
+ err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
+ if err != nil {
+ return []byte(""), err
+ }
+ data, _ := proto.Marshal(&aqueryProtoResult)
+ return data, err
+}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 9c50098..b2ea22f 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -534,3 +534,55 @@
}
return outs
}
+
+// BazelStringOrLabelFromProp splits a Soong module property that can be
+// either a string literal, path (with android:path tag) or a module reference
+// into separate bazel string or label attributes. Bazel treats string and label
+// attributes as distinct types, so this function categorizes a string property
+// into either one of them.
+//
+// e.g. apex.private_key = "foo.pem" can either refer to:
+//
+// 1. "foo.pem" in the current directory -> file target
+// 2. "foo.pem" module -> rule target
+// 3. "foo.pem" file in a different directory, prefixed by a product variable handled
+// in a bazel macro. -> string literal
+//
+// For the first two cases, they are defined using the label attribute. For the third case,
+// it's defined with the string attribute.
+func BazelStringOrLabelFromProp(
+ ctx TopDownMutatorContext,
+ propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) {
+
+ var labelAttr bazel.LabelAttribute
+ var strAttr bazel.StringAttribute
+
+ if propToDistinguish == nil {
+ // nil pointer
+ return labelAttr, strAttr
+ }
+
+ prop := String(propToDistinguish)
+ if SrcIsModule(prop) != "" {
+ // If it's a module (SrcIsModule will return the module name), set the
+ // resolved label to the label attribute.
+ labelAttr.SetValue(BazelLabelForModuleDepSingle(ctx, prop))
+ } else {
+ // Not a module name. This could be a string literal or a file target in
+ // the current dir. Check if the path exists:
+ path := ExistentPathForSource(ctx, ctx.ModuleDir(), prop)
+
+ if path.Valid() && parentDir(path.String()) == ctx.ModuleDir() {
+ // If it exists and the path is relative to the current dir, resolve the bazel label
+ // for the _file target_ and set it to the label attribute.
+ //
+ // Resolution is necessary because this could be a file in a subpackage.
+ labelAttr.SetValue(BazelLabelForModuleSrcSingle(ctx, prop))
+ } else {
+ // Otherwise, treat it as a string literal and assign to the string attribute.
+ strAttr.Value = propToDistinguish
+ }
+ }
+
+ return labelAttr, strAttr
+}
diff --git a/android/bazel_test.go b/android/bazel_test.go
index dbe6067..7b38b6a 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -71,6 +71,20 @@
},
packageDir: "a",
},
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrue,
+ },
+ packageDir: "a/b",
+ },
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ packageDir: "a/b/c",
+ },
}
for _, test := range testCases {
@@ -133,6 +147,20 @@
},
packageDir: "a",
},
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrue,
+ },
+ packageDir: "a/b/c",
+ },
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b": allowlists.Bp2BuildDefaultFalseRecursively,
+ },
+ packageDir: "a/b/c",
+ },
}
for _, test := range testCases {
@@ -395,3 +423,21 @@
}
}
}
+
+func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
+ allowlist := NewBp2BuildAllowlist()
+ // entry "a/b2/c2" is moot because of its parent "a/b2"
+ allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
+ truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
+ falsities := []string{"a1", "a/b", "a/b1/c"}
+ for _, dir := range truths {
+ if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected TRUE but was FALSE", dir)
+ }
+ }
+ for _, dir := range falsities {
+ if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected FALSE but was TRUE", dir)
+ }
+ }
+}
diff --git a/android/config.go b/android/config.go
index 4992882..1deb7d4 100644
--- a/android/config.go
+++ b/android/config.go
@@ -75,6 +75,9 @@
// Don't use bazel at all during module analysis.
AnalysisNoBazel SoongBuildMode = iota
+ // Symlink fores mode: merge two directory trees into a symlink forest
+ SymlinkForest
+
// Bp2build mode: Generate BUILD files from blueprint files and exit.
Bp2build
@@ -97,6 +100,11 @@
// allowlisted on an experimental basis.
BazelDevMode
+ // Use bazel during analysis of a few allowlisted build modules. The allowlist
+ // is considered "staging, as these are modules being prepared to be released
+ // into prod mode shortly after.
+ BazelStagingMode
+
// Use bazel during analysis of build modules from an allowlist carefully
// curated by the build team to be proven stable.
BazelProdMode
@@ -528,7 +536,7 @@
// Returns true if "Bazel builds" is enabled. In this mode, part of build
// analysis is handled by Bazel.
func (c *config) IsMixedBuildsEnabled() bool {
- return c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode
+ return c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode || c.BuildMode == BazelStagingMode
}
func (c *config) SetAllowMissingDependencies() {
@@ -1101,7 +1109,7 @@
return c.config.productVariables.WithDexpreopt
}
-func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
+func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool {
return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid()
}
@@ -1264,10 +1272,6 @@
return coverage
}
-func (c *deviceConfig) AfdoAdditionalProfileDirs() []string {
- return c.config.productVariables.AfdoAdditionalProfileDirs
-}
-
func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
return c.config.productVariables.PgoAdditionalProfileDirs
}
diff --git a/android/config_bp2build.go b/android/config_bp2build.go
index d6b2bcf..2beeb51 100644
--- a/android/config_bp2build.go
+++ b/android/config_bp2build.go
@@ -69,6 +69,7 @@
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)...)
+ ret = append(ret, ev.exportedConfigDependingVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
return ret
}
@@ -141,6 +142,33 @@
m[k] = v
}
+func (m ExportedConfigDependingVariables) asBazel(config Config,
+ stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for variable, unevaluatedVar := range m {
+ evalFunc := reflect.ValueOf(unevaluatedVar)
+ validateVariableMethod(variable, evalFunc)
+ evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
+ evaluatedValue := evaluatedResult[0].Interface().(string)
+ expandedVars, err := expandVar(config, evaluatedValue, stringVars, stringListVars, cfgDepVars)
+ if err != nil {
+ panic(fmt.Errorf("error expanding config variable %s: %s", variable, err))
+ }
+ if len(expandedVars) > 1 {
+ ret = append(ret, bazelConstant{
+ variableName: variable,
+ internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
+ })
+ } else {
+ ret = append(ret, bazelConstant{
+ variableName: variable,
+ internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVars[0])),
+ })
+ }
+ }
+ return ret
+}
+
// 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`, `"`, `\`} {
diff --git a/android/filegroup.go b/android/filegroup.go
index 6b11172..af4d89a 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -234,7 +234,8 @@
}
func (fg *fileGroup) IsMixedBuildSupported(ctx BaseModuleContext) bool {
- return true
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ return false
}
func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) {
diff --git a/android/filegroup_test.go b/android/filegroup_test.go
index a7ea805..8292d5e 100644
--- a/android/filegroup_test.go
+++ b/android/filegroup_test.go
@@ -6,6 +6,8 @@
)
func TestFileGroupWithPathProp(t *testing.T) {
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ t.Skip("Re-enable once filegroups are corrected for mixed builds")
outBaseDir := "outputbase"
pathPrefix := outBaseDir + "/execroot/__main__"
expectedOutputfile := filepath.Join(pathPrefix, "a/b/c/d/test.aidl")
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 4ee5bf7..18b63d3 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -98,6 +98,11 @@
var orderOnlyDeps Paths
var args []string
+ if n := ctx.ModuleName(); n != "" {
+ args = append(args,
+ "-mn "+proptools.NinjaAndShellEscape(n))
+ }
+
if t := ctx.ModuleType(); t != "" {
args = append(args,
"-mt "+proptools.NinjaAndShellEscape(t))
diff --git a/android/licenses.go b/android/licenses.go
index c47b3e6..c6b3243 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -340,4 +340,5 @@
ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
+ ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
}
diff --git a/android/makevars.go b/android/makevars.go
index 5165a55..0800190 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -471,7 +471,7 @@
fmt.Fprintf(buf, " %s", dep.String())
}
fmt.Fprintln(buf)
- fmt.Fprintln(buf, "\t@echo \"Install $@\"")
+ fmt.Fprintln(buf, "\t@echo \"Install: $@\"")
fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@\n", preserveSymlinksFlag)
if install.executable {
fmt.Fprintf(buf, "\tchmod +x $@\n")
@@ -515,7 +515,7 @@
fromStr = symlink.absFrom
}
- fmt.Fprintln(buf, "\t@echo \"Symlink $@\"")
+ fmt.Fprintln(buf, "\t@echo \"Symlink: $@\"")
fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
fmt.Fprintln(buf)
fmt.Fprintln(buf)
diff --git a/android/metrics.go b/android/metrics.go
index ecda026..3d41a1d 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -62,7 +62,7 @@
})
}
-func collectMetrics(config Config, eventHandler metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
+func collectMetrics(config Config, eventHandler *metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
metrics := &soong_metrics_proto.SoongBuildMetrics{}
soongMetrics, ok := readSoongMetrics(config)
@@ -107,7 +107,7 @@
return metrics
}
-func WriteMetrics(config Config, eventHandler metrics.EventHandler, metricsFile string) error {
+func WriteMetrics(config Config, eventHandler *metrics.EventHandler, metricsFile string) error {
metrics := collectMetrics(config, eventHandler)
buf, err := proto.Marshal(metrics)
diff --git a/android/module.go b/android/module.go
index 68d9f8e..b41a898 100644
--- a/android/module.go
+++ b/android/module.go
@@ -915,12 +915,21 @@
type CommonAttributes struct {
// Soong nameProperties -> Bazel name
Name string
+
// Data mapped from: Required
Data bazel.LabelListAttribute
+ // SkipData is neither a Soong nor Bazel target attribute
+ // If true, this will not fill the data attribute automatically
+ // This is useful for Soong modules that have 1:many Bazel targets
+ // Some of the generated Bazel targets might not have a data attribute
+ SkipData *bool
+
Tags bazel.StringListAttribute
Applicable_licenses bazel.LabelListAttribute
+
+ Testonly *bool
}
// constraintAttributes represents Bazel attributes pertaining to build constraints,
@@ -1239,12 +1248,14 @@
// when generated as the 'data' label list attribute in Bazel. Remove it if
// it exists. See b/247985196.
_, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), mod.commonProperties.Required)
+ requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
required := depsToLabelList(requiredWithoutCycles)
archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
for axis, configToProps := range archVariantProps {
for config, _props := range configToProps {
if archProps, ok := _props.(*commonProperties); ok {
_, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), archProps.Required)
+ requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
if !neitherHostNorDevice {
if archProps.Enabled != nil {
@@ -1305,7 +1316,12 @@
platformEnabledAttribute.Add(&l)
}
- attrs.Data.Append(required)
+ if !proptools.Bool(attrs.SkipData) {
+ attrs.Data.Append(required)
+ }
+ // SkipData is not an attribute of any Bazel target
+ // Set this to nil so that it does not appear in the generated build file
+ attrs.SkipData = nil
moduleEnableConstraints := bazel.LabelListAttribute{}
moduleEnableConstraints.Append(platformEnabledAttribute)
diff --git a/android/neverallow.go b/android/neverallow.go
index 2745238..d288439 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -58,7 +58,7 @@
AddNeverAllowRules(createMakefileGoalRules()...)
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
- AddNeverAllowRules(createBp2BuildRules()...)
+ AddNeverAllowRules(createBp2BuildRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -66,22 +66,12 @@
neverallows = append(neverallows, rules...)
}
-func createBp2BuildRules() []Rule {
- rules := []Rule{}
- bp2buildAvailableAllowedDirs := []string{
- // Can we just allowlist these modules in allowlists.go?
- "bionic/libc",
- }
-
- for _, dir := range bp2buildAvailableAllowedDirs {
- rule := NeverAllow().
- With("bazel_module.bp2build_available", "true").
- NotIn(dir).
- Because("disallowed usages of bp2build_available for custom conversion")
- rules = append(rules, rule)
- }
-
- return rules
+func createBp2BuildRule() Rule {
+ return NeverAllow().
+ With("bazel_module.bp2build_available", "true").
+ NotIn("soong_tests"). // only used in tests
+ Because("setting bp2build_available in Android.bp is not " +
+ "supported for custom conversion, use allowlists.go instead.")
}
func createIncludeDirsRules() []Rule {
@@ -173,6 +163,7 @@
"development/build",
"external/guava",
"external/robolectric-shadows",
+ "external/robolectric",
"frameworks/layoutlib",
}
diff --git a/android/ninja_deps_test.go b/android/ninja_deps_test.go
index 947c257..d6afcc0 100644
--- a/android/ninja_deps_test.go
+++ b/android/ninja_deps_test.go
@@ -18,21 +18,6 @@
"testing"
)
-func init() {
- // This variable uses ExistentPathForSource on a PackageVarContext, which is a PathContext
- // that is not a PathGlobContext. That requires the deps to be stored in the Config.
- pctx.VariableFunc("test_ninja_deps_variable", func(ctx PackageVarContext) string {
- // Using ExistentPathForSource to look for a file that does not exist in a directory that
- // does exist (test_ninja_deps) from a PackageVarContext adds a dependency from build.ninja
- // to the directory.
- if ExistentPathForSource(ctx, "test_ninja_deps/does_not_exist").Valid() {
- return "true"
- } else {
- return "false"
- }
- })
-}
-
func testNinjaDepsSingletonFactory() Singleton {
return testNinjaDepsSingleton{}
}
@@ -40,33 +25,19 @@
type testNinjaDepsSingleton struct{}
func (testNinjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
- // Reference the test_ninja_deps_variable in a build statement so Blueprint is forced to
- // evaluate it.
- ctx.Build(pctx, BuildParams{
- Rule: Cp,
- Input: PathForTesting("foo"),
- Output: PathForOutput(ctx, "test_ninja_deps_out"),
- Args: map[string]string{
- "cpFlags": "${test_ninja_deps_variable}",
- },
- })
+ ctx.Config().addNinjaFileDeps("foo")
}
func TestNinjaDeps(t *testing.T) {
- fs := MockFS{
- "test_ninja_deps/exists": nil,
- }
-
result := GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
}),
- fs.AddToFixture(),
).RunTest(t)
// Verify that the ninja file has a dependency on the test_ninja_deps directory.
- if g, w := result.NinjaDeps, "test_ninja_deps"; !InList(w, g) {
+ if g, w := result.NinjaDeps, "foo"; !InList(w, g) {
t.Errorf("expected %q in %q", w, g)
}
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index f354db8..c348c82 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -48,7 +48,7 @@
var _ PathContext = &configErrorWrapper{}
var _ errorfContext = &configErrorWrapper{}
-var _ PackageVarContext = &configErrorWrapper{}
+var _ PackageVarContext = &variableFuncContextWrapper{}
var _ PackagePoolContext = &configErrorWrapper{}
var _ PackageRuleContext = &configErrorWrapper{}
@@ -62,21 +62,33 @@
e.config.addNinjaFileDeps(deps...)
}
-type PackageVarContext interface {
+type variableFuncContextWrapper struct {
+ configErrorWrapper
+ blueprint.VariableFuncContext
+}
+
+type PackagePoolContext interface {
PathContext
errorfContext
}
-type PackagePoolContext PackageVarContext
-type PackageRuleContext PackageVarContext
+type PackageRuleContext PackagePoolContext
+
+type PackageVarContext interface {
+ PackagePoolContext
+ PathGlobContext
+}
// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
// argument to a PackageVarContext.
func (p PackageContext) VariableFunc(name string,
f func(PackageVarContext) string) blueprint.Variable {
- return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
- ctx := &configErrorWrapper{p, config.(Config), nil}
+ return p.PackageContext.VariableFunc(name, func(bpctx blueprint.VariableFuncContext, config interface{}) (string, error) {
+ ctx := &variableFuncContextWrapper{
+ configErrorWrapper: configErrorWrapper{p, config.(Config), nil},
+ VariableFuncContext: bpctx,
+ }
ret := f(ctx)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
diff --git a/android/paths.go b/android/paths.go
index dbcdb23..a6a54fa 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -39,6 +39,7 @@
}
type PathGlobContext interface {
+ PathContext
GlobWithDeps(globPattern string, excludes []string) ([]string, error)
}
@@ -56,7 +57,6 @@
// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
// Path methods. These path methods can be called before any mutators have run.
type EarlyModulePathContext interface {
- PathContext
PathGlobContext
ModuleDir() string
@@ -375,7 +375,7 @@
// ExistentPathsForSources returns a list of Paths rooted from SrcDir, *not* rooted from the
// module's local source directory, that are found in the tree. If any are not found, they are
// omitted from the list, and dependencies are added so that we're re-run when they are added.
-func ExistentPathsForSources(ctx PathContext, paths []string) Paths {
+func ExistentPathsForSources(ctx PathGlobContext, paths []string) Paths {
ret := make(Paths, 0, len(paths))
for _, path := range paths {
p := ExistentPathForSource(ctx, path)
@@ -1087,21 +1087,12 @@
// existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
// path does not exist.
-func existsWithDependencies(ctx PathContext, path SourcePath) (exists bool, err error) {
+func existsWithDependencies(ctx PathGlobContext, path SourcePath) (exists bool, err error) {
var files []string
- if gctx, ok := ctx.(PathGlobContext); ok {
- // Use glob to produce proper dependencies, even though we only want
- // a single file.
- files, err = gctx.GlobWithDeps(path.String(), nil)
- } else {
- var result pathtools.GlobResult
- // We cannot add build statements in this context, so we fall back to
- // AddNinjaFileDeps
- result, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
- ctx.AddNinjaFileDeps(result.Deps...)
- files = result.Matches
- }
+ // Use glob to produce proper dependencies, even though we only want
+ // a single file.
+ files, err = ctx.GlobWithDeps(path.String(), nil)
if err != nil {
return false, fmt.Errorf("glob: %s", err.Error())
@@ -1124,7 +1115,7 @@
}
if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
- exists, err := existsWithDependencies(ctx, path)
+ exists, err := existsWithDependencies(modCtx, path)
if err != nil {
reportPathError(ctx, err)
}
@@ -1139,11 +1130,26 @@
return path
}
+// MaybeExistentPathForSource joins the provided path components and validates that the result
+// neither escapes the source dir nor is in the out dir.
+// It does not validate whether the path exists.
+func MaybeExistentPathForSource(ctx PathContext, pathComponents ...string) SourcePath {
+ path, err := pathForSource(ctx, pathComponents...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+
+ if pathtools.IsGlob(path.String()) {
+ ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
+ }
+ return path
+}
+
// ExistentPathForSource returns an OptionalPath with the SourcePath, rooted from SrcDir, *not*
// rooted from the module's local source directory, if the path exists, or an empty OptionalPath if
// it doesn't exist. Dependencies are added so that the ninja file will be regenerated if the state
// of the path changes.
-func ExistentPathForSource(ctx PathContext, pathComponents ...string) OptionalPath {
+func ExistentPathForSource(ctx PathGlobContext, pathComponents ...string) OptionalPath {
path, err := pathForSource(ctx, pathComponents...)
if err != nil {
reportPathError(ctx, err)
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 7d21b75..1519f60 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -642,9 +642,13 @@
// Extracts an interface from values containing the properties to apply based on config.
// If config does not match a value with a non-nil property set, the default value will be returned.
func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ configValue := config.String(s.variable)
+ if configValue != "" && !InList(configValue, s.values) {
+ return nil, fmt.Errorf("Soong config property %q must be one of %v, found %q", s.variable, s.values, configValue)
+ }
for j, v := range s.values {
f := values.Field(j)
- if config.String(s.variable) == v && !f.Elem().IsNil() {
+ if configValue == v && !f.Elem().IsNil() {
return f.Interface(), nil
}
}
@@ -861,3 +865,13 @@
}
var emptyInterfaceType = reflect.TypeOf(emptyInterfaceStruct{}).Field(0).Type
+
+// InList checks if the string belongs to the list
+func InList(s string, list []string) bool {
+ for _, s2 := range list {
+ if s2 == s {
+ return true
+ }
+ }
+ return false
+}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index a7800e8..d5d87ef 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -303,6 +303,10 @@
Bool_var interface{}
}
+type stringSoongConfigVars struct {
+ String_var interface{}
+}
+
func Test_PropertiesToApply(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -365,6 +369,51 @@
}
}
+func Test_PropertiesToApply_String_Error(t *testing.T) {
+ mt, _ := newModuleType(&ModuleTypeProperties{
+ Module_type: "foo",
+ Config_namespace: "bar",
+ Variables: []string{"string_var"},
+ Properties: []string{"a", "b"},
+ })
+ mt.Variables = append(mt.Variables, &stringVariable{
+ baseVariable: baseVariable{
+ variable: "string_var",
+ },
+ values: []string{"a", "b", "c"},
+ })
+ stringVarPositive := &properties{
+ A: proptools.StringPtr("A"),
+ B: true,
+ }
+ conditionsDefault := &properties{
+ A: proptools.StringPtr("default"),
+ B: false,
+ }
+ actualProps := &struct {
+ Soong_config_variables stringSoongConfigVars
+ }{
+ Soong_config_variables: stringSoongConfigVars{
+ String_var: &boolVarProps{
+ A: stringVarPositive.A,
+ B: stringVarPositive.B,
+ Conditions_default: conditionsDefault,
+ },
+ },
+ }
+ props := reflect.ValueOf(actualProps)
+
+ _, err := PropertiesToApply(mt, props, Config(map[string]string{
+ "string_var": "x",
+ }))
+ expected := `Soong config property "string_var" must be one of [a b c], found "x"`
+ if err == nil {
+ t.Fatalf("Expected an error, got nil")
+ } else if err.Error() != expected {
+ t.Fatalf("Error message was not correct, expected %q, got %q", expected, err.Error())
+ }
+}
+
func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
testCases := []struct {
desc string
diff --git a/android/testing.go b/android/testing.go
index f9f9670..2256c96 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -1120,6 +1120,7 @@
}
func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
+ t.Helper()
var p AndroidMkEntriesProvider
var ok bool
if p, ok = mod.(AndroidMkEntriesProvider); !ok {
@@ -1134,6 +1135,7 @@
}
func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
+ t.Helper()
var p AndroidMkDataProvider
var ok bool
if p, ok = mod.(AndroidMkDataProvider); !ok {
diff --git a/android/variable.go b/android/variable.go
index 37ecab5..28f22c9 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -336,8 +336,7 @@
NamespacesToExport []string `json:",omitempty"`
- AfdoAdditionalProfileDirs []string `json:",omitempty"`
- PgoAdditionalProfileDirs []string `json:",omitempty"`
+ PgoAdditionalProfileDirs []string `json:",omitempty"`
VndkUseCoreVariant *bool `json:",omitempty"`
VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 4247db4..72403f9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -17,13 +17,14 @@
package apex
import (
- "android/soong/bazel/cquery"
"fmt"
"path/filepath"
"regexp"
"sort"
"strings"
+ "android/soong/bazel/cquery"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
@@ -47,7 +48,7 @@
func registerApexBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_test", testApexBundleFactory)
+ ctx.RegisterModuleType("apex_test", TestApexBundleFactory)
ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
ctx.RegisterModuleType("apex_defaults", defaultsFactory)
ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
@@ -224,7 +225,7 @@
// List of JNI libraries that are embedded inside this APEX.
Jni_libs []string
- // List of rust dyn libraries
+ // List of rust dyn libraries that are embedded inside this APEX.
Rust_dyn_libs []string
// List of native executables that are embedded inside this APEX.
@@ -235,6 +236,41 @@
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
+
+ // List of native libraries to exclude from this APEX.
+ Exclude_native_shared_libs []string
+
+ // List of JNI libraries to exclude from this APEX.
+ Exclude_jni_libs []string
+
+ // List of rust dyn libraries to exclude from this APEX.
+ Exclude_rust_dyn_libs []string
+
+ // List of native executables to exclude from this APEX.
+ Exclude_binaries []string
+
+ // List of native tests to exclude from this APEX.
+ Exclude_tests []string
+
+ // List of filesystem images to exclude from this APEX bundle.
+ Exclude_filesystems []string
+}
+
+// Merge combines another ApexNativeDependencies into this one
+func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) {
+ a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
+ a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
+ a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
+ a.Binaries = append(a.Binaries, b.Binaries...)
+ a.Tests = append(a.Tests, b.Tests...)
+ a.Filesystems = append(a.Filesystems, b.Filesystems...)
+
+ a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
+ a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
+ a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...)
+ a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
+ a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
+ a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
}
type apexMultilibProperties struct {
@@ -674,12 +710,18 @@
// Use *FarVariation* to be able to depend on modules having conflicting variations with
// this module. This is required since arch variant of an APEX bundle is 'common' but it is
// 'arm' or 'arm64' for native shared libs.
- ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...)
- ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
- ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
- ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
- ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, nativeModules.Rust_dyn_libs...)
- ctx.AddFarVariationDependencies(target.Variations(), fsTag, nativeModules.Filesystems...)
+ ctx.AddFarVariationDependencies(binVariations, executableTag,
+ android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
+ ctx.AddFarVariationDependencies(binVariations, testTag,
+ android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
+ ctx.AddFarVariationDependencies(libVariations, jniLibTag,
+ android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...)
+ ctx.AddFarVariationDependencies(libVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...)
+ ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
+ ctx.AddFarVariationDependencies(target.Variations(), fsTag,
+ android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -747,12 +789,12 @@
continue
}
- var depsList []ApexNativeDependencies
+ var deps ApexNativeDependencies
// Add native modules targeting both ABIs. When multilib.* is omitted for
// native_shared_libs/jni_libs/tests, it implies multilib.both
- depsList = append(depsList, a.properties.Multilib.Both)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.Both)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: a.properties.Native_shared_libs,
Tests: a.properties.Tests,
Jni_libs: a.properties.Jni_libs,
@@ -763,8 +805,8 @@
// binaries, it implies multilib.first
isPrimaryAbi := i == 0
if isPrimaryAbi {
- depsList = append(depsList, a.properties.Multilib.First)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.First)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: nil,
Tests: nil,
Jni_libs: nil,
@@ -775,34 +817,32 @@
// Add native modules targeting either 32-bit or 64-bit ABI
switch target.Arch.ArchType.Multilib {
case "lib32":
- depsList = append(depsList, a.properties.Multilib.Lib32)
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Lib32)
+ deps.Merge(a.properties.Multilib.Prefer32)
case "lib64":
- depsList = append(depsList, a.properties.Multilib.Lib64)
+ deps.Merge(a.properties.Multilib.Lib64)
if !has32BitTarget {
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Prefer32)
}
}
// Add native modules targeting a specific arch variant
switch target.Arch.ArchType {
case android.Arm:
- depsList = append(depsList, a.archProperties.Arch.Arm.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies)
case android.Arm64:
- depsList = append(depsList, a.archProperties.Arch.Arm64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies)
case android.Riscv64:
- depsList = append(depsList, a.archProperties.Arch.Riscv64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies)
case android.X86:
- depsList = append(depsList, a.archProperties.Arch.X86.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies)
case android.X86_64:
- depsList = append(depsList, a.archProperties.Arch.X86_64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies)
default:
panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
}
- for _, d := range depsList {
- addDependenciesForNativeModules(ctx, d, target, imageVariation)
- }
+ addDependenciesForNativeModules(ctx, deps, target, imageVariation)
ctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "os", Variation: target.OsVariation()},
{Mutator: "arch", Variation: target.ArchVariation()},
@@ -1853,24 +1893,24 @@
a.outputFile = a.outputApexFile
a.setCompression(ctx)
- a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyPair[0])
- a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyPair[1])
- a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyPair[0])
- a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyPair[1])
+ // TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer
+ // interface if these were set in a provider rather than the module itself
+ a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0])
+ a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[1])
+ a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[0])
+ a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[1])
+
apexType := a.properties.ApexType
switch apexType {
case imageApex:
- // TODO(asmundak): Bazel does not create these files yet.
- // b/190817312
+
+ // TODO(b/190817312): Generate the notice file from the apex rule.
a.htmlGzNotice = android.PathForBazelOut(ctx, "NOTICE.html.gz")
- // b/239081457
- a.bundleModuleFile = android.PathForBazelOut(ctx, a.Name()+apexType.suffix()+"-base.zip")
- // b/239081455
- a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_using.txt"))
- // b/239081456
- a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_backing.txt"))
- // b/239084755
- a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_using.xml"))
+ a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
+ a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
+ a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
+ // TODO(b/239084755): Generate the java api using.xml file from Bazel.
+ a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
installSuffix := imageApexSuffix
if a.isCompressed {
installSuffix = imageCapexSuffix
@@ -2563,7 +2603,7 @@
// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
// certain compatibility checks such as apex_available are not done for apex_test.
-func testApexBundleFactory() android.Module {
+func TestApexBundleFactory() android.Module {
bundle := newApexBundle()
bundle.testApex = true
return bundle
@@ -2592,6 +2632,7 @@
module.AddProperties(
&apexBundleProperties{},
&apexTargetBundleProperties{},
+ &apexArchBundleProperties{},
&overridableProperties{},
)
@@ -2665,12 +2706,13 @@
// Certificate
if overridableProperties.Certificate == nil {
- // delegated to the rule attr default
- attrs.Certificate = nil
+ // If overridableProperties.Certificate is nil, clear this out as
+ // well with zeroed structs, so the override_apex does not use the
+ // base apex's certificate.
+ attrs.Certificate = bazel.LabelAttribute{}
+ attrs.Certificate_name = bazel.StringAttribute{}
} else {
- certificateName, certificate := java.ParseCertificateToAttribute(ctx, overridableProperties.Certificate)
- attrs.Certificate_name = certificateName
- attrs.Certificate = certificate
+ attrs.Certificate, attrs.Certificate_name = android.BazelStringOrLabelFromProp(ctx, overridableProperties.Certificate)
}
// Prebuilts
@@ -2740,11 +2782,6 @@
return ""
}
- archMinApiLevel := cc.MinApiForArch(ctx, a.MultiTargets()[0].Arch.ArchType)
- if !archMinApiLevel.IsNone() && archMinApiLevel.CompareTo(minApiLevel) > 0 {
- minApiLevel = archMinApiLevel
- }
-
overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
@@ -3351,8 +3388,8 @@
Android_manifest bazel.LabelAttribute
File_contexts bazel.LabelAttribute
Key bazel.LabelAttribute
- Certificate *bazel.Label // used when the certificate prop is a module
- Certificate_name *string // used when the certificate prop is a string
+ Certificate bazel.LabelAttribute // used when the certificate prop is a module
+ Certificate_name bazel.StringAttribute // used when the certificate prop is a string
Min_sdk_version *string
Updatable bazel.BoolAttribute
Installable bazel.BoolAttribute
@@ -3363,6 +3400,7 @@
Compressible bazel.BoolAttribute
Package_name *string
Logging_parent *string
+ Tests bazel.LabelListAttribute
}
type convertedNativeSharedLibs struct {
@@ -3372,13 +3410,19 @@
// ConvertWithBp2build performs bp2build conversion of an apex
func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // We do not convert apex_test modules at this time
- if ctx.ModuleType() != "apex" {
+ // We only convert apex and apex_test modules at this time
+ if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" {
return
}
attrs, props := convertWithBp2build(a, ctx)
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, &attrs)
+ commonAttrs := android.CommonAttributes{
+ Name: a.Name(),
+ }
+ if a.testApex {
+ commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
+ }
+ ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
@@ -3414,13 +3458,19 @@
keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key))
}
- certificateName, certificate := java.ParseCertificateToAttribute(ctx, a.overridableProperties.Certificate)
+ // Certificate
+ certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableProperties.Certificate)
nativeSharedLibs := &convertedNativeSharedLibs{
Native_shared_libs_32: bazel.LabelListAttribute{},
Native_shared_libs_64: bazel.LabelListAttribute{},
}
- compileMultilib := "both"
+
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=698;drc=f05b0d35d2fbe51be9961ce8ce8031f840295c68
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2549;drc=ec731a83e3e2d80a1254e32fd4ad7ef85e262669
+ // In Soong, decodeMultilib, used to get multilib, return "first" if defaultMultilib is set to "common".
+ // Since apex sets defaultMultilib to be "common", equivalent compileMultilib in bp2build for apex should be "first"
+ compileMultilib := "first"
if a.CompileMultilib() != nil {
compileMultilib = *a.CompileMultilib()
}
@@ -3439,6 +3489,12 @@
binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries)
binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries)
+ var testsAttrs bazel.LabelListAttribute
+ if a.testApex && len(a.properties.ApexNativeDependencies.Tests) > 0 {
+ tests := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Tests)
+ testsAttrs = bazel.MakeLabelListAttribute(tests)
+ }
+
var updatableAttribute bazel.BoolAttribute
if a.properties.Updatable != nil {
updatableAttribute.Value = a.properties.Updatable
@@ -3481,6 +3537,7 @@
Compressible: compressibleAttribute,
Package_name: packageName,
Logging_parent: loggingParent,
+ Tests: testsAttrs,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e130fcc..985ad59 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "os"
"path"
"path/filepath"
"reflect"
@@ -30,6 +29,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel/cquery"
"android/soong/bpf"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -2191,6 +2191,38 @@
`)
}
+func TestApexMinSdkVersion_MinApiForArch(t *testing.T) {
+ // Tests that an apex dependency with min_sdk_version higher than the
+ // min_sdk_version of the apex is allowed as long as the dependency's
+ // min_sdk_version is less than or equal to the api level that the
+ // architecture was introduced in. In this case, arm64 didn't exist
+ // until api level 21, so the arm64 code will never need to run on
+ // an api level 20 device, even if other architectures of the apex
+ // will.
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ min_sdk_version: "20",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ srcs: ["mylib.cpp"],
+ apex_available: ["myapex"],
+ min_sdk_version: "21",
+ stl: "none",
+ }
+ `)
+}
+
func TestJavaStableSdkVersion(t *testing.T) {
testCases := []struct {
name string
@@ -4098,6 +4130,76 @@
ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
}
+func TestCompileMultilibProp(t *testing.T) {
+ testCases := []struct {
+ compileMultiLibProp string
+ containedLibs []string
+ notContainedLibs []string
+ }{
+ {
+ containedLibs: []string{
+ "image.apex/lib64/mylib.so",
+ "image.apex/lib/mylib.so",
+ },
+ compileMultiLibProp: `compile_multilib: "both",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "first",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ // compile_multilib, when unset, should result to the same output as when compile_multilib is "first"
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "64",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib64/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "32",`,
+ },
+ }
+ for _, testCase := range testCases {
+ ctx := testApex(t, fmt.Sprintf(`
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ %s
+ native_shared_libs: ["mylib"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+ `, testCase.compileMultiLibProp),
+ )
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ apexRule := module.Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ for _, containedLib := range testCase.containedLibs {
+ ensureContains(t, copyCmds, containedLib)
+ }
+ for _, notContainedLib := range testCase.notContainedLibs {
+ ensureNotContains(t, copyCmds, notContainedLib)
+ }
+ }
+}
+
func TestNonTestApex(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -4297,12 +4399,15 @@
name: "myapex",
key: "myapex.key",
updatable: false,
+ native_shared_libs: ["mylib.generic"],
arch: {
arm64: {
native_shared_libs: ["mylib.arm64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
x86_64: {
native_shared_libs: ["mylib.x64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
}
}
@@ -4314,6 +4419,18 @@
}
cc_library {
+ name: "mylib.generic",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ // TODO: remove //apex_available:platform
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
+ cc_library {
name: "mylib.arm64",
srcs: ["mylib.cpp"],
system_shared_libs: [],
@@ -4343,6 +4460,7 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.generic"), "android_arm64_armv8-a_shared_apex10000")
ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
@@ -9628,6 +9746,86 @@
android.AssertBoolEquals(t, "core variant should link against source libc", true, hasDep(libfooCoreVariant, libcCoreVariant))
}
-func TestMain(m *testing.M) {
- os.Exit(m.Run())
+func TestApexImageInMixedBuilds(t *testing.T) {
+ bp := `
+apex_key{
+ name: "foo_key",
+}
+apex {
+ name: "foo",
+ key: "foo_key",
+ updatable: true,
+ min_sdk_version: "31",
+ file_contexts: ":myapex-file_contexts",
+ bazel_module: { label: "//:foo" },
+}`
+
+ outputBaseDir := "out/bazel"
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outputBaseDir,
+ LabelToApexInfo: map[string]cquery.ApexInfo{
+ "//:foo": cquery.ApexInfo{
+ SignedOutput: "signed_out.apex",
+ UnsignedOutput: "unsigned_out.apex",
+ BundleKeyInfo: []string{"public_key", "private_key"},
+ ContainerKeyInfo: []string{"container_cert", "container_private"},
+ SymbolsUsedByApex: "foo_using.txt",
+ JavaSymbolsUsedByApex: "foo_using.xml",
+ BundleFile: "apex_bundle.zip",
+
+ // unused
+ PackageName: "pkg_name",
+ ProvidesLibs: []string{"a", "b"},
+ RequiresLibs: []string{"c", "d"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ m := result.ModuleForTests("foo", "android_common_foo_image").Module()
+ ab, ok := m.(*apexBundle)
+ if !ok {
+ t.Fatalf("Expected module to be an apexBundle, was not")
+ }
+
+ if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
+ t.Errorf("Expected public key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
+ t.Errorf("Expected private key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
+ t.Errorf("Expected public container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
+ t.Errorf("Expected private container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
+ var builder strings.Builder
+ mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
+
+ data := builder.String()
+ if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
}
diff --git a/apex/builder.go b/apex/builder.go
index ad8075b..e4c1673 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -922,10 +922,16 @@
installedSymlinks = append(installedSymlinks,
ctx.InstallAbsoluteSymlink(installDir, fi.stem(), pathOnDevice))
} else {
- target := ctx.InstallFile(installDir, fi.stem(), fi.builtFile)
- for _, sym := range fi.symlinks {
- installedSymlinks = append(installedSymlinks,
- ctx.InstallSymlink(installDir, sym, target))
+ if fi.class == appSet {
+ as := fi.module.(*java.AndroidAppSet)
+ ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk",
+ as.OutputFile(), as.PackedAdditionalOutputs())
+ } else {
+ target := ctx.InstallFile(installDir, fi.stem(), fi.builtFile)
+ for _, sym := range fi.symlinks {
+ installedSymlinks = append(installedSymlinks,
+ ctx.InstallSymlink(installDir, sym, target))
+ }
}
}
}
diff --git a/apex/key.go b/apex/key.go
index 2b09f1d..0a7e80f 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -201,10 +201,10 @@
type bazelApexKeyAttributes struct {
Public_key bazel.LabelAttribute
- Public_key_name bazel.LabelAttribute
+ Public_key_name bazel.StringAttribute
Private_key bazel.LabelAttribute
- Private_key_name bazel.LabelAttribute
+ Private_key_name bazel.StringAttribute
}
// ConvertWithBp2build performs conversion apexKey for bp2build
@@ -213,27 +213,11 @@
}
func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
- var privateKeyLabelAttribute bazel.LabelAttribute
- var privateKeyNameAttribute bazel.LabelAttribute
- if module.properties.Private_key != nil {
- m := String(module.properties.Private_key)
- if android.SrcIsModule(m) == "" {
- privateKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key))
- } else {
- privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Private_key))
- }
- }
+ privateKeyLabelAttribute, privateKeyNameAttribute :=
+ android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key)
- var publicKeyLabelAttribute bazel.LabelAttribute
- var publicKeyNameAttribute bazel.LabelAttribute
- if module.properties.Public_key != nil {
- m := String(module.properties.Public_key)
- if android.SrcIsModule(m) == "" {
- publicKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key))
- } else {
- publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Public_key))
- }
- }
+ publicKeyLabelAttribute, publicKeyNameAttribute :=
+ android.BazelStringOrLabelFromProp(ctx, module.properties.Public_key)
attrs := &bazelApexKeyAttributes{
Private_key: privateKeyLabelAttribute,
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 0f57911..39446a1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -500,6 +500,9 @@
Arm64 struct {
Src *string `android:"path"`
}
+ Riscv64 struct {
+ Src *string `android:"path"`
+ }
X86 struct {
Src *string `android:"path"`
}
@@ -527,6 +530,12 @@
src = String(p.Arch.Arm.Src)
case android.Arm64:
src = String(p.Arch.Arm64.Src)
+ case android.Riscv64:
+ src = String(p.Arch.Riscv64.Src)
+ // HACK: fall back to arm64 prebuilts, the riscv64 ones don't exist yet.
+ if src == "" {
+ src = String(p.Arch.Arm64.Src)
+ }
case android.X86:
src = String(p.Arch.X86.Src)
case android.X86_64:
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 9e7edc7..d11c78b 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -20,6 +20,7 @@
"soong_build",
],
deps: [
+ "bazel_analysis_v2_proto",
"blueprint",
],
}
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 05f6ed4..bc823b3 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -17,7 +17,6 @@
import (
"crypto/sha256"
"encoding/base64"
- "encoding/json"
"fmt"
"path/filepath"
"reflect"
@@ -25,6 +24,8 @@
"strings"
"github.com/google/blueprint/proptools"
+ "google.golang.org/protobuf/proto"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
type artifactId int
@@ -312,11 +313,79 @@
// BuildStatements are one-to-one with actions in the given action graph, and AqueryDepsets
// are one-to-one with Bazel's depSetOfFiles objects.
func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, []AqueryDepset, error) {
- var aqueryResult actionGraphContainer
- err := json.Unmarshal(aqueryJsonProto, &aqueryResult)
+ aqueryProto := &analysis_v2_proto.ActionGraphContainer{}
+ err := proto.Unmarshal(aqueryJsonProto, aqueryProto)
if err != nil {
return nil, nil, err
}
+ aqueryResult := actionGraphContainer{}
+
+ for _, protoArtifact := range aqueryProto.Artifacts {
+ aqueryResult.Artifacts = append(aqueryResult.Artifacts, artifact{artifactId(protoArtifact.Id),
+ pathFragmentId(protoArtifact.PathFragmentId)})
+ }
+
+ for _, protoAction := range aqueryProto.Actions {
+ var environmentVariable []KeyValuePair
+ var inputDepSetIds []depsetId
+ var outputIds []artifactId
+ var substitutions []KeyValuePair
+
+ for _, protoEnvironmentVariable := range protoAction.EnvironmentVariables {
+ environmentVariable = append(environmentVariable, KeyValuePair{
+ protoEnvironmentVariable.Key, protoEnvironmentVariable.Value,
+ })
+ }
+ for _, protoInputDepSetIds := range protoAction.InputDepSetIds {
+ inputDepSetIds = append(inputDepSetIds, depsetId(protoInputDepSetIds))
+ }
+ for _, protoOutputIds := range protoAction.OutputIds {
+ outputIds = append(outputIds, artifactId(protoOutputIds))
+ }
+ for _, protoSubstitutions := range protoAction.Substitutions {
+ substitutions = append(substitutions, KeyValuePair{
+ protoSubstitutions.Key, protoSubstitutions.Value,
+ })
+ }
+
+ aqueryResult.Actions = append(aqueryResult.Actions,
+ action{
+ Arguments: protoAction.Arguments,
+ EnvironmentVariables: environmentVariable,
+ InputDepSetIds: inputDepSetIds,
+ Mnemonic: protoAction.Mnemonic,
+ OutputIds: outputIds,
+ TemplateContent: protoAction.TemplateContent,
+ Substitutions: substitutions,
+ FileContents: protoAction.FileContents})
+ }
+
+ for _, protoDepSetOfFiles := range aqueryProto.DepSetOfFiles {
+ var directArtifactIds []artifactId
+ var transitiveDepSetIds []depsetId
+
+ for _, protoDirectArtifactIds := range protoDepSetOfFiles.DirectArtifactIds {
+ directArtifactIds = append(directArtifactIds, artifactId(protoDirectArtifactIds))
+ }
+ for _, protoTransitiveDepSetIds := range protoDepSetOfFiles.TransitiveDepSetIds {
+ transitiveDepSetIds = append(transitiveDepSetIds, depsetId(protoTransitiveDepSetIds))
+ }
+ aqueryResult.DepSetOfFiles = append(aqueryResult.DepSetOfFiles,
+ depSetOfFiles{
+ Id: depsetId(protoDepSetOfFiles.Id),
+ DirectArtifactIds: directArtifactIds,
+ TransitiveDepSetIds: transitiveDepSetIds})
+
+ }
+
+ for _, protoPathFragments := range aqueryProto.PathFragments {
+ aqueryResult.PathFragments = append(aqueryResult.PathFragments,
+ pathFragment{
+ Id: pathFragmentId(protoPathFragments.Id),
+ Label: protoPathFragments.Label,
+ ParentId: pathFragmentId(protoPathFragments.ParentId)})
+
+ }
aqueryHandler, err := newAqueryHandler(aqueryResult)
if err != nil {
return nil, nil, err
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 5810364..2eacafa 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -15,118 +15,128 @@
package bazel
import (
+ "encoding/json"
"fmt"
"reflect"
"sort"
"testing"
+
+ "google.golang.org/protobuf/proto"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
func TestAqueryMultiArchGenrule(t *testing.T) {
// This input string is retrieved from a real build of bionic-related genrules.
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 6 },
- { "id": 3, "pathFragmentId": 8 },
- { "id": 4, "pathFragmentId": 12 },
- { "id": 5, "pathFragmentId": 19 },
- { "id": 6, "pathFragmentId": 20 },
- { "id": 7, "pathFragmentId": 21 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [1],
- "outputIds": [4],
- "primaryOutputId": 4
- }, {
- "targetId": 2,
- "actionKey": "9f4309ce165dac458498cb92811c18b0b7919782cc37b82a42d2141b8cc90826",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [2],
- "outputIds": [5],
- "primaryOutputId": 5
- }, {
- "targetId": 3,
- "actionKey": "50d6c586103ebeed3a218195540bcc30d329464eae36377eb82f8ce7c36ac342",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86_64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86_64.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [3],
- "outputIds": [6],
- "primaryOutputId": 6
- }, {
- "targetId": 4,
- "actionKey": "f30cbe442f5216f4223cf16a39112cad4ec56f31f49290d85cff587e48647ffa",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm64.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [4],
- "outputIds": [7],
- "primaryOutputId": 7
- }],
- "targets": [
- { "id": 1, "label": "@sourceroot//bionic/libc:syscalls-arm", "ruleClassId": 1 },
- { "id": 2, "label": "@sourceroot//bionic/libc:syscalls-x86", "ruleClassId": 1 },
- { "id": 3, "label": "@sourceroot//bionic/libc:syscalls-x86_64", "ruleClassId": 1 },
- { "id": 4, "label": "@sourceroot//bionic/libc:syscalls-arm64", "ruleClassId": 1 }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2, 3] },
- { "id": 2, "directArtifactIds": [1, 2, 3] },
- { "id": 3, "directArtifactIds": [1, 2, 3] },
- { "id": 4, "directArtifactIds": [1, 2, 3] }],
- "configuration": [{
- "id": 1,
- "mnemonic": "k8-fastbuild",
- "platformName": "k8",
- "checksum": "485c362832c178e367d972177f68e69e0981e51e67ef1c160944473db53fe046"
- }],
- "ruleClasses": [{ "id": 1, "name": "genrule"}],
- "pathFragments": [
- { "id": 5, "label": ".." },
- { "id": 4, "label": "sourceroot", "parentId": 5 },
- { "id": 3, "label": "bionic", "parentId": 4 },
- { "id": 2, "label": "libc", "parentId": 3 },
- { "id": 1, "label": "SYSCALLS.TXT", "parentId": 2 },
- { "id": 7, "label": "tools", "parentId": 2 },
- { "id": 6, "label": "gensyscalls.py", "parentId": 7 },
- { "id": 11, "label": "bazel_tools", "parentId": 5 },
- { "id": 10, "label": "tools", "parentId": 11 },
- { "id": 9, "label": "genrule", "parentId": 10 },
- { "id": 8, "label": "genrule-setup.sh", "parentId": 9 },
- { "id": 18, "label": "bazel-out" },
- { "id": 17, "label": "sourceroot", "parentId": 18 },
- { "id": 16, "label": "k8-fastbuild", "parentId": 17 },
- { "id": 15, "label": "bin", "parentId": 16 },
- { "id": 14, "label": "bionic", "parentId": 15 },
- { "id": 13, "label": "libc", "parentId": 14 },
- { "id": 12, "label": "syscalls-arm.S", "parentId": 13 },
- { "id": 19, "label": "syscalls-x86.S", "parentId": 13 },
- { "id": 20, "label": "syscalls-x86_64.S", "parentId": 13 },
- { "id": 21, "label": "syscalls-arm64.S", "parentId": 13 }]
-}`
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ "Artifacts": [
+ { "Id": 1, "path_fragment_id": 1 },
+ { "Id": 2, "path_fragment_id": 6 },
+ { "Id": 3, "path_fragment_id": 8 },
+ { "Id": 4, "path_fragment_id": 12 },
+ { "Id": 5, "path_fragment_id": 19 },
+ { "Id": 6, "path_fragment_id": 20 },
+ { "Id": 7, "path_fragment_id": 21 }],
+ "Actions": [{
+ "target_id": 1,
+ "action_key": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [1],
+ "output_ids": [4],
+ "primary_output_id": 4
+ }, {
+ "target_id": 2,
+ "action_key": "9f4309ce165dac458498cb92811c18b0b7919782cc37b82a42d2141b8cc90826",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [2],
+ "output_ids": [5],
+ "primary_output_id": 5
+ }, {
+ "target_id": 3,
+ "action_key": "50d6c586103ebeed3a218195540bcc30d329464eae36377eb82f8ce7c36ac342",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86_64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86_64.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [3],
+ "output_ids": [6],
+ "primary_output_id": 6
+ }, {
+ "target_id": 4,
+ "action_key": "f30cbe442f5216f4223cf16a39112cad4ec56f31f49290d85cff587e48647ffa",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm64.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [4],
+ "output_ids": [7],
+ "primary_output_id": 7
+ }],
+ "Targets": [
+ { "Id": 1, "Label": "@sourceroot//bionic/libc:syscalls-arm", "rule_class_id": 1 },
+ { "Id": 2, "Label": "@sourceroot//bionic/libc:syscalls-x86", "rule_class_id": 1 },
+ { "Id": 3, "Label": "@sourceroot//bionic/libc:syscalls-x86_64", "rule_class_id": 1 },
+ { "Id": 4, "Label": "@sourceroot//bionic/libc:syscalls-arm64", "rule_class_id": 1 }],
+ "dep_set_of_files": [
+ { "Id": 1, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 2, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 3, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 4, "direct_artifact_ids": [1, 2, 3] }],
+ "Configuration": [{
+ "Id": 1,
+ "Mnemonic": "k8-fastbuild",
+ "platform_name": "k8",
+ "Checksum": "485c362832c178e367d972177f68e69e0981e51e67ef1c160944473db53fe046"
+ }],
+ "rule_classes": [{ "Id": 1, "Name": "genrule"}],
+ "path_fragments": [
+ { "Id": 5, "Label": ".." },
+ { "Id": 4, "Label": "sourceroot", "parent_id": 5 },
+ { "Id": 3, "Label": "bionic", "parent_id": 4 },
+ { "Id": 2, "Label": "libc", "parent_id": 3 },
+ { "Id": 1, "Label": "SYSCALLS.TXT", "parent_id": 2 },
+ { "Id": 7, "Label": "tools", "parent_id": 2 },
+ { "Id": 6, "Label": "gensyscalls.py", "parent_id": 7 },
+ { "Id": 11, "Label": "bazel_tools", "parent_id": 5 },
+ { "Id": 10, "Label": "tools", "parent_id": 11 },
+ { "Id": 9, "Label": "genrule", "parent_id": 10 },
+ { "Id": 8, "Label": "genrule-setup.sh", "parent_id": 9 },
+ { "Id": 18, "Label": "bazel-out" },
+ { "Id": 17, "Label": "sourceroot", "parent_id": 18 },
+ { "Id": 16, "Label": "k8-fastbuild", "parent_id": 17 },
+ { "Id": 15, "Label": "bin", "parent_id": 16 },
+ { "Id": 14, "Label": "bionic", "parent_id": 15 },
+ { "Id": 13, "Label": "libc", "parent_id": 14 },
+ { "Id": 12, "Label": "syscalls-arm.S", "parent_id": 13 },
+ { "Id": 19, "Label": "syscalls-x86.S", "parent_id": 13 },
+ { "Id": 20, "Label": "syscalls-x86_64.S", "parent_id": 13 },
+ { "Id": 21, "Label": "syscalls-arm64.S", "parent_id": 13 }]
+}
+`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
var expectedBuildStatements []BuildStatement
for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
expectedBuildStatements = append(expectedBuildStatements,
@@ -161,130 +171,155 @@
func TestInvalidOutputId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined outputId 3")
}
func TestInvalidInputDepsetIdFromAction(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [2],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [2],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input depsetId 2")
}
func TestInvalidInputDepsetIdFromDepset(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2], "transitiveDepSetIds": [42] }],
- "pathFragments": [
- { "id": 1, "label": "one"},
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2], "transitive_dep_set_ids": [42] }],
+ "path_fragments": [
+ { "id": 1, "label": "one"},
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input depsetId 42 (referenced by depsetId 1)")
}
func TestInvalidInputArtifactId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 3] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 3] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input artifactId 3")
}
func TestInvalidPathFragmentId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two", "parentId": 3 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two", "parent_id": 3 }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined path fragment id 3")
}
@@ -292,27 +327,32 @@
const inputString = `
{
"artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 }],
"actions": [{
- "targetId": 1,
- "actionKey": "x",
+ "target_Id": 1,
+ "action_Key": "x",
"mnemonic": "x",
"arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [2, 3],
- "primaryOutputId": 2
+ "input_dep_set_ids": [1],
+ "output_ids": [2, 3],
+ "primary_output_id": 2
}],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2, 3] }],
- "pathFragments": [
+ "dep_set_of_files": [
+ { "id": 1, "direct_Artifact_Ids": [1, 2, 3] }],
+ "path_fragments": [
{ "id": 1, "label": "one" },
{ "id": 2, "label": "two" },
{ "id": 3, "label": "two.d" }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -332,32 +372,37 @@
func TestMultipleDepfiles(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 },
- { "id": 4, "pathFragmentId": 4 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [2,3,4],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2, 3, 4]
- }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" },
- { "id": 3, "label": "two.d" },
- { "id": 4, "label": "other.d" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 },
+ { "id": 4, "path_fragment_id": 4 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [2,3,4],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [{
+ "id": 1,
+ "direct_artifact_ids": [1, 2, 3, 4]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" },
+ { "id": 3, "label": "two.d" },
+ { "id": 4, "label": "other.d" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
}
@@ -366,74 +411,79 @@
// a single action with many inputs given via a deep depset.
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 7 },
- { "id": 3, "pathFragmentId": 8 },
- { "id": 4, "pathFragmentId": 9 },
- { "id": 5, "pathFragmentId": 10 },
- { "id": 6, "pathFragmentId": 11 },
- { "id": 7, "pathFragmentId": 12 },
- { "id": 8, "pathFragmentId": 13 },
- { "id": 9, "pathFragmentId": 14 },
- { "id": 10, "pathFragmentId": 15 },
- { "id": 11, "pathFragmentId": 16 },
- { "id": 12, "pathFragmentId": 17 },
- { "id": 13, "pathFragmentId": 18 },
- { "id": 14, "pathFragmentId": 19 },
- { "id": 15, "pathFragmentId": 20 },
- { "id": 16, "pathFragmentId": 21 },
- { "id": 17, "pathFragmentId": 22 },
- { "id": 18, "pathFragmentId": 23 },
- { "id": 19, "pathFragmentId": 24 },
- { "id": 20, "pathFragmentId": 25 },
- { "id": 21, "pathFragmentId": 26 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
- "mnemonic": "Action",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"],
- "inputDepSetIds": [1],
- "outputIds": [21],
- "primaryOutputId": 21
- }],
- "depSetOfFiles": [
- { "id": 3, "directArtifactIds": [1, 2, 3, 4, 5] },
- { "id": 4, "directArtifactIds": [6, 7, 8, 9, 10] },
- { "id": 2, "transitiveDepSetIds": [3, 4], "directArtifactIds": [11, 12, 13, 14, 15] },
- { "id": 5, "directArtifactIds": [16, 17, 18, 19] },
- { "id": 1, "transitiveDepSetIds": [2, 5], "directArtifactIds": [20] }],
- "pathFragments": [
- { "id": 6, "label": "bazel-out" },
- { "id": 5, "label": "sourceroot", "parentId": 6 },
- { "id": 4, "label": "k8-fastbuild", "parentId": 5 },
- { "id": 3, "label": "bin", "parentId": 4 },
- { "id": 2, "label": "testpkg", "parentId": 3 },
- { "id": 1, "label": "test_1", "parentId": 2 },
- { "id": 7, "label": "test_2", "parentId": 2 },
- { "id": 8, "label": "test_3", "parentId": 2 },
- { "id": 9, "label": "test_4", "parentId": 2 },
- { "id": 10, "label": "test_5", "parentId": 2 },
- { "id": 11, "label": "test_6", "parentId": 2 },
- { "id": 12, "label": "test_7", "parentId": 2 },
- { "id": 13, "label": "test_8", "parentId": 2 },
- { "id": 14, "label": "test_9", "parentId": 2 },
- { "id": 15, "label": "test_10", "parentId": 2 },
- { "id": 16, "label": "test_11", "parentId": 2 },
- { "id": 17, "label": "test_12", "parentId": 2 },
- { "id": 18, "label": "test_13", "parentId": 2 },
- { "id": 19, "label": "test_14", "parentId": 2 },
- { "id": 20, "label": "test_15", "parentId": 2 },
- { "id": 21, "label": "test_16", "parentId": 2 },
- { "id": 22, "label": "test_17", "parentId": 2 },
- { "id": 23, "label": "test_18", "parentId": 2 },
- { "id": 24, "label": "test_19", "parentId": 2 },
- { "id": 25, "label": "test_root", "parentId": 2 },
- { "id": 26,"label": "test_out", "parentId": 2 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 7 },
+ { "id": 3, "path_fragment_id": 8 },
+ { "id": 4, "path_fragment_id": 9 },
+ { "id": 5, "path_fragment_id": 10 },
+ { "id": 6, "path_fragment_id": 11 },
+ { "id": 7, "path_fragment_id": 12 },
+ { "id": 8, "path_fragment_id": 13 },
+ { "id": 9, "path_fragment_id": 14 },
+ { "id": 10, "path_fragment_id": 15 },
+ { "id": 11, "path_fragment_id": 16 },
+ { "id": 12, "path_fragment_id": 17 },
+ { "id": 13, "path_fragment_id": 18 },
+ { "id": 14, "path_fragment_id": 19 },
+ { "id": 15, "path_fragment_id": 20 },
+ { "id": 16, "path_fragment_id": 21 },
+ { "id": 17, "path_fragment_id": 22 },
+ { "id": 18, "path_fragment_id": 23 },
+ { "id": 19, "path_fragment_id": 24 },
+ { "id": 20, "path_fragment_id": 25 },
+ { "id": 21, "path_fragment_id": 26 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
+ "mnemonic": "Action",
+ "configuration_id": 1,
+ "arguments": ["/bin/bash", "-c", "touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"],
+ "input_dep_set_ids": [1],
+ "output_ids": [21],
+ "primary_output_id": 21
+ }],
+ "dep_set_of_files": [
+ { "id": 3, "direct_artifact_ids": [1, 2, 3, 4, 5] },
+ { "id": 4, "direct_artifact_ids": [6, 7, 8, 9, 10] },
+ { "id": 2, "transitive_dep_set_ids": [3, 4], "direct_artifact_ids": [11, 12, 13, 14, 15] },
+ { "id": 5, "direct_artifact_ids": [16, 17, 18, 19] },
+ { "id": 1, "transitive_dep_set_ids": [2, 5], "direct_artifact_ids": [20] }],
+ "path_fragments": [
+ { "id": 6, "label": "bazel-out" },
+ { "id": 5, "label": "sourceroot", "parent_id": 6 },
+ { "id": 4, "label": "k8-fastbuild", "parent_id": 5 },
+ { "id": 3, "label": "bin", "parent_id": 4 },
+ { "id": 2, "label": "testpkg", "parent_id": 3 },
+ { "id": 1, "label": "test_1", "parent_id": 2 },
+ { "id": 7, "label": "test_2", "parent_id": 2 },
+ { "id": 8, "label": "test_3", "parent_id": 2 },
+ { "id": 9, "label": "test_4", "parent_id": 2 },
+ { "id": 10, "label": "test_5", "parent_id": 2 },
+ { "id": 11, "label": "test_6", "parent_id": 2 },
+ { "id": 12, "label": "test_7", "parent_id": 2 },
+ { "id": 13, "label": "test_8", "parent_id": 2 },
+ { "id": 14, "label": "test_9", "parent_id": 2 },
+ { "id": 15, "label": "test_10", "parent_id": 2 },
+ { "id": 16, "label": "test_11", "parent_id": 2 },
+ { "id": 17, "label": "test_12", "parent_id": 2 },
+ { "id": 18, "label": "test_13", "parent_id": 2 },
+ { "id": 19, "label": "test_14", "parent_id": 2 },
+ { "id": 20, "label": "test_15", "parent_id": 2 },
+ { "id": 21, "label": "test_16", "parent_id": 2 },
+ { "id": 22, "label": "test_17", "parent_id": 2 },
+ { "id": 23, "label": "test_18", "parent_id": 2 },
+ { "id": 24, "label": "test_19", "parent_id": 2 },
+ { "id": 25, "label": "test_root", "parent_id": 2 },
+ { "id": 26,"label": "test_out", "parent_id": 2 }]
}`
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
expectedBuildStatements := []BuildStatement{
{
@@ -463,27 +513,32 @@
func TestSymlinkTree(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "SymlinkTree",
- "configurationId": 1,
- "inputDepSetIds": [1],
- "outputIds": [2],
- "primaryOutputId": 2,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64"
- }],
- "pathFragments": [
- { "id": 1, "label": "foo.manifest" },
- { "id": 2, "label": "foo.runfiles/MANIFEST" }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1] }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SymlinkTree",
+ "configuration_id": 1,
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" },
+ { "id": 2, "label": "foo.runfiles/MANIFEST" }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -499,37 +554,42 @@
func TestBazelOutRemovalFromInputDepsets(t *testing.T) {
const inputString = `{
- "artifacts": [
- { "id": 1, "pathFragmentId": 10 },
- { "id": 2, "pathFragmentId": 20 },
- { "id": 3, "pathFragmentId": 30 },
- { "id": 4, "pathFragmentId": 40 }],
- "depSetOfFiles": [{
- "id": 1111,
- "directArtifactIds": [3 , 4]
- }, {
- "id": 2222,
- "directArtifactIds": [3]
- }],
- "actions": [{
- "targetId": 100,
- "actionKey": "x",
- "inputDepSetIds": [1111, 2222],
- "mnemonic": "x",
- "arguments": ["bogus", "command"],
- "outputIds": [2],
- "primaryOutputId": 1
- }],
- "pathFragments": [
- { "id": 10, "label": "input" },
- { "id": 20, "label": "output" },
- { "id": 30, "label": "dep1", "parentId": 50 },
- { "id": 40, "label": "dep2", "parentId": 60 },
- { "id": 50, "label": "bazel_tools", "parentId": 60 },
- { "id": 60, "label": ".."}
- ]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 10 },
+ { "id": 2, "path_fragment_id": 20 },
+ { "id": 3, "path_fragment_id": 30 },
+ { "id": 4, "path_fragment_id": 40 }],
+ "dep_set_of_files": [{
+ "id": 1111,
+ "direct_artifact_ids": [3 , 4]
+ }, {
+ "id": 2222,
+ "direct_artifact_ids": [3]
+ }],
+ "actions": [{
+ "target_id": 100,
+ "action_key": "x",
+ "input_dep_set_ids": [1111, 2222],
+ "mnemonic": "x",
+ "arguments": ["bogus", "command"],
+ "output_ids": [2],
+ "primary_output_id": 1
+ }],
+ "path_fragments": [
+ { "id": 10, "label": "input" },
+ { "id": 20, "label": "output" },
+ { "id": 30, "label": "dep1", "parent_id": 50 },
+ { "id": 40, "label": "dep2", "parent_id": 60 },
+ { "id": 50, "label": "bazel_tools", "parent_id": 60 },
+ { "id": 60, "label": ".."}
+ ]
}`
- actualBuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
if len(actualDepsets) != 2 {
t.Errorf("expected 1 depset but found %#v", actualDepsets)
return
@@ -567,43 +627,47 @@
func TestMiddlemenAction(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 },
- { "id": 4, "pathFragmentId": 4 },
- { "id": 5, "pathFragmentId": 5 },
- { "id": 6, "pathFragmentId": 6 }],
- "pathFragments": [
- { "id": 1, "label": "middleinput_one" },
- { "id": 2, "label": "middleinput_two" },
- { "id": 3, "label": "middleman_artifact" },
- { "id": 4, "label": "maininput_one" },
- { "id": 5, "label": "maininput_two" },
- { "id": 6, "label": "output" }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] },
- { "id": 2, "directArtifactIds": [3, 4, 5] }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Middleman",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }, {
- "targetId": 2,
- "actionKey": "y",
- "mnemonic": "Main action",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [2],
- "outputIds": [6],
- "primaryOutputId": 6
- }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 },
+ { "id": 4, "path_fragment_id": 4 },
+ { "id": 5, "path_fragment_id": 5 },
+ { "id": 6, "path_fragment_id": 6 }],
+ "path_fragments": [
+ { "id": 1, "label": "middleinput_one" },
+ { "id": 2, "label": "middleinput_two" },
+ { "id": 3, "label": "middleman_artifact" },
+ { "id": 4, "label": "maininput_one" },
+ { "id": 5, "label": "maininput_two" },
+ { "id": 6, "label": "output" }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] },
+ { "id": 2, "direct_artifact_ids": [3, 4, 5] }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Middleman",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }, {
+ "target_id": 2,
+ "action_key": "y",
+ "mnemonic": "Main action",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [2],
+ "output_ids": [6],
+ "primary_output_id": 6
+ }]
}`
-
- actualBuildStatements, actualDepsets, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -675,28 +739,32 @@
func TestSimpleSymlink(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 3 },
- { "id": 2, "pathFragmentId": 5 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "outputIds": [2],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "file_subdir", "parentId": 1 },
- { "id": 3, "label": "file", "parentId": 2 },
- { "id": 4, "label": "symlink_subdir", "parentId": 1 },
- { "id": 5, "label": "symlink", "parentId": 4 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 3 },
+ { "id": 2, "path_fragment_id": 5 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file_subdir", "parent_id": 1 },
+ { "id": 3, "label": "file", "parent_id": 2 },
+ { "id": 4, "label": "symlink_subdir", "parent_id": 1 },
+ { "id": 5, "label": "symlink", "parent_id": 4 }]
}`
-
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
@@ -719,29 +787,33 @@
func TestSymlinkQuotesPaths(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 3 },
- { "id": 2, "pathFragmentId": 5 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "SolibSymlink",
- "inputDepSetIds": [1],
- "outputIds": [2],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "file subdir", "parentId": 1 },
- { "id": 3, "label": "file", "parentId": 2 },
- { "id": 4, "label": "symlink subdir", "parentId": 1 },
- { "id": 5, "label": "symlink", "parentId": 4 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 3 },
+ { "id": 2, "path_fragment_id": 5 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SolibSymlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file subdir", "parent_id": 1 },
+ { "id": 3, "label": "file", "parent_id": 2 },
+ { "id": 4, "label": "symlink subdir", "parent_id": 1 },
+ { "id": 5, "label": "symlink", "parent_id": 4 }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
-
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -763,82 +835,95 @@
func TestSymlinkMultipleInputs(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }],
- "depSetOfFiles": [{ "id": 1, "directArtifactIds": [1,2] }],
- "pathFragments": [
- { "id": 1, "label": "file" },
- { "id": 2, "label": "other_file" },
- { "id": 3, "label": "symlink" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }],
+ "dep_set_of_files": [{ "id": 1, "direct_artifact_ids": [1,2] }],
+ "path_fragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "other_file" },
+ { "id": 3, "label": "symlink" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
}
func TestSymlinkMultipleOutputs(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "outputIds": [2,3],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1] }],
- "pathFragments": [
- { "id": 1, "label": "file" },
- { "id": 2, "label": "symlink" },
- { "id": 3, "label": "other_symlink" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 3, "path_fragment_id": 3 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2,3],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "symlink" },
+ { "id": 3, "label": "other_symlink" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
- assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file"], output ["symlink" "other_symlink"]`)
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
+ assertError(t, err, "undefined outputId 2")
}
func TestTemplateExpandActionSubstitutions(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "TemplateExpand",
- "configurationId": 1,
- "outputIds": [1],
- "primaryOutputId": 1,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "templateContent": "Test template substitutions: %token1%, %python_binary%",
- "substitutions": [
- { "key": "%token1%", "value": "abcd" },
- { "key": "%python_binary%", "value": "python3" }]
- }],
- "pathFragments": [
- { "id": 1, "label": "template_file" }]
+ "artifacts": [{
+ "id": 1,
+ "path_fragment_id": 1
+ }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "TemplateExpand",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "template_content": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "template_file" }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
-
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -857,48 +942,58 @@
func TestTemplateExpandActionNoOutput(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "TemplateExpand",
- "configurationId": 1,
- "primaryOutputId": 1,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "templateContent": "Test template substitutions: %token1%, %python_binary%",
- "substitutions": [
- { "key": "%token1%", "value": "abcd" },
- { "key": "%python_binary%", "value": "python3" }]
- }],
- "pathFragments": [
- { "id": 1, "label": "template_file" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "TemplateExpand",
+ "configuration_id": 1,
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "templateContent": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "template_file" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `Expect 1 output to template expand action, got: output []`)
}
func TestFileWrite(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "FileWrite",
- "configurationId": 1,
- "outputIds": [1],
- "primaryOutputId": 1,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "fileContents": "file data\n"
- }],
- "pathFragments": [
- { "id": 1, "label": "foo.manifest" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "FileWrite",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "file_contents": "file data\n"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -914,23 +1009,28 @@
func TestSourceSymlinkManifest(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "SourceSymlinkManifest",
- "configurationId": 1,
- "outputIds": [1],
- "primaryOutputId": 1,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "fileContents": "symlink target\n"
- }],
- "pathFragments": [
- { "id": 1, "label": "foo.manifest" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SourceSymlinkManifest",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "file_contents": "symlink target\n"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -1011,3 +1111,14 @@
sort.Strings(sorted)
return sorted
}
+
+// Transform the json format to ActionGraphContainer
+func JsonToActionGraphContainer(inputString string) ([]byte, error) {
+ var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
+ err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
+ if err != nil {
+ return []byte(""), err
+ }
+ data, _ := proto.Marshal(&aqueryProtoResult)
+ return data, err
+}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index e35b531..eb44dd1 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -7,10 +7,11 @@
)
var (
- GetOutputFiles = &getOutputFilesRequestType{}
- GetPythonBinary = &getPythonBinaryRequestType{}
- GetCcInfo = &getCcInfoType{}
- GetApexInfo = &getApexInfoType{}
+ GetOutputFiles = &getOutputFilesRequestType{}
+ GetPythonBinary = &getPythonBinaryRequestType{}
+ GetCcInfo = &getCcInfoType{}
+ GetApexInfo = &getApexInfoType{}
+ GetCcUnstrippedInfo = &getCcUnstippedInfoType{}
)
type CcInfo struct {
@@ -29,7 +30,9 @@
// be a subset of OutputFiles. (or shared libraries, this will be equal to OutputFiles,
// but general cc_library will also have dynamic libraries in output files).
RootDynamicLibraries []string
+ TidyFiles []string
TocFile string
+ UnstrippedOutput string
}
type getOutputFilesRequestType struct{}
@@ -135,12 +138,17 @@
rootSharedLibraries = []
shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo"
+unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
+unstripped = ""
if shared_info_tag in providers(target):
shared_info = providers(target)[shared_info_tag]
path = shared_info.output_file.path
sharedLibraries.append(path)
rootSharedLibraries += [path]
+ unstripped = path
+ if unstripped_tag in providers(target):
+ unstripped = providers(target)[unstripped_tag].unstripped.path
else:
for linker_input in linker_inputs:
for library in linker_input.libraries:
@@ -158,6 +166,12 @@
# NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
pass
+tidy_files = []
+p = providers(target)
+clang_tidy_info = p.get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo")
+if clang_tidy_info:
+ tidy_files = [v.path for v in clang_tidy_info.tidy_files.to_list()]
+
return json_encode({
"OutputFiles": outputFiles,
"CcObjectFiles": ccObjectFiles,
@@ -168,7 +182,9 @@
"Headers": headers,
"RootStaticArchives": rootStaticArchives,
"RootDynamicLibraries": rootSharedLibraries,
- "TocFile": toc_file
+ "TidyFiles": tidy_files,
+ "TocFile": toc_file,
+ "UnstrippedOutput": unstripped,
})`
}
@@ -178,13 +194,10 @@
// Starlark given in StarlarkFunctionBody.
func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
var ccInfo CcInfo
- decoder := json.NewDecoder(strings.NewReader(rawString))
- decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
- err := decoder.Decode(&ccInfo)
- if err != nil {
- return ccInfo, fmt.Errorf("error parsing CcInfo result. %s RAW STRING: %s", err, rawString)
+ if err := parseJson(rawString, &ccInfo); err != nil {
+ return ccInfo, err
}
- return ccInfo, err
+ return ccInfo, nil
}
// Query Bazel for the artifacts generated by the apex modules.
@@ -205,36 +218,81 @@
// - The function body should not be indented outside of its own scope.
func (g getApexInfoType) StarlarkFunctionBody() string {
return `info = providers(target)["//build/bazel/rules/apex:apex.bzl%ApexInfo"]
+bundle_key_info = info.bundle_key_info
+container_key_info = info.container_key_info
return json_encode({
"signed_output": info.signed_output.path,
"unsigned_output": info.unsigned_output.path,
"provides_native_libs": [str(lib) for lib in info.provides_native_libs],
"requires_native_libs": [str(lib) for lib in info.requires_native_libs],
- "bundle_key_pair": [f.path for f in info.bundle_key_pair],
- "container_key_pair": [f.path for f in info.container_key_pair]
+ "bundle_key_info": [bundle_key_info.public_key.path, bundle_key_info.private_key.path],
+ "container_key_info": [container_key_info.pem.path, container_key_info.pk8.path, container_key_info.key_name],
+ "package_name": info.package_name,
+ "symbols_used_by_apex": info.symbols_used_by_apex.path,
+ "java_symbols_used_by_apex": info.java_symbols_used_by_apex.path,
+ "backing_libs": info.backing_libs.path,
+ "bundle_file": info.base_with_config_zip.path,
})`
}
-type ApexCqueryInfo struct {
- SignedOutput string `json:"signed_output"`
- UnsignedOutput string `json:"unsigned_output"`
- ProvidesLibs []string `json:"provides_native_libs"`
- RequiresLibs []string `json:"requires_native_libs"`
- BundleKeyPair []string `json:"bundle_key_pair"`
- ContainerKeyPair []string `json:"container_key_pair"`
+type ApexInfo struct {
+ SignedOutput string `json:"signed_output"`
+ UnsignedOutput string `json:"unsigned_output"`
+ ProvidesLibs []string `json:"provides_native_libs"`
+ RequiresLibs []string `json:"requires_native_libs"`
+ BundleKeyInfo []string `json:"bundle_key_info"`
+ ContainerKeyInfo []string `json:"container_key_info"`
+ PackageName string `json:"package_name"`
+ SymbolsUsedByApex string `json:"symbols_used_by_apex"`
+ JavaSymbolsUsedByApex string `json:"java_symbols_used_by_apex"`
+ BackingLibs string `json:"backing_libs"`
+ BundleFile string `json:"bundle_file"`
}
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
-func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo {
- var info ApexCqueryInfo
- decoder := json.NewDecoder(strings.NewReader(rawString))
- decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
- if err := decoder.Decode(&info); err != nil {
- panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err))
- }
- return info
+func (g getApexInfoType) ParseResult(rawString string) (ApexInfo, error) {
+ var info ApexInfo
+ err := parseJson(rawString, &info)
+ return info, err
+}
+
+// getCcUnstrippedInfoType implements cqueryRequest interface. It handles the
+// interaction with `bazel cquery` to retrieve CcUnstrippedInfo provided
+// by the` cc_binary` and `cc_shared_library` rules.
+type getCcUnstippedInfoType struct{}
+
+func (g getCcUnstippedInfoType) Name() string {
+ return "getCcUnstrippedInfo"
+}
+
+func (g getCcUnstippedInfoType) StarlarkFunctionBody() string {
+ return `unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
+p = providers(target)
+output_path = target.files.to_list()[0].path
+unstripped = output_path
+if unstripped_tag in p:
+ unstripped = p[unstripped_tag].unstripped.files.to_list()[0].path
+return json_encode({
+ "OutputFile": output_path,
+ "UnstrippedOutput": unstripped,
+})
+`
+}
+
+// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
+// The given rawString must correspond to the string output which was created by evaluating the
+// Starlark given in StarlarkFunctionBody.
+func (g getCcUnstippedInfoType) ParseResult(rawString string) (CcUnstrippedInfo, error) {
+ var info CcUnstrippedInfo
+ err := parseJson(rawString, &info)
+ return info, err
+}
+
+type CcUnstrippedInfo struct {
+ OutputFile string
+ UnstrippedOutput string
}
// splitOrEmpty is a modification of strings.Split() that returns an empty list
@@ -246,3 +304,15 @@
return strings.Split(s, sep)
}
}
+
+// parseJson decodes json string into the fields of the receiver.
+// Unknown attribute name causes panic.
+func parseJson(jsonString string, info interface{}) error {
+ decoder := json.NewDecoder(strings.NewReader(jsonString))
+ decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
+ err := decoder.Decode(info)
+ if err != nil {
+ return fmt.Errorf("cannot parse cquery result '%s': %s", jsonString, err)
+ }
+ return nil
+}
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index afe478b..a0a993f 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -3,10 +3,12 @@
import (
"encoding/json"
"reflect"
+ "strings"
"testing"
)
func TestGetOutputFilesParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
@@ -29,14 +31,17 @@
},
}
for _, tc := range testCases {
- actualOutput := GetOutputFiles.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput := GetOutputFiles.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
}
}
func TestGetPythonBinaryParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
@@ -54,14 +59,17 @@
},
}
for _, tc := range testCases {
- actualOutput := GetPythonBinary.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput := GetPythonBinary.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
}
}
func TestGetCcInfoParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
inputCcInfo CcInfo
@@ -73,24 +81,6 @@
expectedOutput: CcInfo{},
},
{
- description: "only output",
- inputCcInfo: CcInfo{
- OutputFiles: []string{"test", "test3"},
- },
- expectedOutput: CcInfo{
- OutputFiles: []string{"test", "test3"},
- },
- },
- {
- description: "only ToC",
- inputCcInfo: CcInfo{
- TocFile: "test",
- },
- expectedOutput: CcInfo{
- TocFile: "test",
- },
- },
- {
description: "all items set",
inputCcInfo: CcInfo{
OutputFiles: []string{"out1", "out2"},
@@ -119,49 +109,194 @@
},
}
for _, tc := range testCases {
- jsonInput, _ := json.Marshal(tc.inputCcInfo)
- actualOutput, err := GetCcInfo.ParseResult(string(jsonInput))
- if err != nil {
- t.Errorf("%q:\n test case get error: %q", tc.description, err)
- } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ jsonInput, _ := json.Marshal(tc.inputCcInfo)
+ actualOutput, err := GetCcInfo.ParseResult(string(jsonInput))
+ if err != nil {
+ t.Errorf("error parsing result: %q", err)
+ } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v\n!= actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetCcInfoParseResultsError(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "toc_file": "dir/file.so.toc"
+}`,
+ expectedError: `json: unknown field "toc_file"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetCcInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
}
}
func TestGetApexInfoParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
- expectedOutput ApexCqueryInfo
+ expectedOutput ApexInfo
}{
{
description: "no result",
input: "{}",
- expectedOutput: ApexCqueryInfo{},
+ expectedOutput: ApexInfo{},
},
{
description: "one result",
- input: `{"signed_output":"my.apex",` +
- `"unsigned_output":"my.apex.unsigned",` +
- `"requires_native_libs":["//bionic/libc:libc","//bionic/libdl:libdl"],` +
- `"bundle_key_pair":["foo.pem","foo.privkey"],` +
- `"container_key_pair":["foo.x509.pem", "foo.pk8"],` +
- `"provides_native_libs":[]}`,
- expectedOutput: ApexCqueryInfo{
- SignedOutput: "my.apex",
- UnsignedOutput: "my.apex.unsigned",
- RequiresLibs: []string{"//bionic/libc:libc", "//bionic/libdl:libdl"},
- ProvidesLibs: []string{},
- BundleKeyPair: []string{"foo.pem", "foo.privkey"},
- ContainerKeyPair: []string{"foo.x509.pem", "foo.pk8"},
+ input: `{
+ "signed_output":"my.apex",
+ "unsigned_output":"my.apex.unsigned",
+ "requires_native_libs":["//bionic/libc:libc","//bionic/libdl:libdl"],
+ "bundle_key_info":["foo.pem", "foo.privkey"],
+ "container_key_info":["foo.x509.pem", "foo.pk8", "foo"],
+ "package_name":"package.name",
+ "symbols_used_by_apex": "path/to/my.apex_using.txt",
+ "backing_libs":"path/to/backing.txt",
+ "bundle_file": "dir/bundlefile.zip",
+ "provides_native_libs":[]
+}`,
+ expectedOutput: ApexInfo{
+ SignedOutput: "my.apex",
+ UnsignedOutput: "my.apex.unsigned",
+ RequiresLibs: []string{"//bionic/libc:libc", "//bionic/libdl:libdl"},
+ ProvidesLibs: []string{},
+ BundleKeyInfo: []string{"foo.pem", "foo.privkey"},
+ ContainerKeyInfo: []string{"foo.x509.pem", "foo.pk8", "foo"},
+ PackageName: "package.name",
+ SymbolsUsedByApex: "path/to/my.apex_using.txt",
+ BackingLibs: "path/to/backing.txt",
+ BundleFile: "dir/bundlefile.zip",
},
},
}
for _, tc := range testCases {
- actualOutput := GetApexInfo.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput, err := GetApexInfo.ParseResult(tc.input)
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetApexInfoParseResultsError(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "fake_field": "path/to/file"
+}`,
+ expectedError: `json: unknown field "fake_field"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetApexInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
+ }
+}
+
+func TestGetCcUnstrippedParseResults(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedOutput CcUnstrippedInfo
+ }{
+ {
+ description: "no result",
+ input: "{}",
+ expectedOutput: CcUnstrippedInfo{},
+ },
+ {
+ description: "one result",
+ input: `{"OutputFile":"myapp", "UnstrippedOutput":"myapp_unstripped"}`,
+ expectedOutput: CcUnstrippedInfo{
+ OutputFile: "myapp",
+ UnstrippedOutput: "myapp_unstripped",
+ },
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput, err := GetCcUnstrippedInfo.ParseResult(tc.input)
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetCcUnstrippedParseResultsErrors(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "fake_field": "path/to/file"
+}`,
+ expectedError: `json: unknown field "fake_field"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetCcUnstrippedInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
}
}
diff --git a/bazel/properties.go b/bazel/properties.go
index c329e41..823cda8 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -73,6 +73,17 @@
}
}
+// MakeLabelListFromTargetNames creates a LabelList from unqualified target names
+// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets
+func MakeLabelListFromTargetNames(targetNames []string) LabelList {
+ labels := []Label{}
+ for _, name := range targetNames {
+ label := Label{Label: ":" + name}
+ labels = append(labels, label)
+ }
+ return MakeLabelList(labels)
+}
+
func (ll *LabelList) Equals(other LabelList) bool {
if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
return false
@@ -1178,6 +1189,11 @@
ConfigurableValues configurableStringLists
}
+// IsEmpty returns true if the attribute has no values under any configuration.
+func (sla StringListAttribute) IsEmpty() bool {
+ return len(sla.Value) == 0 && !sla.HasConfigurableValues()
+}
+
type configurableStringLists map[ConfigurationAxis]stringListSelectValues
func (csl configurableStringLists) Append(other configurableStringLists) {
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index e112be3..2b35521 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -27,6 +27,7 @@
}
func registerAndroidAppModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
}
func TestMinimalAndroidApp(t *testing.T) {
@@ -76,6 +77,7 @@
manifest: "manifest/AndroidManifest.xml",
static_libs: ["static_lib_dep"],
java_version: "7",
+ certificate: "foocert",
}
`,
ExpectedBazelTargets: []string{
@@ -86,9 +88,10 @@
"resa/res.png",
"resb/res.png",
]`,
- "custom_package": `"com.google"`,
- "deps": `[":static_lib_dep"]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "custom_package": `"com.google"`,
+ "deps": `[":static_lib_dep"]`,
+ "javacopts": `["-source 1.7 -target 1.7"]`,
+ "certificate_name": `"foocert"`,
}),
}})
}
@@ -130,3 +133,70 @@
}),
}})
}
+
+func TestAndroidAppCertIsModule(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is module",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{},
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+android_app {
+ name: "TestApp",
+ certificate: ":foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate": `":foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestAndroidAppCertIsSrcFile(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is src file",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{
+ "foocert": "",
+ },
+ Blueprint: `
+android_app {
+ name: "TestApp",
+ certificate: "foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate": `"foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestAndroidAppCertIsNotSrcOrModule(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is not src or module",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{
+ // deliberate empty
+ },
+ Blueprint: `
+android_app {
+ name: "TestApp",
+ certificate: "foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate_name": `"foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 4fd6e43..b6061e4 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -22,6 +22,7 @@
"android/soong/java"
"android/soong/sh"
+ "fmt"
"testing"
)
@@ -41,6 +42,7 @@
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
+ ctx.RegisterModuleType("cc_test", cc.TestFactory)
}
func runOverrideApexTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -153,10 +155,17 @@
"key": `":com.android.apogee.key"`,
"manifest": `"apogee_manifest.json"`,
"min_sdk_version": `"29"`,
- "native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ]`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
":native_shared_lib_1",
@@ -273,10 +282,11 @@
}
`,
},
- Blueprint: createMultilibBlueprint("both"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "both",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_32": `[
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib32",
] + select({
@@ -286,11 +296,13 @@
})`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
@@ -303,53 +315,69 @@
}})
}
-func TestApexBundleCompileMultilibFirst(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with compile_multilib=first",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: createMultilibBlueprint("first"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_32": `select({
+func TestApexBundleCompileMultilibFirstAndDefaultValue(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+ "native_shared_libs_32": `select({
"//build/bazel/platforms/arch:arm": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib32",
":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib32",
":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
- "native_shared_libs_64": `select({
+ "native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
+ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+ "manifest": `"apex_manifest.json"`,
+ }),
+ }
+
+ // "first" is the default value of compile_multilib prop so `compile_multilib_: "first"` and unset compile_multilib
+ // should result to the same bp2build output
+ compileMultiLibPropValues := []string{`compile_multilib: "first",`, ""}
+ for _, compileMultiLibProp := range compileMultiLibPropValues {
+ descriptionSuffix := compileMultiLibProp
+ if descriptionSuffix == "" {
+ descriptionSuffix = "compile_multilib unset"
+ }
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - example with " + compileMultiLibProp,
+ ModuleTypeUnderTest: "apex",
+ ModuleTypeUnderTestFactory: apex.BundleFactory,
+ Filesystem: map[string]string{
+ "system/sepolicy/apex/Android.bp": `
+ filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [ "apogee-file_contexts", ],
+ bazel_module: { bp2build_available: false },
+ }
+ `,
+ },
+ Blueprint: createMultilibBlueprint(compileMultiLibProp),
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
}
func TestApexBundleCompileMultilib32(t *testing.T) {
@@ -366,10 +394,11 @@
}
`,
},
- Blueprint: createMultilibBlueprint("32"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "32",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_32": `[
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib32",
] + select({
@@ -397,16 +426,18 @@
}
`,
},
- Blueprint: createMultilibBlueprint("64"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "64",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
+ ":unnested_native_shared_lib",
":native_shared_lib_for_both",
":native_shared_lib_for_lib64",
":native_shared_lib_for_first",
@@ -420,7 +451,7 @@
}
func createMultilibBlueprint(compile_multilib string) string {
- return `
+ return fmt.Sprintf(`
cc_library {
name: "native_shared_lib_for_both",
bazel_module: { bp2build_available: false },
@@ -441,9 +472,15 @@
bazel_module: { bp2build_available: false },
}
+cc_library {
+ name: "unnested_native_shared_lib",
+ bazel_module: { bp2build_available: false },
+}
+
apex {
name: "com.android.apogee",
- compile_multilib: "` + compile_multilib + `",
+ %s
+ native_shared_libs: ["unnested_native_shared_lib"],
multilib: {
both: {
native_shared_libs: [
@@ -466,7 +503,7 @@
],
},
},
-}`
+}`, compile_multilib)
}
func TestApexBundleDefaultPropertyValues(t *testing.T) {
@@ -636,10 +673,17 @@
"key": `":com.google.android.apogee.key"`,
"manifest": `"apogee_manifest.json"`,
"min_sdk_version": `"29"`,
- "native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ]`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
":native_shared_lib_1",
@@ -1206,3 +1250,28 @@
}),
}})
}
+
+func TestApexTestBundleSimple(t *testing.T) {
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex_test - simple",
+ ModuleTypeUnderTest: "apex_test",
+ ModuleTypeUnderTestFactory: apex.TestApexBundleFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+cc_test { name: "cc_test_1", bazel_module: { bp2build_available: false } }
+
+apex_test {
+ name: "test_com.android.apogee",
+ file_contexts: "file_contexts_file",
+ tests: ["cc_test_1"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "test_com.android.apogee", AttrNameToString{
+ "file_contexts": `"file_contexts_file"`,
+ "manifest": `"apex_manifest.json"`,
+ "testonly": `True`,
+ "tests": `[":cc_test_1"]`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 79b1d89..f9a68c9 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -30,12 +30,37 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
}
-func TestApexKeySimple_KeysAreSrcFiles(t *testing.T) {
+func TestApexKeySimple_KeysAreSrcFilesInSameDir(t *testing.T) {
runApexKeyTestCase(t, Bp2buildTestCase{
- Description: "apex key - keys are src files, use key_name attributes",
+ Description: "apex key - keys are src files, use key attributes",
ModuleTypeUnderTest: "apex_key",
ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
- Filesystem: map[string]string{},
+ Filesystem: map[string]string{
+ "com.android.apogee.avbpubkey": "",
+ "com.android.apogee.pem": "",
+ },
+ Blueprint: `
+apex_key {
+ name: "com.android.apogee.key",
+ public_key: "com.android.apogee.avbpubkey",
+ private_key: "com.android.apogee.pem",
+}
+`,
+ ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
+ "private_key": `"com.android.apogee.pem"`,
+ "public_key": `"com.android.apogee.avbpubkey"`,
+ }),
+ }})
+}
+
+func TestApexKeySimple_KeysAreSrcFilesNotInDir(t *testing.T) {
+ runApexKeyTestCase(t, Bp2buildTestCase{
+ Description: "apex key - keys are not src or module, use key_name attributes",
+ ModuleTypeUnderTest: "apex_key",
+ ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
+ Filesystem: map[string]string{
+ // deliberately left empty
+ },
Blueprint: `
apex_key {
name: "com.android.apogee.key",
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 0e3d2a5..a75a84e 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -26,7 +26,7 @@
// Codegen is the backend of bp2build. The code generator is responsible for
// writing .bzl files that are equivalent to Android.bp files that are capable
// of being built with Bazel.
-func Codegen(ctx *CodegenContext) CodegenMetrics {
+func Codegen(ctx *CodegenContext) *CodegenMetrics {
// This directory stores BUILD files that could be eventually checked-in.
bp2buildDir := android.PathForOutput(ctx, "bp2build")
if err := android.RemoveAllOutputDir(bp2buildDir); err != nil {
@@ -48,7 +48,7 @@
soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics))
- return res.metrics
+ return &res.metrics
}
// Get the output directory and create it if it doesn't exist.
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 82ce115..5ab54e3 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -28,7 +28,6 @@
"android/soong/android"
"android/soong/bazel"
"android/soong/starlark_fmt"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -137,7 +136,7 @@
type CodegenContext struct {
config android.Config
- context android.Context
+ context *android.Context
mode CodegenMode
additionalDeps []string
unconvertedDepMode unconvertedDepsMode
@@ -204,12 +203,12 @@
return ctx.additionalDeps
}
-func (ctx *CodegenContext) Config() android.Config { return ctx.config }
-func (ctx *CodegenContext) Context() android.Context { return ctx.context }
+func (ctx *CodegenContext) Config() android.Config { return ctx.config }
+func (ctx *CodegenContext) Context() *android.Context { return ctx.context }
// NewCodegenContext creates a wrapper context that conforms to PathContext for
// writing BUILD files in the output directory.
-func NewCodegenContext(config android.Config, context android.Context, mode CodegenMode) *CodegenContext {
+func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode) *CodegenContext {
var unconvertedDeps unconvertedDepsMode
if config.IsEnvTrue("BP2BUILD_ERROR_UNCONVERTED") {
unconvertedDeps = errorModulesUnconvertedDeps
@@ -245,12 +244,7 @@
buildFileToTargets := make(map[string]BazelTargets)
// Simple metrics tracking for bp2build
- metrics := CodegenMetrics{
- ruleClassCount: make(map[string]uint64),
- convertedModulePathMap: make(map[string]string),
- convertedModuleTypeCount: make(map[string]uint64),
- totalModuleTypeCount: make(map[string]uint64),
- }
+ metrics := CreateCodegenMetrics()
dirs := make(map[string]bool)
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 7c24a94..c40c45a 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -209,7 +209,7 @@
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
+ codegenCtx := NewCodegenContext(config, ctx.Context, QueryView)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
@@ -530,7 +530,7 @@
return
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
@@ -903,7 +903,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
@@ -1156,7 +1156,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
@@ -1263,7 +1263,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
// For each directory, test that the expected number of generated targets is correct.
for dir, expectedCount := range testCase.expectedCount {
@@ -1398,7 +1398,7 @@
if testCase.Dir != "" {
checkDir = testCase.Dir
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
android.FailIfErrored(t, err)
bazelTargets.sort()
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index d4461b6..4c86374 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -2743,6 +2743,205 @@
)
}
+func TestCcApiContributionsWithHdrs(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ stubs: { symbol_file: "libfoo.map.txt", versions: ["28", "29", "current"] },
+ llndk: { symbol_file: "libfoo.map.txt", override_export_include_dirs: ["dir2"]},
+ export_include_dirs: ["dir1"],
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "cc_api_library_headers",
+ "libfoo.systemapi.headers",
+ AttrNameToString{
+ "export_includes": `["dir1"]`,
+ }),
+ MakeBazelTarget(
+ "cc_api_library_headers",
+ "libfoo.vendorapi.headers",
+ AttrNameToString{
+ "export_includes": `["dir2"]`,
+ }),
+ MakeBazelTarget(
+ "cc_api_contribution",
+ "libfoo.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "library_name": `"libfoo"`,
+ "api_surfaces": `[
+ "systemapi",
+ "vendorapi",
+ ]`,
+ "hdrs": `[
+ ":libfoo.systemapi.headers",
+ ":libfoo.vendorapi.headers",
+ ]`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: bp,
+ Description: "cc API contributions to systemapi and vendorapi",
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+}
+
+func TestCcApiSurfaceCombinations(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedApi string
+ expectedApiSurfaces string
+ description string
+ }{
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ stubs: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `["systemapi"]`,
+ description: "Library that contributes to systemapi",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ llndk: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `["vendorapi"]`,
+ description: "Library that contributes to vendorapi",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ llndk: {symbol_file: "a.map.txt"},
+ stubs: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `[
+ "systemapi",
+ "vendorapi",
+ ]`,
+ description: "Library that contributes to systemapi and vendorapi",
+ },
+ }
+ for _, testCase := range testCases {
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "cc_api_contribution",
+ "a.contribution",
+ AttrNameToString{
+ "library_name": `"a"`,
+ "hdrs": `[]`,
+ "api": testCase.expectedApi,
+ "api_surfaces": testCase.expectedApiSurfaces,
+ },
+ ),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: testCase.bp,
+ Description: testCase.description,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
+}
+
+// llndk struct property in Soong provides users with several options to configure the exported include dirs
+// Test the generated bazel targets for the different configurations
+func TestCcVendorApiHeaders(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedIncludes string
+ expectedSystemIncludes string
+ description string
+ }{
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ export_headers_as_system: true,
+ },
+ }
+ `,
+ expectedIncludes: "",
+ expectedSystemIncludes: `[
+ "base_system_include",
+ "include",
+ ]`,
+ description: "Headers are exported as system to API surface",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ override_export_include_dirs: ["llndk_include"],
+ },
+ }
+ `,
+ expectedIncludes: `["llndk_include"]`,
+ expectedSystemIncludes: `["base_system_include"]`,
+ description: "Non-system Headers are ovverriden before export to API surface",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ override_export_include_dirs: ["llndk_include"],
+ export_headers_as_system: true,
+ },
+ }
+ `,
+ expectedIncludes: "", // includes are set to nil
+ expectedSystemIncludes: `[
+ "base_system_include",
+ "llndk_include",
+ ]`,
+ description: "System Headers are extended before export to API surface",
+ },
+ }
+ for _, testCase := range testCases {
+ attrs := AttrNameToString{}
+ if testCase.expectedIncludes != "" {
+ attrs["export_includes"] = testCase.expectedIncludes
+ }
+ if testCase.expectedSystemIncludes != "" {
+ attrs["export_system_includes"] = testCase.expectedSystemIncludes
+ }
+
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_api_library_headers", "a.vendorapi.headers", attrs),
+ // Create a target for cc_api_contribution target
+ MakeBazelTarget("cc_api_contribution", "a.contribution", AttrNameToString{
+ "api": `"a.map.txt"`,
+ "api_surfaces": `["vendorapi"]`,
+ "hdrs": `[":a.vendorapi.headers"]`,
+ "library_name": `"a"`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: testCase.bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
+}
+
func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "stub target generation of the same lib across configs should not result in duplicates",
@@ -3309,3 +3508,38 @@
},
})
}
+
+func TestCcLibraryWithTidy(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library uses tidy properties",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: ["foo.cpp"],
+ tidy: true,
+ tidy_checks: ["check1", "check2"],
+ tidy_checks_as_errors: ["check1error", "check2error"],
+ tidy_disabled_srcs: ["bar.cpp"],
+ tidy_timeout_srcs: ["baz.cpp"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["foo.cpp"]`,
+ "tidy": `True`,
+ "tidy_checks": `[
+ "check1",
+ "check2",
+ ]`,
+ "tidy_checks_as_errors": `[
+ "check1error",
+ "check2error",
+ ]`,
+ "tidy_disabled_srcs": `["bar.cpp"]`,
+ "tidy_timeout_srcs": `["baz.cpp"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 5fa7cac..7d9db6f 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -123,6 +123,69 @@
})
}
+func TestCcApiHeaders(t *testing.T) {
+ fs := map[string]string{
+ "bar/Android.bp": `cc_library_headers { name: "bar_headers", }`,
+ }
+ bp := `
+ cc_library_headers {
+ name: "foo_headers",
+ export_include_dirs: ["dir1", "dir2"],
+ export_header_lib_headers: ["bar_headers"],
+
+ arch: {
+ arm: {
+ export_include_dirs: ["dir_arm"],
+ },
+ x86: {
+ export_include_dirs: ["dir_x86"],
+ },
+ },
+
+ target: {
+ android: {
+ export_include_dirs: ["dir1", "dir_android"],
+ },
+ windows: {
+ export_include_dirs: ["dir_windows"],
+ },
+ }
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{
+ "export_includes": `["dir_arm"]`,
+ "arch": `"arm"`,
+ }),
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{
+ "export_includes": `["dir_x86"]`,
+ "arch": `"x86"`,
+ }),
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{
+ "export_includes": `["dir_android"]`, // common includes are deduped
+ }),
+ // Windows headers are not exported
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{
+ "export_includes": `[
+ "dir1",
+ "dir2",
+ ]`,
+ "deps": `[
+ "//bar:bar_headers.contribution",
+ ":foo_headers.contribution.arm",
+ ":foo_headers.contribution.x86",
+ ":foo_headers.contribution.androidos",
+ ]`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{
+ Blueprint: bp,
+ Description: "Header library contributions to API surfaces",
+ ExpectedBazelTargets: expectedBazelTargets,
+ Filesystem: fs,
+ })
+}
+
func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
Description: "cc_library_headers test with os-specific header_libs props",
diff --git a/bp2build/cc_prebuilt_binary_conversion_test.go b/bp2build/cc_prebuilt_binary_conversion_test.go
new file mode 100644
index 0000000..0e8048c
--- /dev/null
+++ b/bp2build/cc_prebuilt_binary_conversion_test.go
@@ -0,0 +1,125 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package bp2build
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltBinaryTestCase(t *testing.T, testCase Bp2buildTestCase) {
+ t.Helper()
+ description := fmt.Sprintf("cc_prebuilt_binary: %s", testCase.Description)
+ testCase.ModuleTypeUnderTest = "cc_prebuilt_binary"
+ testCase.ModuleTypeUnderTestFactory = cc.PrebuiltBinaryFactory
+ testCase.Description = description
+ t.Run(description, func(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+}
+
+func TestPrebuiltBinary(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "simple",
+ Filesystem: map[string]string{
+ "bin": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `"bin"`,
+ })},
+ })
+}
+
+func TestPrebuiltBinaryWithStrip(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "with strip",
+ Filesystem: map[string]string{
+ "bin": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ strip: { all: true },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `"bin"`,
+ "strip": `{
+ "all": True,
+ }`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltBinaryWithArchVariance(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "with arch variance",
+ Filesystem: map[string]string{
+ "bina": "",
+ "binb": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ arch: {
+ arm64: { srcs: ["bina"], },
+ arm: { srcs: ["binb"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "binb",
+ "//build/bazel/platforms/arch:arm64": "bina",
+ "//conditions:default": None,
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltBinaryMultipleSrcsFails(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "fails because multiple sources",
+ Filesystem: map[string]string{
+ "bina": "",
+ "binb": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bina", "binb"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf("Expected at most one source file"),
+ })
+}
+
+// TODO: nosrcs test
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
index dd217c3..47006ac 100644
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ b/bp2build/cc_prebuilt_library_conversion_test.go
@@ -36,10 +36,10 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -66,14 +66,14 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
"//conditions:default": None,
})`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
@@ -104,13 +104,13 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
"export_includes": `["testdir/1/"]`,
"export_system_includes": `["testdir/2/"]`,
}),
// TODO(b/229374533): When fixed, update this test
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -185,10 +185,10 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libg.so"`,
}),
},
@@ -215,7 +215,7 @@
// bazel_module: { bp2build_available: true },
//}`,
// expectedBazelTargets: []string{
-// makeBazelTarget("prebuilt_library_shared", "libtest", attrNameToString{
+// makeBazelTarget("cc_prebuilt_library_shared", "libtest", attrNameToString{
// "shared_library": `"libf.so"`,
// }),
// },
@@ -242,7 +242,7 @@
// bazel_module: { bp2build_available: true },
//}`,
// expectedBazelTargets: []string{
-// makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
+// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
// "static_library": `"libf.so"`,
// }),
// },
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
index 541ce5e..58c0a70 100644
--- a/bp2build/cc_prebuilt_library_shared_test.go
+++ b/bp2build/cc_prebuilt_library_shared_test.go
@@ -23,7 +23,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -50,7 +50,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go
index 69a1b5e..6116b00 100644
--- a/bp2build/cc_prebuilt_library_static_test.go
+++ b/bp2build/cc_prebuilt_library_static_test.go
@@ -36,7 +36,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
"static_library": `"libf.so"`,
}),
},
@@ -63,7 +63,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
"static_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 4d8b8a4..8ca13b8 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -32,7 +32,7 @@
files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package.
files = append(files, newFile("apex_toolchain", "constants.bzl", apex.BazelApexToolchainVars()))
- files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
+ files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.Serialize().ConvertedModules, "\n")))
convertedModulePathMap, err := json.MarshalIndent(metrics.convertedModulePathMap, "", "\t")
if err != nil {
@@ -55,10 +55,6 @@
return files
}
-func convertedModules(convertedModules []string) string {
- return strings.Join(convertedModules, "\n")
-}
-
func CreateBazelFiles(
cfg android.Config,
ruleShims map[string]RuleShim,
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index b696a98..cfd6128 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -84,7 +84,7 @@
func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
testConfig := android.TestConfig("", make(map[string]string), "", make(map[string][]byte))
- files := CreateSoongInjectionFiles(testConfig, CodegenMetrics{})
+ files := CreateSoongInjectionFiles(testConfig, CreateCodegenMetrics())
expectedFilePaths := []bazelFilepath{
{
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 160395b..3490881 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -15,12 +15,13 @@
package bp2build
import (
+ "fmt"
+ "testing"
+
"android/soong/android"
"android/soong/cc"
"android/soong/genrule"
"android/soong/java"
- "fmt"
- "testing"
)
func registerGenruleModuleTypes(ctx android.RegistrationContext) {
@@ -643,3 +644,50 @@
})
}
}
+
+func TestCcGenruleArchAndExcludeSrcs(t *testing.T) {
+ name := "cc_genrule with arch"
+ bp := `
+ cc_genrule {
+ name: "foo",
+ srcs: [
+ "foo1.in",
+ "foo2.in",
+ ],
+ exclude_srcs: ["foo2.in"],
+ arch: {
+ arm: {
+ srcs: [
+ "foo1_arch.in",
+ "foo2_arch.in",
+ ],
+ exclude_srcs: ["foo2_arch.in"],
+ },
+ },
+ cmd: "cat $(in) > $(out)",
+ bazel_module: { bp2build_available: true },
+ }`
+
+ expectedBazelAttrs := AttrNameToString{
+ "srcs": `["foo1.in"] + select({
+ "//build/bazel/platforms/arch:arm": ["foo1_arch.in"],
+ "//conditions:default": [],
+ })`,
+ "cmd": `"cat $(SRCS) > $(OUTS)"`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ }
+
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("genrule", "foo", expectedBazelAttrs),
+ }
+
+ t.Run(name, func(t *testing.T) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_genrule",
+ ModuleTypeUnderTestFactory: cc.GenRuleFactory,
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+}
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 86f3d42..e8551e5 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -29,10 +29,11 @@
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory)
ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ ctx.RegisterModuleType("java_import_host", java.ImportFactory)
}, tc)
}
-var fs = map[string]string{
+var testFs = map[string]string{
"test.mf": "Main-Class: com.android.test.MainClass",
"other/Android.bp": `cc_library_host_shared {
name: "jni-lib-1",
@@ -43,7 +44,7 @@
func TestJavaBinaryHost(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
srcs: ["a.java", "b.java"],
@@ -76,7 +77,7 @@
func TestJavaBinaryHostRuntimeDeps(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
static_libs: ["java-dep-1"],
@@ -102,3 +103,34 @@
},
})
}
+
+func TestJavaBinaryHostLibs(t *testing.T) {
+ runJavaBinaryHostTestCase(t, Bp2buildTestCase{
+ Description: "java_binary_host with srcs, libs.",
+ Filesystem: testFs,
+ Blueprint: `java_binary_host {
+ name: "java-binary-host-libs",
+ libs: ["java-lib-dep-1"],
+ manifest: "test.mf",
+ srcs: ["a.java"],
+}
+
+java_import_host{
+ name: "java-lib-dep-1",
+ jars: ["foo.jar"],
+ bazel_module: { bp2build_available: false },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_binary", "java-binary-host-libs", AttrNameToString{
+ "main_class": `"com.android.test.MainClass"`,
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-dep-1-neverlink"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index 05d7142..ac7dfff 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -48,6 +48,10 @@
MakeBazelTarget("java_import", "example_import", AttrNameToString{
"jars": `["import.jar"]`,
}),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
}})
}
@@ -81,5 +85,35 @@
"//conditions:default": [],
})`,
}),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
+ }})
+}
+
+func TestJavaImportHost(t *testing.T) {
+ runJavaImportTestCase(t, Bp2buildTestCase{
+ Description: "Java import host- simple example",
+ ModuleTypeUnderTest: "java_import_host",
+ ModuleTypeUnderTestFactory: java.ImportFactory,
+ Filesystem: map[string]string{
+ "import.jar": "",
+ },
+ Blueprint: `
+java_import_host {
+ name: "example_import",
+ jars: ["import.jar"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_import", "example_import", AttrNameToString{
+ "jars": `["import.jar"]`,
+ }),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
}})
}
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 0b45996..bd21629 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,25 +9,16 @@
"android/soong/android"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
+ "google.golang.org/protobuf/proto"
"github.com/google/blueprint"
)
-// Simple metrics struct to collect information about a Blueprint to BUILD
+// CodegenMetrics represents information about the Blueprint-to-BUILD
// conversion process.
+// Use CreateCodegenMetrics() to get a properly initialized instance
type CodegenMetrics struct {
- // Total number of Soong modules converted to generated targets
- generatedModuleCount uint64
-
- // Total number of Soong modules converted to handcrafted targets
- handCraftedModuleCount uint64
-
- // Total number of unconverted Soong modules
- unconvertedModuleCount uint64
-
- // Counts of generated Bazel targets per Bazel rule class
- ruleClassCount map[string]uint64
-
+ serialized *bp2build_metrics_proto.Bp2BuildMetrics
// List of modules with unconverted deps
// NOTE: NOT in the .proto
moduleWithUnconvertedDepsMsgs []string
@@ -36,40 +27,32 @@
// NOTE: NOT in the .proto
moduleWithMissingDepsMsgs []string
- // List of converted modules
- convertedModules []string
-
// Map of converted modules and paths to call
+ // NOTE: NOT in the .proto
convertedModulePathMap map[string]string
+}
- // Counts of converted modules by module type.
- convertedModuleTypeCount map[string]uint64
-
- // Counts of total modules by module type.
- totalModuleTypeCount map[string]uint64
-
- Events []*bp2build_metrics_proto.Event
+func CreateCodegenMetrics() CodegenMetrics {
+ return CodegenMetrics{
+ serialized: &bp2build_metrics_proto.Bp2BuildMetrics{
+ RuleClassCount: make(map[string]uint64),
+ ConvertedModuleTypeCount: make(map[string]uint64),
+ TotalModuleTypeCount: make(map[string]uint64),
+ },
+ convertedModulePathMap: make(map[string]string),
+ }
}
// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
-func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
- return bp2build_metrics_proto.Bp2BuildMetrics{
- GeneratedModuleCount: metrics.generatedModuleCount,
- HandCraftedModuleCount: metrics.handCraftedModuleCount,
- UnconvertedModuleCount: metrics.unconvertedModuleCount,
- RuleClassCount: metrics.ruleClassCount,
- ConvertedModules: metrics.convertedModules,
- ConvertedModuleTypeCount: metrics.convertedModuleTypeCount,
- TotalModuleTypeCount: metrics.totalModuleTypeCount,
- Events: metrics.Events,
- }
+func (metrics *CodegenMetrics) Serialize() *bp2build_metrics_proto.Bp2BuildMetrics {
+ return metrics.serialized
}
// Print the codegen metrics to stdout.
func (metrics *CodegenMetrics) Print() {
generatedTargetCount := uint64(0)
- for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
- count := metrics.ruleClassCount[ruleClass]
+ for _, ruleClass := range android.SortedStringKeys(metrics.serialized.RuleClassCount) {
+ count := metrics.serialized.RuleClassCount[ruleClass]
fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
generatedTargetCount += count
}
@@ -80,9 +63,9 @@
%d converted modules have missing deps:
%s
`,
- metrics.generatedModuleCount,
+ metrics.serialized.GeneratedModuleCount,
generatedTargetCount,
- metrics.handCraftedModuleCount,
+ metrics.serialized.HandCraftedModuleCount,
metrics.TotalModuleCount(),
len(metrics.moduleWithUnconvertedDepsMsgs),
strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
@@ -119,29 +102,67 @@
fail(err, "Error outputting %s", metricsFile)
}
if _, err := os.Stat(metricsFile); err != nil {
- fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile)
+ if os.IsNotExist(err) {
+ fail(err, "MISSING BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ } else {
+ fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ }
+ }
+}
+
+// ReadCodegenMetrics loads CodegenMetrics from `dir`
+// returns a nil pointer if the file doesn't exist
+func ReadCodegenMetrics(dir string) *CodegenMetrics {
+ metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
+ if _, err := os.Stat(metricsFile); err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ } else {
+ fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ panic("unreachable after fail")
+ }
+ }
+ if buf, err := os.ReadFile(metricsFile); err != nil {
+ fail(err, "FAILED TO READ BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ panic("unreachable after fail")
+ } else {
+ bp2BuildMetrics := bp2build_metrics_proto.Bp2BuildMetrics{
+ RuleClassCount: make(map[string]uint64),
+ ConvertedModuleTypeCount: make(map[string]uint64),
+ TotalModuleTypeCount: make(map[string]uint64),
+ }
+ if err := proto.Unmarshal(buf, &bp2BuildMetrics); err != nil {
+ fail(err, "FAILED TO PARSE BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ }
+ return &CodegenMetrics{
+ serialized: &bp2BuildMetrics,
+ convertedModulePathMap: make(map[string]string),
+ }
}
}
func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
- metrics.ruleClassCount[ruleClass] += 1
+ metrics.serialized.RuleClassCount[ruleClass] += 1
}
+func (metrics *CodegenMetrics) AddEvent(event *bp2build_metrics_proto.Event) {
+ metrics.serialized.Events = append(metrics.serialized.Events, event)
+}
func (metrics *CodegenMetrics) AddUnconvertedModule(moduleType string) {
- metrics.unconvertedModuleCount += 1
- metrics.totalModuleTypeCount[moduleType] += 1
+ metrics.serialized.UnconvertedModuleCount += 1
+ metrics.serialized.TotalModuleTypeCount[moduleType] += 1
}
func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
- return metrics.handCraftedModuleCount +
- metrics.generatedModuleCount +
- metrics.unconvertedModuleCount
+ return metrics.serialized.HandCraftedModuleCount +
+ metrics.serialized.GeneratedModuleCount +
+ metrics.serialized.UnconvertedModuleCount
}
// Dump serializes the metrics to the given filename
func (metrics *CodegenMetrics) dump(filename string) (err error) {
ser := metrics.Serialize()
- return shared.Save(&ser, filename)
+ return shared.Save(ser, filename)
}
type ConversionType int
@@ -154,14 +175,14 @@
func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string, conversionType ConversionType) {
// Undo prebuilt_ module name prefix modifications
moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
- metrics.convertedModules = append(metrics.convertedModules, moduleName)
+ metrics.serialized.ConvertedModules = append(metrics.serialized.ConvertedModules, moduleName)
metrics.convertedModulePathMap[moduleName] = "//" + dir
- metrics.convertedModuleTypeCount[moduleType] += 1
- metrics.totalModuleTypeCount[moduleType] += 1
+ metrics.serialized.ConvertedModuleTypeCount[moduleType] += 1
+ metrics.serialized.TotalModuleTypeCount[moduleType] += 1
if conversionType == Handcrafted {
- metrics.handCraftedModuleCount += 1
+ metrics.serialized.HandCraftedModuleCount += 1
} else if conversionType == Generated {
- metrics.generatedModuleCount += 1
+ metrics.serialized.GeneratedModuleCount += 1
}
}
diff --git a/bp2build/performance_test.go b/bp2build/performance_test.go
index c4bbae2..272ebf5 100644
--- a/bp2build/performance_test.go
+++ b/bp2build/performance_test.go
@@ -22,11 +22,12 @@
// run for longer, set -benchtime to a larger value.
import (
- "android/soong/android"
"fmt"
"math"
"strings"
"testing"
+
+ "android/soong/android"
)
const (
@@ -105,7 +106,7 @@
ctx := android.NewTestContext(config)
registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
return testConfig{
config,
ctx,
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index e8b9bc4..1b538d0 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -4,6 +4,7 @@
"testing"
"android/soong/android"
+ "android/soong/genrule"
"android/soong/python"
)
@@ -12,6 +13,8 @@
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
+ ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+ ctx.RegisterModuleType("python_defaults", python.DefaultsFactory)
}, tc)
}
@@ -165,3 +168,152 @@
},
})
}
+
+func TestPythonBinaryMainIsNotSpecified(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main label in same package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsLabel(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main label in same package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: ":a",
+ bazel_module: { bp2build_available: true },
+}
+
+genrule {
+ name: "a",
+ bazel_module: { bp2build_available: false },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `":a"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsSubpackageFile(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main is subpackage file",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Filesystem: map[string]string{
+ "a/Android.bp": "",
+ "a/b.py": "",
+ },
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a/b.py",
+ bazel_module: { bp2build_available: true },
+}
+
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"//a:b.py"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsSubDirFile(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main is file in sub directory that is not Bazel package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Filesystem: map[string]string{
+ "a/b.py": "",
+ },
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a/b.py",
+ bazel_module: { bp2build_available: true },
+}
+
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"a/b.py"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryDuplicatesInRequired(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host duplicates in required attribute of the module and its defaults",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a.py",
+ defaults: ["d"],
+ required: [
+ "r1",
+ ],
+ bazel_module: { bp2build_available: true },
+}
+
+python_defaults {
+ name: "d",
+ required: [
+ "r1",
+ "r2",
+ ],
+}` + simpleModuleDoNotConvertBp2build("genrule", "r1") +
+ simpleModuleDoNotConvertBp2build("genrule", "r2"),
+
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"a.py"`,
+ "imports": `["."]`,
+ "data": `[
+ ":r1",
+ ":r2",
+ ]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 7c39a11..81ec7ee 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -15,13 +15,16 @@
package bp2build
import (
+ "errors"
"fmt"
+ "io/fs"
"io/ioutil"
"os"
"path/filepath"
"regexp"
+ "sync"
+ "sync/atomic"
- "android/soong/android"
"android/soong/shared"
)
@@ -31,14 +34,78 @@
// or a directory. If excluded is true, then that file/directory should be
// excluded from symlinking. Otherwise, the node is not excluded, but one of its
// descendants is (otherwise the node in question would not exist)
-type node struct {
+
+type instructionsNode struct {
name string
excluded bool // If false, this is just an intermediate node
- children map[string]*node
+ children map[string]*instructionsNode
+}
+
+type symlinkForestContext struct {
+ verbose bool
+ topdir string // $TOPDIR
+
+ // State
+ wg sync.WaitGroup
+ depCh chan string
+ okay atomic.Bool // Whether the forest was successfully constructed
+}
+
+// A simple thread pool to limit concurrency on system calls.
+// Necessary because Go spawns a new OS-level thread for each blocking system
+// call. This means that if syscalls are too slow and there are too many of
+// them, the hard limit on OS-level threads can be exhausted.
+type syscallPool struct {
+ shutdownCh []chan<- struct{}
+ workCh chan syscall
+}
+
+type syscall struct {
+ work func()
+ done chan<- struct{}
+}
+
+func createSyscallPool(count int) *syscallPool {
+ result := &syscallPool{
+ shutdownCh: make([]chan<- struct{}, count),
+ workCh: make(chan syscall),
+ }
+
+ for i := 0; i < count; i++ {
+ shutdownCh := make(chan struct{})
+ result.shutdownCh[i] = shutdownCh
+ go result.worker(shutdownCh)
+ }
+
+ return result
+}
+
+func (p *syscallPool) do(work func()) {
+ doneCh := make(chan struct{})
+ p.workCh <- syscall{work, doneCh}
+ <-doneCh
+}
+
+func (p *syscallPool) shutdown() {
+ for _, ch := range p.shutdownCh {
+ ch <- struct{}{} // Blocks until the value is received
+ }
+}
+
+func (p *syscallPool) worker(shutdownCh <-chan struct{}) {
+ for {
+ select {
+ case <-shutdownCh:
+ return
+ case work := <-p.workCh:
+ work.work()
+ work.done <- struct{}{}
+ }
+ }
}
// Ensures that the node for the given path exists in the tree and returns it.
-func ensureNodeExists(root *node, path string) *node {
+func ensureNodeExists(root *instructionsNode, path string) *instructionsNode {
if path == "" {
return root
}
@@ -56,15 +123,14 @@
if child, ok := dn.children[base]; ok {
return child
} else {
- dn.children[base] = &node{base, false, make(map[string]*node)}
+ dn.children[base] = &instructionsNode{base, false, make(map[string]*instructionsNode)}
return dn.children[base]
}
}
-// Turns a list of paths to be excluded into a tree made of "node" objects where
-// the specified paths are marked as excluded.
-func treeFromExcludePathList(paths []string) *node {
- result := &node{"", false, make(map[string]*node)}
+// Turns a list of paths to be excluded into a tree
+func instructionsFromExcludePathList(paths []string) *instructionsNode {
+ result := &instructionsNode{"", false, make(map[string]*instructionsNode)}
for _, p := range paths {
ensureNodeExists(result, p).excluded = true
@@ -179,17 +245,23 @@
// Recursively plants a symlink forest at forestDir. The symlink tree will
// contain every file in buildFilesDir and srcDir excluding the files in
-// exclude. Collects every directory encountered during the traversal of srcDir
-// into acc.
-func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string, okay *bool) {
- if exclude != nil && exclude.excluded {
+// instructions. Collects every directory encountered during the traversal of
+// srcDir .
+func plantSymlinkForestRecursive(context *symlinkForestContext, instructions *instructionsNode, forestDir string, buildFilesDir string, srcDir string) {
+ defer context.wg.Done()
+
+ if instructions != nil && instructions.excluded {
// This directory is not needed, bail out
return
}
- *acc = append(*acc, srcDir)
- srcDirMap := readdirToMap(shared.JoinPath(topdir, srcDir))
- buildFilesMap := readdirToMap(shared.JoinPath(topdir, buildFilesDir))
+ // We don't add buildFilesDir here because the bp2build files marker files is
+ // already a dependency which covers it. If we ever wanted to turn this into
+ // a generic symlink forest creation tool, we'd need to add it, too.
+ context.depCh <- srcDir
+
+ srcDirMap := readdirToMap(shared.JoinPath(context.topdir, srcDir))
+ buildFilesMap := readdirToMap(shared.JoinPath(context.topdir, buildFilesDir))
renamingBuildFile := false
if _, ok := srcDirMap["BUILD"]; ok {
@@ -202,16 +274,16 @@
}
}
- allEntries := make(map[string]bool)
+ allEntries := make(map[string]struct{})
for n := range srcDirMap {
- allEntries[n] = true
+ allEntries[n] = struct{}{}
}
for n := range buildFilesMap {
- allEntries[n] = true
+ allEntries[n] = struct{}{}
}
- err := os.MkdirAll(shared.JoinPath(topdir, forestDir), 0777)
+ err := os.MkdirAll(shared.JoinPath(context.topdir, forestDir), 0777)
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot mkdir '%s': %s\n", forestDir, err)
os.Exit(1)
@@ -230,100 +302,152 @@
}
buildFilesChild := shared.JoinPath(buildFilesDir, f)
- // Descend in the exclusion tree, if there are any excludes left
- var excludeChild *node = nil
- if exclude != nil {
+ // Descend in the instruction tree if it exists
+ var instructionsChild *instructionsNode = nil
+ if instructions != nil {
if f == "BUILD.bazel" && renamingBuildFile {
- excludeChild = exclude.children["BUILD"]
+ instructionsChild = instructions.children["BUILD"]
} else {
- excludeChild = exclude.children[f]
+ instructionsChild = instructions.children[f]
}
}
srcChildEntry, sExists := srcDirMap[f]
buildFilesChildEntry, bExists := buildFilesMap[f]
- if excludeChild != nil && excludeChild.excluded {
+ if instructionsChild != nil && instructionsChild.excluded {
if bExists {
- symlinkIntoForest(topdir, forestChild, buildFilesChild)
+ symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
}
continue
}
- sDir := false
- bDir := false
- if sExists {
- sDir = isDir(shared.JoinPath(topdir, srcChild), srcChildEntry)
- }
-
- if bExists {
- bDir = isDir(shared.JoinPath(topdir, buildFilesChild), buildFilesChildEntry)
- }
+ sDir := sExists && isDir(shared.JoinPath(context.topdir, srcChild), srcChildEntry)
+ bDir := bExists && isDir(shared.JoinPath(context.topdir, buildFilesChild), buildFilesChildEntry)
if !sExists {
- if bDir && excludeChild != nil {
+ if bDir && instructionsChild != nil {
// Not in the source tree, but we have to exclude something from under
// this subtree, so descend
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the source tree, symlink BUILD file
- symlinkIntoForest(topdir, forestChild, buildFilesChild)
+ symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
}
} else if !bExists {
- if sDir && excludeChild != nil {
+ if sDir && instructionsChild != nil {
// Not in the build file tree, but we have to exclude something from
// under this subtree, so descend
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the build file tree, symlink source tree, carry on
- symlinkIntoForest(topdir, forestChild, srcChild)
+ symlinkIntoForest(context.topdir, forestChild, srcChild)
}
} else if sDir && bDir {
// Both are directories. Descend.
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else if !sDir && !bDir {
// Neither is a directory. Merge them.
- srcBuildFile := shared.JoinPath(topdir, srcChild)
- generatedBuildFile := shared.JoinPath(topdir, buildFilesChild)
- // Add the src and generated build files as dependencies so that bp2build
- // is rerun when they change. Currently, this is only really necessary
- // for srcBuildFile, because if we regenerate the generated build files
- // we will always rerun the symlink forest generation as well. If that
- // is later split up into separate, fully dependency-tracing steps, then
- // we'll need srcBuildFile as well. Adding srcBuildFile here today
- // technically makes it a dependency of bp2build_workspace_marker, which
- // also implicitly outputs that file, but since bp2build_workspace_marker
- // will always have a newer timestamp than the generatedBuildFile it
- // shouldn't be a problem.
- *acc = append(*acc, srcBuildFile, generatedBuildFile)
- err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE"))
+ srcBuildFile := shared.JoinPath(context.topdir, srcChild)
+ generatedBuildFile := shared.JoinPath(context.topdir, buildFilesChild)
+ // The Android.bp file that codegen used to produce `buildFilesChild` is
+ // already a dependency, we can ignore `buildFilesChild`.
+ context.depCh <- srcChild
+ err = mergeBuildFiles(shared.JoinPath(context.topdir, forestChild), srcBuildFile, generatedBuildFile, context.verbose)
if err != nil {
fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
srcBuildFile, generatedBuildFile, err)
- *okay = false
+ context.okay.Store(false)
}
} else {
// Both exist and one is a file. This is an error.
fmt.Fprintf(os.Stderr,
"Conflict in workspace symlink tree creation: both '%s' and '%s' exist and exactly one is a directory\n",
srcChild, buildFilesChild)
- *okay = false
+ context.okay.Store(false)
}
}
}
+func removeParallelRecursive(pool *syscallPool, path string, fi os.FileInfo, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ if fi.IsDir() {
+ children := readdirToMap(path)
+ childrenWg := &sync.WaitGroup{}
+ childrenWg.Add(len(children))
+
+ for child, childFi := range children {
+ go removeParallelRecursive(pool, shared.JoinPath(path, child), childFi, childrenWg)
+ }
+
+ childrenWg.Wait()
+ }
+
+ pool.do(func() {
+ if err := os.Remove(path); err != nil {
+ fmt.Fprintf(os.Stderr, "Cannot unlink '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+ })
+}
+
+func removeParallel(path string) {
+ fi, err := os.Lstat(path)
+ if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ return
+ }
+
+ fmt.Fprintf(os.Stderr, "Cannot lstat '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+
+ // Random guess as to the best number of syscalls to run in parallel
+ pool := createSyscallPool(100)
+ removeParallelRecursive(pool, path, fi, wg)
+ pool.shutdown()
+
+ wg.Wait()
+}
+
// Creates a symlink forest by merging the directory tree at "buildFiles" and
// "srcDir" while excluding paths listed in "exclude". Returns the set of paths
// under srcDir on which readdir() had to be called to produce the symlink
// forest.
-func PlantSymlinkForest(cfg android.Config, topdir string, forest string, buildFiles string, srcDir string, exclude []string) []string {
+func PlantSymlinkForest(verbose bool, topdir string, forest string, buildFiles string, exclude []string) []string {
+ context := &symlinkForestContext{
+ verbose: verbose,
+ topdir: topdir,
+ depCh: make(chan string),
+ }
+
+ context.okay.Store(true)
+
+ removeParallel(shared.JoinPath(topdir, forest))
+
+ instructions := instructionsFromExcludePathList(exclude)
+ go func() {
+ context.wg.Add(1)
+ plantSymlinkForestRecursive(context, instructions, forest, buildFiles, ".")
+ context.wg.Wait()
+ close(context.depCh)
+ }()
+
deps := make([]string, 0)
- os.RemoveAll(shared.JoinPath(topdir, forest))
- excludeTree := treeFromExcludePathList(exclude)
- okay := true
- plantSymlinkForestRecursive(cfg, topdir, forest, buildFiles, srcDir, excludeTree, &deps, &okay)
- if !okay {
+ for dep := range context.depCh {
+ deps = append(deps, dep)
+ }
+
+ if !context.okay.Load() {
os.Exit(1)
}
+
return deps
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 31aa830..3750804 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -155,7 +155,7 @@
if tc.Dir != "" {
checkDir = tc.Dir
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
codegenCtx.unconvertedDepMode = tc.UnconvertedDepsMode
bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
if tc.ExpectedErr != nil {
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 60a410d..a840fa3 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -18,11 +18,13 @@
"fmt"
"io"
"path/filepath"
+ "runtime"
"strings"
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
+ "android/soong/cc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -31,6 +33,7 @@
func init() {
registerBpfBuildComponents(android.InitRegistrationContext)
pctx.Import("android/soong/cc/config")
+ pctx.StaticVariable("relPwd", cc.PwdPrefix())
}
var (
@@ -40,7 +43,7 @@
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- Command: "$ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
+ Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
CommandDeps: []string{"$ccCmd"},
},
"ccCmd", "cFlags")
@@ -164,6 +167,9 @@
if proptools.Bool(bpf.properties.Btf) {
cflags = append(cflags, "-g")
+ if runtime.GOOS != "darwin" {
+ cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
+ }
}
srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
diff --git a/build_test.bash b/build_test.bash
index 92819a1..eda4beb 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -48,8 +48,10 @@
case $(uname) in
Linux)
- export LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
- export SEGFAULT_USE_ALTSTACK=1
+ if [[ -f /lib/x86_64-linux-gnu/libSegFault.so ]]; then
+ export LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
+ export SEGFAULT_USE_ALTSTACK=1
+ fi
ulimit -a
;;
esac
@@ -62,7 +64,7 @@
echo
echo "Running Bazel smoke test..."
-STANDALONE_BAZEL=true "${TOP}/tools/bazel" --batch --max_idle_secs=1 help
+STANDALONE_BAZEL=true "${TOP}/build/bazel/bin/bazel" --batch --max_idle_secs=1 help
echo
echo "Running Soong test..."
diff --git a/cc/afdo.go b/cc/afdo.go
index fb66bbe..d36f4af 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -36,7 +36,7 @@
func getAfdoProfileProjects(config android.DeviceConfig) []string {
return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
- return append(globalAfdoProfileProjects, config.AfdoAdditionalProfileDirs()...)
+ return globalAfdoProfileProjects
})
}
diff --git a/cc/api_level.go b/cc/api_level.go
index 8f9e1f6..fdff5cb 100644
--- a/cc/api_level.go
+++ b/cc/api_level.go
@@ -20,7 +20,7 @@
"android/soong/android"
)
-func MinApiForArch(ctx android.EarlyModuleContext,
+func minApiForArch(ctx android.EarlyModuleContext,
arch android.ArchType) android.ApiLevel {
switch arch {
@@ -38,7 +38,7 @@
func nativeApiLevelFromUser(ctx android.BaseModuleContext,
raw string) (android.ApiLevel, error) {
- min := MinApiForArch(ctx, ctx.Arch().ArchType)
+ min := minApiForArch(ctx, ctx.Arch().ArchType)
if raw == "minimum" {
return min, nil
}
diff --git a/cc/binary.go b/cc/binary.go
index 69cf4ac..c2868e7 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -577,25 +577,20 @@
func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+ bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
}
func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
if err != nil {
ctx.ModuleErrorf(err.Error())
return
}
- if len(filePaths) != 1 {
- ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths)
- return
- }
- outputFilePath := android.PathForBazelOut(ctx, filePaths[0])
+ outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- // TODO(b/220164721): We need to decide if we should return the stripped as the unstripped.
- handler.module.linker.(*binaryDecorator).unstrippedOutputFile = outputFilePath
+ handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
}
func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
@@ -651,6 +646,8 @@
sdkAttributes: bp2BuildParseSdkAttributes(m),
}
+ m.convertTidyAttributes(ctx, &attrs.tidyAttributes)
+
return attrs
}
@@ -703,4 +700,6 @@
Features bazel.StringListAttribute
sdkAttributes
+
+ tidyAttributes
}
diff --git a/cc/binary_test.go b/cc/binary_test.go
index cba5974..db6fb3a 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -15,6 +15,7 @@
package cc
import (
+ "android/soong/bazel/cquery"
"testing"
"android/soong/android"
@@ -30,8 +31,11 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.BazelContext = android.MockBazelContext{
OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:bar": []string{"foo"},
+ LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
+ "//foo/bar:bar": cquery.CcUnstrippedInfo{
+ OutputFile: "foo",
+ UnstrippedOutput: "foo.unstripped",
+ },
},
}
ctx := testCcWithConfig(t, config)
@@ -46,7 +50,7 @@
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
- expectedUnStrippedFile := "outputbase/execroot/__main__/foo"
+ expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 868ff0d..6caa854 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -66,6 +66,40 @@
Native_coverage bazel.BoolAttribute
sdkAttributes
+
+ tidyAttributes
+}
+
+type tidyAttributes struct {
+ Tidy *bool
+ Tidy_flags []string
+ Tidy_checks []string
+ Tidy_checks_as_errors []string
+ Tidy_disabled_srcs bazel.LabelListAttribute
+ Tidy_timeout_srcs bazel.LabelListAttribute
+}
+
+func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) {
+ for _, f := range m.features {
+ if tidy, ok := f.(*tidyFeature); ok {
+ moduleAttrs.Tidy = tidy.Properties.Tidy
+ moduleAttrs.Tidy_flags = tidy.Properties.Tidy_flags
+ moduleAttrs.Tidy_checks = tidy.Properties.Tidy_checks
+ moduleAttrs.Tidy_checks_as_errors = tidy.Properties.Tidy_checks_as_errors
+ }
+
+ }
+ archVariantProps := m.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*BaseCompilerProperties); ok {
+ archDisabledSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_disabled_srcs)
+ moduleAttrs.Tidy_disabled_srcs.SetSelectValue(axis, config, archDisabledSrcs)
+ archTimeoutSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_timeout_srcs)
+ moduleAttrs.Tidy_timeout_srcs.SetSelectValue(axis, config, archTimeoutSrcs)
+ }
+ }
+ }
}
// groupSrcsByExtension partitions `srcs` into groups based on file extension.
@@ -169,6 +203,14 @@
}
}
+func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) {
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) {
+ for config, props := range configToProps {
+ parseFunc(axis, config, props)
+ }
+ }
+}
+
// Parses properties common to static and shared libraries. Also used for prebuilt libraries.
func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
attrs := staticOrSharedAttributes{}
@@ -227,32 +269,30 @@
Enabled bazel.BoolAttribute
}
+func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) {
+ srcFileError := func() {
+ ctx.ModuleErrorf("parseSrc: Expected at most one source file for %s %s\n", axis, config)
+ }
+ if len(srcs) > 1 {
+ srcFileError()
+ return
+ } else if len(srcs) == 0 {
+ return
+ }
+ if srcLabelAttribute.SelectValue(axis, config) != nil {
+ srcFileError()
+ return
+ }
+ srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, srcs[0]))
+}
+
// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) prebuiltAttributes {
- manySourceFileError := func(axis bazel.ConfigurationAxis, config string) {
- ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most one source file for %s %s\n", axis, config)
- }
+
var srcLabelAttribute bazel.LabelAttribute
-
- parseSrcs := func(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, srcs []string) {
- if len(srcs) > 1 {
- manySourceFileError(axis, config)
- return
- } else if len(srcs) == 0 {
- return
- }
- if srcLabelAttribute.SelectValue(axis, config) != nil {
- manySourceFileError(axis, config)
- return
- }
-
- src := android.BazelLabelForModuleSrcSingle(ctx, srcs[0])
- srcLabelAttribute.SetSelectValue(axis, config, src)
- }
-
bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok {
- parseSrcs(ctx, axis, config, prebuiltLinkerProperties.Srcs)
+ parseSrc(ctx, &srcLabelAttribute, axis, config, prebuiltLinkerProperties.Srcs)
}
})
@@ -261,7 +301,7 @@
if props.Enabled != nil {
enabledLabelAttribute.SetSelectValue(axis, config, props.Enabled)
}
- parseSrcs(ctx, axis, config, props.Srcs)
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
}
if isStatic {
@@ -284,11 +324,16 @@
}
}
-func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) {
- for config, props := range configToProps {
- parseFunc(axis, config, props)
+func bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+ var srcLabelAttribute bazel.LabelAttribute
+ bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if props, ok := props.(*prebuiltLinkerProperties); ok {
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
}
+ })
+
+ return prebuiltAttributes{
+ Src: srcLabelAttribute,
}
}
diff --git a/cc/builder.go b/cc/builder.go
index 39f7dc3..46cea0b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -924,9 +924,9 @@
}
// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
-func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName, exportedHeaderFlags string, diffFlags []string, prevVersion int,
- checkAllApis, isLlndk, isNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath {
+func sourceAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
+ baseName string, diffFlags []string, prevVersion int,
+ checkAllApis, isLlndkOrNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath {
var outputFile android.ModuleOutPath
if previousVersionDiff {
@@ -946,12 +946,8 @@
}
var errorMessage string
- // When error occurs in previous version ABI diff, Developers can't just update ABI
- // reference but need to follow instructions to ensure ABI backward compatibility.
if previousVersionDiff {
- // TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved.
- extraFlags = append(extraFlags, "-advice-only")
- errorMessage = "error: Please follow development/vndk/tools/header-checker/README.md to ensure the ABI compatibility between your source code and version " + strconv.Itoa(prevVersion) + "."
+ errorMessage = "error: Please follow https://android.googlesource.com/platform/development/+/master/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + strconv.Itoa(prevVersion) + "."
sourceVersion := prevVersion + 1
extraFlags = append(extraFlags, "-target-version", strconv.Itoa(sourceVersion))
} else {
@@ -959,7 +955,7 @@
extraFlags = append(extraFlags, "-target-version", "current")
}
- if isLlndk || isNdk {
+ if isLlndkOrNdk {
extraFlags = append(extraFlags, "-consider-opaque-types-different")
}
if isVndkExt || previousVersionDiff {
diff --git a/cc/cc.go b/cc/cc.go
index d4eaa53..306e483 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1853,6 +1853,11 @@
func (c *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) {
bazelModuleLabel := c.getBazelModuleLabel(ctx)
+ bazelCtx := ctx.Config().BazelContext
+ if ccInfo, err := bazelCtx.GetCcInfo(bazelModuleLabel, android.GetConfigKey(ctx)); err == nil {
+ c.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ }
+
c.bazelHandler.ProcessBazelQueryResponse(ctx, bazelModuleLabel)
c.Properties.SubName = GetSubnameProperty(ctx, c)
@@ -2335,9 +2340,11 @@
ctx.ctx = ctx
deps := c.deps(ctx)
-
apiImportInfo := GetApiImports(c, actx)
- deps = updateDepsWithApiImports(deps, apiImportInfo)
+
+ if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
+ deps = updateDepsWithApiImports(deps, apiImportInfo)
+ }
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
@@ -2362,7 +2369,9 @@
}
// Check header lib replacement from API surface first, and then check again with VSDK
- lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
+ if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
+ lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
+ }
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
if c.isNDKStubLibrary() {
@@ -2536,6 +2545,8 @@
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
}
}
+
+ updateImportedLibraryDependency(ctx)
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
@@ -3626,6 +3637,16 @@
return err
}
+ // A dependency only needs to support a min_sdk_version at least
+ // as high as the api level that the architecture was introduced in.
+ // This allows introducing new architectures in the platform that
+ // need to be included in apexes that normally require an older
+ // min_sdk_version.
+ minApiForArch := minApiForArch(ctx, c.Target().Arch.ArchType)
+ if sdkVersion.LessThan(minApiForArch) {
+ sdkVersion = minApiForArch
+ }
+
if ver.GreaterThan(sdkVersion) {
return fmt.Errorf("newer SDK(%v)", ver)
}
@@ -3714,7 +3735,9 @@
prebuilt := c.IsPrebuilt()
switch c.typ() {
case binary:
- if !prebuilt {
+ if prebuilt {
+ prebuiltBinaryBp2Build(ctx, c)
+ } else {
binaryBp2build(ctx, c)
}
case testBin:
@@ -3751,7 +3774,18 @@
var _ android.ApiProvider = (*Module)(nil)
func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
+ if c.IsPrebuilt() {
+ return
+ }
switch c.typ() {
+ case fullLibrary:
+ apiContributionBp2Build(ctx, c)
+ case sharedLibrary:
+ apiContributionBp2Build(ctx, c)
+ case headerLibrary:
+ // Aggressively generate api targets for all header modules
+ // This is necessary since the header module does not know if it is a dep of API surface stub library
+ apiLibraryHeadersBp2Build(ctx, c)
case ndkLibrary:
ndkLibraryBp2build(ctx, c)
}
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 2d316e6..9f5124b 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -58,8 +58,8 @@
)
func init() {
- pctx.StaticVariable("LinuxBionicArm64Cflags", strings.Join(linuxCrossCflags, " "))
- pctx.StaticVariable("LinuxBionicArm64Ldflags", strings.Join(linuxCrossLdflags, " "))
+ exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Cflags", linuxCrossCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Ldflags", linuxCrossLdflags)
}
// toolchain config for ARM64 Linux CrossHost. Almost everything is the same as the ARM64 Android
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index b53a097..981d1ea 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -222,6 +222,7 @@
"": "${config.ArmGenericCflags}",
"cortex-a7": "${config.ArmCortexA7Cflags}",
"cortex-a8": "${config.ArmCortexA8Cflags}",
+ "cortex-a9": "${config.ArmGenericCflags}",
"cortex-a15": "${config.ArmCortexA15Cflags}",
"cortex-a53": "${config.ArmCortexA53Cflags}",
"cortex-a53.a57": "${config.ArmCortexA53Cflags}",
diff --git a/cc/config/global.go b/cc/config/global.go
index bf80907..9f18784 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -76,9 +76,6 @@
// Help catch common 32/64-bit errors.
"-Werror=int-conversion",
- // Enable the new pass manager.
- "-fexperimental-new-pass-manager",
-
// Disable overly aggressive warning for macros defined with a leading underscore
// This happens in AndroidConfig.h, which is included nearly everywhere.
// TODO: can we remove this now?
@@ -91,9 +88,6 @@
// Warnings from clang-7.0
"-Wno-sign-compare",
- // Warnings from clang-8.0
- "-Wno-defaulted-function-deleted",
-
// Disable -Winconsistent-missing-override until we can clean up the existing
// codebase for it.
"-Wno-inconsistent-missing-override",
@@ -150,6 +144,11 @@
"-fdebug-info-for-profiling",
}
+ commonGlobalLldflags = []string{
+ "-fuse-ld=lld",
+ "-Wl,--icf=safe",
+ }
+
deviceGlobalCppflags = []string{
"-fvisibility-inlines-hidden",
}
@@ -167,13 +166,9 @@
"-Wl,--exclude-libs,libgcc_stripped.a",
"-Wl,--exclude-libs,libunwind_llvm.a",
"-Wl,--exclude-libs,libunwind.a",
- "-Wl,--icf=safe",
}
- deviceGlobalLldflags = append(deviceGlobalLdflags,
- []string{
- "-fuse-ld=lld",
- }...)
+ deviceGlobalLldflags = append(deviceGlobalLdflags, commonGlobalLldflags...)
hostGlobalCflags = []string{}
@@ -181,7 +176,7 @@
hostGlobalLdflags = []string{}
- hostGlobalLldflags = []string{"-fuse-ld=lld"}
+ hostGlobalLldflags = commonGlobalLldflags
commonGlobalCppflags = []string{
"-Wsign-promo",
@@ -295,10 +290,8 @@
}
llvmNextExtraCommonGlobalCflags = []string{
- // New warnings to be fixed after clang-r468909
- "-Wno-error=array-parameter", // http://b/241941550
- "-Wno-error=deprecated-builtins", // http://b/241601211
- "-Wno-error=deprecated", // in external/googletest/googletest
+ // New warnings to be fixed after clang-r475365
+ "-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
}
IllegalFlags = []string{
@@ -312,8 +305,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r468909"
- ClangDefaultShortVersion = "15.0.2"
+ ClangDefaultVersion = "clang-r468909b"
+ ClangDefaultShortVersion = "15.0.3"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index d8918f1..825be7f 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -25,6 +25,7 @@
riscv64Cflags = []string{
// Help catch common 32/64-bit errors.
"-Werror=implicit-function-declaration",
+ "-fno-emulated-tls",
}
riscv64ArchVariantCflags = map[string][]string{}
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index af49e88..f32ebf2 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -58,17 +58,14 @@
)
func init() {
- // Many clang-tidy checks like altera-*, llvm-*, modernize-*
- // are not designed for Android source code or creating too
- // many (false-positive) warnings. The global default tidy checks
- // should include only tested groups and exclude known noisy checks.
+ // The global default tidy checks should include clang-tidy
+ // default checks and tested groups, but exclude known noisy checks.
// See https://clang.llvm.org/extra/clang-tidy/checks/list.html
- pctx.VariableFunc("TidyDefaultGlobalChecks", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" {
+ exportedVars.ExportVariableConfigMethod("TidyDefaultGlobalChecks", func(config android.Config) string {
+ if override := config.Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" {
return override
}
checks := strings.Join([]string{
- "-*",
"android-*",
"bugprone-*",
"cert-*",
@@ -95,7 +92,7 @@
"-misc-non-private-member-variables-in-classes",
"-misc-unused-parameters",
"-performance-no-int-to-ptr",
- // the following groups are excluded by -*
+ // the following groups are not in clang-tidy default checks.
// -altera-*
// -cppcoreguidelines-*
// -darwin-*
@@ -109,49 +106,55 @@
// -readability-*
// -zircon-*
}, ",")
- // clang-analyzer-* checks are too slow to be in the default for WITH_TIDY=1.
- // nightly builds add CLANG_ANALYZER_CHECKS=1 to run those checks.
+ // clang-analyzer-* checks are slow for large files, but we have TIDY_TIMEOUT to
+ // limit clang-tidy runtime. We allow clang-tidy default clang-analyzer-* checks,
+ // and add it explicitly when CLANG_ANALYZER_CHECKS is set.
// The insecureAPI.DeprecatedOrUnsafeBufferHandling warning does not apply to Android.
- if ctx.Config().IsEnvTrue("CLANG_ANALYZER_CHECKS") {
+ if config.IsEnvTrue("CLANG_ANALYZER_CHECKS") {
checks += ",clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
+ } else {
+ checks += ",-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
}
return checks
})
- // There are too many clang-tidy warnings in external and vendor projects.
- // Enable only some google checks for these projects.
- pctx.VariableFunc("TidyExternalVendorChecks", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" {
+ // The external and vendor projects do not run clang-tidy unless TIDY_EXTERNAL_VENDOR is set.
+ // We do not add "-*" to the check list to avoid suppressing the check list in .clang-tidy config files.
+ // There are too many clang-tidy warnings in external and vendor projects, so we only
+ // enable some google checks for these projects. Users can add more checks locally with the
+ // "tidy_checks" list in .bp files, or the "Checks" list in .clang-tidy config files.
+ exportedVars.ExportVariableConfigMethod("TidyExternalVendorChecks", func(config android.Config) string {
+ if override := config.Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" {
return override
}
return strings.Join([]string{
- "-*",
"clang-diagnostic-unused-command-line-argument",
"google-build-explicit-make-pair",
"google-build-namespaces",
"google-runtime-operator",
"google-upgrade-*",
+ "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
}, ",")
})
- pctx.VariableFunc("TidyGlobalNoChecks", func(ctx android.PackageVarContext) string {
+ exportedVars.ExportVariableFuncVariable("TidyGlobalNoChecks", func() string {
return strings.Join(globalNoCheckList, ",")
})
- pctx.VariableFunc("TidyGlobalNoErrorChecks", func(ctx android.PackageVarContext) string {
+ exportedVars.ExportVariableFuncVariable("TidyGlobalNoErrorChecks", func() string {
return strings.Join(globalNoErrorCheckList, ",")
})
// To reduce duplicate warnings from the same header files,
// header-filter will contain only the module directory and
// those specified by DEFAULT_TIDY_HEADER_DIRS.
- pctx.VariableFunc("TidyDefaultHeaderDirs", func(ctx android.PackageVarContext) string {
- return ctx.Config().Getenv("DEFAULT_TIDY_HEADER_DIRS")
+ exportedVars.ExportVariableConfigMethod("TidyDefaultHeaderDirs", func(config android.Config) string {
+ return config.Getenv("DEFAULT_TIDY_HEADER_DIRS")
})
// Use WTIH_TIDY_FLAGS to pass extra global default clang-tidy flags.
- pctx.VariableFunc("TidyWithTidyFlags", func(ctx android.PackageVarContext) string {
- return ctx.Config().Getenv("WITH_TIDY_FLAGS")
+ exportedVars.ExportVariableConfigMethod("TidyWithTidyFlags", func(config android.Config) string {
+ return config.Getenv("WITH_TIDY_FLAGS")
})
}
@@ -202,11 +205,18 @@
return tidyDefault
}
-func NoClangTidyForDir(dir string) bool {
+func neverTidyForDir(dir string) bool {
+ // This function can be extended if tidy needs to be disabled for more directories.
+ return strings.HasPrefix(dir, "external/grpc-grpc")
+}
+
+func NoClangTidyForDir(allowExternalVendor bool, dir string) bool {
+ // Tidy can be disable for a module in dir, if the dir is "neverTidyForDir",
+ // or if it belongs to external|vendor and !allowExternalVendor.
// This function depends on TidyChecksForDir, which selects tidyExternalVendor
- // checks for external/vendor projects. For those projects we disable clang-tidy
- // by default, unless some modules enable clang-tidy with tidy:true.
- return TidyChecksForDir(dir) == tidyExternalVendor
+ // checks for external/vendor projects.
+ return neverTidyForDir(dir) ||
+ (!allowExternalVendor && TidyChecksForDir(dir) == tidyExternalVendor)
}
// Returns a globally disabled tidy checks, overriding locally selected checks.
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index eb71aa1..052832d 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -244,4 +244,8 @@
return LibclangRuntimeLibrary(t, "fuzzer")
}
+func LibFuzzerRuntimeInterceptors(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
+}
+
var inList = android.InList
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 96a53bf..e006471 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -15,8 +15,6 @@
package config
import (
- "strings"
-
"android/soong/android"
)
@@ -71,14 +69,13 @@
)
func init() {
-
- pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
- pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
- pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLdflags, " "))
+ exportedVars.ExportStringListStaticVariable("LinuxBionicCflags", linuxBionicCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicLdflags", linuxBionicLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicLldflags", linuxBionicLdflags)
// Use the device gcc toolchain for now
- pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
- pctx.SourcePathVariable("LinuxBionicGccRoot",
+ exportedVars.ExportStringStaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+ exportedVars.ExportSourcePathVariable("LinuxBionicGccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
}
diff --git a/cc/coverage.go b/cc/coverage.go
index d0902ea..a7356f8 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -108,6 +108,12 @@
if EnableContinuousCoverage(ctx) {
flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-runtime-counter-relocation")
}
+
+ // http://b/248022906, http://b/247941801 enabling coverage and hwasan-globals
+ // instrumentation together causes duplicate-symbol errors for __llvm_profile_filename.
+ if c, ok := ctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(Hwasan) {
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-hwasan-globals=0")
+ }
}
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 13c94ad..64bb7dd 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -126,6 +126,14 @@
deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
} else {
deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+ // Fuzzers built with HWASAN should use the interceptors for better
+ // mutation based on signals in strcmp, memcpy, etc. This is only needed for
+ // fuzz targets, not generic HWASAN-ified binaries or libraries.
+ if module, ok := ctx.Module().(*Module); ok {
+ if module.IsSanitizerEnabled(Hwasan) {
+ deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeInterceptors(ctx.toolchain()))
+ }
+ }
}
deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
@@ -137,9 +145,18 @@
// RunPaths on devices isn't instantiated by the base linker. `../lib` for
// installed fuzz targets (both host and device), and `./lib` for fuzz
// target packages.
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+ // When running on device, fuzz targets with vendor: true set will be in
+ // fuzzer_name/vendor/fuzzer_name (note the extra 'vendor' and thus need to
+ // link with libraries in ../../lib/. Non-vendor binaries only need to look
+ // one level up, in ../lib/.
+ if ctx.inVendor() {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ } else {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+ }
+
return flags
}
@@ -264,7 +281,7 @@
}
// Grab the list of required shared libraries.
- fuzzBin.sharedLibraries = CollectAllSharedDependencies(ctx)
+ fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
for _, lib := range fuzzBin.sharedLibraries {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
@@ -478,9 +495,10 @@
// VisitDirectDeps is used first to avoid incorrectly using the core libraries (sanitizer
// runtimes, libc, libdl, etc.) from a dependency. This may cause issues when dependencies
// have explicit sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
-func CollectAllSharedDependencies(ctx android.ModuleContext) android.Paths {
+func CollectAllSharedDependencies(ctx android.ModuleContext) (android.Paths, []android.Module) {
seen := make(map[string]bool)
recursed := make(map[string]bool)
+ deps := []android.Module{}
var sharedLibraries android.Paths
@@ -494,6 +512,7 @@
return
}
seen[ctx.OtherModuleName(dep)] = true
+ deps = append(deps, dep)
sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, dep, "unstripped"))
})
@@ -503,6 +522,7 @@
}
if !seen[ctx.OtherModuleName(child)] {
seen[ctx.OtherModuleName(child)] = true
+ deps = append(deps, child)
sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, child, "unstripped"))
}
@@ -513,5 +533,5 @@
return true
})
- return sharedLibraries
+ return sharedLibraries, deps
}
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index f25f704..0d16e62 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -40,14 +40,13 @@
name: "gen",
tool_files: ["tool"],
cmd: "$(location tool) $(in) $(out)",
+ out: ["out_arm"],
arch: {
arm: {
srcs: ["foo"],
- out: ["out_arm"],
},
arm64: {
srcs: ["bar"],
- out: ["out_arm64"],
},
},
}
@@ -70,7 +69,7 @@
t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
}
- gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm64")
+ gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm")
expected = []string{"bar"}
if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Implicits.Strings())
diff --git a/cc/library.go b/cc/library.go
index 13a7a3e..897f3c7 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -30,6 +30,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
)
// LibraryProperties is a collection of properties shared by cc library rules/cc.
@@ -288,6 +289,16 @@
None bazel.BoolAttribute
}
+func stripAttrsFromLinkerAttrs(la *linkerAttributes) stripAttributes {
+ return stripAttributes{
+ Keep_symbols: la.stripKeepSymbols,
+ Keep_symbols_and_debug_frame: la.stripKeepSymbolsAndDebugFrame,
+ Keep_symbols_list: la.stripKeepSymbolsList,
+ All: la.stripAll,
+ None: la.stripNone,
+ }
+}
+
func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
// For some cc_library modules, their static variants are ready to be
// converted, but not their shared variants. For these modules, delegate to
@@ -394,13 +405,7 @@
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
- Strip: stripAttributes{
- Keep_symbols: linkerAttrs.stripKeepSymbols,
- Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: linkerAttrs.stripKeepSymbolsList,
- All: linkerAttrs.stripAll,
- None: linkerAttrs.stripNone,
- },
+ Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
Features: baseAttributes.features,
}
@@ -466,6 +471,147 @@
}
}
+func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ apiSurfaces := make([]string, 0)
+ apiHeaders := make([]string, 0)
+ // systemapi (non-null `stubs` property)
+ if module.HasStubsVariants() {
+ apiSurfaces = append(apiSurfaces, android.SystemApi.String())
+ apiIncludes := getSystemApiIncludes(ctx, module)
+ if !apiIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, apiIncludes)
+ apiHeaders = append(apiHeaders, apiIncludes.name)
+ }
+ }
+ // vendorapi (non-null `llndk` property)
+ if module.HasLlndkStubs() {
+ apiSurfaces = append(apiSurfaces, android.VendorApi.String())
+ apiIncludes := getVendorApiIncludes(ctx, module)
+ if !apiIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, apiIncludes)
+ apiHeaders = append(apiHeaders, apiIncludes.name)
+ }
+ }
+ // create a target only if this module contributes to an api surface
+ // TODO: Currently this does not distinguish systemapi-only headers and vendrorapi-only headers
+ // TODO: Update so that systemapi-only headers do not get exported to vendorapi (and vice-versa)
+ if len(apiSurfaces) > 0 {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_contribution",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ attrs := &bazelCcApiContributionAttributes{
+ Library_name: module.Name(),
+ Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces),
+ Api: apiLabelAttribute(ctx, module),
+ Hdrs: bazel.MakeLabelListAttribute(
+ bazel.MakeLabelListFromTargetNames(apiHeaders),
+ ),
+ }
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: android.ApiContributionTargetName(module.Name()),
+ SkipData: proptools.BoolPtr(true),
+ },
+ attrs,
+ )
+ }
+}
+
+// Native apis are versioned in a single .map.txt for all api surfaces
+// Pick any one of the .map.txt files
+func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute {
+ var apiFile *string
+ linker := module.linker.(*libraryDecorator)
+ if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil {
+ apiFile = llndkApi
+ } else if systemApi := linker.Properties.Stubs.Symbol_file; systemApi != nil {
+ apiFile = systemApi
+ } else {
+ ctx.ModuleErrorf("API surface library does not have any API file")
+ }
+ apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label
+ return *bazel.MakeLabelAttribute(apiLabel)
+}
+
+// wrapper struct to flatten the arch and os specific export_include_dirs
+// flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.)
+type bazelCcApiLibraryHeadersAttributes struct {
+ bazelCcLibraryHeadersAttributes
+
+ Arch *string
+}
+
+func (a *bazelCcApiLibraryHeadersAttributes) isEmpty() bool {
+ return a.Export_includes.IsEmpty() &&
+ a.Export_system_includes.IsEmpty() &&
+ a.Deps.IsEmpty()
+}
+
+type apiIncludes struct {
+ name string // name of the Bazel target in the generated bp2build workspace
+ attrs bazelCcApiLibraryHeadersAttributes
+}
+
+func (includes *apiIncludes) isEmpty() bool {
+ return includes.attrs.isEmpty()
+}
+
+func (includes *apiIncludes) addDep(name string) {
+ l := bazel.Label{Label: ":" + name}
+ ll := bazel.MakeLabelList([]bazel.Label{l})
+ lla := bazel.MakeLabelListAttribute(ll)
+ includes.attrs.Deps.Append(lla)
+}
+
+func getSystemApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
+ flagProps := c.library.(*libraryDecorator).flagExporter.Properties
+ linkProps := c.library.(*libraryDecorator).baseLinker.Properties
+ includes := android.FirstUniqueStrings(flagProps.Export_include_dirs)
+ systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs)
+ headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers)
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)),
+ }
+
+ return apiIncludes{
+ name: c.Name() + ".systemapi.headers",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ },
+ }
+}
+
+func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
+ baseProps := c.library.(*libraryDecorator).flagExporter.Properties
+ llndkProps := c.library.(*libraryDecorator).Properties.Llndk
+ includes := baseProps.Export_include_dirs
+ systemIncludes := baseProps.Export_system_include_dirs
+ // LLNDK can override the base includes
+ if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil {
+ includes = llndkIncludes
+ }
+ if proptools.Bool(llndkProps.Export_headers_as_system) {
+ systemIncludes = append(systemIncludes, includes...)
+ includes = nil
+ }
+
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)),
+ }
+ return apiIncludes{
+ name: c.Name() + ".vendorapi.headers",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ },
+ }
+}
+
// cc_library creates both static and/or shared libraries for a device and/or
// host. By default, a cc_library has a single variant that targets the device.
// Specifying `host_supported: true` also creates a library that targets the
@@ -739,7 +885,7 @@
outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- handler.module.linker.(*libraryDecorator).unstrippedOutputFile = outputFilePath
+ handler.module.linker.(*libraryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, ccInfo.UnstrippedOutput)
var tocFile android.OptionalPath
if len(ccInfo.TocFile) > 0 {
@@ -810,7 +956,7 @@
for _, path := range paths {
dir := path.String()
// Skip if dir is for generated headers
- if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
+ if strings.HasPrefix(dir, ctx.Config().OutDir()) {
continue
}
@@ -1764,26 +1910,28 @@
addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
+ isNdk := ctx.isNdk(ctx.Config())
+ isLlndk := ctx.isImplementationForLLNDKPublic()
// If NDK or PLATFORM library, check against previous version ABI.
if !ctx.useVndk() {
prevRefAbiDumpFile := getRefAbiDumpFile(ctx, strconv.Itoa(prevVersion), fileName)
if prevRefAbiDumpFile != nil {
library.prevSAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- prevRefAbiDumpFile, fileName, exportedHeaderFlags,
+ prevRefAbiDumpFile, fileName,
library.Properties.Header_abi_checker.Diff_flags, prevVersion,
Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), true)
+ isLlndk || isNdk, ctx.IsVndkExt(), true)
}
}
refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName)
if refAbiDumpFile != nil {
library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- refAbiDumpFile, fileName, exportedHeaderFlags,
+ refAbiDumpFile, fileName,
library.Properties.Header_abi_checker.Diff_flags,
/* unused if not previousVersionDiff */ 0,
Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), false)
+ isLlndk || isNdk, ctx.IsVndkExt(), false)
}
}
}
@@ -2451,11 +2599,12 @@
m := mctx.Module().(*Module)
isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary()
+ isImportedApiLibrary := m.isImportedApiLibrary()
modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
- if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
+ if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
// A stubs or LLNDK stubs variant.
c := m.(*Module)
c.sanitize = nil
@@ -2645,6 +2794,8 @@
Runtime_deps: linkerAttrs.runtimeDeps,
}
+ module.convertTidyAttributes(ctx, &commonAttrs.tidyAttributes)
+
var attrs interface{}
if isStatic {
commonAttrs.Deps.Add(baseAttributes.protoDependency)
@@ -2697,13 +2848,7 @@
Absolute_includes: compilerAttrs.absoluteIncludes,
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
- Strip: stripAttributes{
- Keep_symbols: linkerAttrs.stripKeepSymbols,
- Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: linkerAttrs.stripKeepSymbolsList,
- All: linkerAttrs.stripAll,
- None: linkerAttrs.stripNone,
- },
+ Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
Features: baseAttributes.features,
diff --git a/cc/library_headers.go b/cc/library_headers.go
index a683f58..1c4f354 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -15,6 +15,8 @@
package cc
import (
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
@@ -145,3 +147,118 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
}
+
+// Append .contribution suffix to input labels
+func apiBazelTargets(ll bazel.LabelList) bazel.LabelList {
+ labels := make([]bazel.Label, 0)
+ for _, l := range ll.Includes {
+ labels = append(labels, bazel.Label{
+ Label: android.ApiContributionTargetName(l.Label),
+ })
+ }
+ return bazel.MakeLabelList(labels)
+}
+
+func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ // cc_api_library_headers have a 1:1 mapping to arch/no-arch
+ // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps
+
+ // arch-agnostic includes
+ apiIncludes := getSystemApiIncludes(ctx, module)
+ // arch and os specific includes
+ archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module)
+ for _, arch := range allArches { // sorted iteration
+ archApiInclude := archApiIncludes[arch]
+ if !archApiInclude.isEmpty() {
+ createApiHeaderTarget(ctx, archApiInclude)
+ apiIncludes.addDep(archApiInclude.name)
+ }
+ }
+ // os==android includes
+ if !androidOsIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, androidOsIncludes)
+ apiIncludes.addDep(androidOsIncludes.name)
+ }
+
+ if !apiIncludes.isEmpty() {
+ // override the name from <mod>.systemapi.headers --> <mod>.contribution
+ apiIncludes.name = android.ApiContributionTargetName(module.Name())
+ createApiHeaderTarget(ctx, apiIncludes)
+ }
+}
+
+func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_library_headers",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: includes.name,
+ SkipData: proptools.BoolPtr(true),
+ },
+ &includes.attrs,
+ )
+}
+
+var (
+ allArches = []string{"arm", "arm64", "x86", "x86_64"}
+)
+
+type archApiIncludes map[string]apiIncludes
+
+func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) {
+ baseProps := bp2BuildParseBaseProps(ctx, module)
+ i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes)
+ archRet := archApiIncludes{}
+ for _, arch := range allArches {
+ includes := i.Includes.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ systemIncludes := i.SystemIncludes.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ deps := baseProps.deps.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ }
+ apiDeps := apiBazelTargets(deps)
+ if !apiDeps.IsEmpty() {
+ attrs.Deps = bazel.MakeLabelListAttribute(apiDeps)
+ }
+ apiIncludes := apiIncludes{
+ name: android.ApiContributionTargetName(module.Name()) + "." + arch,
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ Arch: proptools.StringPtr(arch),
+ },
+ }
+ archRet[arch] = apiIncludes
+ }
+
+ // apiIncludes for os == Android
+ androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid)
+ androidOsAttrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(
+ i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
+ ),
+ Export_system_includes: bazel.MakeStringListAttribute(
+ i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
+ ),
+ }
+ androidOsApiDeps := apiBazelTargets(androidOsDeps)
+ if !androidOsApiDeps.IsEmpty() {
+ androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps)
+ }
+ osRet := apiIncludes{
+ name: android.ApiContributionTargetName(module.Name()) + ".androidos",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: androidOsAttrs,
+ },
+ }
+ return archRet, osRet
+}
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 2ebb6ef..2fb21a3 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -15,6 +15,10 @@
package cc
import (
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/multitree"
)
@@ -26,10 +30,30 @@
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
+ ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
+}
- // cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
- ctx.RegisterModuleType("cc_api_stub_library", CcApiStubLibraryFactory)
- ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
+func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ apiLibrary, ok := m.linker.(*apiLibraryDecorator)
+ if !ok {
+ return
+ }
+
+ if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
+ // Add LLNDK dependencies
+ for _, variant := range apiLibrary.properties.Variants {
+ if variant == "llndk" {
+ variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
+ ctx.AddDependency(m, nil, variantName)
+ break
+ }
+ }
+ }
}
// 'cc_api_library' is a module type which is from the exported API surface
@@ -37,7 +61,8 @@
// offer a link to the module that generates shared library object from the
// map file.
type apiLibraryProperties struct {
- Src *string `android:"arch_variant"`
+ Src *string `android:"arch_variant"`
+ Variants []string
}
type apiLibraryDecorator struct {
@@ -59,11 +84,9 @@
module.compiler = nil
module.linker = apiLibraryDecorator
module.installer = nil
+ module.library = apiLibraryDecorator
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
- // Mark module as stub, so APEX would not include this stub in the package.
- module.library.setBuildStubs(true)
-
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -81,25 +104,79 @@
return basename + multitree.GetApiImportSuffix()
}
+// Export include dirs without checking for existence.
+// The directories are not guaranteed to exist during Soong analysis.
+func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
+ exporterProps := d.flagExporter.Properties
+ for _, dir := range exporterProps.Export_include_dirs {
+ d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
+ }
+ // system headers
+ for _, dir := range exporterProps.Export_system_include_dirs {
+ d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
+ }
+}
+
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
- // Export headers as system include dirs if specified. Mostly for libc
- if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
+ m, _ := ctx.Module().(*Module)
+
+ var in android.Path
+
+ if src := proptools.String(d.properties.Src); src != "" {
+ in = android.PathForModuleSrc(ctx, src)
+ }
+
+ // LLNDK variant
+ if m.UseVndk() && d.hasLLNDKStubs() {
+ apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
+
+ var mod android.Module
+
+ ctx.VisitDirectDeps(func(depMod android.Module) {
+ if depMod.Name() == apiVariantModule {
+ mod = depMod
+ }
+ })
+
+ if mod != nil {
+ variantMod, ok := mod.(*CcApiVariant)
+ if ok {
+ in = variantMod.Src()
+
+ // Copy LLDNK properties to cc_api_library module
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
+ variantMod.exportProperties.Export_headers...)
+
+ // Export headers as system include dirs if specified. Mostly for libc
+ if proptools.Bool(variantMod.exportProperties.Export_headers_as_system) {
+ d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
+ d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
+ }
+ }
+ }
}
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
- d.libraryDecorator.flagExporter.exportIncludes(ctx)
+ d.exportIncludes(ctx)
d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
- d.libraryDecorator.flagExporter.setProvider(ctx)
- in := android.PathForModuleSrc(ctx, *d.properties.Src)
+ if in == nil {
+ ctx.PropertyErrorf("src", "Unable to locate source property")
+ return nil
+ }
+
+ // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
+ // The .so file itself has an order-only dependency on the headers contributed by this library.
+ // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
+ d.libraryDecorator.reexportDeps(in)
+ d.libraryDecorator.flagExporter.setProvider(ctx)
d.unstrippedOutputFile = in
libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
@@ -123,6 +200,43 @@
return true
}
+func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+ m, ok := ctx.Module().(*Module)
+
+ if !ok {
+ return nil
+ }
+
+ if d.hasLLNDKStubs() && m.UseVndk() {
+ // LLNDK libraries only need a single stubs variant.
+ return []string{android.FutureApiLevel.String()}
+ }
+
+ // TODO(b/244244438) Create more version information for NDK and APEX variations
+ // NDK variants
+ if m.MinSdkVersion() == "" {
+ return nil
+ }
+
+ firstVersion, err := nativeApiLevelFromUser(ctx,
+ m.MinSdkVersion())
+
+ if err != nil {
+ return nil
+ }
+
+ return ndkLibraryVersions(ctx, firstVersion)
+}
+
+func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
+ for _, variant := range d.properties.Variants {
+ if strings.Contains(variant, "llndk") {
+ return true
+ }
+ }
+ return false
+}
+
// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
// header libraries. The module will replace any dependencies to existing
// original header libraries.
@@ -145,9 +259,6 @@
module.linker = apiHeadersDecorator
module.installer = nil
- // Mark module as stub, so APEX would not include this stub in the package.
- module.library.setBuildStubs(true)
-
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -170,135 +281,90 @@
return true
}
-func CcApiStubLibraryFactory() android.Module {
- module, decorator := NewLibrary(android.DeviceSupported)
- apiStubDecorator := &apiStubDecorator{
- libraryDecorator: decorator,
- }
- apiStubDecorator.BuildOnlyShared()
+type ccApiexportProperties struct {
+ Src *string `android:"arch_variant"`
+ Variant *string
+ Version *string
+}
- module.compiler = apiStubDecorator
- module.linker = apiStubDecorator
- module.installer = nil
- module.library = apiStubDecorator
- module.Properties.HideFromMake = true // TODO: remove
+type variantExporterProperties struct {
+ // Header directory or library to export
+ Export_headers []string
+
+ // Export all headers as system include
+ Export_headers_as_system *bool
+}
+
+type CcApiVariant struct {
+ android.ModuleBase
+
+ properties ccApiexportProperties
+ exportProperties variantExporterProperties
+
+ src android.Path
+}
+
+var _ android.Module = (*CcApiVariant)(nil)
+var _ android.ImageInterface = (*CcApiVariant)(nil)
+
+func CcApiVariantFactory() android.Module {
+ module := &CcApiVariant{}
+
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.exportProperties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- module.AddProperties(&module.Properties,
- &apiStubDecorator.properties,
- &apiStubDecorator.MutatedProperties,
- &apiStubDecorator.apiStubLibraryProperties)
return module
}
-type apiStubLiraryProperties struct {
- Imported_includes []string `android:"path"`
-}
+func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // No need to build
-type apiStubDecorator struct {
- *libraryDecorator
- properties libraryProperties
- apiStubLibraryProperties apiStubLiraryProperties
-}
-
-func (compiler *apiStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
- firstVersion := String(compiler.properties.First_version)
- return ndkLibraryVersions(ctx, android.ApiLevelOrPanic(ctx, firstVersion))
-}
-
-func (decorator *apiStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- if decorator.stubsVersion() == "" {
- decorator.setStubsVersion("current")
- } // TODO: fix
- symbolFile := String(decorator.properties.Symbol_file)
- nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
- android.ApiLevelOrPanic(ctx, decorator.stubsVersion()),
- "")
- return compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
-}
-
-func (decorator *apiStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
- decorator.reexportDirs(android.PathsForModuleSrc(ctx, decorator.apiStubLibraryProperties.Imported_includes)...)
- return decorator.libraryDecorator.link(ctx, flags, deps, objects)
-}
-
-func init() {
- pctx.HostBinToolVariable("gen_api_surface_build_files", "gen_api_surface_build_files")
-}
-
-type CcApiContribution struct {
- android.ModuleBase
- properties ccApiContributionProperties
-}
-
-type ccApiContributionProperties struct {
- Symbol_file *string `android:"path"`
- First_version *string
- Export_include_dir *string
-}
-
-func CcApiContributionFactory() android.Module {
- module := &CcApiContribution{}
- module.AddProperties(&module.properties)
- android.InitAndroidModule(module)
- return module
-}
-
-// Do some simple validations
-// Majority of the build rules will be created in the ctx of the api surface this module contributes to
-func (contrib *CcApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if contrib.properties.Symbol_file == nil {
- ctx.PropertyErrorf("symbol_file", "%v does not have symbol file", ctx.ModuleName())
+ if proptools.String(v.properties.Src) == "" {
+ ctx.PropertyErrorf("src", "src is a required property")
}
- if contrib.properties.First_version == nil {
- ctx.PropertyErrorf("first_version", "%v does not have first_version for stub variants", ctx.ModuleName())
+
+ // Skip the existence check of the stub prebuilt file.
+ // The file is not guaranteed to exist during Soong analysis.
+ // Build orchestrator will be responsible for creating a connected ninja graph.
+ v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), proptools.String(v.properties.Src))
+}
+
+func (v *CcApiVariant) Name() string {
+ version := proptools.String(v.properties.Version)
+ return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
+}
+
+func (v *CcApiVariant) Src() android.Path {
+ return v.src
+}
+
+func BuildApiVariantName(baseName string, variant string, version string) string {
+ names := []string{baseName, variant}
+ if version != "" {
+ names = append(names, version)
}
+
+ return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
}
-// Path is out/soong/.export/ but will be different in final multi-tree layout
-func outPathApiSurface(ctx android.ModuleContext, myModuleName string, pathComponent string) android.OutputPath {
- return android.PathForOutput(ctx, ".export", ctx.ModuleName(), myModuleName, pathComponent)
-}
+// Implement ImageInterface to generate image variants
+func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ var variations []string
+ platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
-func (contrib *CcApiContribution) CopyFilesWithTag(apiSurfaceContext android.ModuleContext) map[string]android.Paths {
- // copy map.txt for now
- // hardlinks cannot be created since nsjail creates a different mountpoint for out/
- myDir := apiSurfaceContext.OtherModuleDir(contrib)
- genMapTxt := outPathApiSurface(apiSurfaceContext, contrib.Name(), String(contrib.properties.Symbol_file))
- apiSurfaceContext.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Description: "import map.txt file",
- Input: android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Symbol_file)),
- Output: genMapTxt,
- })
-
- outputs := make(map[string]android.Paths)
- outputs["map"] = []android.Path{genMapTxt}
-
- if contrib.properties.Export_include_dir != nil {
- includeDir := android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Export_include_dir))
- outputs["export_include_dir"] = []android.Path{includeDir}
+ if proptools.String(v.properties.Variant) == "llndk" {
+ variations = append(variations, VendorVariationPrefix+platformVndkVersion)
+ variations = append(variations, ProductVariationPrefix+platformVndkVersion)
}
- return outputs
+
+ return variations
}
-
-var _ multitree.ApiContribution = (*CcApiContribution)(nil)
-
-/*
-func (contrib *CcApiContribution) GenerateBuildFiles(apiSurfaceContext android.ModuleContext) android.Paths {
- genAndroidBp := outPathApiSurface(apiSurfaceContext, contrib.Name(), "Android.bp")
-
- // generate Android.bp
- apiSurfaceContext.Build(pctx, android.BuildParams{
- Rule: genApiSurfaceBuildFiles,
- Description: "generate API surface build files",
- Outputs: []android.WritablePath{genAndroidBp},
- Args: map[string]string{
- "name": contrib.Name() + "." + apiSurfaceContext.ModuleName(), //e.g. liblog.ndk
- "symbol_file": String(contrib.properties.Symbol_file),
- "first_version": String(contrib.properties.First_version),
- },
- })
- return []android.Path{genAndroidBp}
+func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
-*/
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index cd06172..8ce74c4 100644
--- a/cc/library_stub_test.go
+++ b/cc/library_stub_test.go
@@ -21,94 +21,10 @@
"testing"
"android/soong/android"
- "android/soong/multitree"
"github.com/google/blueprint"
)
-func TestCcApiStubLibraryOutputFiles(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := prepareForCcTest.RunTestWithBp(t, bp)
- outputs := result.ModuleForTests("foo", "android_arm64_armv8-a_shared").AllOutputs()
- expected_file_suffixes := []string{".c", "stub.map", ".o", ".so"}
- for _, expected_file_suffix := range expected_file_suffixes {
- android.AssertBoolEquals(t, expected_file_suffix+" file not found in output", true, android.SuffixInList(outputs, expected_file_suffix))
- }
-}
-
-func TestCcApiStubLibraryVariants(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := prepareForCcTest.RunTestWithBp(t, bp)
- variants := result.ModuleVariantsForTests("foo")
- expected_variants := []string{"29", "30", "S", "Tiramisu"} //TODO: make this test deterministic by using fixtures
- for _, expected_variant := range expected_variants {
- android.AssertBoolEquals(t, expected_variant+" variant not found in foo", true, android.SubstringInList(variants, expected_variant))
- }
-}
-
-func TestCcLibraryUsesCcApiStubLibrary(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- cc_library {
- name: "foo_user",
- shared_libs: [
- "foo#29",
- ],
- }
-
- `
- prepareForCcTest.RunTestWithBp(t, bp)
-}
-
-func TestApiSurfaceOutputs(t *testing.T) {
- bp := `
- api_surface {
- name: "mysdk",
- contributions: [
- "foo",
- ],
- }
-
- cc_api_contribution {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := android.GroupFixturePreparers(
- prepareForCcTest,
- multitree.PrepareForTestWithApiSurface,
- ).RunTestWithBp(t, bp)
- mysdk := result.ModuleForTests("mysdk", "")
-
- actual_surface_inputs := mysdk.Rule("phony").BuildParams.Inputs.Strings()
- expected_file_suffixes := []string{"mysdk/foo/foo.map.txt"}
- for _, expected_file_suffix := range expected_file_suffixes {
- android.AssertBoolEquals(t, expected_file_suffix+" file not found in input", true, android.SuffixInList(actual_surface_inputs, expected_file_suffix))
- }
-
- // check args/inputs to rule
- /*api_surface_gen_rule_args := result.ModuleForTests("mysdk", "").Rule("genApiSurfaceBuildFiles").Args
- android.AssertStringEquals(t, "name", "foo.mysdk", api_surface_gen_rule_args["name"])
- android.AssertStringEquals(t, "symbol_file", "foo.map.txt", api_surface_gen_rule_args["symbol_file"])*/
-}
-
func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
t.Helper()
var found bool
@@ -325,3 +241,97 @@
android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
}
+
+func TestExportDirFromStubLibrary(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ export_include_dirs: ["source_include_dir"],
+ export_system_include_dirs: ["source_system_include_dir"],
+ vendor_available: true,
+ }
+ cc_api_library {
+ name: "libfoo",
+ export_include_dirs: ["stub_include_dir"],
+ export_system_include_dirs: ["stub_system_include_dir"],
+ vendor_available: true,
+ src: "libfoo.so",
+ }
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libfoo",
+ ],
+ header_libs: [],
+ }
+ // vendor binary
+ cc_binary {
+ name: "vendorbin",
+ vendor: true,
+ srcs: ["vendor.cc"],
+ shared_libs: ["libfoo"],
+ }
+ `
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+ vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
+ android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
+ android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
+ android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
+
+ vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
+ // Building the stub.so file first assembles its .h files in multi-tree out.
+ // These header files are required for compiling the other API domain (vendor in this case)
+ android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
+}
+
+func TestApiLibraryWithLlndkVariant(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "binfoo",
+ vendor: true,
+ srcs: ["binfoo.cc"],
+ shared_libs: ["libbar"],
+ }
+
+ cc_api_library {
+ name: "libbar",
+ // TODO(b/244244438) Remove src property once all variants are implemented.
+ src: "libbar.so",
+ vendor_available: true,
+ variants: [
+ "llndk",
+ ],
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "llndk",
+ src: "libbar_llndk.so",
+ export_headers: ["libbar_llndk_include"]
+ }
+
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libbar",
+ ],
+ header_libs: [],
+ }
+ `
+
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+
+ libfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
+ libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
+
+ android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
+ android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
+
+ libFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", libFooLibFlags, "libbar_llndk.so")
+
+ libFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", libFooCFlags, "-Ilibbar_llndk_include")
+}
diff --git a/cc/library_test.go b/cc/library_test.go
index 6d5eda2..2bc9967 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -259,6 +259,7 @@
SystemIncludes: []string{"system_include"},
Headers: []string{"foo.h"},
RootDynamicLibraries: []string{"foo.so"},
+ UnstrippedOutput: "foo_unstripped.so",
},
"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
CcObjectFiles: []string{"foo.o"},
@@ -294,6 +295,7 @@
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+ android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
diff --git a/cc/lto.go b/cc/lto.go
index 581856b..1afa1dd 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -91,6 +91,11 @@
return flags
}
+ // TODO(b/254713216): LTO doesn't work on riscv64 yet.
+ if ctx.Arch().ArchType == android.Riscv64 {
+ return flags
+ }
+
if lto.LTO(ctx) {
var ltoCFlag string
var ltoLdFlag string
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 06ded3f..d704e32 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -307,6 +307,7 @@
impl, ok := dep.(*Module)
if !ok {
ctx.ModuleErrorf("Implementation for stub is not correct module type")
+ return nil
}
output := impl.UnstrippedOutputFile()
if output == nil {
@@ -581,12 +582,12 @@
}
// Names of the cc_api_header targets in the bp2build workspace
-func (s *stubDecorator) apiHeaderLabels(ctx android.TopDownMutatorContext) bazel.LabelList {
+func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList {
addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string {
label := android.BazelModuleLabel(ctx, module)
return android.ApiContributionTargetName(label)
}
- return android.BazelLabelForModuleDepsWithFn(ctx, s.properties.Export_header_libs, addSuffix)
+ return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
}
func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
@@ -604,7 +605,7 @@
apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label
attrs.Api = *bazel.MakeLabelAttribute(apiLabel)
}
- apiHeaders := stubLibrary.apiHeaderLabels(ctx)
+ apiHeaders := apiHeaderLabels(ctx, stubLibrary.properties.Export_header_libs)
attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders)
apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName())
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 867c36c..1842e5a 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -33,7 +33,7 @@
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
- ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
+ ctx.RegisterModuleType("cc_prebuilt_binary", PrebuiltBinaryFactory)
}
type prebuiltLinkerInterface interface {
@@ -358,12 +358,12 @@
// TODO(b/228623543): The below is not entirely true until the bug is fixed. For now, both targets are always generated
// Implements bp2build for cc_prebuilt_library modules. This will generate:
-// - Only a prebuilt_library_static if the shared.enabled property is set to false across all variants.
-// - Only a prebuilt_library_shared if the static.enabled property is set to false across all variants
-// - Both a prebuilt_library_static and prebuilt_library_shared if the aforementioned properties are not false across
+// - Only a cc_prebuilt_library_static if the shared.enabled property is set to false across all variants.
+// - Only a cc_prebuilt_library_shared if the static.enabled property is set to false across all variants
+// - Both a cc_prebuilt_library_static and cc_prebuilt_library_shared if the aforementioned properties are not false across
// all variants
//
-// In all cases, prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
+// In all cases, cc_prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
prebuiltLibraryStaticBp2Build(ctx, module, true)
prebuiltLibrarySharedBp2Build(ctx, module)
@@ -380,8 +380,8 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_static.bzl",
+ Rule_class: "cc_prebuilt_library_static",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
@@ -403,8 +403,8 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_shared.bzl",
+ Rule_class: "cc_prebuilt_library_shared",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
@@ -668,15 +668,21 @@
}
// cc_prebuilt_binary installs a precompiled executable in srcs property in the
-// device's directory.
-func prebuiltBinaryFactory() android.Module {
+// device's directory, for both the host and device
+func PrebuiltBinaryFactory() android.Module {
module, _ := NewPrebuiltBinary(android.HostAndDeviceSupported)
return module.Init()
}
+type prebuiltBinaryBazelHandler struct {
+ module *Module
+ decorator *binaryDecorator
+}
+
func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module, binary := newBinary(hod, false)
+ module, binary := newBinary(hod, true)
module.compiler = nil
+ module.bazelHandler = &prebuiltBinaryBazelHandler{module, binary}
prebuilt := &prebuiltBinaryLinker{
binaryDecorator: binary,
@@ -690,6 +696,53 @@
return module, binary
}
+var _ BazelHandler = (*prebuiltBinaryBazelHandler)(nil)
+
+func (h *prebuiltBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (h *prebuiltBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ outputs, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+ if len(outputs) != 1 {
+ ctx.ModuleErrorf("Expected a single output for `%s`, but got:\n%v", label, outputs)
+ return
+ }
+ out := android.PathForBazelOut(ctx, outputs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+ h.module.maybeUnhideFromMake()
+}
+
+type bazelPrebuiltBinaryAttributes struct {
+ Src bazel.LabelAttribute
+ Strip stripAttributes
+}
+
+func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module)
+
+ var la linkerAttributes
+ la.convertStripProps(ctx, module)
+ attrs := &bazelPrebuiltBinaryAttributes{
+ Src: prebuiltAttrs.Src,
+ Strip: stripAttrsFromLinkerAttrs(&la),
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_prebuilt_binary",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_binary.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+}
+
type Sanitized struct {
None struct {
Srcs []string `android:"path,arch_variant"`
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 53cf781..95fa99e 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -683,3 +683,27 @@
}`
testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
}
+
+func TestPrebuiltBinaryWithBazel(t *testing.T) {
+ const bp = `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ bazel_module: { label: "//bin/foo:foo" },
+}`
+ const outBaseDir = "outputbase"
+ const expectedOut = outBaseDir + "/execroot/__main__/bin"
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outBaseDir,
+ LabelToOutputFiles: map[string][]string{"//bin/foo:foo": []string{"bin"}},
+ }
+ ctx := testCcWithConfig(t, config)
+ bin := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
+ out := bin.OutputFile()
+ if !out.Valid() {
+ t.Error("Invalid output file")
+ return
+ }
+ android.AssertStringEquals(t, "output file", expectedOut, out.String())
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 0b47f0e..d3fc221 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -511,6 +511,12 @@
s.Integer_overflow = nil
}
+ // TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
+ if ctx.Arch().ArchType == android.Riscv64 {
+ s.Cfi = nil
+ s.Diag.Cfi = nil
+ }
+
// Disable CFI for musl
if ctx.toolchain().Musl() {
s.Cfi = nil
@@ -613,6 +619,14 @@
return flags
}
+ // Currently unwinding through tagged frames for exceptions is broken, so disable memtag stack
+ // in that case, so we don't end up tagging those.
+ // TODO(b/174878242): Remove once https://r.android.com/2251926 is included in toolchain.
+ if android.InList("-fexceptions", flags.Local.CFlags) || android.InList("-fexceptions", flags.Global.CFlags) {
+ sanitize.Properties.Sanitize.Memtag_stack = nil
+ _, sanitize.Properties.Sanitizers = android.RemoveFromList("memtag-stack", sanitize.Properties.Sanitizers)
+ }
+
if Bool(sanitize.Properties.Sanitize.Address) {
if ctx.Arch().ArchType == android.Arm {
// Frame pointer based unwinder in ASan requires ARM frame setup.
@@ -1384,6 +1398,7 @@
// Determine the runtime library required
runtimeLibrary := ""
+ alwaysStaticRuntime := false
var extraStaticDeps []string
toolchain := c.toolchain(mctx)
if Bool(c.sanitize.Properties.Sanitize.Address) {
@@ -1408,8 +1423,15 @@
Bool(c.sanitize.Properties.Sanitize.Undefined) ||
Bool(c.sanitize.Properties.Sanitize.All_undefined) {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
- if c.staticBinary() {
+ if c.staticBinary() || toolchain.Musl() {
+ // Use a static runtime for static binaries.
+ // Also use a static runtime for musl to match
+ // what clang does for glibc. Otherwise dlopening
+ // libraries that depend on libclang_rt.ubsan_standalone.so
+ // fails with:
+ // Error relocating ...: initial-exec TLS resolves to dynamic definition
runtimeLibrary += ".static"
+ alwaysStaticRuntime = true
}
}
@@ -1453,7 +1475,7 @@
//
// Note that by adding dependency with {static|shared}DepTag, the lib is
// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
- if c.staticBinary() {
+ if c.staticBinary() || alwaysStaticRuntime {
addStaticDeps(runtimeLibrary)
addStaticDeps(extraStaticDeps...)
} else if !c.static() && !c.Header() {
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 48ac650..2393f3e 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -41,6 +41,7 @@
static_libs: [
"libstatic",
"libnoasan",
+ "libstatic_asan",
],
sanitize: {
address: true,
@@ -57,6 +58,7 @@
static_libs: [
"libstatic",
"libnoasan",
+ "libstatic_asan",
],
}
@@ -92,6 +94,15 @@
address: false,
}
}
+
+ cc_library_static {
+ name: "libstatic_asan",
+ host_supported: true,
+ sanitize: {
+ address: true,
+ }
+ }
+
`
result := android.GroupFixturePreparers(
@@ -125,6 +136,10 @@
// Static library that never uses asan.
libNoAsan := result.ModuleForTests("libnoasan", staticVariant)
+ // Static library that specifies asan
+ libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
+ libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
+
// expectSharedLinkDep verifies that the from module links against the to module as a
// shared library.
expectSharedLinkDep := func(from, to android.TestingModule) {
@@ -176,6 +191,7 @@
expectStaticLinkDep(binWithAsan, libStaticAsanVariant)
expectStaticLinkDep(binWithAsan, libNoAsan)
+ expectStaticLinkDep(binWithAsan, libStaticAsan)
expectInstallDep(binWithAsan, libShared)
expectInstallDep(binWithAsan, libAsan)
@@ -190,6 +206,7 @@
expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant)
expectStaticLinkDep(binNoAsan, libNoAsan)
+ expectStaticLinkDep(binNoAsan, libStaticAsanNoAsanVariant)
expectInstallDep(binNoAsan, libShared)
expectInstallDep(binNoAsan, libAsan)
diff --git a/cc/sdk.go b/cc/sdk.go
index a83e5ad..a0d196b 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -78,5 +78,7 @@
}
case *snapshotModule:
ctx.CreateVariations("")
+ case *CcApiVariant:
+ ctx.CreateVariations("")
}
}
diff --git a/cc/stl.go b/cc/stl.go
index 85a06da..6353a4a 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -139,6 +139,8 @@
return "libunwind"
}
+// Should be kept up to date with
+// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=46;drc=21771b671ae08565033768a6d3d151c54f887fa2
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
switch stl.Properties.SelectedStl {
case "libstdc++":
@@ -194,6 +196,8 @@
return deps
}
+// Should be kept up to date with
+// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=94;drc=5bc8e39d2637927dc57dd0850210d43d348a1341
func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
switch stl.Properties.SelectedStl {
case "libc++", "libc++_static":
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index 9bf07f2..94c8567 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -41,6 +41,7 @@
ALL_ARCHITECTURES = (
Arch('arm'),
Arch('arm64'),
+ Arch('riscv64'),
Arch('x86'),
Arch('x86_64'),
)
diff --git a/cc/test.go b/cc/test.go
index 715c537..536210b 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -643,6 +643,8 @@
Gtest bool
Isolated bool
+
+ tidyAttributes
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
@@ -676,6 +678,8 @@
}
}
+ m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
+
for _, propIntf := range m.GetProperties() {
if testLinkerProps, ok := propIntf.(*TestLinkerProperties); ok {
testBinaryAttrs.Gtest = proptools.BoolDefault(testLinkerProps.Gtest, true)
diff --git a/cc/tidy.go b/cc/tidy.go
index 2ba13ca..a3d548b 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -68,6 +68,7 @@
// Then, that old style usage will be obsolete and an error.
const NoWarningsAsErrorsInTidyFlags = true
+// keep this up to date with https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/clang_tidy.bzl
func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
CheckBadTidyFlags(ctx, "tidy_flags", tidy.Properties.Tidy_flags)
CheckBadTidyChecks(ctx, "tidy_checks", tidy.Properties.Tidy_checks)
@@ -79,9 +80,10 @@
// Some projects like external/* and vendor/* have clang-tidy disabled by default,
// unless they are enabled explicitly with the "tidy:true" property or
// when TIDY_EXTERNAL_VENDOR is set to true.
- if !ctx.Config().IsEnvTrue("TIDY_EXTERNAL_VENDOR") &&
- !proptools.Bool(tidy.Properties.Tidy) &&
- config.NoClangTidyForDir(ctx.ModuleDir()) {
+ if !proptools.Bool(tidy.Properties.Tidy) &&
+ config.NoClangTidyForDir(
+ ctx.Config().IsEnvTrue("TIDY_EXTERNAL_VENDOR"),
+ ctx.ModuleDir()) {
return flags
}
// If not explicitly disabled, set flags.Tidy to generate .tidy rules.
diff --git a/cmd/extract_apks/bundle_proto/Android.bp b/cmd/extract_apks/bundle_proto/Android.bp
new file mode 100644
index 0000000..e56c0fb
--- /dev/null
+++ b/cmd/extract_apks/bundle_proto/Android.bp
@@ -0,0 +1,13 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_library_host {
+ name: "config_proto",
+ srcs: [
+ "config.proto",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/cmd/extract_apks/bundle_proto/config.proto b/cmd/extract_apks/bundle_proto/config.proto
index d6fac03..946bd9a 100644
--- a/cmd/extract_apks/bundle_proto/config.proto
+++ b/cmd/extract_apks/bundle_proto/config.proto
@@ -26,6 +26,9 @@
ASSET_ONLY = 2;
}
BundleType type = 8;
+
+ // Configuration for locales.
+ Locales locales = 9;
}
message Bundletool {
@@ -40,6 +43,48 @@
// the name of the modules, and using forward slash ("/") as a name separator.
// Examples: "res/raw/**", "assets/**/*.uncompressed", etc.
repeated string uncompressed_glob = 1;
+
+ enum AssetModuleCompression {
+ UNSPECIFIED = 0;
+ // Assets are left uncompressed in the generated asset module.
+ UNCOMPRESSED = 1;
+ // Assets are compressed in the generated asset module.
+ // This option can be overridden at a finer granularity by specifying
+ // files or folders to keep uncompressed in `uncompressed_glob`.
+ // This option should only be used if the app is able to handle compressed
+ // asset module content at runtime (some runtime APIs may misbehave).
+ COMPRESSED = 2;
+ }
+
+ // Default compression strategy for install-time asset modules.
+ // If the compression strategy indicates to compress a file and the same file
+ // matches one of the `uncompressed_glob` values, the `uncompressed_glob`
+ // takes precedence (the file is left uncompressed in the generated APK).
+ //
+ // If unspecified, asset module content is left uncompressed in the
+ // generated asset modules.
+ //
+ // Note: this flag only configures the compression strategy for install-time
+ // asset modules; the content of on-demand and fast-follow asset modules is
+ // always kept uncompressed.
+ AssetModuleCompression install_time_asset_module_default_compression = 2;
+
+ enum ApkCompressionAlgorithm {
+ // Default in the current version of bundletool is zlib deflate algorithm
+ // with compression level 9 for the application's resources and compression
+ // level 6 for other entries.
+ //
+ // This is a good trade-off between size of final APK and size of patches
+ // which are used to update the application from previous to next version.
+ DEFAULT_APK_COMPRESSION_ALGORITHM = 0;
+
+ // 7zip implementation of deflate algorithm which gives smaller APK size
+ // but size of patches required to update the application are larger.
+ P7ZIP = 1;
+ }
+
+ // Compression algorithm which is used to compress entries in final APKs.
+ ApkCompressionAlgorithm apk_compression_algorithm = 3;
}
// Resources to keep in the master split.
@@ -55,12 +100,40 @@
// This is for uncompressing native libraries on M+ devices (L+ devices on
// instant apps).
UncompressNativeLibraries uncompress_native_libraries = 2;
- // This is for uncompressing dex files on P+ devices.
+ // This is for uncompressing dex files.
UncompressDexFiles uncompress_dex_files = 3;
// Configuration for the generation of standalone APKs.
// If no StandaloneConfig is set, the configuration is inherited from
// splits_config.
StandaloneConfig standalone_config = 4;
+
+ // Optimizations that are applied to resources.
+ ResourceOptimizations resource_optimizations = 5;
+
+ // Configuration for archiving the app.
+ StoreArchive store_archive = 6;
+}
+
+message ResourceOptimizations {
+ // Whether to use sparse encoding for resource tables.
+ // Resources in sparse resource table are accessed using a binary search tree.
+ // This decreases APK size at the cost of resource retrieval performance.
+ SparseEncoding sparse_encoding = 1;
+
+ enum SparseEncoding {
+ // Previously 'ENFORCED'. This option is deprecated because of issues found
+ // in Android O up to Android Sv2 and causes segfaults in
+ // Resources#getIdentifier.
+ reserved 1;
+ reserved "ENFORCED";
+
+ // Disables sparse encoding.
+ UNSPECIFIED = 0;
+ // Generates special APKs for Android SDK +32 with sparse resource tables.
+ // Devices with Android SDK below 32 will still receive APKs with regular
+ // resource tables.
+ VARIANT_FOR_SDK_32 = 2;
+ }
}
message UncompressNativeLibraries {
@@ -68,7 +141,39 @@
}
message UncompressDexFiles {
+ // A new variant with uncompressed dex will be generated. The sdk targeting
+ // of the variant is determined by 'uncompressed_dex_target_sdk'.
bool enabled = 1;
+
+ // If 'enabled' field is set, this will determine the sdk targeting of the
+ // generated variant.
+ UncompressedDexTargetSdk uncompressed_dex_target_sdk = 2;
+
+ enum UncompressedDexTargetSdk {
+ // Q+ variant will be generated.
+ UNSPECIFIED = 0;
+ // S+ variant will be generated.
+ SDK_31 = 1;
+ }
+}
+
+message StoreArchive {
+ // Archive is an app state that allows an official app store to reclaim device
+ // storage and disable app functionality temporarily until the user interacts
+ // with the app again. Upon interaction the latest available version of the
+ // app will be restored while leaving user data unaffected.
+ // Enabled by default.
+ bool enabled = 1;
+}
+
+message Locales {
+ // Instructs bundletool to generate locale config and inject it into
+ // AndroidManifest.xml. A locale is marked as supported by the application if
+ // there is at least one resource value in this locale. Be very careful with
+ // this setting because if some of your libraries expose resources in some
+ // locales which are not actually supported by your application it will mark
+ // this locale as supported. Disabled by default.
+ bool inject_locale_config = 1;
}
// Optimization configuration used to generate Split APKs.
@@ -82,8 +187,28 @@
repeated SplitDimension split_dimension = 1;
// Whether 64 bit libraries should be stripped from Standalone APKs.
bool strip_64_bit_libraries = 2;
+ // Dex merging strategy that should be applied to produce Standalone APKs.
+ DexMergingStrategy dex_merging_strategy = 3;
+
+ enum DexMergingStrategy {
+ // Strategy that does dex merging for applications that have minimum SDK
+ // below 21 to ensure dex files from all modules are merged into one or
+ // mainDexList is applied when merging into one dex is not possible. For
+ // applications with minSdk >= 21 dex files from all modules are copied into
+ // standalone APK as is because Android supports multiple dex files natively
+ // starting from Android 5.0.
+ MERGE_IF_NEEDED = 0;
+ // Requires to copy dex files from all modules into standalone APK as is.
+ // If an application supports SDKs below 21 this strategy puts
+ // responsibility of providing dex files compatible with legacy multidex on
+ // application developers.
+ NEVER_MERGE = 1;
+ }
}
+// BEGIN-INTERNAL
+// LINT.IfChange
+// END-INTERNAL
message SplitDimension {
enum Value {
UNSPECIFIED_VALUE = 0;
@@ -92,8 +217,9 @@
LANGUAGE = 3;
TEXTURE_COMPRESSION_FORMAT = 4;
// BEGIN-INTERNAL
- GRAPHICS_API = 5;
+ GRAPHICS_API = 5 [deprecated = true];
// END-INTERNAL
+ DEVICE_TIER = 6;
}
Value value = 1;
@@ -105,11 +231,14 @@
// the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1)
SuffixStripping suffix_stripping = 3;
}
+// BEGIN-INTERNAL
+// LINT.ThenChange(//depot/google3/wireless/android/vending/developer/proto/storage/app/apk_bundle.proto)
+// END-INTERNAL
message SuffixStripping {
// If set to 'true', indicates that the targeting suffix should be removed
- // from assets paths for this dimension when splits (or asset slices) are
- // generated.
+ // from assets paths for this dimension when splits (e.g: "asset packs") or
+ // standalone/universal APKs are generated.
// This only applies to assets.
// For example a folder with path "assets/level1_textures#tcf_etc1"
// would be outputted to "assets/level1_textures". File contents are
@@ -117,9 +246,9 @@
bool enabled = 1;
// The default suffix to be used for the cases where separate slices can't
- // be generated for this dimension. In the case of standalone/universal APKs
- // generation, stripping the suffix can lead to file name collisions. This
- // default suffix defines the directories to retain. The others are
+ // be generated for this dimension - typically for standalone or universal
+ // APKs.
+ // This default suffix defines the directories to retain. The others are
// discarded: standalone/universal APKs will contain only directories
// targeted at this value for the dimension.
//
@@ -135,6 +264,15 @@
message ApexConfig {
// Configuration for processing of APKs embedded in an APEX image.
repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1;
+
+ // Explicit list of supported ABIs.
+ // Default: See ApexBundleValidator.REQUIRED_ONE_OF_ABI_SETS
+ repeated SupportedAbiSet supported_abi_set = 2;
+}
+
+// Represents a set of ABIs which must be supported by a single APEX image.
+message SupportedAbiSet {
+ repeated string abi = 1;
}
message ApexEmbeddedApkConfig {
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 7cb8ab7..d8d5e5d 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -48,6 +48,10 @@
var outDir = flag.String("out", "", "path to store output directories (defaults to tmpdir under $OUT when empty)")
var alternateResultDir = flag.Bool("dist", false, "write select results to $DIST_DIR (or <out>/dist when empty)")
+var bazelMode = flag.Bool("bazel-mode", false, "use bazel for analysis of certain modules")
+var bazelModeStaging = flag.Bool("bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
+var bazelModeDev = flag.Bool("bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
+
var onlyConfig = flag.Bool("only-config", false, "Only run product config (not Soong or Kati)")
var onlySoong = flag.Bool("only-soong", false, "Only run product config and Soong (not Kati)")
@@ -214,6 +218,31 @@
return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
}
+func getBazelArg() string {
+ count := 0
+ str := ""
+ if *bazelMode {
+ count++
+ str = "--bazel-mode"
+ }
+ if *bazelModeStaging {
+ count++
+ str = "--bazel-mode-staging"
+ }
+ if *bazelModeDev {
+ count++
+ str = "--bazel-mode-dev"
+ }
+
+ if count > 1 {
+ // Can't set more than one
+ fmt.Errorf("Only one bazel mode is permitted to be set.")
+ os.Exit(1)
+ }
+
+ return str
+}
+
func main() {
stdio := terminal.StdioImpl{}
@@ -472,6 +501,11 @@
args = append(args, "--soong-only")
}
+ bazelStr := getBazelArg()
+ if bazelStr != "" {
+ args = append(args, bazelStr)
+ }
+
cmd := exec.Command(mpctx.SoongUi, args...)
cmd.Stdout = consoleLogWriter
cmd.Stderr = consoleLogWriter
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index 0e8ad05..ba0648d 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -207,6 +207,10 @@
return p.Packaging == "jar"
}
+func (p Pom) IsApk() bool {
+ return p.Packaging == "apk"
+}
+
func (p Pom) IsHostModule() bool {
return hostModuleNames.IsHostModule(p.GroupId, p.ArtifactId)
}
@@ -244,6 +248,8 @@
func (p Pom) ImportModuleType() string {
if p.IsAar() {
return "android_library_import"
+ } else if p.IsApk() {
+ return "android_app_import"
} else if p.IsHostOnly() {
return "java_import_host"
} else {
@@ -254,6 +260,8 @@
func (p Pom) BazelImportTargetType() string {
if p.IsAar() {
return "aar_import"
+ } else if p.IsApk() {
+ return "apk_import"
} else {
return "java_import"
}
@@ -262,6 +270,8 @@
func (p Pom) ImportProperty() string {
if p.IsAar() {
return "aars"
+ } else if p.IsApk() {
+ return "apk"
} else {
return "jars"
}
@@ -270,6 +280,8 @@
func (p Pom) BazelImportProperty() string {
if p.IsAar() {
return "aar"
+ } else if p.IsApk() {
+ return "apk"
} else {
return "jars"
}
@@ -493,8 +505,12 @@
var bpTemplate = template.Must(template.New("bp").Parse(`
{{.ImportModuleType}} {
name: "{{.BpName}}",
+ {{- if .IsApk}}
+ {{.ImportProperty}}: "{{.ArtifactFile}}",
+ {{- else}}
{{.ImportProperty}}: ["{{.ArtifactFile}}"],
sdk_version: "{{.SdkVersion}}",
+ {{- end}}
{{- if .Jetifier}}
jetifier: true,
{{- end}}
@@ -535,8 +551,14 @@
],
{{- end}}
{{- else if not .IsHostOnly}}
+ {{- if not .IsApk}}
min_sdk_version: "{{.DefaultMinSdkVersion}}",
{{- end}}
+ {{- end}}
+ {{- if .IsApk}}
+ presigned: true
+ {{- end}}
+
}
`))
@@ -995,7 +1017,7 @@
for _, pom := range poms {
var err error
- if staticDeps {
+ if staticDeps && !pom.IsApk() {
err = depsTemplate.Execute(buf, pom)
} else {
err = template.Execute(buf, pom)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 9f00fc3..3fed1a1 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io/ioutil"
@@ -55,6 +56,7 @@
bazelQueryViewDir string
bazelApiBp2buildDir string
bp2buildMarker string
+ symlinkForestMarker string
cmdlineArgs bootstrap.Args
)
@@ -85,9 +87,11 @@
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
flag.StringVar(&bazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
+ flag.StringVar(&symlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules")
+ flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
flag.BoolVar(&cmdlineArgs.BazelModeDev, "bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
// Flags that probably shouldn't be flags of soong_build but we haven't found
@@ -128,7 +132,9 @@
func newConfig(availableEnv map[string]string) android.Config {
var buildMode android.SoongBuildMode
- if bp2buildMarker != "" {
+ if symlinkForestMarker != "" {
+ buildMode = android.SymlinkForest
+ } else if bp2buildMarker != "" {
buildMode = android.Bp2build
} else if bazelQueryViewDir != "" {
buildMode = android.GenerateQueryView
@@ -142,6 +148,8 @@
buildMode = android.BazelDevMode
} else if cmdlineArgs.BazelMode {
buildMode = android.BazelProdMode
+ } else if cmdlineArgs.BazelModeStaging {
+ buildMode = android.BazelStagingMode
} else {
buildMode = android.AnalysisNoBazel
}
@@ -167,21 +175,26 @@
return configuration.BazelContext.InvokeBazel(configuration)
}
ctx.SetBeforePrepareBuildActionsHook(bazelHook)
-
ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, ctx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ bazelPaths, err := readBazelPaths(configuration)
+ if err != nil {
+ panic("Bazel deps file not found: " + err.Error())
+ }
+ ninjaDeps = append(ninjaDeps, bazelPaths...)
+
globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
- writeDepFile(cmdlineArgs.OutFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
}
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
func runQueryView(queryviewDir, queryviewMarker string, configuration android.Config, ctx *android.Context) {
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
- codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
+ codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.QueryView)
absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
if err := createBazelWorkspace(codegenContext, absoluteQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
@@ -222,7 +235,7 @@
ninjaDeps = append(ninjaDeps, globs...)
// Run codegen to generate BUILD files
- codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.ApiBp2build)
+ codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.ApiBp2build)
absoluteApiBp2buildDir := shared.JoinPath(topDir, bazelApiBp2buildDir)
if err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
@@ -231,7 +244,7 @@
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
// Create soong_injection repository
- soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CodegenMetrics{})
+ soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CreateCodegenMetrics())
absoluteSoongInjectionDir := shared.JoinPath(topDir, configuration.SoongOutDir(), bazel.SoongInjectionDirName)
for _, file := range soongInjectionFiles {
writeReadOnlyFile(absoluteSoongInjectionDir, file)
@@ -245,16 +258,15 @@
// Create the symlink forest
symlinkDeps := bp2build.PlantSymlinkForest(
- configuration,
+ configuration.IsEnvTrue("BP2BUILD_VERBOSE"),
topDir,
workspace,
bazelApiBp2buildDir,
- ".",
excludes)
ninjaDeps = append(ninjaDeps, symlinkDeps...)
workspaceMarkerFile := workspace + ".marker"
- writeDepFile(workspaceMarkerFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(workspaceMarkerFile, ctx.EventHandler, ninjaDeps)
touch(shared.JoinPath(topDir, workspaceMarkerFile))
return workspaceMarkerFile
}
@@ -281,7 +293,7 @@
return ret
}
-func writeMetrics(configuration android.Config, eventHandler metrics.EventHandler, metricsDir string) {
+func writeMetrics(configuration android.Config, eventHandler *metrics.EventHandler, metricsDir string) {
if len(metricsDir) < 1 {
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
os.Exit(1)
@@ -321,7 +333,7 @@
return bootstrap.GlobFileListFiles(globDir)
}
-func writeDepFile(outputFile string, eventHandler metrics.EventHandler, ninjaDeps []string) {
+func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDeps []string) {
eventHandler.Begin("ninja_deps")
defer eventHandler.End("ninja_deps")
depFile := shared.JoinPath(topDir, outputFile+".d")
@@ -335,11 +347,14 @@
// doChosenActivity runs Soong for a specific activity, like bp2build, queryview
// or the actual Soong build for the build.ninja file. Returns the top level
// output file of the specific activity.
-func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string) string {
- if configuration.BuildMode == android.Bp2build {
+func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, metricsDir string) string {
+ if configuration.BuildMode == android.SymlinkForest {
+ runSymlinkForestCreation(configuration, extraNinjaDeps, metricsDir)
+ return symlinkForestMarker
+ } else if configuration.BuildMode == android.Bp2build {
// Run the alternate pipeline of bp2build mutators and singleton to convert
// Blueprint to BUILD files before everything else.
- runBp2Build(configuration, extraNinjaDeps)
+ runBp2Build(configuration, extraNinjaDeps, metricsDir)
return bp2buildMarker
} else if configuration.IsMixedBuildsEnabled() {
runMixedModeBuild(configuration, ctx, extraNinjaDeps)
@@ -365,11 +380,11 @@
if configuration.BuildMode == android.GenerateQueryView {
queryviewMarkerFile := bazelQueryViewDir + ".marker"
runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
- writeDepFile(queryviewMarkerFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
return queryviewMarkerFile
} else if configuration.BuildMode == android.GenerateModuleGraph {
writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
- writeDepFile(moduleGraphFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(moduleGraphFile, ctx.EventHandler, ninjaDeps)
return moduleGraphFile
} else if configuration.BuildMode == android.GenerateDocFile {
// TODO: we could make writeDocs() return the list of documentation files
@@ -379,12 +394,12 @@
fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
os.Exit(1)
}
- writeDepFile(docFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(docFile, ctx.EventHandler, ninjaDeps)
return docFile
} else {
// The actual output (build.ninja) was written in the RunBlueprint() call
// above
- writeDepFile(cmdlineArgs.OutFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
}
}
@@ -450,10 +465,10 @@
ctx := newContext(configuration)
ctx.EventHandler.Begin("soong_build")
- finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps)
+ finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir)
ctx.EventHandler.End("soong_build")
- writeMetrics(configuration, *ctx.EventHandler, logDir)
+ writeMetrics(configuration, ctx.EventHandler, logDir)
writeUsedEnvironmentFile(configuration, finalOutputFile)
}
@@ -470,12 +485,19 @@
os.Exit(1)
}
- err = ioutil.WriteFile(path, data, 0666)
- if err != nil {
+ if preexistingData, err := os.ReadFile(path); err != nil {
+ if !os.IsNotExist(err) {
+ fmt.Fprintf(os.Stderr, "error reading used environment file '%s': %s\n", usedEnvFile, err)
+ os.Exit(1)
+ }
+ } else if bytes.Equal(preexistingData, data) {
+ // used environment file is unchanged
+ return
+ }
+ if err = os.WriteFile(path, data, 0666); err != nil {
fmt.Fprintf(os.Stderr, "error writing used environment file '%s': %s\n", usedEnvFile, err)
os.Exit(1)
}
-
// Touch the output file so that it's not older than the file we just
// wrote. We can't write the environment file earlier because one an access
// new environment variables while writing it.
@@ -583,12 +605,69 @@
}
}
+// This could in theory easily be separated into a binary that generically
+// merges two directories into a symlink tree. The main obstacle is that this
+// function currently depends on both Bazel-specific knowledge (the existence
+// of bazel-* symlinks) and configuration (the set of BUILD.bazel files that
+// should and should not be kept)
+//
+// Ideally, bp2build would write a file that contains instructions to the
+// symlink tree creation binary. Then the latter would not need to depend on
+// the very heavy-weight machinery of soong_build .
+func runSymlinkForestCreation(configuration android.Config, extraNinjaDeps []string, metricsDir string) {
+ eventHandler := &metrics.EventHandler{}
+
+ var ninjaDeps []string
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
+ workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
+
+ excludes := bazelArtifacts()
+
+ if outDir[0] != '/' {
+ excludes = append(excludes, outDir)
+ }
+
+ existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
+ os.Exit(1)
+ }
+
+ pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
+ excludes = append(excludes, pathsToIgnoredBuildFiles...)
+ excludes = append(excludes, getTemporaryExcludes()...)
+
+ // PlantSymlinkForest() returns all the directories that were readdir()'ed.
+ // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
+ // or file created/deleted under it would trigger an update of the symlink
+ // forest.
+ eventHandler.Do("symlink_forest", func() {
+ symlinkForestDeps := bp2build.PlantSymlinkForest(
+ configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
+ ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
+ })
+
+ writeDepFile(symlinkForestMarker, eventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, symlinkForestMarker))
+ codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
+ if codegenMetrics == nil {
+ m := bp2build.CreateCodegenMetrics()
+ codegenMetrics = &m
+ } else {
+ //TODO (usta) we cannot determine if we loaded a stale file, i.e. from an unrelated prior
+ //invocation of codegen. We should simply use a separate .pb file
+ }
+ writeBp2BuildMetrics(codegenMetrics, eventHandler, metricsDir)
+}
+
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
- var codegenMetrics bp2build.CodegenMetrics
- eventHandler := metrics.EventHandler{}
+func runBp2Build(configuration android.Config, extraNinjaDeps []string, metricsDir string) {
+ var codegenMetrics *bp2build.CodegenMetrics
+ eventHandler := &metrics.EventHandler{}
eventHandler.Do("bp2build", func() {
// Register an alternate set of singletons and mutators for bazel
@@ -600,21 +679,11 @@
bp2buildCtx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
bp2buildCtx.RegisterForBazelConversion()
+ bp2buildCtx.SetModuleListFile(cmdlineArgs.ModuleListFile)
var ninjaDeps []string
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- // The bp2build process is a purely functional process that only depends on
- // Android.bp files. It must not depend on the values of per-build product
- // configurations or variables, since those will generate different BUILD
- // files based on how the user has configured their tree.
- bp2buildCtx.SetModuleListFile(cmdlineArgs.ModuleListFile)
- if modulePaths, err := bp2buildCtx.ListModulePaths("."); err != nil {
- panic(err)
- } else {
- ninjaDeps = append(ninjaDeps, modulePaths...)
- }
-
// Run the loading and analysis pipeline to prepare the graph of regular
// Modules parsed from Android.bp files, and the BazelTargetModules mapped
// from the regular Modules.
@@ -629,46 +698,14 @@
// Run the code-generation phase to convert BazelTargetModules to BUILD files
// and print conversion codegenMetrics to the user.
- codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
+ codegenContext := bp2build.NewCodegenContext(configuration, bp2buildCtx, bp2build.Bp2Build)
eventHandler.Do("codegen", func() {
codegenMetrics = bp2build.Codegen(codegenContext)
})
- generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
- workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
-
- excludes := bazelArtifacts()
-
- if outDir[0] != '/' {
- excludes = append(excludes, outDir)
- }
-
- existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
- os.Exit(1)
- }
-
- pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
- excludes = append(excludes, pathsToIgnoredBuildFiles...)
-
- excludes = append(excludes, getTemporaryExcludes()...)
-
- // PlantSymlinkForest() returns all the directories that were readdir()'ed.
- // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
- // or file created/deleted under it would trigger an update of the symlink
- // forest.
- eventHandler.Do("symlink_forest", func() {
- symlinkForestDeps := bp2build.PlantSymlinkForest(
- configuration, topDir, workspaceRoot, generatedRoot, ".", excludes)
- ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
- })
-
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
writeDepFile(bp2buildMarker, eventHandler, ninjaDeps)
-
- // Create an empty bp2build marker file.
touch(shared.JoinPath(topDir, bp2buildMarker))
})
@@ -678,24 +715,32 @@
if configuration.IsEnvTrue("BP2BUILD_VERBOSE") {
codegenMetrics.Print()
}
- writeBp2BuildMetrics(&codegenMetrics, configuration, eventHandler)
+ writeBp2BuildMetrics(codegenMetrics, eventHandler, metricsDir)
}
// Write Bp2Build metrics into $LOG_DIR
-func writeBp2BuildMetrics(codegenMetrics *bp2build.CodegenMetrics,
- configuration android.Config, eventHandler metrics.EventHandler) {
+func writeBp2BuildMetrics(codegenMetrics *bp2build.CodegenMetrics, eventHandler *metrics.EventHandler, metricsDir string) {
for _, event := range eventHandler.CompletedEvents() {
- codegenMetrics.Events = append(codegenMetrics.Events,
- &bp2build_metrics_proto.Event{
- Name: event.Id,
- StartTime: uint64(event.Start.UnixNano()),
- RealTime: event.RuntimeNanoseconds(),
- })
+ codegenMetrics.AddEvent(&bp2build_metrics_proto.Event{
+ Name: event.Id,
+ StartTime: uint64(event.Start.UnixNano()),
+ RealTime: event.RuntimeNanoseconds(),
+ })
}
- metricsDir := configuration.Getenv("LOG_DIR")
if len(metricsDir) < 1 {
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating bp2build metrics: LOG_DIR\n")
os.Exit(1)
}
codegenMetrics.Write(metricsDir)
}
+
+func readBazelPaths(configuration android.Config) ([]string, error) {
+ depsPath := configuration.Getenv("BAZEL_DEPS_FILE")
+
+ data, err := os.ReadFile(depsPath)
+ if err != nil {
+ return nil, err
+ }
+ paths := strings.Split(strings.TrimSpace(string(data)), "\n")
+ return paths, nil
+}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index b06e4fe..19166d2 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -132,8 +132,13 @@
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))
+ // Create and start a new metric record.
+ met := metrics.New()
+ met.SetBuildDateTime(buildStarted)
+ met.SetBuildCommand(os.Args)
+
// Attach a new logger instance to the terminal output.
- log := logger.New(output)
+ log := logger.NewWithMetrics(output, met)
defer log.Cleanup()
// Create a context to simplify the program termination process.
@@ -144,11 +149,6 @@
trace := tracer.New(log)
defer trace.Close()
- // Create and start a new metric record.
- met := metrics.New()
- met.SetBuildDateTime(buildStarted)
- met.SetBuildCommand(os.Args)
-
// Create a new Status instance, which manages action counts and event output channels.
stat := &status.Status{}
defer stat.Finish()
@@ -281,7 +281,7 @@
if flags.NArg() != 1 {
flags.Usage()
- os.Exit(1)
+ ctx.Fatalf("Invalid usage")
}
varName := flags.Arg(0)
@@ -341,7 +341,7 @@
if flags.NArg() != 0 {
flags.Usage()
- os.Exit(1)
+ ctx.Fatalf("Invalid usage")
}
vars := strings.Fields(*varsStr)
@@ -502,7 +502,7 @@
fmt.Fprintln(writer, "!")
fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
fmt.Fprintln(writer, "")
- ctx.Fatal("done")
+ ctx.Fatal("Invalid argument")
}
if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
@@ -513,7 +513,7 @@
fmt.Fprintln(writer, "!")
fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
fmt.Fprintln(writer, "")
- ctx.Fatal("done")
+ ctx.Fatal("Invalid environment")
}
build.Build(ctx, config)
diff --git a/compliance/build_license_metadata/build_license_metadata.go b/compliance/build_license_metadata/build_license_metadata.go
index 53d2407..fb4b784 100644
--- a/compliance/build_license_metadata/build_license_metadata.go
+++ b/compliance/build_license_metadata/build_license_metadata.go
@@ -66,6 +66,7 @@
packageName := flags.String("p", "", "license package name")
moduleType := newMultiString(flags, "mt", "module type")
+ moduleName := flags.String("mn", "", "module name")
kinds := newMultiString(flags, "k", "license kinds")
moduleClass := newMultiString(flags, "mc", "module class")
conditions := newMultiString(flags, "c", "license conditions")
@@ -83,6 +84,7 @@
metadata := license_metadata_proto.LicenseMetadata{}
metadata.PackageName = proto.String(*packageName)
+ metadata.ModuleName = proto.String(*moduleName)
metadata.ModuleTypes = *moduleType
metadata.ModuleClasses = *moduleClass
metadata.IsContainer = proto.Bool(*isContainer)
diff --git a/compliance/license_metadata_proto/license_metadata.pb.go b/compliance/license_metadata_proto/license_metadata.pb.go
index 44dbc78..69aa377 100644
--- a/compliance/license_metadata_proto/license_metadata.pb.go
+++ b/compliance/license_metadata_proto/license_metadata.pb.go
@@ -14,8 +14,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.27.1
-// protoc v3.19.0
+// protoc-gen-go v1.28.0
+// protoc v3.12.4
// source: license_metadata.proto
package license_metadata_proto
@@ -40,7 +40,9 @@
unknownFields protoimpl.UnknownFields
// package_name identifies the source package. License texts are named relative to the package name.
- PackageName *string `protobuf:"bytes,1,opt,name=package_name,json=packageName" json:"package_name,omitempty"`
+ PackageName *string `protobuf:"bytes,1,opt,name=package_name,json=packageName" json:"package_name,omitempty"`
+ // module_name identifies the target
+ ModuleName *string `protobuf:"bytes,14,opt,name=module_name,json=moduleName" json:"module_name,omitempty"`
ModuleTypes []string `protobuf:"bytes,2,rep,name=module_types,json=moduleTypes" json:"module_types,omitempty"`
ModuleClasses []string `protobuf:"bytes,3,rep,name=module_classes,json=moduleClasses" json:"module_classes,omitempty"`
// projects identifies the git project(s) containing the associated source code.
@@ -104,6 +106,13 @@
return ""
}
+func (x *LicenseMetadata) GetModuleName() string {
+ if x != nil && x.ModuleName != nil {
+ return *x.ModuleName
+ }
+ return ""
+}
+
func (x *LicenseMetadata) GetModuleTypes() []string {
if x != nil {
return x.ModuleTypes
@@ -311,52 +320,54 @@
0x0a, 0x16, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x22, 0x8a, 0x04, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
+ 0x22, 0xab, 0x04, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x65,
- 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x23, 0x0a,
- 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18, 0x05,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x69, 0x6e,
- 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f,
- 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11,
- 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x78,
- 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
- 0x65, 0x54, 0x65, 0x78, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e,
- 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
- 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x69,
- 0x6c, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x12,
- 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a,
- 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x0b, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e,
- 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x73, 0x74,
- 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d,
- 0x61, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x04,
- 0x64, 0x65, 0x70, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70,
- 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x50, 0x0a,
- 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x66,
- 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x66, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
- 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68, 0x22,
- 0x4b, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70, 0x65,
- 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x6e,
- 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x31, 0x5a, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6f,
- 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
- 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x23,
+ 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18,
+ 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x69,
+ 0x6e, 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x11, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65,
+ 0x78, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69,
+ 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75,
+ 0x69, 0x6c, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74,
+ 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x43,
+ 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x0b, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65,
+ 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x4d, 0x61, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3f, 0x0a,
+ 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65,
+ 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x50,
+ 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09,
+ 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x08, 0x66, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68,
+ 0x22, 0x4b, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70,
+ 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61,
+ 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x31, 0x5a,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63,
+ 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
+ 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/compliance/license_metadata_proto/license_metadata.proto b/compliance/license_metadata_proto/license_metadata.proto
index 1b4f34f..61f8126 100644
--- a/compliance/license_metadata_proto/license_metadata.proto
+++ b/compliance/license_metadata_proto/license_metadata.proto
@@ -21,6 +21,9 @@
// package_name identifies the source package. License texts are named relative to the package name.
optional string package_name = 1;
+ // module_name identifies the target
+ optional string module_name = 14;
+
repeated string module_types = 2;
repeated string module_classes = 3;
@@ -54,6 +57,9 @@
// deps lists the license metadata files depended on.
repeated AnnotatedDependency deps = 13;
+
+ // next id: 15
+
}
// InstallMap messages describe the mapping from an input filesystem file to the path to the file
diff --git a/compliance/project_metadata_proto/Android.bp b/compliance/project_metadata_proto/Android.bp
new file mode 100644
index 0000000..56e76e7
--- /dev/null
+++ b/compliance/project_metadata_proto/Android.bp
@@ -0,0 +1,27 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "project_metadata_proto",
+ pkgPath: "android/soong/compliance/project_metadata_proto",
+ srcs: ["project_metadata.pb.go"],
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+}
diff --git a/compliance/project_metadata_proto/project_metadata.pb.go b/compliance/project_metadata_proto/project_metadata.pb.go
new file mode 100644
index 0000000..529159c
--- /dev/null
+++ b/compliance/project_metadata_proto/project_metadata.pb.go
@@ -0,0 +1,765 @@
+// 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.
+
+// A proto definition used to parse METADATA file in third party projects.
+
+// This proto will only contain fields and values used by android compliance.
+// It is not intended to be the formal definition of METADATA file.
+
+// See google3/third_party/metadata.proto if you need to add more stuff to
+// match upstream. Do not add new fields and values here. Add them upstream
+// when necessary, and copy them here.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.0
+// protoc v3.12.4
+// source: project_metadata.proto
+
+package project_metadata_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// License type that identifies how the packages may be used. See
+// go/thirdpartylicenses for full explanation of each license type.
+type LicenseType int32
+
+const (
+ LicenseType_BY_EXCEPTION_ONLY LicenseType = 1
+ LicenseType_NOTICE LicenseType = 2
+ LicenseType_PERMISSIVE LicenseType = 3
+ LicenseType_RECIPROCAL LicenseType = 4
+ LicenseType_RESTRICTED_IF_STATICALLY_LINKED LicenseType = 5
+ LicenseType_RESTRICTED LicenseType = 6
+ LicenseType_UNENCUMBERED LicenseType = 7
+)
+
+// Enum value maps for LicenseType.
+var (
+ LicenseType_name = map[int32]string{
+ 1: "BY_EXCEPTION_ONLY",
+ 2: "NOTICE",
+ 3: "PERMISSIVE",
+ 4: "RECIPROCAL",
+ 5: "RESTRICTED_IF_STATICALLY_LINKED",
+ 6: "RESTRICTED",
+ 7: "UNENCUMBERED",
+ }
+ LicenseType_value = map[string]int32{
+ "BY_EXCEPTION_ONLY": 1,
+ "NOTICE": 2,
+ "PERMISSIVE": 3,
+ "RECIPROCAL": 4,
+ "RESTRICTED_IF_STATICALLY_LINKED": 5,
+ "RESTRICTED": 6,
+ "UNENCUMBERED": 7,
+ }
+)
+
+func (x LicenseType) Enum() *LicenseType {
+ p := new(LicenseType)
+ *p = x
+ return p
+}
+
+func (x LicenseType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (LicenseType) Descriptor() protoreflect.EnumDescriptor {
+ return file_project_metadata_proto_enumTypes[0].Descriptor()
+}
+
+func (LicenseType) Type() protoreflect.EnumType {
+ return &file_project_metadata_proto_enumTypes[0]
+}
+
+func (x LicenseType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *LicenseType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = LicenseType(num)
+ return nil
+}
+
+// Deprecated: Use LicenseType.Descriptor instead.
+func (LicenseType) EnumDescriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+type URL_Type int32
+
+const (
+ // The homepage for the package. For example, "https://bazel.io/". This URL
+ // is optional, but encouraged to help disambiguate similarly named packages
+ // or to get more information about the package. This is especially helpful
+ // when no other URLs provide human readable resources (such as git:// or
+ // sso:// URLs).
+ URL_HOMEPAGE URL_Type = 1
+ // The URL of the archive containing the source code for the package, for
+ // example a zip or tgz file.
+ URL_ARCHIVE URL_Type = 2
+ // The URL of the upstream git repository this package is retrieved from.
+ // For example:
+ // - https://github.com/git/git.git
+ // - git://git.kernel.org/pub/scm/git/git.git
+ //
+ // Use of a git URL requires that the package "version" value must specify a
+ // specific git tag or revision.
+ URL_GIT URL_Type = 3
+ // The URL of the upstream SVN repository this package is retrieved from.
+ // For example:
+ // - http://llvm.org/svn/llvm-project/llvm/
+ //
+ // Use of an SVN URL requires that the package "version" value must specify
+ // a specific SVN tag or revision.
+ URL_SVN URL_Type = 7
+ // The URL of the upstream mercurial repository this package is retrieved
+ // from. For example:
+ // - https://mercurial-scm.org/repo/evolve
+ //
+ // Use of a mercurial URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ URL_HG URL_Type = 8
+ // The URL of the upstream darcs repository this package is retrieved
+ // from. For example:
+ // - https://hub.darcs.net/hu.dwim/hu.dwim.util
+ //
+ // Use of a DARCS URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ URL_DARCS URL_Type = 9
+ // The URL of the upstream piper location. This is primarily used when a
+ // package is being migrated into third_party from elsewhere in piper, or
+ // when a package is being newly developed in third_party. For newly
+ // developed packages, the PIPER URL should reference the package itself
+ // (e.g. "http://google3/third_party/my/package")
+ URL_PIPER URL_Type = 4
+ // A URL that does not fit any other type. This may also indicate that the
+ // source code was received via email or some other out-of-band way. This is
+ // most commonly used with commercial software received directly from the
+ // vendor. In the case of email, the URL value can be used to provide
+ // additional information about how it was received.
+ URL_OTHER URL_Type = 11
+ // The URL identifying where the local copy of the package source code can
+ // be found.
+ //
+ // Typically, the metadata files describing a package reside in the same
+ // directory as the source code for the package. In a few rare cases where
+ // they are separate, the LOCAL_SOURCE URL identifies where to find the
+ // source code. This only describes where to find the local copy of the
+ // source; there should always be an additional URL describing where the
+ // package was retrieved from.
+ //
+ // Examples:
+ // - http://google3/third_party/java_src/gerritcodereview/gerrit/
+ // - https://android.googlesource.com/platform/external/apache-http/
+ URL_LOCAL_SOURCE URL_Type = 6
+)
+
+// Enum value maps for URL_Type.
+var (
+ URL_Type_name = map[int32]string{
+ 1: "HOMEPAGE",
+ 2: "ARCHIVE",
+ 3: "GIT",
+ 7: "SVN",
+ 8: "HG",
+ 9: "DARCS",
+ 4: "PIPER",
+ 11: "OTHER",
+ 6: "LOCAL_SOURCE",
+ }
+ URL_Type_value = map[string]int32{
+ "HOMEPAGE": 1,
+ "ARCHIVE": 2,
+ "GIT": 3,
+ "SVN": 7,
+ "HG": 8,
+ "DARCS": 9,
+ "PIPER": 4,
+ "OTHER": 11,
+ "LOCAL_SOURCE": 6,
+ }
+)
+
+func (x URL_Type) Enum() *URL_Type {
+ p := new(URL_Type)
+ *p = x
+ return p
+}
+
+func (x URL_Type) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (URL_Type) Descriptor() protoreflect.EnumDescriptor {
+ return file_project_metadata_proto_enumTypes[1].Descriptor()
+}
+
+func (URL_Type) Type() protoreflect.EnumType {
+ return &file_project_metadata_proto_enumTypes[1]
+}
+
+func (x URL_Type) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *URL_Type) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = URL_Type(num)
+ return nil
+}
+
+// Deprecated: Use URL_Type.Descriptor instead.
+func (URL_Type) EnumDescriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{2, 0}
+}
+
+type Metadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Name of this API/package.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // A short description (a few lines) of the package. It will be
+ // included on the summary page.
+ // Example: "Handles location lookups, throttling, batching, etc."
+ Description *string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
+ // Specifies additional data about third-party packages.
+ ThirdParty *ThirdParty `protobuf:"bytes,13,opt,name=third_party,json=thirdParty" json:"third_party,omitempty"`
+}
+
+func (x *Metadata) Reset() {
+ *x = Metadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Metadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Metadata) ProtoMessage() {}
+
+func (x *Metadata) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[0]
+ 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 Metadata.ProtoReflect.Descriptor instead.
+func (*Metadata) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Metadata) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *Metadata) GetDescription() string {
+ if x != nil && x.Description != nil {
+ return *x.Description
+ }
+ return ""
+}
+
+func (x *Metadata) GetThirdParty() *ThirdParty {
+ if x != nil {
+ return x.ThirdParty
+ }
+ return nil
+}
+
+type ThirdParty struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // URL(s) associated with the package.
+ //
+ // At a minimum, all packages must specify a URL which identifies where it
+ // came from, containing a type of: ARCHIVE, GIT, PIPER, or OTHER. Typically,
+ // a package should contain only a single URL from these types. Occasionally,
+ // a package may be broken across multiple archive files for whatever reason,
+ // in which case having multiple ARCHIVE URLs is okay. However, this should
+ // not be used to combine different logical packages that are versioned and
+ // possibly licensed differently.
+ Url []*URL `protobuf:"bytes,1,rep,name=url" json:"url,omitempty"`
+ // The package version. In order of preference, this should contain:
+ // - If the package comes from Git or another source control system,
+ // a specific tag or revision in source control, such as "r123" or
+ // "58e27d2". This MUST NOT be a mutable ref such as a branch name.
+ // - a released package version such as "1.0", "2.3-beta", etc.
+ // - the date the package was retrieved, formatted as "As of YYYY-MM-DD".
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ // The date of the change in which the package was last upgraded from
+ // upstream.
+ // This should only identify package upgrades from upstream, not local
+ // modifications. This may identify the date of either the original or
+ // merged change.
+ //
+ // Note: this is NOT the date that this version of the package was released
+ // externally.
+ LastUpgradeDate *Date `protobuf:"bytes,10,opt,name=last_upgrade_date,json=lastUpgradeDate" json:"last_upgrade_date,omitempty"`
+ // License type that identifies how the package may be used. See
+ // go/thirdpartylicenses for instructions on selecting the appropriate type.
+ LicenseType *LicenseType `protobuf:"varint,4,opt,name=license_type,json=licenseType,enum=project_metadata.LicenseType" json:"license_type,omitempty"`
+ // Description of local changes that have been made to the package. This does
+ // not need to (and in most cases should not) attempt to include an exhaustive
+ // list of all changes, but may instead direct readers to review the local
+ // commit history, a collection of patch files, a separate README.md (or
+ // similar) document, etc.
+ // Note: Use of this field to store IDs of advisories fixed with a backported
+ // patch is deprecated, use "security.mitigated_security_patch" instead.
+ LocalModifications *string `protobuf:"bytes,6,opt,name=local_modifications,json=localModifications" json:"local_modifications,omitempty"`
+ // The URL for any public mirror created for compliance purposes.
+ // See go/thirdpartylicenses#reciprocal policy for more details.
+ ComplianceMirrorUrl *string `protobuf:"bytes,12,opt,name=compliance_mirror_url,json=complianceMirrorUrl" json:"compliance_mirror_url,omitempty"`
+ // The homepage for the package. This will eventually replace
+ // `url { type: HOMEPAGE }`
+ Homepage *string `protobuf:"bytes,14,opt,name=homepage" json:"homepage,omitempty"`
+}
+
+func (x *ThirdParty) Reset() {
+ *x = ThirdParty{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ThirdParty) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ThirdParty) ProtoMessage() {}
+
+func (x *ThirdParty) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[1]
+ 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 ThirdParty.ProtoReflect.Descriptor instead.
+func (*ThirdParty) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ThirdParty) GetUrl() []*URL {
+ if x != nil {
+ return x.Url
+ }
+ return nil
+}
+
+func (x *ThirdParty) GetVersion() string {
+ if x != nil && x.Version != nil {
+ return *x.Version
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetLastUpgradeDate() *Date {
+ if x != nil {
+ return x.LastUpgradeDate
+ }
+ return nil
+}
+
+func (x *ThirdParty) GetLicenseType() LicenseType {
+ if x != nil && x.LicenseType != nil {
+ return *x.LicenseType
+ }
+ return LicenseType_BY_EXCEPTION_ONLY
+}
+
+func (x *ThirdParty) GetLocalModifications() string {
+ if x != nil && x.LocalModifications != nil {
+ return *x.LocalModifications
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetComplianceMirrorUrl() string {
+ if x != nil && x.ComplianceMirrorUrl != nil {
+ return *x.ComplianceMirrorUrl
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetHomepage() string {
+ if x != nil && x.Homepage != nil {
+ return *x.Homepage
+ }
+ return ""
+}
+
+// URL associated with a third-party package.
+type URL struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The type of resource this URL identifies.
+ Type *URL_Type `protobuf:"varint,1,opt,name=type,enum=project_metadata.URL_Type" json:"type,omitempty"`
+ // The actual URL value. URLs should be absolute and start with 'http://' or
+ // 'https://' (or occasionally 'git://' or 'ftp://' where appropriate).
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+}
+
+func (x *URL) Reset() {
+ *x = URL{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *URL) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*URL) ProtoMessage() {}
+
+func (x *URL) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[2]
+ 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 URL.ProtoReflect.Descriptor instead.
+func (*URL) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *URL) GetType() URL_Type {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return URL_HOMEPAGE
+}
+
+func (x *URL) GetValue() string {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return ""
+}
+
+// Represents a whole or partial calendar date, such as a birthday. The time of
+// day and time zone are either specified elsewhere or are insignificant. The
+// date is relative to the Gregorian Calendar. This can represent one of the
+// following:
+//
+// - A full date, with non-zero year, month, and day values.
+// - A month and day, with a zero year (for example, an anniversary).
+// - A year on its own, with a zero month and a zero day.
+// - A year and month, with a zero day (for example, a credit card expiration
+// date).
+type Date struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Year of the date. Must be from 1 to 9999, or 0 to specify a date without
+ // a year.
+ Year *int32 `protobuf:"varint,1,opt,name=year" json:"year,omitempty"`
+ // Month of a year. Must be from 1 to 12, or 0 to specify a year without a
+ // month and day.
+ Month *int32 `protobuf:"varint,2,opt,name=month" json:"month,omitempty"`
+ // Day of a month. Must be from 1 to 31 and valid for the year and month, or 0
+ // to specify a year by itself or a year and month where the day isn't
+ // significant.
+ Day *int32 `protobuf:"varint,3,opt,name=day" json:"day,omitempty"`
+}
+
+func (x *Date) Reset() {
+ *x = Date{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Date) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Date) ProtoMessage() {}
+
+func (x *Date) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[3]
+ 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 Date.ProtoReflect.Descriptor instead.
+func (*Date) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Date) GetYear() int32 {
+ if x != nil && x.Year != nil {
+ return *x.Year
+ }
+ return 0
+}
+
+func (x *Date) GetMonth() int32 {
+ if x != nil && x.Month != nil {
+ return *x.Month
+ }
+ return 0
+}
+
+func (x *Date) GetDay() int32 {
+ if x != nil && x.Day != nil {
+ return *x.Day
+ }
+ return 0
+}
+
+var File_project_metadata_proto protoreflect.FileDescriptor
+
+var file_project_metadata_proto_rawDesc = []byte{
+ 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7f, 0x0a, 0x08, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0b,
+ 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52,
+ 0x0a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x22, 0xd6, 0x02, 0x0a, 0x0a,
+ 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x27, 0x0a, 0x03, 0x75, 0x72,
+ 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x03,
+ 0x75, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a,
+ 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x64, 0x61,
+ 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+ 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x65,
+ 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x44, 0x61, 0x74,
+ 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x6f, 0x64,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e,
+ 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x4d,
+ 0x69, 0x72, 0x72, 0x6f, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x6d, 0x65,
+ 0x70, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x6d, 0x65,
+ 0x70, 0x61, 0x67, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x2e, 0x0a, 0x04,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
+ 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x52,
+ 0x4c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x22, 0x6e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4f,
+ 0x4d, 0x45, 0x50, 0x41, 0x47, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x52, 0x43, 0x48,
+ 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x49, 0x54, 0x10, 0x03, 0x12, 0x07,
+ 0x0a, 0x03, 0x53, 0x56, 0x4e, 0x10, 0x07, 0x12, 0x06, 0x0a, 0x02, 0x48, 0x47, 0x10, 0x08, 0x12,
+ 0x09, 0x0a, 0x05, 0x44, 0x41, 0x52, 0x43, 0x53, 0x10, 0x09, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x49,
+ 0x50, 0x45, 0x52, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x0b,
+ 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
+ 0x10, 0x06, 0x22, 0x42, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x79, 0x65,
+ 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x79, 0x65, 0x61, 0x72, 0x12, 0x14,
+ 0x0a, 0x05, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x03, 0x64, 0x61, 0x79, 0x2a, 0x97, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x59, 0x5f, 0x45, 0x58, 0x43,
+ 0x45, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x0a, 0x0a,
+ 0x06, 0x4e, 0x4f, 0x54, 0x49, 0x43, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52,
+ 0x4d, 0x49, 0x53, 0x53, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x43,
+ 0x49, 0x50, 0x52, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53,
+ 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49,
+ 0x43, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e,
+ 0x0a, 0x0a, 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x10,
+ 0x0a, 0x0c, 0x55, 0x4e, 0x45, 0x4e, 0x43, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x45, 0x44, 0x10, 0x07,
+ 0x42, 0x31, 0x5a, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
+ 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f,
+ 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_project_metadata_proto_rawDescOnce sync.Once
+ file_project_metadata_proto_rawDescData = file_project_metadata_proto_rawDesc
+)
+
+func file_project_metadata_proto_rawDescGZIP() []byte {
+ file_project_metadata_proto_rawDescOnce.Do(func() {
+ file_project_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_project_metadata_proto_rawDescData)
+ })
+ return file_project_metadata_proto_rawDescData
+}
+
+var file_project_metadata_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_project_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_project_metadata_proto_goTypes = []interface{}{
+ (LicenseType)(0), // 0: project_metadata.LicenseType
+ (URL_Type)(0), // 1: project_metadata.URL.Type
+ (*Metadata)(nil), // 2: project_metadata.Metadata
+ (*ThirdParty)(nil), // 3: project_metadata.ThirdParty
+ (*URL)(nil), // 4: project_metadata.URL
+ (*Date)(nil), // 5: project_metadata.Date
+}
+var file_project_metadata_proto_depIdxs = []int32{
+ 3, // 0: project_metadata.Metadata.third_party:type_name -> project_metadata.ThirdParty
+ 4, // 1: project_metadata.ThirdParty.url:type_name -> project_metadata.URL
+ 5, // 2: project_metadata.ThirdParty.last_upgrade_date:type_name -> project_metadata.Date
+ 0, // 3: project_metadata.ThirdParty.license_type:type_name -> project_metadata.LicenseType
+ 1, // 4: project_metadata.URL.type:type_name -> project_metadata.URL.Type
+ 5, // [5:5] is the sub-list for method output_type
+ 5, // [5:5] is the sub-list for method input_type
+ 5, // [5:5] is the sub-list for extension type_name
+ 5, // [5:5] is the sub-list for extension extendee
+ 0, // [0:5] is the sub-list for field type_name
+}
+
+func init() { file_project_metadata_proto_init() }
+func file_project_metadata_proto_init() {
+ if File_project_metadata_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_project_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Metadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ThirdParty); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*URL); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Date); 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_project_metadata_proto_rawDesc,
+ NumEnums: 2,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_project_metadata_proto_goTypes,
+ DependencyIndexes: file_project_metadata_proto_depIdxs,
+ EnumInfos: file_project_metadata_proto_enumTypes,
+ MessageInfos: file_project_metadata_proto_msgTypes,
+ }.Build()
+ File_project_metadata_proto = out.File
+ file_project_metadata_proto_rawDesc = nil
+ file_project_metadata_proto_goTypes = nil
+ file_project_metadata_proto_depIdxs = nil
+}
diff --git a/compliance/project_metadata_proto/project_metadata.proto b/compliance/project_metadata_proto/project_metadata.proto
new file mode 100644
index 0000000..94cc516
--- /dev/null
+++ b/compliance/project_metadata_proto/project_metadata.proto
@@ -0,0 +1,225 @@
+// 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.
+
+// A proto definition used to parse METADATA file in third party projects.
+
+// This proto will only contain fields and values used by android compliance.
+// It is not intended to be the formal definition of METADATA file.
+
+// See google3/third_party/metadata.proto if you need to add more stuff to
+// match upstream. Do not add new fields and values here. Add them upstream
+// when necessary, and copy them here.
+
+syntax = "proto2"; // As long as upstream is proto2...
+
+package project_metadata;
+option go_package = "android/soong/compliance/project_metadata_proto";
+
+// Definitions for project metadata. (go/thirdparty/metadata)
+
+// Special naming conventions:
+// Repeated fields should have singular names (instead of plural).
+
+message Metadata {
+ // Name of this API/package.
+ optional string name = 1;
+
+ // A short description (a few lines) of the package. It will be
+ // included on the summary page.
+ // Example: "Handles location lookups, throttling, batching, etc."
+ optional string description = 3;
+
+ // Specifies additional data about third-party packages.
+ optional ThirdParty third_party = 13;
+}
+
+message ThirdParty {
+ // The name and description for the package should be specified using the top
+ // level fields in MetaData above
+ //
+ // Description should only specify a short description (a few lines) of the
+ // packages. Instructions for maintainers or similar information should be
+ // specified in BUILD comments, a separate README.md file, etc.
+
+ // URL(s) associated with the package.
+ //
+ // At a minimum, all packages must specify a URL which identifies where it
+ // came from, containing a type of: ARCHIVE, GIT, PIPER, or OTHER. Typically,
+ // a package should contain only a single URL from these types. Occasionally,
+ // a package may be broken across multiple archive files for whatever reason,
+ // in which case having multiple ARCHIVE URLs is okay. However, this should
+ // not be used to combine different logical packages that are versioned and
+ // possibly licensed differently.
+ repeated URL url = 1;
+
+ // The package version. In order of preference, this should contain:
+ // - If the package comes from Git or another source control system,
+ // a specific tag or revision in source control, such as "r123" or
+ // "58e27d2". This MUST NOT be a mutable ref such as a branch name.
+ // - a released package version such as "1.0", "2.3-beta", etc.
+ // - the date the package was retrieved, formatted as "As of YYYY-MM-DD".
+ optional string version = 2;
+
+ // The date of the change in which the package was last upgraded from
+ // upstream.
+ // This should only identify package upgrades from upstream, not local
+ // modifications. This may identify the date of either the original or
+ // merged change.
+ //
+ // Note: this is NOT the date that this version of the package was released
+ // externally.
+ optional Date last_upgrade_date = 10;
+
+ // License type that identifies how the package may be used. See
+ // go/thirdpartylicenses for instructions on selecting the appropriate type.
+ optional LicenseType license_type = 4;
+
+ // Description of local changes that have been made to the package. This does
+ // not need to (and in most cases should not) attempt to include an exhaustive
+ // list of all changes, but may instead direct readers to review the local
+ // commit history, a collection of patch files, a separate README.md (or
+ // similar) document, etc.
+ // Note: Use of this field to store IDs of advisories fixed with a backported
+ // patch is deprecated, use "security.mitigated_security_patch" instead.
+ optional string local_modifications = 6;
+
+ // The URL for any public mirror created for compliance purposes.
+ // See go/thirdpartylicenses#reciprocal policy for more details.
+ optional string compliance_mirror_url = 12;
+
+ // The homepage for the package. This will eventually replace
+ // `url { type: HOMEPAGE }`
+ optional string homepage = 14;
+}
+
+// URL associated with a third-party package.
+message URL {
+ enum Type {
+ // The homepage for the package. For example, "https://bazel.io/". This URL
+ // is optional, but encouraged to help disambiguate similarly named packages
+ // or to get more information about the package. This is especially helpful
+ // when no other URLs provide human readable resources (such as git:// or
+ // sso:// URLs).
+ HOMEPAGE = 1;
+
+ // The URL of the archive containing the source code for the package, for
+ // example a zip or tgz file.
+ ARCHIVE = 2;
+
+ // The URL of the upstream git repository this package is retrieved from.
+ // For example:
+ // - https://github.com/git/git.git
+ // - git://git.kernel.org/pub/scm/git/git.git
+ //
+ // Use of a git URL requires that the package "version" value must specify a
+ // specific git tag or revision.
+ GIT = 3;
+
+ // The URL of the upstream SVN repository this package is retrieved from.
+ // For example:
+ // - http://llvm.org/svn/llvm-project/llvm/
+ //
+ // Use of an SVN URL requires that the package "version" value must specify
+ // a specific SVN tag or revision.
+ SVN = 7;
+
+ // The URL of the upstream mercurial repository this package is retrieved
+ // from. For example:
+ // - https://mercurial-scm.org/repo/evolve
+ //
+ // Use of a mercurial URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ HG = 8;
+
+ // The URL of the upstream darcs repository this package is retrieved
+ // from. For example:
+ // - https://hub.darcs.net/hu.dwim/hu.dwim.util
+ //
+ // Use of a DARCS URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ DARCS = 9;
+
+ // The URL of the upstream piper location. This is primarily used when a
+ // package is being migrated into third_party from elsewhere in piper, or
+ // when a package is being newly developed in third_party. For newly
+ // developed packages, the PIPER URL should reference the package itself
+ // (e.g. "http://google3/third_party/my/package")
+ PIPER = 4;
+
+ // A URL that does not fit any other type. This may also indicate that the
+ // source code was received via email or some other out-of-band way. This is
+ // most commonly used with commercial software received directly from the
+ // vendor. In the case of email, the URL value can be used to provide
+ // additional information about how it was received.
+ OTHER = 11;
+
+ // The URL identifying where the local copy of the package source code can
+ // be found.
+ //
+ // Typically, the metadata files describing a package reside in the same
+ // directory as the source code for the package. In a few rare cases where
+ // they are separate, the LOCAL_SOURCE URL identifies where to find the
+ // source code. This only describes where to find the local copy of the
+ // source; there should always be an additional URL describing where the
+ // package was retrieved from.
+ //
+ // Examples:
+ // - http://google3/third_party/java_src/gerritcodereview/gerrit/
+ // - https://android.googlesource.com/platform/external/apache-http/
+ LOCAL_SOURCE = 6;
+ }
+
+ // The type of resource this URL identifies.
+ optional Type type = 1;
+
+ // The actual URL value. URLs should be absolute and start with 'http://' or
+ // 'https://' (or occasionally 'git://' or 'ftp://' where appropriate).
+ optional string value = 2;
+}
+
+// License type that identifies how the packages may be used. See
+// go/thirdpartylicenses for full explanation of each license type.
+enum LicenseType {
+ BY_EXCEPTION_ONLY = 1;
+ NOTICE = 2;
+ PERMISSIVE = 3;
+ RECIPROCAL = 4;
+ RESTRICTED_IF_STATICALLY_LINKED = 5;
+ RESTRICTED = 6;
+ UNENCUMBERED = 7;
+}
+
+
+// Represents a whole or partial calendar date, such as a birthday. The time of
+// day and time zone are either specified elsewhere or are insignificant. The
+// date is relative to the Gregorian Calendar. This can represent one of the
+// following:
+//
+// * A full date, with non-zero year, month, and day values.
+// * A month and day, with a zero year (for example, an anniversary).
+// * A year on its own, with a zero month and a zero day.
+// * A year and month, with a zero day (for example, a credit card expiration
+// date).
+message Date {
+ // Year of the date. Must be from 1 to 9999, or 0 to specify a date without
+ // a year.
+ optional int32 year = 1;
+ // Month of a year. Must be from 1 to 12, or 0 to specify a year without a
+ // month and day.
+ optional int32 month = 2;
+ // Day of a month. Must be from 1 to 31 and valid for the year and month, or 0
+ // to specify a year by itself or a year and month where the day isn't
+ // significant.
+ optional int32 day = 3;
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index eb248bb..5e5769b 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -151,6 +151,8 @@
// If there's a Java fuzzer with JNI, a different version of Jazzer would
// need to be added to the fuzzer package than one without JNI
IsJni *bool `json:"is_jni,omitempty"`
+ // List of modules for monitoring coverage drops in directories (e.g. "libicu")
+ Target_modules []string `json:"target_modules,omitempty"`
}
type FuzzFrameworks struct {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index d4ed363..14895c9 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -875,7 +875,7 @@
type genRuleProperties struct {
// names of the output files that will be generated
- Out []string `android:"arch_variant"`
+ Out []string
}
type bazelGenruleAttributes struct {
@@ -893,11 +893,27 @@
tools_prop.Append(tool_files_prop)
tools := bazel.MakeLabelListAttribute(tools_prop)
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs))
+ srcs := bazel.LabelListAttribute{}
+ srcs_labels := bazel.LabelList{}
+ // Only cc_genrule is arch specific
+ if ctx.ModuleType() == "cc_genrule" {
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &generatorProperties{}) {
+ for config, props := range configToProps {
+ if props, ok := props.(*generatorProperties); ok {
+ labels := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
+ srcs_labels.Append(labels)
+ srcs.SetSelectValue(axis, config, labels)
+ }
+ }
+ }
+ } else {
+ srcs_labels = android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ srcs = bazel.MakeLabelListAttribute(srcs_labels)
+ }
var allReplacements bazel.LabelList
allReplacements.Append(tools.Value)
- allReplacements.Append(srcs.Value)
+ allReplacements.Append(bazel.FirstUniqueBazelLabelList(srcs_labels))
// Replace in and out variables with $< and $@
var cmd string
diff --git a/go.mod b/go.mod
index 8c1a9f0..5f0b91a 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,12 @@
replace github.com/google/go-cmp v0.5.5 => ../../external/go-cmp
-// Indirect dep from go-cmp
-exclude golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
+require prebuilts/bazel/common/proto/analysis_v2 v0.0.0
+
+replace prebuilts/bazel/common/proto/analysis_v2 => ../../prebuilts/bazel/common/proto/analysis_v2
+
+require prebuilts/bazel/common/proto/build v0.0.0 // indirect
+
+replace prebuilts/bazel/common/proto/build => ../../prebuilts/bazel/common/proto/build
go 1.18
diff --git a/java/androidmk.go b/java/androidmk.go
index cd86880..42b4ef1 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -139,6 +139,7 @@
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "null-suite")
androidMkWriteTestData(j.jniFilePaths, entries)
+ androidMkWriteTestData(android.Paths{j.implementationJarFile}, entries)
})
return entriesList
}
diff --git a/java/app.go b/java/app.go
index bbd9d2d..2a51e10 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1486,22 +1486,8 @@
*bazelAapt
Deps bazel.LabelListAttribute
Custom_package *string
- Certificate *bazel.Label
- Certificate_name *string
-}
-
-// ParseCertificateToAttribute splits the certificate prop into a certificate
-// label attribute or a certificate_name string attribute.
-func ParseCertificateToAttribute(ctx android.TopDownMutatorContext, certificate *string) (*string, *bazel.Label) {
- var certificateLabel *bazel.Label
- certificateName := proptools.StringDefault(certificate, "")
- certModule := android.SrcIsModule(certificateName)
- if certModule != "" {
- c := android.BazelLabelForModuleDepSingle(ctx, certificateName)
- certificateLabel = &c
- certificate = nil
- }
- return certificate, certificateLabel
+ Certificate bazel.LabelAttribute
+ Certificate_name bazel.StringAttribute
}
// ConvertWithBp2build is used to convert android_app to Bazel.
@@ -1513,7 +1499,8 @@
aapt := a.convertAaptAttrsWithBp2Build(ctx)
- certificateName, certificate := ParseCertificateToAttribute(ctx, a.overridableAppProperties.Certificate)
+ certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
+
attrs := &bazelAndroidAppAttributes{
commonAttrs,
aapt,
diff --git a/java/app_import.go b/java/app_import.go
index 6e603c9..8c1e19c 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -500,7 +500,18 @@
type AndroidTestImport struct {
AndroidAppImport
- testProperties testProperties
+ testProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test
+ Data []string `android:"path"`
+
+ // Install the test into a folder named for the module in all test suites.
+ Per_testcase_directory *bool
+ }
testImportProperties androidTestImportProperties
diff --git a/java/app_set.go b/java/app_set.go
index d99fadb..d8c2a8d 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -90,9 +90,10 @@
}
var TargetCpuAbi = map[string]string{
- "arm": "ARMEABI_V7A",
- "arm64": "ARM64_V8A",
- "riscv64": "RISCV64",
+ "arm": "ARMEABI_V7A",
+ "arm64": "ARM64_V8A",
+ // TODO: use "RISCV64" when that is supported in bundles
+ "riscv64": "ARM64_V8A",
"x86": "X86",
"x86_64": "X86_64",
}
diff --git a/java/base.go b/java/base.go
index bcb7226..602e8d8 100644
--- a/java/base.go
+++ b/java/base.go
@@ -190,7 +190,7 @@
// constructing a new module.
type DeviceProperties struct {
// If not blank, set to the version of the sdk to compile against.
- // Defaults to private.
+ // Defaults to an empty string, which compiles the module against the private platform APIs.
// Values are of one of the following forms:
// 1) numerical API level, "current", "none", or "core_platform"
// 2) An SDK kind with an API level: "<sdk kind>_<API level>"
@@ -447,9 +447,11 @@
// installed file for hostdex copy
hostdexInstallFile android.InstallPath
- // list of .java files and srcjars that was passed to javac
- compiledJavaSrcs android.Paths
- compiledSrcJars android.Paths
+ // list of unique .java and .kt source files
+ uniqueSrcFiles android.Paths
+
+ // list of srcjars that was passed to javac
+ compiledSrcJars android.Paths
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
@@ -591,6 +593,8 @@
return android.Paths{j.outputFile}, nil
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
+ case ".hjar":
+ return android.Paths{j.headerJarFile}, nil
case ".proguard_map":
if j.dexer.proguardDictionary.Valid() {
return android.Paths{j.dexer.proguardDictionary.Path()}, nil
@@ -1078,15 +1082,26 @@
jarName := ctx.ModuleName() + ".jar"
- javaSrcFiles := srcFiles.FilterByExt(".java")
- var uniqueSrcFiles android.Paths
+ var uniqueJavaFiles android.Paths
set := make(map[string]bool)
- for _, v := range javaSrcFiles {
+ for _, v := range srcFiles.FilterByExt(".java") {
if _, found := set[v.String()]; !found {
set[v.String()] = true
- uniqueSrcFiles = append(uniqueSrcFiles, v)
+ uniqueJavaFiles = append(uniqueJavaFiles, v)
}
}
+ var uniqueKtFiles android.Paths
+ for _, v := range srcFiles.FilterByExt(".kt") {
+ if _, found := set[v.String()]; !found {
+ set[v.String()] = true
+ uniqueKtFiles = append(uniqueKtFiles, v)
+ }
+ }
+
+ var uniqueSrcFiles android.Paths
+ uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
+ uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
+ j.uniqueSrcFiles = uniqueSrcFiles
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
@@ -1094,7 +1109,7 @@
// is used to run all of the annotation processors.
disableTurbine := deps.disableTurbine
- // Collect .java files for AIDEGen
+ // Collect .java and .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
var kotlinJars android.Paths
@@ -1132,12 +1147,7 @@
flags.kotlincFlags += "$kotlincFlags"
}
- var kotlinSrcFiles android.Paths
- kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
- kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
-
- // Collect .kt files for AIDEGen
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+ // Collect common .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
@@ -1150,7 +1160,7 @@
// Use kapt for annotation processing
kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
- kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
srcJars = append(srcJars, kaptSrcJar)
kotlinJars = append(kotlinJars, kaptResJar)
// Disable annotation processing in javac, it's already been handled by kapt
@@ -1160,7 +1170,7 @@
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
@@ -1185,8 +1195,6 @@
jars := append(android.Paths(nil), kotlinJars...)
- // Store the list of .java files that was passed to javac
- j.compiledJavaSrcs = uniqueSrcFiles
j.compiledSrcJars = srcJars
enableSharding := false
@@ -1201,12 +1209,12 @@
// with sharding enabled. See: b/77284273.
}
headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
if ctx.Failed() {
return
}
}
- if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
+ if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 {
hasErrorproneableFiles := false
for _, ext := range j.sourceExtensions {
if ext != ".proto" && ext != ".aidl" {
@@ -1231,7 +1239,7 @@
errorproneFlags := enableErrorproneFlags(flags)
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- transformJavaToClasses(ctx, errorprone, -1, uniqueSrcFiles, srcJars, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1243,8 +1251,8 @@
}
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
- if len(uniqueSrcFiles) > 0 {
- shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
+ if len(uniqueJavaFiles) > 0 {
+ shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize)
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
@@ -1257,7 +1265,7 @@
jars = append(jars, classes)
}
} else {
- classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
+ classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
jars = append(jars, classes)
}
if ctx.Failed() {
diff --git a/java/builder.go b/java/builder.go
index c0fadd4..b1b9a4a 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -83,9 +83,9 @@
_ = pctx.VariableFunc("kytheCuJavaSourceMax",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuJavaSourceMax() })
_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
- // Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
- // "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
- // to field java.nio.Buffer.address"
+ // Run it with several --add-exports to allow the classes in the
+ // com.google.devtools.kythe.extractors.java.standalone package access the packages in the
+ // jdk.compiler compiler module. Long live Java modules.
kytheExtract = pctx.AndroidStaticRule("kythe",
blueprint.RuleParams{
Command: `${config.ZipSyncCmd} -d $srcJarDir ` +
@@ -97,7 +97,17 @@
`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
`KYTHE_JAVA_SOURCE_BATCH_SIZE=${kytheCuJavaSourceMax} ` +
`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
+ // Avoid JDK9's warning about "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
+ // to field java.nio.Buffer.address"
`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
+ // Allow the classes in the com.google.devtools.kythe.extractors.java.standalone package
+ // access the packages in the jdk.compiler compiler module
+ `--add-opens=java.base/java.nio=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
`${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
diff --git a/java/config/config.go b/java/config/config.go
index a84c315..49d88c4 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -43,6 +43,7 @@
InstrumentFrameworkModules = []string{
"framework",
"framework-minus-apex",
+ "ims-common",
"telephony-common",
"services",
"android.car",
@@ -83,7 +84,7 @@
// ErrorProne can use significantly more memory than javac alone, give it a higher heap
// size (b/221480398).
- exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "4096M")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "8192M")
exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
// D8 invocations are shorter lived, so we restrict their JIT tiering relative to R8.
@@ -124,10 +125,6 @@
// This is set up and guaranteed by soong_ui
return ctx.Config().Getenv("ANDROID_JAVA_HOME")
})
- pctx.VariableFunc("Java11Home", func(ctx android.PackageVarContext) string {
- // This is set up and guaranteed by soong_ui
- return ctx.Config().Getenv("ANDROID_JAVA11_HOME")
- })
pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
@@ -136,12 +133,11 @@
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
- pctx.SourcePathVariable("Java11Toolchain", "${Java11Home}/bin")
pctx.SourcePathVariableWithEnvOverride("JavacCmd",
"${JavaToolchain}/javac", "ALTERNATE_JAVAC")
pctx.SourcePathVariable("JavaCmd", "${JavaToolchain}/java")
pctx.SourcePathVariable("JarCmd", "${JavaToolchain}/jar")
- pctx.SourcePathVariable("JavadocCmd", "${Java11Toolchain}/javadoc")
+ pctx.SourcePathVariable("JavadocCmd", "${JavaToolchain}/javadoc")
pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink")
pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
@@ -268,7 +264,7 @@
// JavadocCmd returns a SourcePath object with the path to the java command.
func JavadocCmd(ctx android.PathContext) android.SourcePath {
- return java11Tool(ctx, "javadoc")
+ return javaTool(ctx, "javadoc")
}
func javaTool(ctx android.PathContext, tool string) android.SourcePath {
@@ -282,17 +278,6 @@
}
-func java11Tool(ctx android.PathContext, tool string) android.SourcePath {
- type javaToolKey string
-
- key := android.NewCustomOnceKey(javaToolKey(tool))
-
- return ctx.Config().OnceSourcePath(key, func() android.SourcePath {
- return java11Toolchain(ctx).Join(ctx, tool)
- })
-
-}
-
var javaToolchainKey = android.NewOnceKey("javaToolchain")
func javaToolchain(ctx android.PathContext) android.SourcePath {
@@ -301,14 +286,6 @@
})
}
-var java11ToolchainKey = android.NewOnceKey("java11Toolchain")
-
-func java11Toolchain(ctx android.PathContext) android.SourcePath {
- return ctx.Config().OnceSourcePath(java11ToolchainKey, func() android.SourcePath {
- return java11Home(ctx).Join(ctx, "bin")
- })
-}
-
var javaHomeKey = android.NewOnceKey("javaHome")
func javaHome(ctx android.PathContext) android.SourcePath {
@@ -317,12 +294,3 @@
return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA_HOME"))
})
}
-
-var java11HomeKey = android.NewOnceKey("java11Home")
-
-func java11Home(ctx android.PathContext) android.SourcePath {
- return ctx.Config().OnceSourcePath(java11HomeKey, func() android.SourcePath {
- // This is set up and guaranteed by soong_ui
- return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA11_HOME"))
- })
-}
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 1c1070a..3d2c5c3 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -63,6 +63,7 @@
java_binary {
name: "foo",
srcs: ["a.java"],
+ main_class: "foo.bar.jb",
}`,
enabled: true,
},
diff --git a/java/droidstubs.go b/java/droidstubs.go
index d9efb40..5777b18 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -28,7 +28,7 @@
)
// The values allowed for Droidstubs' Api_levels_sdk_type
-var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib"}
+var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
@@ -134,7 +134,7 @@
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
- // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system' and 'module-lib' for now; defaults to public.
+ // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system', 'module-lib' and 'system-server'; defaults to public.
Api_levels_sdk_type *string
// the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
@@ -445,6 +445,8 @@
// for older releases. Similarly, module-lib falls back to system API.
var sdkDirs []string
switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
+ case "system-server":
+ sdkDirs = []string{"system-server", "module-lib", "system", "public"}
case "module-lib":
sdkDirs = []string{"module-lib", "system", "public"}
case "system":
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 2443692..25f8c86 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -122,7 +122,7 @@
"some-other-exported-dir",
],
api_levels_annotations_enabled: true,
- api_levels_sdk_type: "%s",
+ api_levels_sdk_type: "%s",
}
`, sdkType),
map[string][]byte{
@@ -169,6 +169,21 @@
}, patterns)
}
+func TestSystemServerDroidstubs(t *testing.T) {
+ patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
+
+ android.AssertArrayString(t, "order of patterns", []string{
+ "--android-jar-pattern somedir/%/system-server/android.jar",
+ "--android-jar-pattern someotherdir/%/system-server/android.jar",
+ "--android-jar-pattern somedir/%/module-lib/android.jar",
+ "--android-jar-pattern someotherdir/%/module-lib/android.jar",
+ "--android-jar-pattern somedir/%/system/android.jar",
+ "--android-jar-pattern someotherdir/%/system/android.jar",
+ "--android-jar-pattern somedir/%/public/android.jar",
+ "--android-jar-pattern someotherdir/%/public/android.jar",
+ }, patterns)
+}
+
func TestDroidstubsSandbox(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
genrule {
diff --git a/java/fuzz.go b/java/fuzz.go
index d0f369f..1d6b913 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -15,6 +15,7 @@
package java
import (
+ "path/filepath"
"sort"
"strings"
@@ -26,6 +27,11 @@
"android/soong/fuzz"
)
+const (
+ hostString = "host"
+ targetString = "target"
+)
+
type jniProperties struct {
// list of jni libs
Jni_libs []string
@@ -39,8 +45,10 @@
}
func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_fuzz_host", FuzzFactory)
- ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
+ ctx.RegisterModuleType("java_fuzz", JavaFuzzFactory)
+ ctx.RegisterModuleType("java_fuzz_host", JavaFuzzHostFactory)
+ ctx.RegisterSingletonType("java_fuzz_host_packaging", javaFuzzHostPackagingFactory)
+ ctx.RegisterSingletonType("java_fuzz_device_packaging", javaFuzzDevicePackagingFactory)
}
type JavaFuzzLibrary struct {
@@ -55,11 +63,11 @@
// sanitized for the given sanitizer or not.
func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
// TODO: once b/231370928 is resolved, please uncomment the loop
- // for _, s := range j.jniProperties.Sanitizers {
- // if sanitizerName == s {
- // return true
- // }
- // }
+ // for _, s := range j.jniProperties.Sanitizers {
+ // if sanitizerName == s {
+ // return true
+ // }
+ // }
return false
}
@@ -72,7 +80,6 @@
// this will be used by the ingestion pipeline to determine the version
// of jazzer to add to the fuzzer package
j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
-
for _, target := range mctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
@@ -91,17 +98,28 @@
if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
}
-
if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
j.fuzzPackagedModule.Config = configPath
}
- ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
+ _, sharedDeps := cc.CollectAllSharedDependencies(ctx)
+
+ for _, dep := range sharedDeps {
sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
if sharedLibInfo.SharedLibrary != nil {
- libPath := android.PathForModuleOut(ctx, sharedLibInfo.SharedLibrary.Base())
+ // The .class jars are output in slightly different locations
+ // relative to the jni libs. Therefore, for consistency across
+ // host and device fuzzers of jni lib location, we save it in a
+ // native_libs directory.
+ var relPath string
+ if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
+ } else {
+ relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
+ }
+ libPath := android.PathForModuleOut(ctx, relPath)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: sharedLibInfo.SharedLibrary,
@@ -111,18 +129,17 @@
} else {
ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
}
- })
+ }
j.Library.GenerateAndroidBuildActions(ctx)
}
-// java_fuzz builds and links sources into a `.jar` file for the host.
+// java_fuzz_host builds and links sources into a `.jar` file for the host.
//
// By default, a java_fuzz produces a `.jar` file containing `.class` files.
// This jar is not suitable for installing on a device.
-func FuzzFactory() android.Module {
+func JavaFuzzHostFactory() android.Module {
module := &JavaFuzzLibrary{}
-
module.addHostProperties()
module.AddProperties(&module.jniProperties)
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -141,23 +158,54 @@
ctx.AppendProperties(&disableLinuxBionic)
})
- module.initModuleAndImport(module)
- android.InitSdkAwareModule(module)
- InitJavaModuleMultiTargets(module, android.HostSupported)
+ InitJavaModuleMultiTargets(module, android.HostSupportedNoCross)
return module
}
-// Responsible for generating rules that package fuzz targets into
-// their architecture & target/host specific zip file.
-type javaFuzzPackager struct {
+// java_fuzz builds and links sources into a `.jar` file for the device.
+// This generates .class files in a jar which can then be instrumented before
+// fuzzing in Android Runtime (ART: Android OS on emulator or device)
+func JavaFuzzFactory() android.Module {
+ module := &JavaFuzzLibrary{}
+ module.addHostAndDeviceProperties()
+ module.AddProperties(&module.jniProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
+ module.Module.dexpreopter.isTest = true
+ module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ InitJavaModuleMultiTargets(module, android.DeviceSupported)
+ return module
+}
+
+// Responsible for generating rules that package host fuzz targets into
+// a zip file.
+type javaFuzzHostPackager struct {
fuzz.FuzzPackager
}
-func javaFuzzPackagingFactory() android.Singleton {
- return &javaFuzzPackager{}
+// Responsible for generating rules that package device fuzz targets into
+// a zip file.
+type javaFuzzDevicePackager struct {
+ fuzz.FuzzPackager
}
-func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+func javaFuzzHostPackagingFactory() android.Singleton {
+ return &javaFuzzHostPackager{}
+}
+
+func javaFuzzDevicePackagingFactory() android.Singleton {
+ return &javaFuzzDevicePackager{}
+}
+
+func (s *javaFuzzHostPackager) GenerateBuildActions(ctx android.SingletonContext) {
+ generateBuildActions(&s.FuzzPackager, hostString, ctx)
+}
+
+func (s *javaFuzzDevicePackager) GenerateBuildActions(ctx android.SingletonContext) {
+ generateBuildActions(&s.FuzzPackager, targetString, ctx)
+}
+
+func generateBuildActions(s *fuzz.FuzzPackager, hostOrTargetString string, ctx android.SingletonContext) {
// Map between each architecture + host/device combination.
archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
@@ -171,8 +219,14 @@
return
}
- if javaFuzzModule.Target().HostCross {
- return
+ if hostOrTargetString == hostString {
+ if !javaFuzzModule.Host() {
+ return
+ }
+ } else if hostOrTargetString == targetString {
+ if javaFuzzModule.Host() || javaFuzzModule.Target().HostCross {
+ return
+ }
}
fuzzModuleValidator := fuzz.FuzzModule{
@@ -185,12 +239,7 @@
return
}
- hostOrTargetString := "target"
- if javaFuzzModule.Host() {
- hostOrTargetString = "host"
- }
archString := javaFuzzModule.Arch().ArchType.String()
-
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -201,7 +250,7 @@
files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
// Add .jar
- files = append(files, fuzz.FileToZip{javaFuzzModule.outputFile, ""})
+ files = append(files, fuzz.FileToZip{javaFuzzModule.implementationJarFile, ""})
// Add jni .so files
for _, fPath := range javaFuzzModule.jniFilePaths {
@@ -217,12 +266,22 @@
s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
}
-func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+func (s *javaFuzzHostPackager) MakeVars(ctx android.MakeVarsContext) {
packages := s.Packages.Strings()
sort.Strings(packages)
- ctx.Strict("SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+ ctx.Strict("SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
// Preallocate the slice of fuzz targets to minimize memory allocations.
- s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_TARGETS")
+ s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_HOST_TARGETS")
+}
+
+func (s *javaFuzzDevicePackager) MakeVars(ctx android.MakeVarsContext) {
+ packages := s.Packages.Strings()
+ sort.Strings(packages)
+
+ ctx.Strict("SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+
+ // Preallocate the slice of fuzz targets to minimize memory allocations.
+ s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_DEVICE_TARGETS")
}
diff --git a/java/java.go b/java/java.go
index 5091d26..b6fc6b8 100644
--- a/java/java.go
+++ b/java/java.go
@@ -211,6 +211,14 @@
PropertyName: "java_tests",
},
}
+
+ // Rule for generating device binary default wrapper
+ deviceBinaryWrapper = pctx.StaticRule("deviceBinaryWrapper", blueprint.RuleParams{
+ Command: `echo -e '#!/system/bin/sh\n` +
+ `export CLASSPATH=/system/framework/$jar_name\n` +
+ `exec app_process /$partition/bin $main_class "$$@"'> ${out}`,
+ Description: "Generating device binary wrapper ${jar_name}",
+ }, "jar_name", "partition", "main_class")
)
// JavaInfo contains information about a java module for use by modules that depend on it.
@@ -1398,7 +1406,31 @@
ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
}
- j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ if ctx.Device() {
+ // device binary should have a main_class property if it does not
+ // have a specific wrapper, so that a default wrapper can
+ // be generated for it.
+ if j.binaryProperties.Main_class == nil {
+ ctx.PropertyErrorf("main_class", "main_class property "+
+ "is required for device binary if no default wrapper is assigned")
+ } else {
+ wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
+ jarName := j.Stem() + ".jar"
+ partition := j.PartitionTag(ctx.DeviceConfig())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: deviceBinaryWrapper,
+ Output: wrapper,
+ Args: map[string]string{
+ "jar_name": jarName,
+ "partition": partition,
+ "main_class": String(j.binaryProperties.Main_class),
+ },
+ })
+ j.wrapperFile = wrapper
+ }
+ } else {
+ j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ }
}
ext := ""
@@ -2312,7 +2344,7 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "event_log_tags",
- Bzl_load_location: "//build/make/tools:event_log_tags.bzl",
+ Bzl_load_location: "//build/bazel/rules/java:event_log_tags.bzl",
},
android.CommonAttributes{Name: logtagsLibName},
&eventLogTagsAttributes{
@@ -2384,7 +2416,18 @@
}
if m.properties.Libs != nil {
- deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
+
+ // TODO 244210934 ALIX Check if this else statement breaks presubmits get rid of it if it doesn't
+ if strings.HasPrefix(ctx.ModuleType(), "java_binary") {
+ for _, d := range m.properties.Libs {
+ neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
+ neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
+ deps.Add(&neverlinkLabel)
+ }
+
+ } else {
+ deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
+ }
}
if m.properties.Static_libs != nil {
@@ -2409,8 +2452,9 @@
type javaLibraryAttributes struct {
*javaCommonAttributes
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
+ Neverlink bazel.BoolAttribute
}
func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
@@ -2440,7 +2484,8 @@
Bzl_load_location: "//build/bazel/rules/java:library.bzl",
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+ name := m.Name()
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
}
type javaBinaryHostAttributes struct {
@@ -2522,7 +2567,8 @@
}
type bazelJavaImportAttributes struct {
- Jars bazel.LabelListAttribute
+ Jars bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
}
// java_import bp2Build converter.
@@ -2543,7 +2589,17 @@
}
props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+ name := android.RemoveOptionalPrebuiltPrefix(i.Name())
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+
+ neverlink := true
+ neverlinkAttrs := &javaLibraryAttributes{
+ Neverlink: bazel.BoolAttribute{Value: &neverlink},
+ Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ }
+ ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs)
+
}
var _ android.MixedBuildBuildable = (*Import)(nil)
diff --git a/java/java_test.go b/java/java_test.go
index 7f0cea7..f06b520 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -588,8 +588,8 @@
sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
fooLibrary := fooModule.Module().(*Library)
- assertDeepEquals(t, "foo java sources incorrect",
- []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings())
+ assertDeepEquals(t, "foo unique sources incorrect",
+ []string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings())
assertDeepEquals(t, "foo java source jars incorrect",
[]string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
@@ -1288,6 +1288,8 @@
}
func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ t.Skip("Re-enable once filegroups are corrected for mixed builds")
bp := `
filegroup {
name: "foo_aidl",
@@ -1781,3 +1783,26 @@
t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
}
}
+
+func TestDeviceBinaryWrapperGeneration(t *testing.T) {
+ // Scenario 1: java_binary has main_class property in its bp
+ ctx, _ := testJava(t, `
+ java_binary {
+ name: "foo",
+ srcs: ["foo.java"],
+ main_class: "foo.bar.jb",
+ }
+ `)
+ wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_arm64_armv8-a").AllOutputs())
+ if !strings.Contains(wrapperPath, "foo.sh") {
+ t.Errorf("wrapper file foo.sh is not generated")
+ }
+
+ // Scenario 2: java_binary has neither wrapper nor main_class, its build
+ // is expected to be failed.
+ testJavaError(t, "main_class property is required for device binary if no default wrapper is assigned", `
+ java_binary {
+ name: "foo",
+ srcs: ["foo.java"],
+ }`)
+}
diff --git a/java/lint.go b/java/lint.go
index 931820d..9827159 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -333,7 +333,7 @@
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
// Skip lint warning checks for NewApi warnings for libcore where they come from source
// files that reference the API they are adding (b/208656169).
- if ctx.ModuleDir() != "libcore" {
+ if !strings.HasPrefix(ctx.ModuleDir(), "libcore") {
_, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks)
if len(filtered) != 0 {
@@ -473,20 +473,23 @@
cmd.FlagWithOutput("--write-reference-baseline ", baseline)
- cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
+ cmd.Text("; EXITCODE=$?; ")
+
+ // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and
+ // export them out of the sandbox. Do this before exiting so that the suggestions exit even after
+ // a fatal error.
+ cmd.BuiltTool("soong_zip").
+ FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")).
+ FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))).
+ FlagWithInput("-r ", srcsList)
+
+ cmd.Text("; if [ $EXITCODE != 0 ]; then if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit $EXITCODE; fi")
rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
// The HTML output contains a date, remove it to make the output deterministic.
rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html)
- // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and
- // export them out of the sandbox.
- rule.Command().BuiltTool("soong_zip").
- FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")).
- FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))).
- FlagWithInput("-r ", srcsList)
-
rule.Build("lint", "lint")
l.outputs = lintOutputs{
diff --git a/java/robolectric.go b/java/robolectric.go
index 7f2981f..2cb0798 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -65,6 +65,10 @@
// The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
// instead of the one built from source in external/robolectric-shadows.
Robolectric_prebuilt_version *string
+
+ // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectri
+ // to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
+ Upstream *bool
}
type robolectricTest struct {
@@ -108,7 +112,11 @@
if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
} else {
- ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ if proptools.Bool(r.robolectricProperties.Upstream) {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream")
+ } else {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ }
}
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
@@ -188,9 +196,9 @@
// TODO: this could all be removed if tradefed was used as the test runner, it will find everything
// annotated as a test and run it.
- for _, src := range r.compiledJavaSrcs {
+ for _, src := range r.uniqueSrcFiles {
s := src.Rel()
- if !strings.HasSuffix(s, "Test.java") {
+ if !strings.HasSuffix(s, "Test.java") && !strings.HasSuffix(s, "Test.kt") {
continue
} else if strings.HasSuffix(s, "/BaseRobolectricTest.java") {
continue
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 61b17bf..54981e1 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -839,84 +839,84 @@
license_kind {
name: "SPDX-license-identifier-LGPL",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.0.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0+",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.0+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0-only",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.0-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.0-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.1.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1+",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.1+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1-only",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.1-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-2.1-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-3.0.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0+",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-3.0+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0-only",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-3.0-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPL-3.0-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPLLR",
- conditions: ["restricted"],
+ conditions: ["restricted_allows_dynamic_linking"],
url: "https://spdx.org/licenses/LGPLLR.html",
}
@@ -1152,7 +1152,7 @@
license_kind {
name: "SPDX-license-identifier-WTFPL",
- conditions: ["notice"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/WTFPL.html",
}
diff --git a/python/Android.bp b/python/Android.bp
index 99c02bd..e49fa6a 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -27,15 +27,3 @@
],
pluginFor: ["soong_build"],
}
-
-// We're transitioning all of these flags to be true by default.
-// This is a defaults flag that can be used to easily add all of them to
-// certain modules.
-python_defaults {
- name: "modern_python_path_defaults",
- dont_add_top_level_directories_to_path: true,
- dont_add_entrypoint_folder_to_path: true,
- proto: {
- respect_pkg_path: true,
- },
-}
diff --git a/python/binary.go b/python/binary.go
index e6324a3..670e0d3 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -34,7 +34,7 @@
}
type bazelPythonBinaryAttributes struct {
- Main *string
+ Main *bazel.Label
Srcs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Python_version *string
@@ -42,17 +42,6 @@
}
func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- var main *string
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*BinaryProperties); ok {
- // main is optional.
- if props.Main != nil {
- main = props.Main
- break
- }
- }
- }
-
// TODO(b/182306917): this doesn't fully handle all nested props versioned
// by the python version, which would have been handled by the version split
// mutator. This is sufficient for very simple python_binary_host modules
@@ -72,13 +61,24 @@
baseAttrs := m.makeArchVariantBaseAttributes(ctx)
attrs := &bazelPythonBinaryAttributes{
- Main: main,
+ Main: nil,
Srcs: baseAttrs.Srcs,
Deps: baseAttrs.Deps,
Python_version: python_version,
Imports: baseAttrs.Imports,
}
+ for _, propIntf := range m.GetProperties() {
+ if props, ok := propIntf.(*BinaryProperties); ok {
+ // main is optional.
+ if props.Main != nil {
+ main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
+ attrs.Main = &main
+ break
+ }
+ }
+ }
+
props := bazel.BazelTargetModuleProperties{
// Use the native py_binary rule.
Rule_class: "py_binary",
@@ -116,22 +116,6 @@
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config *bool
-
- // Currently, both the root of the zipfile and all the directories 1 level
- // below that are added to the python path. When this flag is set to true,
- // only the root of the zipfile will be added to the python path. This flag
- // will be removed after all the python modules in the tree have been updated
- // to support it. When using embedded_launcher: true, this is already the
- // behavior. The default is currently false.
- Dont_add_top_level_directories_to_path *bool
-
- // Setting this to true will mimic Python 3.11+'s PYTHON_SAFE_PATH environment
- // variable or -P flag, even on older python versions. This is a temporary
- // flag while modules are changed to support it, eventually true will be the
- // default and the flag will be removed. The default is currently false. It
- // is only applicable when embedded_launcher is false, when embedded_launcher
- // is true this is already implied.
- Dont_add_entrypoint_folder_to_path *bool
}
type binaryDecorator struct {
@@ -191,14 +175,9 @@
}
})
}
-
- addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, false)
- dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, false)
-
binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...),
- addTopDirectoriesToPath, dontAddEntrypointFolderToPath)
+ main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
return android.OptionalPathForPath(binFile)
}
diff --git a/python/builder.go b/python/builder.go
index f7f9a99..b4ab206 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -43,17 +43,7 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
- `echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
- `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips && ` +
- `chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix)`,
- CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/stub_template_host.txt"},
- },
- "interp", "main", "srcsZips", "addTopDirectoriesToPath")
-
- hostParWithoutAddingEntrypointFolderToPath = pctx.AndroidStaticRule("hostParWithoutAddingEntrypointFolderToPath",
- blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
+ Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
"sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " +
"$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " +
`echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
@@ -61,7 +51,7 @@
"chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)",
CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"},
},
- "interp", "main", "srcsZips", "addTopDirectoriesToPath")
+ "interp", "main", "srcsZips")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
@@ -92,7 +82,7 @@
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
launcherPath android.OptionalPath, interpreter, main, binName string,
- srcsZips android.Paths, addTopDirectoriesToPath bool, dontAddEntrypointFolderToPath bool) android.Path {
+ srcsZips android.Paths) android.Path {
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
@@ -101,37 +91,17 @@
implicits := srcsZips
if !embeddedLauncher {
- addDirsString := "False"
- if addTopDirectoriesToPath {
- addDirsString = "True"
- }
- if dontAddEntrypointFolderToPath {
- ctx.Build(pctx, android.BuildParams{
- Rule: hostParWithoutAddingEntrypointFolderToPath,
- Description: "host python archive",
- Output: binFile,
- Implicits: implicits,
- Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- "addTopDirectoriesToPath": addDirsString,
- },
- })
- } else {
- ctx.Build(pctx, android.BuildParams{
- Rule: hostPar,
- Description: "host python archive",
- Output: binFile,
- Implicits: implicits,
- Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(main, "/", `\/`, -1),
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- "addTopDirectoriesToPath": addDirsString,
- },
- })
- }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hostPar,
+ Description: "host python archive",
+ Output: binFile,
+ Implicits: implicits,
+ Args: map[string]string{
+ "interp": strings.Replace(interpreter, "/", `\/`, -1),
+ "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
+ "srcsZips": strings.Join(srcsZips.Strings(), " "),
+ },
+ })
} else if launcherPath.Valid() {
// added launcherPath to the implicits Ninja dependencies.
implicits = append(implicits, launcherPath.Path())
diff --git a/python/defaults.go b/python/defaults.go
index c54e7d0..3dc5bc4 100644
--- a/python/defaults.go
+++ b/python/defaults.go
@@ -19,7 +19,7 @@
)
func init() {
- android.RegisterModuleType("python_defaults", defaultsFactory)
+ android.RegisterModuleType("python_defaults", DefaultsFactory)
}
type Defaults struct {
@@ -30,7 +30,7 @@
func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
-func defaultsFactory() android.Module {
+func DefaultsFactory() android.Module {
module := &Defaults{}
module.AddProperties(
diff --git a/python/proto.go b/python/proto.go
index 53ebb58..400e72c 100644
--- a/python/proto.go
+++ b/python/proto.go
@@ -18,7 +18,7 @@
"android/soong/android"
)
-func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags, pkgPath string) android.Path {
+func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path {
srcsZipFile := android.PathForModuleGen(ctx, protoFile.Base()+".srcszip")
outDir := srcsZipFile.ReplaceExtension(ctx, "tmp")
@@ -36,9 +36,6 @@
zipCmd := rule.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", srcsZipFile)
- if pkgPath != "" {
- zipCmd.FlagWithArg("-P ", pkgPath)
- }
zipCmd.FlagWithArg("-C ", outDir.String()).
FlagWithArg("-D ", outDir.String())
diff --git a/python/python.go b/python/python.go
index f6029c2..24e1bb2 100644
--- a/python/python.go
+++ b/python/python.go
@@ -120,15 +120,6 @@
// whether the binary is required to be built with embedded launcher for this actual_version.
// this is set by the python version mutator based on version-specific properties
Embedded_launcher *bool `blueprint:"mutated"`
-
- Proto struct {
- // Whether generated python protos should include the pkg_path in
- // their import statements. This is a temporary flag to help transition to
- // the new behavior where this is always true. It will be removed after all
- // usages of protos with pkg_path have been updated. The default is currently
- // false.
- Respect_pkg_path *bool
- }
}
type baseAttributes struct {
@@ -677,10 +668,7 @@
protoFlags := android.GetProtoFlags(ctx, &p.protoProperties)
protoFlags.OutTypeFlag = "--python_out"
- // TODO(b/247578564): Change the default to true, and then eventually remove respect_pkg_path
- protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, false)
- pkgPathForProtos := pkgPath
- if pkgPathForProtos != "" && protosRespectPkgPath {
+ if pkgPath != "" {
pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path")
rule := android.NewRuleBuilder(pctx, ctx)
var stagedProtoSrcs android.Paths
@@ -692,11 +680,10 @@
}
rule.Build("stage_protos_for_pkg_path", "Stage protos for pkg_path")
protoSrcs = stagedProtoSrcs
- pkgPathForProtos = ""
}
for _, srcFile := range protoSrcs {
- zip := genProto(ctx, srcFile, protoFlags, pkgPathForProtos)
+ zip := genProto(ctx, srcFile, protoFlags)
zips = append(zips, zip)
}
}
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index a0ddffe..5eedc18 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -23,16 +23,7 @@
zf.extractall(runfiles_path)
zf.close()
- # Add runfiles path to PYTHONPATH.
- python_path_entries = [runfiles_path]
-
- if ADD_TOP_DIRECTORIES_TO_PATH:
- # Add top dirs within runfiles path to PYTHONPATH.
- top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)]
- top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)]
- python_path_entries += top_pkg_dirs
-
- new_python_path = ":".join(python_path_entries)
+ new_python_path = runfiles_path
old_python_path = os.environ.get(PYTHON_PATH)
if old_python_path:
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
index ea5076e..e54e9b2 100644
--- a/python/tests/dont_import_folder_of_entrypoint/Android.bp
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -9,7 +9,6 @@
"mypkg/main.py",
"mypkg/mymodule.py",
],
- defaults: ["modern_python_path_defaults"],
}
python_test_host {
diff --git a/python/tests/proto_pkg_path/Android.bp b/python/tests/proto_pkg_path/Android.bp
index ef79850..a6bfd3f 100644
--- a/python/tests/proto_pkg_path/Android.bp
+++ b/python/tests/proto_pkg_path/Android.bp
@@ -12,6 +12,5 @@
pkg_path: "mylib/subpackage",
proto: {
canonical_path_from_root: false,
- respect_pkg_path: true,
},
}
diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp
index fe13d4f..574350a 100644
--- a/python/tests/top_level_dirs/Android.bp
+++ b/python/tests/top_level_dirs/Android.bp
@@ -9,5 +9,4 @@
"main.py",
"mypkg/mymodule.py",
],
- dont_add_top_level_directories_to_path: true,
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 0199d3a..17d80dd 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -30,7 +30,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r450784d"
+ bindgenClangVersion = "clang-r468909b"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
@@ -51,7 +51,7 @@
})
_ = pctx.VariableFunc("bindgenClangLibdir", func(ctx android.PackageVarContext) string {
if ctx.Config().UseHostMusl() {
- return "musl/lib64/"
+ return "musl/lib/"
} else {
return "lib64/"
}
@@ -239,6 +239,10 @@
cflags = append(cflags, "-x c")
}
+ // clang-r468909b complains about the -x c in the flags in clang-sys parse_search_paths:
+ // clang: error: '-x c' after last input file has no effect [-Werror,-Wunused-command-line-argument]
+ cflags = append(cflags, "-Wno-unused-command-line-argument")
+
// LLVM_NEXT may contain flags that bindgen doesn't recognise. Turn off unknown flags warning.
if ctx.Config().IsEnvTrue("LLVM_NEXT") {
cflags = append(cflags, "-Wno-unknown-warning-option")
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 76cf21a..6faf55c 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -91,7 +91,7 @@
out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
// Grab the list of required shared libraries.
- fuzzer.sharedLibraries = cc.CollectAllSharedDependencies(ctx)
+ fuzzer.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
return out
}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index a3c5cb5..c68137e 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -189,16 +189,6 @@
}
}
- // TODO:(b/178369775)
- // For now sanitizing is only supported on devices
- if ctx.Os() == android.Android && Bool(s.Fuzzer) {
- sanitize.Properties.SanitizerEnabled = true
- }
-
- if ctx.Os() == android.Android && Bool(s.Address) {
- sanitize.Properties.SanitizerEnabled = true
- }
-
// HWASan requires AArch64 hardware feature (top-byte-ignore).
if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
s.Hwaddress = nil
@@ -219,7 +209,9 @@
s.Memtag_heap = nil
}
- if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap)) {
+ // TODO:(b/178369775)
+ // For now sanitizing is only supported on devices
+ if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
sanitize.Properties.SanitizerEnabled = true
}
}
diff --git a/scripts/gen_ndk_usedby_apex.sh b/scripts/gen_ndk_usedby_apex.sh
index 0d3ed5a..93d1370 100755
--- a/scripts/gen_ndk_usedby_apex.sh
+++ b/scripts/gen_ndk_usedby_apex.sh
@@ -19,6 +19,7 @@
# For example, current line llvm-readelf output is:
# 1: 00000000 0 FUNC GLOBAL DEFAULT UND dlopen@LIBC
# After the parse function below "dlopen" would be write to the output file.
+
printHelp() {
echo "**************************** Usage Instructions ****************************"
echo "This script is used to generate the Mainline modules used-by NDK symbols."
@@ -29,30 +30,33 @@
}
parseReadelfOutput() {
+ local readelfOutput=$1; shift
+ local ndkApisOutput=$1; shift
while IFS= read -r line
do
if [[ $line = *FUNC*GLOBAL*UND*@* ]] ;
then
- echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "$2"
+ echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "${ndkApisOutput}"
fi
- done < "$1"
- echo "" >> "$2"
+ done < "${readelfOutput}"
+ echo "" >> "${ndkApisOutput}"
}
unzipJarAndApk() {
- tmpUnzippedDir="$1"/tmpUnzipped
- [[ -e "$tmpUnzippedDir" ]] && rm -rf "$tmpUnzippedDir"
- mkdir -p "$tmpUnzippedDir"
- find "$1" -name "*.jar" -exec unzip -o {} -d "$tmpUnzippedDir" \;
- find "$1" -name "*.apk" -exec unzip -o {} -d "$tmpUnzippedDir" \;
- find "$tmpUnzippedDir" -name "*.MF" -exec rm {} \;
+ local dir="$1"; shift
+ local tmpUnzippedDir="$1"; shift
+ mkdir -p "${tmpUnzippedDir}"
+ find "$dir" -name "*.jar" -exec unzip -o {} -d "${tmpUnzippedDir}" \;
+ find "$dir" -name "*.apk" -exec unzip -o {} -d "${tmpUnzippedDir}" \;
+ find "${tmpUnzippedDir}" -name "*.MF" -exec rm {} \;
}
lookForExecFile() {
- dir="$1"
- readelf="$2"
- find "$dir" -type f -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \;
- find "$dir" -type f -perm /111 ! -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \;
+ local dir="$1"; shift
+ local readelf="$1"; shift
+ local tmpOutput="$1"; shift
+ find -L "$dir" -type f -name "*.so" -exec "${readelf}" --dyn-symbols {} >> "${tmpOutput}" \;
+ find -L "$dir" -type f -perm /111 ! -name "*.so" -exec "${readelf}" --dyn-symbols {} >> "${tmpOutput}" \;
}
if [[ "$1" == "help" ]]
@@ -62,11 +66,22 @@
then
echo "Wrong argument length. Expecting 3 argument representing image file directory, llvm-readelf tool path, output path."
else
- unzipJarAndApk "$1"
- lookForExecFile "$1" "$2"
- tmpReadelfOutput="$1/../tmpReadelf.txt"
- [[ -e "$3" ]] && rm "$3"
- parseReadelfOutput "$tmpReadelfOutput" "$3"
- [[ -e "$tmpReadelfOutput" ]] && rm "$tmpReadelfOutput"
- rm -rf "$1/tmpUnzipped"
-fi
\ No newline at end of file
+ imageDir="$1"; shift
+ readelf="$1"; shift
+ outputFile="$1"; shift
+
+ tmpReadelfOutput=$(mktemp /tmp/temporary-file.XXXXXXXX)
+ tmpUnzippedDir=$(mktemp -d /tmp/temporary-dir.XXXXXXXX)
+ trap 'rm -rf -- "${tmpReadelfOutput}" "${tmpUnzippedDir}"' EXIT
+
+ # If there are any jars or apks, unzip them to surface native files.
+ unzipJarAndApk "${imageDir}" "${tmpUnzippedDir}"
+ # Analyze the unzipped files.
+ lookForExecFile "${tmpUnzippedDir}" "${readelf}" "${tmpReadelfOutput}"
+
+ # Analyze the apex image staging dir itself.
+ lookForExecFile "${imageDir}" "${readelf}" "${tmpReadelfOutput}"
+
+ [[ -e "${outputFile}" ]] && rm "${outputFile}"
+ parseReadelfOutput "${tmpReadelfOutput}" "${outputFile}"
+fi
diff --git a/scripts/microfactory.bash b/scripts/microfactory.bash
index 192b38f..ce4a0e4 100644
--- a/scripts/microfactory.bash
+++ b/scripts/microfactory.bash
@@ -59,7 +59,7 @@
BUILDDIR=$(getoutdir) \
SRCDIR=${TOP} \
BLUEPRINTDIR=${TOP}/build/blueprint \
- EXTRA_ARGS="-pkg-path android/soong=${TOP}/build/soong -pkg-path rbcrun=${TOP}/build/make/tools/rbcrun -pkg-path google.golang.org/protobuf=${TOP}/external/golang-protobuf -pkg-path go.starlark.net=${TOP}/external/starlark-go" \
+ EXTRA_ARGS="-pkg-path android/soong=${TOP}/build/soong -pkg-path prebuilts/bazel/common/proto=${TOP}/prebuilts/bazel/common/proto -pkg-path rbcrun=${TOP}/build/make/tools/rbcrun -pkg-path google.golang.org/protobuf=${TOP}/external/golang-protobuf -pkg-path go.starlark.net=${TOP}/external/starlark-go" \
build_go $@
}
diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go
index 9946d34..ca3d50e 100644
--- a/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -16,9 +16,12 @@
import (
"debug/macho"
+ "encoding/binary"
"fmt"
"io"
+ "os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
)
@@ -98,6 +101,80 @@
}
func CodeSignMachoFile(path string) error {
- cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path)
- return cmd.Run()
+ filename := filepath.Base(path)
+ cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", "-i", filename, path)
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ return modifyCodeSignFlags(path)
+}
+
+const LC_CODE_SIGNATURE = 0x1d
+const CSSLOT_CODEDIRECTORY = 0
+
+// To make codesign not invalidated by stripping, modify codesign flags to 0x20002
+// (adhoc | linkerSigned).
+func modifyCodeSignFlags(path string) error {
+ f, err := os.OpenFile(path, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Step 1: find code signature section.
+ machoFile, err := macho.NewFile(f)
+ if err != nil {
+ return err
+ }
+ var codeSignSectionOffset uint32 = 0
+ var codeSignSectionSize uint32 = 0
+ for _, l := range machoFile.Loads {
+ data := l.Raw()
+ cmd := machoFile.ByteOrder.Uint32(data)
+ if cmd == LC_CODE_SIGNATURE {
+ codeSignSectionOffset = machoFile.ByteOrder.Uint32(data[8:])
+ codeSignSectionSize = machoFile.ByteOrder.Uint32(data[12:])
+ }
+ }
+ if codeSignSectionOffset == 0 {
+ return fmt.Errorf("code signature section not found")
+ }
+
+ data := make([]byte, codeSignSectionSize)
+ _, err = f.ReadAt(data, int64(codeSignSectionOffset))
+ if err != nil {
+ return err
+ }
+
+ // Step 2: get flags offset.
+ blobCount := binary.BigEndian.Uint32(data[8:])
+ off := 12
+ var codeDirectoryOff uint32 = 0
+ for blobCount > 0 {
+ blobType := binary.BigEndian.Uint32(data[off:])
+ if blobType == CSSLOT_CODEDIRECTORY {
+ codeDirectoryOff = binary.BigEndian.Uint32(data[off+4:])
+ break
+ }
+ blobCount--
+ off += 8
+ }
+ if codeDirectoryOff == 0 {
+ return fmt.Errorf("no code directory in code signature section")
+ }
+ flagsOff := codeSignSectionOffset + codeDirectoryOff + 12
+
+ // Step 3: modify flags.
+ flagsData := make([]byte, 4)
+ _, err = f.ReadAt(flagsData, int64(flagsOff))
+ if err != nil {
+ return err
+ }
+ oldFlags := binary.BigEndian.Uint32(flagsData)
+ if oldFlags != 0x2 {
+ return fmt.Errorf("unexpected flags in code signature section: 0x%x", oldFlags)
+ }
+ binary.BigEndian.PutUint32(flagsData, 0x20002)
+ _, err = f.WriteAt(flagsData, int64(flagsOff))
+ return err
}
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 61d131b..5fbbd0f 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -34,7 +34,7 @@
BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
function call_bazel() {
- tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
+ build/bazel/bin/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
}
function cleanup {
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index e92a561..d89e6b7 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -285,6 +285,35 @@
}
+function test_create_global_include_directory() {
+ setup
+ run_soong
+ local mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+ # Soong needs to know if top level directories like hardware/ exist for use
+ # as global include directories. Make sure that doesn't cause regens for
+ # unrelated changes to the top level directory.
+ mkdir -p system/core
+
+ run_soong
+ local mtime2=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime1" != "$mtime2" ]]; then
+ fail "Output Ninja file changed when top level directory changed"
+ fi
+
+ # Make sure it does regen if a missing directory in the path of a global
+ # include directory is added.
+ mkdir -p system/core/include
+
+ run_soong
+ local mtime3=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime2" = "$mtime3" ]]; then
+ fail "Output Ninja file did not change when global include directory created"
+ fi
+
+}
+
+
function test_add_file_to_soong_build() {
setup
run_soong
@@ -547,12 +576,48 @@
function test_bp2build_generates_marker_file {
setup
- create_mock_bazel
run_soong bp2build
+ if [[ ! -f "./out/soong/bp2build_files_marker" ]]; then
+ fail "bp2build marker file was not generated"
+ fi
+
if [[ ! -f "./out/soong/bp2build_workspace_marker" ]]; then
- fail "Marker file was not generated"
+ fail "symlink forest marker file was not generated"
+ fi
+}
+
+function test_bp2build_add_irrelevant_file {
+ setup
+
+ mkdir -p a/b
+ touch a/b/c.txt
+ cat > a/b/Android.bp <<'EOF'
+filegroup {
+ name: "c",
+ srcs: ["c.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ run_soong bp2build
+ if [[ ! -e out/soong/bp2build/a/b/BUILD.bazel ]]; then
+ fail "BUILD file in symlink forest was not created";
+ fi
+
+ local mtime1=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
+
+ touch a/irrelevant.txt
+ run_soong bp2build
+ local mtime2=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
+
+ if [[ "$mtime1" != "$mtime2" ]]; then
+ fail "BUILD.bazel file was regenerated"
+ fi
+
+ if [[ ! -e "out/soong/workspace/a/irrelevant.txt" ]]; then
+ fail "New file was not symlinked into symlink forest"
fi
}
@@ -838,6 +903,7 @@
test_add_file_to_soong_build
test_glob_during_bootstrapping
test_soong_build_rerun_iff_environment_changes
+test_create_global_include_directory
test_multiple_soong_build_modes
test_dump_json_module_graph
test_json_module_graph_back_and_forth_null_build
@@ -849,6 +915,7 @@
test_bp2build_null_build
test_bp2build_back_and_forth_null_build
test_bp2build_add_android_bp
+test_bp2build_add_irrelevant_file
test_bp2build_add_to_glob
test_bp2build_bazel_workspace_structure
test_bp2build_bazel_workspace_add_file
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 3cb6c8c..679ac55 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -48,9 +48,52 @@
test_bp2build_null_build_with_globs
+function test_different_relative_outdir {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ bazel_module: {bp2build_available: true},
+ }
+EOF
+
+ # A directory under $MOCK_TOP
+ outdir=out2
+ trap "rm -rf $outdir" EXIT
+ # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
+ (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
+}
+
+test_different_relative_outdir
+
+function test_different_absolute_outdir {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ bazel_module: {bp2build_available: true},
+ }
+EOF
+
+ # A directory under /tmp/...
+ outdir=$(mktemp -t -d st.XXXXX)
+ trap 'rm -rf $outdir' EXIT
+ # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
+ (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
+}
+
+test_different_absolute_outdir
+
function test_bp2build_generates_all_buildfiles {
setup
- create_mock_bazel
mkdir -p foo/convertible_soong_module
cat > foo/convertible_soong_module/Android.bp <<'EOF'
@@ -121,7 +164,6 @@
function test_cc_correctness {
setup
- create_mock_bazel
mkdir -p a
cat > a/Android.bp <<EOF
diff --git a/tests/lib.sh b/tests/lib.sh
index 4b4d908..e40f0ad 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -82,6 +82,7 @@
}
function create_mock_soong {
+ create_mock_bazel
copy_directory build/blueprint
copy_directory build/soong
copy_directory build/make/tools/rbcrun
@@ -128,7 +129,6 @@
symlink_file WORKSPACE
symlink_file BUILD
- symlink_file tools/bazel
}
function run_bazel {
@@ -136,7 +136,7 @@
# output should not be parsed as such.
rm -rf out/ninja_build
- tools/bazel "$@"
+ build/bazel/bin/bazel "$@"
}
function run_ninja {
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index f6fffad..8949b42 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -12,11 +12,56 @@
function test_bazel_smoke {
setup
- create_mock_bazel
run_soong bp2build
run_bazel info --config=bp2build
}
+function test_add_irrelevant_file {
+ setup
+
+ mkdir -p soong_tests/a/b
+ touch soong_tests/a/b/c.txt
+ cat > soong_tests/a/b/Android.bp <<'EOF'
+filegroup {
+ name: "c",
+ srcs: ["c.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ run_soong --bazel-mode-staging nothing
+
+ if [[ ! -e out/soong/bp2build/soong_tests/a/b/BUILD.bazel ]]; then
+ fail "BUILD.bazel not created"
+ fi
+
+ if [[ ! -e out/soong/build.ninja ]]; then
+ fail "build.ninja not created"
+ fi
+
+ local mtime_build1=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
+ local mtime_ninja1=$(stat -c "%y" out/soong/build.ninja)
+
+ touch soong_tests/a/irrelevant.txt
+
+ run_soong --bazel-mode-staging nothing
+ local mtime_build2=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
+ local mtime_ninja2=$(stat -c "%y" out/soong/build.ninja)
+
+ if [[ "$mtime_build1" != "$mtime_build2" ]]; then
+ fail "BUILD.bazel was generated"
+ fi
+
+ if [[ "$mtime_ninja1" != "$mtime_ninja2" ]]; then
+ fail "build.ninja was regenerated"
+ fi
+
+ if [[ ! -e out/soong/workspace/soong_tests/a/irrelevant.txt ]]; then
+ fail "new file was not symlinked"
+ fi
+}
+
+test_add_irrelevant_file
test_bazel_smoke
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 0ebfcd8..bd469a4 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -85,9 +85,9 @@
bazelEnv["SHELL"] = "/bin/bash"
- // `tools/bazel` is the default entry point for executing Bazel in the AOSP
+ // `build/bazel/bin/bazel` is the default entry point for executing Bazel in the AOSP
// source tree.
- bazelExecutable := filepath.Join("tools", "bazel")
+ bazelExecutable := filepath.Join("build", "bazel", "bin", "bazel")
cmd := Command(ctx, config, "bazel", bazelExecutable)
// Append custom startup flags to the Bazel command. Startup flags affect
diff --git a/ui/build/build.go b/ui/build/build.go
index 2022e50..b9bd898 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -112,9 +112,19 @@
// checkBazelMode fails the build if there are conflicting arguments for which bazel
// build mode to use.
func checkBazelMode(ctx Context, config Config) {
- if config.bazelProdMode && config.bazelDevMode {
+ count := 0
+ if config.bazelProdMode {
+ count++
+ }
+ if config.bazelDevMode {
+ count++
+ }
+ if config.bazelStagingMode {
+ count++
+ }
+ if count > 1 {
ctx.Fatalln("Conflicting bazel mode.\n" +
- "Do not specify both --bazel-mode and --bazel-mode-dev")
+ "Do not specify more than one of --bazel-mode and --bazel-mode-dev and --bazel-mode-staging ")
}
}
diff --git a/ui/build/config.go b/ui/build/config.go
index f6f5b46..de10112 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -100,8 +100,9 @@
pathReplaced bool
- bazelProdMode bool
- bazelDevMode bool
+ bazelProdMode bool
+ bazelDevMode bool
+ bazelStagingMode bool
// Set by multiproduct_kati
emptyNinjaFile bool
@@ -235,6 +236,19 @@
return nil
}
+func defaultBazelProdMode(cfg *configImpl) bool {
+ // Envirnoment flag to disable Bazel for users which experience
+ // broken bazel-handled builds, or significant performance regressions.
+ if cfg.IsBazelMixedBuildForceDisabled() {
+ return false
+ }
+ // Darwin-host builds are currently untested with Bazel.
+ if runtime.GOOS == "darwin" {
+ return false
+ }
+ return true
+}
+
func NewConfig(ctx Context, args ...string) Config {
ret := &configImpl{
environ: OsEnvironment(),
@@ -463,10 +477,11 @@
func buildConfig(config Config) *smpb.BuildConfig {
c := &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(config.ForceUseGoma()),
- UseGoma: proto.Bool(config.UseGoma()),
- UseRbe: proto.Bool(config.UseRBE()),
- BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
+ ForceUseGoma: proto.Bool(config.ForceUseGoma()),
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
+ BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
+ ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
}
c.Targets = append(c.Targets, config.arguments...)
@@ -721,6 +736,8 @@
c.bazelProdMode = true
} else if arg == "--bazel-mode-dev" {
c.bazelDevMode = true
+ } else if arg == "--bazel-mode-staging" {
+ c.bazelStagingMode = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -770,6 +787,9 @@
c.arguments = append(c.arguments, arg)
}
}
+ if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
+ c.bazelProdMode = defaultBazelProdMode(c)
+ }
}
func (c *configImpl) configureLocale(ctx Context) {
@@ -907,7 +927,11 @@
return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
}
-func (c *configImpl) Bp2BuildMarkerFile() string {
+func (c *configImpl) Bp2BuildFilesMarkerFile() string {
+ return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
+}
+
+func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
}
@@ -1115,7 +1139,7 @@
}
func (c *configImpl) BazelBuildEnabled() bool {
- return c.bazelProdMode || c.bazelDevMode
+ return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
}
func (c *configImpl) StartRBE() bool {
@@ -1449,6 +1473,10 @@
return c.emptyNinjaFile
}
+func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
+ return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
+}
+
func GetMetricsUploader(topDir string, env *Environment) string {
if p, ok := env.Get("METRICS_UPLOADER"); ok {
metricsUploader := filepath.Join(topDir, p)
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 150ec35..940d85c 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -28,6 +28,7 @@
"android/soong/ui/logger"
smpb "android/soong/ui/metrics/metrics_proto"
"android/soong/ui/status"
+
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
@@ -89,7 +90,9 @@
t.Fatal(err)
})
+ env := Environment([]string{})
c := &configImpl{
+ environ: &env,
parallel: -1,
keepGoing: -1,
}
@@ -1008,46 +1011,62 @@
useBazel bool
bazelDevMode bool
bazelProdMode bool
+ bazelStagingMode bool
expectedBuildConfig *smpb.BuildConfig
}{
{
name: "none set",
environ: Environment{},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "force use goma",
environ: Environment{"FORCE_USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(true),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "use goma",
environ: Environment{"USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(true),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "use rbe",
environ: Environment{"USE_RBE=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(true),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
+ },
+ },
+ {
+ name: "disable mixed builds",
+ environ: Environment{"BUILD_BROKEN_DISABLE_BAZEL=1"},
+ expectedBuildConfig: &smpb.BuildConfig{
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(true),
},
},
{
@@ -1055,10 +1074,11 @@
environ: Environment{},
useBazel: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1066,10 +1086,11 @@
environ: Environment{},
bazelDevMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1077,10 +1098,23 @@
environ: Environment{},
bazelProdMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
+ },
+ },
+ {
+ name: "bazel mixed build from staging mode",
+ environ: Environment{},
+ bazelStagingMode: true,
+ expectedBuildConfig: &smpb.BuildConfig{
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1089,11 +1123,12 @@
useBazel: true,
arguments: []string{"droid", "dist"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- Targets: []string{"droid", "dist"},
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ Targets: []string{"droid", "dist"},
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1102,14 +1137,16 @@
"FORCE_USE_GOMA=1",
"USE_GOMA=1",
"USE_RBE=1",
+ "BUILD_BROKEN_DISABLE_BAZEL=1",
},
useBazel: true,
bazelDevMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(true),
+ UseGoma: proto.Bool(true),
+ UseRbe: proto.Bool(true),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(true),
},
},
}
@@ -1118,10 +1155,11 @@
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
c := &configImpl{
- environ: &tc.environ,
- bazelDevMode: tc.bazelDevMode,
- bazelProdMode: tc.bazelProdMode,
- arguments: tc.arguments,
+ environ: &tc.environ,
+ bazelDevMode: tc.bazelDevMode,
+ bazelProdMode: tc.bazelProdMode,
+ bazelStagingMode: tc.bazelStagingMode,
+ arguments: tc.arguments,
}
config := Config{c}
checkBazelMode(ctx, config)
diff --git a/ui/build/context.go b/ui/build/context.go
index 4a4352c..2fef0d0 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -48,7 +48,7 @@
c.Tracer.Begin(desc, c.Thread)
}
if c.Metrics != nil {
- c.Metrics.EventTracer.Begin(name, desc, c.Thread)
+ c.Metrics.EventTracer.Begin(name, desc)
}
}
@@ -58,7 +58,7 @@
c.Tracer.End(c.Thread)
}
if c.Metrics != nil {
- c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End(c.Thread))
+ c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End())
}
}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 6231e52..c3e52c6 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -94,6 +94,9 @@
}
func startRBE(ctx Context, config Config) {
+ if !config.GoogleProdCredsExist() && prodCredsAuthType(config) {
+ ctx.Fatalf("Unable to start RBE reproxy\nFAILED: Missing LOAS credentials.")
+ }
ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
defer ctx.EndTrace()
diff --git a/ui/build/soong.go b/ui/build/soong.go
index e0d67cc..4aded17 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -41,12 +41,13 @@
availableEnvFile = "soong.environment.available"
usedEnvFile = "soong.environment.used"
- soongBuildTag = "build"
- bp2buildTag = "bp2build"
- jsonModuleGraphTag = "modulegraph"
- queryviewTag = "queryview"
- apiBp2buildTag = "api_bp2build"
- soongDocsTag = "soong_docs"
+ soongBuildTag = "build"
+ bp2buildFilesTag = "bp2build_files"
+ bp2buildWorkspaceTag = "bp2build_workspace"
+ jsonModuleGraphTag = "modulegraph"
+ queryviewTag = "queryview"
+ apiBp2buildTag = "api_bp2build"
+ soongDocsTag = "soong_docs"
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
// version of bootstrap and needs cleaning before continuing the build. Increment this for
@@ -235,7 +236,7 @@
func bootstrapGlobFileList(config Config) []string {
return []string{
config.NamedGlobFile(soongBuildTag),
- config.NamedGlobFile(bp2buildTag),
+ config.NamedGlobFile(bp2buildFilesTag),
config.NamedGlobFile(jsonModuleGraphTag),
config.NamedGlobFile(queryviewTag),
config.NamedGlobFile(apiBp2buildTag),
@@ -260,6 +261,9 @@
if config.bazelDevMode {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-dev")
}
+ if config.bazelStagingMode {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-staging")
+ }
mainSoongBuildInvocation := primaryBuilderInvocation(
config,
@@ -273,20 +277,33 @@
// Mixed builds call Bazel from soong_build and they therefore need the
// Bazel workspace to be available. Make that so by adding a dependency on
// the bp2build marker file to the action that invokes soong_build .
- mainSoongBuildInvocation.Inputs = append(mainSoongBuildInvocation.Inputs,
- config.Bp2BuildMarkerFile())
+ mainSoongBuildInvocation.OrderOnlyInputs = append(mainSoongBuildInvocation.OrderOnlyInputs,
+ config.Bp2BuildWorkspaceMarkerFile())
}
bp2buildInvocation := primaryBuilderInvocation(
config,
- bp2buildTag,
- config.Bp2BuildMarkerFile(),
+ bp2buildFilesTag,
+ config.Bp2BuildFilesMarkerFile(),
[]string{
- "--bp2build_marker", config.Bp2BuildMarkerFile(),
+ "--bp2build_marker", config.Bp2BuildFilesMarkerFile(),
},
fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()),
)
+ bp2buildWorkspaceInvocation := primaryBuilderInvocation(
+ config,
+ bp2buildWorkspaceTag,
+ config.Bp2BuildWorkspaceMarkerFile(),
+ []string{
+ "--symlink_forest_marker", config.Bp2BuildWorkspaceMarkerFile(),
+ },
+ fmt.Sprintf("Creating Bazel symlink forest"),
+ )
+
+ bp2buildWorkspaceInvocation.Inputs = append(bp2buildWorkspaceInvocation.Inputs,
+ config.Bp2BuildFilesMarkerFile())
+
jsonModuleGraphInvocation := primaryBuilderInvocation(
config,
jsonModuleGraphTag,
@@ -358,6 +375,7 @@
primaryBuilderInvocations: []bootstrap.PrimaryBuilderInvocation{
mainSoongBuildInvocation,
bp2buildInvocation,
+ bp2buildWorkspaceInvocation,
jsonModuleGraphInvocation,
queryviewInvocation,
apiBp2buildInvocation,
@@ -396,7 +414,7 @@
soongBuildEnv := config.Environment().Copy()
soongBuildEnv.Set("TOP", os.Getenv("TOP"))
// For Bazel mixed builds.
- soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
+ soongBuildEnv.Set("BAZEL_PATH", "./build/bazel/bin/bazel")
// Bazel's HOME var is set to an output subdirectory which doesn't exist. This
// prevents Bazel from file I/O in the actual user HOME directory.
soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
@@ -404,6 +422,7 @@
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
soongBuildEnv.Set("LOG_DIR", config.LogsDir())
+ soongBuildEnv.Set("BAZEL_DEPS_FILE", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazel.list")))
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
@@ -422,7 +441,7 @@
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongBuildTag))
if config.BazelBuildEnabled() || config.Bp2Build() {
- checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildTag))
+ checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildFilesTag))
}
if config.JsonModuleGraph() {
@@ -493,7 +512,7 @@
}
if config.Bp2Build() {
- targets = append(targets, config.Bp2BuildMarkerFile())
+ targets = append(targets, config.Bp2BuildWorkspaceMarkerFile())
}
if config.Queryview() {
@@ -513,17 +532,22 @@
targets = append(targets, config.SoongNinjaFile())
}
- ninja("bootstrap", "bootstrap.ninja", targets...)
-
if shouldCollectBuildSoongMetrics(config) {
- soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
- if soongBuildMetrics != nil {
- logSoongBuildMetrics(ctx, soongBuildMetrics)
- if ctx.Metrics != nil {
- ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
- }
+ soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
+ if err := os.Remove(soongBuildMetricsFile); err != nil && !os.IsNotExist(err) {
+ ctx.Verbosef("Failed to remove %s", soongBuildMetricsFile)
}
+ defer func() {
+ soongBuildMetrics := loadSoongBuildMetrics(ctx, soongBuildMetricsFile)
+ if soongBuildMetrics != nil {
+ logSoongBuildMetrics(ctx, soongBuildMetrics)
+ if ctx.Metrics != nil {
+ ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
+ }
+ }
+ }()
}
+ ninja("bootstrap", "bootstrap.ninja", targets...)
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
distFile(ctx, config, config.SoongVarsFile(), "soong")
@@ -562,8 +586,7 @@
return config.SoongBuildInvocationNeeded()
}
-func loadSoongBuildMetrics(ctx Context, config Config) *soong_metrics_proto.SoongBuildMetrics {
- soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
+func loadSoongBuildMetrics(ctx Context, soongBuildMetricsFile string) *soong_metrics_proto.SoongBuildMetrics {
buf, err := os.ReadFile(soongBuildMetricsFile)
if errors.Is(err, fs.ErrNotExist) {
// Soong may not have run during this invocation
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 687f519..9f14bdd 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -18,6 +18,7 @@
// another.
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -56,7 +57,9 @@
}
if fi.IsDir() {
- if l, err := ioutil.ReadDir(p); err == nil {
+ if l, err := ioutil.ReadDir(p); err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "Failed to find files under %s\n", p)
+ } else {
files := make([]string, 0, len(l))
for _, fi := range l {
files = append(files, filepath.Join(p, fi.Name()))
diff --git a/ui/logger/Android.bp b/ui/logger/Android.bp
index 269a5a0..7883ea6 100644
--- a/ui/logger/Android.bp
+++ b/ui/logger/Android.bp
@@ -25,4 +25,7 @@
testSrcs: [
"logger_test.go",
],
+ deps: [
+ "soong-ui-metrics",
+ ],
}
diff --git a/ui/logger/logger.go b/ui/logger/logger.go
index 9b26ae8..1185298 100644
--- a/ui/logger/logger.go
+++ b/ui/logger/logger.go
@@ -29,6 +29,7 @@
package logger
import (
+ "android/soong/ui/metrics"
"errors"
"fmt"
"io"
@@ -72,8 +73,8 @@
Output(calldepth int, str string) error
}
-// fatalLog is the type used when Fatal[f|ln]
-type fatalLog struct {
+// fatalError is the type used when Fatal[f|ln]
+type fatalError struct {
error
}
@@ -127,7 +128,7 @@
if p == nil {
return
- } else if log, ok := p.(fatalLog); ok {
+ } else if log, ok := p.(fatalError); ok {
fn(error(log))
} else {
panic(p)
@@ -141,6 +142,7 @@
fileLogger *log.Logger
mutex sync.Mutex
file *os.File
+ metrics *metrics.Metrics
}
var _ Logger = &stdLogger{}
@@ -149,9 +151,14 @@
// os.Stderr, but it may be a buffer for tests, or a separate log file if
// the user doesn't need to see the output.
func New(out io.Writer) *stdLogger {
+ return NewWithMetrics(out, nil)
+}
+
+func NewWithMetrics(out io.Writer, m *metrics.Metrics) *stdLogger {
return &stdLogger{
stderr: log.New(out, "", log.Ltime),
fileLogger: log.New(ioutil.Discard, "", log.Ldate|log.Lmicroseconds|log.Llongfile),
+ metrics: m,
}
}
@@ -201,7 +208,7 @@
fatal := false
p := recover()
- if _, ok := p.(fatalLog); ok {
+ if _, ok := p.(fatalError); ok {
fatal = true
p = nil
} else if p != nil {
@@ -217,40 +224,56 @@
}
}
+type verbosityLevel int
+
+const (
+ verboseLog verbosityLevel = iota
+ infoLog
+ fatalLog
+ panicLog
+)
+
// Output writes string to both stderr and the file log.
func (s *stdLogger) Output(calldepth int, str string) error {
- s.stderr.Output(calldepth+1, str)
+ return s.output(calldepth, str, infoLog)
+}
+
+// output writes string to stderr, the file log, and if fatal or panic, to metrics.
+func (s *stdLogger) output(calldepth int, str string, level verbosityLevel) error {
+ if level != verboseLog || s.verbose {
+ s.stderr.Output(calldepth+1, str)
+ }
+ if level >= fatalLog {
+ s.metrics.SetFatalOrPanicMessage(str)
+ }
return s.fileLogger.Output(calldepth+1, str)
}
// VerboseOutput is equivalent to Output, but only goes to the file log
// unless SetVerbose(true) has been called.
func (s *stdLogger) VerboseOutput(calldepth int, str string) error {
- if s.verbose {
- s.stderr.Output(calldepth+1, str)
- }
- return s.fileLogger.Output(calldepth+1, str)
+ return s.output(calldepth, str, verboseLog)
}
// Print prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Print.
func (s *stdLogger) Print(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Printf prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Printf.
func (s *stdLogger) Printf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Println prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Println.
func (s *stdLogger) Println(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Verbose is equivalent to Print, but only goes to the file log unless
@@ -278,43 +301,43 @@
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatal(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Fatalf is equivalent to Printf() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Fatalln is equivalent to Println() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalln(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Panic is equivalent to Print() followed by a call to panic().
func (s *stdLogger) Panic(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
// Panicf is equivalent to Printf() followed by a call to panic().
func (s *stdLogger) Panicf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
// Panicln is equivalent to Println() followed by a call to panic().
func (s *stdLogger) Panicln(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 05db1d7..2301c56 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -25,7 +25,6 @@
"soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
"soong-ui-mk_metrics_proto",
- "soong-ui-tracer",
"soong-shared",
],
srcs: [
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index ebe664f..b3a027e 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -31,7 +31,6 @@
"time"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
- "android/soong/ui/tracer"
"google.golang.org/protobuf/proto"
)
@@ -50,6 +49,10 @@
// for metrics analysis).
desc string
+ nonZeroExitCode bool
+
+ errorMsg *string
+
// The time that the event started to occur.
start time.Time
@@ -68,13 +71,18 @@
func (e event) perfInfo() soong_metrics_proto.PerfInfo {
realTime := uint64(_now().Sub(e.start).Nanoseconds())
- return soong_metrics_proto.PerfInfo{
+ perfInfo := soong_metrics_proto.PerfInfo{
Description: proto.String(e.desc),
Name: proto.String(e.name),
StartTime: proto.Uint64(uint64(e.start.UnixNano())),
RealTime: proto.Uint64(realTime),
ProcessesResourceInfo: e.procResInfo,
+ NonZeroExit: proto.Bool(e.nonZeroExitCode),
}
+ if m := e.errorMsg; m != nil {
+ perfInfo.ErrorMessage = proto.String(*m)
+ }
+ return perfInfo
}
// EventTracer is an array of events that provides functionality to trace a
@@ -94,6 +102,9 @@
// peek returns the active build event.
func (t *EventTracer) peek() *event {
+ if t.empty() {
+ return nil
+ }
return (*t)[t.lastIndex()]
}
@@ -137,12 +148,12 @@
}
// Begin starts tracing the event.
-func (t *EventTracer) Begin(name, desc string, _ tracer.Thread) {
+func (t *EventTracer) Begin(name, desc string) {
t.push(newEvent(name, desc))
}
// End performs post calculations such as duration of the event, aggregates
// the collected performance information into PerfInfo protobuf message.
-func (t *EventTracer) End(tracer.Thread) soong_metrics_proto.PerfInfo {
+func (t *EventTracer) End() soong_metrics_proto.PerfInfo {
return t.pop().perfInfo()
}
diff --git a/ui/metrics/event_test.go b/ui/metrics/event_test.go
index 043450b..a80e7cf 100644
--- a/ui/metrics/event_test.go
+++ b/ui/metrics/event_test.go
@@ -17,8 +17,6 @@
import (
"testing"
"time"
-
- "android/soong/ui/tracer"
)
func TestEnd(t *testing.T) {
@@ -35,8 +33,31 @@
start: startTime,
})
- perf := et.End(tracer.Thread(0))
+ perf := et.End()
if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
}
}
+
+func TestEndWithError(t *testing.T) {
+ startTime := time.Date(2020, time.July, 13, 13, 0, 0, 0, time.UTC)
+ dur := time.Nanosecond * 10
+ initialNow := _now
+ _now = func() time.Time { return startTime.Add(dur) }
+ defer func() { _now = initialNow }()
+
+ err := "foobar"
+ et := &EventTracer{}
+ et.push(&event{
+ desc: "test",
+ name: "test",
+ start: startTime,
+ nonZeroExitCode: true,
+ errorMsg: &err,
+ })
+
+ perf := et.End()
+ if msg := perf.GetErrorMessage(); msg != err {
+ t.Errorf("got %q, want %q for even error message", msg, err)
+ }
+}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 0c62865..ce2d946 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -125,6 +125,21 @@
}
}
+// SetFatalOrPanicMessage stores a non-zero exit and the relevant message in the latest event if
+// available or the metrics base.
+func (m *Metrics) SetFatalOrPanicMessage(errMsg string) {
+ if m == nil {
+ return
+ }
+ if event := m.EventTracer.peek(); event != nil {
+ event.nonZeroExitCode = true
+ event.errorMsg = &errMsg
+ } else {
+ m.metrics.ErrorMessage = proto.String(errMsg)
+ }
+ m.metrics.NonZeroExit = proto.Bool(true)
+}
+
// BuildConfig stores information about the build configuration.
func (m *Metrics) BuildConfig(b *soong_metrics_proto.BuildConfig) {
m.metrics.BuildConfig = b
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 2dd8299..90d124b 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -338,6 +338,12 @@
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"`
+ // Whether the build exited with a panic or non-zero exit code, includes both
+ // non-zero exits of recorded phases and non-recorded phases of the build.
+ NonZeroExit *bool `protobuf:"varint,29,opt,name=non_zero_exit,json=nonZeroExit" json:"non_zero_exit,omitempty"`
+ // The error message due to a non-zero exit _only_ if it did not occur in a
+ // recorded phase of the build.
+ ErrorMessage *string `protobuf:"bytes,30,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
}
// Default values for MetricsBase fields.
@@ -576,6 +582,20 @@
return nil
}
+func (x *MetricsBase) GetNonZeroExit() bool {
+ if x != nil && x.NonZeroExit != nil {
+ return *x.NonZeroExit
+ }
+ return false
+}
+
+func (x *MetricsBase) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
type BuildConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -592,6 +612,8 @@
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
Targets []string `protobuf:"bytes,6,rep,name=targets" json:"targets,omitempty"`
+ // Whether the user explicitly disabled bazel mixed builds for this build.
+ ForceDisableBazelMixedBuild *bool `protobuf:"varint,7,opt,name=force_disable_bazel_mixed_build,json=forceDisableBazelMixedBuild" json:"force_disable_bazel_mixed_build,omitempty"`
}
func (x *BuildConfig) Reset() {
@@ -668,6 +690,13 @@
return nil
}
+func (x *BuildConfig) GetForceDisableBazelMixedBuild() bool {
+ if x != nil && x.ForceDisableBazelMixedBuild != nil {
+ return *x.ForceDisableBazelMixedBuild
+ }
+ return false
+}
+
type SystemResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -746,6 +775,11 @@
MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"`
// The resource information of each executed process.
ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"`
+ // Whether the phase of tool running exited with a panic or non-zero exit
+ // code.
+ NonZeroExit *bool `protobuf:"varint,7,opt,name=non_zero_exit,json=nonZeroExit" json:"non_zero_exit,omitempty"`
+ // The error message, if any, due to a non-zero exit.
+ ErrorMessage *string `protobuf:"bytes,8,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
}
func (x *PerfInfo) Reset() {
@@ -823,6 +857,20 @@
return nil
}
+func (x *PerfInfo) GetNonZeroExit() bool {
+ if x != nil && x.NonZeroExit != nil {
+ return *x.NonZeroExit
+ }
+ return false
+}
+
+func (x *PerfInfo) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
type ProcessResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1361,7 +1409,7 @@
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, 0xad, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0xf6, 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,
@@ -1461,152 +1509,166 @@
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, 0xcc, 0x02, 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, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+ 0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f,
+ 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e,
+ 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, 0x99, 0x02,
+ 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, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66, 0x6f,
+ 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 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, 0xca, 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, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73,
- 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 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, 0x47, 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, 0x12,
- 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54,
- 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78,
- 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78,
- 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 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,
+ 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, 0x12, 0x22,
+ 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78,
+ 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, 0xcc, 0x02,
+ 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, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69,
+ 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65,
+ 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78,
+ 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 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, 0x47, 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, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49,
+ 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d,
+ 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45,
+ 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a,
+ 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 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,
}
var (
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 4f8fe7f..07a7df1 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -111,6 +111,14 @@
// The metrics of the experiment config fetcher
optional ExpConfigFetcher exp_config_fetcher = 28;
+
+ // Whether the build exited with a panic or non-zero exit code, includes both
+ // non-zero exits of recorded phases and non-recorded phases of the build.
+ optional bool non_zero_exit = 29;
+
+ // The error message due to a non-zero exit _only_ if it did not occur in a
+ // recorded phase of the build.
+ optional string error_message = 30;
}
message BuildConfig {
@@ -130,6 +138,9 @@
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
repeated string targets = 6;
+
+ // Whether the user explicitly disabled bazel mixed builds for this build.
+ optional bool force_disable_bazel_mixed_build = 7;
}
message SystemResourceInfo {
@@ -160,6 +171,13 @@
// The resource information of each executed process.
repeated ProcessResourceInfo processes_resource_info = 6;
+
+ // Whether the phase of tool running exited with a panic or non-zero exit
+ // code.
+ optional bool non_zero_exit = 7;
+
+ // The error message, if any, due to a non-zero exit.
+ optional string error_message = 8;
}
message ProcessResourceInfo {