diff options
94 files changed, 2646 insertions, 958 deletions
diff --git a/Android.bp b/Android.bp index d6260b400..b5ddaa4e4 100644 --- a/Android.bp +++ b/Android.bp @@ -62,6 +62,7 @@ toolchain_library { }, }, notice: ":mingw-libwinpthread-notice", + licenses: ["winpthreads_license"], } kernel_headers { diff --git a/android/androidmk.go b/android/androidmk.go index 967c550d6..f48c06bce 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -29,6 +29,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "sort" "strings" @@ -836,6 +837,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod case "*aidl.aidlApi": // writes non-custom before adding .phony case "*aidl.aidlMapping": // writes non-custom before adding .phony case "*android.customModule": // appears in tests only + case "*android_sdk.sdkRepoHost": // doesn't go through base_rules case "*apex.apexBundle": // license properties written case "*bpf.bpf": // license properties written (both for module and objs) case "*genrule.Module": // writes non-custom before adding .phony @@ -901,6 +903,13 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { return true } + // On Mac, only expose host darwin modules to Make, as that's all we claim to support. + // In reality, some of them depend on device-built (Java) modules, so we can't disable all + // device modules in Soong, but we can hide them from Make (and thus the build user interface) + if runtime.GOOS == "darwin" && module.Os() != Darwin { + return true + } + return !module.Enabled() || module.commonProperties.HideFromMake || // Make does not understand LinuxBionic diff --git a/android/androidmk_test.go b/android/androidmk_test.go index 8eda9b247..ecfb00825 100644 --- a/android/androidmk_test.go +++ b/android/androidmk_test.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "reflect" + "runtime" "strings" "testing" @@ -155,6 +156,11 @@ func buildContextAndCustomModuleFoo(t *testing.T, bp string) (*TestContext, *cus } func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) { + if runtime.GOOS == "darwin" { + // Device modules are not exported on Mac, so this test doesn't work. + t.SkipNow() + } + bp := ` custom { name: "foo", diff --git a/android/arch.go b/android/arch.go index 54242e56d..5e3e9204a 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1587,10 +1587,12 @@ func hasArmAbi(arch Arch) bool { return PrefixInList(arch.Abi, "arm") } -// hasArmArch returns true if targets has at least non-native_bridge arm Android arch +// hasArmAndroidArch returns true if targets has at least +// one arm Android arch (possibly native bridged) func hasArmAndroidArch(targets []Target) bool { for _, target := range targets { - if target.Os == Android && target.Arch.ArchType == Arm { + if target.Os == Android && + (target.Arch.ArchType == Arm || target.Arch.ArchType == Arm64) { return true } } @@ -2006,17 +2008,10 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe osToProp := ArchVariantProperties{} archOsToProp := ArchVariantProperties{} - var linuxStructs, bionicStructs []reflect.Value - var ok bool - - linuxStructs, ok = getTargetStructs(ctx, archProperties, "Linux") - if !ok { - linuxStructs = make([]reflect.Value, 0) - } - bionicStructs, ok = getTargetStructs(ctx, archProperties, "Bionic") - if !ok { - bionicStructs = make([]reflect.Value, 0) - } + linuxStructs := getTargetStructs(ctx, archProperties, "Linux") + bionicStructs := getTargetStructs(ctx, archProperties, "Bionic") + hostStructs := getTargetStructs(ctx, archProperties, "Host") + hostNotWindowsStructs := getTargetStructs(ctx, archProperties, "Not_windows") // For android, linux, ... for _, os := range osTypeList { @@ -2025,9 +2020,10 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe continue } osStructs := make([]reflect.Value, 0) - osSpecificStructs, ok := getTargetStructs(ctx, archProperties, os.Field) - if ok { - osStructs = append(osStructs, osSpecificStructs...) + + osSpecificStructs := getTargetStructs(ctx, archProperties, os.Field) + if os.Class == Host { + osStructs = append(osStructs, hostStructs...) } if os.Linux() { osStructs = append(osStructs, linuxStructs...) @@ -2035,37 +2031,44 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe if os.Bionic() { osStructs = append(osStructs, bionicStructs...) } + + if os == LinuxMusl { + osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Musl")...) + } + if os == Linux { + osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Glibc")...) + } + + osStructs = append(osStructs, osSpecificStructs...) + + if os.Class == Host && os != Windows { + osStructs = append(osStructs, hostNotWindowsStructs...) + } osToProp[os.Name] = mergeStructs(ctx, osStructs, propertySet) // For arm, x86, ... for _, arch := range osArchTypeMap[os] { osArchStructs := make([]reflect.Value, 0) - targetField := GetCompoundTargetField(os, arch) - targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name) - targetStructs, ok := getTargetStructs(ctx, archProperties, targetField) - if ok { - osArchStructs = append(osArchStructs, targetStructs...) - } - // Auto-combine with Linux_ and Bionic_ targets. This potentially results in // repetition and select() bloat, but use of Linux_* and Bionic_* targets is rare. // TODO(b/201423152): Look into cleanup. if os.Linux() { targetField := "Linux_" + arch.Name - targetStructs, ok := getTargetStructs(ctx, archProperties, targetField) - if ok { - osArchStructs = append(osArchStructs, targetStructs...) - } + targetStructs := getTargetStructs(ctx, archProperties, targetField) + osArchStructs = append(osArchStructs, targetStructs...) } if os.Bionic() { targetField := "Bionic_" + arch.Name - targetStructs, ok := getTargetStructs(ctx, archProperties, targetField) - if ok { - osArchStructs = append(osArchStructs, targetStructs...) - } + targetStructs := getTargetStructs(ctx, archProperties, targetField) + osArchStructs = append(osArchStructs, targetStructs...) } + targetField := GetCompoundTargetField(os, arch) + targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name) + targetStructs := getTargetStructs(ctx, archProperties, targetField) + osArchStructs = append(osArchStructs, targetStructs...) + archOsToProp[targetName] = mergeStructs(ctx, osArchStructs, propertySet) } } @@ -2089,8 +2092,8 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe // } // } // This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"] -func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) ([]reflect.Value, bool) { - propertyStructs := make([]reflect.Value, 0) +func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value { + var propertyStructs []reflect.Value for _, archProperty := range archProperties { archPropValues := reflect.ValueOf(archProperty).Elem() targetProp := archPropValues.FieldByName("Target").Elem() @@ -2098,11 +2101,11 @@ func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targ if ok { propertyStructs = append(propertyStructs, targetStruct) } else { - return propertyStructs, false + return []reflect.Value{} } } - return propertyStructs, true + return propertyStructs } func mergeStructs(ctx ArchVariantContext, propertyStructs []reflect.Value, propertySet interface{}) interface{} { diff --git a/android/bazel.go b/android/bazel.go index 6aba75984..5dda65537 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -182,8 +182,8 @@ var ( "external/boringssl": Bp2BuildDefaultTrueRecursively, "external/brotli": Bp2BuildDefaultTrue, "external/fmtlib": Bp2BuildDefaultTrueRecursively, - "external/googletest/googletest": Bp2BuildDefaultTrueRecursively, "external/google-benchmark": Bp2BuildDefaultTrueRecursively, + "external/googletest/googletest": Bp2BuildDefaultTrueRecursively, "external/gwp_asan": Bp2BuildDefaultTrueRecursively, "external/jemalloc_new": Bp2BuildDefaultTrueRecursively, "external/jsoncpp": Bp2BuildDefaultTrueRecursively, @@ -191,10 +191,15 @@ var ( "external/libcxx": Bp2BuildDefaultTrueRecursively, "external/libcxxabi": Bp2BuildDefaultTrueRecursively, "external/lz4/lib": Bp2BuildDefaultTrue, + "external/mdnsresponder": Bp2BuildDefaultTrueRecursively, + "external/minijail": Bp2BuildDefaultTrueRecursively, + "external/pcre": Bp2BuildDefaultTrueRecursively, "external/protobuf": Bp2BuildDefaultTrueRecursively, "external/python/six": Bp2BuildDefaultTrueRecursively, "external/scudo": Bp2BuildDefaultTrueRecursively, + "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively, "external/zlib": Bp2BuildDefaultTrueRecursively, + "external/zstd": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively, "packages/modules/adb": Bp2BuildDefaultTrue, "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively, @@ -208,6 +213,7 @@ var ( "system/core/libasyncio": Bp2BuildDefaultTrue, "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively, "system/core/libcutils": Bp2BuildDefaultTrueRecursively, + "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively, "system/core/libprocessgroup": Bp2BuildDefaultTrue, "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue, "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue, @@ -237,10 +243,21 @@ var ( "brotli-fuzzer-corpus", // b/202015218: outputs are in location incompatible with bazel genrule handling. + // b/203369847: multiple genrules in the same package creating the same file + // //development/sdk/... + "platform_tools_properties", + "build_tools_source_properties", + // //external/libcap/... "libcap", // http://b/198595332, depends on _makenames, a cc_binary "cap_names.h", // http://b/198596102, depends on _makenames, a cc_binary + "libminijail", // depends on unconverted modules: libcap + "getcap", // depends on unconverted modules: libcap + "setcap", // depends on unconverted modules: libcap + "minijail0", // depends on unconverted modules: libcap, libminijail + "drop_privs", // depends on unconverted modules: libminijail + // Tests. Handle later. "libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found "libjemalloc5_integrationtest", @@ -266,6 +283,20 @@ var ( "libgtest_ndk_c++", // b/201816222: Requires sdk_version support. "libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support. + + "abb", // depends on unconverted modules: libadbd_core, libadbd_services, libcmd, libbinder, libutils, libselinux + "adb", // depends on unconverted modules: bin2c_fastdeployagent, libadb_crypto, libadb_host, libadb_pairing_connection, libadb_protos, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libmdnssd, libopenscreen-discovery, libopenscreen-platform-impl, libusb, libutils, libziparchive, libzstd, AdbWinApi + "adbd", // depends on unconverted modules: libadb_crypto, libadb_pairing_connection, libadb_protos, libadbd, libadbd_core, libapp_processes_protos_lite, libmdnssd, libzstd, libadbd_services, libcap, libminijail, libselinux + "bionic_tests_zipalign", // depends on unconverted modules: libziparchive, libutils + "linker", // depends on unconverted modules: liblinker_debuggerd_stub, libdebuggerd_handler_fallback, libziparchive, liblinker_main, liblinker_malloc + "linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_* + "sefcontext_compile", // depends on unconverted modules: libsepol + "versioner", // depends on unconverted modules: libclang_cxx_host, libLLVM_host + + "linkerconfig", // http://b/202876379 has arch-variant static_executable + "mdnsd", // http://b/202876379 has arch-variant static_executable + + "acvp_modulewrapper", // disabled for android x86/x86_64 } // Per-module denylist of cc_library modules to only generate the static @@ -282,7 +313,7 @@ var ( "libseccomp_policy_app_zygote_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module. "libseccomp_policy_app_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module. "libseccomp_policy_system_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module. - + "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module. } // Used for quicker lookups diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 06712a1ea..3c6212e0c 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -48,11 +48,17 @@ type cqueryRequest interface { StarlarkFunctionBody() string } +// Portion of cquery map key to describe target configuration. +type configKey struct { + archType ArchType + osType OsType +} + // Map key to describe bazel cquery requests. type cqueryKey struct { label string requestType cqueryRequest - archType ArchType + configKey configKey } // bazelHandler is the interface for a helper object related to deferring to Bazel for @@ -72,14 +78,14 @@ type BazelContext interface { // has been queued to be run later. // Returns result files built by building the given bazel target label. - GetOutputFiles(label string, archType ArchType) ([]string, bool) + GetOutputFiles(label string, cfgKey configKey) ([]string, bool) // TODO(cparsons): Other cquery-related methods should be added here. // Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order). - GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) + GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) // Returns the executable binary resultant from building together the python sources - GetPythonBinary(label string, archType ArchType) (string, bool) + GetPythonBinary(label string, cfgKey configKey) (string, bool) // ** End cquery methods @@ -140,17 +146,17 @@ type MockBazelContext struct { LabelToPythonBinary map[string]string } -func (m MockBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) { +func (m MockBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) { result, ok := m.LabelToOutputFiles[label] return result, ok } -func (m MockBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) { +func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) { result, ok := m.LabelToCcInfo[label] return result, ok, nil } -func (m MockBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) { +func (m MockBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) { result, ok := m.LabelToPythonBinary[label] return result, ok } @@ -171,8 +177,8 @@ func (m MockBazelContext) BuildStatementsToRegister() []bazel.BuildStatement { var _ BazelContext = MockBazelContext{} -func (bazelCtx *bazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) { - rawString, ok := bazelCtx.cquery(label, cquery.GetOutputFiles, archType) +func (bazelCtx *bazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) { + rawString, ok := bazelCtx.cquery(label, cquery.GetOutputFiles, cfgKey) var ret []string if ok { bazelOutput := strings.TrimSpace(rawString) @@ -181,8 +187,8 @@ func (bazelCtx *bazelContext) GetOutputFiles(label string, archType ArchType) ([ return ret, ok } -func (bazelCtx *bazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) { - result, ok := bazelCtx.cquery(label, cquery.GetCcInfo, archType) +func (bazelCtx *bazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) { + result, ok := bazelCtx.cquery(label, cquery.GetCcInfo, cfgKey) if !ok { return cquery.CcInfo{}, ok, nil } @@ -192,8 +198,8 @@ func (bazelCtx *bazelContext) GetCcInfo(label string, archType ArchType) (cquery return ret, ok, err } -func (bazelCtx *bazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) { - rawString, ok := bazelCtx.cquery(label, cquery.GetPythonBinary, archType) +func (bazelCtx *bazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) { + rawString, ok := bazelCtx.cquery(label, cquery.GetPythonBinary, cfgKey) var ret string if ok { bazelOutput := strings.TrimSpace(rawString) @@ -202,19 +208,15 @@ func (bazelCtx *bazelContext) GetPythonBinary(label string, archType ArchType) ( return ret, ok } -func (n noopBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) { +func (n noopBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) { panic("unimplemented") } -func (n noopBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) { +func (n noopBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) { panic("unimplemented") } -func (n noopBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) { - panic("unimplemented") -} - -func (n noopBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) { +func (n noopBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) { panic("unimplemented") } @@ -303,8 +305,8 @@ func (context *bazelContext) BazelEnabled() bool { // returns (result, true). If the request is queued but no results are available, // then returns ("", false). func (context *bazelContext) cquery(label string, requestType cqueryRequest, - archType ArchType) (string, bool) { - key := cqueryKey{label, requestType, archType} + cfgKey configKey) (string, bool) { + key := cqueryKey{label, requestType, cfgKey} if result, ok := context.results[key]; ok { return result, true } else { @@ -419,7 +421,7 @@ func (context *bazelContext) mainBzlFileContents() []byte { def _config_node_transition_impl(settings, attr): return { - "//command_line_option:platforms": "@//build/bazel/platforms:android_%s" % attr.arch, + "//command_line_option:platforms": "@//build/bazel/platforms:%s_%s" % (attr.os, attr.arch), } _config_node_transition = transition( @@ -437,7 +439,8 @@ config_node = rule( implementation = _passthrough_rule_impl, attrs = { "arch" : attr.string(mandatory = True), - "deps" : attr.label_list(cfg = _config_node_transition), + "os" : attr.string(mandatory = True), + "deps" : attr.label_list(cfg = _config_node_transition, allow_files = True), "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"), }, ) @@ -488,38 +491,32 @@ phony_root(name = "phonyroot", configNodeFormatString := ` config_node(name = "%s", arch = "%s", + os = "%s", deps = [%s], ) ` - commonArchFilegroupString := ` -filegroup(name = "common", - srcs = [%s], -) -` - configNodesSection := "" - labelsByArch := map[string][]string{} + labelsByConfig := map[string][]string{} for val, _ := range context.requests { labelString := fmt.Sprintf("\"@%s\"", val.label) - archString := getArchString(val) - labelsByArch[archString] = append(labelsByArch[archString], labelString) + configString := getConfigString(val) + labelsByConfig[configString] = append(labelsByConfig[configString], labelString) } allLabels := []string{} - for archString, labels := range labelsByArch { - if archString == "common" { - // arch-less labels (e.g. filegroups) don't need a config_node - allLabels = append(allLabels, "\":common\"") - labelsString := strings.Join(labels, ",\n ") - configNodesSection += fmt.Sprintf(commonArchFilegroupString, labelsString) - } else { - // Create a config_node, and add the config_node's label to allLabels - allLabels = append(allLabels, fmt.Sprintf("\":%s\"", archString)) - labelsString := strings.Join(labels, ",\n ") - configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString) + for configString, labels := range labelsByConfig { + configTokens := strings.Split(configString, "|") + if len(configTokens) != 2 { + panic(fmt.Errorf("Unexpected config string format: %s", configString)) } + archString := configTokens[0] + osString := configTokens[1] + targetString := fmt.Sprintf("%s_%s", osString, archString) + allLabels = append(allLabels, fmt.Sprintf("\":%s\"", targetString)) + labelsString := strings.Join(labels, ",\n ") + configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, labelsString) } return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n "))) @@ -587,11 +584,15 @@ def %s(target): %s def get_arch(target): + # TODO(b/199363072): filegroups and file targets aren't associated with any + # specific platform architecture in mixed builds. This is consistent with how + # Soong treats filegroups, but it may not be the case with manually-written + # filegroup BUILD targets. buildoptions = build_options(target) if buildoptions == None: # File targets do not have buildoptions. File targets aren't associated with - # any specific platform architecture in mixed builds. - return "common" + # any specific platform architecture in mixed builds, so use the host. + return "x86_64|linux" platforms = build_options(target)["//command_line_option:platforms"] if len(platforms) != 1: # An individual configured target should have only one platform architecture. @@ -601,10 +602,12 @@ def get_arch(target): platform_name = build_options(target)["//command_line_option:platforms"][0].name if platform_name == "host": return "HOST" + elif platform_name.startswith("linux_glibc_"): + return platform_name[len("linux_glibc_"):] + "|" + platform_name[:len("linux_glibc_")-1] elif platform_name.startswith("android_"): - return platform_name[len("android_"):] + return platform_name[len("android_"):] + "|" + platform_name[:len("android_")-1] elif platform_name.startswith("linux_"): - return platform_name[len("linux_"):] + return platform_name[len("linux_"):] + "|" + platform_name[:len("linux_")-1] else: fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms)) return "UNKNOWN" @@ -852,14 +855,23 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { } func getCqueryId(key cqueryKey) string { - return key.label + "|" + getArchString(key) + return key.label + "|" + getConfigString(key) } -func getArchString(key cqueryKey) string { - arch := key.archType.Name - if len(arch) > 0 { - return arch - } else { - return "x86_64" +func getConfigString(key cqueryKey) string { + arch := key.configKey.archType.Name + if len(arch) == 0 || arch == "common" { + // Use host platform, which is currently hardcoded to be x86_64. + arch = "x86_64" } + os := key.configKey.osType.Name + if len(os) == 0 || os == "common_os" { + // Use host OS, which is currently hardcoded to be linux. + os = "linux" + } + return arch + "|" + os +} + +func GetConfigKey(ctx ModuleContext) configKey { + return configKey{archType: ctx.Arch().ArchType, osType: ctx.Os()} } diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go index fe66a9092..ad5b63bae 100644 --- a/android/bazel_handler_test.go +++ b/android/bazel_handler_test.go @@ -9,11 +9,11 @@ import ( func TestRequestResultsAfterInvokeBazel(t *testing.T) { label := "//foo:bar" - arch := Arm64 + cfg := configKey{Arm64, Android} bazelContext, _ := testBazelContext(t, map[bazelCommand]string{ - bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64>>out/foo/bar.txt`, + bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64|android>>out/foo/bar.txt`, }) - g, ok := bazelContext.GetOutputFiles(label, arch) + g, ok := bazelContext.GetOutputFiles(label, cfg) if ok { t.Errorf("Did not expect cquery results prior to running InvokeBazel(), but got %s", g) } @@ -21,7 +21,7 @@ func TestRequestResultsAfterInvokeBazel(t *testing.T) { if err != nil { t.Fatalf("Did not expect error invoking Bazel, but got %s", err) } - g, ok = bazelContext.GetOutputFiles(label, arch) + g, ok = bazelContext.GetOutputFiles(label, cfg) if !ok { t.Errorf("Expected cquery results after running InvokeBazel(), but got none") } else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) { diff --git a/android/config.go b/android/config.go index c8d7cfdc9..6060bce7c 100644 --- a/android/config.go +++ b/android/config.go @@ -1578,6 +1578,10 @@ func (c *deviceConfig) SepolicyFreezeTestExtraPrebuiltDirs() []string { return c.config.productVariables.SepolicyFreezeTestExtraPrebuiltDirs } +func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool { + return c.config.productVariables.GenerateAidlNdkPlatformBackend +} + // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs. // Such lists are used in the build system for things like bootclasspath jars or system server jars. // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a diff --git a/android/filegroup.go b/android/filegroup.go index f8f095586..a79374d1f 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -118,14 +118,16 @@ func (fg *fileGroup) maybeGenerateBazelBuildActions(ctx ModuleContext) { } archVariant := ctx.Arch().ArchType + osVariant := ctx.Os() if len(fg.Srcs()) == 1 && fg.Srcs()[0].Base() == fg.Name() { // This will be a regular file target, not filegroup, in Bazel. // See FilegroupBp2Build for more information. archVariant = Common + osVariant = CommonOS } bazelCtx := ctx.Config().BazelContext - filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), archVariant) + filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{archVariant, osVariant}) if !ok { return } diff --git a/android/module.go b/android/module.go index 327e6ae20..02706eccb 100644 --- a/android/module.go +++ b/android/module.go @@ -2818,11 +2818,13 @@ func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPat } func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec { + licenseFiles := m.Module().EffectiveLicenseFiles() spec := PackagingSpec{ - relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()), - srcPath: srcPath, - symlinkTarget: "", - executable: executable, + relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()), + srcPath: srcPath, + symlinkTarget: "", + executable: executable, + effectiveLicenseFiles: &licenseFiles, } m.packagingSpecs = append(m.packagingSpecs, spec) return spec diff --git a/android/neverallow.go b/android/neverallow.go index b8517a986..9098a718e 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -150,6 +150,7 @@ func createTrebleRules() []Rule { func createJavaDeviceForHostRules() []Rule { javaDeviceForHostProjectsAllowedList := []string{ + "development/build", "external/guava", "external/robolectric-shadows", "frameworks/layoutlib", diff --git a/android/notices.go b/android/notices.go index 07cf3e4d0..d8cfaf2a1 100644 --- a/android/notices.go +++ b/android/notices.go @@ -100,3 +100,56 @@ func BuildNoticeOutput(ctx ModuleContext, installPath InstallPath, installFilena HtmlGzOutput: OptionalPathForPath(htmlGzOutput), } } + +// BuildNotices merges the supplied NOTICE files into a single file that lists notices +// for every key in noticeMap (which would normally be installed files). +func BuildNotices(ctx ModuleContext, noticeMap map[string]Paths) NoticeOutputs { + // TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass. + // + // generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules + // about input NOTICE file paths. + // 1. Their relative paths to the src root become their NOTICE index titles. We want to use + // on-device paths as titles, and so output the merged NOTICE file the corresponding location. + // 2. They must end with .txt extension. Otherwise, they're ignored. + + mergeTool := PathForSource(ctx, "build/soong/scripts/mergenotice.py") + generateNoticeTool := PathForSource(ctx, "build/soong/scripts/generate-notice-files.py") + + outputDir := PathForModuleOut(ctx, "notices") + builder := NewRuleBuilder(pctx, ctx). + Sbox(outputDir, PathForModuleOut(ctx, "notices.sbox.textproto")) + for _, installPath := range SortedStringKeys(noticeMap) { + noticePath := outputDir.Join(ctx, installPath+".txt") + // It would be nice if sbox created directories for temporaries, but until then + // this is simple enough. + builder.Command(). + Text("(cd").OutputDir().Text("&&"). + Text("mkdir -p").Text(filepath.Dir(installPath)).Text(")") + builder.Temporary(noticePath) + builder.Command(). + Tool(mergeTool). + Flag("--output").Output(noticePath). + Inputs(noticeMap[installPath]) + } + + // Transform the merged NOTICE file into a gzipped HTML file. + txtOutput := outputDir.Join(ctx, "NOTICE.txt") + htmlOutput := outputDir.Join(ctx, "NOTICE.html") + htmlGzOutput := outputDir.Join(ctx, "NOTICE.html.gz") + title := "\"Notices for " + ctx.ModuleName() + "\"" + builder.Command().Tool(generateNoticeTool). + FlagWithOutput("--text-output ", txtOutput). + FlagWithOutput("--html-output ", htmlOutput). + FlagWithArg("-t ", title). + Flag("-s").OutputDir() + builder.Command().BuiltTool("minigzip"). + FlagWithInput("-c ", htmlOutput). + FlagWithOutput("> ", htmlGzOutput) + builder.Build("build_notices", "generate notice output") + + return NoticeOutputs{ + TxtOutput: OptionalPathForPath(txtOutput), + HtmlOutput: OptionalPathForPath(htmlOutput), + HtmlGzOutput: OptionalPathForPath(htmlGzOutput), + } +} diff --git a/android/packaging.go b/android/packaging.go index 906582667..e3a0b54be 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -38,6 +38,8 @@ type PackagingSpec struct { // Whether relPathInPackage should be marked as executable or not executable bool + + effectiveLicenseFiles *Paths } // Get file name of installed package @@ -54,6 +56,17 @@ func (p *PackagingSpec) RelPathInPackage() string { return p.relPathInPackage } +func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) { + p.relPathInPackage = relPathInPackage +} + +func (p *PackagingSpec) EffectiveLicenseFiles() Paths { + if p.effectiveLicenseFiles == nil { + return Paths{} + } + return *p.effectiveLicenseFiles +} + type PackageModule interface { Module packagingBase() *PackagingBase @@ -214,15 +227,9 @@ func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]Packa return m } -// See PackageModule.CopyDepsToZip -func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) { - m := p.GatherPackagingSpecs(ctx) - builder := NewRuleBuilder(pctx, ctx) - - dir := PathForModuleOut(ctx, ".zip") - builder.Command().Text("rm").Flag("-rf").Text(dir.String()) - builder.Command().Text("mkdir").Flag("-p").Text(dir.String()) - +// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec +// entries into the specified directory. +func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, m map[string]PackagingSpec, dir ModuleOutPath) (entries []string) { seenDir := make(map[string]bool) for _, k := range SortedStringKeys(m) { ps := m[k] @@ -243,6 +250,19 @@ func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (e } } + return entries +} + +// See PackageModule.CopyDepsToZip +func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) { + m := p.GatherPackagingSpecs(ctx) + builder := NewRuleBuilder(pctx, ctx) + + dir := PathForModuleOut(ctx, ".zip") + builder.Command().Text("rm").Flag("-rf").Text(dir.String()) + builder.Command().Text("mkdir").Flag("-p").Text(dir.String()) + entries = p.CopySpecsToDir(ctx, builder, m, dir) + builder.Command(). BuiltTool("soong_zip"). FlagWithOutput("-o ", zipOut). diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go index b2f8eaad8..0ec9bcbd5 100644 --- a/android/soong_config_modules_test.go +++ b/android/soong_config_modules_test.go @@ -60,7 +60,7 @@ func TestSoongConfigModule(t *testing.T) { module_type: "test", config_namespace: "acme", variables: ["board", "feature1", "FEATURE3", "unused_string_var"], - bool_variables: ["feature2", "unused_feature"], + bool_variables: ["feature2", "unused_feature", "always_true"], value_variables: ["size", "unused_size"], properties: ["cflags", "srcs", "defaults"], } @@ -148,6 +148,11 @@ func TestSoongConfigModule(t *testing.T) { cflags: ["DEFAULT_B"], } + test_defaults { + name: "foo_defaults_always_true", + cflags: ["DEFAULT_ALWAYS_TRUE"], + } + acme_test { name: "foo_with_defaults", cflags: ["-DGENERIC"], @@ -176,6 +181,15 @@ func TestSoongConfigModule(t *testing.T) { FEATURE3: { cflags: ["-DFEATURE3"], }, + always_true: { + defaults: ["foo_defaults_always_true"], + conditions_default: { + // verify that conditions_default is skipped if the + // soong config variable is true by specifying a + // non-existent module in conditions_default + defaults: ["//nonexistent:defaults"], + } + }, }, } ` @@ -205,6 +219,7 @@ func TestSoongConfigModule(t *testing.T) { "unused_feature": "true", // unused "unused_size": "1", // unused "unused_string_var": "a", // unused + "always_true": "true", }, }), fooExpectedFlags: []string{ @@ -217,6 +232,7 @@ func TestSoongConfigModule(t *testing.T) { }, fooDefaultsExpectedFlags: []string{ "DEFAULT_A", + "DEFAULT_ALWAYS_TRUE", "DEFAULT", "-DGENERIC", "-DSIZE=42", @@ -227,7 +243,10 @@ func TestSoongConfigModule(t *testing.T) { { name: "empty_prop_for_string_var", preparer: fixtureForVendorVars(map[string]map[string]string{ - "acme": {"board": "soc_c"}}), + "acme": { + "board": "soc_c", + "always_true": "true", + }}), fooExpectedFlags: []string{ "DEFAULT", "-DGENERIC", @@ -236,6 +255,7 @@ func TestSoongConfigModule(t *testing.T) { "-DF1_CONDITIONS_DEFAULT", }, fooDefaultsExpectedFlags: []string{ + "DEFAULT_ALWAYS_TRUE", "DEFAULT", "-DGENERIC", }, @@ -243,7 +263,10 @@ func TestSoongConfigModule(t *testing.T) { { name: "unused_string_var", preparer: fixtureForVendorVars(map[string]map[string]string{ - "acme": {"board": "soc_d"}}), + "acme": { + "board": "soc_d", + "always_true": "true", + }}), fooExpectedFlags: []string{ "DEFAULT", "-DGENERIC", @@ -253,14 +276,18 @@ func TestSoongConfigModule(t *testing.T) { "-DF1_CONDITIONS_DEFAULT", }, fooDefaultsExpectedFlags: []string{ + "DEFAULT_ALWAYS_TRUE", "DEFAULT", "-DGENERIC", }, }, { - name: "conditions_default", - preparer: fixtureForVendorVars(map[string]map[string]string{}), + name: "conditions_default", + preparer: fixtureForVendorVars(map[string]map[string]string{ + "acme": { + "always_true": "true", + }}), fooExpectedFlags: []string{ "DEFAULT", "-DGENERIC", @@ -270,6 +297,7 @@ func TestSoongConfigModule(t *testing.T) { "-DF1_CONDITIONS_DEFAULT", }, fooDefaultsExpectedFlags: []string{ + "DEFAULT_ALWAYS_TRUE", "DEFAULT", "-DGENERIC", }, diff --git a/android/variable.go b/android/variable.go index 4a82f23d3..baa6dfac3 100644 --- a/android/variable.go +++ b/android/variable.go @@ -40,6 +40,7 @@ type variableProperties struct { Platform_sdk_version struct { Asflags []string Cflags []string + Cmd *string } Platform_sdk_version_or_codename struct { @@ -50,6 +51,10 @@ type variableProperties struct { Cmd *string } + Platform_version_name struct { + Base_dir *string + } + // unbundled_build is a catch-all property to annotate modules that don't build in one or // more unbundled branches, usually due to dependencies missing from the manifest. Unbundled_build struct { @@ -414,6 +419,8 @@ type productVariables struct { SepolicyFreezeTestExtraDirs []string `json:",omitempty"` SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"` + + GenerateAidlNdkPlatformBackend bool `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/android_sdk/Android.bp b/android_sdk/Android.bp new file mode 100644 index 000000000..e686d59ff --- /dev/null +++ b/android_sdk/Android.bp @@ -0,0 +1,22 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-android-sdk", + pkgPath: "android/soong/android_sdk", + deps: [ + "blueprint", + "soong", + "soong-android", + "soong-cc", + "soong-cc-config", + ], + srcs: [ + "sdk_repo_host.go", + ], + testSrcs: [ + "sdk_repo_host_test.go", + ], + pluginFor: ["soong_build"], +} diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go new file mode 100644 index 000000000..d64eb7a92 --- /dev/null +++ b/android_sdk/sdk_repo_host.go @@ -0,0 +1,294 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android_sdk + +import ( + "fmt" + "io" + "path/filepath" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" + + "android/soong/android" + "android/soong/cc/config" +) + +var pctx = android.NewPackageContext("android/soong/android_sdk") + +func init() { + registerBuildComponents(android.InitRegistrationContext) +} + +func registerBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("android_sdk_repo_host", SdkRepoHostFactory) +} + +type sdkRepoHost struct { + android.ModuleBase + android.PackagingBase + + properties sdkRepoHostProperties + + outputBaseName string + outputFile android.OptionalPath +} + +type remapProperties struct { + From string + To string +} + +type sdkRepoHostProperties struct { + // The top level directory to use for the SDK repo. + Base_dir *string + + // List of src:dst mappings to rename files from `deps`. + Deps_remap []remapProperties `android:"arch_variant"` + + // List of zip files to merge into the SDK repo. + Merge_zips []string `android:"arch_variant,path"` + + // List of sources to include into the SDK repo. These are usually raw files, filegroups, + // or genrules, as most built modules should be referenced via `deps`. + Srcs []string `android:"arch_variant,path"` + + // List of files to strip. This should be a list of files, not modules. This happens after + // `deps_remap` and `merge_zips` are applied, but before the `base_dir` is added. + Strip_files []string `android:"arch_variant"` +} + +// android_sdk_repo_host defines an Android SDK repo containing host tools. +// +// This implementation is trying to be a faithful reproduction of how these sdk-repos were produced +// in the Make system, which may explain some of the oddities (like `strip_files` not being +// automatic) +func SdkRepoHostFactory() android.Module { + return newSdkRepoHostModule() +} + +func newSdkRepoHostModule() *sdkRepoHost { + s := &sdkRepoHost{} + s.AddProperties(&s.properties) + android.InitPackageModule(s) + android.InitAndroidMultiTargetsArchModule(s, android.HostSupported, android.MultilibCommon) + return s +} + +type dependencyTag struct { + blueprint.BaseDependencyTag + android.PackagingItemAlwaysDepTag +} + +// TODO(b/201696252): Evaluate whether licenses should be propagated through this dependency. +func (d dependencyTag) PropagateLicenses() bool { + return false +} + +var depTag = dependencyTag{} + +func (s *sdkRepoHost) DepsMutator(ctx android.BottomUpMutatorContext) { + s.AddDeps(ctx, depTag) +} + +func (s *sdkRepoHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { + dir := android.PathForModuleOut(ctx, "zip") + builder := android.NewRuleBuilder(pctx, ctx). + Sbox(dir, android.PathForModuleOut(ctx, "out.sbox.textproto")). + SandboxInputs() + + // Get files from modules listed in `deps` + packageSpecs := s.GatherPackagingSpecs(ctx) + + // Handle `deps_remap` renames + err := remapPackageSpecs(packageSpecs, s.properties.Deps_remap) + if err != nil { + ctx.PropertyErrorf("deps_remap", "%s", err.Error()) + } + + s.CopySpecsToDir(ctx, builder, packageSpecs, dir) + + // Collect licenses to write into NOTICE.txt + noticeMap := map[string]android.Paths{} + for path, pkgSpec := range packageSpecs { + licenseFiles := pkgSpec.EffectiveLicenseFiles() + if len(licenseFiles) > 0 { + noticeMap[path] = pkgSpec.EffectiveLicenseFiles() + } + } + notices := android.BuildNotices(ctx, noticeMap) + builder.Command().Text("cp"). + Input(notices.TxtOutput.Path()). + Text(filepath.Join(dir.String(), "NOTICE.txt")) + + // Handle `merge_zips` by extracting their contents into our tmpdir + for _, zip := range android.PathsForModuleSrc(ctx, s.properties.Merge_zips) { + builder.Command(). + Text("unzip"). + Flag("-DD"). + Flag("-q"). + FlagWithArg("-d ", dir.String()). + Input(zip) + } + + // Copy files from `srcs` into our tmpdir + for _, src := range android.PathsForModuleSrc(ctx, s.properties.Srcs) { + builder.Command(). + Text("cp").Input(src).Flag(dir.Join(ctx, src.Rel()).String()) + } + + // Handle `strip_files` by calling the necessary strip commands + // + // Note: this stripping logic was copied over from the old Make implementation + // It's not using the same flags as the regular stripping support, nor does it + // support the array of per-module stripping options. It would be nice if we + // pulled the stripped versions from the CC modules, but that doesn't exist + // for host tools today. (And not all the things we strip are CC modules today) + if ctx.Darwin() { + macStrip := config.MacStripPath(ctx) + for _, strip := range s.properties.Strip_files { + builder.Command(). + Text(macStrip).Flag("-x"). + Flag(dir.Join(ctx, strip).String()) + } + } else { + llvmStrip := config.ClangPath(ctx, "bin/llvm-strip") + llvmLib := config.ClangPath(ctx, "lib64/libc++.so.1") + for _, strip := range s.properties.Strip_files { + cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib) + if !ctx.Windows() { + cmd.Flag("-x") + } + cmd.Flag(dir.Join(ctx, strip).String()) + } + } + + // Fix up the line endings of all text files. This also removes executable permissions. + builder.Command(). + Text("find"). + Flag(dir.String()). + Flag("-name '*.aidl' -o -name '*.css' -o -name '*.html' -o -name '*.java'"). + Flag("-o -name '*.js' -o -name '*.prop' -o -name '*.template'"). + Flag("-o -name '*.txt' -o -name '*.windows' -o -name '*.xml' -print0"). + // Using -n 500 for xargs to limit the max number of arguments per call to line_endings + // to 500. This avoids line_endings failing with "arguments too long". + Text("| xargs -0 -n 500 "). + BuiltTool("line_endings"). + Flag("unix") + + // Exclude some file types (roughly matching sdk.exclude.atree) + builder.Command(). + Text("find"). + Flag(dir.String()). + Flag("'('"). + Flag("-name '.*' -o -name '*~' -o -name 'Makefile' -o -name 'Android.mk' -o"). + Flag("-name '.*.swp' -o -name '.DS_Store' -o -name '*.pyc' -o -name 'OWNERS' -o"). + Flag("-name 'MODULE_LICENSE_*' -o -name '*.ezt' -o -name 'Android.bp'"). + Flag("')' -print0"). + Text("| xargs -0 -r rm -rf") + builder.Command(). + Text("find"). + Flag(dir.String()). + Flag("-name '_*' ! -name '__*' -print0"). + Text("| xargs -0 -r rm -rf") + + if ctx.Windows() { + // Fix EOL chars to make window users happy + builder.Command(). + Text("find"). + Flag(dir.String()). + Flag("-maxdepth 2 -name '*.bat' -type f -print0"). + Text("| xargs -0 -r unix2dos") + } + + // Zip up our temporary directory as the sdk-repo + outputZipFile := dir.Join(ctx, "output.zip") + builder.Command(). + BuiltTool("soong_zip"). + FlagWithOutput("-o ", outputZipFile). + FlagWithArg("-P ", proptools.StringDefault(s.properties.Base_dir, ".")). + FlagWithArg("-C ", dir.String()). + FlagWithArg("-D ", dir.String()) + builder.Command().Text("rm").Flag("-rf").Text(dir.String()) + + builder.Build("build_sdk_repo", "Creating sdk-repo-"+s.BaseModuleName()) + + osName := ctx.Os().String() + if osName == "linux_glibc" { + osName = "linux" + } + name := fmt.Sprintf("sdk-repo-%s-%s", osName, s.BaseModuleName()) + + s.outputBaseName = name + s.outputFile = android.OptionalPathForPath(outputZipFile) + ctx.InstallFile(android.PathForModuleInstall(ctx, "sdk-repo"), name+".zip", outputZipFile) +} + +func (s *sdkRepoHost) AndroidMk() android.AndroidMkData { + return android.AndroidMkData{ + Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + fmt.Fprintln(w, ".PHONY:", name, "sdk_repo", "sdk-repo-"+name) + fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", strings.Join(s.FilesToInstall().Strings(), " ")) + + fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-$(FILE_NAME_TAG).zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName) + }, + } +} + +func remapPackageSpecs(specs map[string]android.PackagingSpec, remaps []remapProperties) error { + for _, remap := range remaps { + for path, spec := range specs { + if match, err := pathtools.Match(remap.From, path); err != nil { + return fmt.Errorf("Error parsing %q: %v", remap.From, err) + } else if match { + newPath := remap.To + if pathtools.IsGlob(remap.From) { + rel, err := filepath.Rel(constantPartOfPattern(remap.From), path) + if err != nil { + return fmt.Errorf("Error handling %q", path) + } + newPath = filepath.Join(remap.To, rel) + } + delete(specs, path) + spec.SetRelPathInPackage(newPath) + specs[newPath] = spec + } + } + } + return nil +} + +func constantPartOfPattern(pattern string) string { + ret := "" + for pattern != "" { + var first string + first, pattern = splitFirst(pattern) + if pathtools.IsGlob(first) { + return ret + } + ret = filepath.Join(ret, first) + } + return ret +} + +func splitFirst(path string) (string, string) { + i := strings.IndexRune(path, filepath.Separator) + if i < 0 { + return path, "" + } + return path[:i], path[i+1:] +} diff --git a/android_sdk/sdk_repo_host_test.go b/android_sdk/sdk_repo_host_test.go new file mode 100644 index 000000000..0688921f4 --- /dev/null +++ b/android_sdk/sdk_repo_host_test.go @@ -0,0 +1,124 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android_sdk + +import ( + "fmt" + "runtime" + "sort" + "testing" + + "android/soong/android" + "android/soong/cc" + + "github.com/google/blueprint/pathtools" +) + +var fixture = android.GroupFixturePreparers( + android.PrepareForIntegrationTestWithAndroid, + cc.PrepareForIntegrationTestWithCc, + android.FixtureRegisterWithContext(registerBuildComponents), +) + +func TestSdkRepoHostDeps(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skipf("Skipping sdk_repo_host testing that is only supported on linux not %s", runtime.GOOS) + } + + result := fixture.RunTestWithBp(t, ` + android_sdk_repo_host { + name: "platform-tools", + } + `) + + // produces "sdk-repo-{OS}-platform-tools.zip" + result.ModuleForTests("platform-tools", "linux_glibc_common").Output("sdk-repo-linux-platform-tools.zip") +} + +func TestRemapPackageSpecs(t *testing.T) { + testcases := []struct { + name string + input []string + remaps []remapProperties + output []string + err string + }{ + { + name: "basic remap", + input: []string{"a", "c"}, + remaps: []remapProperties{ + {From: "a", To: "b"}, + }, + output: []string{"b", "c"}, + }, + { + name: "non-matching remap", + input: []string{"a"}, + remaps: []remapProperties{ + {From: "b", To: "c"}, + }, + output: []string{"a"}, + }, + { + name: "glob", + input: []string{"bin/d", "liba.so", "libb.so", "lib/c.so"}, + remaps: []remapProperties{ + {From: "lib*.so", To: "lib/"}, + }, + output: []string{"bin/d", "lib/c.so", "lib/liba.so", "lib/libb.so"}, + }, + { + name: "bad glob", + input: []string{"a"}, + remaps: []remapProperties{ + {From: "**", To: "./"}, + }, + err: fmt.Sprintf("Error parsing \"**\": %v", pathtools.GlobLastRecursiveErr.Error()), + }, + { + name: "globbed dirs", + input: []string{"a/b/c"}, + remaps: []remapProperties{ + {From: "a/*/c", To: "./"}, + }, + output: []string{"b/c"}, + }, + } + + for _, test := range testcases { + t.Run(test.name, func(t *testing.T) { + specs := map[string]android.PackagingSpec{} + for _, input := range test.input { + spec := android.PackagingSpec{} + spec.SetRelPathInPackage(input) + specs[input] = spec + } + + err := remapPackageSpecs(specs, test.remaps) + + if test.err != "" { + android.AssertErrorMessageEquals(t, "", test.err, err) + } else { + outputs := []string{} + for path, spec := range specs { + android.AssertStringEquals(t, "path does not match rel path", path, spec.RelPathInPackage()) + outputs = append(outputs, path) + } + sort.Strings(outputs) + android.AssertArrayString(t, "outputs mismatch", test.output, outputs) + } + }) + } +} diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go index 963e905cb..f3ad1523b 100644 --- a/androidmk/androidmk/android.go +++ b/androidmk/androidmk/android.go @@ -639,6 +639,12 @@ func prebuiltModulePath(ctx variableAssignmentContext) error { if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" { fixed = val.Strings[1] varname = val.Variables[0].Name.Strings[0] + // TARGET_OUT_OPTIONAL_EXECUTABLES puts the artifact in xbin, which is + // deprecated. TARGET_OUT_DATA_APPS install location will be handled + // automatically by Soong + if varname == "TARGET_OUT_OPTIONAL_EXECUTABLES" || varname == "TARGET_OUT_DATA_APPS" { + return nil + } } else if len(val.Variables) == 2 && varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && varLiteralName(val.Variables[1]) == "TARGET_COPY_OUT_VENDOR" && len(val.Strings) == 3 && val.Strings[0] == "" && val.Strings[1] == "/" { fixed = val.Strings[2] diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go index 9fd4ff943..775a9a88e 100644 --- a/androidmk/androidmk/androidmk_test.go +++ b/androidmk/androidmk/androidmk_test.go @@ -1516,7 +1516,23 @@ android_app { ], } `, - }, + }, { + desc: "Obsolete LOCAL_MODULE_PATH", + in: ` +include $(CLEAR_VARS) +LOCAL_MODULE := foo +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_CTS_TEST_PACKAGE := bar +LOCAL_USE_AAPT2 := blah +include $(BUILD_PACKAGE) +`, + expected: ` +android_app { + name: "foo", + +} +`}, } func TestEndToEnd(t *testing.T) { diff --git a/apex/apex.go b/apex/apex.go index 7ac3bc8d4..1f0618750 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -158,8 +158,8 @@ type apexBundleProperties struct { // is 'image'. Payload_type *string - // The type of filesystem to use when the payload_type is 'image'. Either 'ext4' or 'f2fs'. - // Default 'ext4'. + // The type of filesystem to use when the payload_type is 'image'. Either 'ext4', 'f2fs' + // or 'erofs'. Default 'ext4'. Payload_fs_type *string // For telling the APEX to ignore special handling for system libraries such as bionic. @@ -348,7 +348,6 @@ type apexBundle struct { // Flags for special variants of APEX testApex bool vndkApex bool - artApex bool // Tells whether this variant of the APEX bundle is the primary one or not. Only the primary // one gets installed to the device. @@ -754,13 +753,6 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...) ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...) - if a.artApex { - // With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library. - if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { - ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent") - } - } - // Marks that this APEX (in fact all the modules in it) has to be built with the given SDKs. // This field currently isn't used. // TODO(jiyong): consider dropping this feature @@ -1151,8 +1143,9 @@ const ( zipApexType = "zip" flattenedApexType = "flattened" - ext4FsType = "ext4" - f2fsFsType = "f2fs" + ext4FsType = "ext4" + f2fsFsType = "f2fs" + erofsFsType = "erofs" ) // The suffix for the output "file", not the module @@ -1625,6 +1618,7 @@ type fsType int const ( ext4 fsType = iota f2fs + erofs ) func (f fsType) string() string { @@ -1633,6 +1627,8 @@ func (f fsType) string() string { return ext4FsType case f2fs: return f2fsFsType + case erofs: + return erofsFsType default: panic(fmt.Errorf("unknown APEX payload type %d", f)) } @@ -1679,6 +1675,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { return false } + if mod, ok := child.(android.Module); ok && !mod.Enabled() { + return false + } depName := ctx.OtherModuleName(child) if _, isDirectDep := parent.(*apexBundle); isDirectDep { switch depTag { @@ -2056,8 +2055,10 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.payloadFsType = ext4 case f2fsFsType: a.payloadFsType = f2fs + case erofsFsType: + a.payloadFsType = erofs default: - ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs]", *a.properties.Payload_fs_type) + ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type) } // Optimization. If we are building bundled APEX, for the files that are gathered due to the @@ -2194,10 +2195,9 @@ func newApexBundle() *apexBundle { return module } -func ApexBundleFactory(testApex bool, artApex bool) android.Module { +func ApexBundleFactory(testApex bool) android.Module { bundle := newApexBundle() bundle.testApex = testApex - bundle.artApex = artApex return bundle } diff --git a/apex/apex_test.go b/apex/apex_test.go index 5d7a1be19..78a6bb8f4 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3183,7 +3183,6 @@ func TestMacro(t *testing.T) { "myapex", "otherapex", ], - use_apex_name_macro: true, recovery_available: true, min_sdk_version: "29", } @@ -3198,13 +3197,11 @@ func TestMacro(t *testing.T) { mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"] ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=10000") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__") // APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"] ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=29") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__") // When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and // each variant defines additional macros to distinguish which apex variant it is built for @@ -3213,42 +3210,15 @@ func TestMacro(t *testing.T) { mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__") - // APEX variant has __ANDROID_APEX__ defined - mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__") - - // APEX variant has __ANDROID_APEX__ defined - mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"] - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__") - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__") - // recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__ mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"] ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__") ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__") - // When a dependency of a cc_library sets use_apex_name_macro: true each apex gets a unique - // variant. - // non-APEX variant does not have __ANDROID_APEX__ defined mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__") - // APEX variant has __ANDROID_APEX__ defined - mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"] - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__") - - // APEX variant has __ANDROID_APEX__ defined - mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"] - ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__") - ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__") - // recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__ mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"] ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__") @@ -8289,6 +8259,75 @@ func TestProhibitStaticExecutable(t *testing.T) { `) } +func TestAndroidMk_DexpreoptBuiltInstalledForApex(t *testing.T) { + ctx := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + updatable: false, + java_libs: ["foo"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_library { + name: "foo", + srcs: ["foo.java"], + apex_available: ["myapex"], + installable: true, + } + `, + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), + ) + + apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + data := android.AndroidMkDataForTest(t, ctx, apexBundle) + var builder strings.Builder + data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data) + androidMk := builder.String() + ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex") +} + +func TestAndroidMk_DexpreoptBuiltInstalledForApex_Prebuilt(t *testing.T) { + ctx := testApex(t, ` + prebuilt_apex { + name: "myapex", + arch: { + arm64: { + src: "myapex-arm64.apex", + }, + arm: { + src: "myapex-arm.apex", + }, + }, + exported_java_libs: ["foo"], + } + + java_import { + name: "foo", + jars: ["foo.jar"], + installable: true, + } + `, + dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), + ) + + prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt) + entriesList := android.AndroidMkEntriesForTest(t, ctx, prebuilt) + mainModuleEntries := entriesList[0] + android.AssertArrayString(t, + "LOCAL_REQUIRED_MODULES", + mainModuleEntries.EntryMap["LOCAL_REQUIRED_MODULES"], + []string{ + "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex", + "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex", + }) +} + func TestMain(m *testing.M) { os.Exit(m.Run()) } diff --git a/apex/builder.go b/apex/builder.go index c05c20c47..772f7897a 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -65,6 +65,7 @@ func init() { pctx.HostBinToolVariable("extract_apks", "extract_apks") pctx.HostBinToolVariable("make_f2fs", "make_f2fs") pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs") + pctx.HostBinToolVariable("make_erofs", "make_erofs") pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool") pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh") } @@ -120,7 +121,7 @@ var ( `--payload_type image ` + `--key ${key} ${opt_flags} ${image_dir} ${out} `, CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}", - "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}", + "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}", "${make_erofs}", "${soong_zip}", "${zipalign}", "${aapt2}", "prebuilts/sdk/current/public/android.jar"}, Rspfile: "${out}.copy_commands", RspfileContent: "${copy_commands}", @@ -715,12 +716,10 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { } } apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt") - ndkLibraryList := android.PathForSource(ctx, "system/core/rootdir/etc/public.libraries.android.txt") rule := android.NewRuleBuilder(pctx, ctx) rule.Command(). Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")). Output(apisBackedbyOutputFile). - Input(ndkLibraryList). Flags(libNames) rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex") a.apisBackedByModuleFile = apisBackedbyOutputFile diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 53ef4d787..61e7a0be3 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -264,17 +264,6 @@ func (p *prebuiltCommon) createEntriesForApexFile(fi apexFile, apexName string) // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.jar.jar entries.SetString("LOCAL_MODULE_STEM", strings.TrimSuffix(fi.stem(), ".jar")) - var classesJar android.Path - var headerJar android.Path - if javaModule, ok := fi.module.(java.ApexDependency); ok { - classesJar = javaModule.ImplementationAndResourcesJars()[0] - headerJar = javaModule.HeaderJars()[0] - } else { - classesJar = fi.builtFile - headerJar = fi.builtFile - } - entries.SetString("LOCAL_SOONG_CLASSES_JAR", classesJar.String()) - entries.SetString("LOCAL_SOONG_HEADER_JAR", headerJar.String()) entries.SetString("LOCAL_SOONG_DEX_JAR", fi.builtFile.String()) entries.SetString("LOCAL_DEX_PREOPT", "false") }, diff --git a/bazel/aquery.go b/bazel/aquery.go index 8741afbc5..0dedcf492 100644 --- a/bazel/aquery.go +++ b/bazel/aquery.go @@ -246,7 +246,8 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) { outDir := proptools.ShellEscapeIncludingSpaces(filepath.Dir(out)) out = proptools.ShellEscapeIncludingSpaces(out) in := proptools.ShellEscapeIncludingSpaces(inputPaths[0]) - buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -rsf %[3]s %[2]s", outDir, out, in) + // Use hard links, because some soong actions expect real files (for example, `cp -d`). + buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -f %[3]s %[2]s", outDir, out, in) buildStatement.SymlinkPaths = outputPaths[:] } else if len(actionEntry.Arguments) < 1 { return nil, fmt.Errorf("received action with no command: [%v]", buildStatement) diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go index 43e41554e..88066c8fe 100644 --- a/bazel/aquery_test.go +++ b/bazel/aquery_test.go @@ -859,7 +859,7 @@ func TestSimpleSymlink(t *testing.T) { BuildStatement{ Command: "mkdir -p one/symlink_subdir && " + "rm -f one/symlink_subdir/symlink && " + - "ln -rsf one/file_subdir/file one/symlink_subdir/symlink", + "ln -f one/file_subdir/file one/symlink_subdir/symlink", InputPaths: []string{"one/file_subdir/file"}, OutputPaths: []string{"one/symlink_subdir/symlink"}, SymlinkPaths: []string{"one/symlink_subdir/symlink"}, @@ -923,7 +923,7 @@ func TestSymlinkQuotesPaths(t *testing.T) { BuildStatement{ Command: "mkdir -p 'one/symlink subdir' && " + "rm -f 'one/symlink subdir/symlink' && " + - "ln -rsf 'one/file subdir/file' 'one/symlink subdir/symlink'", + "ln -f 'one/file subdir/file' 'one/symlink subdir/symlink'", InputPaths: []string{"one/file subdir/file"}, OutputPaths: []string{"one/symlink subdir/symlink"}, SymlinkPaths: []string{"one/symlink subdir/symlink"}, diff --git a/bazel/properties.go b/bazel/properties.go index ee32e73ac..6a06c1bab 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -164,48 +164,36 @@ func UniqueSortedBazelLabelList(originalLabelList LabelList) LabelList { // Subtract needle from haystack func SubtractStrings(haystack []string, needle []string) []string { // This is really a set - remainder := make(map[string]bool) - - for _, s := range haystack { - remainder[s] = true - } + needleMap := make(map[string]bool) for _, s := range needle { - delete(remainder, s) + needleMap[s] = true } var strings []string - for s, _ := range remainder { - strings = append(strings, s) + for _, s := range haystack { + if exclude := needleMap[s]; !exclude { + strings = append(strings, s) + } } - sort.SliceStable(strings, func(i, j int) bool { - return strings[i] < strings[j] - }) - return strings } // Subtract needle from haystack func SubtractBazelLabels(haystack []Label, needle []Label) []Label { // This is really a set - remainder := make(map[Label]bool) - - for _, label := range haystack { - remainder[label] = true - } - for _, label := range needle { - delete(remainder, label) + needleMap := make(map[Label]bool) + for _, s := range needle { + needleMap[s] = true } var labels []Label - for label, _ := range remainder { - labels = append(labels, label) + for _, label := range haystack { + if exclude := needleMap[label]; !exclude { + labels = append(labels, label) + } } - sort.SliceStable(labels, func(i, j int) bool { - return labels[i].Label < labels[j].Label - }) - return labels } diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go index 45a3cb6fe..b0c3899ba 100644 --- a/bp2build/bp2build.go +++ b/bp2build/bp2build.go @@ -15,11 +15,12 @@ package bp2build import ( - "android/soong/android" - "android/soong/bazel" "fmt" "os" "strings" + + "android/soong/android" + "android/soong/bazel" ) // Codegen is the backend of bp2build. The code generator is responsible for @@ -43,7 +44,7 @@ func Codegen(ctx *CodegenContext) CodegenMetrics { writeFiles(ctx, bp2buildDir, bp2buildFiles) soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName) - writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(res.metrics)) + writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics)) return res.metrics } diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index f14574c06..ee1d862cd 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -223,6 +223,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) { func TestGenerateBazelTargetModules(t *testing.T) { testCases := []bp2buildTestCase{ { + description: "string props", blueprint: `custom { name: "foo", string_list_prop: ["a", "b"], @@ -240,6 +241,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { }, }, { + description: "control characters", blueprint: `custom { name: "control_characters", string_list_prop: ["\t", "\n"], @@ -257,6 +259,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { }, }, { + description: "handles dep", blueprint: `custom { name: "has_dep", arch_paths: [":dep"], @@ -279,25 +282,98 @@ custom { }, }, { + description: "arch-variant srcs", blueprint: `custom { name: "arch_paths", arch: { - x86: { - arch_paths: ["abc"], - }, + x86: { arch_paths: ["x86.txt"] }, + x86_64: { arch_paths: ["x86_64.txt"] }, + arm: { arch_paths: ["arm.txt"] }, + arm64: { arch_paths: ["arm64.txt"] }, + }, + target: { + linux: { arch_paths: ["linux.txt"] }, + bionic: { arch_paths: ["bionic.txt"] }, + host: { arch_paths: ["host.txt"] }, + not_windows: { arch_paths: ["not_windows.txt"] }, + android: { arch_paths: ["android.txt"] }, + linux_musl: { arch_paths: ["linux_musl.txt"] }, + musl: { arch_paths: ["musl.txt"] }, + linux_glibc: { arch_paths: ["linux_glibc.txt"] }, + glibc: { arch_paths: ["glibc.txt"] }, + linux_bionic: { arch_paths: ["linux_bionic.txt"] }, + darwin: { arch_paths: ["darwin.txt"] }, + windows: { arch_paths: ["windows.txt"] }, + }, + multilib: { + lib32: { arch_paths: ["lib32.txt"] }, + lib64: { arch_paths: ["lib64.txt"] }, }, bazel_module: { bp2build_available: true }, }`, expectedBazelTargets: []string{`custom( name = "arch_paths", arch_paths = select({ - "//build/bazel/platforms/arch:x86": ["abc"], + "//build/bazel/platforms/arch:arm": [ + "arm.txt", + "lib32.txt", + ], + "//build/bazel/platforms/arch:arm64": [ + "arm64.txt", + "lib64.txt", + ], + "//build/bazel/platforms/arch:x86": [ + "x86.txt", + "lib32.txt", + ], + "//build/bazel/platforms/arch:x86_64": [ + "x86_64.txt", + "lib64.txt", + ], + "//conditions:default": [], + }) + select({ + "//build/bazel/platforms/os:android": [ + "linux.txt", + "bionic.txt", + "android.txt", + ], + "//build/bazel/platforms/os:darwin": [ + "host.txt", + "darwin.txt", + "not_windows.txt", + ], + "//build/bazel/platforms/os:linux": [ + "host.txt", + "linux.txt", + "glibc.txt", + "linux_glibc.txt", + "not_windows.txt", + ], + "//build/bazel/platforms/os:linux_bionic": [ + "host.txt", + "linux.txt", + "bionic.txt", + "linux_bionic.txt", + "not_windows.txt", + ], + "//build/bazel/platforms/os:linux_musl": [ + "host.txt", + "linux.txt", + "musl.txt", + "linux_musl.txt", + "not_windows.txt", + ], + "//build/bazel/platforms/os:windows": [ + "host.txt", + "windows.txt", + ], "//conditions:default": [], }), )`, }, }, { + description: "arch-variant deps", blueprint: `custom { name: "has_dep", arch: { @@ -327,6 +403,7 @@ custom { }, }, { + description: "embedded props", blueprint: `custom { name: "embedded_props", embedded_prop: "abc", @@ -339,6 +416,7 @@ custom { }, }, { + description: "ptr to embedded props", blueprint: `custom { name: "ptr_to_embedded_props", other_embedded_prop: "abc", @@ -354,38 +432,40 @@ custom { dir := "." for _, testCase := range testCases { - config := android.TestConfig(buildDir, nil, testCase.blueprint, nil) - ctx := android.NewTestContext(config) + t.Run(testCase.description, func(t *testing.T) { + config := android.TestConfig(buildDir, nil, testCase.blueprint, nil) + ctx := android.NewTestContext(config) - registerCustomModuleForBp2buildConversion(ctx) + registerCustomModuleForBp2buildConversion(ctx) - _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) - if errored(t, testCase, errs) { - continue - } - _, errs = ctx.ResolveDependencies(config) - if errored(t, testCase, errs) { - continue - } + _, errs := ctx.ParseFileList(dir, []string{"Android.bp"}) + if errored(t, testCase, errs) { + return + } + _, errs = ctx.ResolveDependencies(config) + if errored(t, testCase, errs) { + return + } - codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) - bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) - android.FailIfErrored(t, err) + codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) + bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir) + android.FailIfErrored(t, err) - if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { - t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount) - } else { - for i, expectedBazelTarget := range testCase.expectedBazelTargets { - actualBazelTarget := bazelTargets[i] - if actualBazelTarget.content != expectedBazelTarget { - t.Errorf( - "Expected generated Bazel target to be '%s', got '%s'", - expectedBazelTarget, - actualBazelTarget.content, - ) + if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount { + t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount) + } else { + for i, expectedBazelTarget := range testCase.expectedBazelTargets { + actualBazelTarget := bazelTargets[i] + if actualBazelTarget.content != expectedBazelTarget { + t.Errorf( + "Expected generated Bazel target to be '%s', got '%s'", + expectedBazelTarget, + actualBazelTarget.content, + ) + } } } - } + }) } } diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go new file mode 100644 index 000000000..3a07128ea --- /dev/null +++ b/bp2build/cc_binary_conversion_test.go @@ -0,0 +1,415 @@ +// 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 bp2build + +import ( + "android/soong/android" + "android/soong/cc" + "fmt" + "strings" + "testing" +) + +const ( + ccBinaryTypePlaceHolder = "{rule_name}" + compatibleWithPlaceHolder = "{target_compatible_with}" +) + +func registerCcBinaryModuleTypes(ctx android.RegistrationContext) { + cc.RegisterCCBuildComponents(ctx) + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) + ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) + ctx.RegisterModuleType("cc_library", cc.LibraryFactory) +} + +var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary", compatibleWithPlaceHolder, "") +var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host", compatibleWithPlaceHolder, ` + target_compatible_with = select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + }),`) + +func runCcBinaryTests(t *testing.T, tc bp2buildTestCase) { + t.Helper() + runCcBinaryTestCase(t, tc) + runCcHostBinaryTestCase(t, tc) +} + +func runCcBinaryTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + testCase := tc + testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...) + testCase.moduleTypeUnderTest = "cc_binary" + testCase.moduleTypeUnderTestFactory = cc.BinaryFactory + testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryBp2build + testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description) + testCase.blueprint = binaryReplacer.Replace(testCase.blueprint) + for i, et := range testCase.expectedBazelTargets { + testCase.expectedBazelTargets[i] = binaryReplacer.Replace(et) + } + t.Run(testCase.description, func(t *testing.T) { + runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase) + }) +} + +func runCcHostBinaryTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + testCase := tc + testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...) + testCase.moduleTypeUnderTest = "cc_binary_host" + testCase.moduleTypeUnderTestFactory = cc.BinaryHostFactory + testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryHostBp2build + testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description) + testCase.blueprint = hostBinaryReplacer.Replace(testCase.blueprint) + for i, et := range testCase.expectedBazelTargets { + testCase.expectedBazelTargets[i] = hostBinaryReplacer.Replace(et) + } + t.Run(testCase.description, func(t *testing.T) { + runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase) + }) +} + +func TestBasicCcBinary(t *testing.T) { + runCcBinaryTests(t, bp2buildTestCase{ + description: "basic -- properties -> attrs with little/no transformation", + blueprint: ` +{rule_name} { + name: "foo", + srcs: ["a.cc"], + local_include_dirs: ["dir"], + include_dirs: ["absolute_dir"], + cflags: ["-Dcopt"], + cppflags: ["-Dcppflag"], + conlyflags: ["-Dconlyflag"], + asflags: ["-Dasflag"], + ldflags: ["ld-flag"], + rtti: true, + strip: { + all: true, + keep_symbols: true, + keep_symbols_and_debug_frame: true, + keep_symbols_list: ["symbol"], + none: true, + }, +} +`, + expectedBazelTargets: []string{`cc_binary( + name = "foo", + absolute_includes = ["absolute_dir"], + asflags = ["-Dasflag"], + conlyflags = ["-Dconlyflag"], + copts = ["-Dcopt"], + cppflags = ["-Dcppflag"], + linkopts = ["ld-flag"], + local_includes = [ + "dir", + ".", + ], + rtti = True, + srcs = ["a.cc"], + strip = { + "all": True, + "keep_symbols": True, + "keep_symbols_and_debug_frame": True, + "keep_symbols_list": ["symbol"], + "none": True, + },{target_compatible_with} +)`}, + }) +} + +func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) { + runCcBinaryTests(t, bp2buildTestCase{ + description: `ldflag "-shared" disables static_flag feature`, + blueprint: ` +{rule_name} { + name: "foo", + ldflags: ["-shared"], + include_build_directory: false, +} +`, + expectedBazelTargets: []string{`cc_binary( + name = "foo", + features = ["-static_flag"], + linkopts = ["-shared"],{target_compatible_with} +)`}, + }) +} + +func TestCcBinaryWithLinkStatic(t *testing.T) { + runCcBinaryTests(t, bp2buildTestCase{ + description: "link static", + blueprint: ` +{rule_name} { + name: "foo", + static_executable: true, + include_build_directory: false, +} +`, + expectedBazelTargets: []string{`cc_binary( + name = "foo", + linkshared = False,{target_compatible_with} +)`}, + }) +} + +func TestCcBinaryVersionScript(t *testing.T) { + runCcBinaryTests(t, bp2buildTestCase{ + description: `version script`, + blueprint: ` +{rule_name} { + name: "foo", + include_build_directory: false, + version_script: "vs", +} +`, + expectedBazelTargets: []string{`cc_binary( + name = "foo", + additional_linker_inputs = ["vs"], + linkopts = ["-Wl,--version-script,$(location vs)"],{target_compatible_with} +)`}, + }) +} + +func TestCcBinarySplitSrcsByLang(t *testing.T) { + runCcHostBinaryTestCase(t, bp2buildTestCase{ + description: "split srcs by lang", + blueprint: ` +{rule_name} { + name: "foo", + srcs: [ + "asonly.S", + "conly.c", + "cpponly.cpp", + ":fg_foo", + ], + include_build_directory: false, +} +` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"), + expectedBazelTargets: []string{`cc_binary( + name = "foo", + srcs = [ + "cpponly.cpp", + ":fg_foo_cpp_srcs", + ], + srcs_as = [ + "asonly.S", + ":fg_foo_as_srcs", + ], + srcs_c = [ + "conly.c", + ":fg_foo_c_srcs", + ],{target_compatible_with} +)`}, + }) +} + +func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) { + runCcBinaryTestCase(t, bp2buildTestCase{ + description: "no implementation deps", + blueprint: ` +{rule_name} { + name: "foo", + shared_libs: ["implementation_shared_dep", "shared_dep"], + export_shared_lib_headers: ["shared_dep"], + static_libs: ["implementation_static_dep", "static_dep"], + export_static_lib_headers: ["static_dep", "whole_static_dep"], + whole_static_libs: ["not_explicitly_exported_whole_static_dep", "whole_static_dep"], + include_build_directory: false, +} +` + + simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") + + simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") + + simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") + + simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") + + simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") + + simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"), + expectedBazelTargets: []string{`cc_binary( + name = "foo", + deps = [ + ":implementation_static_dep", + ":static_dep", + ], + dynamic_deps = [ + ":implementation_shared_dep", + ":shared_dep", + ],{target_compatible_with} + whole_archive_deps = [ + ":not_explicitly_exported_whole_static_dep", + ":whole_static_dep", + ], +)`}, + }) +} + +func TestCcBinaryNocrtTests(t *testing.T) { + baseTestCases := []struct { + description string + soongProperty string + bazelAttr string + }{ + { + description: "nocrt: true", + soongProperty: `nocrt: true,`, + bazelAttr: ` link_crt = False,`, + }, + { + description: "nocrt: false", + soongProperty: `nocrt: false,`, + }, + { + description: "nocrt: not set", + }, + } + + baseBlueprint := `{rule_name} { + name: "foo",%s + include_build_directory: false, +} +` + + baseBazelTarget := `cc_binary( + name = "foo",%s{target_compatible_with} +)` + + for _, btc := range baseTestCases { + prop := btc.soongProperty + if len(prop) > 0 { + prop = "\n" + prop + } + attr := btc.bazelAttr + if len(attr) > 0 { + attr = "\n" + attr + } + runCcBinaryTests(t, bp2buildTestCase{ + description: btc.description, + blueprint: fmt.Sprintf(baseBlueprint, prop), + expectedBazelTargets: []string{ + fmt.Sprintf(baseBazelTarget, attr), + }, + }) + } +} + +func TestCcBinaryNo_libcrtTests(t *testing.T) { + baseTestCases := []struct { + description string + soongProperty string + bazelAttr string + }{ + { + description: "no_libcrt: true", + soongProperty: `no_libcrt: true,`, + bazelAttr: ` use_libcrt = False,`, + }, + { + description: "no_libcrt: false", + soongProperty: `no_libcrt: false,`, + bazelAttr: ` use_libcrt = True,`, + }, + { + description: "no_libcrt: not set", + }, + } + + baseBlueprint := `{rule_name} { + name: "foo",%s + include_build_directory: false, +} +` + + baseBazelTarget := `cc_binary( + name = "foo",{target_compatible_with}%s +)` + + for _, btc := range baseTestCases { + prop := btc.soongProperty + if len(prop) > 0 { + prop = "\n" + prop + } + attr := btc.bazelAttr + if len(attr) > 0 { + attr = "\n" + attr + } + runCcBinaryTests(t, bp2buildTestCase{ + description: btc.description, + blueprint: fmt.Sprintf(baseBlueprint, prop), + expectedBazelTargets: []string{ + fmt.Sprintf(baseBazelTarget, attr), + }, + }) + } +} + +func TestCcBinaryPropertiesToFeatures(t *testing.T) { + baseTestCases := []struct { + description string + soongProperty string + bazelAttr string + }{ + { + description: "pack_relocation: true", + soongProperty: `pack_relocations: true,`, + }, + { + description: "pack_relocations: false", + soongProperty: `pack_relocations: false,`, + bazelAttr: ` features = ["disable_pack_relocations"],`, + }, + { + description: "pack_relocations: not set", + }, + { + description: "pack_relocation: true", + soongProperty: `allow_undefined_symbols: true,`, + bazelAttr: ` features = ["-no_undefined_symbols"],`, + }, + { + description: "allow_undefined_symbols: false", + soongProperty: `allow_undefined_symbols: false,`, + }, + { + description: "allow_undefined_symbols: not set", + }, + } + + baseBlueprint := `{rule_name} { + name: "foo",%s + include_build_directory: false, +} +` + + baseBazelTarget := `cc_binary( + name = "foo",%s{target_compatible_with} +)` + + for _, btc := range baseTestCases { + prop := btc.soongProperty + if len(prop) > 0 { + prop = "\n" + prop + } + attr := btc.bazelAttr + if len(attr) > 0 { + attr = "\n" + attr + } + runCcBinaryTests(t, bp2buildTestCase{ + description: btc.description, + blueprint: fmt.Sprintf(baseBlueprint, prop), + expectedBazelTargets: []string{ + fmt.Sprintf(baseBazelTarget, attr), + }, + }) + } +} diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 76f83e706..cbdc167dd 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -133,8 +133,8 @@ cc_library { "//conditions:default": [], }) + select({ "//build/bazel/platforms/os:android": [ - "android.cpp", "bionic.cpp", + "android.cpp", ], "//build/bazel/platforms/os:darwin": ["darwin.cpp"], "//build/bazel/platforms/os:linux": ["linux.cpp"], @@ -803,8 +803,9 @@ cc_library { blueprint: soongCcLibraryPreamble, expectedBazelTargets: []string{`cc_library( name = "a", + additional_linker_inputs = ["v.map"], + linkopts = ["-Wl,--version-script,$(location v.map)"], srcs = ["a.cpp"], - version_script = "v.map", )`}, }) } @@ -838,12 +839,17 @@ cc_library { blueprint: soongCcLibraryPreamble, expectedBazelTargets: []string{`cc_library( name = "a", - srcs = ["a.cpp"], - version_script = select({ - "//build/bazel/platforms/arch:arm": "arm.map", - "//build/bazel/platforms/arch:arm64": "arm64.map", - "//conditions:default": None, + additional_linker_inputs = select({ + "//build/bazel/platforms/arch:arm": ["arm.map"], + "//build/bazel/platforms/arch:arm64": ["arm64.map"], + "//conditions:default": [], + }), + linkopts = select({ + "//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"], + "//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"], + "//conditions:default": [], }), + srcs = ["a.cpp"], )`}, }) } @@ -1010,39 +1016,6 @@ func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) { }) } -func TestCcLibraryLabelAttributeGetTargetProperties(t *testing.T) { - runCcLibraryTestCase(t, bp2buildTestCase{ - description: "cc_library GetTargetProperties on a LabelAttribute", - moduleTypeUnderTest: "cc_library", - moduleTypeUnderTestFactory: cc.LibraryFactory, - moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build, - blueprint: soongCcLibraryPreamble + ` -cc_library { - name: "a", - srcs: ["a.cpp"], - target: { - android_arm: { - version_script: "android_arm.map", - }, - linux_bionic_arm64: { - version_script: "linux_bionic_arm64.map", - }, - }, - include_build_directory: false, -} - `, - expectedBazelTargets: []string{`cc_library( - name = "a", - srcs = ["a.cpp"], - version_script = select({ - "//build/bazel/platforms/os_arch:android_arm": "android_arm.map", - "//build/bazel/platforms/os_arch:linux_bionic_arm64": "linux_bionic_arm64.map", - "//conditions:default": None, - }), -)`}, - }) -} - func TestCcLibraryExcludeLibs(t *testing.T) { runCcLibraryTestCase(t, bp2buildTestCase{ moduleTypeUnderTest: "cc_library", @@ -1668,9 +1641,9 @@ cc_library { name = "foo-lib", srcs = ["base.cpp"] + select({ "//build/bazel/platforms/os:android": [ - "android.cpp", - "bionic.cpp", "linux.cpp", + "bionic.cpp", + "android.cpp", ], "//build/bazel/platforms/os:darwin": ["darwin.cpp"], "//build/bazel/platforms/os:linux": [ @@ -1678,8 +1651,8 @@ cc_library { "linux_glibc.cpp", ], "//build/bazel/platforms/os:linux_bionic": [ - "bionic.cpp", "linux.cpp", + "bionic.cpp", ], "//build/bazel/platforms/os:linux_musl": [ "linux.cpp", @@ -1692,7 +1665,7 @@ cc_library { } -func TestCcLibraryCppStdWithGnuExtensions_ConvertstoCopt(t *testing.T) { +func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) { type testCase struct { cpp_std string gnu_extensions string @@ -1751,7 +1724,7 @@ func TestCcLibraryCppStdWithGnuExtensions_ConvertstoCopt(t *testing.T) { } bazelCppStdAttr := "" if tc.bazel_cpp_std != "" { - bazelCppStdAttr = fmt.Sprintf("\n copts = [\"-std=%s\"],", tc.bazel_cpp_std) + bazelCppStdAttr = fmt.Sprintf("\n cpp_std = \"%s\",", tc.bazel_cpp_std) } runCcLibraryTestCase(t, bp2buildTestCase{ @@ -1772,5 +1745,43 @@ cc_library { name = "a",%s )`, bazelCppStdAttr)}, }) + + runCcLibraryStaticTestCase(t, bp2buildTestCase{ + description: fmt.Sprintf( + "cc_library_static with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions), + moduleTypeUnderTest: "cc_library_static", + moduleTypeUnderTestFactory: cc.LibraryStaticFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build, + blueprint: soongCcLibraryPreamble + fmt.Sprintf(` +cc_library_static { + name: "a", +%s // cpp_std: *string +%s // gnu_extensions: *bool + include_build_directory: false, +} +`, cppStdAttr, gnuExtensionsAttr), + expectedBazelTargets: []string{fmt.Sprintf(`cc_library_static( + name = "a",%s +)`, bazelCppStdAttr)}, + }) + + runCcLibrarySharedTestCase(t, bp2buildTestCase{ + description: fmt.Sprintf( + "cc_library_shared with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions), + moduleTypeUnderTest: "cc_library_shared", + moduleTypeUnderTestFactory: cc.LibrarySharedFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build, + blueprint: soongCcLibraryPreamble + fmt.Sprintf(` +cc_library_shared { + name: "a", +%s // cpp_std: *string +%s // gnu_extensions: *bool + include_build_directory: false, +} +`, cppStdAttr, gnuExtensionsAttr), + expectedBazelTargets: []string{fmt.Sprintf(`cc_library_shared( + name = "a",%s +)`, bazelCppStdAttr)}, + }) } } diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index b27206747..bb15776eb 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -361,7 +361,8 @@ cc_library_shared { }`, expectedBazelTargets: []string{`cc_library_shared( name = "foo_shared", - version_script = "version_script", + additional_linker_inputs = ["version_script"], + linkopts = ["-Wl,--version-script,$(location version_script)"], )`}, }) } diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index f02ce4d3f..ef2ec32f3 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -641,12 +641,12 @@ cc_library_static { name = "foo_static", srcs_c = ["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ - "for-arm.c", "not-for-x86.c", + "for-arm.c", ], "//build/bazel/platforms/arch:x86": [ - "for-x86.c", "not-for-arm.c", + "for-x86.c", ], "//conditions:default": [ "not-for-arm.c", @@ -691,28 +691,28 @@ cc_library_static { name = "foo_static", srcs_c = ["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ - "for-arm.c", "not-for-arm64.c", "not-for-x86.c", "not-for-x86_64.c", + "for-arm.c", ], "//build/bazel/platforms/arch:arm64": [ - "for-arm64.c", "not-for-arm.c", "not-for-x86.c", "not-for-x86_64.c", + "for-arm64.c", ], "//build/bazel/platforms/arch:x86": [ - "for-x86.c", "not-for-arm.c", "not-for-arm64.c", "not-for-x86_64.c", + "for-x86.c", ], "//build/bazel/platforms/arch:x86_64": [ - "for-x86_64.c", "not-for-arm.c", "not-for-arm64.c", "not-for-x86.c", + "for-x86_64.c", ], "//conditions:default": [ "not-for-arm.c", @@ -875,20 +875,20 @@ cc_library_static { name = "foo_static2", srcs_c = ["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ - "for-lib32.c", "not-for-lib64.c", + "for-lib32.c", ], "//build/bazel/platforms/arch:arm64": [ - "for-lib64.c", "not-for-lib32.c", + "for-lib64.c", ], "//build/bazel/platforms/arch:x86": [ - "for-lib32.c", "not-for-lib64.c", + "for-lib32.c", ], "//build/bazel/platforms/arch:x86_64": [ - "for-lib64.c", "not-for-lib32.c", + "for-lib64.c", ], "//conditions:default": [ "not-for-lib32.c", @@ -942,36 +942,36 @@ cc_library_static { name = "foo_static3", srcs_c = ["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ - "for-arm.c", - "for-lib32.c", "not-for-arm64.c", "not-for-lib64.c", "not-for-x86.c", "not-for-x86_64.c", + "for-arm.c", + "for-lib32.c", ], "//build/bazel/platforms/arch:arm64": [ - "for-arm64.c", - "for-lib64.c", "not-for-arm.c", "not-for-lib32.c", "not-for-x86.c", "not-for-x86_64.c", + "for-arm64.c", + "for-lib64.c", ], "//build/bazel/platforms/arch:x86": [ - "for-lib32.c", - "for-x86.c", "not-for-arm.c", "not-for-arm64.c", "not-for-lib64.c", "not-for-x86_64.c", + "for-x86.c", + "for-lib32.c", ], "//build/bazel/platforms/arch:x86_64": [ - "for-lib64.c", - "for-x86_64.c", "not-for-arm.c", "not-for-arm64.c", "not-for-lib32.c", "not-for-x86.c", + "for-x86_64.c", + "for-lib64.c", ], "//conditions:default": [ "not-for-arm.c", @@ -986,6 +986,41 @@ cc_library_static { }) } +func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) { + runCcLibraryStaticTestCase(t, bp2buildTestCase{ + moduleTypeUnderTest: "cc_library_static", + moduleTypeUnderTestFactory: cc.LibraryStaticFactory, + moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build, + blueprint: soongCcLibraryStaticPreamble + ` +genrule { + name: "generated_hdr", + cmd: "nothing to see here", +} + +cc_library_static { + name: "foo_static", + srcs: ["cpp_src.cpp", "as_src.S", "c_src.c"], + generated_headers: ["generated_hdr"], + include_build_directory: false, +}`, + expectedBazelTargets: []string{`cc_library_static( + name = "foo_static", + srcs = [ + "cpp_src.cpp", + ":generated_hdr", + ], + srcs_as = [ + "as_src.S", + ":generated_hdr", + ], + srcs_c = [ + "c_src.c", + ":generated_hdr", + ], +)`}, + }) +} + func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) { runCcLibraryStaticTestCase(t, bp2buildTestCase{ description: "cc_library_static arch srcs/exclude_srcs with generated files", @@ -1000,73 +1035,92 @@ func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) { "dep/Android.bp": ` genrule { name: "generated_src_other_pkg", - out: ["generated_src_other_pkg.cpp"], cmd: "nothing to see here", } genrule { name: "generated_hdr_other_pkg", - out: ["generated_hdr_other_pkg.cpp"], cmd: "nothing to see here", } genrule { name: "generated_hdr_other_pkg_x86", - out: ["generated_hdr_other_pkg_x86.cpp"], + cmd: "nothing to see here", +} + +genrule { + name: "generated_hdr_other_pkg_android", cmd: "nothing to see here", }`, }, blueprint: soongCcLibraryStaticPreamble + ` genrule { name: "generated_src", - out: ["generated_src.cpp"], cmd: "nothing to see here", } genrule { - name: "generated_src_x86", - out: ["generated_src_x86.cpp"], + name: "generated_src_not_x86", + cmd: "nothing to see here", +} + +genrule { + name: "generated_src_android", cmd: "nothing to see here", } genrule { name: "generated_hdr", - out: ["generated_hdr.h"], cmd: "nothing to see here", } cc_library_static { - name: "foo_static3", - srcs: ["common.cpp", "not-for-*.cpp"], - exclude_srcs: ["not-for-everything.cpp"], - generated_sources: ["generated_src", "generated_src_other_pkg"], - generated_headers: ["generated_hdr", "generated_hdr_other_pkg"], - arch: { - x86: { - srcs: ["for-x86.cpp"], - exclude_srcs: ["not-for-x86.cpp"], - generated_sources: ["generated_src_x86"], - generated_headers: ["generated_hdr_other_pkg_x86"], - }, - }, + name: "foo_static3", + srcs: ["common.cpp", "not-for-*.cpp"], + exclude_srcs: ["not-for-everything.cpp"], + generated_sources: ["generated_src", "generated_src_other_pkg", "generated_src_not_x86"], + generated_headers: ["generated_hdr", "generated_hdr_other_pkg"], + arch: { + x86: { + srcs: ["for-x86.cpp"], + exclude_srcs: ["not-for-x86.cpp"], + generated_headers: ["generated_hdr_other_pkg_x86"], + exclude_generated_sources: ["generated_src_not_x86"], + }, + }, + target: { + android: { + generated_sources: ["generated_src_android"], + generated_headers: ["generated_hdr_other_pkg_android"], + }, + }, + include_build_directory: false, } `, expectedBazelTargets: []string{`cc_library_static( name = "foo_static3", srcs = [ - "//dep:generated_hdr_other_pkg", + "common.cpp", + ":generated_src", "//dep:generated_src_other_pkg", ":generated_hdr", - ":generated_src", - "common.cpp", + "//dep:generated_hdr_other_pkg", ] + select({ "//build/bazel/platforms/arch:x86": [ - "//dep:generated_hdr_other_pkg_x86", - ":generated_src_x86", "for-x86.cpp", + "//dep:generated_hdr_other_pkg_x86", + ], + "//conditions:default": [ + "not-for-x86.cpp", + ":generated_src_not_x86", ], - "//conditions:default": ["not-for-x86.cpp"], + }) + select({ + "//build/bazel/platforms/os:android": [ + ":generated_src_android", + "//dep:generated_hdr_other_pkg_android", + ], + "//conditions:default": [], }), )`}, }) diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go index 63a0b8a21..c4b276a64 100644 --- a/bp2build/cc_object_conversion_test.go +++ b/bp2build/cc_object_conversion_test.go @@ -439,13 +439,13 @@ func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) { copts = ["-fno-addrsig"], srcs = ["base.cpp"] + select({ "//build/bazel/platforms/os_arch:android_arm64": [ - "bionic_arm64.cpp", "linux_arm64.cpp", + "bionic_arm64.cpp", ], "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"], "//build/bazel/platforms/os_arch:linux_bionic_arm64": [ - "bionic_arm64.cpp", "linux_arm64.cpp", + "bionic_arm64.cpp", ], "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"], "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"], diff --git a/bp2build/conversion.go b/bp2build/conversion.go index d34a4ba9b..944cb83a3 100644 --- a/bp2build/conversion.go +++ b/bp2build/conversion.go @@ -17,11 +17,11 @@ type BazelFile struct { Contents string } -func CreateSoongInjectionFiles(metrics CodegenMetrics) []BazelFile { +func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []BazelFile { var files []BazelFile files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package. - files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars())) + files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars(cfg))) files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n"))) diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go index dfa1a9eb4..d09238a2b 100644 --- a/bp2build/conversion_test.go +++ b/bp2build/conversion_test.go @@ -17,6 +17,8 @@ package bp2build import ( "sort" "testing" + + "android/soong/android" ) type bazelFilepath struct { @@ -80,7 +82,7 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) { } func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) { - files := CreateSoongInjectionFiles(CodegenMetrics{}) + files := CreateSoongInjectionFiles(android.Config{}, CodegenMetrics{}) expectedFilePaths := []bazelFilepath{ { diff --git a/bp2build/testing.go b/bp2build/testing.go index 6c322eefe..7c2f43a06 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -283,7 +283,7 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) { return } - paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude)) + paths := bazel.LabelListAttribute{} for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) { for config, props := range configToProps { diff --git a/cc/binary.go b/cc/binary.go index b423c50ae..4d1301bb4 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -20,6 +20,7 @@ import ( "github.com/google/blueprint" "android/soong/android" + "android/soong/bazel" ) type BinaryLinkerProperties struct { @@ -62,7 +63,7 @@ func init() { func RegisterBinaryBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_binary", BinaryFactory) - ctx.RegisterModuleType("cc_binary_host", binaryHostFactory) + ctx.RegisterModuleType("cc_binary_host", BinaryHostFactory) } // cc_binary produces a binary that is runnable on a device. @@ -72,7 +73,7 @@ func BinaryFactory() android.Module { } // cc_binary_host produces a binary that is runnable on a host. -func binaryHostFactory() android.Module { +func BinaryHostFactory() android.Module { module, _ := NewBinary(android.HostSupported) return module.Init() } @@ -541,3 +542,125 @@ func (binary *binaryDecorator) verifyHostBionicLinker(ctx ModuleContext, in, lin }, }) } + +func init() { + android.RegisterBp2BuildMutator("cc_binary", BinaryBp2build) + android.RegisterBp2BuildMutator("cc_binary_host", BinaryHostBp2build) +} + +func BinaryBp2build(ctx android.TopDownMutatorContext) { + binaryBp2build(ctx, "cc_binary") +} + +func BinaryHostBp2build(ctx android.TopDownMutatorContext) { + binaryBp2build(ctx, "cc_binary_host") +} + +func binaryBp2build(ctx android.TopDownMutatorContext, typ string) { + m, ok := ctx.Module().(*Module) + if !ok { + // Not a cc module + return + } + if !m.ConvertWithBp2build(ctx) { + return + } + + if ctx.ModuleType() != typ { + return + } + + var compatibleWith bazel.StringListAttribute + if typ == "cc_binary_host" { + //incompatible with android OS + compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, []string{"@platforms//:incompatible"}) + compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, bazel.ConditionsDefaultConfigKey, []string{}) + } + + compilerAttrs := bp2BuildParseCompilerProps(ctx, m) + linkerAttrs := bp2BuildParseLinkerProps(ctx, m) + + attrs := &binaryAttributes{ + binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m), + + Srcs: compilerAttrs.srcs, + Srcs_c: compilerAttrs.cSrcs, + Srcs_as: compilerAttrs.asSrcs, + + Copts: compilerAttrs.copts, + Cppflags: compilerAttrs.cppFlags, + Conlyflags: compilerAttrs.conlyFlags, + Asflags: compilerAttrs.asFlags, + + Deps: linkerAttrs.implementationDeps, + Dynamic_deps: linkerAttrs.implementationDynamicDeps, + Whole_archive_deps: linkerAttrs.wholeArchiveDeps, + System_deps: linkerAttrs.systemDynamicDeps, + + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Linkopts: linkerAttrs.linkopts, + Link_crt: linkerAttrs.linkCrt, + Use_libcrt: linkerAttrs.useLibcrt, + Rtti: compilerAttrs.rtti, + Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, + + 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, + }, + + Target_compatible_with: compatibleWith, + Features: linkerAttrs.features, + } + + ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{ + Rule_class: "cc_binary", + Bzl_load_location: "//build/bazel/rules:cc_binary.bzl", + }, + android.CommonAttributes{Name: m.Name()}, + attrs) +} + +// binaryAttributes contains Bazel attributes corresponding to a cc binary +type binaryAttributes struct { + binaryLinkerAttrs + Srcs bazel.LabelListAttribute + Srcs_c bazel.LabelListAttribute + Srcs_as bazel.LabelListAttribute + + Copts bazel.StringListAttribute + Cppflags bazel.StringListAttribute + Conlyflags bazel.StringListAttribute + Asflags bazel.StringListAttribute + + Deps bazel.LabelListAttribute + Dynamic_deps bazel.LabelListAttribute + Whole_archive_deps bazel.LabelListAttribute + System_deps bazel.LabelListAttribute + + Local_includes bazel.StringListAttribute + Absolute_includes bazel.StringListAttribute + + Linkopts bazel.StringListAttribute + Additional_linker_inputs bazel.LabelListAttribute + + Link_crt bazel.BoolAttribute + Use_libcrt bazel.BoolAttribute + + Rtti bazel.BoolAttribute + Stl *string + Cpp_std *string + + Strip stripAttributes + + Features bazel.StringListAttribute + + Target_compatible_with bazel.StringListAttribute +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 0b2c133b9..3c238b5d2 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -14,6 +14,7 @@ package cc import ( + "fmt" "path/filepath" "strings" @@ -25,6 +26,12 @@ import ( "github.com/google/blueprint/proptools" ) +const ( + cSrcPartition = "c" + asSrcPartition = "as" + cppSrcPartition = "cpp" +) + // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- // properties which apply to either the shared or static version of a cc_library module. type staticOrSharedAttributes struct { @@ -42,7 +49,7 @@ type staticOrSharedAttributes struct { System_dynamic_deps bazel.LabelListAttribute } -func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) { +func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { // Check that a module is a filegroup type named <label>. isFilegroupNamed := func(m android.Module, fullLabel string) bool { if ctx.OtherModuleType(m) != "filegroup" { @@ -74,17 +81,14 @@ func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelLis // TODO(b/190006308): Handle language detection of sources in a Bazel rule. partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ - "c": bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, - "as": bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, + cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, + asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, // C++ is the "catch-all" group, and comprises generated sources because we don't // know the language of these sources until the genrule is executed. - "cpp": bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, + cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, }) - cSrcs = partitioned["c"] - asSrcs = partitioned["as"] - cppSrcs = partitioned["cpp"] - return + return partitioned } // bp2BuildParseLibProps returns the attributes for a variant of a cc_library. @@ -113,7 +117,13 @@ type depsPartition struct { type bazelLabelForDepsFn func(android.TopDownMutatorContext, []string) bazel.LabelList -func partitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition { +func maybePartitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition { + if !exportsDeps { + return depsPartition{ + implementation: fn(ctx, allDeps), + } + } + implementation, export := android.FilterList(allDeps, exportedDeps) return depsPartition{ @@ -124,7 +134,12 @@ func partitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, type bazelLabelForDepsExcludesFn func(android.TopDownMutatorContext, []string, []string) bazel.LabelList -func partitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition { +func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition { + if !exportsDeps { + return depsPartition{ + implementation: fn(ctx, allDeps, excludes), + } + } implementation, export := android.FilterList(allDeps, exportedDeps) return depsPartition{ @@ -141,11 +156,11 @@ func bp2buildParseStaticOrSharedProps(ctx android.TopDownMutatorContext, module attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs)) attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs)) - staticDeps := partitionExportedAndImplementationsDeps(ctx, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps) + staticDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps) attrs.Deps.SetSelectValue(axis, config, staticDeps.export) attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation) - sharedDeps := partitionExportedAndImplementationsDeps(ctx, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps) + sharedDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps) attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export) attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation) @@ -174,10 +189,10 @@ func bp2buildParseStaticOrSharedProps(ctx android.TopDownMutatorContext, module } } - cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.Srcs) - attrs.Srcs = cppSrcs - attrs.Srcs_c = cSrcs - attrs.Srcs_as = asSrcs + partitionedSrcs := groupSrcsByExtension(ctx, attrs.Srcs) + attrs.Srcs = partitionedSrcs[cppSrcPartition] + attrs.Srcs_c = partitionedSrcs[cSrcPartition] + attrs.Srcs_as = partitionedSrcs[asSrcPartition] return attrs } @@ -226,7 +241,10 @@ type compilerAttributes struct { srcs bazel.LabelListAttribute rtti bazel.BoolAttribute - stl *string + + // Not affected by arch variants + stl *string + cppStd *string localIncludes bazel.StringListAttribute absoluteIncludes bazel.StringListAttribute @@ -235,6 +253,7 @@ type compilerAttributes struct { // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes. func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Module) compilerAttributes { var srcs bazel.LabelListAttribute + var implementationHdrs bazel.LabelListAttribute var copts bazel.StringListAttribute var asFlags bazel.StringListAttribute var conlyFlags bazel.StringListAttribute @@ -242,6 +261,8 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul var rtti bazel.BoolAttribute var localIncludes bazel.StringListAttribute var absoluteIncludes bazel.StringListAttribute + var stl *string = nil + var cppStd *string = nil parseCommandLineFlags := func(soongFlags []string) []string { var result []string @@ -255,15 +276,20 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul } // Parse srcs from an arch or OS's props value. - parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList { + parseSrcs := func(props *BaseCompilerProperties) (bazel.LabelList, bool) { + anySrcs := false // Add srcs-like dependencies such as generated files. // First create a LabelList containing these dependencies, then merge the values with srcs. - generatedHdrsAndSrcs := baseCompilerProps.Generated_headers - generatedHdrsAndSrcs = append(generatedHdrsAndSrcs, baseCompilerProps.Generated_sources...) - generatedHdrsAndSrcsLabelList := android.BazelLabelForModuleDeps(ctx, generatedHdrsAndSrcs) + generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, props.Generated_sources, props.Exclude_generated_sources) + if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 { + anySrcs = true + } - allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs) - return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedHdrsAndSrcsLabelList) + allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs) + if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 { + anySrcs = true + } + return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs } archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) @@ -272,12 +298,13 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { // If there's arch specific srcs or exclude_srcs, generate a select entry for it. // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too. - if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 { - srcsList := parseSrcs(baseCompilerProps) + if srcsList, ok := parseSrcs(baseCompilerProps); ok { srcs.SetSelectValue(axis, config, srcsList) } + if len(baseCompilerProps.Generated_headers) > 0 { + implementationHdrs.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Generated_headers)) + } - var archVariantCopts []string if axis == bazel.NoConfigAxis { // If cpp_std is not specified, don't generate it in the // BUILD file. For readability purposes, cpp_std and gnu_extensions are @@ -289,11 +316,14 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul // These transformations are shared with compiler.go. cppStdVal := parseCppStd(baseCompilerProps.Cpp_std) _, cppStdVal = maybeReplaceGnuToC(baseCompilerProps.Gnu_extensions, "", cppStdVal) - archVariantCopts = append(archVariantCopts, "-std="+cppStdVal) + cppStd = &cppStdVal } else if baseCompilerProps.Gnu_extensions != nil && !*baseCompilerProps.Gnu_extensions { - archVariantCopts = append(archVariantCopts, "-std=c++17") + cppStdVal := "c++17" + cppStd = &cppStdVal } } + + var archVariantCopts []string archVariantCopts = append(archVariantCopts, parseCommandLineFlags(baseCompilerProps.Cflags)...) archVariantAsflags := parseCommandLineFlags(baseCompilerProps.Asflags) @@ -315,6 +345,21 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul } srcs.ResolveExcludes() + partitionedSrcs := groupSrcsByExtension(ctx, srcs) + + for p, lla := range partitionedSrcs { + // if there are no sources, there is no need for headers + if lla.IsEmpty() { + continue + } + lla.Append(implementationHdrs) + partitionedSrcs[p] = lla + } + + srcs = partitionedSrcs[cppSrcPartition] + cSrcs := partitionedSrcs[cSrcPartition] + asSrcs := partitionedSrcs[asSrcPartition] + absoluteIncludes.DeduplicateAxesFromBase() localIncludes.DeduplicateAxesFromBase() @@ -337,9 +382,6 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul } } - srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs) - - var stl *string = nil stlPropsByArch := module.GetArchVariantProperties(ctx, &StlProperties{}) for _, configToProps := range stlPropsByArch { for _, props := range configToProps { @@ -367,6 +409,7 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul cppFlags: cppFlags, rtti: rtti, stl: stl, + cppStd: cppStd, localIncludes: localIncludes, absoluteIncludes: absoluteIncludes, } @@ -384,7 +427,7 @@ type linkerAttributes struct { linkCrt bazel.BoolAttribute useLibcrt bazel.BoolAttribute linkopts bazel.StringListAttribute - versionScript bazel.LabelAttribute + additionalLinkerInputs bazel.LabelListAttribute stripKeepSymbols bazel.BoolAttribute stripKeepSymbolsAndDebugFrame bazel.BoolAttribute stripKeepSymbolsList bazel.StringListAttribute @@ -407,8 +450,8 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) systemSharedDeps := bazel.LabelListAttribute{ForceSpecifyEmptyList: true} var linkopts bazel.StringListAttribute - var versionScript bazel.LabelAttribute var linkCrt bazel.BoolAttribute + var additionalLinkerInputs bazel.LabelListAttribute var useLibcrt bazel.BoolAttribute var stripKeepSymbols bazel.BoolAttribute @@ -433,6 +476,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) // Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module var disallowedArchVariantCrt bool + isBinary := module.Binary() for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) { for config, props := range configToProps { @@ -442,7 +486,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) // Excludes to parallel Soong: // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0 staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs) - staticDeps := partitionExportedAndImplementationsDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes) + staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes) deps.SetSelectValue(axis, config, staticDeps.export) implementationDeps.SetSelectValue(axis, config, staticDeps.implementation) @@ -459,17 +503,16 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) systemSharedDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs)) sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs) - sharedDeps := partitionExportedAndImplementationsDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes) + sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes) dynamicDeps.SetSelectValue(axis, config, sharedDeps.export) implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation) headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs) - hDeps := partitionExportedAndImplementationsDeps(ctx, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps) + hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps) headerDeps.SetSelectValue(axis, config, hDeps.export) implementationHeaderDeps.SetSelectValue(axis, config, hDeps.implementation) - linkopts.SetSelectValue(axis, config, baseLinkerProps.Ldflags) if !BoolDefault(baseLinkerProps.Pack_relocations, packRelocationsDefault) { axisFeatures = append(axisFeatures, "disable_pack_relocations") } @@ -478,9 +521,20 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) axisFeatures = append(axisFeatures, "-no_undefined_symbols") } + var linkerFlags []string + if len(baseLinkerProps.Ldflags) > 0 { + linkerFlags = append(linkerFlags, baseLinkerProps.Ldflags...) + // binaries remove static flag if -shared is in the linker flags + if module.Binary() && android.InList("-shared", linkerFlags) { + axisFeatures = append(axisFeatures, "-static_flag") + } + } if baseLinkerProps.Version_script != nil { - versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)) + label := android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script) + additionalLinkerInputs.SetSelectValue(axis, config, bazel.LabelList{Includes: []bazel.Label{label}}) + linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label)) } + linkopts.SetSelectValue(axis, config, linkerFlags) useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt()) // it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it. @@ -572,10 +626,10 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) wholeArchiveDeps: wholeArchiveDeps, systemDynamicDeps: systemSharedDeps, - linkCrt: linkCrt, - linkopts: linkopts, - useLibcrt: useLibcrt, - versionScript: versionScript, + linkCrt: linkCrt, + linkopts: linkopts, + useLibcrt: useLibcrt, + additionalLinkerInputs: additionalLinkerInputs, // Strip properties stripKeepSymbols: stripKeepSymbols, @@ -708,3 +762,29 @@ func bazelLabelForHeaderDeps(ctx android.TopDownMutatorContext, modules []string func bazelLabelForSharedDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList { return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule) } + +type binaryLinkerAttrs struct { + Linkshared *bool +} + +func bp2buildBinaryLinkerProps(ctx android.TopDownMutatorContext, m *Module) binaryLinkerAttrs { + attrs := binaryLinkerAttrs{} + archVariantProps := m.GetArchVariantProperties(ctx, &BinaryLinkerProperties{}) + for axis, configToProps := range archVariantProps { + for _, p := range configToProps { + props := p.(*BinaryLinkerProperties) + staticExecutable := props.Static_executable + if axis == bazel.NoConfigAxis { + if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared { + attrs.Linkshared = &linkBinaryShared + } + } else if staticExecutable != nil { + // TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a + // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling + ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values") + } + } + } + + return attrs +} diff --git a/cc/builder.go b/cc/builder.go index b494f7bab..082a70cf7 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -238,14 +238,6 @@ var ( }, "asFlags") - // Rule to invoke windres, for interaction with Windows resources. - windres = pctx.AndroidStaticRule("windres", - blueprint.RuleParams{ - Command: "$windresCmd $flags -I$$(dirname $in) -i $in -o $out --preprocessor \"${config.ClangBin}/clang -E -xc-header -DRC_INVOKED\"", - CommandDeps: []string{"$windresCmd"}, - }, - "windresCmd", "flags") - _ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper") // -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information. @@ -577,20 +569,6 @@ func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, no }, }) continue - case ".rc": - ctx.Build(pctx, android.BuildParams{ - Rule: windres, - Description: "windres " + srcFile.Rel(), - Output: objFile, - Input: srcFile, - Implicits: cFlagsDeps, - OrderOnly: pathDeps, - Args: map[string]string{ - "windresCmd": mingwCmd(flags.toolchain, "windres"), - "flags": shareFlags("flags", flags.toolchain.WindresFlags()), - }, - }) - continue case ".o": objFiles[i] = srcFile continue @@ -3249,16 +3249,6 @@ func (c *Module) TestFor() []string { return c.Properties.Test_for } -func (c *Module) UniqueApexVariations() bool { - if u, ok := c.compiler.(interface { - uniqueApexVariations() bool - }); ok { - return u.uniqueApexVariations() - } else { - return false - } -} - func (c *Module) EverInstallable() bool { return c.installer != nil && // Check to see whether the module is actually ever installable. diff --git a/cc/compiler.go b/cc/compiler.go index 4f96712e6..00df66912 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -209,15 +209,6 @@ type BaseCompilerProperties struct { // Build and link with OpenMP Openmp *bool `android:"arch_variant"` - - // Deprecated. - // Adds __ANDROID_APEX_<APEX_MODULE_NAME>__ macro defined for apex variants in addition to __ANDROID_APEX__ - Use_apex_name_macro *bool - - // Adds two macros for apex variants in addition to __ANDROID_APEX__ - // * __ANDROID_APEX_COM_ANDROID_FOO__ - // * __ANDROID_APEX_NAME__="com.android.foo" - UseApexNameMacro bool `blueprint:"mutated"` } func NewBaseCompiler() *baseCompiler { @@ -291,10 +282,6 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { return deps } -func (compiler *baseCompiler) useApexNameMacro() bool { - return Bool(compiler.Properties.Use_apex_name_macro) || compiler.Properties.UseApexNameMacro -} - // Return true if the module is in the WarningAllowedProjects. func warningsAreAllowed(subdir string) bool { subdir += "/" @@ -405,10 +392,6 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps if ctx.apexVariationName() != "" { flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__") - if compiler.useApexNameMacro() { - flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexVariationName())+"__") - flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'") - } if ctx.Device() { flags.Global.CommonFlags = append(flags.Global.CommonFlags, fmt.Sprintf("-D__ANDROID_APEX_MIN_SDK_VERSION__=%d", @@ -554,11 +537,6 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps "-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String()) } - if compiler.hasSrcExt(".mc") { - flags.Local.CommonFlags = append(flags.Local.CommonFlags, - "-I"+android.PathForModuleGen(ctx, "windmc", ctx.ModuleDir()).String()) - } - if compiler.hasSrcExt(".aidl") { flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...) if len(compiler.Properties.Aidl.Local_include_dirs) > 0 { @@ -634,10 +612,6 @@ func (compiler *baseCompiler) hasSrcExt(ext string) bool { return false } -func (compiler *baseCompiler) uniqueApexVariations() bool { - return compiler.useApexNameMacro() -} - var invalidDefineCharRegex = regexp.MustCompile("[^a-zA-Z0-9_]") // makeDefineString transforms a name of an APEX module into a value to be used as value for C define diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go index d19f5ac8e..4797acca1 100644 --- a/cc/config/bp2build.go +++ b/cc/config/bp2build.go @@ -16,9 +16,13 @@ package config import ( "fmt" + "reflect" "regexp" "sort" "strings" + + "android/soong/android" + "github.com/google/blueprint" ) const ( @@ -26,18 +30,27 @@ const ( ) type bazelVarExporter interface { - asBazel(exportedStringVariables, exportedStringListVariables) []bazelConstant + asBazel(android.Config, exportedStringVariables, exportedStringListVariables, exportedConfigDependingVariables) []bazelConstant } // Helpers for exporting cc configuration information to Bazel. var ( - // Map containing toolchain variables that are independent of the + // Maps containing toolchain variables that are independent of the // environment variables of the build. exportedStringListVars = exportedStringListVariables{} exportedStringVars = exportedStringVariables{} exportedStringListDictVars = exportedStringListDictVariables{} + + /// Maps containing variables that are dependent on the build config. + exportedConfigDependingVars = exportedConfigDependingVariables{} ) +type exportedConfigDependingVariables map[string]interface{} + +func (m exportedConfigDependingVariables) Set(k string, v interface{}) { + m[k] = v +} + // Ensure that string s has no invalid characters to be generated into the bzl file. func validateCharacters(s string) string { for _, c := range []string{`\n`, `"`, `\`} { @@ -74,10 +87,14 @@ func printBazelList(items []string, indentLevel int) string { return strings.Join(list, "\n") } -func (m exportedStringVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant { +func (m exportedStringVariables) asBazel(config android.Config, + stringVars exportedStringVariables, stringListVars exportedStringListVariables, cfgDepVars exportedConfigDependingVariables) []bazelConstant { ret := make([]bazelConstant, 0, len(m)) for k, variableValue := range m { - expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars) + expandedVar, err := expandVar(config, variableValue, stringVars, stringListVars, cfgDepVars) + if err != nil { + panic(fmt.Errorf("error expanding config variable %s: %s", k, err)) + } if len(expandedVar) > 1 { panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar)) } @@ -101,7 +118,9 @@ func (m exportedStringListVariables) Set(k string, v []string) { m[k] = v } -func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant { +func (m exportedStringListVariables) asBazel(config android.Config, + stringScope exportedStringVariables, stringListScope exportedStringListVariables, + exportedVars exportedConfigDependingVariables) []bazelConstant { ret := make([]bazelConstant, 0, len(m)) // For each exported variable, recursively expand elements in the variableValue // list to ensure that interpolated variables are expanded according to their values @@ -109,7 +128,11 @@ func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables for k, variableValue := range m { var expandedVars []string for _, v := range variableValue { - expandedVars = append(expandedVars, expandVar(v, stringScope, stringListScope)...) + expandedVar, err := expandVar(config, v, stringScope, stringListScope, exportedVars) + if err != nil { + panic(fmt.Errorf("Error expanding config variable %s=%s: %s", k, v, err)) + } + expandedVars = append(expandedVars, expandedVar...) } // Assign the list as a bzl-private variable; this variable will be exported // out through a constants struct later. @@ -121,6 +144,18 @@ func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables return ret } +// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain. +func exportVariableConfigMethod(name string, method interface{}) blueprint.Variable { + exportedConfigDependingVars.Set(name, method) + return pctx.VariableConfigMethod(name, method) +} + +// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain. +func exportSourcePathVariable(name string, value string) { + pctx.SourcePathVariable(name, value) + exportedStringVars.Set(name, value) +} + // Convenience function to declare a static variable and export it to Bazel's cc_toolchain. func exportStringListStaticVariable(name string, value []string) { pctx.StaticVariable(name, strings.Join(value, " ")) @@ -145,7 +180,8 @@ func printBazelStringListDict(dict map[string][]string) string { } // Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries -func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ exportedStringListVariables) []bazelConstant { +func (m exportedStringListDictVariables) asBazel(_ android.Config, _ exportedStringVariables, + _ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant { ret := make([]bazelConstant, 0, len(m)) for k, dict := range m { ret = append(ret, bazelConstant{ @@ -158,19 +194,20 @@ func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ ex // BazelCcToolchainVars generates bzl file content containing variables for // Bazel's cc_toolchain configuration. -func BazelCcToolchainVars() string { +func BazelCcToolchainVars(config android.Config) string { return bazelToolchainVars( + config, exportedStringListDictVars, exportedStringListVars, exportedStringVars) } -func bazelToolchainVars(vars ...bazelVarExporter) string { +func bazelToolchainVars(config android.Config, vars ...bazelVarExporter) string { ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n" results := []bazelConstant{} for _, v := range vars { - results = append(results, v.asBazel(exportedStringVars, exportedStringListVars)...) + results = append(results, v.asBazel(config, exportedStringVars, exportedStringListVars, exportedConfigDependingVars)...) } sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName }) @@ -201,34 +238,35 @@ func bazelToolchainVars(vars ...bazelVarExporter) string { // string slice than to handle a pass-by-referenced map, which would make it // quite complex to track depth-first interpolations. It's also unlikely the // interpolation stacks are deep (n > 1). -func expandVar(toExpand string, stringScope exportedStringVariables, stringListScope exportedStringListVariables) []string { +func expandVar(config android.Config, toExpand string, stringScope exportedStringVariables, + stringListScope exportedStringListVariables, exportedVars exportedConfigDependingVariables) ([]string, error) { // e.g. "${ExternalCflags}" r := regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`) // Internal recursive function. - var expandVarInternal func(string, map[string]bool) []string - expandVarInternal = func(toExpand string, seenVars map[string]bool) []string { - var ret []string - for _, v := range strings.Split(toExpand, " ") { - matches := r.FindStringSubmatch(v) + var expandVarInternal func(string, map[string]bool) (string, error) + expandVarInternal = func(toExpand string, seenVars map[string]bool) (string, error) { + var ret string + remainingString := toExpand + for len(remainingString) > 0 { + matches := r.FindStringSubmatch(remainingString) if len(matches) == 0 { - return []string{v} + return ret + remainingString, nil } - if len(matches) != 2 { - panic(fmt.Errorf( - "Expected to only match 1 subexpression in %s, got %d", - v, - len(matches)-1)) + panic(fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", remainingString, len(matches)-1)) } + matchIndex := strings.Index(remainingString, matches[0]) + ret += remainingString[:matchIndex] + remainingString = remainingString[matchIndex+len(matches[0]):] // Index 1 of FindStringSubmatch contains the subexpression match // (variable name) of the capture group. variable := matches[1] // toExpand contains a variable. if _, ok := seenVars[variable]; ok { - panic(fmt.Errorf( - "Unbounded recursive interpolation of variable: %s", variable)) + return ret, fmt.Errorf( + "Unbounded recursive interpolation of variable: %s", variable) } // A map is passed-by-reference. Create a new map for // this scope to prevent variables seen in one depth-first expansion @@ -239,15 +277,65 @@ func expandVar(toExpand string, stringScope exportedStringVariables, stringListS } newSeenVars[variable] = true if unexpandedVars, ok := stringListScope[variable]; ok { + expandedVars := []string{} for _, unexpandedVar := range unexpandedVars { - ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...) + expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars) + if err != nil { + return ret, err + } + expandedVars = append(expandedVars, expandedVar) } + ret += strings.Join(expandedVars, " ") } else if unexpandedVar, ok := stringScope[variable]; ok { - ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...) + expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars) + if err != nil { + return ret, err + } + ret += expandedVar + } else if unevaluatedVar, ok := exportedVars[variable]; ok { + evalFunc := reflect.ValueOf(unevaluatedVar) + validateVariableMethod(variable, evalFunc) + evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)}) + evaluatedValue := evaluatedResult[0].Interface().(string) + expandedVar, err := expandVarInternal(evaluatedValue, newSeenVars) + if err != nil { + return ret, err + } + ret += expandedVar + } else { + return "", fmt.Errorf("Unbound config variable %s", variable) } } - return ret + return ret, nil + } + var ret []string + for _, v := range strings.Split(toExpand, " ") { + val, err := expandVarInternal(v, map[string]bool{}) + if err != nil { + return ret, err + } + ret = append(ret, val) } - return expandVarInternal(toExpand, map[string]bool{}) + return ret, nil +} + +func validateVariableMethod(name string, methodValue reflect.Value) { + methodType := methodValue.Type() + if methodType.Kind() != reflect.Func { + panic(fmt.Errorf("method given for variable %s is not a function", + name)) + } + if n := methodType.NumIn(); n != 1 { + panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)", + name, n)) + } + if n := methodType.NumOut(); n != 1 { + panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)", + name, n)) + } + if kind := methodType.Out(0).Kind(); kind != reflect.String { + panic(fmt.Errorf("method for variable %s does not return a string", + name)) + } } diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go index 883597ad3..3118df1f8 100644 --- a/cc/config/bp2build_test.go +++ b/cc/config/bp2build_test.go @@ -16,13 +16,21 @@ package config import ( "testing" + + "android/soong/android" ) func TestExpandVars(t *testing.T) { + android_arm64_config := android.TestConfig("out", nil, "", nil) + android_arm64_config.BuildOS = android.Android + android_arm64_config.BuildArch = android.Arm64 + testCases := []struct { description string + config android.Config stringScope exportedStringVariables stringListScope exportedStringListVariables + configVars exportedConfigDependingVariables toExpand string expectedValues []string }{ @@ -57,7 +65,7 @@ func TestExpandVars(t *testing.T) { "bar": []string{"baz", "${qux}"}, }, toExpand: "${foo}", - expectedValues: []string{"baz", "hello"}, + expectedValues: []string{"baz hello"}, }, { description: "double level expansion", @@ -75,7 +83,7 @@ func TestExpandVars(t *testing.T) { "b": []string{"d"}, }, toExpand: "${a}", - expectedValues: []string{"d", "c"}, + expectedValues: []string{"d c"}, }, { description: "double level expansion, with two variables in a string", @@ -85,7 +93,7 @@ func TestExpandVars(t *testing.T) { "c": []string{"e"}, }, toExpand: "${a}", - expectedValues: []string{"d", "e"}, + expectedValues: []string{"d e"}, }, { description: "triple level expansion with two variables in a string", @@ -96,13 +104,38 @@ func TestExpandVars(t *testing.T) { "d": []string{"foo"}, }, toExpand: "${a}", - expectedValues: []string{"foo", "foo", "foo"}, + expectedValues: []string{"foo foo foo"}, + }, + { + description: "expansion with config depending vars", + configVars: exportedConfigDependingVariables{ + "a": func(c android.Config) string { return c.BuildOS.String() }, + "b": func(c android.Config) string { return c.BuildArch.String() }, + }, + config: android_arm64_config, + toExpand: "${a}-${b}", + expectedValues: []string{"android-arm64"}, + }, + { + description: "double level multi type expansion", + stringListScope: exportedStringListVariables{ + "platform": []string{"${os}-${arch}"}, + "const": []string{"const"}, + }, + configVars: exportedConfigDependingVariables{ + "os": func(c android.Config) string { return c.BuildOS.String() }, + "arch": func(c android.Config) string { return c.BuildArch.String() }, + "foo": func(c android.Config) string { return "foo" }, + }, + config: android_arm64_config, + toExpand: "${const}/${platform}/${foo}", + expectedValues: []string{"const/android-arm64/foo"}, }, } for _, testCase := range testCases { t.Run(testCase.description, func(t *testing.T) { - output := expandVar(testCase.toExpand, testCase.stringScope, testCase.stringListScope) + output, _ := expandVar(testCase.config, testCase.toExpand, testCase.stringScope, testCase.stringListScope, testCase.configVars) if len(output) != len(testCase.expectedValues) { t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output)) } @@ -119,6 +152,7 @@ func TestExpandVars(t *testing.T) { func TestBazelToolchainVars(t *testing.T) { testCases := []struct { name string + config android.Config vars []bazelVarExporter expectedOut string }{ @@ -248,7 +282,7 @@ constants = struct( for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - out := bazelToolchainVars(tc.vars...) + out := bazelToolchainVars(tc.config, tc.vars...) if out != tc.expectedOut { t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out) } diff --git a/cc/config/global.go b/cc/config/global.go index 5f41f9e06..7abd2fc12 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -77,10 +77,6 @@ var ( // TODO: can we remove this now? "-Wno-reserved-id-macro", - // Workaround for ccache with clang. - // See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html. - "-Wno-unused-command-line-argument", - // Force clang to always output color diagnostics. Ninja will strip the ANSI // color codes if it is not running in a terminal. "-fcolor-diagnostics", @@ -274,8 +270,8 @@ var ( // prebuilts/clang default settings. ClangDefaultBase = "prebuilts/clang/host" - ClangDefaultVersion = "clang-r433403" - ClangDefaultShortVersion = "13.0.2" + ClangDefaultVersion = "clang-r433403b" + ClangDefaultShortVersion = "13.0.3" // Directories with warnings from Android.bp files. WarningAllowedProjects = []string{ @@ -329,6 +325,12 @@ func init() { // Default to zero initialization. flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang") } + + // Workaround for ccache with clang. + // See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html. + if ctx.Config().IsEnvTrue("USE_CCACHE") { + flags = append(flags, "-Wno-unused-command-line-argument") + } return strings.Join(flags, " ") }) @@ -364,28 +366,12 @@ func init() { exportStringStaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion) exportStringStaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion) - pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase) - pctx.VariableFunc("ClangBase", func(ctx android.PackageVarContext) string { - if override := ctx.Config().Getenv("LLVM_PREBUILTS_BASE"); override != "" { - return override - } - return "${ClangDefaultBase}" - }) - pctx.VariableFunc("ClangVersion", func(ctx android.PackageVarContext) string { - if override := ctx.Config().Getenv("LLVM_PREBUILTS_VERSION"); override != "" { - return override - } - return ClangDefaultVersion - }) + pctx.StaticVariableWithEnvOverride("ClangBase", "LLVM_PREBUILTS_BASE", ClangDefaultBase) + pctx.StaticVariableWithEnvOverride("ClangVersion", "LLVM_PREBUILTS_VERSION", ClangDefaultVersion) pctx.StaticVariable("ClangPath", "${ClangBase}/${HostPrebuiltTag}/${ClangVersion}") pctx.StaticVariable("ClangBin", "${ClangPath}/bin") - pctx.VariableFunc("ClangShortVersion", func(ctx android.PackageVarContext) string { - if override := ctx.Config().Getenv("LLVM_RELEASE_VERSION"); override != "" { - return override - } - return ClangDefaultShortVersion - }) + pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion) pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib64/clang/${ClangShortVersion}/lib/linux") // These are tied to the version of LLVM directly in external/llvm, so they might trail the host prebuilts @@ -418,4 +404,30 @@ func init() { pctx.StaticVariableWithEnvOverride("REAbiLinkerExecStrategy", "RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy) } -var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS) +var HostPrebuiltTag = exportVariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS) + +func ClangPath(ctx android.PathContext, file string) android.SourcePath { + type clangToolKey string + + key := android.NewCustomOnceKey(clangToolKey(file)) + + return ctx.Config().OnceSourcePath(key, func() android.SourcePath { + return clangPath(ctx).Join(ctx, file) + }) +} + +var clangPathKey = android.NewOnceKey("clangPath") + +func clangPath(ctx android.PathContext) android.SourcePath { + return ctx.Config().OnceSourcePath(clangPathKey, func() android.SourcePath { + clangBase := ClangDefaultBase + if override := ctx.Config().Getenv("LLVM_PREBUILTS_BASE"); override != "" { + clangBase = override + } + clangVersion := ClangDefaultVersion + if override := ctx.Config().Getenv("LLVM_PREBUILTS_VERSION"); override != "" { + clangVersion = override + } + return android.PathForSource(ctx, clangBase, ctx.Config().PrebuiltOS(), clangVersion) + }) +} diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index 20384a871..6320dbbbc 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -95,8 +95,6 @@ type Toolchain interface { YasmFlags() string - WindresFlags() string - Is64Bit() bool ShlibSuffix() string @@ -169,10 +167,6 @@ func (toolchainBase) YasmFlags() string { return "" } -func (toolchainBase) WindresFlags() string { - return "" -} - func (toolchainBase) LibclangRuntimeLibraryArch() string { return "" } diff --git a/cc/config/vndk.go b/cc/config/vndk.go index 3f30191ab..9577a8c1c 100644 --- a/cc/config/vndk.go +++ b/cc/config/vndk.go @@ -103,6 +103,7 @@ var VndkMustUseVendorVariantList = []string{ "android.system.keystore2-V1-ndk", "android.hardware.wifi.hostapd-V1-ndk", "android.hardware.wifi.hostapd-V1-ndk_platform", + "android.hardware.wifi.supplicant-V1-ndk", "android.system.keystore2-V1-ndk_platform", "android.system.keystore2-ndk_platform", "android.system.keystore2-unstable-ndk_platform", diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go index 0bb1a816e..ad82b9476 100644 --- a/cc/config/x86_darwin_host.go +++ b/cc/config/x86_darwin_host.go @@ -56,9 +56,7 @@ var ( "10.13", "10.14", "10.15", - "11.0", - "11.1", - "11.3", + "11", } darwinAvailableLibraries = append( @@ -113,6 +111,10 @@ func init() { pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64") } +func MacStripPath(ctx android.PathContext) string { + return getMacTools(ctx).stripPath +} + type macPlatformTools struct { once sync.Once err error @@ -125,7 +127,7 @@ type macPlatformTools struct { var macTools = &macPlatformTools{} -func getMacTools(ctx android.PackageVarContext) *macPlatformTools { +func getMacTools(ctx android.PathContext) *macPlatformTools { macTools.once.Do(func() { xcrunTool := "/usr/bin/xcrun" @@ -134,7 +136,7 @@ func getMacTools(ctx android.PackageVarContext) *macPlatformTools { return "" } - bytes, err := exec.Command(xcrunTool, args...).Output() + bytes, err := exec.Command(xcrunTool, append([]string{"--sdk", "macosx"}, args...)...).Output() if err != nil { macTools.err = fmt.Errorf("xcrun %q failed with: %q", args, err) return "" @@ -143,34 +145,26 @@ func getMacTools(ctx android.PackageVarContext) *macPlatformTools { return strings.TrimSpace(string(bytes)) } - xcrunSdk := func(arg string) string { - if selected := ctx.Config().Getenv("MAC_SDK_VERSION"); selected != "" { - if !inList(selected, darwinSupportedSdkVersions) { - macTools.err = fmt.Errorf("MAC_SDK_VERSION %s isn't supported: %q", selected, darwinSupportedSdkVersions) - return "" - } - - return xcrun("--sdk", "macosx"+selected, arg) + sdkVersion := xcrun("--show-sdk-version") + sdkVersionSupported := false + for _, version := range darwinSupportedSdkVersions { + if version == sdkVersion || strings.HasPrefix(sdkVersion, version+".") { + sdkVersionSupported = true } - - for _, sdk := range darwinSupportedSdkVersions { - bytes, err := exec.Command(xcrunTool, "--sdk", "macosx"+sdk, arg).Output() - if err == nil { - return strings.TrimSpace(string(bytes)) - } - } - macTools.err = fmt.Errorf("Could not find a supported mac sdk: %q", darwinSupportedSdkVersions) - return "" + } + if !sdkVersionSupported { + macTools.err = fmt.Errorf("Unsupported macOS SDK version %q not in %v", sdkVersion, darwinSupportedSdkVersions) + return } - macTools.sdkRoot = xcrunSdk("--show-sdk-path") + macTools.sdkRoot = xcrun("--show-sdk-path") macTools.arPath = xcrun("--find", "ar") macTools.stripPath = xcrun("--find", "strip") macTools.toolPath = filepath.Dir(xcrun("--find", "ld")) }) if macTools.err != nil { - ctx.Errorf("%q", macTools.err) + android.ReportPathErrorf(ctx, "%q", macTools.err) } return macTools } diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index ac5d5f74e..43333fada 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -120,40 +120,40 @@ const ( ) func init() { - pctx.StaticVariable("LinuxGccVersion", linuxGccVersion) - pctx.StaticVariable("LinuxGlibcVersion", linuxGlibcVersion) + exportStringStaticVariable("LinuxGccVersion", linuxGccVersion) + exportStringStaticVariable("LinuxGlibcVersion", linuxGlibcVersion) + // Most places use the full GCC version. A few only use up to the first two numbers. if p := strings.Split(linuxGccVersion, "."); len(p) > 2 { - pctx.StaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], ".")) + exportStringStaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], ".")) } else { - pctx.StaticVariable("ShortLinuxGccVersion", linuxGccVersion) + exportStringStaticVariable("ShortLinuxGccVersion", linuxGccVersion) } - pctx.SourcePathVariable("LinuxGccRoot", - "prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}") - - pctx.StaticVariable("LinuxGccTriple", "x86_64-linux") - - pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " ")) - pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " ")) - pctx.StaticVariable("LinuxLldflags", strings.Join(linuxLdflags, " ")) - - pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " ")) - pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " ")) - pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " ")) - pctx.StaticVariable("LinuxX86Lldflags", strings.Join(linuxX86Ldflags, " ")) - pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " ")) - pctx.StaticVariable("LinuxX8664Lldflags", strings.Join(linuxX8664Ldflags, " ")) + exportSourcePathVariable("LinuxGccRoot", + "prebuilts/gcc/linux-x86/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}") + + exportStringListStaticVariable("LinuxGccTriple", []string{"x86_64-linux"}) + + exportStringListStaticVariable("LinuxCflags", linuxCflags) + exportStringListStaticVariable("LinuxLdflags", linuxLdflags) + exportStringListStaticVariable("LinuxLldflags", linuxLdflags) + exportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags) + exportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags) + exportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags) + exportStringListStaticVariable("LinuxMuslCflags", linuxMuslCflags) + exportStringListStaticVariable("LinuxMuslLdflags", linuxMuslLdflags) + exportStringListStaticVariable("LinuxMuslLldflags", linuxMuslLdflags) + + exportStringListStaticVariable("LinuxX86Cflags", linuxX86Cflags) + exportStringListStaticVariable("LinuxX8664Cflags", linuxX8664Cflags) + exportStringListStaticVariable("LinuxX86Ldflags", linuxX86Ldflags) + exportStringListStaticVariable("LinuxX86Lldflags", linuxX86Ldflags) + exportStringListStaticVariable("LinuxX8664Ldflags", linuxX8664Ldflags) + exportStringListStaticVariable("LinuxX8664Lldflags", linuxX8664Ldflags) // Yasm flags - pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86") - pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64") - - pctx.StaticVariable("LinuxGlibcCflags", strings.Join(linuxGlibcCflags, " ")) - pctx.StaticVariable("LinuxGlibcLdflags", strings.Join(linuxGlibcLdflags, " ")) - pctx.StaticVariable("LinuxGlibcLldflags", strings.Join(linuxGlibcLdflags, " ")) - pctx.StaticVariable("LinuxMuslCflags", strings.Join(linuxMuslCflags, " ")) - pctx.StaticVariable("LinuxMuslLdflags", strings.Join(linuxMuslLdflags, " ")) - pctx.StaticVariable("LinuxMuslLldflags", strings.Join(linuxMuslLdflags, " ")) + exportStringListStaticVariable("LinuxX86YasmFlags", []string{"-f elf32 -m x86"}) + exportStringListStaticVariable("LinuxX8664YasmFlags", []string{"-f elf64 -m amd64"}) } type toolchainLinux struct { diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go index d9a7537f3..9daf40f95 100644 --- a/cc/config/x86_windows_host.go +++ b/cc/config/x86_windows_host.go @@ -188,14 +188,6 @@ func (t *toolchainWindows) IncludeFlags() string { return "${config.WindowsIncludeFlags}" } -func (t *toolchainWindowsX86) WindresFlags() string { - return "-F pe-i386" -} - -func (t *toolchainWindowsX8664) WindresFlags() string { - return "-F pe-x86-64" -} - func (t *toolchainWindowsX86) ClangTriple() string { return "i686-windows-gnu" } diff --git a/cc/fuzz.go b/cc/fuzz.go index 83f003741..40f16f358 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -79,54 +79,21 @@ func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { return flags } -// This function performs a breadth-first search over the provided module's -// dependencies using `visitDirectDeps` to enumerate all shared library -// dependencies. We require breadth-first expansion, as otherwise we may -// incorrectly use 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.SingletonContext, module android.Module) android.Paths { - var fringe []android.Module - - seen := make(map[string]bool) - - // Enumerate the first level of dependencies, as we discard all non-library - // modules in the BFS loop below. - ctx.VisitDirectDeps(module, func(dep android.Module) { - if isValidSharedDependency(dep) { - fringe = append(fringe, dep) - } - }) - - var sharedLibraries android.Paths - - for i := 0; i < len(fringe); i++ { - module := fringe[i] - if seen[module.Name()] { - continue - } - seen[module.Name()] = true - - ccModule := module.(*Module) - sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile()) - ctx.VisitDirectDeps(module, func(dep android.Module) { - if isValidSharedDependency(dep) && !seen[dep.Name()] { - fringe = append(fringe, dep) - } - }) +func UnstrippedOutputFile(module android.Module) android.Path { + if mod, ok := module.(LinkableInterface); ok { + return mod.UnstrippedOutputFile() } - - return sharedLibraries + panic("UnstrippedOutputFile called on non-LinkableInterface module: " + module.Name()) } -// This function takes a module and determines if it is a unique shared library +// IsValidSharedDependency takes a module and determines if it is a unique shared library // that should be installed in the fuzz target output directories. This function // returns true, unless: // - The module is not an installable shared library, or // - The module is a header or stub, or // - The module is a prebuilt and its source is available, or // - The module is a versioned member of an SDK snapshot. -func isValidSharedDependency(dependency android.Module) bool { +func IsValidSharedDependency(dependency android.Module) bool { // TODO(b/144090547): We should be parsing these modules using // ModuleDependencyTag instead of the current brute-force checking. @@ -246,7 +213,7 @@ func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) { } seen[child.Name()] = true - if isValidSharedDependency(child) { + if IsValidSharedDependency(child) { sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile()) return true } @@ -304,7 +271,6 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module { // their architecture & target/host specific zip file. type ccFuzzPackager struct { fuzz.FuzzPackager - sharedLibInstallStrings []string } func fuzzPackagingFactory() android.Singleton { @@ -317,14 +283,14 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // archive}). archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip) - // Map tracking whether each shared library has an install rule to avoid duplicate install rules from - // multiple fuzzers that depend on the same shared library. - sharedLibraryInstalled := make(map[string]bool) - // List of individual fuzz targets, so that 'make fuzz' also installs the targets // to the correct output directories as well. s.FuzzTargets = make(map[string]bool) + // Map tracking whether each shared library has an install rule to avoid duplicate install rules from + // multiple fuzzers that depend on the same shared library. + sharedLibraryInstalled := make(map[string]bool) + ctx.VisitAllModules(func(module android.Module) { ccModule, ok := module.(*Module) if !ok || ccModule.Properties.PreventInstall { @@ -351,7 +317,7 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()} // Grab the list of required shared libraries. - sharedLibraries := collectAllSharedDependencies(ctx, module) + sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, UnstrippedOutputFile, IsValidSharedDependency) var files []fuzz.FileToZip builder := android.NewRuleBuilder(pctx, ctx) @@ -359,39 +325,8 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // Package the corpus, data, dict and config into a zipfile. files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder) - // Find and mark all the transiently-dependent shared libraries for - // packaging. - for _, library := range sharedLibraries { - files = append(files, fuzz.FileToZip{library, "lib"}) - - // For each architecture-specific shared library dependency, we need to - // install it to the output directory. Setup the install destination here, - // which will be used by $(copy-many-files) in the Make backend. - installDestination := sharedLibraryInstallLocation( - library, ccModule.Host(), archString) - if sharedLibraryInstalled[installDestination] { - continue - } - sharedLibraryInstalled[installDestination] = true - - // Escape all the variables, as the install destination here will be called - // via. $(eval) in Make. - installDestination = strings.ReplaceAll( - installDestination, "$", "$$") - s.sharedLibInstallStrings = append(s.sharedLibInstallStrings, - library.String()+":"+installDestination) - - // Ensure that on device, the library is also reinstalled to the /symbols/ - // dir. Symbolized DSO's are always installed to the device when fuzzing, but - // we want symbolization tools (like `stack`) to be able to find the symbols - // in $ANDROID_PRODUCT_OUT/symbols automagically. - if !ccModule.Host() { - symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString) - symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$") - s.sharedLibInstallStrings = append(s.sharedLibInstallStrings, - library.String()+":"+symbolsInstallDestination) - } - } + // Package shared libraries + files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...) // The executable. files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""}) @@ -409,15 +344,54 @@ func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) { packages := s.Packages.Strings() sort.Strings(packages) - sort.Strings(s.sharedLibInstallStrings) + sort.Strings(s.FuzzPackager.SharedLibInstallStrings) // TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's // ready to handle phony targets created in Soong. In the meantime, this // exports the phony 'fuzz' target and dependencies on packages to // core/main.mk so that we can use dist-for-goals. ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " ")) ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS", - strings.Join(s.sharedLibInstallStrings, " ")) + strings.Join(s.FuzzPackager.SharedLibInstallStrings, " ")) // Preallocate the slice of fuzz targets to minimise memory allocations. s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS") } + +// GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for +// packaging. +func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip { + var files []fuzz.FileToZip + + for _, library := range sharedLibraries { + files = append(files, fuzz.FileToZip{library, "lib"}) + + // For each architecture-specific shared library dependency, we need to + // install it to the output directory. Setup the install destination here, + // which will be used by $(copy-many-files) in the Make backend. + installDestination := sharedLibraryInstallLocation( + library, module.Host(), archString) + if (*sharedLibraryInstalled)[installDestination] { + continue + } + (*sharedLibraryInstalled)[installDestination] = true + + // Escape all the variables, as the install destination here will be called + // via. $(eval) in Make. + installDestination = strings.ReplaceAll( + installDestination, "$", "$$") + s.SharedLibInstallStrings = append(s.SharedLibInstallStrings, + library.String()+":"+installDestination) + + // Ensure that on device, the library is also reinstalled to the /symbols/ + // dir. Symbolized DSO's are always installed to the device when fuzzing, but + // we want symbolization tools (like `stack`) to be able to find the symbols + // in $ANDROID_PRODUCT_OUT/symbols automagically. + if !module.Host() { + symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString) + symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$") + s.SharedLibInstallStrings = append(s.SharedLibInstallStrings, + library.String()+":"+symbolsInstallDestination) + } + } + return files +} @@ -45,13 +45,6 @@ var ( CommandDeps: []string{"$syspropCmd"}, }, "headerOutDir", "publicOutDir", "srcOutDir", "includeName") - - windmc = pctx.AndroidStaticRule("windmc", - blueprint.RuleParams{ - Command: "$windmcCmd -r$$(dirname $out) -h$$(dirname $out) $in", - CommandDeps: []string{"$windmcCmd"}, - }, - "windmcCmd") ) type YaccProperties struct { @@ -200,26 +193,6 @@ func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Pa return cppFile, headers.Paths() } -func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFlags) (android.Path, android.Path) { - headerFile := android.GenPathWithExt(ctx, "windmc", srcFile, "h") - rcFile := android.GenPathWithExt(ctx, "windmc", srcFile, "rc") - - windmcCmd := mingwCmd(flags.toolchain, "windmc") - - ctx.Build(pctx, android.BuildParams{ - Rule: windmc, - Description: "windmc " + srcFile.Rel(), - Output: rcFile, - ImplicitOutput: headerFile, - Input: srcFile, - Args: map[string]string{ - "windmcCmd": windmcCmd, - }, - }) - - return rcFile, headerFile -} - // Used to communicate information from the genSources method back to the library code that uses // it. type generatedSourceInfo struct { @@ -305,10 +278,6 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, cppFile := rsGeneratedCppFile(ctx, srcFile) rsFiles = append(rsFiles, srcFiles[i]) srcFiles[i] = cppFile - case ".mc": - rcFile, headerFile := genWinMsg(ctx, srcFile, buildFlags) - srcFiles[i] = rcFile - deps = append(deps, headerFile) case ".sysprop": cppFile, headerFiles := genSysprop(ctx, srcFile) srcFiles[i] = cppFile diff --git a/cc/installer.go b/cc/installer.go index f95b49346..2522610d9 100644 --- a/cc/installer.go +++ b/cc/installer.go @@ -29,6 +29,9 @@ type InstallerProperties struct { // Install output directly in {partition}/, not in any subdir. This is only intended for use by // init_first_stage. Install_in_root *bool `android:"arch_variant"` + + // Install output directly in {partition}/xbin + Install_in_xbin *bool `android:"arch_vvariant"` } type installLocation int @@ -73,6 +76,8 @@ func (installer *baseInstaller) installDir(ctx ModuleContext) android.InstallPat if installer.installInRoot() { dir = "" + } else if installer.installInXbin() { + dir = "xbin" } if ctx.Target().NativeBridge == android.NativeBridgeEnabled { @@ -123,3 +128,7 @@ func (installer *baseInstaller) makeUninstallable(mod *Module) { func (installer *baseInstaller) installInRoot() bool { return Bool(installer.Properties.Install_in_root) } + +func (installer *baseInstaller) installInXbin() bool { + return Bool(installer.Properties.Install_in_xbin) +} diff --git a/cc/library.go b/cc/library.go index 0cffd5667..d63acfbf7 100644 --- a/cc/library.go +++ b/cc/library.go @@ -248,11 +248,13 @@ type bazelCcLibraryAttributes struct { Linkopts bazel.StringListAttribute Use_libcrt bazel.BoolAttribute Rtti bazel.BoolAttribute - Stl *string + + Stl *string + Cpp_std *string // This is shared only. - Version_script bazel.LabelAttribute - Link_crt bazel.BoolAttribute + Link_crt bazel.BoolAttribute + Additional_linker_inputs bazel.LabelListAttribute // Common properties shared between both shared and static variants. Shared staticOrSharedAttributes @@ -328,8 +330,9 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) { Use_libcrt: linkerAttrs.useLibcrt, Rtti: compilerAttrs.rtti, Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, - Version_script: linkerAttrs.versionScript, + Additional_linker_inputs: linkerAttrs.additionalLinkerInputs, Strip: stripAttributes{ Keep_symbols: linkerAttrs.stripKeepSymbols, @@ -636,7 +639,7 @@ func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx androi func (handler *ccLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext - ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType) + ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err) return false @@ -2399,10 +2402,10 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, attrs = &bazelCcLibraryStaticAttributes{ staticOrSharedAttributes: commonAttrs, - Linkopts: linkerAttrs.linkopts, Use_libcrt: linkerAttrs.useLibcrt, Rtti: compilerAttrs.rtti, Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, Export_includes: exportedIncludes.Includes, Export_system_includes: exportedIncludes.SystemIncludes, Local_includes: compilerAttrs.localIncludes, @@ -2427,12 +2430,13 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, Use_libcrt: linkerAttrs.useLibcrt, Rtti: compilerAttrs.rtti, Stl: compilerAttrs.stl, + Cpp_std: compilerAttrs.cppStd, - Export_includes: exportedIncludes.Includes, - Export_system_includes: exportedIncludes.SystemIncludes, - Local_includes: compilerAttrs.localIncludes, - Absolute_includes: compilerAttrs.absoluteIncludes, - Version_script: linkerAttrs.versionScript, + Export_includes: exportedIncludes.Includes, + Export_system_includes: exportedIncludes.SystemIncludes, + Local_includes: compilerAttrs.localIncludes, + Absolute_includes: compilerAttrs.absoluteIncludes, + Additional_linker_inputs: linkerAttrs.additionalLinkerInputs, Strip: stripAttributes{ Keep_symbols: linkerAttrs.stripKeepSymbols, @@ -2458,10 +2462,10 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, type bazelCcLibraryStaticAttributes struct { staticOrSharedAttributes - Linkopts bazel.StringListAttribute Use_libcrt bazel.BoolAttribute Rtti bazel.BoolAttribute Stl *string + Cpp_std *string Export_includes bazel.StringListAttribute Export_system_includes bazel.StringListAttribute @@ -2489,6 +2493,7 @@ type bazelCcLibrarySharedAttributes struct { Use_libcrt bazel.BoolAttribute Rtti bazel.BoolAttribute Stl *string + Cpp_std *string Export_includes bazel.StringListAttribute Export_system_includes bazel.StringListAttribute @@ -2496,8 +2501,8 @@ type bazelCcLibrarySharedAttributes struct { Absolute_includes bazel.StringListAttribute Hdrs bazel.LabelListAttribute - Strip stripAttributes - Version_script bazel.LabelAttribute + Strip stripAttributes + Additional_linker_inputs bazel.LabelListAttribute Cppflags bazel.StringListAttribute Conlyflags bazel.StringListAttribute diff --git a/cc/library_headers.go b/cc/library_headers.go index 51c1eb828..b2b3dbce9 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -57,7 +57,7 @@ type libraryHeaderBazelHander struct { func (h *libraryHeaderBazelHander) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext - ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType) + ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err) return false diff --git a/cc/linkable.go b/cc/linkable.go index b510508a7..560c9debe 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -110,6 +110,7 @@ type LinkableInterface interface { BaseModuleName() string OutputFile() android.OptionalPath + UnstrippedOutputFile() android.Path CoverageFiles() android.Paths NonCcVariants() bool @@ -49,8 +49,9 @@ type LTOProperties struct { // Dep properties indicate that this module needs to be built with LTO // since it is an object dependency of an LTO module. - FullDep bool `blueprint:"mutated"` - ThinDep bool `blueprint:"mutated"` + FullDep bool `blueprint:"mutated"` + ThinDep bool `blueprint:"mutated"` + NoLtoDep bool `blueprint:"mutated"` // Use clang lld instead of gnu ld. Use_clang_lld *bool @@ -70,15 +71,6 @@ func (lto *lto) props() []interface{} { func (lto *lto) begin(ctx BaseModuleContext) { if ctx.Config().IsEnvTrue("DISABLE_LTO") { lto.Properties.Lto.Never = proptools.BoolPtr(true) - } else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") { - staticLib := ctx.static() && !ctx.staticBinary() - hostBin := ctx.Host() - vndk := ctx.isVndk() // b/169217596 - if !staticLib && !hostBin && !vndk { - if !lto.Never() && !lto.FullLTO() { - lto.Properties.Lto.Thin = proptools.BoolPtr(true) - } - } } } @@ -96,22 +88,27 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { return flags } - if lto.LTO() { - var ltoFlag string + if lto.LTO(ctx) { + var ltoCFlag string + var ltoLdFlag string if lto.ThinLTO() { - ltoFlag = "-flto=thin -fsplit-lto-unit" + ltoCFlag = "-flto=thin -fsplit-lto-unit" + } else if lto.FullLTO() { + ltoCFlag = "-flto" } else { - ltoFlag = "-flto" + ltoCFlag = "-flto=thin -fsplit-lto-unit" + ltoLdFlag = "-Wl,--lto-O0" } - flags.Local.CFlags = append(flags.Local.CFlags, ltoFlag) - flags.Local.LdFlags = append(flags.Local.LdFlags, ltoFlag) + flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlag) + flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlag) + flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlag) if Bool(lto.Properties.Whole_program_vtables) { flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables") } - if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) { + if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) { // Set appropriate ThinLTO cache policy cacheDirFormat := "-Wl,--thinlto-cache-dir=" cacheDir := android.PathForOutput(ctx, "thinlto-cache").String() @@ -134,33 +131,41 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { return flags } -// Can be called with a null receiver -func (lto *lto) LTO() bool { - if lto == nil || lto.Never() { - return false - } +func (lto *lto) LTO(ctx BaseModuleContext) bool { + return lto.ThinLTO() || lto.FullLTO() || lto.DefaultThinLTO(ctx) +} - return lto.FullLTO() || lto.ThinLTO() +func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool { + host := ctx.Host() + test := ctx.testBinary() + vndk := ctx.isVndk() // b/169217596 + return GlobalThinLTO(ctx) && !lto.Never() && !host && !test && !vndk } func (lto *lto) FullLTO() bool { - return Bool(lto.Properties.Lto.Full) + return lto != nil && Bool(lto.Properties.Lto.Full) } func (lto *lto) ThinLTO() bool { - return Bool(lto.Properties.Lto.Thin) + return lto != nil && Bool(lto.Properties.Lto.Thin) } -// Is lto.never explicitly set to true? func (lto *lto) Never() bool { - return Bool(lto.Properties.Lto.Never) + return lto != nil && Bool(lto.Properties.Lto.Never) +} + +func GlobalThinLTO(ctx android.BaseModuleContext) bool { + return ctx.Config().IsEnvTrue("GLOBAL_THINLTO") } // Propagate lto requirements down from binaries func ltoDepsMutator(mctx android.TopDownMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() { + globalThinLTO := GlobalThinLTO(mctx) + + if m, ok := mctx.Module().(*Module); ok { full := m.lto.FullLTO() thin := m.lto.ThinLTO() + never := m.lto.Never() if full && thin { mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive") } @@ -180,14 +185,16 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { } } - if dep, ok := dep.(*Module); ok && dep.lto != nil && - !dep.lto.Never() { + if dep, ok := dep.(*Module); ok { if full && !dep.lto.FullLTO() { dep.lto.Properties.FullDep = true } - if thin && !dep.lto.ThinLTO() { + if !globalThinLTO && thin && !dep.lto.ThinLTO() { dep.lto.Properties.ThinDep = true } + if globalThinLTO && never && !dep.lto.Never() { + dep.lto.Properties.NoLtoDep = true + } } // Recursively walk static dependencies @@ -198,6 +205,8 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { // Create lto variants for modules that need them func ltoMutator(mctx android.BottomUpMutatorContext) { + globalThinLTO := GlobalThinLTO(mctx) + if m, ok := mctx.Module().(*Module); ok && m.lto != nil { // Create variations for LTO types required as static // dependencies @@ -205,18 +214,25 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { if m.lto.Properties.FullDep && !m.lto.FullLTO() { variationNames = append(variationNames, "lto-full") } - if m.lto.Properties.ThinDep && !m.lto.ThinLTO() { + if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() { variationNames = append(variationNames, "lto-thin") } + if globalThinLTO && m.lto.Properties.NoLtoDep && !m.lto.Never() { + variationNames = append(variationNames, "lto-none") + } // Use correct dependencies if LTO property is explicitly set // (mutually exclusive) if m.lto.FullLTO() { mctx.SetDependencyVariation("lto-full") } - if m.lto.ThinLTO() { + if !globalThinLTO && m.lto.ThinLTO() { mctx.SetDependencyVariation("lto-thin") } + // Never must be the last, it overrides Thin or Full. + if globalThinLTO && m.lto.Never() { + mctx.SetDependencyVariation("lto-none") + } if len(variationNames) > 1 { modules := mctx.CreateVariations(variationNames...) @@ -232,16 +248,18 @@ func ltoMutator(mctx android.BottomUpMutatorContext) { // LTO properties for dependencies if name == "lto-full" { variation.lto.Properties.Lto.Full = proptools.BoolPtr(true) - variation.lto.Properties.Lto.Thin = proptools.BoolPtr(false) } if name == "lto-thin" { - variation.lto.Properties.Lto.Full = proptools.BoolPtr(false) variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true) } + if name == "lto-none" { + variation.lto.Properties.Lto.Never = proptools.BoolPtr(true) + } variation.Properties.PreventInstall = true variation.Properties.HideFromMake = true variation.lto.Properties.FullDep = false variation.lto.Properties.ThinDep = false + variation.lto.Properties.NoLtoDep = false } } } diff --git a/cc/object.go b/cc/object.go index d8bb08fac..43abb3a3c 100644 --- a/cc/object.go +++ b/cc/object.go @@ -54,7 +54,7 @@ type objectBazelHandler struct { func (handler *objectBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext - objPaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType) + objPaths, ok := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx)) if ok { if len(objPaths) != 1 { ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths) diff --git a/cc/prebuilt.go b/cc/prebuilt.go index d324241e0..4a2c451f5 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -16,7 +16,6 @@ package cc import ( "path/filepath" - "strings" "android/soong/android" ) @@ -232,7 +231,7 @@ func (p *prebuiltLibraryLinker) disablePrebuilt() { // Implements versionedInterface func (p *prebuiltLibraryLinker) implementationModuleName(name string) string { - return strings.TrimPrefix(name, "prebuilt_") + return android.RemoveOptionalPrebuiltPrefix(name) } func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { @@ -330,7 +329,7 @@ type prebuiltStaticLibraryBazelHandler struct { func (h *prebuiltStaticLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext - ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType) + ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx)) if err != nil { ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err) } diff --git a/cmd/multiproduct_kati/Android.bp b/cmd/multiproduct_kati/Android.bp index e5be6c0c8..20ca2a3c9 100644 --- a/cmd/multiproduct_kati/Android.bp +++ b/cmd/multiproduct_kati/Android.bp @@ -31,4 +31,14 @@ blueprint_go_binary { testSrcs: [ "main_test.go", ], + linux: { + srcs: [ + "main_linux.go", + ], + }, + darwin: { + srcs: [ + "main_darwin.go", + ], + }, } diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go index 3c9cac190..0577c86ff 100644 --- a/cmd/multiproduct_kati/main.go +++ b/cmd/multiproduct_kati/main.go @@ -166,15 +166,6 @@ type mpContext struct { MainLogsDir string } -func detectTotalRAM() uint64 { - var info syscall.Sysinfo_t - err := syscall.Sysinfo(&info) - if err != nil { - panic(err) - } - return info.Totalram * uint64(info.Unit) -} - func findNamedProducts(soongUi string, log logger.Logger) []string { cmd := exec.Command(soongUi, "--dumpvars-mode", "--vars=all_named_products") output, err := cmd.Output() @@ -301,7 +292,7 @@ func main() { jobs = runtime.NumCPU() / 4 ramGb := int(detectTotalRAM() / (1024 * 1024 * 1024)) - if ramJobs := ramGb / 25; ramGb > 0 && jobs > ramJobs { + if ramJobs := ramGb / 30; ramGb > 0 && jobs > ramJobs { jobs = ramJobs } diff --git a/cmd/multiproduct_kati/main_darwin.go b/cmd/multiproduct_kati/main_darwin.go new file mode 100644 index 000000000..3d1b12ab1 --- /dev/null +++ b/cmd/multiproduct_kati/main_darwin.go @@ -0,0 +1,20 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +func detectTotalRAM() uint64 { + // unimplemented stub on darwin + return 0 +} diff --git a/cmd/multiproduct_kati/main_linux.go b/cmd/multiproduct_kati/main_linux.go new file mode 100644 index 000000000..db7449696 --- /dev/null +++ b/cmd/multiproduct_kati/main_linux.go @@ -0,0 +1,28 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "syscall" +) + +func detectTotalRAM() uint64 { + var info syscall.Sysinfo_t + err := syscall.Sysinfo(&info) + if err != nil { + panic(err) + } + return info.Totalram * uint64(info.Unit) +} diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index c5e889664..e9eabd37c 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -217,15 +217,6 @@ func doChosenActivity(configuration android.Config, extraNinjaDeps []string) str generateModuleGraphFile := moduleGraphFile != "" generateDocFile := docFile != "" - blueprintArgs := cmdlineArgs - - var stopBefore bootstrap.StopBefore - if !generateModuleGraphFile && !generateQueryView && !generateDocFile { - stopBefore = bootstrap.DoEverything - } else { - stopBefore = bootstrap.StopBeforePrepareBuildActions - } - if generateBazelWorkspace { // Run the alternate pipeline of bp2build mutators and singleton to convert // Blueprint to BUILD files before everything else. @@ -233,6 +224,19 @@ func doChosenActivity(configuration android.Config, extraNinjaDeps []string) str return bp2buildMarker } + blueprintArgs := cmdlineArgs + + var stopBefore bootstrap.StopBefore + if generateModuleGraphFile { + stopBefore = bootstrap.StopBeforeWriteNinja + } else if generateQueryView { + stopBefore = bootstrap.StopBeforePrepareBuildActions + } else if generateDocFile { + stopBefore = bootstrap.StopBeforePrepareBuildActions + } else { + stopBefore = bootstrap.DoEverything + } + ctx := newContext(configuration) if mixedModeBuild { runMixedModeBuild(configuration, ctx, extraNinjaDeps) diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index a1ce8dc8e..2865ffad2 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -439,6 +439,7 @@ func PrebuiltEtcHostFactory() android.Module { InitPrebuiltEtcModule(module, "etc") // This module is host-only android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) + android.InitDefaultableModule(module) return module } @@ -449,6 +450,7 @@ func PrebuiltRootFactory() android.Module { InitPrebuiltRootModule(module) // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } @@ -459,6 +461,7 @@ func PrebuiltUserShareFactory() android.Module { InitPrebuiltEtcModule(module, "usr/share") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } @@ -469,6 +472,7 @@ func PrebuiltUserShareHostFactory() android.Module { InitPrebuiltEtcModule(module, "usr/share") // This module is host-only android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) + android.InitDefaultableModule(module) return module } @@ -478,6 +482,7 @@ func PrebuiltFontFactory() android.Module { InitPrebuiltEtcModule(module, "fonts") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } @@ -491,6 +496,7 @@ func PrebuiltFirmwareFactory() android.Module { InitPrebuiltEtcModule(module, "etc/firmware") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } @@ -503,6 +509,7 @@ func PrebuiltDSPFactory() android.Module { InitPrebuiltEtcModule(module, "etc/dsp") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } @@ -516,6 +523,7 @@ func PrebuiltRFSAFactory() android.Module { InitPrebuiltEtcModule(module, "lib/rfsa") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) return module } diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index ccadc0ff2..8861d1b6b 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -42,8 +42,9 @@ type FuzzModule struct { } type FuzzPackager struct { - Packages android.Paths - FuzzTargets map[string]bool + Packages android.Paths + FuzzTargets map[string]bool + SharedLibInstallStrings []string } type FileToZip struct { @@ -251,3 +252,42 @@ func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets str sort.Strings(fuzzTargets) ctx.Strict(targets, strings.Join(fuzzTargets, " ")) } + +// CollectAllSharedDependencies performs a breadth-first search over the provided module's +// dependencies using `visitDirectDeps` to enumerate all shared library +// dependencies. We require breadth-first expansion, as otherwise we may +// incorrectly use 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.SingletonContext, module android.Module, unstrippedOutputFile func(module android.Module) android.Path, isValidSharedDependency func(dependency android.Module) bool) android.Paths { + var fringe []android.Module + + seen := make(map[string]bool) + + // Enumerate the first level of dependencies, as we discard all non-library + // modules in the BFS loop below. + ctx.VisitDirectDeps(module, func(dep android.Module) { + if isValidSharedDependency(dep) { + fringe = append(fringe, dep) + } + }) + + var sharedLibraries android.Paths + + for i := 0; i < len(fringe); i++ { + module := fringe[i] + if seen[module.Name()] { + continue + } + seen[module.Name()] = true + + sharedLibraries = append(sharedLibraries, unstrippedOutputFile(module)) + ctx.VisitDirectDeps(module, func(dep android.Module) { + if isValidSharedDependency(dep) && !seen[dep.Name()] { + fringe = append(fringe, dep) + } + }) + } + + return sharedLibraries +} diff --git a/genrule/genrule.go b/genrule/genrule.go index 4dd21351a..b9c2b109d 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -248,7 +248,7 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) { // Returns true if information was available from Bazel, false if bazel invocation still needs to occur. func (c *Module) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool { bazelCtx := ctx.Config().BazelContext - filePaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType) + filePaths, ok := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx)) if ok { var bazelOutputFiles android.Paths exportIncludeDirs := map[string]bool{} diff --git a/java/androidmk.go b/java/androidmk.go index 537159ef3..eca5caacb 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -60,6 +60,11 @@ func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries { func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { var entriesList []android.AndroidMkEntries + if library.Os() == android.Windows { + // Make does not support Windows Java modules + return nil + } + if library.hideApexVariantFromMake { // For a java library built for an APEX, we don't need a Make module for itself. Otherwise, it // will conflict with the platform variant because they have the same module name in the @@ -250,6 +255,10 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries { } func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { + if binary.Os() == android.Windows { + // Make does not support Windows Java modules + return nil + } if !binary.isWrapperVariant { return []android.AndroidMkEntries{android.AndroidMkEntries{ diff --git a/java/device_host_converter.go b/java/device_host_converter.go index 39fb04a8e..4abdcc6e9 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -118,7 +118,7 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont TransformJarsToJar(ctx, outputFile, "combine", d.implementationAndResourceJars, android.OptionalPath{}, false, nil, nil) d.combinedImplementationJar = outputFile - } else { + } else if len(d.implementationAndResourceJars) == 1 { d.combinedImplementationJar = d.implementationAndResourceJars[0] } @@ -127,7 +127,7 @@ func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleCont TransformJarsToJar(ctx, outputFile, "turbine combine", d.headerJars, android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"}) d.combinedHeaderJar = outputFile - } else { + } else if len(d.headerJars) == 1 { d.combinedHeaderJar = d.headerJars[0] } @@ -174,7 +174,9 @@ func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData { return android.AndroidMkData{ Class: "JAVA_LIBRARIES", OutputFile: android.OptionalPathForPath(d.combinedImplementationJar), - Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", + // Make does not support Windows Java modules + Disabled: d.Os() == android.Windows, + Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true") diff --git a/java/genrule.go b/java/genrule.go index e0a9c8faf..16743b357 100644 --- a/java/genrule.go +++ b/java/genrule.go @@ -64,6 +64,7 @@ func genRuleFactory() android.Module { module := genrule.NewGenRule() android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) return module } @@ -76,6 +77,7 @@ func genRuleFactoryHost() android.Module { module := genrule.NewGenRule() android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) + android.InitDefaultableModule(module) return module } diff --git a/java/java.go b/java/java.go index 287bcfaeb..854097b0a 100644 --- a/java/java.go +++ b/java/java.go @@ -532,6 +532,14 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo return false } +// Sets `dexer.dexProperties.Uncompress_dex` to the proper value. +func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) { + if dexer.dexProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, dexpreopter)) + } +} + func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) @@ -545,10 +553,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.installPath = j.dexpreopter.getInstallPath( ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - if j.dexProperties.Uncompress_dex == nil { - // If the value was not force-set by the user, use reasonable default based on the module. - j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) - } + setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) j.compile(ctx, nil) @@ -565,10 +570,6 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), j.Stem()+".jar", j.outputFile, extraInstallDeps...) } - - if ctx.Windows() { - j.HideFromMake() - } } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1135,10 +1136,6 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName()+ext, j.wrapperFile) } - - if ctx.Windows() { - j.HideFromMake() - } } func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1401,16 +1398,13 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName())) j.dexJarInstallFile = installPath - // Initialize the hiddenapi structure. - j.initHiddenAPI(ctx, dexJarFile, outputFile, nil) - j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath) - if j.dexProperties.Uncompress_dex == nil { - // If the value was not force-set by the user, use reasonable default based on the module. - j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) - } + setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex j.dexpreopt(ctx, dexOutputPath) + + // Initialize the hiddenapi structure. + j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex) } else { // This should never happen as a variant for a prebuilt_apex is only created if the // prebuilt_apex has been configured to export the java library dex file. @@ -1430,10 +1424,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.dexpreopter.installPath = j.dexpreopter.getInstallPath( ctx, android.PathForModuleInstall(ctx, "framework", jarName)) - if j.dexProperties.Uncompress_dex == nil { - // If the value was not force-set by the user, use reasonable default based on the module. - j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) - } + setUncompressDex(ctx, &j.dexpreopter, &j.dexer) j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex var dexOutputFile android.OutputPath @@ -1549,9 +1540,6 @@ var _ android.IDEInfo = (*Import)(nil) var _ android.IDECustomizedModuleName = (*Import)(nil) // Collect information for opening IDE project files in java/jdeps.go. -const ( - removedPrefix = "prebuilt_" -) func (j *Import) IDEInfo(dpInfo *android.IdeInfo) { dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...) diff --git a/java/proto.go b/java/proto.go index 8731822c3..2fa22b626 100644 --- a/java/proto.go +++ b/java/proto.go @@ -24,7 +24,7 @@ import ( func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths { // Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid // hitting command line length limits. - shards := android.ShardPaths(protoFiles, 100) + shards := android.ShardPaths(protoFiles, 50) srcJarFiles := make(android.Paths, 0, len(shards)) diff --git a/java/sdk.go b/java/sdk.go index d1b899e48..80f2d6a69 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -370,7 +370,7 @@ func createAPIFingerprint(ctx android.SingletonContext) { "frameworks-base-api-current.txt", "frameworks-base-api-system-current.txt", "frameworks-base-api-module-lib-current.txt", - "services-system-server-current.txt", + "frameworks-base-api-system-server-current.txt", } count := 0 ctx.VisitAllModules(func(module android.Module) { diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 3ae8ab94c..b377fd828 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -1162,17 +1162,21 @@ func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive, } // Either pattern or text should be const, and the // non-const one should be varRefExpr - if xInList, ok = xPattern.(*stringLiteralExpr); ok { + if xInList, ok = xPattern.(*stringLiteralExpr); ok && !strings.ContainsRune(xInList.literal, '%') && xText.typ() == starlarkTypeList { expr = xText } else if xInList, ok = xText.(*stringLiteralExpr); ok { expr = xPattern } else { - return &callExpr{ + expr = &callExpr{ object: nil, name: filterFuncCall.name, args: filterFuncCall.args, returnType: starlarkTypeBool, } + if negate { + expr = ¬Expr{expr: expr} + } + return expr } case *variableRefExpr: if v, ok := xPattern.(*variableRefExpr); ok { diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go index 434500bf7..fe1fa0813 100644 --- a/mk2rbc/mk2rbc_test.go +++ b/mk2rbc/mk2rbc_test.go @@ -360,20 +360,27 @@ ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng)) endif ifneq (,$(filter true, $(v1)$(v2))) endif +ifeq (,$(filter barbet coral%,$(TARGET_PRODUCT))) +else ifneq (,$(filter barbet%,$(TARGET_PRODUCT))) +endif `, expected: `load("//build/make/core:product_config.rbc", "rblf") def init(g, handle): cfg = rblf.cfg(handle) - if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]: + if not rblf.filter("userdebug eng", g["TARGET_BUILD_VARIANT"]): pass - if g["TARGET_BUILD_VARIANT"] == "userdebug": + if rblf.filter("userdebug", g["TARGET_BUILD_VARIANT"]): pass if "plaf" in g.get("PLATFORM_LIST", []): pass if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]: pass - if "%s%s" % (_v1, _v2) == "true": + if rblf.filter("true", "%s%s" % (_v1, _v2)): + pass + if not rblf.filter("barbet coral%", g["TARGET_PRODUCT"]): + pass + elif rblf.filter("barbet%", g["TARGET_PRODUCT"]): pass `, }, diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go index 27e8198a8..64645d761 100644 --- a/mk2rbc/version_defaults.go +++ b/mk2rbc/version_defaults.go @@ -15,7 +15,6 @@ package mk2rbc import ( - mkparser "android/soong/androidmk/parser" "bytes" "fmt" "io/ioutil" @@ -23,6 +22,8 @@ import ( "sort" "strconv" "strings" + + mkparser "android/soong/androidmk/parser" ) const codenamePrefix = "PLATFORM_VERSION_CODENAME." @@ -97,7 +98,10 @@ func VersionDefaults(values map[string]string) string { strings.ToLower(name), genericValue(value))) } } + sort.Strings(lines) + sort.Strings(codenames) + sink.WriteString("version_defaults = struct(\n") for _, l := range lines { sink.WriteString(l) diff --git a/rust/builder.go b/rust/builder.go index 426a569bf..f79cf9b12 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -95,7 +95,7 @@ func init() { func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin") } @@ -112,13 +112,13 @@ func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib") } func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib") } diff --git a/rust/compiler.go b/rust/compiler.go index 1ce71f60b..cada9854a 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -449,6 +449,10 @@ func (compiler *baseCompiler) relativeInstallPath() string { // Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs. func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) { + if len(srcs) == 0 { + ctx.PropertyErrorf("srcs", "srcs must not be empty") + } + // The srcs can contain strings with prefix ":". // They are dependent modules of this module, with android.SourceDepTag. // They are not the main source file compiled by rustc. diff --git a/rust/compiler_test.go b/rust/compiler_test.go index f589b691d..ec6829a1b 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -98,6 +98,41 @@ func TestEnforceSingleSourceFile(t *testing.T) { }`) } +// Test that we reject _no_ source files. +func TestEnforceMissingSourceFiles(t *testing.T) { + + singleSrcError := "srcs must not be empty" + + // Test libraries + testRustError(t, singleSrcError, ` + rust_library_host { + name: "foo-bar-library", + crate_name: "foo", + }`) + + // Test binaries + testRustError(t, singleSrcError, ` + rust_binary_host { + name: "foo-bar-binary", + crate_name: "foo", + }`) + + // Test proc_macros + testRustError(t, singleSrcError, ` + rust_proc_macro { + name: "foo-bar-proc-macro", + crate_name: "foo", + }`) + + // Test prebuilts + testRustError(t, singleSrcError, ` + rust_prebuilt_dylib { + name: "foo-bar-prebuilt", + crate_name: "foo", + host_supported: true, + }`) +} + // Test environment vars for Cargo compat are set. func TestCargoCompat(t *testing.T) { ctx := testRust(t, ` diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go index 47ca3a7ec..b11357383 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -32,6 +32,7 @@ var ( "system/security", "system/tools/aidl", "tools/security/fuzzing/example_rust_fuzzer", + "tools/security/fuzzing/orphans", "vendor/", } diff --git a/rust/fuzz.go b/rust/fuzz.go index 5fb56ff40..a628b6158 100644 --- a/rust/fuzz.go +++ b/rust/fuzz.go @@ -111,6 +111,10 @@ func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // List of individual fuzz targets. s.FuzzTargets = make(map[string]bool) + // Map tracking whether each shared library has an install rule to avoid duplicate install rules from + // multiple fuzzers that depend on the same shared library. + sharedLibraryInstalled := make(map[string]bool) + ctx.VisitAllModules(func(module android.Module) { // Discard non-fuzz targets. rustModule, ok := module.(*Module) @@ -145,6 +149,12 @@ func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // The executable. files = append(files, fuzz.FileToZip{rustModule.unstrippedOutputFile.Path(), ""}) + // Grab the list of required shared libraries. + sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency) + + // Package shared libraries + files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...) + archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs) if !ok { return diff --git a/rust/rust.go b/rust/rust.go index b9afc7f82..13169f17e 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -130,9 +130,10 @@ type BaseProperties struct { // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). Min_sdk_version *string - PreventInstall bool - HideFromMake bool - Installable *bool + HideFromMake bool `blueprint:"mutated"` + PreventInstall bool `blueprint:"mutated"` + + Installable *bool } type Module struct { @@ -177,8 +178,8 @@ func (mod *Module) SetHideFromMake() { mod.Properties.HideFromMake = true } -func (c *Module) HiddenFromMake() bool { - return c.Properties.HideFromMake +func (mod *Module) HiddenFromMake() bool { + return mod.Properties.HideFromMake } func (mod *Module) SanitizePropDefined() bool { @@ -526,10 +527,6 @@ func (mod *Module) PreventInstall() bool { return mod.Properties.PreventInstall } -func (mod *Module) HideFromMake() { - mod.Properties.HideFromMake = true -} - func (mod *Module) MarkAsCoverageVariant(coverage bool) { mod.coverage.Properties.IsCoverageVariant = coverage } @@ -597,6 +594,13 @@ func (mod *Module) CcLibraryInterface() bool { return false } +func (mod *Module) UnstrippedOutputFile() android.Path { + if mod.unstrippedOutputFile.Valid() { + return mod.unstrippedOutputFile.Path() + } + return nil +} + func (mod *Module) IncludeDirs() android.Paths { if mod.compiler != nil { if library, ok := mod.compiler.(*libraryDecorator); ok { @@ -898,8 +902,24 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo) - if mod.installable(apexInfo) { + if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) { + // If the module has been specifically configure to not be installed then + // hide from make as otherwise it will break when running inside make as the + // output path to install will not be specified. Not all uninstallable + // modules can be hidden from make as some are needed for resolving make + // side dependencies. + mod.HideFromMake() + } else if !mod.installable(apexInfo) { + mod.SkipInstall() + } + + // Still call install though, the installs will be stored as PackageSpecs to allow + // using the outputs in a genrule. + if mod.OutputFile().Valid() { mod.compiler.install(ctx) + if ctx.Failed() { + return + } } ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh index b05861ba1..281cb82a4 100755 --- a/scripts/build-mainline-modules.sh +++ b/scripts/build-mainline-modules.sh @@ -17,6 +17,7 @@ MAINLINE_MODULES=( MODULES_SDK_AND_EXPORTS=( art-module-sdk art-module-test-exports + compos-module-sdk conscrypt-module-host-exports conscrypt-module-sdk conscrypt-module-test-exports diff --git a/scripts/gen_ndk_backedby_apex.sh b/scripts/gen_ndk_backedby_apex.sh index 4abaaba41..212362e03 100755 --- a/scripts/gen_ndk_backedby_apex.sh +++ b/scripts/gen_ndk_backedby_apex.sh @@ -21,52 +21,29 @@ # 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 backed-by NDK symbols." + echo "This script is used to generate the native libraries backed by Mainline modules." echo "" - echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$NDK_LIB_NAME_LIST \$MODULE_LIB1 \$MODULE_LIB2..." + echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$MODULE_LIB1 \$MODULE_LIB2..." echo "For example: If output write to /backedby.txt then the command would be:" - echo "./gen_ndk_backed_by_apex.sh /backedby.txt /ndkLibList.txt lib1.so lib2.so" + echo "./gen_ndk_backed_by_apex.sh /backedby.txt lib1.so lib2.so" echo "If the module1 is backing lib1 then the backedby.txt would contains: " - echo "lib1" + echo "lib1.so lib2.so" } -contains() { - val="$1" - shift - for x in "$@"; do - if [ "$x" = "$val" ]; then - return 0 - fi - done - return 1 -} - - -genBackedByList() { +genAllBackedByList() { out="$1" shift - ndk_list="$1" - shift rm -f "$out" touch "$out" - while IFS= read -r line - do - soFileName=$(echo "$line" | sed 's/\(.*so\).*/\1/') - if [[ ! -z "$soFileName" && "$soFileName" != *"#"* ]] - then - if contains "$soFileName" "$@"; then - echo "$soFileName" >> "$out" - fi - fi - done < "$ndk_list" + echo "$@" >> "$out" } if [[ "$1" == "help" ]] then printHelp -elif [[ "$#" -lt 2 ]] +elif [[ "$#" -lt 1 ]] then - echo "Wrong argument length. Expecting at least 2 argument representing output path, path to ndk library list, followed by a list of libraries in the Mainline module." + echo "Wrong argument length. Expecting at least 1 argument representing output path, followed by a list of libraries in the Mainline module." else - genBackedByList "$@" + genAllBackedByList "$@" fi diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py index 64d922a20..691c45dd3 100755 --- a/scripts/get_clang_version.py +++ b/scripts/get_clang_version.py @@ -34,7 +34,7 @@ def get_clang_prebuilts_version(global_go): with open(global_go) as infile: contents = infile.read() - regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-r\d+[a-z]?\d?)"' + regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-.*)"' match_rev = re.search(regex_rev, contents) if match_rev is None: raise RuntimeError('Parsing clang info failed') diff --git a/ui/build/config.go b/ui/build/config.go index 5cd5c658d..7837cc4e0 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -83,6 +83,8 @@ type configImpl struct { // Set by multiproduct_kati emptyNinjaFile bool + + metricsUploader string } const srcDirFileCheck = "build/soong/root.bp" @@ -237,7 +239,8 @@ func NewConfig(ctx Context, args ...string) Config { // Precondition: the current directory is the top of the source tree checkTopDir(ctx) - if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') { + srcDir := absPath(ctx, ".") + if strings.ContainsRune(srcDir, ' ') { ctx.Println("You are building in a directory whose absolute path contains a space character:") ctx.Println() ctx.Printf("%q\n", srcDir) @@ -245,6 +248,8 @@ func NewConfig(ctx Context, args ...string) Config { ctx.Fatalln("Directory names containing spaces are not supported") } + ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ) + if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') { ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:") ctx.Println() @@ -1246,10 +1251,7 @@ func (c *configImpl) BuildDateTime() string { } func (c *configImpl) MetricsUploaderApp() string { - if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok { - return p - } - return "" + return c.metricsUploader } // LogsDir returns the logs directory where build log and metrics @@ -1277,3 +1279,14 @@ func (c *configImpl) SetEmptyNinjaFile(v bool) { func (c *configImpl) EmptyNinjaFile() bool { return c.emptyNinjaFile } + +func GetMetricsUploader(topDir string, env *Environment) string { + if p, ok := env.Get("METRICS_UPLOADER"); ok { + metricsUploader := filepath.Join(topDir, p) + if _, err := os.Stat(metricsUploader); err == nil { + return metricsUploader + } + } + + return "" +} diff --git a/ui/build/config_test.go b/ui/build/config_test.go index 03d304e43..e29327572 100644 --- a/ui/build/config_test.go +++ b/ui/build/config_test.go @@ -1122,3 +1122,65 @@ func TestBuildConfig(t *testing.T) { }) } } + +func TestGetMetricsUploaderApp(t *testing.T) { + + metricsUploaderDir := "metrics_uploader_dir" + metricsUploaderBinary := "metrics_uploader_binary" + metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary) + tests := []struct { + description string + environ Environment + createFiles bool + expected string + }{{ + description: "Uploader binary exist", + environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath}, + createFiles: true, + expected: metricsUploaderPath, + }, { + description: "Uploader binary not exist", + environ: Environment{"METRICS_UPLOADER=" + metricsUploaderPath}, + createFiles: false, + expected: "", + }, { + description: "Uploader binary variable not set", + createFiles: true, + expected: "", + }} + + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + defer logger.Recover(func(err error) { + t.Fatalf("got unexpected error: %v", err) + }) + + // Create the root source tree. + topDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatalf("failed to create temp dir: %v", err) + } + defer os.RemoveAll(topDir) + + expected := tt.expected + if len(expected) > 0 { + expected = filepath.Join(topDir, expected) + } + + if tt.createFiles { + if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil { + t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err) + } + if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil { + t.Errorf("failed to create file %s: %v", expected, err) + } + } + + actual := GetMetricsUploader(topDir, &tt.environ) + + if actual != expected { + t.Errorf("expecting: %s, actual: %s", expected, actual) + } + }) + } +} diff --git a/ui/build/context.go b/ui/build/context.go index f5e987e9d..4a4352cbb 100644 --- a/ui/build/context.go +++ b/ui/build/context.go @@ -71,9 +71,9 @@ func (c ContextImpl) CompleteTrace(name, desc string, begin, end uint64) { realTime := end - begin c.Metrics.SetTimeMetrics( soong_metrics_proto.PerfInfo{ - Desc: &desc, - Name: &name, - StartTime: &begin, - RealTime: &realTime}) + Description: &desc, + Name: &name, + StartTime: &begin, + RealTime: &realTime}) } } diff --git a/ui/build/upload.go b/ui/build/upload.go index 55ada335b..687f51977 100644 --- a/ui/build/upload.go +++ b/ui/build/upload.go @@ -70,12 +70,11 @@ func pruneMetricsFiles(paths []string) []string { return metricsFiles } -// UploadMetrics uploads a set of metrics files to a server for analysis. An -// uploader full path is specified in ANDROID_ENABLE_METRICS_UPLOAD environment -// variable in order to upload the set of metrics files. The metrics files are -// first copied to a temporary directory and the uploader is then executed in -// the background to allow the user/system to continue working. Soong communicates -// to the uploader through the upload_proto raw protobuf file. +// UploadMetrics uploads a set of metrics files to a server for analysis. +// The metrics files are first copied to a temporary directory +// and the uploader is then executed in the background to allow the user/system +// to continue working. Soong communicates to the uploader through the +// upload_proto raw protobuf file. func UploadMetrics(ctx Context, config Config, simpleOutput bool, buildStarted time.Time, paths ...string) { ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics") defer ctx.EndTrace() diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go index b740c1120..764a1e127 100644 --- a/ui/build/upload_test.go +++ b/ui/build/upload_test.go @@ -80,13 +80,10 @@ func TestUploadMetrics(t *testing.T) { createFiles bool files []string }{{ - description: "ANDROID_ENABLE_METRICS_UPLOAD not set", - }, { - description: "no metrics files to upload", - uploader: "fake", + description: "no metrics uploader", }, { description: "non-existent metrics files no upload", - uploader: "fake", + uploader: "echo", files: []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"}, }, { description: "trigger upload", @@ -137,9 +134,9 @@ func TestUploadMetrics(t *testing.T) { config := Config{&configImpl{ environ: &Environment{ "OUT_DIR=" + outDir, - "ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader, }, - buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10), + buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10), + metricsUploader: tt.uploader, }} UploadMetrics(ctx, config, false, time.Now(), metricsFiles...) @@ -192,9 +189,10 @@ func TestUploadMetricsErrors(t *testing.T) { config := Config{&configImpl{ environ: &Environment{ - "ANDROID_ENABLE_METRICS_UPLOAD=fake", "OUT_DIR=/bad", - }}} + }, + metricsUploader: "echo", + }} UploadMetrics(ctx, config, true, time.Now(), metricsFile) t.Errorf("got nil, expecting %q as a failure", tt.expectedErr) diff --git a/ui/metrics/event.go b/ui/metrics/event.go index c3367e3ac..ebe664fc6 100644 --- a/ui/metrics/event.go +++ b/ui/metrics/event.go @@ -69,7 +69,7 @@ func newEvent(name, desc string) *event { func (e event) perfInfo() soong_metrics_proto.PerfInfo { realTime := uint64(_now().Sub(e.start).Nanoseconds()) return soong_metrics_proto.PerfInfo{ - Desc: proto.String(e.desc), + Description: proto.String(e.desc), Name: proto.String(e.name), StartTime: proto.Uint64(uint64(e.start.UnixNano())), RealTime: proto.Uint64(realTime), diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go index ccf9bd8c4..f1bb862bd 100644 --- a/ui/metrics/metrics.go +++ b/ui/metrics/metrics.go @@ -25,16 +25,11 @@ package metrics // that captures the metrics and is them added as a perfInfo into the set // of the collected metrics. Finally, when soong_ui has finished the build, // the defer Dump function is invoked to store the collected metrics to the -// raw protobuf file in the $OUT directory. -// -// There is one additional step that occurs after the raw protobuf file is written. -// If the configuration environment variable ANDROID_ENABLE_METRICS_UPLOAD is -// set with the path, the raw protobuf file is uploaded to the destination. See -// ui/build/upload.go for more details. The filename of the raw protobuf file -// and the list of files to be uploaded is defined in cmd/soong_ui/main.go. -// -// See ui/metrics/event.go for the explanation of what an event is and how -// the metrics system is a stack based system. +// raw protobuf file in the $OUT directory and this raw protobuf file will be +// uploaded to the destination. See ui/build/upload.go for more details. The +// filename of the raw protobuf file and the list of files to be uploaded is +// defined in cmd/soong_ui/main.go. See ui/metrics/event.go for the explanation +// of what an event is and how the metrics system is a stack based system. import ( "io/ioutil" diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go index 80f80bc9e..2e530b0f4 100644 --- a/ui/metrics/metrics_proto/metrics.pb.go +++ b/ui/metrics/metrics_proto/metrics.pb.go @@ -660,7 +660,7 @@ type PerfInfo struct { unknownFields protoimpl.UnknownFields // The description for the phase/action/part while the tool running. - Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"` + Description *string `protobuf:"bytes,1,opt,name=description" json:"description,omitempty"` // The name for the running phase/action/part. Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` // The absolute start time. @@ -709,9 +709,9 @@ func (*PerfInfo) Descriptor() ([]byte, []int) { return file_metrics_proto_rawDescGZIP(), []int{3} } -func (x *PerfInfo) GetDesc() string { - if x != nil && x.Desc != nil { - return *x.Desc +func (x *PerfInfo) GetDescription() string { + if x != nil && x.Description != nil { + return *x.Description } return "" } @@ -1268,93 +1268,93 @@ var file_metrics_proto_rawDesc = []byte{ 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, 0xf3, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 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, 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, 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, 0xc3, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, - 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, - 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, - 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 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, 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, 0xc3, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, + 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, + 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 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 ec8f36bec..db0a14ae1 100644 --- a/ui/metrics/metrics_proto/metrics.proto +++ b/ui/metrics/metrics_proto/metrics.proto @@ -139,7 +139,7 @@ message SystemResourceInfo { message PerfInfo { // The description for the phase/action/part while the tool running. - optional string desc = 1; + optional string description = 1; // The name for the running phase/action/part. optional string name = 2; |