diff options
91 files changed, 2266 insertions, 2112 deletions
diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go index 90b09c814..17385c3d1 100644 --- a/aconfig/rust_aconfig_library_test.go +++ b/aconfig/rust_aconfig_library_test.go @@ -50,11 +50,11 @@ func TestRustAconfigLibrary(t *testing.T) { } for _, variant := range variants { - android.AssertStringListContains( + android.AssertStringEquals( t, "dylib variant builds from generated rust code", - variant.Rule("rustc").Implicits.RelativeToTop().Strings(), "out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs", + variant.Rule("rustc").Inputs[0].RelativeToTop().String(), ) } } diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 5c8e5e31c..64cb2fa51 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -75,14 +75,17 @@ var ( "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, "build/soong/cc/symbolfile": Bp2BuildDefaultTrue, + "build/soong/jar": Bp2BuildDefaultTrue, "build/soong/licenses": Bp2BuildDefaultTrue, "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively, + "build/soong/response": Bp2BuildDefaultTrue, "build/soong/scripts": Bp2BuildDefaultTrueRecursively, + "build/soong/third_party/zip": Bp2BuildDefaultTrue, "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively, - "cts/libs/json": Bp2BuildDefaultTrueRecursively, - "cts/tests/tests/gesture": Bp2BuildDefaultTrueRecursively, - "platform_testing/libraries/annotations": Bp2BuildDefaultTrueRecursively, + "cts/flags/cc_tests": Bp2BuildDefaultTrueRecursively, + "cts/libs/json": Bp2BuildDefaultTrueRecursively, + "cts/tests/tests/gesture": Bp2BuildDefaultTrueRecursively, "dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively, @@ -139,6 +142,7 @@ var ( "external/bzip2": Bp2BuildDefaultTrueRecursively, "external/clang/lib": Bp2BuildDefaultTrue, "external/conscrypt": Bp2BuildDefaultTrue, + "external/dexmaker": Bp2BuildDefaultTrueRecursively, "external/e2fsprogs": Bp2BuildDefaultTrueRecursively, "external/eigen": Bp2BuildDefaultTrueRecursively, "external/erofs-utils": Bp2BuildDefaultTrueRecursively, @@ -191,6 +195,7 @@ var ( "external/lzma/C": Bp2BuildDefaultTrueRecursively, "external/mdnsresponder": Bp2BuildDefaultTrueRecursively, "external/minijail": Bp2BuildDefaultTrueRecursively, + "external/mockito": Bp2BuildDefaultTrueRecursively, "external/musl": Bp2BuildDefaultTrueRecursively, "external/objenesis": Bp2BuildDefaultTrueRecursively, "external/openscreen": Bp2BuildDefaultTrueRecursively, @@ -213,6 +218,7 @@ var ( "external/tinyalsa": Bp2BuildDefaultTrueRecursively, "external/tinyalsa_new": Bp2BuildDefaultTrueRecursively, "external/toybox": Bp2BuildDefaultTrueRecursively, + "external/xz-java": Bp2BuildDefaultTrueRecursively, "external/zlib": Bp2BuildDefaultTrueRecursively, "external/zopfli": Bp2BuildDefaultTrueRecursively, "external/zstd": Bp2BuildDefaultTrueRecursively, @@ -230,9 +236,11 @@ var ( "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively, "frameworks/base/apex/jobscheduler/service/jni": Bp2BuildDefaultTrueRecursively, "frameworks/base/core/java": Bp2BuildDefaultTrue, + "frameworks/base/core/res": Bp2BuildDefaultTrueRecursively, "frameworks/base/libs/androidfw": Bp2BuildDefaultTrue, "frameworks/base/libs/services": Bp2BuildDefaultTrue, "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue, + "frameworks/base/mime": Bp2BuildDefaultTrueRecursively, "frameworks/base/proto": Bp2BuildDefaultTrue, "frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue, "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue, @@ -242,6 +250,8 @@ var ( "frameworks/base/tools/codegen": Bp2BuildDefaultTrueRecursively, "frameworks/base/tools/locked_region_code_injection": Bp2BuildDefaultTrueRecursively, "frameworks/base/tools/streaming_proto": Bp2BuildDefaultTrueRecursively, + "frameworks/hardware/interfaces": Bp2BuildDefaultTrue, + "frameworks/hardware/interfaces/displayservice": Bp2BuildDefaultTrueRecursively, "frameworks/hardware/interfaces/stats/aidl": Bp2BuildDefaultTrue, "frameworks/libs/modules-utils/build": Bp2BuildDefaultTrueRecursively, "frameworks/libs/modules-utils/java": Bp2BuildDefaultTrue, @@ -275,6 +285,7 @@ var ( "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue, "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue, "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue, + "hardware/interfaces/contexthub/aidl": Bp2BuildDefaultTrue, "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue, "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue, "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue, @@ -307,6 +318,9 @@ var ( "hardware/interfaces/neuralnetworks/1.2/vts": Bp2BuildDefaultFalseRecursively, "hardware/interfaces/neuralnetworks/1.3/vts": Bp2BuildDefaultFalseRecursively, "hardware/interfaces/neuralnetworks/1.4/vts": Bp2BuildDefaultFalseRecursively, + "hardware/interfaces/tests": Bp2BuildDefaultTrueRecursively, + "hardware/interfaces/tests/extension": Bp2BuildDefaultFalseRecursively, // missing deps + "hardware/interfaces/tests/msgq": Bp2BuildDefaultFalseRecursively, // missing deps "libnativehelper": Bp2BuildDefaultTrueRecursively, @@ -335,7 +349,9 @@ var ( "packages/screensavers/Basic": Bp2BuildDefaultTrue, "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321) - "platform_testing/tests/example": Bp2BuildDefaultTrueRecursively, + "platform_testing/libraries/annotations": Bp2BuildDefaultTrueRecursively, + "platform_testing/libraries/flag-helpers/libflagtest": Bp2BuildDefaultTrueRecursively, + "platform_testing/tests/example": Bp2BuildDefaultTrueRecursively, "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively, "prebuilts/gradle-plugin": Bp2BuildDefaultTrueRecursively, @@ -373,6 +389,7 @@ var ( "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue, "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue, "system/core/libsparse": Bp2BuildDefaultTrueRecursively, + "system/core/libstats/expresslog": Bp2BuildDefaultTrueRecursively, "system/core/libsuspend": Bp2BuildDefaultTrue, "system/core/libsystem": Bp2BuildDefaultTrueRecursively, "system/core/libsysutils": Bp2BuildDefaultTrueRecursively, @@ -398,8 +415,7 @@ var ( "system/libhidl/transport/manager/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/manager/1.1": Bp2BuildDefaultTrue, "system/libhidl/transport/manager/1.2": Bp2BuildDefaultTrue, - "system/libhidl/transport/memory/1.0": Bp2BuildDefaultTrue, - "system/libhidl/transport/memory/token/1.0": Bp2BuildDefaultTrue, + "system/libhidl/transport/memory": Bp2BuildDefaultTrueRecursively, "system/libhidl/transport/safe_union/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/token/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/token/1.0/utils": Bp2BuildDefaultTrue, @@ -409,14 +425,14 @@ var ( "system/libziparchive": Bp2BuildDefaultTrueRecursively, "system/logging": Bp2BuildDefaultTrueRecursively, "system/media": Bp2BuildDefaultTrue, - "system/media/audio": Bp2BuildDefaultTrueRecursively, "system/media/alsa_utils": Bp2BuildDefaultTrueRecursively, + "system/media/audio": Bp2BuildDefaultTrueRecursively, "system/media/audio_utils": Bp2BuildDefaultTrueRecursively, "system/media/camera": Bp2BuildDefaultTrueRecursively, "system/memory/libion": Bp2BuildDefaultTrueRecursively, "system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively, - "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively, "system/security/fsverity": Bp2BuildDefaultTrueRecursively, + "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively, "system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively, "system/timezone/apex": Bp2BuildDefaultTrueRecursively, "system/timezone/output_data": Bp2BuildDefaultTrueRecursively, @@ -424,13 +440,14 @@ var ( "system/timezone/testing": Bp2BuildDefaultTrueRecursively, "system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue, "system/tools/aidl/metadata": Bp2BuildDefaultTrue, - "system/tools/hidl/metadata": Bp2BuildDefaultTrue, - "system/tools/hidl/utils": Bp2BuildDefaultTrue, + "system/tools/hidl": Bp2BuildDefaultTrueRecursively, "system/tools/mkbootimg": Bp2BuildDefaultTrueRecursively, "system/tools/sysprop": Bp2BuildDefaultTrue, "system/tools/xsdc/utils": Bp2BuildDefaultTrueRecursively, "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively, + "test/vts/vts_hal_hidl_target": Bp2BuildDefaultTrueRecursively, + "tools/apifinder": Bp2BuildDefaultTrue, "tools/apksig": Bp2BuildDefaultTrue, "tools/dexter/slicer": Bp2BuildDefaultTrueRecursively, @@ -438,6 +455,7 @@ var ( "tools/metalava": Bp2BuildDefaultTrueRecursively, "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively, "tools/platform-compat/java/androidprocessor": Bp2BuildDefaultTrueRecursively, + "tools/tradefederation/core/util_apps": Bp2BuildDefaultTrueRecursively, "tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively, } @@ -463,6 +481,7 @@ var ( "external/bazelbuild-rules_go":/* recursive = */ true, "external/bazelbuild-rules_python":/* recursive = */ true, "external/bazelbuild-rules_rust":/* recursive = */ true, + "external/bazelbuild-rules_testing":/* recursive = */ true, "external/bazelbuild-kotlin-rules":/* recursive = */ true, "external/bazel-skylib":/* recursive = */ true, "external/protobuf":/* recursive = */ false, @@ -556,13 +575,8 @@ var ( // ext "tagsoup", - // framework-res - "remote-color-resources-compile-public", - "remote-color-resources-compile-colors", - // framework-minus-apex "ImmutabilityAnnotationProcessor", - "android.mime.types.minimized", "debian.mime.types.minimized", "framework-javastream-protos", "libview-inspector-annotation-processor", @@ -571,7 +585,6 @@ var ( "apache-commons-math", "cbor-java", "icu4j_calendar_astronomer", - "remote-color-resources-compile-public", "statslog-art-java-gen", "AndroidCommonLint", @@ -755,6 +768,7 @@ var ( //system/core/fs_mgr "libfs_mgr", + "libcodec2_aidl", "libcodec2_hidl@1.0", "libcodec2_hidl@1.1", "libcodec2_hidl@1.2", @@ -894,7 +908,6 @@ var ( "libRSDispatch", // hal_unit_tests and deps - "android.hardware.contexthub_interface", // created implicitly by android.hardware.contexthub "chre_flatbuffers", "event_logger", "hal_unit_tests", @@ -922,9 +935,7 @@ var ( "androidx.test.annotation-nodeps", // jni deps of an internal android_test (b/297405812) - "libdexmakerjvmtiagent", "libopenjdkjvmti_headers", - "libstaticjvmtiagent", // tradefed deps "tradefed-protos", @@ -947,6 +958,34 @@ var ( "gson", "GsonBuildConfig.java", "gson_version_generator", + "lab-resource-grpc", + "blueprint-deptools", + "protoc-gen-grpc-java-plugin", + "perfetto_trace-full", + "tf-remote-client", + "truth", + "tradefed-lite", + "tradefed-isolation-protos", + "snakeyaml_patched_src_files", + "asuite_proto_java", + "tradefed-service-grpc-lib", + "tradefed-invocation-grpc", + "tradefed-external-dependencies", + "tradefed-dynamic-sharding-grpc", + "tradefed-device-manager-grpc", + "statsd_internal_protos", + "snakeyaml", + "loganalysis", + "junit-params", + "grpc-java-testing", + "grpc-java-netty-shaded", + "aoa-helper", + "test-services.apk", + "test-composers", + "py3-stdlib-prebuilt-srcs", + "platformprotos", + "perfetto_metrics-full", + "test-services-normalized.apk", } Bp2buildModuleTypeAlwaysConvertList = []string{ @@ -969,8 +1008,8 @@ var ( "java_sdk_library_import", "license", "linker_config", - "ndk_library", "ndk_headers", + "ndk_library", "sysprop_library", "xsd_config", // go/keep-sorted end @@ -1060,20 +1099,22 @@ var ( "libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported // unconverted deps - "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib - "adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi - "android_icu4j_srcgen", // depends on unconverted modules: currysrc - "android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc - "apex_compression_test", // depends on unconverted modules: soong_zip, com.android.example.apex - "apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full - "apexer_with_DCLA_preprocessing_test", // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex - "art-script", // depends on unconverted modules: dalvikvm, dex2oat - "bin2c_fastdeployagent", // depends on unconverted modules: deployagent - "com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig - "currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9 - "dex2oat-script", // depends on unconverted modules: dex2oat - "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary - "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary + "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib + "adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi + "android_icu4j_srcgen", // depends on unconverted modules: currysrc + "android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc + "apex_compression_test", // depends on unconverted modules: soong_zip, com.android.example.apex + "apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full + "apexer_with_DCLA_preprocessing_test", // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex + "art-script", // depends on unconverted modules: dalvikvm, dex2oat + "bin2c_fastdeployagent", // depends on unconverted modules: deployagent + "com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig + "currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9 + "dex2oat-script", // depends on unconverted modules: dex2oat + "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary + "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary + "hidl_system_api_test", + "hidl_test_java", "host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano "jacoco-stubs", // b/245767077, depends on droidstubs "libapexutil", // depends on unconverted modules: apex-info-list-tinyxml @@ -1656,6 +1697,7 @@ var ( // python_test_host with test data "sbom_writers_test", + "hidl_test", // TODO(B/283193845): tradefed and its java_test_host dependents "tradefed", @@ -1713,6 +1755,13 @@ var ( "NanoAndroidTest", "MtsLibnativehelperTestCases", + // Depends on androidx.test.rules + "DexmakerTests", + "dexmaker-tests-lib", + "dexmaker-mockmaker-tests", + "dexmaker-inline-mockmaker-tests", + "dexmaker-extended-mockmaker-tests", + // android_test_helper_app from allowlisted packages, but with unconverted deps "SharedLibraryInfoTestApp", } @@ -1777,18 +1826,4 @@ var ( "art_": DEFAULT_PRIORITIZED_WEIGHT, "ndk_library": DEFAULT_PRIORITIZED_WEIGHT, } - - BazelSandwichTargets = []struct { - Label string - Host bool - }{ - { - Label: "//build/bazel/examples/partitions:system_image", - Host: false, - }, - { - Label: "//build/bazel/examples/partitions:run_test", - Host: false, - }, - } ) diff --git a/android/api_domain.go b/android/api_domain.go index 587ceaefa..0603c7016 100644 --- a/android/api_domain.go +++ b/android/api_domain.go @@ -107,24 +107,3 @@ func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []stri bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix) return bazel.MakeLabelListAttribute(bazelLabels) } - -type bazelApiDomainAttributes struct { - Cc_api_contributions bazel.LabelListAttribute - Java_api_contributions bazel.LabelListAttribute -} - -var _ ApiProvider = (*apiDomain)(nil) - -func (a *apiDomain) ConvertWithApiBp2build(ctx TopDownMutatorContext) { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "api_domain", - Bzl_load_location: "//build/bazel/rules/apis:api_domain.bzl", - } - attrs := &bazelApiDomainAttributes{ - Cc_api_contributions: contributionBazelAttributes(ctx, a.properties.Cc_api_contributions), - Java_api_contributions: contributionBazelAttributes(ctx, a.properties.Java_api_contributions), - } - ctx.CreateBazelTargetModule(props, CommonAttributes{ - Name: ctx.ModuleName(), - }, attrs) -} diff --git a/android/bazel.go b/android/bazel.go index 8634daba1..5df12f02e 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -218,6 +218,28 @@ func InitBazelModule(module BazelModule) { module.bazelProps().Bazel_module.CanConvertToBazel = true } +// BazelHandcraftedHook is a load hook to possibly register the current module as +// a "handcrafted" Bazel target of a given name. If the current module should be +// registered in this way, the hook function should return the target name. If +// it should not be registered in this way, this function should return the empty string. +type BazelHandcraftedHook func(ctx LoadHookContext) string + +// AddBazelHandcraftedHook adds a load hook to (maybe) mark the given module so that +// it is treated by bp2build as if it has a handcrafted Bazel target. +func AddBazelHandcraftedHook(module BazelModule, hook BazelHandcraftedHook) { + AddLoadHook(module, func(ctx LoadHookContext) { + var targetName string = hook(ctx) + if len(targetName) > 0 { + moduleDir := ctx.ModuleDir() + if moduleDir == Bp2BuildTopLevel { + moduleDir = "" + } + label := fmt.Sprintf("//%s:%s", moduleDir, targetName) + module.bazelProps().Bazel_module.Label = &label + } + }) +} + // bazelProps returns the Bazel properties for the given BazelModuleBase. func (b *BazelModuleBase) bazelProps() *properties { return &b.bazelProperties @@ -600,17 +622,10 @@ func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2Bui } func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) { - ctx.TopDown("bp2build_conversion", bp2buildConversionMutator).Parallel() + ctx.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel() } -func bp2buildConversionMutator(ctx TopDownMutatorContext) { - if ctx.Config().HasBazelBuildTargetInSource(ctx) { - // Defer to the BUILD target. Generating an additional target would - // cause a BUILD file conflict. - ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "") - return - } - +func bp2buildConversionMutator(ctx BottomUpMutatorContext) { bModule, ok := ctx.Module().(Bazelable) if !ok { ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") @@ -634,21 +649,23 @@ func bp2buildConversionMutator(ctx TopDownMutatorContext) { ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "") return } + if ctx.Module().base().GetUnconvertedReason() != nil { + return + } + bModule.ConvertWithBp2build(ctx) - if !ctx.Module().base().IsConvertedByBp2build() && ctx.Module().base().GetUnconvertedReason() == nil { + if len(ctx.Module().base().Bp2buildTargets()) == 0 && ctx.Module().base().GetUnconvertedReason() == nil { panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName())) } -} - -func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) { - ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel() -} -// Generate API contribution targets if the Soong module provides APIs -func convertWithApiBp2build(ctx TopDownMutatorContext) { - if m, ok := ctx.Module().(ApiProvider); ok { - m.ConvertWithApiBp2build(ctx) + for _, targetInfo := range ctx.Module().base().Bp2buildTargets() { + if ctx.Config().HasBazelBuildTargetInSource(targetInfo.TargetPackage(), targetInfo.TargetName()) { + // Defer to the BUILD target. Generating an additional target would + // cause a BUILD file conflict. + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, targetInfo.TargetName()) + return + } } } diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 56ec17d02..51ce3c9e9 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -33,10 +33,10 @@ import ( "android/soong/shared" "android/soong/starlark_import" + "android/soong/bazel" + "github.com/google/blueprint" "github.com/google/blueprint/metrics" - - "android/soong/bazel" ) var ( @@ -1048,39 +1048,46 @@ var ( allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd} ) +// This can't be part of bp2build_product_config.go because it would create a circular go package dependency +func getLabelsForBazelSandwichPartitions(variables *ProductVariables) []string { + targetProduct := "unknown" + if variables.DeviceProduct != nil { + targetProduct = *variables.DeviceProduct + } + currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct) + if len(variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory) > 0 { + currentProductFolder = fmt.Sprintf("%s%s", variables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory, targetProduct) + } + var ret []string + if variables.PartitionVarsForBazelMigrationOnlyDoNotUse.PartitionQualifiedVariables["system"].BuildingImage { + ret = append(ret, "@//"+currentProductFolder+":system_image") + ret = append(ret, "@//"+currentProductFolder+":run_system_image_test") + } + return ret +} + func GetBazelSandwichCqueryRequests(config Config) ([]cqueryKey, error) { - result := make([]cqueryKey, 0, len(allowlists.BazelSandwichTargets)) + partitionLabels := getLabelsForBazelSandwichPartitions(&config.productVariables) + result := make([]cqueryKey, 0, len(partitionLabels)) labelRegex := regexp.MustCompile("^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$") // Note that bazel "targets" are different from soong "targets", the bazel targets are // synonymous with soong modules, and soong targets are a configuration a module is built in. - for _, target := range allowlists.BazelSandwichTargets { - match := labelRegex.FindStringSubmatch(target.Label) + for _, target := range partitionLabels { + match := labelRegex.FindStringSubmatch(target) if match == nil { - return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target.Label) - } - if _, err := os.Stat(absolutePath(match[1])); err != nil { - if os.IsNotExist(err) { - // Ignore bazel sandwich targets that don't exist. - continue - } else { - return nil, err - } + return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target) } - var soongTarget Target - if target.Host { - soongTarget = config.BuildOSTarget - } else { - soongTarget = config.AndroidCommonTarget - if soongTarget.Os.Class != Device { - // kernel-build-tools seems to set the AndroidCommonTarget to a linux host - // target for some reason, disable device builds in that case. - continue - } + // change this to config.BuildOSTarget if we add host targets + soongTarget := config.AndroidCommonTarget + if soongTarget.Os.Class != Device { + // kernel-build-tools seems to set the AndroidCommonTarget to a linux host + // target for some reason, disable device builds in that case. + continue } result = append(result, cqueryKey{ - label: target.Label, + label: target, requestType: cquery.GetOutputFiles, configKey: configKey{ arch: soongTarget.Arch.String(), diff --git a/android/bazel_paths.go b/android/bazel_paths.go index 4ac58403c..d8effaa12 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -442,6 +442,9 @@ func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string, otherLabel := labelFromModule(ctx, m) // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets. + if tag != "" && m.Name() == "framework-res" { + otherLabel += tag + } if samePackage(label, otherLabel) { otherLabel = bazelShortLabel(otherLabel) diff --git a/android/config.go b/android/config.go index d7d48c33f..f0fc15b45 100644 --- a/android/config.go +++ b/android/config.go @@ -2023,10 +2023,9 @@ func (c *config) LogMixedBuild(ctx BaseModuleContext, useBazel bool) { } } -func (c *config) HasBazelBuildTargetInSource(ctx BaseModuleContext) bool { - moduleName := ctx.Module().Name() - for _, buildTarget := range c.bazelTargetsByDir[ctx.ModuleDir()] { - if moduleName == buildTarget { +func (c *config) HasBazelBuildTargetInSource(dir string, target string) bool { + for _, existingTarget := range c.bazelTargetsByDir[dir] { + if target == existingTarget { return true } } @@ -2082,3 +2081,7 @@ func (c *config) Bp2buildMode() bool { func (c *deviceConfig) CheckVendorSeappViolations() bool { return Bool(c.config.productVariables.CheckVendorSeappViolations) } + +func (c *deviceConfig) NextReleaseHideFlaggedApi() bool { + return Bool(c.config.productVariables.NextReleaseHideFlaggedApi) +} diff --git a/android/depset_generic.go b/android/depset_generic.go index 9f07596b5..45c193715 100644 --- a/android/depset_generic.go +++ b/android/depset_generic.go @@ -95,12 +95,6 @@ func NewDepSet[T depSettableType](order DepSetOrder, direct []T, transitive []*D } } -// AddDirectToDepSet returns a new DepSet with additional elements added to its direct set. -// The transitive sets remain untouched. -func AddDirectToDepSet[T depSettableType](d *DepSet[T], direct ...T) *DepSet[T] { - return NewDepSet[T](d.order, Concat(d.direct, direct), d.transitive) -} - // DepSetBuilder is used to create an immutable DepSet. type DepSetBuilder[T depSettableType] struct { order DepSetOrder @@ -194,14 +188,3 @@ func (d *DepSet[T]) ToList() []T { } return list } - -// ToListDirect returns the direct elements of a DepSet flattened to a list. -func (d *DepSet[T]) ToListDirect() []T { - if d == nil { - return nil - } - list := make([]T, len(d.direct)) - copy(list, d.direct) - list = firstUniqueInPlace(list) - return list -} diff --git a/android/filegroup.go b/android/filegroup.go index a4bbcae99..5a8c4b9bc 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -86,12 +86,6 @@ type bazelAidlLibraryAttributes struct { Strip_import_prefix *string } -// api srcs can be contained in filegroups. -// this should be generated in api_bp2build workspace as well. -func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) { - fg.ConvertWithBp2build(ctx) -} - // ConvertWithBp2build performs bp2build conversion of filegroup func (fg *fileGroup) ConvertWithBp2build(ctx Bp2buildMutatorContext) { srcs := bazel.MakeLabelListAttribute( diff --git a/android/module.go b/android/module.go index f48af4a03..74b8cb8ff 100644 --- a/android/module.go +++ b/android/module.go @@ -565,8 +565,8 @@ type Module interface { AddProperties(props ...interface{}) GetProperties() []interface{} - // IsConvertedByBp2build returns whether this module was converted via bp2build - IsConvertedByBp2build() bool + // If this module should not have bazel BUILD definitions generated by bp2build, + // GetUnconvertedReason returns a reason this is the case. GetUnconvertedReason() *UnconvertedReason // Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module @@ -1272,7 +1272,7 @@ func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupport m.base().commonProperties.CreateCommonOSVariant = true } -func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext, +func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *bottomUpMutatorContext, enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes { mod := ctx.Module().base() @@ -1430,7 +1430,7 @@ var ( // If compile_mulitilib is set to // 1. 32: Add an incompatibility constraint for non-32 arches // 1. 64: Add an incompatibility constraint for non-64 arches -func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, enabled *bazel.LabelListAttribute) { +func addCompatibilityConstraintForCompileMultilib(ctx *bottomUpMutatorContext, enabled *bazel.LabelListAttribute) { mod := ctx.Module().base() multilib, _ := decodeMultilib(mod, mod.commonProperties.CompileOS, ctx.Config().IgnorePrefer32OnDevice()) @@ -1456,7 +1456,7 @@ func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, en // Check product variables for `enabled: true` flag override. // Returns a list of the constraint_value targets who enable this override. -func productVariableConfigEnableAttribute(ctx *topDownMutatorContext) bazel.LabelListAttribute { +func productVariableConfigEnableAttribute(ctx *bottomUpMutatorContext) bazel.LabelListAttribute { result := bazel.LabelListAttribute{} productVariableProps, errs := ProductVariableProperties(ctx, ctx.Module()) for _, err := range errs { @@ -1639,35 +1639,16 @@ func (b bp2buildInfo) BazelAttributes() []interface{} { } func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) { - reason := m.commonProperties.BazelConversionStatus.UnconvertedReason - if reason != nil { - panic(fmt.Errorf("bp2build: internal error trying to convert module '%s' marked unconvertible. Reason type %d: %s", - m.Name(), - reason.ReasonType, - reason.Detail)) - } m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info) } func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) { - if len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0 { - fmt.Println(m.commonProperties.BazelConversionStatus.Bp2buildInfo) - panic(fmt.Errorf("bp2build: internal error trying to mark converted module '%s' as unconvertible. Reason type %d: %s", - m.Name(), - reasonType, - detail)) - } m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{ ReasonType: int(reasonType), Detail: detail, } } -// IsConvertedByBp2build returns whether this module was converted via bp2build. -func (m *ModuleBase) IsConvertedByBp2build() bool { - return len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0 -} - func (m *ModuleBase) GetUnconvertedReason() *UnconvertedReason { return m.commonProperties.BazelConversionStatus.UnconvertedReason } diff --git a/android/mutator.go b/android/mutator.go index 336f8f73c..57ff1e092 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -38,13 +38,6 @@ func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []Register registerMutatorsForBazelConversion(ctx, bp2buildMutators) } -// RegisterMutatorsForApiBazelConversion is an alternate registration pipeline for api_bp2build -// This pipeline restricts generation of Bazel targets to Soong modules that contribute APIs -func RegisterMutatorsForApiBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) { - bp2buildMutators := append(preArchMutators, registerApiBp2buildConversionMutator) - registerMutatorsForBazelConversion(ctx, bp2buildMutators) -} - func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) { mctx := ®isterMutatorsContext{ bazelConversionMode: true, @@ -284,7 +277,6 @@ type TopDownMutator func(TopDownMutatorContext) type TopDownMutatorContext interface { BaseMutatorContext - Bp2buildMutatorContext // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies // the specified property structs to it as if the properties were set in a blueprint file. @@ -300,6 +292,7 @@ type BottomUpMutator func(BottomUpMutatorContext) type BottomUpMutatorContext interface { BaseMutatorContext + Bp2buildMutatorContext // AddDependency adds a dependency to the given module. It returns a slice of modules for each // dependency (some entries may be nil). @@ -711,14 +704,14 @@ func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) { ctx.BottomUp("deps", depsMutator).Parallel() } -func (t *topDownMutatorContext) CreateBazelTargetModule( +func (t *bottomUpMutatorContext) CreateBazelTargetModule( bazelProps bazel.BazelTargetModuleProperties, commonAttrs CommonAttributes, attrs interface{}) { t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{}) } -func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions( +func (t *bottomUpMutatorContext) CreateBazelTargetModuleWithRestrictions( bazelProps bazel.BazelTargetModuleProperties, commonAttrs CommonAttributes, attrs interface{}, @@ -726,7 +719,7 @@ func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions( t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty) } -func (t *topDownMutatorContext) MarkBp2buildUnconvertible( +func (t *bottomUpMutatorContext) MarkBp2buildUnconvertible( reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) { mod := t.Module() mod.base().setBp2buildUnconvertible(reasonType, detail) @@ -742,7 +735,7 @@ type bazelAliasAttributes struct { Actual *bazel.LabelAttribute } -func (t *topDownMutatorContext) CreateBazelTargetAliasInDir( +func (t *bottomUpMutatorContext) CreateBazelTargetAliasInDir( dir string, name string, actual bazel.Label) { @@ -763,7 +756,7 @@ func (t *topDownMutatorContext) CreateBazelTargetAliasInDir( // Returns the directory in which the bazel target will be generated // If ca.Dir is not nil, use that // Otherwise default to the directory of the soong module -func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) string { +func dirForBazelTargetGeneration(t *bottomUpMutatorContext, ca *CommonAttributes) string { dir := t.OtherModuleDir(t.Module()) if ca.Dir != nil { dir = *ca.Dir @@ -781,7 +774,7 @@ func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) return dir } -func (t *topDownMutatorContext) CreateBazelConfigSetting( +func (t *bottomUpMutatorContext) CreateBazelConfigSetting( csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string) { @@ -867,7 +860,7 @@ func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvai return ConvertApexAvailableToTags(noTestApexes) } -func (t *topDownMutatorContext) createBazelTargetModule( +func (t *bottomUpMutatorContext) createBazelTargetModule( bazelProps bazel.BazelTargetModuleProperties, commonAttrs CommonAttributes, attrs interface{}, diff --git a/android/paths.go b/android/paths.go index d4b1d6e29..325a953c4 100644 --- a/android/paths.go +++ b/android/paths.go @@ -171,9 +171,6 @@ type Path interface { // Base returns the last element of the path Base() string - // Dir returns a path pointing the directory containing the path - Dir() Path - // Rel returns the portion of the path relative to the directory it was created from. For // example, Rel on a PathsForModuleSrc would return the path relative to the module source // directory, and OutputPath.Join("foo").Rel() would return "foo". @@ -1015,12 +1012,6 @@ func (p basePath) Base() string { return filepath.Base(p.path) } -func (p basePath) Dir() Path { - p.path = filepath.Dir(p.path) - p.rel = filepath.Dir(p.rel) - return p -} - func (p basePath) Rel() string { if p.rel != "" { return p.rel @@ -1055,11 +1046,6 @@ func (p SourcePath) withRel(rel string) SourcePath { return p } -func (p SourcePath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - return p -} - // safePathForSource is for paths that we expect are safe -- only for use by go // code that is embedding ninja variables in paths func safePathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) { @@ -1262,12 +1248,6 @@ func (p OutputPath) withRel(rel string) OutputPath { return p } -func (p OutputPath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - p.fullPath = filepath.Dir(p.fullPath) - return p -} - func (p OutputPath) WithoutRel() OutputPath { p.basePath.rel = filepath.Base(p.basePath.path) return p @@ -1300,11 +1280,6 @@ type toolDepPath struct { basePath } -func (p toolDepPath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - return p -} - func (t toolDepPath) RelativeToTop() Path { ensureTestOnly() return t @@ -1488,11 +1463,6 @@ type ModuleOutPath struct { OutputPath } -func (p ModuleOutPath) Dir() Path { - p.OutputPath = p.OutputPath.Dir().(OutputPath) - return p -} - func (p ModuleOutPath) RelativeToTop() Path { p.OutputPath = p.outputPathRelativeToTop() return p @@ -1537,11 +1507,6 @@ type ModuleGenPath struct { ModuleOutPath } -func (p ModuleGenPath) Dir() Path { - p.ModuleOutPath = p.ModuleOutPath.Dir().(ModuleOutPath) - return p -} - func (p ModuleGenPath) RelativeToTop() Path { p.OutputPath = p.outputPathRelativeToTop() return p @@ -1581,11 +1546,6 @@ type ModuleObjPath struct { ModuleOutPath } -func (p ModuleObjPath) Dir() Path { - p.ModuleOutPath = p.ModuleOutPath.Dir().(ModuleOutPath) - return p -} - func (p ModuleObjPath) RelativeToTop() Path { p.OutputPath = p.outputPathRelativeToTop() return p @@ -1610,11 +1570,6 @@ type ModuleResPath struct { ModuleOutPath } -func (p ModuleResPath) Dir() Path { - p.ModuleOutPath = p.ModuleOutPath.Dir().(ModuleOutPath) - return p -} - func (p ModuleResPath) RelativeToTop() Path { p.OutputPath = p.outputPathRelativeToTop() return p @@ -1651,11 +1606,6 @@ type InstallPath struct { makePath bool } -func (p InstallPath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - return p -} - // Will panic if called from outside a test environment. func ensureTestOnly() { if PrefixInList(os.Args, "-test.") { @@ -1972,11 +1922,6 @@ type PhonyPath struct { basePath } -func (p PhonyPath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - return p -} - func (p PhonyPath) writablePath() {} func (p PhonyPath) getSoongOutDir() string { @@ -2002,11 +1947,6 @@ type testPath struct { basePath } -func (p testPath) Dir() Path { - p.basePath = p.basePath.Dir().(basePath) - return p -} - func (p testPath) RelativeToTop() Path { ensureTestOnly() return p diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go index c00b22ba4..17b323067 100644 --- a/android/prebuilt_build_tool.go +++ b/android/prebuilt_build_tool.go @@ -14,11 +14,7 @@ package android -import ( - "path/filepath" - - "github.com/google/blueprint" -) +import "path/filepath" func init() { RegisterModuleType("prebuilt_build_tool", NewPrebuiltBuildTool) @@ -59,13 +55,6 @@ func (t *prebuiltBuildTool) DepsMutator(ctx BottomUpMutatorContext) { } } -type PrebuiltBuildToolInfo struct { - Src Path - Deps Paths -} - -var PrebuiltBuildToolInfoProvider = blueprint.NewProvider(PrebuiltBuildToolInfo{}) - func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) { sourcePath := t.prebuilt.SingleSourcePath(ctx) installedPath := PathForModuleOut(ctx, t.BaseModuleName()) @@ -93,11 +82,6 @@ func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) { } t.toolPath = OptionalPathForPath(installedPath) - - ctx.SetProvider(PrebuiltBuildToolInfoProvider, PrebuiltBuildToolInfo{ - Src: sourcePath, - Deps: deps, - }) } func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) { diff --git a/android/proto.go b/android/proto.go index fc21d0177..c449a87ea 100644 --- a/android/proto.go +++ b/android/proto.go @@ -289,7 +289,7 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz attrs.Strip_import_prefix = proptools.StringPtr("") } - tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module()) + tags := ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module()) moduleDir := ctx.ModuleDir() if !canonicalPathFromRoot { diff --git a/android/util.go b/android/util.go index 7f6af2d68..5375373a6 100644 --- a/android/util.go +++ b/android/util.go @@ -33,17 +33,12 @@ func CopyOf[T any](s []T) []T { return append([]T{}, s...) } -// Concat returns a new slice concatenated from the input slices. It does not change the input +// Concat returns a new slice concatenated from the two input slices. It does not change the input // slices. -func Concat[T any](slices ...[]T) []T { - newLength := 0 - for _, s := range slices { - newLength += len(s) - } - res := make([]T, 0, newLength) - for _, s := range slices { - res = append(res, s...) - } +func Concat[T any](s1, s2 []T) []T { + res := make([]T, 0, len(s1)+len(s2)) + res = append(res, s1...) + res = append(res, s2...) return res } diff --git a/android/variable.go b/android/variable.go index d33294c16..73a4b2c61 100644 --- a/android/variable.go +++ b/android/variable.go @@ -485,11 +485,65 @@ type ProductVariables struct { CheckVendorSeappViolations *bool `json:",omitempty"` - // PartitionsVars are extra variables that are used to define the partition images. They should - // not be read from soong modules. - PartitionVars struct { - ProductDirectory string `json:",omitempty"` - } `json:",omitempty"` + // PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the + // partition images. They should not be read from soong modules. + PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"` + + NextReleaseHideFlaggedApi *bool `json:",omitempty"` +} + +type PartitionVariables struct { + ProductDirectory string `json:",omitempty"` + PartitionQualifiedVariables map[string]struct { + BuildingImage bool `json:",omitempty"` + BoardErofsCompressor string `json:",omitempty"` + BoardErofsCompressHints string `json:",omitempty"` + BoardErofsPclusterSize string `json:",omitempty"` + BoardExtfsInodeCount string `json:",omitempty"` + BoardExtfsRsvPct string `json:",omitempty"` + BoardF2fsSloadCompressFlags string `json:",omitempty"` + BoardFileSystemCompress string `json:",omitempty"` + BoardFileSystemType string `json:",omitempty"` + BoardJournalSize string `json:",omitempty"` + BoardPartitionReservedSize string `json:",omitempty"` + BoardPartitionSize string `json:",omitempty"` + BoardSquashfsBlockSize string `json:",omitempty"` + BoardSquashfsCompressor string `json:",omitempty"` + BoardSquashfsCompressorOpt string `json:",omitempty"` + BoardSquashfsDisable4kAlign string `json:",omitempty"` + ProductBaseFsPath string `json:",omitempty"` + ProductHeadroom string `json:",omitempty"` + ProductVerityPartition string `json:",omitempty"` + + BoardAvbAddHashtreeFooterArgs string `json:",omitempty"` + BoardAvbKeyPath string `json:",omitempty"` + BoardAvbAlgorithm string `json:",omitempty"` + BoardAvbRollbackIndex string `json:",omitempty"` + BoardAvbRollbackIndexLocation string `json:",omitempty"` + } + TargetUserimagesUseExt2 bool `json:",omitempty"` + TargetUserimagesUseExt3 bool `json:",omitempty"` + TargetUserimagesUseExt4 bool `json:",omitempty"` + + TargetUserimagesSparseExtDisabled bool `json:",omitempty"` + TargetUserimagesSparseErofsDisabled bool `json:",omitempty"` + TargetUserimagesSparseSquashfsDisabled bool `json:",omitempty"` + TargetUserimagesSparseF2fsDisabled bool `json:",omitempty"` + + BoardErofsCompressor string `json:",omitempty"` + BoardErofsCompressorHints string `json:",omitempty"` + BoardErofsPclusterSize string `json:",omitempty"` + BoardErofsShareDupBlocks string `json:",omitempty"` + BoardErofsUseLegacyCompression string `json:",omitempty"` + BoardExt4ShareDupBlocks string `json:",omitempty"` + BoardFlashLogicalBlockSize string `json:",omitempty"` + BoardFlashEraseBlockSize string `json:",omitempty"` + BoardUsesRecoveryAsBoot bool `json:",omitempty"` + BoardBuildGkiBootImageWithoutRamdisk bool `json:",omitempty"` + ProductUseDynamicPartitionSize bool `json:",omitempty"` + CopyImagesForTargetFilesZip bool `json:",omitempty"` + + BoardAvbEnable bool `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/apex/apex_test.go b/apex/apex_test.go index 3a6af1e44..9475f5da3 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -948,7 +948,7 @@ func TestApexWithStubs(t *testing.T) { // Ensure that stub dependency from a rust module is not included ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so") // The rust module is linked to the stub cc library - rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").RuleParams.Command + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"] ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so") ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so") @@ -1024,7 +1024,7 @@ func TestApexCanUsePrivateApis(t *testing.T) { mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"] ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so") ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so") - rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").RuleParams.Command + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"] ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so") ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so") } diff --git a/bazel/aquery.go b/bazel/aquery.go index c35571239..7195a97a6 100644 --- a/bazel/aquery.go +++ b/bazel/aquery.go @@ -18,14 +18,16 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" + "errors" "fmt" "path/filepath" - analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2" "reflect" "sort" "strings" "sync" + analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2" + "github.com/google/blueprint/metrics" "github.com/google/blueprint/proptools" "google.golang.org/protobuf/proto" @@ -374,9 +376,14 @@ func AqueryBuildStatements(aqueryJsonProto []byte, eventHandler *metrics.EventHa for i, actionEntry := range aqueryProto.Actions { wg.Add(1) go func(i int, actionEntry *analysis_v2_proto.Action) { - buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry) - if aErr != nil { + if buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry); aErr != nil { errOnce.Do(func() { + for _, t := range aqueryProto.Targets { + if t.GetId() == actionEntry.GetTargetId() { + aErr = fmt.Errorf("%s: [%s] [%s]", aErr.Error(), actionEntry.GetMnemonic(), t.GetLabel()) + break + } + } err = aErr }) } else { @@ -782,7 +789,7 @@ func (a *aqueryArtifactHandler) actionToBuildStatement(actionEntry *analysis_v2_ } if len(actionEntry.Arguments) < 1 { - return nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic) + return nil, errors.New("received action with no command") } return a.normalActionBuildStatement(actionEntry) diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go index 59aacbb15..57c38db97 100644 --- a/bp2build/aar_conversion_test.go +++ b/bp2build/aar_conversion_test.go @@ -21,6 +21,17 @@ import ( "android/soong/java" ) +func runAndroidLibraryImportTestWithRegistrationCtxFunc(t *testing.T, registrationCtxFunc func(ctx android.RegistrationContext), tc Bp2buildTestCase) { + t.Helper() + (&tc).ModuleTypeUnderTest = "android_library_import" + (&tc).ModuleTypeUnderTestFactory = java.AARImportFactory + RunBp2BuildTestCase(t, registrationCtxFunc, tc) +} + +func runAndroidLibraryImportTest(t *testing.T, tc Bp2buildTestCase) { + runAndroidLibraryImportTestWithRegistrationCtxFunc(t, func(ctx android.RegistrationContext) {}, tc) +} + func TestConvertAndroidLibrary(t *testing.T) { t.Helper() RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{ @@ -75,7 +86,7 @@ android_library { func TestConvertAndroidLibraryWithNoSources(t *testing.T) { t.Helper() RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{ - Description: "Android Library - modules with deps must have sources", + Description: "Android Library - modules will deps when there are no sources", ModuleTypeUnderTest: "android_library", ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, Filesystem: map[string]string{ @@ -91,26 +102,29 @@ android_library { sdk_version: "current", } `, - ExpectedBazelTargets: []string{}, + ExpectedBazelTargets: []string{ + MakeBazelTarget( + "android_library", + "TestLib", + AttrNameToString{ + "manifest": `"AndroidManifest.xml"`, + "resource_files": `["res/res.png"]`, + "sdk_version": `"current"`, // use as default + }, + ), + MakeNeverlinkDuplicateTarget("android_library", "TestLib"), + }, }) } func TestConvertAndroidLibraryImport(t *testing.T) { - t.Helper() - RunBp2BuildTestCase( - t, + runAndroidLibraryImportTestWithRegistrationCtxFunc(t, func(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_library", java.AndroidLibraryFactory) }, Bp2buildTestCase{ - Description: "Android Library Import", - ModuleTypeUnderTest: "android_library_import", - ModuleTypeUnderTestFactory: java.AARImportFactory, - Filesystem: map[string]string{ - "import.aar": "", - "dep.aar": "", - }, - StubbedBuildDefinitions: []string{"static_lib_dep", "prebuilt_static_import_dep"}, + Description: "Android Library Import", + StubbedBuildDefinitions: []string{"static_lib_dep", "static_import_dep", "static_import_dep-neverlink"}, // Bazel's aar_import can only export *_import targets, so we expect // only "static_import_dep" in exports, but both "static_lib_dep" and // "static_import_dep" in deps @@ -122,9 +136,9 @@ android_library_import { sdk_version: "current", } -// TODO: b/301007952 - This dep is needed because android_library_import must have aars set. android_library_import { name: "static_import_dep", + aars: ["import.aar"], } `, ExpectedBazelTargets: []string{ @@ -219,3 +233,16 @@ android_library { MakeNeverlinkDuplicateTarget("android_library", "TestLib"), }}) } + +func TestAarImportFailsToConvertNoAars(t *testing.T) { + runAndroidLibraryImportTest(t, + Bp2buildTestCase{ + Description: "Android Library Import with no aars does not convert.", + Blueprint: ` +android_library_import { + name: "no_aar_import", +} +`, + ExpectedBazelTargets: []string{}, + }) +} diff --git a/bp2build/aconfig_conversion_test.go b/bp2build/aconfig_conversion_test.go index cbf42ac06..51f0b2ff3 100644 --- a/bp2build/aconfig_conversion_test.go +++ b/bp2build/aconfig_conversion_test.go @@ -105,7 +105,6 @@ func TestCcAconfigLibrary(t *testing.T) { cc_library { name: "server_configurable_flags", srcs: ["bar.cc"], - bazel_module: { bp2build_available: false }, } cc_aconfig_library { name: "foo", @@ -131,7 +130,8 @@ func TestCcAconfigLibrary(t *testing.T) { }, )} RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{ - Blueprint: bp, - ExpectedBazelTargets: expectedBazelTargets, + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + StubbedBuildDefinitions: []string{"server_configurable_flags"}, }) } diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go index 8ec4b3566..afe6dcd55 100644 --- a/bp2build/android_app_conversion_test.go +++ b/bp2build/android_app_conversion_test.go @@ -478,3 +478,41 @@ android_app { }), }}) } + +func TestFrameworkResConversion(t *testing.T) { + runAndroidAppTestCase(t, Bp2buildTestCase{ + Description: "Framework Res custom conversion", + ModuleTypeUnderTest: "android_app", + ModuleTypeUnderTestFactory: java.AndroidAppFactory, + Filesystem: map[string]string{ + "res/values/attrs.xml": "", + "resource_zip.zip": "", + }, + Blueprint: ` +android_app { + name: "framework-res", + resource_zips: [ + "resource_zip.zip", + ], + certificate: "platform", +} + +filegroup { + name: "framework-res-package-jar", + srcs: [":framework-res{.export-package.apk}"], +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("framework_resources", "framework-res", AttrNameToString{ + "certificate_name": `"platform"`, + "manifest": `"AndroidManifest.xml"`, + "resource_files": `["res/values/attrs.xml"]`, + "resource_zips": `["resource_zip.zip"]`, + "target_compatible_with": `["//build/bazel/platforms/os:android"]`, + }), + MakeBazelTargetNoRestrictions("filegroup", "framework-res-package-jar", AttrNameToString{ + "srcs": `[":framework-res.export-package.apk"]`, + }), + }}) + +} diff --git a/bp2build/android_test_conversion_test.go b/bp2build/android_test_conversion_test.go index 52413fad5..486f154ca 100644 --- a/bp2build/android_test_conversion_test.go +++ b/bp2build/android_test_conversion_test.go @@ -47,7 +47,40 @@ android_test { name: "TestApp", srcs: ["app.java"], sdk_version: "current", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("android_test", "TestApp", AttrNameToString{ + "srcs": `["app.java"]`, + "manifest": `"AndroidManifest.xml"`, + "resource_files": `["res/res.png"]`, + "sdk_version": `"current"`, + "assets": `["assets/asset.png"]`, + "assets_dir": `"assets"`, + // no need for optimize = False because it's false for + // android_test by default + }), + }}) +} + +func TestAndroidTest_OptimizationEnabled(t *testing.T) { + runAndroidAppTestCase(t, Bp2buildTestCase{ + Description: "Android test - simple example", + ModuleTypeUnderTest: "android_test", + ModuleTypeUnderTestFactory: java.AndroidTestFactory, + Filesystem: map[string]string{ + "app.java": "", + "res/res.png": "", + "AndroidManifest.xml": "", + "assets/asset.png": "", + }, + Blueprint: ` +android_test { + name: "TestApp", + srcs: ["app.java"], + sdk_version: "current", optimize: { + enabled: true, shrink: true, optimize: true, obfuscate: true, @@ -62,6 +95,9 @@ android_test { "sdk_version": `"current"`, "assets": `["assets/asset.png"]`, "assets_dir": `"assets"`, + // optimize = True because it's false for android_test by + // default + "optimize": `True`, }), }}) } @@ -98,6 +134,45 @@ android_test_helper_app { "assets": `["assets/asset.png"]`, "assets_dir": `"assets"`, "testonly": `True`, + // no need for optimize = True because it's true for + // android_test_helper_app by default + }), + }}) +} + +func TestAndroidTestHelperApp_OptimizationDisabled(t *testing.T) { + runAndroidAppTestCase(t, Bp2buildTestCase{ + Description: "Android test helper app - simple example", + ModuleTypeUnderTest: "android_test_helper_app", + ModuleTypeUnderTestFactory: java.AndroidTestHelperAppFactory, + Filesystem: map[string]string{ + "app.java": "", + "res/res.png": "", + "AndroidManifest.xml": "", + "assets/asset.png": "", + }, + Blueprint: ` +android_test_helper_app { + name: "TestApp", + srcs: ["app.java"], + sdk_version: "current", + optimize: { + enabled: false, + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("android_binary", "TestApp", AttrNameToString{ + "srcs": `["app.java"]`, + "manifest": `"AndroidManifest.xml"`, + "resource_files": `["res/res.png"]`, + "sdk_version": `"current"`, + "assets": `["assets/asset.png"]`, + "assets_dir": `"assets"`, + "testonly": `True`, + // optimize = False because it's true for + // android_test_helper_app by default + "optimize": `False`, }), }}) } diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go index 60de28cc5..5871d5921 100644 --- a/bp2build/apex_conversion_test.go +++ b/bp2build/apex_conversion_test.go @@ -112,7 +112,7 @@ filegroup { } cc_binary { name: "cc_binary_1"} -sh_binary { name: "sh_binary_2"} +sh_binary { name: "sh_binary_2", src: "foo.sh"} apex { name: "com.android.apogee", @@ -609,7 +609,7 @@ filegroup { } cc_binary { name: "cc_binary_1" } -sh_binary { name: "sh_binary_2" } +sh_binary { name: "sh_binary_2", src: "foo.sh"} apex { name: "com.android.apogee", @@ -736,7 +736,7 @@ filegroup { } cc_binary { name: "cc_binary_1"} -sh_binary { name: "sh_binary_2"} +sh_binary { name: "sh_binary_2", src: "foo.sh"} apex_test { name: "com.android.apogee", diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go index 7c26262ae..3e004534e 100644 --- a/bp2build/bp2build_product_config.go +++ b/bp2build/bp2build_product_config.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "reflect" + "sort" "strings" "android/soong/android" @@ -22,6 +23,32 @@ type createProductConfigFilesResult struct { bp2buildTargets map[string]BazelTargets } +type bazelLabel struct { + repo string + pkg string + target string +} + +func (l *bazelLabel) Less(other *bazelLabel) bool { + if l.repo < other.repo { + return true + } + if l.repo > other.repo { + return false + } + if l.pkg < other.pkg { + return true + } + if l.pkg > other.pkg { + return false + } + return l.target < other.target +} + +func (l *bazelLabel) String() string { + return fmt.Sprintf("@%s//%s:%s", l.repo, l.pkg, l.target) +} + func createProductConfigFiles( ctx *CodegenContext, metrics CodegenMetrics) (createProductConfigFilesResult, error) { @@ -54,8 +81,8 @@ func createProductConfigFiles( } currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct) - if len(productVariables.PartitionVars.ProductDirectory) > 0 { - currentProductFolder = fmt.Sprintf("%s%s", productVariables.PartitionVars.ProductDirectory, targetProduct) + if len(productVariables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory) > 0 { + currentProductFolder = fmt.Sprintf("%s%s", productVariables.PartitionVarsForBazelMigrationOnlyDoNotUse.ProductDirectory, targetProduct) } productReplacer := strings.NewReplacer( @@ -72,14 +99,22 @@ func createProductConfigFiles( productsForTesting[i] = fmt.Sprintf(" \"@//build/bazel/tests/products:%s\",", productsForTesting[i]) } - productLabelsToVariables := make(map[string]*android.ProductVariables) - productLabelsToVariables[productReplacer.Replace("@//{PRODUCT_FOLDER}:{PRODUCT}")] = &productVariables + productLabelsToVariables := make(map[bazelLabel]*android.ProductVariables) + productLabelsToVariables[bazelLabel{ + repo: "", + pkg: currentProductFolder, + target: targetProduct, + }] = &productVariables for product, productVariablesStarlark := range productsForTestingMap { productVariables, err := starlarkMapToProductVariables(productVariablesStarlark) if err != nil { return res, err } - productLabelsToVariables["@//build/bazel/tests/products:"+product] = &productVariables + productLabelsToVariables[bazelLabel{ + repo: "", + pkg: "build/bazel/tests/products", + target: product, + }] = &productVariables } res.bp2buildTargets = make(map[string]BazelTargets) @@ -194,7 +229,7 @@ build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_darwin_x86_64 } func platformMappingContent( - productLabelToVariables map[string]*android.ProductVariables, + productLabelToVariables map[bazelLabel]*android.ProductVariables, soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions, convertedModulePathMap map[string]string) (string, error) { var result strings.Builder @@ -211,9 +246,16 @@ func platformMappingContent( mergedConvertedModulePathMap[k] = v } + productLabels := make([]bazelLabel, 0, len(productLabelToVariables)) + for k := range productLabelToVariables { + productLabels = append(productLabels, k) + } + sort.Slice(productLabels, func(i, j int) bool { + return productLabels[i].Less(&productLabels[j]) + }) result.WriteString("platforms:\n") - for productLabel, productVariables := range productLabelToVariables { - platformMappingSingleProduct(productLabel, productVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result) + for _, productLabel := range productLabels { + platformMappingSingleProduct(productLabel, productLabelToVariables[productLabel], soongConfigDefinitions, mergedConvertedModulePathMap, &result) } return result.String(), nil } @@ -233,7 +275,7 @@ var bazelPlatformSuffixes = []string{ } func platformMappingSingleProduct( - label string, + label bazelLabel, productVariables *android.ProductVariables, soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions, convertedModulePathMap map[string]string, @@ -249,11 +291,22 @@ func platformMappingSingleProduct( defaultAppCertificateFilegroup = "@//" + filepath.Dir(proptools.String(productVariables.DefaultAppCertificate)) + ":generated_android_certificate_directory" } + // TODO: b/301598690 - commas can't be escaped in a string-list passed in a platform mapping, + // so commas are switched for ":" here, and must be back-substituted into commas + // wherever the AAPTCharacteristics product config variable is used. + AAPTConfig := []string{} + for _, conf := range productVariables.AAPTConfig { + AAPTConfig = append(AAPTConfig, strings.Replace(conf, ",", ":", -1)) + } + for _, suffix := range bazelPlatformSuffixes { result.WriteString(" ") - result.WriteString(label) + result.WriteString(label.String()) result.WriteString(suffix) result.WriteString("\n") + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:aapt_characteristics=%s\n", proptools.String(productVariables.AAPTCharacteristics))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:aapt_config=%s\n", strings.Join(AAPTConfig, ","))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:aapt_preferred_config=%s\n", proptools.String(productVariables.AAPTPreferredConfig))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:always_use_prebuilt_sdks=%t\n", proptools.Bool(productVariables.Always_use_prebuilt_sdks))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:arc=%t\n", proptools.Bool(productVariables.Arc))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride))) @@ -272,7 +325,7 @@ func platformMappingSingleProduct( result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_name=%s\n", proptools.String(productVariables.DeviceName))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_page_size_agnostic=%t\n", proptools.Bool(productVariables.DevicePageSizeAgnostic))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_product=%s\n", proptools.String(productVariables.DeviceProduct))) - result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_platform=%s\n", label)) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_platform=%s\n", label.String())) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enforce_vintf_manifest=%t\n", proptools.Bool(productVariables.Enforce_vintf_manifest))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte))) @@ -284,6 +337,8 @@ func platformMappingSingleProduct( result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:manifest_package_name_overrides=%s\n", strings.Join(productVariables.ManifestPackageNameOverrides, ","))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:native_coverage=%t\n", proptools.Bool(productVariables.Native_coverage))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_sdk_final=%t\n", proptools.Bool(productVariables.Platform_sdk_final))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_security_patch=%s\n", proptools.String(productVariables.Platform_security_patch))) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_version_last_stable=%s\n", proptools.String(productVariables.Platform_version_last_stable))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_brand=%s\n", productVariables.ProductBrand)) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_manufacturer=%s\n", productVariables.ProductManufacturer)) @@ -310,8 +365,9 @@ func platformMappingSingleProduct( } } - for namespace, namespaceContents := range productVariables.VendorVars { - for variable, value := range namespaceContents { + for _, namespace := range android.SortedKeys(productVariables.VendorVars) { + for _, variable := range android.SortedKeys(productVariables.VendorVars[namespace]) { + value := productVariables.VendorVars[namespace][variable] key := namespace + "__" + variable _, hasBool := soongConfigDefinitions.BoolVars[key] _, hasString := soongConfigDefinitions.StringVars[key] @@ -422,11 +478,15 @@ func starlarkMapToProductVariables(in map[string]starlark.Value) (android.Produc return result, nil } -func createTargets(productLabelsToVariables map[string]*android.ProductVariables, res map[string]BazelTargets) { +func createTargets(productLabelsToVariables map[bazelLabel]*android.ProductVariables, res map[string]BazelTargets) { createGeneratedAndroidCertificateDirectories(productLabelsToVariables, res) + createAvbKeyFilegroups(productLabelsToVariables, res) + for label, variables := range productLabelsToVariables { + createSystemPartition(label, &variables.PartitionVarsForBazelMigrationOnlyDoNotUse, res) + } } -func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[string]*android.ProductVariables, targets map[string]BazelTargets) { +func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[bazelLabel]*android.ProductVariables, targets map[string]BazelTargets) { var allDefaultAppCertificateDirs []string for _, productVariables := range productLabelsToVariables { if proptools.String(productVariables.DefaultAppCertificate) != "" { @@ -454,3 +514,311 @@ func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[s }) } } + +func createAvbKeyFilegroups(productLabelsToVariables map[bazelLabel]*android.ProductVariables, targets map[string]BazelTargets) { + var allAvbKeys []string + for _, productVariables := range productLabelsToVariables { + for _, partitionVariables := range productVariables.PartitionVarsForBazelMigrationOnlyDoNotUse.PartitionQualifiedVariables { + if partitionVariables.BoardAvbKeyPath != "" { + if !android.InList(partitionVariables.BoardAvbKeyPath, allAvbKeys) { + allAvbKeys = append(allAvbKeys, partitionVariables.BoardAvbKeyPath) + } + } + } + } + for _, key := range allAvbKeys { + dir := filepath.Dir(key) + name := filepath.Base(key) + content := fmt.Sprintf(`filegroup( + name = "%s_filegroup", + srcs = ["%s"], + visibility = ["//visibility:public"], +)`, name, name) + targets[dir] = append(targets[dir], BazelTarget{ + name: name + "_filegroup", + packageName: dir, + content: content, + ruleClass: "filegroup", + }) + } +} + +func createSystemPartition(platformLabel bazelLabel, variables *android.PartitionVariables, targets map[string]BazelTargets) { + if !variables.PartitionQualifiedVariables["system"].BuildingImage { + return + } + qualifiedVariables := variables.PartitionQualifiedVariables["system"] + + imageProps := generateImagePropDictionary(variables, "system") + imageProps["skip_fsck"] = "true" + + var properties strings.Builder + for _, prop := range android.SortedKeys(imageProps) { + properties.WriteString(prop) + properties.WriteRune('=') + properties.WriteString(imageProps[prop]) + properties.WriteRune('\n') + } + + var extraProperties strings.Builder + if variables.BoardAvbEnable { + extraProperties.WriteString(" avb_enable = True,\n") + extraProperties.WriteString(fmt.Sprintf(" avb_add_hashtree_footer_args = %q,\n", qualifiedVariables.BoardAvbAddHashtreeFooterArgs)) + keypath := qualifiedVariables.BoardAvbKeyPath + if keypath != "" { + extraProperties.WriteString(fmt.Sprintf(" avb_key = \"//%s:%s\",\n", filepath.Dir(keypath), filepath.Base(keypath)+"_filegroup")) + extraProperties.WriteString(fmt.Sprintf(" avb_algorithm = %q,\n", qualifiedVariables.BoardAvbAlgorithm)) + extraProperties.WriteString(fmt.Sprintf(" avb_rollback_index = %s,\n", qualifiedVariables.BoardAvbRollbackIndex)) + extraProperties.WriteString(fmt.Sprintf(" avb_rollback_index_location = %s,\n", qualifiedVariables.BoardAvbRollbackIndexLocation)) + } + } + + targets[platformLabel.pkg] = append(targets[platformLabel.pkg], BazelTarget{ + name: "system_image", + packageName: platformLabel.pkg, + content: fmt.Sprintf(`partition( + name = "system_image", + base_staging_dir = "//build/bazel/bazel_sandwich:system_staging_dir", + base_staging_dir_file_list = "//build/bazel/bazel_sandwich:system_staging_dir_file_list", + root_dir = "//build/bazel/bazel_sandwich:root_staging_dir", + selinux_file_contexts = "//build/bazel/bazel_sandwich:selinux_file_contexts", + image_properties = """ +%s +""", +%s + type = "system", +)`, properties.String(), extraProperties.String()), + ruleClass: "partition", + loads: []BazelLoad{{ + file: "//build/bazel/rules/partitions:partition.bzl", + symbols: []BazelLoadSymbol{{ + symbol: "partition", + }}, + }}, + }, BazelTarget{ + name: "system_image_test", + packageName: platformLabel.pkg, + content: `partition_diff_test( + name = "system_image_test", + partition1 = "//build/bazel/bazel_sandwich:make_system_image", + partition2 = ":system_image", +)`, + ruleClass: "partition_diff_test", + loads: []BazelLoad{{ + file: "//build/bazel/rules/partitions/diff:partition_diff.bzl", + symbols: []BazelLoadSymbol{{ + symbol: "partition_diff_test", + }}, + }}, + }, BazelTarget{ + name: "run_system_image_test", + packageName: platformLabel.pkg, + content: `run_test_in_build( + name = "run_system_image_test", + test = ":system_image_test", +)`, + ruleClass: "run_test_in_build", + loads: []BazelLoad{{ + file: "//build/bazel/bazel_sandwich:run_test_in_build.bzl", + symbols: []BazelLoadSymbol{{ + symbol: "run_test_in_build", + }}, + }}, + }) +} + +var allPartitionTypes = []string{ + "system", + "vendor", + "cache", + "userdata", + "product", + "system_ext", + "oem", + "odm", + "vendor_dlkm", + "odm_dlkm", + "system_dlkm", +} + +// An equivalent of make's generate-image-prop-dictionary function +func generateImagePropDictionary(variables *android.PartitionVariables, partitionType string) map[string]string { + partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType] + if !ok { + panic("Unknown partitionType: " + partitionType) + } + ret := map[string]string{} + if partitionType == "system" { + if len(variables.PartitionQualifiedVariables["system_other"].BoardPartitionSize) > 0 { + ret["system_other_size"] = variables.PartitionQualifiedVariables["system_other"].BoardPartitionSize + } + if len(partitionQualifiedVariables.ProductHeadroom) > 0 { + ret["system_headroom"] = partitionQualifiedVariables.ProductHeadroom + } + addCommonRoFlagsToImageProps(variables, partitionType, ret) + } + // TODO: other partition-specific logic + if variables.TargetUserimagesUseExt2 { + ret["fs_type"] = "ext2" + } else if variables.TargetUserimagesUseExt3 { + ret["fs_type"] = "ext3" + } else if variables.TargetUserimagesUseExt4 { + ret["fs_type"] = "ext4" + } + + if !variables.TargetUserimagesSparseExtDisabled { + ret["extfs_sparse_flag"] = "-s" + } + if !variables.TargetUserimagesSparseErofsDisabled { + ret["erofs_sparse_flag"] = "-s" + } + if !variables.TargetUserimagesSparseSquashfsDisabled { + ret["squashfs_sparse_flag"] = "-s" + } + if !variables.TargetUserimagesSparseF2fsDisabled { + ret["f2fs_sparse_flag"] = "-S" + } + erofsCompressor := variables.BoardErofsCompressor + if len(erofsCompressor) == 0 && hasErofsPartition(variables) { + if len(variables.BoardErofsUseLegacyCompression) > 0 { + erofsCompressor = "lz4" + } else { + erofsCompressor = "lz4hc,9" + } + } + if len(erofsCompressor) > 0 { + ret["erofs_default_compressor"] = erofsCompressor + } + if len(variables.BoardErofsCompressorHints) > 0 { + ret["erofs_default_compress_hints"] = variables.BoardErofsCompressorHints + } + if len(variables.BoardErofsCompressorHints) > 0 { + ret["erofs_default_compress_hints"] = variables.BoardErofsCompressorHints + } + if len(variables.BoardErofsPclusterSize) > 0 { + ret["erofs_pcluster_size"] = variables.BoardErofsPclusterSize + } + if len(variables.BoardErofsShareDupBlocks) > 0 { + ret["erofs_share_dup_blocks"] = variables.BoardErofsShareDupBlocks + } + if len(variables.BoardErofsUseLegacyCompression) > 0 { + ret["erofs_use_legacy_compression"] = variables.BoardErofsUseLegacyCompression + } + if len(variables.BoardExt4ShareDupBlocks) > 0 { + ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks + } + if len(variables.BoardFlashLogicalBlockSize) > 0 { + ret["flash_logical_block_size"] = variables.BoardFlashLogicalBlockSize + } + if len(variables.BoardFlashEraseBlockSize) > 0 { + ret["flash_erase_block_size"] = variables.BoardFlashEraseBlockSize + } + if len(variables.BoardExt4ShareDupBlocks) > 0 { + ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks + } + if len(variables.BoardExt4ShareDupBlocks) > 0 { + ret["ext4_share_dup_blocks"] = variables.BoardExt4ShareDupBlocks + } + for _, partitionType := range allPartitionTypes { + if qualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType]; ok && len(qualifiedVariables.ProductVerityPartition) > 0 { + ret[partitionType+"_verity_block_device"] = qualifiedVariables.ProductVerityPartition + } + } + // TODO: Vboot + // TODO: AVB + if variables.BoardUsesRecoveryAsBoot { + ret["recovery_as_boot"] = "true" + } + if variables.BoardBuildGkiBootImageWithoutRamdisk { + ret["gki_boot_image_without_ramdisk"] = "true" + } + if variables.ProductUseDynamicPartitionSize { + ret["use_dynamic_partition_size"] = "true" + } + if variables.CopyImagesForTargetFilesZip { + ret["use_fixed_timestamp"] = "true" + } + return ret +} + +// Soong equivalent of make's add-common-ro-flags-to-image-props +func addCommonRoFlagsToImageProps(variables *android.PartitionVariables, partitionType string, ret map[string]string) { + partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType] + if !ok { + panic("Unknown partitionType: " + partitionType) + } + if len(partitionQualifiedVariables.BoardErofsCompressor) > 0 { + ret[partitionType+"_erofs_compressor"] = partitionQualifiedVariables.BoardErofsCompressor + } + if len(partitionQualifiedVariables.BoardErofsCompressHints) > 0 { + ret[partitionType+"_erofs_compress_hints"] = partitionQualifiedVariables.BoardErofsCompressHints + } + if len(partitionQualifiedVariables.BoardErofsPclusterSize) > 0 { + ret[partitionType+"_erofs_pcluster_size"] = partitionQualifiedVariables.BoardErofsPclusterSize + } + if len(partitionQualifiedVariables.BoardExtfsRsvPct) > 0 { + ret[partitionType+"_extfs_rsv_pct"] = partitionQualifiedVariables.BoardExtfsRsvPct + } + if len(partitionQualifiedVariables.BoardF2fsSloadCompressFlags) > 0 { + ret[partitionType+"_f2fs_sldc_flags"] = partitionQualifiedVariables.BoardF2fsSloadCompressFlags + } + if len(partitionQualifiedVariables.BoardFileSystemCompress) > 0 { + ret[partitionType+"_f2fs_compress"] = partitionQualifiedVariables.BoardFileSystemCompress + } + if len(partitionQualifiedVariables.BoardFileSystemType) > 0 { + ret[partitionType+"_fs_type"] = partitionQualifiedVariables.BoardFileSystemType + } + if len(partitionQualifiedVariables.BoardJournalSize) > 0 { + ret[partitionType+"_journal_size"] = partitionQualifiedVariables.BoardJournalSize + } + if len(partitionQualifiedVariables.BoardPartitionReservedSize) > 0 { + ret[partitionType+"_reserved_size"] = partitionQualifiedVariables.BoardPartitionReservedSize + } + if len(partitionQualifiedVariables.BoardPartitionSize) > 0 { + ret[partitionType+"_size"] = partitionQualifiedVariables.BoardPartitionSize + } + if len(partitionQualifiedVariables.BoardSquashfsBlockSize) > 0 { + ret[partitionType+"_squashfs_block_size"] = partitionQualifiedVariables.BoardSquashfsBlockSize + } + if len(partitionQualifiedVariables.BoardSquashfsCompressor) > 0 { + ret[partitionType+"_squashfs_compressor"] = partitionQualifiedVariables.BoardSquashfsCompressor + } + if len(partitionQualifiedVariables.BoardSquashfsCompressorOpt) > 0 { + ret[partitionType+"_squashfs_compressor_opt"] = partitionQualifiedVariables.BoardSquashfsCompressorOpt + } + if len(partitionQualifiedVariables.BoardSquashfsDisable4kAlign) > 0 { + ret[partitionType+"_squashfs_disable_4k_align"] = partitionQualifiedVariables.BoardSquashfsDisable4kAlign + } + if len(partitionQualifiedVariables.BoardPartitionSize) == 0 && len(partitionQualifiedVariables.BoardPartitionReservedSize) == 0 && len(partitionQualifiedVariables.ProductHeadroom) == 0 { + ret[partitionType+"_disable_sparse"] = "true" + } + addCommonFlagsToImageProps(variables, partitionType, ret) +} + +func hasErofsPartition(variables *android.PartitionVariables) bool { + return variables.PartitionQualifiedVariables["product"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["system_ext"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["odm"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["vendor"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["system"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["vendor_dlkm"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["odm_dlkm"].BoardFileSystemType == "erofs" || + variables.PartitionQualifiedVariables["system_dlkm"].BoardFileSystemType == "erofs" +} + +// Soong equivalent of make's add-common-flags-to-image-props +func addCommonFlagsToImageProps(variables *android.PartitionVariables, partitionType string, ret map[string]string) { + // The selinux_fc will be handled separately + partitionQualifiedVariables, ok := variables.PartitionQualifiedVariables[partitionType] + if !ok { + panic("Unknown partitionType: " + partitionType) + } + ret["building_"+partitionType+"_image"] = boolToMakeString(partitionQualifiedVariables.BuildingImage) +} + +func boolToMakeString(b bool) string { + if b { + return "true" + } + return "" +} diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index 15b77669c..f53588d76 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -287,9 +287,9 @@ func (r conversionResults) BuildDirToTargets() map[string]BazelTargets { return r.buildFileToTargets } -// struct to store state of go bazel targets +// struct to store state of b bazel targets (e.g. go targets which do not implement android.Module) // this implements bp2buildModule interface and is passed to generateBazelTargets -type goBazelTarget struct { +type bTarget struct { targetName string targetPackage string bazelRuleClass string @@ -297,26 +297,26 @@ type goBazelTarget struct { bazelAttributes []interface{} } -var _ bp2buildModule = (*goBazelTarget)(nil) +var _ bp2buildModule = (*bTarget)(nil) -func (g goBazelTarget) TargetName() string { - return g.targetName +func (b bTarget) TargetName() string { + return b.targetName } -func (g goBazelTarget) TargetPackage() string { - return g.targetPackage +func (b bTarget) TargetPackage() string { + return b.targetPackage } -func (g goBazelTarget) BazelRuleClass() string { - return g.bazelRuleClass +func (b bTarget) BazelRuleClass() string { + return b.bazelRuleClass } -func (g goBazelTarget) BazelRuleLoadLocation() string { - return g.bazelRuleLoadLocation +func (b bTarget) BazelRuleLoadLocation() string { + return b.bazelRuleLoadLocation } -func (g goBazelTarget) BazelAttributes() []interface{} { - return g.bazelAttributes +func (b bTarget) BazelAttributes() []interface{} { + return b.bazelAttributes } // Creates a target_compatible_with entry that is *not* compatible with android @@ -421,7 +421,7 @@ func generateBazelTargetsGoTest(ctx *android.Context, goModulesMap nameToGoLibra Target_compatible_with: targetNotCompatibleWithAndroid(), } - libTest := goBazelTarget{ + libTest := bTarget{ targetName: gp.name, targetPackage: gp.dir, bazelRuleClass: "go_test", @@ -514,7 +514,7 @@ func generateBazelTargetsGoPackage(ctx *android.Context, g *bootstrap.GoPackage, Target_compatible_with: targetNotCompatibleWithAndroid(), } - lib := goBazelTarget{ + lib := bTarget{ targetName: g.Name(), targetPackage: ctx.ModuleDir(g), bazelRuleClass: "go_library", @@ -555,23 +555,35 @@ type goLibraryModule struct { Deps []string } +type buildConversionMetadata struct { + nameToGoLibraryModule nameToGoLibraryModule + ndkHeaders []blueprint.Module +} + type nameToGoLibraryModule map[string]goLibraryModule -// Visit each module in the graph +// Visit each module in the graph, and collect metadata about the build graph // If a module is of type `bootstrap_go_package`, return a map containing metadata like its dir and deps -func createGoLibraryModuleMap(ctx *android.Context) nameToGoLibraryModule { - ret := nameToGoLibraryModule{} +// If a module is of type `ndk_headers`, add it to a list and return the list +func createBuildConversionMetadata(ctx *android.Context) buildConversionMetadata { + goMap := nameToGoLibraryModule{} + ndkHeaders := []blueprint.Module{} ctx.VisitAllModules(func(m blueprint.Module) { moduleType := ctx.ModuleType(m) // We do not need to store information about blueprint_go_binary since it does not have any rdeps if moduleType == "bootstrap_go_package" { - ret[m.Name()] = goLibraryModule{ + goMap[m.Name()] = goLibraryModule{ Dir: ctx.ModuleDir(m), Deps: m.(*bootstrap.GoPackage).Deps(), } + } else if moduleType == "ndk_headers" { + ndkHeaders = append(ndkHeaders, m) } }) - return ret + return buildConversionMetadata{ + nameToGoLibraryModule: goMap, + ndkHeaders: ndkHeaders, + } } // Returns the deps in the transitive closure of a go target @@ -620,7 +632,7 @@ func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, g Deps: goDepLabels(transitiveDeps, goModulesMap), Target_compatible_with: targetNotCompatibleWithAndroid(), } - libTestSource := goBazelTarget{ + libTestSource := bTarget{ targetName: goSource, targetPackage: ctx.ModuleDir(g), bazelRuleClass: "go_source", @@ -669,7 +681,7 @@ func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, g ga.Srcs = goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()) } - bin := goBazelTarget{ + bin := bTarget{ targetName: g.Name(), targetPackage: ctx.ModuleDir(g), bazelRuleClass: "go_binary", @@ -700,7 +712,9 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers // Visit go libraries in a pre-run and store its state in a map // The time complexity remains O(N), and this does not add significant wall time. - nameToGoLibMap := createGoLibraryModuleMap(ctx.Context()) + meta := createBuildConversionMetadata(ctx.Context()) + nameToGoLibMap := meta.nameToGoLibraryModule + ndkHeaders := meta.ndkHeaders bpCtx := ctx.Context() bpCtx.VisitAllModules(func(m blueprint.Module) { @@ -713,27 +727,32 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers switch ctx.Mode() { case Bp2Build: - // There are two main ways of converting a Soong module to Bazel: - // 1) Manually handcrafting a Bazel target and associating the module with its label - // 2) Automatically generating with bp2build converters - // - // bp2build converters are used for the majority of modules. - if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() { - if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() { - panic(fmt.Errorf("module %q [%s] [%s] was both converted with bp2build and has a handcrafted label", bpCtx.ModuleName(m), moduleType, dir)) + if aModule, ok := m.(android.Module); ok { + reason := aModule.GetUnconvertedReason() + if reason != nil { + // If this module was force-enabled, cause an error. + if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" { + err := fmt.Errorf("Force Enabled Module %s not converted", m.Name()) + errs = append(errs, err) + } + + // Log the module isn't to be converted by bp2build. + // TODO: b/291598248 - Log handcrafted modules differently than other unconverted modules. + metrics.AddUnconvertedModule(m, moduleType, dir, *reason) + return + } + if len(aModule.Bp2buildTargets()) == 0 { + panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", aModule.Name())) } - // Handle modules converted to handcrafted targets. - // - // Since these modules are associated with some handcrafted - // target in a BUILD file, we don't autoconvert them. - // Log the module. - metrics.AddUnconvertedModule(m, moduleType, dir, - android.UnconvertedReason{ - ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE), - }) - } else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() { // Handle modules converted to generated targets. + targets, targetErrs = generateBazelTargets(bpCtx, aModule) + errs = append(errs, targetErrs...) + for _, t := range targets { + // A module can potentially generate more than 1 Bazel + // target, each of a different rule class. + metrics.IncrementRuleClassCount(t.ruleClass) + } // Log the module. metrics.AddConvertedModule(aModule, moduleType, dir) @@ -761,34 +780,16 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers return } } - targets, targetErrs = generateBazelTargets(bpCtx, aModule) - errs = append(errs, targetErrs...) - for _, t := range targets { - // A module can potentially generate more than 1 Bazel - // target, each of a different rule class. - metrics.IncrementRuleClassCount(t.ruleClass) - } - } else if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" { - err := fmt.Errorf("Force Enabled Module %s not converted", m.Name()) - errs = append(errs, err) - } else if aModule, ok := m.(android.Module); ok { - reason := aModule.GetUnconvertedReason() - if reason == nil { - panic(fmt.Errorf("module '%s' was neither converted nor marked unconvertible with bp2build", aModule.Name())) - } else { - metrics.AddUnconvertedModule(m, moduleType, dir, *reason) - } - return } else if glib, ok := m.(*bootstrap.GoPackage); ok { targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap) errs = append(errs, targetErrs...) - metrics.IncrementRuleClassCount("go_library") - metrics.AddConvertedModule(glib, "go_library", dir) + metrics.IncrementRuleClassCount("bootstrap_go_package") + metrics.AddConvertedModule(glib, "bootstrap_go_package", dir) } else if gbin, ok := m.(*bootstrap.GoBinary); ok { targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap) errs = append(errs, targetErrs...) - metrics.IncrementRuleClassCount("go_binary") - metrics.AddConvertedModule(gbin, "go_binary", dir) + metrics.IncrementRuleClassCount("blueprint_go_binary") + metrics.AddConvertedModule(gbin, "blueprint_go_binary", dir) } else { metrics.AddUnconvertedModule(m, moduleType, dir, android.UnconvertedReason{ ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED), @@ -818,6 +819,39 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers } }) + // Create an ndk_sysroot target that has a dependency edge on every target corresponding to Soong's ndk_headers + // This root target will provide headers to sdk variants of jni libraries + if ctx.Mode() == Bp2Build { + var depLabels bazel.LabelList + for _, ndkHeader := range ndkHeaders { + depLabel := bazel.Label{ + Label: "//" + bpCtx.ModuleDir(ndkHeader) + ":" + ndkHeader.Name(), + } + depLabels.Add(&depLabel) + } + a := struct { + Deps bazel.LabelListAttribute + System_dynamic_deps bazel.LabelListAttribute + }{ + Deps: bazel.MakeLabelListAttribute(bazel.UniqueSortedBazelLabelList(depLabels)), + System_dynamic_deps: bazel.MakeLabelListAttribute(bazel.MakeLabelList([]bazel.Label{})), + } + ndkSysroot := bTarget{ + targetName: "ndk_sysroot", + targetPackage: "build/bazel/rules/cc", // The location is subject to change, use build/bazel for now + bazelRuleClass: "cc_library_headers", + bazelRuleLoadLocation: "//build/bazel/rules/cc:cc_library_headers.bzl", + bazelAttributes: []interface{}{&a}, + } + + if t, err := generateBazelTarget(bpCtx, ndkSysroot); err == nil { + dir := ndkSysroot.targetPackage + buildFileToTargets[dir] = append(buildFileToTargets[dir], t) + } else { + errs = append(errs, err) + } + } + if len(errs) > 0 { return conversionResults{}, errs } diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 329c907f8..afbfffacc 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -1994,6 +1994,41 @@ func TestAlreadyPresentBuildTarget(t *testing.T) { }) } +func TestAlreadyPresentOneToManyBuildTarget(t *testing.T) { + bp := ` + custom { + name: "foo", + one_to_many_prop: true, + } + custom { + name: "bar", + } + ` + alreadyPresentBuildFile := + MakeBazelTarget( + "custom", + // one_to_many_prop ensures that foo generates "foo_proto_library_deps". + "foo_proto_library_deps", + AttrNameToString{}, + ) + expectedBazelTargets := []string{ + MakeBazelTarget( + "custom", + "bar", + AttrNameToString{}, + ), + } + registerCustomModule := func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice) + } + RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{ + AlreadyExistingBuildContents: alreadyPresentBuildFile, + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + Description: "Not duplicating work for an already-present BUILD target (different generated name)", + }) +} + // Verifies that if a module is defined in pkg1/Android.bp, that a target present // in pkg2/BUILD.bazel does not result in the module being labeled "already defined // in a BUILD file". diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 560123ea4..3cce430aa 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -159,6 +159,10 @@ cc_library { "min_sdk_version": `"29"`, "use_version_lib": `True`, "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`, + "deps": `select({ + "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"], + "//conditions:default": [], + })`, }), }) } @@ -5157,7 +5161,6 @@ func TestNdkLibraryConversion(t *testing.T) { Blueprint: ` cc_library { name: "libfoo", - bazel_module: { bp2build_available: false }, } ndk_library { name: "libfoo", @@ -5165,6 +5168,7 @@ ndk_library { symbol_file: "libfoo.map.txt", } `, + StubbedBuildDefinitions: []string{"libfoo"}, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_stub_suite", "libfoo.ndk_stub_libs", AttrNameToString{ "api_surface": `"publicapi"`, diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index fde4c973e..e54f05162 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -118,6 +118,10 @@ cc_library_headers { ]`, "sdk_version": `"current"`, "min_sdk_version": `"29"`, + "deps": `select({ + "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"], + "//conditions:default": [], + })`, }), }, }) diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index bdde996eb..2c5305f72 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -175,6 +175,10 @@ cc_library_shared { ]`, "sdk_version": `"current"`, "min_sdk_version": `"29"`, + "deps": `select({ + "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"], + "//conditions:default": [], + })`, }), }, }) @@ -1595,7 +1599,7 @@ func TestCcLibrarySdkVariantUsesStubs(t *testing.T) { Description: "cc_library_shared stubs", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, - StubbedBuildDefinitions: []string{"libNoStubs", "libHasApexStubs", "libHasApexAndNdkStubs"}, + StubbedBuildDefinitions: []string{"libNoStubs", "libHasApexStubs", "libHasApexAndNdkStubs", "libHasApexAndNdkStubs.ndk_stub_libs"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "libUsesSdk", @@ -1621,9 +1625,7 @@ cc_library_shared { } ndk_library { name: "libHasApexAndNdkStubs", - // TODO: b/301321658 - Stub this once existing-build-file handling can deal with - // modules that generate targets of a different name. - bazel_module: { bp2build_available: false }, + first_version: "28", } `, ExpectedBazelTargets: []string{ @@ -1644,6 +1646,10 @@ ndk_library { })`, "local_includes": `["."]`, "sdk_version": `"current"`, + "deps": `select({ + "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"], + "//conditions:default": [], + })`, }), }, }) diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index 7b97b3906..09e40edab 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -203,6 +203,10 @@ cc_library_static { ]`, "sdk_version": `"current"`, "min_sdk_version": `"29"`, + "deps": `select({ + "//build/bazel/rules/apex:unbundled_app": ["//build/bazel/rules/cc:ndk_sysroot"], + "//conditions:default": [], + })`, }), }, }) diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go index 679a36461..392a9621d 100644 --- a/bp2build/cc_test_conversion_test.go +++ b/bp2build/cc_test_conversion_test.go @@ -631,3 +631,23 @@ cc_test { }, }) } + +func TestCcTest_UnitTestFalse(t *testing.T) { + runCcTestTestCase(t, ccTestBp2buildTestCase{ + description: "cc test with test_options.tags converted to tags", + blueprint: ` +cc_test { + name: "mytest", + host_supported: true, + srcs: ["test.cpp"], + test_options: { unit_test: false }, +} +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), + stubbedBuildDefinitions: []string{ + "libgtest_main", + "libgtest", + }, + targets: []testBazelTarget{}, + }) +} diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go index 7d8ab635a..4271f76a5 100644 --- a/bp2build/java_binary_host_conversion_test.go +++ b/bp2build/java_binary_host_conversion_test.go @@ -114,7 +114,7 @@ func TestJavaBinaryHostLibs(t *testing.T) { runJavaBinaryHostTestCase(t, Bp2buildTestCase{ Description: "java_binary_host with srcs, libs.", Filesystem: testFs, - StubbedBuildDefinitions: []string{"prebuilt_java-lib-dep-1"}, + StubbedBuildDefinitions: []string{"java-lib-dep-1", "java-lib-dep-1-neverlink"}, Blueprint: `java_binary_host { name: "java-binary-host-libs", libs: ["java-lib-dep-1"], diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go index 3d55eb27a..4e96efe5e 100644 --- a/bp2build/java_proto_conversion_test.go +++ b/bp2build/java_proto_conversion_test.go @@ -141,17 +141,22 @@ func TestJavaProtoDefault(t *testing.T) { func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) { runJavaProtoTestCase(t, Bp2buildTestCase{ Description: "java_library that has only proto srcs", - StubbedBuildDefinitions: []string{"java-lib"}, + StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"}, Blueprint: `java_library_static { name: "java-protos", srcs: ["a.proto"], - libs: ["java-lib"], + libs: ["java-lib-1"], + static_libs: ["java-lib-2"], java_version: "7", sdk_version: "current", } java_library_static { - name: "java-lib", + name: "java-lib-1", +} + +java_library_static { + name: "java-lib-2", } `, ExpectedBazelTargets: []string{ @@ -162,12 +167,19 @@ java_library_static { "java_lite_proto_library", "java-protos_java_proto_lite", AttrNameToString{ - "deps": `[":java-protos_proto"]`, + "deps": `[":java-protos_proto"]`, + "additional_proto_deps": `[ + ":java-lib-1-neverlink", + ":java-lib-2", + ]`, "java_version": `"7"`, "sdk_version": `"current"`, }), MakeBazelTarget("java_library", "java-protos", AttrNameToString{ - "exports": `[":java-protos_java_proto_lite"]`, + "exports": `[ + ":java-lib-2", + ":java-protos_java_proto_lite", + ]`, "java_version": `"7"`, "sdk_version": `"current"`, }), diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go index 95c239dbf..87f35f6bc 100644 --- a/bp2build/java_test_host_conversion_test.go +++ b/bp2build/java_test_host_conversion_test.go @@ -97,14 +97,13 @@ java_test_host { java_library { name: "lib_a", - bazel_module: { bp2build_available: false }, } java_library { name: "static_libs_a", - bazel_module: { bp2build_available: false }, } `, + StubbedBuildDefinitions: []string{"lib_a", "static_libs_a"}, ExpectedBazelTargets: []string{ MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{ "runtime_deps": `[ diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go index cf256aadc..bd4f54b41 100644 --- a/bp2build/rust_protobuf_conversion_test.go +++ b/bp2build/rust_protobuf_conversion_test.go @@ -27,7 +27,7 @@ func runRustProtobufTestCase(t *testing.T, tc Bp2buildTestCase) { func registerRustProtobufModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("rust_protobuf_host", rust.RustProtobufHostFactory) - + ctx.RegisterModuleType("rust_protobuf", rust.RustProtobufHostFactory) } func TestRustProtobufHostTestCase(t *testing.T) { @@ -58,3 +58,32 @@ rust_protobuf_host { }, ) } + +func TestRustProtobufTestCase(t *testing.T) { + runRustProtobufTestCase(t, Bp2buildTestCase{ + Dir: "external/rust/crates/foo", + Blueprint: "", + Filesystem: map[string]string{ + "external/rust/crates/foo/src/lib.rs": "", + "external/rust/crates/foo/src/helper.rs": "", + "external/rust/crates/foo/Android.bp": ` +rust_protobuf { + name: "libfoo", + crate_name: "foo", + protos: ["src/foo.proto"], + bazel_module: { bp2build_available: true }, +} +`, + }, + ExpectedBazelTargets: []string{ + makeBazelTargetHostOrDevice("proto_library", "libfoo_proto", AttrNameToString{ + "srcs": `["src/foo.proto"]`, + }, android.HostSupported), + makeBazelTargetHostOrDevice("rust_proto_library", "libfoo", AttrNameToString{ + "crate_name": `"foo"`, + "deps": `[":libfoo_proto"]`, + }, android.HostSupported), + }, + }, + ) +} diff --git a/bp2build/testing.go b/bp2build/testing.go index a81070942..d26b346dd 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -27,6 +27,7 @@ import ( "strings" "testing" + "android/soong/ui/metrics/bp2build_metrics_proto" "github.com/google/blueprint/proptools" "android/soong/android" @@ -87,6 +88,15 @@ type Bp2buildTestCase struct { // ExpectedBazelTargets compares the BazelTargets generated in `Dir` (if not empty). // Otherwise, it checks the BazelTargets generated by `Blueprint` in the root directory. ExpectedBazelTargets []string + // ExpectedConvertedModules asserts that modules in this list are labeled as "converted + // by bp2build" in the metrics reported by bp2build. + ExpectedConvertedModules []string + // ExpectedHandcraftedModules asserts that modules in this list are labeled as "handcrafted + // in build files" in the metrics reported by bp2build. Such modules are either explicitly + // defined in a BUILD file (by name), or registered as "otherwise implicitly handled" + // by bp2build (for example, by macros owned by other modules). + ExpectedHandcraftedModules []string + // AlreadyExistingBuildContents, if non-empty, simulates an already-present source BUILD file // in the directory under test. The BUILD file has the given contents. This BUILD file // will also be treated as "BUILD file to keep" by the simulated bp2build environment. @@ -116,6 +126,16 @@ type Bp2buildTestCase struct { KeepBuildFileForDirs []string } +func RunBp2BuildTestCaseExtraContext(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), modifyContext func(ctx *android.TestContext), tc Bp2buildTestCase) { + t.Helper() + bp2buildSetup := android.GroupFixturePreparers( + android.FixtureRegisterWithContext(registerModuleTypes), + android.FixtureModifyContext(modifyContext), + SetBp2BuildTestRunner, + ) + runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc) +} + func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) { t.Helper() bp2buildSetup := android.GroupFixturePreparers( @@ -223,7 +243,7 @@ func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePre checkDir: tc.ExpectedBazelTargets, } - result.CompareAllBazelTargets(t, tc.Description, expectedTargets, true) + result.CompareAllBazelTargets(t, tc, expectedTargets, true) } // SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode. @@ -274,7 +294,7 @@ type BazelTestResult struct { // have a corresponding expected BazelTarget. // // If ignoreUnexpected=true then it will ignore directories for which there are no expected targets. -func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) { +func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, tc Bp2buildTestCase, expectedTargets map[string][]string, ignoreUnexpected bool) { t.Helper() actualTargets := b.buildFileToTargets @@ -301,7 +321,24 @@ func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string t.Errorf("expected %d bazel modules in %q but did not find any", expectedCount, dir) } } else { - b.CompareBazelTargets(t, description, expected, actual) + b.CompareBazelTargets(t, tc.Description, expected, actual) + } + } + + for _, module := range tc.ExpectedConvertedModules { + if _, found := b.metrics.convertedModulePathMap[module]; !found { + t.Errorf("expected %s to be generated by bp2build, but was not. Map of converted modules: %s", module, b.metrics.convertedModulePathMap) + } + } + + for _, module := range tc.ExpectedHandcraftedModules { + if reason, found := b.metrics.serialized.UnconvertedModules[module]; !found { + t.Errorf("expected %s to be marked 'unconverted' by bp2build, but was not found. Full list: %s", + module, b.metrics.serialized.UnconvertedModules) + } else { + if reason.Type != bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE { + t.Errorf("expected %s to be marked 'handcrafted' by bp2build, but was disabled for another reason: %s", module, reason) + } } } } @@ -571,23 +608,6 @@ func (m *customModule) createConfigSetting(ctx android.Bp2buildMutatorContext) { ) } -var _ android.ApiProvider = (*customModule)(nil) - -func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "custom_api_contribution", - } - apiAttribute := bazel.MakeLabelAttribute( - android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label, - ) - attrs := &customBazelModuleAttributes{ - Api: *apiAttribute, - } - ctx.CreateBazelTargetModule(props, - android.CommonAttributes{Name: c.Name()}, - attrs) -} - // A bp2build mutator that uses load statements and creates a 1:M mapping from // module to target. func customBp2buildOneToMany(ctx android.Bp2buildMutatorContext, m *customModule) { diff --git a/cc/bp2build.go b/cc/bp2build.go index 569f721a5..7738487db 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -223,7 +223,7 @@ func partitionHeaders(ctx android.BazelConversionPathContext, hdrs bazel.LabelLi } // bp2BuildParseLibProps returns the attributes for a variant of a cc_library. -func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes { +func bp2BuildParseLibProps(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) staticOrSharedAttributes { lib, ok := module.compiler.(*libraryDecorator) if !ok { return staticOrSharedAttributes{} @@ -232,12 +232,12 @@ func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Modul } // bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library. -func bp2BuildParseSharedProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes { +func bp2BuildParseSharedProps(ctx android.Bp2buildMutatorContext, module *Module) staticOrSharedAttributes { return bp2BuildParseLibProps(ctx, module, false) } // bp2buildParseStaticProps returns the attributes for the static variant of a cc_library. -func bp2BuildParseStaticProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes { +func bp2BuildParseStaticProps(ctx android.Bp2buildMutatorContext, module *Module) staticOrSharedAttributes { return bp2BuildParseLibProps(ctx, module, true) } @@ -288,7 +288,7 @@ func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, pro } // Parses properties common to static and shared libraries. Also used for prebuilt libraries. -func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes { +func bp2buildParseStaticOrSharedProps(ctx android.Bp2buildMutatorContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes { attrs := staticOrSharedAttributes{} setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) { @@ -334,7 +334,7 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo attrs.Srcs_c = partitionedSrcs[cSrcPartition] attrs.Srcs_as = partitionedSrcs[asSrcPartition] - attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable) + attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx, apexAvailable) attrs.Features.Append(convertHiddenVisibilityToFeatureStaticOrShared(ctx, module, isStatic)) @@ -1143,7 +1143,7 @@ func bp2buildCcAidlLibrary( compilerAttrs compilerAttributes, ) *bazel.LabelAttribute { var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute - apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module()) + apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module()) if !aidlSrcs.IsEmpty() { aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool { @@ -1283,7 +1283,7 @@ func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPat la.implementationDeps.Append(staticExcludesLabelList) } -func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) { +func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.Bp2buildMutatorContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) { isBinary := module.Binary() // Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module var axisFeatures []string @@ -1378,10 +1378,10 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion // having stubs or not, so Bazel select() statement can be used to choose // source/stub variants of them. apexAvailable := module.ApexAvailable() - SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, 0, false) - SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, 1, false) + SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, &la.deps, 0, false) + SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, &la.deps, 1, false) if len(systemSharedLibs) > 0 { - SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, 2, true) + SetStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, &la.deps, 2, true) } } @@ -1490,7 +1490,7 @@ func GetApiDomain(apexName string) string { // Note that this is an anti-pattern: The config_setting should be created from the apex definition // and not from a cc_library. // This anti-pattern is needed today since not all apexes have been allowlisted. -func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) { +func createInApexConfigSetting(ctx android.Bp2buildMutatorContext, apexName string) { if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex { // These correspond to android-non_apex and android-in_apex return @@ -1587,13 +1587,13 @@ func hasNdkStubs(ctx android.BazelConversionPathContext, c *Module) bool { return exists && ctx.OtherModuleType(mod) == "ndk_library" } -func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, - config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) { +func SetStubsForDynamicDeps(ctx android.Bp2buildMutatorContext, axis bazel.ConfigurationAxis, + config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, deps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) { // Create a config_setting for each apex_available. // This will be used to select impl of a dep if dep is available to the same apex. for _, aa := range apexAvailable { - createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa) + createInApexConfigSetting(ctx, aa) } apiDomainForSelects := []string{} @@ -1669,9 +1669,21 @@ func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.C existingValue.Append(bazel.MakeLabelList([]bazel.Label{label})) dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue)) } + + // Add ndk_sysroot to deps. + // ndk_sysroot has a dependency edge on all ndk_headers, and will provide the .h files of _every_ ndk library + existingValue := deps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app") + existingValue.Append(bazel.MakeLabelList([]bazel.Label{ndkSysrootLabel})) + deps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue)) } } +var ( + ndkSysrootLabel = bazel.Label{ + Label: "//build/bazel/rules/cc:ndk_sysroot", + } +) + func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) { if stripProperties, ok := props.(*StripProperties); ok { @@ -4273,24 +4273,6 @@ func (c *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { } } -var _ android.ApiProvider = (*Module)(nil) - -func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { - if c.IsPrebuilt() { - return - } - switch c.typ() { - case fullLibrary: - apiContributionBp2Build(ctx, c) - case sharedLibrary: - apiContributionBp2Build(ctx, c) - case headerLibrary: - // Aggressively generate api targets for all header modules - // This is necessary since the header module does not know if it is a dep of API surface stub library - apiLibraryHeadersBp2Build(ctx, c) - } -} - // Defaults type Defaults struct { android.ModuleBase diff --git a/cc/library.go b/cc/library.go index b9dc71b32..e66ce08e6 100644 --- a/cc/library.go +++ b/cc/library.go @@ -517,70 +517,6 @@ func createStubsBazelTargetIfNeeded(ctx android.Bp2buildMutatorContext, m *Modul } } -func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) { - apiSurfaces := make([]string, 0) - apiHeaders := make([]string, 0) - // module-libapi for apexes (non-null `stubs` property) - if module.HasStubsVariants() { - apiSurfaces = append(apiSurfaces, android.ModuleLibApi.String()) - apiIncludes := getModuleLibApiIncludes(ctx, module) - if !apiIncludes.isEmpty() { - createApiHeaderTarget(ctx, apiIncludes) - apiHeaders = append(apiHeaders, apiIncludes.name) - } - } - // vendorapi (non-null `llndk` property) - if module.HasLlndkStubs() { - apiSurfaces = append(apiSurfaces, android.VendorApi.String()) - apiIncludes := getVendorApiIncludes(ctx, module) - if !apiIncludes.isEmpty() { - createApiHeaderTarget(ctx, apiIncludes) - apiHeaders = append(apiHeaders, apiIncludes.name) - } - } - // create a target only if this module contributes to an api surface - // TODO: Currently this does not distinguish modulelibapi-only headers and vendrorapi-only headers - // TODO: Update so that modulelibapi-only headers do not get exported to vendorapi (and vice-versa) - if len(apiSurfaces) > 0 { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "cc_api_contribution", - Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", - } - attrs := &bazelCcApiContributionAttributes{ - Library_name: module.Name(), - Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces), - Api: apiLabelAttribute(ctx, module), - Hdrs: bazel.MakeLabelListAttribute( - bazel.MakeLabelListFromTargetNames(apiHeaders), - ), - } - ctx.CreateBazelTargetModule( - props, - android.CommonAttributes{ - Name: android.ApiContributionTargetName(module.Name()), - SkipData: proptools.BoolPtr(true), - }, - attrs, - ) - } -} - -// Native apis are versioned in a single .map.txt for all api surfaces -// Pick any one of the .map.txt files -func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute { - var apiFile *string - linker := module.linker.(*libraryDecorator) - if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil { - apiFile = llndkApi - } else if moduleLibApi := linker.Properties.Stubs.Symbol_file; moduleLibApi != nil { - apiFile = moduleLibApi - } else { - ctx.ModuleErrorf("API surface library does not have any API file") - } - apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label - return *bazel.MakeLabelAttribute(apiLabel) -} - // wrapper struct to flatten the arch and os specific export_include_dirs // flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.) type bazelCcApiLibraryHeadersAttributes struct { diff --git a/cc/library_headers.go b/cc/library_headers.go index 5eba6ab96..fccdf996e 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -15,8 +15,6 @@ package cc import ( - "github.com/google/blueprint/proptools" - "android/soong/android" "android/soong/bazel" "android/soong/bazel/cquery" @@ -175,106 +173,6 @@ func apiBazelTargets(ll bazel.LabelList) bazel.LabelList { return bazel.MakeLabelList(labels) } -func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { - // cc_api_library_headers have a 1:1 mapping to arch/no-arch - // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps - - // arch-agnostic includes - apiIncludes := getModuleLibApiIncludes(ctx, module) - // arch and os specific includes - archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module) - for _, arch := range allArches { // sorted iteration - archApiInclude := archApiIncludes[arch] - if !archApiInclude.isEmpty() { - createApiHeaderTarget(ctx, archApiInclude) - apiIncludes.addDep(archApiInclude.name) - } - } - // os==android includes - if !androidOsIncludes.isEmpty() { - createApiHeaderTarget(ctx, androidOsIncludes) - apiIncludes.addDep(androidOsIncludes.name) - } - - if !apiIncludes.isEmpty() { - // override the name from <mod>.module-libapi.headers --> <mod>.contribution - apiIncludes.name = android.ApiContributionTargetName(module.Name()) - createApiHeaderTarget(ctx, apiIncludes) - } -} - -func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "cc_api_library_headers", - Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", - } - ctx.CreateBazelTargetModule( - props, - android.CommonAttributes{ - Name: includes.name, - SkipData: proptools.BoolPtr(true), - }, - &includes.attrs, - ) -} - var ( allArches = []string{"arm", "arm64", "x86", "x86_64"} ) - -type archApiIncludes map[string]apiIncludes - -func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) { - baseProps := bp2BuildParseBaseProps(ctx, module) - i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes) - archRet := archApiIncludes{} - for _, arch := range allArches { - includes := i.Includes.SelectValue( - bazel.ArchConfigurationAxis, - arch) - systemIncludes := i.SystemIncludes.SelectValue( - bazel.ArchConfigurationAxis, - arch) - deps := baseProps.deps.SelectValue( - bazel.ArchConfigurationAxis, - arch) - attrs := bazelCcLibraryHeadersAttributes{ - Export_includes: bazel.MakeStringListAttribute(includes), - Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), - } - apiDeps := apiBazelTargets(deps) - if !apiDeps.IsEmpty() { - attrs.Deps = bazel.MakeLabelListAttribute(apiDeps) - } - apiIncludes := apiIncludes{ - name: android.ApiContributionTargetName(module.Name()) + "." + arch, - attrs: bazelCcApiLibraryHeadersAttributes{ - bazelCcLibraryHeadersAttributes: attrs, - Arch: proptools.StringPtr(arch), - }, - } - archRet[arch] = apiIncludes - } - - // apiIncludes for os == Android - androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid) - androidOsAttrs := bazelCcLibraryHeadersAttributes{ - Export_includes: bazel.MakeStringListAttribute( - i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), - ), - Export_system_includes: bazel.MakeStringListAttribute( - i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), - ), - } - androidOsApiDeps := apiBazelTargets(androidOsDeps) - if !androidOsApiDeps.IsEmpty() { - androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps) - } - osRet := apiIncludes{ - name: android.ApiContributionTargetName(module.Name()) + ".androidos", - attrs: bazelCcApiLibraryHeadersAttributes{ - bazelCcLibraryHeadersAttributes: androidOsAttrs, - }, - } - return archRet, osRet -} diff --git a/cc/ndk_library.go b/cc/ndk_library.go index b3bb2da15..56c57b94c 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -386,9 +386,11 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { // level. abiDiffPath := android.PathForModuleOut(ctx, "stgdiff.timestamp") prebuiltAbiDump := this.findPrebuiltAbiDump(ctx, this.apiLevel) + missingPrebuiltErrorTemplate := + "Did not find prebuilt ABI dump for %q (%q). Generate with " + + "//development/tools/ndk/update_ndk_abi.sh." missingPrebuiltError := fmt.Sprintf( - "Did not find prebuilt ABI dump for %q (%q). Generate with "+ - "//development/tools/ndk/update_ndk_abi.sh.", this.libraryName(ctx), + missingPrebuiltErrorTemplate, this.libraryName(ctx), prebuiltAbiDump.InvalidReason()) if !prebuiltAbiDump.Valid() { ctx.Build(pctx, android.BuildParams{ @@ -424,12 +426,15 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { nextAbiDiffPath := android.PathForModuleOut(ctx, "abidiff_next.timestamp") nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel) + missingNextPrebuiltError := fmt.Sprintf( + missingPrebuiltErrorTemplate, this.libraryName(ctx), + nextAbiDump.InvalidReason()) if !nextAbiDump.Valid() { ctx.Build(pctx, android.BuildParams{ Rule: android.ErrorRule, Output: nextAbiDiffPath, Args: map[string]string{ - "error": missingPrebuiltError, + "error": missingNextPrebuiltError, }, }) } else { diff --git a/cc/proto.go b/cc/proto.go index 0ed4381d7..4e08a4cbd 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -246,7 +246,7 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version name := m.Name() + suffix - tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m) + tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m) ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: rule_class, diff --git a/cc/sanitize.go b/cc/sanitize.go index 9ceb1c8a0..6329e9769 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1113,12 +1113,15 @@ func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool { // indirectly (via a mutator) sets the bool ptr to true, and you can't // distinguish between the cases. It isn't needed though - both cases can be // treated identically. -func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool { - if sanitize == nil { +func (s *sanitize) isSanitizerEnabled(t SanitizerType) bool { + if s == nil { + return false + } + if proptools.Bool(s.Properties.SanitizeMutated.Never) { return false } - sanitizerVal := sanitize.getSanitizerBoolPtr(t) + sanitizerVal := s.getSanitizerBoolPtr(t) return sanitizerVal != nil && *sanitizerVal == true } diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go index 49117a082..31e668ea9 100644 --- a/cc/sanitize_test.go +++ b/cc/sanitize_test.go @@ -16,6 +16,7 @@ package cc import ( "fmt" + "reflect" "runtime" "strings" "testing" @@ -1273,3 +1274,122 @@ func TestCfi(t *testing.T) { t.Errorf("non-CFI variant of baz not expected to contain CFI flags ") } } + +func TestHwasan(t *testing.T) { + t.Parallel() + + bp := ` + cc_library_shared { + name: "shared_with_hwaddress", + static_libs: [ + "static_dep_with_hwaddress", + "static_dep_no_hwaddress", + ], + sanitize: { + hwaddress: true, + }, + sdk_version: "current", + stl: "c++_shared", + } + + cc_library_static { + name: "static_dep_with_hwaddress", + sanitize: { + hwaddress: true, + }, + sdk_version: "current", + stl: "c++_shared", + } + + cc_library_static { + name: "static_dep_no_hwaddress", + sdk_version: "current", + stl: "c++_shared", + } +` + + androidArm := "android_arm_armv7-a-neon" + androidArm64 := "android_arm64_armv8-a" + androidX86 := "android_x86_silvermont" + sharedSuffix := "_shared" + hwasanSuffix := "_hwasan" + staticSuffix := "_static" + sdkSuffix := "_sdk" + + sharedWithHwasanVariant := sharedSuffix + hwasanSuffix + sharedWithSdkVariant := sdkSuffix + sharedSuffix + staticWithHwasanVariant := staticSuffix + hwasanSuffix + staticWithSdkVariant := sdkSuffix + staticSuffix + + testCases := []struct { + buildOs string + extraPreparer android.FixturePreparer + expectedVariants map[string][]string + }{ + { + buildOs: androidArm64, + expectedVariants: map[string][]string{ + "shared_with_hwaddress": []string{ + androidArm64 + sharedWithHwasanVariant, + androidArm64 + sharedWithSdkVariant, + androidArm + sharedSuffix, + androidArm + sharedWithSdkVariant, + }, + "static_dep_with_hwaddress": []string{ + androidArm64 + staticSuffix, + androidArm64 + staticWithHwasanVariant, + androidArm64 + staticWithSdkVariant, + androidArm + staticSuffix, + androidArm + staticWithSdkVariant, + }, + "static_dep_no_hwaddress": []string{ + androidArm64 + staticSuffix, + androidArm64 + staticWithHwasanVariant, + androidArm64 + staticWithSdkVariant, + androidArm + staticSuffix, + androidArm + staticWithSdkVariant, + }, + }, + }, + { + buildOs: androidX86, + extraPreparer: android.FixtureModifyConfig(func(config android.Config) { + config.Targets[android.Android] = []android.Target{ + { + android.Android, + android.Arch{ + ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, android.NativeBridgeDisabled, "", "", false}, + } + }), + expectedVariants: map[string][]string{ + "shared_with_hwaddress": []string{ + androidX86 + sharedSuffix, + androidX86 + sharedWithSdkVariant, + }, + "static_dep_with_hwaddress": []string{ + androidX86 + staticSuffix, + androidX86 + staticWithSdkVariant, + }, + "static_dep_no_hwaddress": []string{ + androidX86 + staticSuffix, + androidX86 + staticWithSdkVariant, + }, + }, + }, + } + + for _, tc := range testCases { + preparer := android.GroupFixturePreparers( + prepareForCcTest, + android.OptionalFixturePreparer(tc.extraPreparer), + ) + result := preparer.RunTestWithBp(t, bp) + + for m, v := range tc.expectedVariants { + variants := result.ModuleVariantsForTests(m) + if !reflect.DeepEqual(variants, v) { + t.Errorf("Expected variants of %q to be %q, but got %q", m, v, variants) + } + } + } +} diff --git a/cc/sysprop.go b/cc/sysprop.go index 7ddd4760e..be030046d 100644 --- a/cc/sysprop.go +++ b/cc/sysprop.go @@ -38,7 +38,7 @@ type SyspropLibraryLabels struct { } func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) { - apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module()) + apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module()) ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "sysprop_library", diff --git a/cc/test.go b/cc/test.go index 7a6cf1b4e..8c63dc614 100644 --- a/cc/test.go +++ b/cc/test.go @@ -25,6 +25,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" "android/soong/tradefed" + "android/soong/ui/metrics/bp2build_metrics_proto" ) // TestLinkerProperties properties to be registered via the linker @@ -718,6 +719,13 @@ func testBinaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs)) data.SetSelectValue(axis, config, combinedData) tags.SetSelectValue(axis, config, p.Test_options.Tags) + + // TODO: b/300117121 - handle bp2build conversion of non-unit tests + // default to true to only handle non-nil falses + if !BoolDefault(p.Test_options.Unit_test, true) { + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "Host unit_test = false") + return + } } } } diff --git a/cc/testing.go b/cc/testing.go index 36bc261e0..71d986b4f 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -68,26 +68,6 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { func commonDefaultModules() string { return ` - prebuilt_build_tool { - name: "clang++", - src: "bin/clang++", - } - prebuilt_build_tool { - name: "clang++.real", - src: "bin/clang++.real", - } - prebuilt_build_tool { - name: "lld", - src: "bin/lld", - } - prebuilt_build_tool { - name: "ld.lld", - src: "bin/ld.lld", - } - prebuilt_build_tool { - name: "llvm-ar", - src: "bin/llvm-ar", - } cc_defaults { name: "toolchain_libs_defaults", host_supported: true, @@ -589,12 +569,6 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers( // Additional files needed in tests that disallow non-existent source. android.MockFS{ - "defaults/cc/common/bin/clang++": nil, - "defaults/cc/common/bin/clang++.real": nil, - "defaults/cc/common/bin/lld": nil, - "defaults/cc/common/bin/ld.lld": nil, - "defaults/cc/common/bin/llvm-ar": nil, - "defaults/cc/common/libc.map.txt": nil, "defaults/cc/common/libdl.map.txt": nil, "defaults/cc/common/libm.map.txt": nil, diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 9ea337b8d..e8e930e8f 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -98,6 +98,11 @@ func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietar if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) { return false } + // cfi and hwasan cannot be enabled at the same time. + // Skip variants that have both cfi and hwasan enabled. + if sanitizable.IsSanitizerEnabled(cfi) && sanitizable.IsSanitizerEnabled(Hwasan) { + return false + } // cfi and hwasan also export both variants. But for static, we capture both. // This is because cfi static libraries can't be linked from non-cfi modules, // and vice versa. diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go index 2e71fe15e..a7308b471 100644 --- a/cmd/extract_apks/main.go +++ b/cmd/extract_apks/main.go @@ -76,8 +76,8 @@ func (apkSet *ApkSet) getToc() (Toc, error) { if err != nil { return nil, err } - bytes := make([]byte, tocFile.FileHeader.UncompressedSize64) - if _, err := rc.Read(bytes); err != nil && err != io.EOF { + bytes, err := io.ReadAll(rc) + if err != nil { return nil, err } rc.Close() diff --git a/jar/jar.go b/jar/jar.go index f164ee1ee..54eded93a 100644 --- a/jar/jar.go +++ b/jar/jar.go @@ -166,10 +166,23 @@ func JavaPackage(r io.Reader, src string) (string, error) { } s.IsIdentRune = javaIdentRune - tok := s.Scan() - if sErr != nil { - return "", sErr + var tok rune + for { + tok = s.Scan() + if sErr != nil { + return "", sErr + } + // If the first token is an annotation, it could be annotating a package declaration, so consume them. + // Note that this does not support "complex" annotations with attributes, e.g. @Foo(x=y). + if tok != '@' { + break + } + tok = s.Scan() + if tok != scanner.Ident || sErr != nil { + return "", fmt.Errorf("expected annotation identifier, got @%v", tok) + } } + if tok == scanner.Ident { switch s.TokenText() { case "package": @@ -189,9 +202,6 @@ func JavaPackage(r io.Reader, src string) (string, error) { default: return "", fmt.Errorf(`expected first token of java file to be "package", got %q`, s.TokenText()) } - } else if tok == '@' { - // File has no package statement, first token is an annotation - return "", nil } else if tok == scanner.EOF { // File no package statement, it has no non-whitespace non-comment tokens return "", nil diff --git a/jar/jar_test.go b/jar/jar_test.go index c92011e12..61da9bb6f 100644 --- a/jar/jar_test.go +++ b/jar/jar_test.go @@ -61,6 +61,16 @@ func TestGetJavaPackage(t *testing.T) { in: "package 0foo.bar;", wantErr: true, }, + { + name: "annotations", + in: "@NonNullApi\n@X\npackage foo.bar;", + want: "foo.bar", + }, + { + name: "complex annotation", + in: "@Foo(x=y)\n@package foo.bar;", + wantErr: true, // Complex annotation not supported yet. + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/java/aar.go b/java/aar.go index f28d97149..44496dc57 100644 --- a/java/aar.go +++ b/java/aar.go @@ -1223,6 +1223,7 @@ func AARImportFactory() android.Module { type bazelAapt struct { Manifest bazel.Label Resource_files bazel.LabelListAttribute + Resource_zips bazel.LabelListAttribute Assets_dir bazel.StringAttribute Assets bazel.LabelListAttribute } @@ -1267,15 +1268,30 @@ func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.Bp2buildMutatorContext) assets = bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))) } + var resourceZips bazel.LabelList + if len(a.aaptProperties.Resource_zips) > 0 { + if ctx.ModuleName() == "framework-res" { + resourceZips = android.BazelLabelForModuleSrc(ctx, a.aaptProperties.Resource_zips) + } else { + //TODO: b/301593550 - Implement support for this + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "resource_zips") + return &bazelAapt{}, false + } + } return &bazelAapt{ android.BazelLabelForModuleSrcSingle(ctx, manifest), bazel.MakeLabelListAttribute(resourceFiles), + bazel.MakeLabelListAttribute(resourceZips), assetsDir, bazel.MakeLabelListAttribute(assets), }, true } func (a *AARImport) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if len(a.properties.Aars) == 0 { + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "aars can't be empty") + return + } aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{}) exportableStaticLibs := []string{} // TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel. @@ -1340,10 +1356,12 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) if !commonAttrs.Srcs.IsEmpty() { deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them } else if !depLabels.Deps.IsEmpty() { - ctx.MarkBp2buildUnconvertible( - bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, - "Module has direct dependencies but no sources. Bazel will not allow this.") - return + // android_library does not accept deps when there are no srcs because + // there is no compilation happening, but it accepts exports. + // The non-empty deps here are unnecessary as deps on the android_library + // since they aren't being propagated to any dependencies. + // So we can drop deps here. + deps = bazel.LabelListAttribute{} } name := a.Name() props := AndroidLibraryBazelTargetModuleProperties() @@ -1352,6 +1370,9 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) if !supported { return } + if hasJavaResources := aaptAttrs.ConvertJavaResources(ctx, commonAttrs); hasJavaResources { + return + } ctx.CreateBazelTargetModule( props, android.CommonAttributes{Name: name}, diff --git a/java/app.go b/java/app.go index dabc3192e..166c22d94 100755 --- a/java/app.go +++ b/java/app.go @@ -1638,6 +1638,15 @@ type bazelAndroidAppAttributes struct { Updatable *bool } +func (b bazelAapt) ConvertJavaResources(ctx android.Bp2buildMutatorContext, javaAttrs *javaCommonAttributes) bool { + // TODO (b/300470246) bp2build support for java_resources & java_resource_dirs in android rules + hasJavaResources := !javaAttrs.javaResourcesAttributes.Resources.IsEmpty() + if hasJavaResources { + ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "(b/300470246) java resources in android_* module") + } + return hasJavaResources +} + func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (bool, android.CommonAttributes, *bazelAndroidAppAttributes) { aapt, supported := a.convertAaptAttrsWithBp2Build(ctx) if !supported { @@ -1674,9 +1683,25 @@ func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (boo Updatable: a.appProperties.Updatable, } - if !BoolDefault(a.dexProperties.Optimize.Enabled, true) { - appAttrs.Optimize = proptools.BoolPtr(false) - } else { + // As framework-res has no sources, no deps in the Bazel sense, and java compilation, dexing and optimization is skipped by + // Soong specifically for it, return early here before any of the conversion work for the above is attempted. + if ctx.ModuleName() == "framework-res" { + appAttrs.bazelAapt = aapt + return true, android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, appAttrs + } + + // Optimization is.. + // - enabled by default for android_app, android_test_helper_app + // - disabled by default for android_test + // + // TODO(b/192032291): Disable android_test_helper_app optimization by + // default after auditing downstream usage. + if a.dexProperties.Optimize.EnabledByDefault != a.dexer.effectiveOptimizeEnabled() { + // Property is explicitly defined by default from default, so emit the Bazel attribute. + appAttrs.Optimize = proptools.BoolPtr(a.dexer.effectiveOptimizeEnabled()) + } + + if a.dexer.effectiveOptimizeEnabled() { handCraftedFlags := "" if Bool(a.dexProperties.Optimize.Ignore_warnings) { handCraftedFlags += "-ignorewarning " @@ -1712,6 +1737,10 @@ func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (boo if !supported { return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} } + if hasJavaResources := aapt.ConvertJavaResources(ctx, commonAttrs); hasJavaResources { + return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} + } + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps @@ -1762,11 +1791,18 @@ func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (boo // ConvertWithBp2build is used to convert android_app to Bazel. func (a *AndroidApp) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, a); ok { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "android_binary", - Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", + var props bazel.BazelTargetModuleProperties + if ctx.ModuleName() == "framework-res" { + props = bazel.BazelTargetModuleProperties{ + Rule_class: "framework_resources", + Bzl_load_location: "//build/bazel/rules/android:framework_resources.bzl", + } + } else { + props = bazel.BazelTargetModuleProperties{ + Rule_class: "android_binary", + Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", + } } - ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs) } @@ -1790,13 +1826,12 @@ func (atha *AndroidTestHelperApp) ConvertWithBp2build(ctx android.Bp2buildMutato // an android_test_helper_app is an android_binary with testonly = True commonAttrs.Testonly = proptools.BoolPtr(true) - // additionally, it sets default values differently to android_app, + // android_test_helper_app sets default values differently to android_app, // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/java/app.go;l=1273-1279;drc=e12c083198403ec694af6c625aed11327eb2bf7f // // installable: true (settable prop) // use_embedded_native_libs: true (settable prop) // lint.test: true (settable prop) - // optimize EnabledByDefault: true (blueprint mutated prop) // AlwaysPackageNativeLibs: true (blueprint mutated prop) // dexpreopt isTest: true (not prop) diff --git a/java/base.go b/java/base.go index a110aff56..db237dac0 100644 --- a/java/base.go +++ b/java/base.go @@ -432,6 +432,9 @@ type Module struct { srcJarArgs []string srcJarDeps android.Paths + // the source files of this module and all its static dependencies + transitiveSrcFiles *android.DepSet[android.Path] + // jar file containing implementation classes and resources including static library // dependencies implementationAndResourcesJar android.Path @@ -1343,10 +1346,17 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath jars = append(jars, classes) } } + // Assume approximately 5 sources per srcjar. + // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean + // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files. if len(srcJars) > 0 { - classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs), - nil, srcJars, flags, extraJarDeps) - jars = append(jars, classes) + startIdx := len(shardSrcs) + shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5) + for idx, shardSrcJars := range shardSrcJarsList { + classes := j.compileJavaClasses(ctx, jarName, startIdx+idx, + nil, shardSrcJars, flags, extraJarDeps) + jars = append(jars, classes) + } } } else { classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps) @@ -1687,6 +1697,8 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath j.linter.lint(ctx) } + j.collectTransitiveSrcFiles(ctx, srcFiles) + ctx.CheckbuildFile(outputFile) j.collectTransitiveAconfigFiles(ctx) @@ -1701,6 +1713,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath AidlIncludeDirs: j.exportAidlIncludeDirs, SrcJarArgs: j.srcJarArgs, SrcJarDeps: j.srcJarDeps, + TransitiveSrcFiles: j.transitiveSrcFiles, ExportedPlugins: j.exportedPluginJars, ExportedPluginClasses: j.exportedPluginClasses, ExportedPluginDisableTurbine: j.exportedDisableTurbine, @@ -2025,6 +2038,21 @@ func (j *Module) JacocoReportClassesFile() android.Path { return j.jacocoReportClassesFile } +func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) { + var fromDeps []*android.DepSet[android.Path] + ctx.VisitDirectDeps(func(module android.Module) { + tag := ctx.OtherModuleDependencyTag(module) + if tag == staticLibTag { + depInfo := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) + if depInfo.TransitiveSrcFiles != nil { + fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles) + } + } + }) + + j.transitiveSrcFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps) +} + func (j *Module) IsInstallable() bool { return Bool(j.properties.Installable) } diff --git a/java/droidstubs.go b/java/droidstubs.go index 1d5dd7624..67a55bd49 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -24,7 +24,6 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" - "android/soong/bazel" "android/soong/java/config" "android/soong/remoteexec" ) @@ -855,34 +854,6 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } -var _ android.ApiProvider = (*Droidstubs)(nil) - -type bazelJavaApiContributionAttributes struct { - Api bazel.LabelAttribute - Api_surface *string -} - -func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { - props := bazel.BazelTargetModuleProperties{ - Rule_class: "java_api_contribution", - Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl", - } - apiFile := d.properties.Check_api.Current.Api_file - // Do not generate a target if check_api is not set - if apiFile == nil { - return - } - attrs := &bazelJavaApiContributionAttributes{ - Api: *bazel.MakeLabelAttribute( - android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label, - ), - Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())), - } - ctx.CreateBazelTargetModule(props, android.CommonAttributes{ - Name: android.ApiContributionTargetName(ctx.ModuleName()), - }, attrs) -} - func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) { api_file := d.properties.Check_api.Current.Api_file api_surface := d.properties.Api_surface diff --git a/java/java.go b/java/java.go index d5aeb7cb2..cac49a2c5 100644 --- a/java/java.go +++ b/java/java.go @@ -278,6 +278,9 @@ type JavaInfo struct { // SrcJarDeps is a list of paths to depend on when packaging the sources of this module. SrcJarDeps android.Paths + // The source files of this module and all its transitive static dependencies. + TransitiveSrcFiles *android.DepSet[android.Path] + // ExportedPlugins is a list of paths that should be used as annotation processors for any // module that depends on this module. ExportedPlugins android.Paths @@ -1667,11 +1670,6 @@ type JavaApiLibraryProperties struct { // This is a list of Soong modules Api_contributions []string - // list of api.txt files relative to this directory that contribute to the - // API surface. - // This is a list of relative paths - Api_files []string `android:"path"` - // List of flags to be passed to the javac compiler to generate jar file Javacflags []string @@ -1819,37 +1817,22 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { } } -// API signature file names sorted from -// the narrowest api scope to the widest api scope -var scopeOrderedSourceFileNames = allApiScopes.Strings( - func(s *apiScope) string { return s.apiFilePrefix + "current.txt" }) +// Map where key is the api scope name and value is the int value +// representing the order of the api scope, narrowest to the widest +var scopeOrderMap = allApiScopes.MapToIndex( + func(s *apiScope) string { return s.name }) -func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo, apiFiles android.Paths) android.Paths { - var sortedSrcFiles android.Paths - - for i, apiScope := range allApiScopes { - for _, srcFileInfo := range srcFilesInfo { - if srcFileInfo.ApiFile.Base() == scopeOrderedSourceFileNames[i] || srcFileInfo.ApiSurface == apiScope.name { - sortedSrcFiles = append(sortedSrcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String())) - } - } - // TODO: b/300964421 - Remove when api_files property is removed - for _, apiFileName := range apiFiles { - if apiFileName.Base() == scopeOrderedSourceFileNames[i] { - sortedSrcFiles = append(sortedSrcFiles, apiFileName) - } +func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo { + for _, srcFileInfo := range srcFilesInfo { + if srcFileInfo.ApiSurface == "" { + ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile) } } + sort.Slice(srcFilesInfo, func(i, j int) bool { + return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface] + }) - if len(srcFilesInfo)+len(apiFiles) != len(sortedSrcFiles) { - var srcFiles android.Paths - for _, srcFileInfo := range srcFilesInfo { - srcFiles = append(srcFiles, srcFileInfo.ApiFile) - } - ctx.ModuleErrorf("Unrecognizable source file found within %s", append(srcFiles, apiFiles...)) - } - - return sortedSrcFiles + return srcFilesInfo } func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1892,16 +1875,12 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { } }) - // Add the api_files inputs - // These are api files in the module subdirectory, which are not provided by - // java_api_contribution but provided directly as module property. - var apiFiles android.Paths - for _, api := range al.properties.Api_files { - apiFiles = append(apiFiles, android.PathForModuleSrc(ctx, api)) + srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo) + var srcFiles android.Paths + for _, srcFileInfo := range srcFilesInfo { + srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String())) } - srcFiles := al.sortApiFilesByApiScope(ctx, srcFilesInfo, apiFiles) - if srcFiles == nil && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName()) } @@ -3067,17 +3046,6 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.Bp2buildMutatorContext } } - protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition]) - // Soong does not differentiate between a java_library and the Bazel equivalent of - // a java_proto_library + proto_library pair. Instead, in Soong proto sources are - // listed directly in the srcs of a java_library, and the classes produced - // by protoc are included directly in the resulting JAR. Thus upstream dependencies - // that depend on a java_library with proto sources can link directly to the protobuf API, - // and so this should be a static dependency. - if protoDepLabel != nil { - staticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel)) - } - depLabels := &javaDependencyLabels{} depLabels.Deps = deps @@ -3093,6 +3061,20 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.Bp2buildMutatorContext } depLabels.StaticDeps.Append(staticDeps) + var additionalProtoDeps bazel.LabelListAttribute + additionalProtoDeps.Append(depLabels.Deps) + additionalProtoDeps.Append(depLabels.StaticDeps) + protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition], additionalProtoDeps) + // Soong does not differentiate between a java_library and the Bazel equivalent of + // a java_proto_library + proto_library pair. Instead, in Soong proto sources are + // listed directly in the srcs of a java_library, and the classes produced + // by protoc are included directly in the resulting JAR. Thus upstream dependencies + // that depend on a java_library with proto sources can link directly to the protobuf API, + // and so this should be a static dependency. + if protoDepLabel != nil { + depLabels.StaticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel)) + } + hasKotlin := !kotlinSrcs.IsEmpty() commonAttrs.kotlinAttributes = &kotlinAttributes{ Kotlincflags: &m.properties.Kotlincflags, diff --git a/java/java_test.go b/java/java_test.go index 2ee05ec73..d51604a25 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1885,7 +1885,6 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { name: "bar2", api_surface: "system", api_contributions: ["foo1", "foo2"], - api_files: ["api1/current.txt", "api2/current.txt"] } `, map[string][]byte{ @@ -1903,7 +1902,7 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { }, { moduleName: "bar2", - sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt"}, + sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"}, }, } for _, c := range testcases { @@ -1975,7 +1974,6 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { api_surface: "system", defaults:["baz1", "baz2"], api_contributions: ["foo4"], - api_files: ["api1/current.txt", "api2/current.txt"] } `, map[string][]byte{ @@ -2000,7 +1998,7 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { { moduleName: "bar3", // API text files need to be sorted from the narrower api scope to the wider api scope - sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt", "c/system-current.txt", "d/system-current.txt"}, + sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"}, }, } for _, c := range testcases { @@ -2265,27 +2263,26 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar") } -func TestJavaApiLibraryFilegroupInput(t *testing.T) { - ctx, _ := testJavaWithFS(t, ` - filegroup { - name: "default_current.txt", - srcs: ["current.txt"], +func TestTransitiveSrcFiles(t *testing.T) { + ctx, _ := testJava(t, ` + java_library { + name: "a", + srcs: ["a.java"], } - - java_api_library { - name: "foo", - api_files: [":default_current.txt"], + java_library { + name: "b", + srcs: ["b.java"], } - `, - map[string][]byte{ - "current.txt": nil, - }) - - m := ctx.ModuleForTests("foo", "android_common") - outputs := fmt.Sprint(m.AllOutputs()) - if !strings.Contains(outputs, "foo/foo.jar") { - t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar") - } + java_library { + name: "c", + srcs: ["c.java"], + libs: ["a"], + static_libs: ["b"], + } + `) + c := ctx.ModuleForTests("c", "android_common").Module() + transitiveSrcFiles := android.Paths(ctx.ModuleProvider(c, JavaInfoProvider).(JavaInfo).TransitiveSrcFiles.ToList()) + android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings()) } func TestTradefedOptions(t *testing.T) { @@ -2423,3 +2420,30 @@ func TestJavaApiContributionImport(t *testing.T) { sourceFilesFlag := "--source-files current.txt" android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) } + +func TestJavaApiLibraryApiFilesSorting(t *testing.T) { + ctx, _ := testJava(t, ` + java_api_library { + name: "foo", + api_contributions: [ + "system-server-api-stubs-docs-non-updatable.api.contribution", + "test-api-stubs-docs-non-updatable.api.contribution", + "system-api-stubs-docs-non-updatable.api.contribution", + "module-lib-api-stubs-docs-non-updatable.api.contribution", + "api-stubs-docs-non-updatable.api.contribution", + ], + } + `) + m := ctx.ModuleForTests("foo", "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + + // Api files are sorted from the narrowest api scope to the widest api scope. + // test api and module lib api surface do not have subset/superset relationship, + // but they will never be passed as inputs at the same time. + sourceFilesFlag := "--source-files default/java/api/current.txt " + + "default/java/api/system-current.txt default/java/api/test-current.txt " + + "default/java/api/module-lib-current.txt default/java/api/system-server-current.txt" + android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag) +} diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index ade739552..02a2298cd 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -57,6 +57,9 @@ type platformBootclasspathModule struct { // Path to the monolithic hiddenapi-unsupported.csv file. hiddenAPIMetadataCSV android.OutputPath + + // Path to a srcjar containing all the transitive sources of the bootclasspath. + srcjar android.OutputPath } type platformBootclasspathProperties struct { @@ -95,6 +98,8 @@ func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, er return android.Paths{b.hiddenAPIIndexCSV}, nil case "hiddenapi-metadata.csv": return android.Paths{b.hiddenAPIMetadataCSV}, nil + case ".srcjar": + return android.Paths{b.srcjar}, nil } return nil, fmt.Errorf("unknown tag %s", tag) @@ -173,6 +178,18 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo allModules = append(allModules, apexModules...) b.configuredModules = allModules + var transitiveSrcFiles android.Paths + for _, module := range allModules { + depInfo := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) + if depInfo.TransitiveSrcFiles != nil { + transitiveSrcFiles = append(transitiveSrcFiles, depInfo.TransitiveSrcFiles.ToList()...) + } + } + jarArgs := resourcePathsToJarArgs(transitiveSrcFiles) + jarArgs = append(jarArgs, "-srcjar") // Move srcfiles to the right package + b.srcjar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-transitive.srcjar").OutputPath + TransformResourcesToJar(ctx, b.srcjar, jarArgs, transitiveSrcFiles) + // Gather all the fragments dependencies. b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index ff2da4bb2..37ff6395c 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -81,6 +81,15 @@ func TestPlatformBootclasspath(t *testing.T) { RunTest(t) }) + fooSourceSrc := "source/a.java" + barSrc := "a.java" + + checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) { + t.Helper() + srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar") + android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar") + android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings()) + } t.Run("source", func(t *testing.T) { result := android.GroupFixturePreparers( preparer, @@ -91,6 +100,10 @@ func TestPlatformBootclasspath(t *testing.T) { "platform:foo", "platform:bar", }) + checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ + fooSourceSrc, + barSrc, + }) }) t.Run("prebuilt", func(t *testing.T) { @@ -103,6 +116,10 @@ func TestPlatformBootclasspath(t *testing.T) { "platform:prebuilt_foo", "platform:bar", }) + checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ + // TODO(b/151360309): This should also have the srcs for prebuilt_foo + barSrc, + }) }) t.Run("source+prebuilt - source preferred", func(t *testing.T) { @@ -116,6 +133,10 @@ func TestPlatformBootclasspath(t *testing.T) { "platform:foo", "platform:bar", }) + checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ + fooSourceSrc, + barSrc, + }) }) t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) { @@ -129,6 +150,10 @@ func TestPlatformBootclasspath(t *testing.T) { "platform:prebuilt_foo", "platform:bar", }) + checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ + // TODO(b/151360309): This should also have the srcs for prebuilt_foo + barSrc, + }) }) t.Run("dex import", func(t *testing.T) { @@ -146,6 +171,10 @@ func TestPlatformBootclasspath(t *testing.T) { "platform:prebuilt_foo", "platform:bar", }) + checkSrcJarInputs(t, result, "platform-bootclasspath", []string{ + // TODO(b/151360309): This should also have the srcs for prebuilt_foo + barSrc, + }) }) } diff --git a/java/proto.go b/java/proto.go index 2ed7b27e9..48adadcc9 100644 --- a/java/proto.go +++ b/java/proto.go @@ -151,11 +151,17 @@ type protoAttributes struct { // a specific .proto file module explicitly. Transitive_deps bazel.LabelListAttribute + // This is the libs and the static_libs of the original java_library module. + // On the bazel side, after proto sources are generated in java_*_proto_library, a java_library + // will compile them. The libs and static_libs from the original java_library module need + // to be linked because they are necessary in compile-time classpath. + Additional_proto_deps bazel.LabelListAttribute + Sdk_version bazel.StringAttribute Java_version bazel.StringAttribute } -func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label { +func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute, AdditionalProtoDeps bazel.LabelListAttribute) *bazel.Label { protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs) if !ok { return nil @@ -184,10 +190,11 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze } protoAttrs := &protoAttributes{ - Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs), - Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs), - Java_version: bazel.StringAttribute{Value: m.properties.Java_version}, - Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version}, + Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs), + Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs), + Additional_proto_deps: AdditionalProtoDeps, + Java_version: bazel.StringAttribute{Value: m.properties.Java_version}, + Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version}, } name := m.Name() + suffix diff --git a/java/sdk_library.go b/java/sdk_library.go index 27f862662..e410a41fa 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -286,6 +286,17 @@ func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string { return list } +// Method that maps the apiScopes properties to the index of each apiScopes elements. +// apiScopes property to be used as the key can be specified with the input accessor. +// Only a string property of apiScope can be used as the key of the map. +func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int { + ret := make(map[string]int) + for i, scope := range scopes { + ret[accessor(scope)] = i + } + return ret +} + var ( scopeByName = make(map[string]*apiScope) allScopeNames []string diff --git a/java/testing.go b/java/testing.go index f2bcccfce..98bea7f14 100644 --- a/java/testing.go +++ b/java/testing.go @@ -424,30 +424,80 @@ func gatherRequiredDepsForTest() string { `, extra) } - extraApiLibraryModules := map[string]string{ - "android_stubs_current.from-text": "api/current.txt", - "android_system_stubs_current.from-text": "api/system-current.txt", - "android_test_stubs_current.from-text": "api/test-current.txt", - "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt", - "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt", - "android_system_server_stubs_current.from-text": "api/system-server-current.txt", - "core.current.stubs.from-text": "api/current.txt", - "legacy.core.platform.api.stubs.from-text": "api/current.txt", - "stable.core.platform.api.stubs.from-text": "api/current.txt", - "core-lambda-stubs.from-text": "api/current.txt", - "android-non-updatable.stubs.from-text": "api/current.txt", - "android-non-updatable.stubs.system.from-text": "api/system-current.txt", - "android-non-updatable.stubs.test.from-text": "api/test-current.txt", - "android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt", + type apiContributionStruct struct { + name string + apiSurface string + apiFile string } - for libName, apiFile := range extraApiLibraryModules { + var publicApiContribution = apiContributionStruct{ + name: "api-stubs-docs-non-updatable.api.contribution", + apiSurface: "public", + apiFile: "api/current.txt", + } + var systemApiContribution = apiContributionStruct{ + name: "system-api-stubs-docs-non-updatable.api.contribution", + apiSurface: "system", + apiFile: "api/system-current.txt", + } + var testApiContribution = apiContributionStruct{ + name: "test-api-stubs-docs-non-updatable.api.contribution", + apiSurface: "test", + apiFile: "api/test-current.txt", + } + var moduleLibApiContribution = apiContributionStruct{ + name: "module-lib-api-stubs-docs-non-updatable.api.contribution", + apiSurface: "module-lib", + apiFile: "api/module-lib-current.txt", + } + var systemServerApiContribution = apiContributionStruct{ + // This module does not exist but is named this way for consistency + name: "system-server-api-stubs-docs-non-updatable.api.contribution", + apiSurface: "system-server", + apiFile: "api/system-server-current.txt", + } + var apiContributionStructs = []apiContributionStruct{ + publicApiContribution, + systemApiContribution, + testApiContribution, + moduleLibApiContribution, + systemServerApiContribution, + } + + extraApiLibraryModules := map[string]apiContributionStruct{ + "android_stubs_current.from-text": publicApiContribution, + "android_system_stubs_current.from-text": systemApiContribution, + "android_test_stubs_current.from-text": testApiContribution, + "android_module_lib_stubs_current.from-text": moduleLibApiContribution, + "android_module_lib_stubs_current_full.from-text": moduleLibApiContribution, + "android_system_server_stubs_current.from-text": systemServerApiContribution, + "core.current.stubs.from-text": publicApiContribution, + "legacy.core.platform.api.stubs.from-text": publicApiContribution, + "stable.core.platform.api.stubs.from-text": publicApiContribution, + "core-lambda-stubs.from-text": publicApiContribution, + "android-non-updatable.stubs.from-text": publicApiContribution, + "android-non-updatable.stubs.system.from-text": systemApiContribution, + "android-non-updatable.stubs.test.from-text": testApiContribution, + "android-non-updatable.stubs.module_lib.from-text": moduleLibApiContribution, + } + + for _, apiContribution := range apiContributionStructs { + bp += fmt.Sprintf(` + java_api_contribution { + name: "%s", + api_surface: "%s", + api_file: "%s", + } + `, apiContribution.name, apiContribution.apiSurface, apiContribution.apiFile) + } + + for libName, apiContribution := range extraApiLibraryModules { bp += fmt.Sprintf(` java_api_library { name: "%s", - api_files: ["%s"], + api_contributions: ["%s"], } - `, libName, apiFile) + `, libName, apiContribution.name) } bp += ` diff --git a/rust/afdo_test.go b/rust/afdo_test.go index 80327af2a..0cdf70491 100644 --- a/rust/afdo_test.go +++ b/rust/afdo_test.go @@ -54,8 +54,8 @@ func TestAfdoEnabled(t *testing.T) { expectedCFlag := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo.afdo") - if !strings.Contains(foo.RuleParams.Command, expectedCFlag) { - t.Errorf("Expected 'foo' to enable afdo, but did not find %q in command %q", expectedCFlag, foo.RuleParams.Command) + if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) { + t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"]) } } @@ -96,17 +96,17 @@ func TestAfdoEnabledWithMultiArchs(t *testing.T) { rustMockedFiles.AddToFixture(), ).RunTestWithBp(t, bp) - fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Description("rustc") - fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Description("rustc") + fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc") + fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc") expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm.afdo") expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm64.afdo") - if !strings.Contains(fooArm.RuleParams.Command, expectedCFlagArm) { - t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in command %q", expectedCFlagArm, fooArm.RuleParams.Command) + if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) { + t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"]) } - if !strings.Contains(fooArm64.RuleParams.Command, expectedCFlagArm64) { - t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in command %q", expectedCFlagArm64, fooArm.RuleParams.Command) + if !strings.Contains(fooArm64.Args["rustcFlags"], expectedCFlagArm64) { + t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm64, fooArm64.Args["rustcFlags"]) } } diff --git a/rust/binary.go b/rust/binary.go index 353381d78..aee4da699 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -149,6 +149,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path flags.RustFlags = append(flags.RustFlags, deps.depFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...) if binary.stripper.NeedsStrip(ctx) { strippedOutputFile := outputFile @@ -159,7 +160,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path } binary.baseCompiler.unstrippedOutputFile = outputFile - ret.kytheFile = TransformSrcToBinary(ctx, binary, crateRootPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrcToBinary(ctx, crateRootPath, deps, flags, outputFile).kytheFile return ret } diff --git a/rust/binary_test.go b/rust/binary_test.go index ab1d2bc36..dff94ac95 100644 --- a/rust/binary_test.go +++ b/rust/binary_test.go @@ -135,7 +135,7 @@ func TestBinaryFlags(t *testing.T) { fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc") - flags := fizzBuzz.RuleParams.Command + flags := fizzBuzz.Args["rustcFlags"] if strings.Contains(flags, "--test") { t.Errorf("extra --test flag, rustcFlags: %#v", flags) } @@ -150,11 +150,11 @@ func TestBootstrap(t *testing.T) { bootstrap: true, }`) - foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc") + foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustLink") flag := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker64" - if !strings.Contains(foo.RuleParams.Command, flag) { - t.Errorf("missing link flag to use bootstrap linker, expecting %#v, command: %#v", flag, foo.RuleParams.Command) + if !strings.Contains(foo.Args["linkFlags"], flag) { + t.Errorf("missing link flag to use bootstrap linker, expecting %#v, linkFlags: %#v", flag, foo.Args["linkFlags"]) } } @@ -167,17 +167,19 @@ func TestStaticBinaryFlags(t *testing.T) { }`) fizzOut := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc") + fizzOutLink := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustLink") fizzMod := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module) - flags := fizzOut.RuleParams.Command + flags := fizzOut.Args["rustcFlags"] + linkFlags := fizzOutLink.Args["linkFlags"] if !strings.Contains(flags, "-C relocation-model=static") { - t.Errorf("static binary missing '-C relocation-model=static' in command, found: %#v", flags) + t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags) } if !strings.Contains(flags, "-C panic=abort") { - t.Errorf("static binary missing '-C panic=abort' in command, found: %#v", flags) + t.Errorf("static binary missing '-C panic=abort' in rustcFlags, found: %#v", flags) } - if !strings.Contains(flags, "-static") { - t.Errorf("static binary missing '-static' in command, found: %#v", flags) + if !strings.Contains(linkFlags, "-static") { + t.Errorf("static binary missing '-static' in linkFlags, found: %#v", flags) } if !android.InList("libc", fizzMod.Properties.AndroidMkStaticLibs) { @@ -199,9 +201,10 @@ func TestLinkObjects(t *testing.T) { name: "libfoo", }`) - fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustc") - if !strings.Contains(fizzBuzz.RuleParams.Command, "/libfoo.so") { - t.Errorf("missing shared dependency 'libfoo.so' in command: %#v", fizzBuzz.RuleParams.Command) + fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustLink") + linkFlags := fizzBuzz.Args["linkFlags"] + if !strings.Contains(linkFlags, "/libfoo.so") { + t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags) } } diff --git a/rust/builder.go b/rust/builder.go index 07405183e..9614d4f8f 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -15,7 +15,6 @@ package rust import ( - "fmt" "path/filepath" "strings" @@ -26,6 +25,54 @@ import ( ) var ( + _ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc") + _ = pctx.SourcePathVariable("mkcraterspCmd", "build/soong/scripts/mkcratersp.py") + rustc = pctx.AndroidStaticRule("rustc", + blueprint.RuleParams{ + Command: "$envVars $rustcCmd " + + "-C linker=$mkcraterspCmd " + + "--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" + + " && grep \"^$out:\" $out.d.raw > $out.d", + CommandDeps: []string{"$rustcCmd", "$mkcraterspCmd"}, + // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633 + // Rustc emits unneeded dependency lines for the .d and input .rs files. + // Those extra lines cause ninja warning: + // "warning: depfile has multiple output paths" + // For ninja, we keep/grep only the dependency rule for the rust $out file. + Deps: blueprint.DepsGCC, + Depfile: "$out.d", + }, + "rustcFlags", "libFlags", "envVars") + rustLink = pctx.AndroidStaticRule("rustLink", + blueprint.RuleParams{ + Command: "${config.RustLinker} -o $out ${crtBegin} ${earlyLinkFlags} @$in ${linkFlags} ${crtEnd}", + }, + "earlyLinkFlags", "linkFlags", "crtBegin", "crtEnd") + + _ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc") + rustdoc = pctx.AndroidStaticRule("rustdoc", + blueprint.RuleParams{ + Command: "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " + + "touch $out", + CommandDeps: []string{"$rustdocCmd"}, + }, + "rustdocFlags", "outDir", "envVars") + + _ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver") + clippyDriver = pctx.AndroidStaticRule("clippy", + blueprint.RuleParams{ + Command: "$envVars $clippyCmd " + + // Because clippy-driver uses rustc as backend, we need to have some output even during the linting. + // Use the metadata output as it has the smallest footprint. + "--emit metadata -o $out --emit dep-info=$out.d.raw $in ${libFlags} " + + "$rustcFlags $clippyFlags" + + " && grep \"^$out:\" $out.d.raw > $out.d", + CommandDeps: []string{"$clippyCmd"}, + Deps: blueprint.DepsGCC, + Depfile: "$out.d", + }, + "rustcFlags", "libFlags", "clippyFlags", "envVars") + zip = pctx.AndroidStaticRule("zip", blueprint.RuleParams{ Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp", @@ -34,7 +81,7 @@ var ( RspfileContent: "$in", }) - cpDir = pctx.AndroidStaticRule("cpDir", + cp = pctx.AndroidStaticRule("cp", blueprint.RuleParams{ Command: "cp `cat $outDir.rsp` $outDir", Rspfile: "${outDir}.rsp", @@ -42,12 +89,6 @@ var ( }, "outDir") - cp = pctx.AndroidStaticRule("cp", - blueprint.RuleParams{ - Command: "rm -f $out && cp $in $out", - Description: "cp $out", - }) - // Cross-referencing: _ = pctx.SourcePathVariable("rustExtractor", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/rust_extractor") @@ -55,6 +96,23 @@ var ( func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() }) _ = pctx.VariableFunc("kytheCuEncoding", func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() }) + _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json") + kytheExtract = pctx.AndroidStaticRule("kythe", + blueprint.RuleParams{ + Command: `KYTHE_CORPUS=${kytheCorpus} ` + + `KYTHE_OUTPUT_FILE=$out ` + + `KYTHE_VNAMES=$kytheVnames ` + + `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` + + `KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` + + `$rustExtractor $envVars ` + + `$rustcCmd ` + + `-C linker=true ` + + `$in ${libFlags} $rustcFlags`, + CommandDeps: []string{"$rustExtractor", "$kytheVnames"}, + Rspfile: "${out}.rsp", + RspfileContent: "$in", + }, + "rustcFlags", "libFlags", "envVars") ) type buildOutput struct { @@ -66,40 +124,40 @@ func init() { pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") } -func TransformSrcToBinary(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "bin") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin") } -func TransformSrctoRlib(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "rlib") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib") } -func TransformSrctoDylib(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "dylib") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib") } -func TransformSrctoStatic(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "staticlib") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib") } -func TransformSrctoShared(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "cdylib") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib") } -func TransformSrctoProcMacro(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, +func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "proc-macro") + return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro") } func rustLibsToPaths(libs RustLibraries) android.Paths { @@ -110,46 +168,28 @@ func rustLibsToPaths(libs RustLibraries) android.Paths { return paths } -func makeLibFlags(deps PathDeps, ruleCmd *android.RuleBuilderCommand) []string { +func makeLibFlags(deps PathDeps) []string { var libFlags []string // Collect library/crate flags - for _, lib := range deps.Rlibs.ToListDirect() { - libPath := ruleCmd.PathForInput(lib.Path) - libFlags = append(libFlags, "--extern "+lib.CrateName+"="+libPath) + for _, lib := range deps.RLibs { + libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String()) } - for _, lib := range deps.Dylibs.ToListDirect() { - libPath := ruleCmd.PathForInput(lib.Path) - libFlags = append(libFlags, "--extern "+lib.CrateName+"="+libPath) + for _, lib := range deps.DyLibs { + libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String()) } - for _, procMacro := range deps.ProcMacros.ToListDirect() { - procMacroPath := ruleCmd.PathForInput(procMacro.Path) - libFlags = append(libFlags, "--extern "+procMacro.CrateName+"="+procMacroPath) + for _, proc_macro := range deps.ProcMacros { + libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String()) } for _, path := range deps.linkDirs { - libFlags = append(libFlags, "-L "+ruleCmd.PathForInput(path)) + libFlags = append(libFlags, "-L "+path) } return libFlags } -func collectImplicits(deps PathDeps) android.Paths { - depPaths := android.Paths{} - depPaths = append(depPaths, rustLibsToPaths(deps.Rlibs.ToList())...) - depPaths = append(depPaths, rustLibsToPaths(deps.Dylibs.ToList())...) - depPaths = append(depPaths, rustLibsToPaths(deps.ProcMacros.ToList())...) - depPaths = append(depPaths, deps.AfdoProfiles...) - depPaths = append(depPaths, deps.WholeStaticLibs...) - depPaths = append(depPaths, deps.SrcDeps...) - depPaths = append(depPaths, deps.srcProviderFiles...) - depPaths = append(depPaths, deps.LibDeps...) - depPaths = append(depPaths, deps.linkObjects...) - depPaths = append(depPaths, deps.BuildToolSrcDeps...) - return depPaths -} - -func rustEnvVars(ctx ModuleContext, deps PathDeps, cmd *android.RuleBuilderCommand) []string { +func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { var envVars []string // libstd requires a specific environment variable to be set. This is @@ -163,17 +203,15 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps, cmd *android.RuleBuilderComma moduleGenDir := ctx.RustModule().compiler.CargoOutDir() // We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this) // assumes that paths are relative to the source file. - var outDir string - if filepath.IsAbs(moduleGenDir.String()) { - // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything. - outDir = moduleGenDir.String() - } else if moduleGenDir.Valid() { + var outDirPrefix string + if !filepath.IsAbs(moduleGenDir.String()) { // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/') - outDir = filepath.Join("$$PWD/", cmd.PathForInput(moduleGenDir.Path())) + outDirPrefix = "$$PWD/" } else { - outDir = "$$PWD/" + // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything. + outDirPrefix = "" } - envVars = append(envVars, "OUT_DIR="+outDir) + envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String())) } else { // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value. envVars = append(envVars, "OUT_DIR=out") @@ -204,7 +242,7 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps, cmd *android.RuleBuilderComma } } - envVars = append(envVars, "AR="+cmd.PathForTool(deps.Llvm_ar)) + envVars = append(envVars, "AR=${cc_config.ClangBin}/llvm-ar") if ctx.Darwin() { envVars = append(envVars, "ANDROID_RUST_DARWIN=true") @@ -213,18 +251,21 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps, cmd *android.RuleBuilderComma return envVars } -func transformSrctoCrate(ctx ModuleContext, comp compiler, main android.Path, deps PathDeps, flags Flags, +func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, crateType string) buildOutput { var inputs android.Paths + var implicits, linkImplicits, linkOrderOnly android.Paths var output buildOutput var rustcFlags, linkFlags []string - var earlyLinkFlags []string + var earlyLinkFlags string output.outputFile = outputFile crateName := ctx.RustModule().CrateName() targetTriple := ctx.toolchain().RustTriple() + envVars := rustEnvVars(ctx, deps) + inputs = append(inputs, main) // Collect rustc flags @@ -245,6 +286,7 @@ func transformSrctoCrate(ctx ModuleContext, comp compiler, main android.Path, de // Enable incremental compilation if requested by user if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") { incrementalPath := android.PathForOutput(ctx, "rustc").String() + rustcFlags = append(rustcFlags, "-Cincremental="+incrementalPath) } @@ -256,16 +298,36 @@ func transformSrctoCrate(ctx ModuleContext, comp compiler, main android.Path, de // Collect linker flags if !ctx.Darwin() { - earlyLinkFlags = append(earlyLinkFlags, "-Wl,--as-needed") + earlyLinkFlags = "-Wl,--as-needed" + } + + linkFlags = append(linkFlags, flags.GlobalLinkFlags...) + linkFlags = append(linkFlags, flags.LinkFlags...) + + // Check if this module needs to use the bootstrap linker + if ctx.RustModule().Bootstrap() && !ctx.RustModule().InRecovery() && !ctx.RustModule().InRamdisk() && !ctx.RustModule().InVendorRamdisk() { + dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker" + if ctx.toolchain().Is64Bit() { + dynamicLinker += "64" + } + linkFlags = append(linkFlags, dynamicLinker) } + libFlags := makeLibFlags(deps) + // Collect dependencies - var linkImplicits android.Paths - implicits := collectImplicits(deps) - toolImplicits := android.Concat(deps.BuildToolDeps) + implicits = append(implicits, rustLibsToPaths(deps.RLibs)...) + implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...) + implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...) + implicits = append(implicits, deps.AfdoProfiles...) + implicits = append(implicits, deps.srcProviderFiles...) + implicits = append(implicits, deps.WholeStaticLibs...) + + linkImplicits = append(linkImplicits, deps.LibDeps...) linkImplicits = append(linkImplicits, deps.CrtBegin...) linkImplicits = append(linkImplicits, deps.CrtEnd...) - implicits = append(implicits, comp.compilationSourcesAndData(ctx)...) + + linkOrderOnly = append(linkOrderOnly, deps.linkObjects...) if len(deps.SrcDeps) > 0 { moduleGenDir := ctx.RustModule().compiler.CargoOutDir() @@ -280,7 +342,7 @@ func transformSrctoCrate(ctx ModuleContext, comp compiler, main android.Path, de } ctx.Build(pctx, android.BuildParams{ - Rule: cpDir, + Rule: cp, Description: "cp " + moduleGenDir.Path().Rel(), Outputs: outputs, Inputs: deps.SrcDeps, @@ -292,176 +354,88 @@ func transformSrctoCrate(ctx ModuleContext, comp compiler, main android.Path, de } if flags.Clippy { - // TODO(b/298461712) remove this hack to let slim manifest branches build - if deps.Clippy_driver == nil { - deps.Clippy_driver = config.RustPath(ctx, "bin/clippy-driver") - } - - clippyRule := getRuleBuilder(ctx, pctx, false, "clippy") - clippyCmd := clippyRule.Command() clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy") - clippyDepInfoFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy.d.raw") - clippyDepFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy.d") - - clippyCmd. - Flags(rustEnvVars(ctx, deps, clippyCmd)). - Tool(deps.Clippy_driver). - Flag("--emit metadata"). - FlagWithOutput("-o ", clippyFile). - FlagWithOutput("--emit dep-info=", clippyDepInfoFile). - Inputs(inputs). - Flags(makeLibFlags(deps, clippyCmd)). - Flags(rustcFlags). - Flags(flags.ClippyFlags). - ImplicitTools(toolImplicits). - Implicits(implicits) - - depfileCreationCmd := clippyRule.Command() - depfileCreationCmd. - Flag(fmt.Sprintf( - `grep "^%s:" %s >`, - depfileCreationCmd.PathForOutput(clippyFile), - depfileCreationCmd.PathForOutput(clippyDepInfoFile), - )). - DepFile(clippyDepFile) - - clippyRule.BuildWithUnescapedNinjaVars("clippy", "clippy "+main.Rel()) - + ctx.Build(pctx, android.BuildParams{ + Rule: clippyDriver, + Description: "clippy " + main.Rel(), + Output: clippyFile, + Inputs: inputs, + Implicits: implicits, + Args: map[string]string{ + "rustcFlags": strings.Join(rustcFlags, " "), + "libFlags": strings.Join(libFlags, " "), + "clippyFlags": strings.Join(flags.ClippyFlags, " "), + "envVars": strings.Join(envVars, " "), + }, + }) // Declare the clippy build as an implicit dependency of the original crate. implicits = append(implicits, clippyFile) } - sboxDirectory := "rustc" - rustSboxOutputFile := android.PathForModuleOut(ctx, sboxDirectory, outputFile.Base()) - depFile := android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".d") - depInfoFile := android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".d.raw") + rustcOutputFile := outputFile var rustcImplicitOutputs android.WritablePaths - - sandboxedCompilation := comp.crateRoot(ctx) != nil - rustcRule := getRuleBuilder(ctx, pctx, sandboxedCompilation, sboxDirectory) - rustcCmd := rustcRule.Command() - - linkFlags = append(linkFlags, flags.GlobalLinkFlags...) - linkFlags = append(linkFlags, flags.LinkFlags...) - linkFlags = append(linkFlags, rustcCmd.PathsForInputs(deps.linkObjects)...) - - // Check if this module needs to use the bootstrap linker - if ctx.RustModule().Bootstrap() && !ctx.RustModule().InRecovery() && !ctx.RustModule().InRamdisk() && !ctx.RustModule().InVendorRamdisk() { - dynamicLinker := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker" - if ctx.toolchain().Is64Bit() { - dynamicLinker += "64" - } - linkFlags = append(linkFlags, dynamicLinker) - } - - libFlags := makeLibFlags(deps, rustcCmd) - usesLinker := crateType == "bin" || crateType == "dylib" || crateType == "cdylib" || crateType == "proc-macro" if usesLinker { - rustSboxOutputFile = android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".rsp") + rustcOutputFile = android.PathForModuleOut(ctx, outputFile.Base()+".rsp") rustcImplicitOutputs = android.WritablePaths{ - android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".whole.a"), - android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".a"), + android.PathForModuleOut(ctx, rustcOutputFile.Base()+".whole.a"), + android.PathForModuleOut(ctx, rustcOutputFile.Base()+".a"), } - } - // TODO(b/298461712) remove this hack to let slim manifest branches build - if deps.Rustc == nil { - deps.Rustc = config.RustPath(ctx, "bin/rustc") } - rustcCmd. - Flags(rustEnvVars(ctx, deps, rustcCmd)). - Tool(deps.Rustc). - FlagWithInput("-C linker=", android.PathForSource(ctx, "build", "soong", "scripts", "mkcratersp.py")). - Flag("--emit link"). - Flag("-o"). - Output(rustSboxOutputFile). - FlagWithOutput("--emit dep-info=", depInfoFile). - Inputs(inputs). - Flags(libFlags). - ImplicitTools(toolImplicits). - Implicits(implicits). - Flags(rustcFlags). - ImplicitOutputs(rustcImplicitOutputs) - - depfileCreationCmd := rustcRule.Command() - depfileCreationCmd. - Flag(fmt.Sprintf( - `grep "^%s:" %s >`, - depfileCreationCmd.PathForOutput(rustSboxOutputFile), - depfileCreationCmd.PathForOutput(depInfoFile), - )). - DepFile(depFile) - - if !usesLinker { - ctx.Build(pctx, android.BuildParams{ - Rule: cp, - Input: rustSboxOutputFile, - Output: outputFile, - }) - } else { - // TODO: delmerico - separate rustLink into its own rule - // mkcratersp.py hardcodes paths to files within the sandbox, so - // those need to be renamed/symlinked to something in the rustLink sandbox - // if we want to separate the rules - linkerSboxOutputFile := android.PathForModuleOut(ctx, sboxDirectory, outputFile.Base()) - rustLinkCmd := rustcRule.Command() - rustLinkCmd. - Tool(deps.Clang). - Flag("-o"). - Output(linkerSboxOutputFile). - Inputs(deps.CrtBegin). - Flags(earlyLinkFlags). - FlagWithInput("@", rustSboxOutputFile). - Flags(linkFlags). - Inputs(deps.CrtEnd). - ImplicitTools(toolImplicits). - Implicits(rustcImplicitOutputs.Paths()). - Implicits(implicits). - Implicits(linkImplicits) + ctx.Build(pctx, android.BuildParams{ + Rule: rustc, + Description: "rustc " + main.Rel(), + Output: rustcOutputFile, + Inputs: inputs, + Implicits: implicits, + ImplicitOutputs: rustcImplicitOutputs, + Args: map[string]string{ + "rustcFlags": strings.Join(rustcFlags, " "), + "libFlags": strings.Join(libFlags, " "), + "envVars": strings.Join(envVars, " "), + }, + }) + + if usesLinker { ctx.Build(pctx, android.BuildParams{ - Rule: cp, - Input: linkerSboxOutputFile, - Output: outputFile, + Rule: rustLink, + Description: "rustLink " + main.Rel(), + Output: outputFile, + Inputs: android.Paths{rustcOutputFile}, + Implicits: linkImplicits, + OrderOnly: linkOrderOnly, + Args: map[string]string{ + "earlyLinkFlags": earlyLinkFlags, + "linkFlags": strings.Join(linkFlags, " "), + "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "), + "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "), + }, }) } - rustcRule.BuildWithUnescapedNinjaVars("rustc", "rustc "+main.Rel()) - if flags.EmitXrefs { - kytheRule := getRuleBuilder(ctx, pctx, false, "kythe") - kytheCmd := kytheRule.Command() kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip") - kytheCmd. - Flag("KYTHE_CORPUS=${kytheCorpus}"). - FlagWithOutput("KYTHE_OUTPUT_FILE=", kytheFile). - FlagWithInput("KYTHE_VNAMES=", android.PathForSource(ctx, "build", "soong", "vnames.json")). - Flag("KYTHE_KZIP_ENCODING=${kytheCuEncoding}"). - Flag("KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative"). - Tool(ctx.Config().PrebuiltBuildTool(ctx, "rust_extractor")). - Flags(rustEnvVars(ctx, deps, kytheCmd)). - Tool(deps.Rustc). - Flag("-C linker=true"). - Inputs(inputs). - Flags(makeLibFlags(deps, kytheCmd)). - Flags(rustcFlags). - ImplicitTools(toolImplicits). - Implicits(implicits) - kytheRule.BuildWithUnescapedNinjaVars("kythe", "Xref Rust extractor "+main.Rel()) + ctx.Build(pctx, android.BuildParams{ + Rule: kytheExtract, + Description: "Xref Rust extractor " + main.Rel(), + Output: kytheFile, + Inputs: inputs, + Implicits: implicits, + Args: map[string]string{ + "rustcFlags": strings.Join(rustcFlags, " "), + "libFlags": strings.Join(libFlags, " "), + "envVars": strings.Join(envVars, " "), + }, + }) output.kytheFile = kytheFile } return output } -func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags) android.ModuleOutPath { - // TODO(b/298461712) remove this hack to let slim manifest branches build - if deps.Rustdoc == nil { - deps.Rustdoc = config.RustPath(ctx, "bin/rustdoc") - } - - rustdocRule := getRuleBuilder(ctx, pctx, false, "rustdoc") - rustdocCmd := rustdocRule.Command() +func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, + flags Flags) android.ModuleOutPath { rustdocFlags := append([]string{}, flags.RustdocFlags...) rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null") @@ -480,7 +454,7 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags) a crateName := ctx.RustModule().CrateName() rustdocFlags = append(rustdocFlags, "--crate-name "+crateName) - rustdocFlags = append(rustdocFlags, makeLibFlags(deps, rustdocCmd)...) + rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...) docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp") // Silence warnings about renamed lints for third-party crates @@ -496,26 +470,18 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags) a // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146 docDir := android.PathForOutput(ctx, "rustdoc") - rustdocCmd. - Flags(rustEnvVars(ctx, deps, rustdocCmd)). - Tool(deps.Rustdoc). - Flags(rustdocFlags). - Input(main). - Flag("-o "+docDir.String()). - FlagWithOutput("&& touch ", docTimestampFile). - Implicit(ctx.RustModule().UnstrippedOutputFile()) + ctx.Build(pctx, android.BuildParams{ + Rule: rustdoc, + Description: "rustdoc " + main.Rel(), + Output: docTimestampFile, + Input: main, + Implicit: ctx.RustModule().UnstrippedOutputFile(), + Args: map[string]string{ + "rustdocFlags": strings.Join(rustdocFlags, " "), + "outDir": docDir.String(), + "envVars": strings.Join(rustEnvVars(ctx, deps), " "), + }, + }) - rustdocRule.BuildWithUnescapedNinjaVars("rustdoc", "rustdoc "+main.Rel()) return docTimestampFile } - -func getRuleBuilder(ctx android.ModuleContext, pctx android.PackageContext, sbox bool, sboxDirectory string) *android.RuleBuilder { - r := android.NewRuleBuilder(pctx, ctx) - if sbox { - r = r.Sbox( - android.PathForModuleOut(ctx, sboxDirectory), - android.PathForModuleOut(ctx, sboxDirectory+".sbox.textproto"), - ).SandboxInputs() - } - return r -} diff --git a/rust/builder_test.go b/rust/builder_test.go index 5c11cb7b5..1fd675fb7 100644 --- a/rust/builder_test.go +++ b/rust/builder_test.go @@ -14,7 +14,11 @@ package rust -import "testing" +import ( + "android/soong/android" + "sort" + "testing" +) func TestSourceProviderCollision(t *testing.T) { testRustError(t, "multiple source providers generate the same filename output: bindings.rs", ` @@ -40,3 +44,122 @@ func TestSourceProviderCollision(t *testing.T) { } `) } + +func TestCompilationOutputFiles(t *testing.T) { + ctx := testRust(t, ` + rust_library { + name: "libfizz_buzz", + crate_name:"fizz_buzz", + srcs: ["lib.rs"], + } + rust_binary { + name: "fizz_buzz", + crate_name:"fizz_buzz", + srcs: ["lib.rs"], + } + rust_ffi { + name: "librust_ffi", + crate_name: "rust_ffi", + srcs: ["lib.rs"], + } + `) + testcases := []struct { + testName string + moduleName string + variant string + expectedFiles []string + }{ + { + testName: "dylib", + moduleName: "libfizz_buzz", + variant: "android_arm64_armv8-a_dylib", + expectedFiles: []string{ + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.clippy", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.rsp", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.rsp.a", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.rsp.whole.a", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/unstripped/libfizz_buzz.dylib.so", + "out/soong/target/product/test_device/system/lib64/libfizz_buzz.dylib.so", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/meta_lic", + }, + }, + { + testName: "rlib dylib-std", + moduleName: "libfizz_buzz", + variant: "android_arm64_armv8-a_rlib_dylib-std", + expectedFiles: []string{ + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/libfizz_buzz.rlib", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/libfizz_buzz.rlib.clippy", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/meta_lic", + }, + }, + { + testName: "rlib rlib-std", + moduleName: "libfizz_buzz", + variant: "android_arm64_armv8-a_rlib_rlib-std", + expectedFiles: []string{ + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/libfizz_buzz.rlib", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/libfizz_buzz.rlib.clippy", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/meta_lic", + "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/rustdoc.timestamp", + }, + }, + { + testName: "rust_binary", + moduleName: "fizz_buzz", + variant: "android_arm64_armv8-a", + expectedFiles: []string{ + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.clippy", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.rsp", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.rsp.a", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.rsp.whole.a", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/unstripped/fizz_buzz", + "out/soong/target/product/test_device/system/bin/fizz_buzz", + "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/meta_lic", + }, + }, + { + testName: "rust_ffi static", + moduleName: "librust_ffi", + variant: "android_arm64_armv8-a_static", + expectedFiles: []string{ + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a.clippy", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/meta_lic", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/rustdoc.timestamp", + }, + }, + { + testName: "rust_ffi shared", + moduleName: "librust_ffi", + variant: "android_arm64_armv8-a_shared", + expectedFiles: []string{ + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.clippy", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.rsp", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.rsp.a", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.rsp.whole.a", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so.toc", + "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/meta_lic", + "out/soong/target/product/test_device/system/lib64/librust_ffi.so", + }, + }, + } + for _, tc := range testcases { + t.Run(tc.testName, func(t *testing.T) { + modOutputs := ctx.ModuleForTests(tc.moduleName, tc.variant).AllOutputs() + sort.Strings(tc.expectedFiles) + sort.Strings(modOutputs) + android.AssertStringPathsRelativeToTopEquals( + t, + "incorrect outputs from rust module", + ctx.Config(), + tc.expectedFiles, + modOutputs, + ) + }) + } +} diff --git a/rust/clippy_test.go b/rust/clippy_test.go index 2703a1c6a..bd3bfb151 100644 --- a/rust/clippy_test.go +++ b/rust/clippy_test.go @@ -63,14 +63,14 @@ func TestClippy(t *testing.T) { ).RunTest(t) r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy") - android.AssertStringDoesContain(t, "libfoo flags", r.RuleParams.Command, tc.fooFlags) + android.AssertStringEquals(t, "libfoo flags", tc.fooFlags, r.Args["clippyFlags"]) r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") - android.AssertStringDoesContain(t, "libbar flags", r.RuleParams.Command, "${config.ClippyDefaultLints}") + android.AssertStringEquals(t, "libbar flags", "${config.ClippyDefaultLints}", r.Args["clippyFlags"]) r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") if r.Rule != nil { - t.Errorf("libfoobar is setup to use clippy when explicitly disabled: command=%q", r.RuleParams.Command) + t.Errorf("libfoobar is setup to use clippy when explicitly disabled: clippyFlags=%q", r.Args["clippyFlags"]) } }) } diff --git a/rust/compiler.go b/rust/compiler.go index 3fa3ccd69..d6c52e8d4 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -82,9 +82,6 @@ type BaseCompilerProperties struct { // not directly used as source files. Crate_root *string `android:"path,arch_variant"` - // Additional data files that are used during compilation only. These are not accessible at runtime. - Compile_data []string `android:"path,arch_variant"` - // name of the lint set that should be used to validate this module. // // Possible values are "default" (for using a sensible set of lints @@ -346,23 +343,6 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD panic(fmt.Errorf("baseCrater doesn't know how to crate things!")) } -func (compile *baseCompiler) crateRoot(ctx ModuleContext) android.Path { - if compile.Properties.Crate_root != nil { - return android.PathForModuleSrc(ctx, *compile.Properties.Crate_root) - } - return nil -} - -// compilationSourcesAndData returns a list of files necessary to complete the compilation. -// This includes the rust source files as well as any other data files that -// are referenced during the build. -func (compile *baseCompiler) compilationSourcesAndData(ctx ModuleContext) android.Paths { - return android.PathsForModuleSrc(ctx, android.Concat( - compile.Properties.Srcs, - compile.Properties.Compile_data, - )) -} - func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath { diff --git a/rust/compiler_test.go b/rust/compiler_test.go index e5cc8884e..ec6829a1b 100644 --- a/rust/compiler_test.go +++ b/rust/compiler_test.go @@ -36,9 +36,9 @@ func TestFeaturesToFlags(t *testing.T) { libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") - if !strings.Contains(libfooDylib.RuleParams.Command, "cfg 'feature=\"fizz\"'") || - !strings.Contains(libfooDylib.RuleParams.Command, "cfg 'feature=\"buzz\"'") { - t.Fatalf("missing fizz and buzz feature flags for libfoo dylib, command: %#v", libfooDylib.RuleParams.Command) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") || + !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") { + t.Fatalf("missing fizz and buzz feature flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) } } @@ -57,9 +57,9 @@ func TestCfgsToFlags(t *testing.T) { libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") - if !strings.Contains(libfooDylib.RuleParams.Command, "cfg 'std'") || - !strings.Contains(libfooDylib.RuleParams.Command, "cfg 'cfg1=\"one\"'") { - t.Fatalf("missing std and cfg1 flags for libfoo dylib, rustcFlags: %#v", libfooDylib.RuleParams.Command) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") || + !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") { + t.Fatalf("missing std and cfg1 flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) } } @@ -146,14 +146,14 @@ func TestCargoCompat(t *testing.T) { fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc") - if !strings.Contains(fizz.RuleParams.Command, "CARGO_BIN_NAME=fizz") { - t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual command: %#v", fizz.RuleParams.Command) + if !strings.Contains(fizz.Args["envVars"], "CARGO_BIN_NAME=fizz") { + t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual envVars: %#v", fizz.Args["envVars"]) } - if !strings.Contains(fizz.RuleParams.Command, "CARGO_CRATE_NAME=foo") { - t.Fatalf("expected 'CARGO_CRATE_NAME=foo' in envVars, actual command: %#v", fizz.RuleParams.Command) + if !strings.Contains(fizz.Args["envVars"], "CARGO_CRATE_NAME=foo") { + t.Fatalf("expected 'CARGO_CRATE_NAME=foo' in envVars, actual envVars: %#v", fizz.Args["envVars"]) } - if !strings.Contains(fizz.RuleParams.Command, "CARGO_PKG_VERSION=1.0.0") { - t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' in envVars, actual command: %#v", fizz.RuleParams.Command) + if !strings.Contains(fizz.Args["envVars"], "CARGO_PKG_VERSION=1.0.0") { + t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' in envVars, actual envVars: %#v", fizz.Args["envVars"]) } } @@ -230,13 +230,13 @@ func TestLints(t *testing.T) { ).RunTest(t) r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - android.AssertStringDoesContain(t, "libfoo flags", r.RuleParams.Command, tc.fooFlags) + android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags) r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - android.AssertStringDoesContain(t, "libbar flags", r.RuleParams.Command, "${config.RustDefaultLints}") + android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}") r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - android.AssertStringDoesContain(t, "libfoobar flags", r.RuleParams.Command, "${config.RustAllowAllLints}") + android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}") }) } } diff --git a/rust/config/global.go b/rust/config/global.go index 0ddc11637..f397ce90d 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -126,27 +126,3 @@ func GetRustVersion(ctx android.PathContext) string { func BazelRustToolchainVars(config android.Config) string { return android.BazelToolchainVars(config, exportedVars) } - -func RustPath(ctx android.PathContext, file string) android.SourcePath { - type rustToolKey string - key := android.NewCustomOnceKey(rustToolKey(file)) - return ctx.Config().OnceSourcePath(key, func() android.SourcePath { - return rustPath(ctx).Join(ctx, file) - }) -} - -var rustPathKey = android.NewOnceKey("clangPath") - -func rustPath(ctx android.PathContext) android.SourcePath { - return ctx.Config().OnceSourcePath(rustPathKey, func() android.SourcePath { - rustBase := RustDefaultBase - if override := ctx.Config().Getenv("RUST_PREBUILTS_BASE"); override != "" { - rustBase = override - } - rustVersion := RustDefaultVersion - if override := ctx.Config().Getenv("RUST_DEFAULT_VERSION"); override != "" { - rustVersion = override - } - return android.PathForSource(ctx, rustBase, ctx.Config().PrebuiltOS(), rustVersion) - }) -} diff --git a/rust/coverage.go b/rust/coverage.go index b312194f2..5216d6098 100644 --- a/rust/coverage.go +++ b/rust/coverage.go @@ -17,7 +17,6 @@ package rust import ( "github.com/google/blueprint" - "android/soong/android" "android/soong/cc" ) @@ -71,10 +70,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags // no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency. if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() { profiler_builtins := ctx.GetDirectDepWithTag(ProfilerBuiltins, rlibDepTag).(*Module) - deps.Rlibs = android.AddDirectToDepSet[RustLibrary](deps.Rlibs, RustLibrary{ - Path: profiler_builtins.OutputFile().Path(), - CrateName: profiler_builtins.CrateName(), - }) + deps.RLibs = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile().Path(), CrateName: profiler_builtins.CrateName()}) } if cc.EnableContinuousCoverage(ctx) { diff --git a/rust/coverage_test.go b/rust/coverage_test.go index 1466e0ce4..64077cf00 100644 --- a/rust/coverage_test.go +++ b/rust/coverage_test.go @@ -55,27 +55,27 @@ func TestCoverageFlags(t *testing.T) { libbarNoCov := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc") fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc") buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc") - libfooCovLink := ctx.ModuleForTests("libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustc") - libbarNoCovLink := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc") - fizzCovLink := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc") - buzzNoCovLink := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc") + libfooCovLink := ctx.ModuleForTests("libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustLink") + libbarNoCovLink := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustLink") + fizzCovLink := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustLink") + buzzNoCovLink := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustLink") rustcCoverageFlags := []string{"-C instrument-coverage", " -g "} for _, flag := range rustcCoverageFlags { missingErrorStr := "missing rustc flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v" containsErrorStr := "contains rustc flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v" - if !strings.Contains(fizzCov.RuleParams.Command, flag) { - t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.RuleParams.Command) + if !strings.Contains(fizzCov.Args["rustcFlags"], flag) { + t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.Args["rustcFlags"]) } - if !strings.Contains(libfooCov.RuleParams.Command, flag) { - t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.RuleParams.Command) + if !strings.Contains(libfooCov.Args["rustcFlags"], flag) { + t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.Args["rustcFlags"]) } - if strings.Contains(buzzNoCov.RuleParams.Command, flag) { - t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.RuleParams.Command) + if strings.Contains(buzzNoCov.Args["rustcFlags"], flag) { + t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.Args["rustcFlags"]) } - if strings.Contains(libbarNoCov.RuleParams.Command, flag) { - t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.RuleParams.Command) + if strings.Contains(libbarNoCov.Args["rustcFlags"], flag) { + t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.Args["rustcFlags"]) } } @@ -84,17 +84,17 @@ func TestCoverageFlags(t *testing.T) { missingErrorStr := "missing rust linker flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v" containsErrorStr := "contains rust linker flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v" - if !strings.Contains(fizzCovLink.RuleParams.Command, flag) { - t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.RuleParams.Command) + if !strings.Contains(fizzCovLink.Args["linkFlags"], flag) { + t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.Args["linkFlags"]) } - if !strings.Contains(libfooCovLink.RuleParams.Command, flag) { - t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.RuleParams.Command) + if !strings.Contains(libfooCovLink.Args["linkFlags"], flag) { + t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.Args["linkFlags"]) } - if strings.Contains(buzzNoCovLink.RuleParams.Command, flag) { - t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.RuleParams.Command) + if strings.Contains(buzzNoCovLink.Args["linkFlags"], flag) { + t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.Args["linkFlags"]) } - if strings.Contains(libbarNoCovLink.RuleParams.Command, flag) { - t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.RuleParams.Command) + if strings.Contains(libbarNoCovLink.Args["linkFlags"], flag) { + t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.Args["linkFlags"]) } } @@ -107,8 +107,8 @@ func TestCoverageDeps(t *testing.T) { srcs: ["foo.rs"], }`) - fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc") - if !strings.Contains(fizz.RuleParams.Command, "libprofile-clang-extras.a") { - t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.RuleParams.Command) + fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustLink") + if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") { + t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"]) } } diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go index ea3590556..ee28c6d3a 100644 --- a/rust/fuzz_test.go +++ b/rust/fuzz_test.go @@ -51,23 +51,23 @@ func TestRustFuzz(t *testing.T) { // Check that compiler flags are set appropriately . fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc") - if !strings.Contains(fuzz_libtest.RuleParams.Command, "-C passes='sancov-module'") || - !strings.Contains(fuzz_libtest.RuleParams.Command, "--cfg fuzzing") { + if !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov-module'") || + !strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") { t.Errorf("rust_fuzz module does not contain the expected flags (sancov-module, cfg fuzzing).") } // Check that host modules support fuzzing. host_fuzzer := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc") - if !strings.Contains(host_fuzzer.RuleParams.Command, "-C passes='sancov-module'") || - !strings.Contains(host_fuzzer.RuleParams.Command, "--cfg fuzzing") { + if !strings.Contains(host_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") || + !strings.Contains(host_fuzzer.Args["rustcFlags"], "--cfg fuzzing") { t.Errorf("rust_fuzz_host module does not contain the expected flags (sancov-module, cfg fuzzing).") } // Check that dependencies have 'fuzzer' variants produced for them as well. - libtest_fuzzer := ctx.ModuleForTests("libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Rule("rustc") - if !strings.Contains(libtest_fuzzer.RuleParams.Command, "-C passes='sancov-module'") || - !strings.Contains(libtest_fuzzer.RuleParams.Command, "--cfg fuzzing") { - t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov-module, cfg fuzzing). command: %q", libtest_fuzzer.RuleParams.Command) + libtest_fuzzer := ctx.ModuleForTests("libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Output("libtest_fuzzing.rlib") + if !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") || + !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "--cfg fuzzing") { + t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov-module, cfg fuzzing).") } } diff --git a/rust/image_test.go b/rust/image_test.go index 813c5bcdd..fb4d9c170 100644 --- a/rust/image_test.go +++ b/rust/image_test.go @@ -59,36 +59,36 @@ func TestImageVndkCfgFlag(t *testing.T) { vendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_static").Rule("rustc") - if !strings.Contains(vendor.RuleParams.Command, "--cfg 'android_vndk'") { - t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.RuleParams.Command) + if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") { + t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } - if !strings.Contains(vendor.RuleParams.Command, "--cfg 'android_vendor'") { - t.Errorf("missing \"--cfg 'android_vendor'\" for libfoo vendor variant, rustcFlags: %#v", vendor.RuleParams.Command) + if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vendor'") { + t.Errorf("missing \"--cfg 'android_vendor'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } - if strings.Contains(vendor.RuleParams.Command, "--cfg 'android_product'") { - t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.RuleParams.Command) + if strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_product'") { + t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) } product := ctx.ModuleForTests("libfoo", "android_product.29_arm64_armv8-a_static").Rule("rustc") - if !strings.Contains(product.RuleParams.Command, "--cfg 'android_vndk'") { - t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.RuleParams.Command) + if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") { + t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } - if strings.Contains(product.RuleParams.Command, "--cfg 'android_vendor'") { - t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo product variant, rustcFlags: %#v", product.RuleParams.Command) + if strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vendor'") { + t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } - if !strings.Contains(product.RuleParams.Command, "--cfg 'android_product'") { - t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.RuleParams.Command) + if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_product'") { + t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) } system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Rule("rustc") - if strings.Contains(system.RuleParams.Command, "--cfg 'android_vndk'") { - t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.RuleParams.Command) + if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") { + t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) } - if strings.Contains(system.RuleParams.Command, "--cfg 'android_vendor'") { - t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.RuleParams.Command) + if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vendor'") { + t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) } - if strings.Contains(system.RuleParams.Command, "--cfg 'android_product'") { - t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.RuleParams.Command) + if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_product'") { + t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.Args["rustcFlags"]) } } diff --git a/rust/library.go b/rust/library.go index 7bb82bcc2..f4a2b5441 100644 --- a/rust/library.go +++ b/rust/library.go @@ -485,23 +485,6 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F return flags } -func (library *libraryDecorator) compilationSourcesAndData(ctx ModuleContext) android.Paths { - var extraSrcs android.Paths - if library.rlib() { - extraSrcs = android.PathsForModuleSrc(ctx, library.Properties.Rlib.Srcs) - } else if library.dylib() { - extraSrcs = android.PathsForModuleSrc(ctx, library.Properties.Dylib.Srcs) - } else if library.static() { - extraSrcs = android.PathsForModuleSrc(ctx, library.Properties.Static.Srcs) - } else if library.shared() { - extraSrcs = android.PathsForModuleSrc(ctx, library.Properties.Shared.Srcs) - } - return android.Concat( - library.baseCompiler.compilationSourcesAndData(ctx), - extraSrcs, - ) -} - func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { var outputFile android.ModuleOutPath var ret buildOutput @@ -542,6 +525,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa flags.RustFlags = append(flags.RustFlags, deps.depFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...) if library.dylib() { // We need prefer-dynamic for now to avoid linking in the static stdlib. See: @@ -552,13 +536,13 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa // Call the appropriate builder for this library type if library.rlib() { - ret.kytheFile = TransformSrctoRlib(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.dylib() { - ret.kytheFile = TransformSrctoDylib(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.static() { - ret.kytheFile = TransformSrctoStatic(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoStatic(ctx, crateRootPath, deps, flags, outputFile).kytheFile } else if library.shared() { - ret.kytheFile = TransformSrctoShared(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile } if library.rlib() || library.dylib() { diff --git a/rust/library_test.go b/rust/library_test.go index dab938159..30ef333b9 100644 --- a/rust/library_test.go +++ b/rust/library_test.go @@ -48,23 +48,23 @@ func TestLibraryVariants(t *testing.T) { staticCrateType := "staticlib" // Test crate type for rlib is correct. - if !strings.Contains(libfooRlib.RuleParams.Command, "crate-type="+rlibCrateType) { - t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.RuleParams.Command) + if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.Args["rustcFlags"]) } // Test crate type for dylib is correct. - if !strings.Contains(libfooDylib.RuleParams.Command, "crate-type="+dylibCrateType) { - t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.RuleParams.Command) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "crate-type="+dylibCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.Args["rustcFlags"]) } // Test crate type for C static libraries is correct. - if !strings.Contains(libfooStatic.RuleParams.Command, "crate-type="+staticCrateType) { - t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.RuleParams.Command) + if !strings.Contains(libfooStatic.Args["rustcFlags"], "crate-type="+staticCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"]) } // Test crate type for C shared libraries is correct. - if !strings.Contains(libfooShared.RuleParams.Command, "crate-type="+sharedCrateType) { - t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.RuleParams.Command) + if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) { + t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"]) } } @@ -78,10 +78,10 @@ func TestDylibPreferDynamic(t *testing.T) { crate_name: "foo", }`) - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Description("rustc") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") - if !strings.Contains(libfooDylib.RuleParams.Command, "prefer-dynamic") { - t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.RuleParams.Command) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") { + t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) } } @@ -94,10 +94,10 @@ func TestAndroidDylib(t *testing.T) { crate_name: "foo", }`) - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Description("rustc") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") - if !strings.Contains(libfooDylib.RuleParams.Command, "--cfg 'android_dylib'") { - t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.RuleParams.Command) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "--cfg 'android_dylib'") { + t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) } } @@ -148,10 +148,10 @@ func TestSharedLibrary(t *testing.T) { libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared") - libfooOutput := libfoo.Rule("rustc") - if !strings.Contains(libfooOutput.RuleParams.Command, "-Wl,-soname=libfoo.so") { + libfooOutput := libfoo.Rule("rustLink") + if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") { t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", - libfooOutput.RuleParams.Command) + libfooOutput.Args["linkFlags"]) } if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkDylibs) { @@ -237,21 +237,19 @@ func TestNativeDependencyOfRlib(t *testing.T) { // The build system assumes the cc deps will be at the final linkage (either a shared library or binary) // Hence, these flags are no-op // TODO: We could consider removing these flags - expectedSharedFlag := "-L out/soong/.intermediates/shared_cc_dep/android_arm64_armv8-a_shared" - expectedStaticFlag := "-L out/soong/.intermediates/static_cc_dep/android_arm64_armv8-a_static" for _, module := range modules { - if !strings.Contains(module.Rule("rustc").RuleParams.Command, expectedSharedFlag) { + if !strings.Contains(module.Rule("rustc").Args["libFlags"], + "-L out/soong/.intermediates/shared_cc_dep/android_arm64_armv8-a_shared/") { t.Errorf( - "expected to find shared library linkdir flag %q, rustcFlags: %#v", - expectedSharedFlag, - rustRlibRlibStd.Rule("rustc").RuleParams.Command, + "missing -L flag for shared_cc_dep, rustcFlags: %#v", + rustRlibRlibStd.Rule("rustc").Args["libFlags"], ) } - if !strings.Contains(module.Rule("rustc").RuleParams.Command, expectedStaticFlag) { + if !strings.Contains(module.Rule("rustc").Args["libFlags"], + "-L out/soong/.intermediates/static_cc_dep/android_arm64_armv8-a_static/") { t.Errorf( - "expected to find static library linkdir flag %q, rustcFlags: %#v", - expectedStaticFlag, - rustRlibRlibStd.Rule("rustc").RuleParams.Command, + "missing -L flag for static_cc_dep, rustcFlags: %#v", + rustRlibRlibStd.Rule("rustc").Args["libFlags"], ) } } diff --git a/rust/prebuilt.go b/rust/prebuilt.go index d012680f0..fe9d0b5dd 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -146,10 +146,7 @@ func (prebuilt *prebuiltLibraryDecorator) compilerProps() []interface{} { } func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { - deps.linkDirs = append(deps.linkDirs, android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs)...) - prebuilt.flagExporter.exportLinkDirs(deps.linkDirs...) - prebuilt.flagExporter.exportLinkObjects(deps.linkObjects...) - prebuilt.flagExporter.exportLibDeps(deps.LibDeps...) + prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) prebuilt.flagExporter.setProvider(ctx) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) @@ -206,7 +203,7 @@ func (prebuilt *prebuiltProcMacroDecorator) compilerProps() []interface{} { } func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { - prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs)...) + prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) prebuilt.flagExporter.setProvider(ctx) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 3f0d17a73..b93b24f15 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -80,7 +80,7 @@ func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, dep outputFile := android.PathForModuleOut(ctx, fileName) srcPath, _ := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs) - ret := TransformSrctoProcMacro(ctx, procMacro, srcPath, deps, flags, outputFile) + ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile) procMacro.baseCompiler.unstrippedOutputFile = outputFile return ret } diff --git a/rust/proc_macro_test.go b/rust/proc_macro_test.go index a547926fc..cc8193858 100644 --- a/rust/proc_macro_test.go +++ b/rust/proc_macro_test.go @@ -30,7 +30,7 @@ func TestRustProcMacro(t *testing.T) { libprocmacro := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Rule("rustc") - if !strings.Contains(libprocmacro.RuleParams.Command, "--extern proc_macro") { - t.Errorf("--extern proc_macro flag not being passed to rustc for proc macro %#v", libprocmacro.RuleParams.Command) + if !strings.Contains(libprocmacro.Args["rustcFlags"], "--extern proc_macro") { + t.Errorf("--extern proc_macro flag not being passed to rustc for proc macro %#v", libprocmacro.Args["rustcFlags"]) } } diff --git a/rust/protobuf.go b/rust/protobuf.go index c8d2bdaeb..2982efdf2 100644 --- a/rust/protobuf.go +++ b/rust/protobuf.go @@ -20,6 +20,7 @@ import ( "android/soong/android" "android/soong/bazel" + "android/soong/cc" "github.com/google/blueprint/proptools" ) @@ -59,14 +60,18 @@ type ProtobufProperties struct { // Use protobuf version 3.x. This will be deleted once we migrate all current users // of protobuf off of 2.x. Use_protobuf3 *bool + + // List of exported include paths containing proto files for dependent rust_protobuf modules. + Exported_include_dirs []string } type protobufDecorator struct { *BaseSourceProvider - Properties ProtobufProperties - protoNames []string - grpcNames []string + Properties ProtobufProperties + protoNames []string + additionalCrates []string + grpcNames []string grpcProtoFlags android.ProtoFlags protoFlags android.ProtoFlags @@ -184,6 +189,10 @@ func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) // stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point. proto.BaseSourceProvider.OutputFiles = append(android.Paths{stemFile}, outputs.Paths()...) + ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{ + IncludeDirs: android.PathsForModuleSrc(ctx, proto.Properties.Exported_include_dirs), + }) + // mod_stem.rs is the entry-point for our library modules, so this is what we return. return stemFile } @@ -192,10 +201,16 @@ func (proto *protobufDecorator) genModFileContents() string { lines := []string{ "// @Soong generated Source", } + for _, protoName := range proto.protoNames { lines = append(lines, fmt.Sprintf("pub mod %s;", protoName)) } + for _, crate := range proto.additionalCrates { + lines = append(lines, fmt.Sprintf("pub use %s::*;", crate)) + + } + for _, grpcName := range proto.grpcNames { lines = append(lines, fmt.Sprintf("pub mod %s;", grpcName)) lines = append(lines, fmt.Sprintf("pub mod %s%s;", grpcName, grpcSuffix)) @@ -305,7 +320,11 @@ func protoLibraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { }, } - ctx.CreateBazelTargetModule( + // TODO(b/295918553): Remove androidRestriction after rust toolchain for android is checked in. + var androidRestriction bazel.BoolAttribute + androidRestriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false)) + + ctx.CreateBazelTargetModuleWithRestrictions( bazel.BazelTargetModuleProperties{ Rule_class: "proto_library", }, @@ -317,9 +336,10 @@ func protoLibraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { android.BazelLabelForModuleSrc(ctx, protoFiles), ), }, + androidRestriction, ) - ctx.CreateBazelTargetModule( + ctx.CreateBazelTargetModuleWithRestrictions( bazel.BazelTargetModuleProperties{ Rule_class: "rust_proto_library", Bzl_load_location: "@rules_rust//proto/protobuf:defs.bzl", @@ -333,5 +353,6 @@ func protoLibraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { }, Deps: protoDeps, }, + androidRestriction, ) } diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go index b723f3f1a..9dca0290f 100644 --- a/rust/protobuf_test.go +++ b/rust/protobuf_test.go @@ -118,6 +118,58 @@ func TestRustProtobuf3(t *testing.T) { } } +func TestRustProtobufInclude(t *testing.T) { + ctx := testRust(t, ` + rust_protobuf { + name: "librust_proto", + protos: ["proto.proto"], + crate_name: "rust_proto", + source_stem: "proto", + use_protobuf3: true, + rustlibs: ["librust_exported_proto", "libfoo"], + } + rust_protobuf { + name: "librust_exported_proto", + protos: ["proto.proto"], + crate_name: "rust_exported_proto", + source_stem: "exported_proto", + use_protobuf3: true, + exported_include_dirs: ["proto"] + } + rust_library { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.rs"], + } + `) + // Check that librust_exported_proto is added as additional crate to generate source. + librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Module().(*Module).sourceProvider.(*protobufDecorator) + if !android.InList("rust_exported_proto", librust_proto.additionalCrates) { + t.Errorf("librust_proto should have librust_exported_proto included as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates) + } + + // Make sure the default crates aren't being included. + if android.InList("std", librust_proto.additionalCrates) { + t.Errorf("librust_proto should not have included libstd as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates) + } + if android.InList("protobuf", librust_proto.additionalCrates) { + t.Errorf("librust_proto should not have included libprotobuf as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates) + } + + // And make sure that non-protobuf crates aren't getting included either. + if android.InList("foo", librust_proto.additionalCrates) { + t.Errorf("librust_proto should not have included libfoo as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates) + } + + // Check librust_proto args includes -Iproto + librust_proto_rule := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("proto.rs") + cmd := librust_proto_rule.RuleParams.Command + if w := "-Iproto"; !strings.Contains(cmd, w) { + t.Errorf("expected %q in %q", w, cmd) + } + +} + func TestRustGrpc(t *testing.T) { ctx := testRust(t, ` rust_protobuf { diff --git a/rust/rust.go b/rust/rust.go index 6d6b55efe..49a7ff353 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -267,6 +267,15 @@ func (mod *Module) Dylib() bool { return false } +func (mod *Module) Source() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil { + return library.source() + } + } + return false +} + func (mod *Module) RlibStd() bool { if mod.compiler != nil { if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() { @@ -438,18 +447,12 @@ type Deps struct { } type PathDeps struct { - Dylibs *android.DepSet[RustLibrary] - Rlibs *android.DepSet[RustLibrary] - ProcMacros *android.DepSet[RustLibrary] + DyLibs RustLibraries + RLibs RustLibraries LibDeps android.Paths WholeStaticLibs android.Paths + ProcMacros RustLibraries AfdoProfiles android.Paths - // These paths are files needed to run the build tools and will be located under - // __SBOX_SANDBOX_DIR__/tools/... - BuildToolDeps android.Paths - // These paths are files needed to run the build tools and will be located under - // __SBOX_SANDBOX_DIR__/... - BuildToolSrcDeps android.Paths // depFlags and depLinkFlags are rustc and linker (clang) flags. depFlags []string @@ -457,7 +460,7 @@ type PathDeps struct { // linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker. // Both of these are exported and propagate to dependencies. - linkDirs android.Paths + linkDirs []string linkObjects android.Paths // Used by bindgen modules which call clang @@ -472,13 +475,6 @@ type PathDeps struct { // Paths to generated source files SrcDeps android.Paths srcProviderFiles android.Paths - - // Paths to specific build tools - Rustc android.Path - Clang android.Path - Llvm_ar android.Path - Clippy_driver android.Path - Rustdoc android.Path } type RustLibraries []RustLibrary @@ -498,8 +494,6 @@ type compiler interface { compilerDeps(ctx DepsContext, deps Deps) Deps crateName() string rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath - crateRoot(ctx ModuleContext) android.Path - compilationSourcesAndData(ctx ModuleContext) android.Paths // Output directory in which source-generated code from dependencies is // copied. This is equivalent to Cargo's OUT_DIR variable. @@ -529,7 +523,7 @@ type compiler interface { } type exportedFlagsProducer interface { - exportLinkDirs(...android.Path) + exportLinkDirs(...string) exportLinkObjects(...android.Path) } @@ -538,13 +532,13 @@ type xref interface { } type flagExporter struct { - linkDirs android.Paths + linkDirs []string linkObjects android.Paths libDeps android.Paths } -func (flagExporter *flagExporter) exportLinkDirs(dirs ...android.Path) { - flagExporter.linkDirs = android.FirstUniquePaths(append(flagExporter.linkDirs, dirs...)) +func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { + flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) } func (flagExporter *flagExporter) exportLinkObjects(flags ...android.Path) { @@ -571,7 +565,7 @@ func NewFlagExporter() *flagExporter { type FlagExporterInfo struct { Flags []string - LinkDirs android.Paths + LinkDirs []string // TODO: this should be android.Paths LinkObjects android.Paths LibDeps android.Paths } @@ -941,14 +935,6 @@ func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchai func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { } -type RustInfo struct { - TransitiveRlibs *android.DepSet[RustLibrary] - TransitiveDylibs *android.DepSet[RustLibrary] - TransitiveProcMacros *android.DepSet[RustLibrary] -} - -var RustInfoProvider = blueprint.NewProvider(RustInfo{}) - func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx := &moduleContext{ ModuleContext: actx, @@ -1058,12 +1044,6 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) } - - ctx.SetProvider(RustInfoProvider, RustInfo{ - TransitiveRlibs: deps.Rlibs, - TransitiveDylibs: deps.Dylibs, - TransitiveProcMacros: deps.ProcMacros, - }) } func (mod *Module) deps(ctx DepsContext) Deps { @@ -1122,7 +1102,6 @@ func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation { var _ android.LicenseAnnotationsDependencyTag = dependencyTag{} var ( - buildToolDepTag = dependencyTag{name: "buildToolTag"} customBindgenDepTag = dependencyTag{name: "customBindgenTag"} rlibDepTag = dependencyTag{name: "rlibTag", library: true} dylibDepTag = dependencyTag{name: "dylib", library: true, dynamic: true} @@ -1186,6 +1165,13 @@ func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.L return cc.MakeLibName(ctx, c, dep, depName) } +func collectIncludedProtos(mod *Module, dep *Module) { + if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok { + if _, ok := dep.sourceProvider.(*protobufDecorator); ok { + protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName()) + } + } +} func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps @@ -1256,9 +1242,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var transitiveAndroidMkSharedLibs []*android.DepSet[string] var directAndroidMkSharedLibs []string - transitiveRlibs := android.NewDepSetBuilder[RustLibrary](android.PREORDER) - transitiveDylibs := android.NewDepSetBuilder[RustLibrary](android.PREORDER) - transitiveProcMacros := android.NewDepSetBuilder[RustLibrary](android.PREORDER) + ctx.VisitDirectDeps(func(dep android.Module) { depName := ctx.OtherModuleName(dep) depTag := ctx.OtherModuleDependencyTag(dep) @@ -1271,17 +1255,6 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - rustInfo := ctx.OtherModuleProvider(dep, RustInfoProvider).(RustInfo) - if rustInfo.TransitiveDylibs != nil { - transitiveDylibs.Transitive(rustInfo.TransitiveDylibs) - } - if rustInfo.TransitiveRlibs != nil { - transitiveRlibs.Transitive(rustInfo.TransitiveRlibs) - } - if rustInfo.TransitiveProcMacros != nil { - transitiveProcMacros.Transitive(rustInfo.TransitiveProcMacros) - } - if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() { //Handle Rust Modules makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName) @@ -1296,12 +1269,9 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directDylibDeps = append(directDylibDeps, rustDep) mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName) mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName)) - transitiveDylibs.Direct(RustLibrary{ - Path: rustDep.UnstrippedOutputFile(), - CrateName: rustDep.CrateName(), - }) case rlibDepTag: + rlib, ok := rustDep.compiler.(libraryInterface) if !ok || !rlib.rlib() { ctx.ModuleErrorf("mod %q not an rlib library", makeLibName) @@ -1310,18 +1280,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directRlibDeps = append(directRlibDeps, rustDep) mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName) mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName)) - transitiveRlibs.Direct(RustLibrary{ - Path: rustDep.UnstrippedOutputFile(), - CrateName: rustDep.CrateName(), - }) case procMacroDepTag: directProcMacroDeps = append(directProcMacroDeps, rustDep) mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName) - transitiveProcMacros.Direct(RustLibrary{ - Path: rustDep.UnstrippedOutputFile(), - CrateName: rustDep.CrateName(), - }) + + case sourceDepTag: + if _, ok := mod.sourceProvider.(*protobufDecorator); ok { + collectIncludedProtos(mod, rustDep) + } } transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs) @@ -1357,11 +1324,19 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { linkFile := rustDep.UnstrippedOutputFile() + linkDir := linkPathFromFilePath(linkFile) if lib, ok := mod.compiler.(exportedFlagsProducer); ok { - lib.exportLinkDirs(linkFile.Dir()) + lib.exportLinkDirs(linkDir) + } + } + if depTag == sourceDepTag { + if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() { + if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok { + exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo) + depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) + } } } - } else if ccDep, ok := dep.(cc.LinkableInterface); ok { //Handle C dependencies makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName) @@ -1385,7 +1360,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - linkPath := linkObject.Path().Dir() + linkPath := linkPathFromFilePath(linkObject.Path()) exportDep := false switch { @@ -1439,7 +1414,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } return } - linkPath = linkObject.Path().Dir() + linkPath = linkPathFromFilePath(linkObject.Path()) depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...) @@ -1474,25 +1449,6 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } else { switch { - case depTag == buildToolDepTag: - buildTool := ctx.OtherModuleProvider(dep, android.PrebuiltBuildToolInfoProvider).(android.PrebuiltBuildToolInfo) - depPaths.BuildToolDeps = append(depPaths.BuildToolDeps, buildTool.Src) - depPaths.BuildToolDeps = append(depPaths.BuildToolDeps, buildTool.Deps...) - switch android.RemoveOptionalPrebuiltPrefix(dep.Name()) { - case "rustc": - depPaths.Rustc = buildTool.Src - // rustc expects the standard cc toolchain libraries (libdl, libm, libc, etc.) - // not to be under the __SBOX_SANDBOX_DIR__/ directory - depPaths.BuildToolSrcDeps = append(depPaths.BuildToolSrcDeps, buildTool.Deps...) - case "clang++": - depPaths.Clang = buildTool.Src - case "llvm-ar": - depPaths.Llvm_ar = buildTool.Src - case "clippy-driver": - depPaths.Clippy_driver = buildTool.Src - case "rustdoc": - depPaths.Rustdoc = buildTool.Src - } case depTag == cc.CrtBeginDepTag: depPaths.CrtBegin = append(depPaths.CrtBegin, android.OutputFileForModule(ctx, dep, "")) case depTag == cc.CrtEndDepTag: @@ -1508,6 +1464,21 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } }) + mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) + + var rlibDepFiles RustLibraries + for _, dep := range directRlibDeps { + rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + } + var dylibDepFiles RustLibraries + for _, dep := range directDylibDeps { + dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + } + var procMacroDepFiles RustLibraries + for _, dep := range directProcMacroDeps { + procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()}) + } + var libDepFiles android.Paths for _, dep := range directStaticLibDeps { libDepFiles = append(libDepFiles, dep.OutputFile().Path()) @@ -1531,22 +1502,20 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { srcProviderDepFiles = append(srcProviderDepFiles, srcs...) } + depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...) + depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...) depPaths.LibDeps = append(depPaths.LibDeps, libDepFiles...) + depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...) depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...) // Dedup exported flags from dependencies - depPaths.linkDirs = android.FirstUniquePaths(depPaths.linkDirs) + depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs) depPaths.linkObjects = android.FirstUniquePaths(depPaths.linkObjects) depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags) depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags) depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths) depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths) - depPaths.Rlibs = transitiveRlibs.Build() - depPaths.Dylibs = transitiveDylibs.Build() - depPaths.ProcMacros = transitiveProcMacros.Build() - mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs) - return depPaths } @@ -1569,6 +1538,10 @@ func (mod *Module) InstallInRecovery() bool { return mod.InRecovery() } +func linkPathFromFilePath(filepath android.Path) string { + return strings.Split(filepath.String(), filepath.Base())[0] +} + // usePublicApi returns true if the rust variant should link against NDK (publicapi) func (r *Module) usePublicApi() bool { return r.Device() && r.UseSdk() @@ -1611,15 +1584,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage}) } - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "rustc") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "clippy-driver") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "rustdoc") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "clang++") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "clang++.real") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "lld") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "ld.lld") - ctx.AddFarVariationDependencies([]blueprint.Variation{}, buildToolDepTag, "llvm-ar") - // rlibs rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation}) for _, lib := range deps.Rlibs { @@ -1636,30 +1600,43 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } // rustlibs - if deps.Rustlibs != nil && !mod.compiler.Disabled() { - autoDep := mod.compiler.(autoDeppable).autoDep(ctx) - for _, lib := range deps.Rustlibs { - if autoDep.depTag == rlibDepTag { - // Handle the rlib deptag case - addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations) - } else { - // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however. - // Check for the existence of the dylib deptag variant. Select it if available, - // otherwise select the rlib variant. - autoDepVariations := append(commonDepVariations, - blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) + if deps.Rustlibs != nil { + if !mod.compiler.Disabled() { + for _, lib := range deps.Rustlibs { + autoDep := mod.compiler.(autoDeppable).autoDep(ctx) + if autoDep.depTag == rlibDepTag { + // Handle the rlib deptag case + addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations) + } else { + // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however. + // Check for the existence of the dylib deptag variant. Select it if available, + // otherwise select the rlib variant. + autoDepVariations := append(commonDepVariations, + blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) + + replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs) + if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) { + addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag) + } else { + // If there's no dylib dependency available, try to add the rlib dependency instead. + addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations) + } + } + } + } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok { + for _, lib := range deps.Rustlibs { replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs) + srcProviderVariations := append(commonDepVariations, + blueprint.Variation{Mutator: "rust_libraries", Variation: "source"}) - if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) { - addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag) - } else { - // If there's no dylib dependency available, try to add the rlib dependency instead. - addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations) + if actx.OtherModuleDependencyVariantExists(srcProviderVariations, replacementLib) { + actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib) } } } } + // stdlibs if deps.Stdlibs != nil { if mod.compiler.stdLinkage(ctx) == RlibLinkage { @@ -1917,7 +1894,7 @@ func (m *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { procMacroBp2build(ctx, m) } else if ctx.ModuleType() == "rust_binary_host" { binaryBp2build(ctx, m) - } else if ctx.ModuleType() == "rust_protobuf_host" { + } else if ctx.ModuleType() == "rust_protobuf_host" || ctx.ModuleType() == "rust_protobuf" { protoLibraryBp2build(ctx, m) } else { ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") diff --git a/rust/rust_test.go b/rust/rust_test.go index 576209d04..835114c13 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -15,17 +15,14 @@ package rust import ( - "fmt" "os" "runtime" "strings" "testing" "github.com/google/blueprint/proptools" - "google.golang.org/protobuf/encoding/prototext" "android/soong/android" - "android/soong/cmd/sbox/sbox_proto" "android/soong/genrule" ) @@ -67,14 +64,11 @@ var rustMockedFiles = android.MockFS{ // testRust returns a TestContext in which a basic environment has been setup. // This environment contains a few mocked files. See rustMockedFiles for the list of these files. -func testRust(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext { +func testRust(t *testing.T, bp string) *android.TestContext { skipTestIfOsNotSupported(t) result := android.GroupFixturePreparers( prepareForRustTest, rustMockedFiles.AddToFixture(), - android.GroupFixturePreparers( - preparers..., - ), ). RunTestWithBp(t, bp) return result.TestContext @@ -208,11 +202,11 @@ func skipTestIfOsNotSupported(t *testing.T) { // Test that we can extract the link path from a lib path. func TestLinkPathFromFilePath(t *testing.T) { barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so") - libName := barPath.Dir() - expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared" + libName := linkPathFromFilePath(barPath) + expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/" - if libName.String() != expectedResult { - t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName.String()) + if libName != expectedResult { + t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName) } } @@ -262,7 +256,7 @@ func TestDepsTracking(t *testing.T) { `) module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module) rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc") - rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc") + rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustLink") // Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up. if !android.InList("librlib.rlib-std", module.Properties.AndroidMkRlibs) { @@ -281,16 +275,16 @@ func TestDepsTracking(t *testing.T) { t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)") } - if !strings.Contains(rustc.RuleParams.Command, "-lstatic=wholestatic") { - t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.RuleParams.Command) + if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=wholestatic") { + t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"]) } - if !strings.Contains(rustLink.RuleParams.Command, "cc_stubs_dep.so") { - t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustLink.RuleParams.Command) + if !strings.Contains(rustLink.Args["linkFlags"], "cc_stubs_dep.so") { + t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustLink.Args["linkFlags"]) } - if !android.SuffixInList(rustLink.Implicits.Strings(), "cc_stubs_dep.so") { - t.Errorf("shared cc dep not being passed as implicit to rustc %#v", rustLink.OrderOnly.Strings()) + if !android.SuffixInList(rustLink.OrderOnly.Strings(), "cc_stubs_dep.so") { + t.Errorf("shared cc dep not being passed as order-only to rustc %#v", rustLink.OrderOnly.Strings()) } if !android.SuffixInList(rustLink.Implicits.Strings(), "cc_stubs_dep.so.toc") { @@ -433,7 +427,7 @@ func TestProcMacroDeviceDeps(t *testing.T) { `) rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc") - if !strings.Contains(rustc.RuleParams.Command, "libbar/linux_glibc_x86_64") { + if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") { t.Errorf("Proc_macro is not using host variant of dependent modules.") } } @@ -486,396 +480,3 @@ func assertString(t *testing.T, got, expected string) { t.Errorf("expected %q got %q", expected, got) } } - -var ( - sboxCompilationFiles = []string{ - "out/soong/.intermediates/defaults/rust/libaddr2line/android_arm64_armv8-a_rlib/libaddr2line.rlib", - "out/soong/.intermediates/defaults/rust/libadler/android_arm64_armv8-a_rlib/libadler.rlib", - "out/soong/.intermediates/defaults/rust/liballoc/android_arm64_armv8-a_rlib/liballoc.rlib", - "out/soong/.intermediates/defaults/rust/libcfg_if/android_arm64_armv8-a_rlib/libcfg_if.rlib", - "out/soong/.intermediates/defaults/rust/libcompiler_builtins/android_arm64_armv8-a_rlib/libcompiler_builtins.rlib", - "out/soong/.intermediates/defaults/rust/libcore/android_arm64_armv8-a_rlib/libcore.rlib", - "out/soong/.intermediates/defaults/rust/libgimli/android_arm64_armv8-a_rlib/libgimli.rlib", - "out/soong/.intermediates/defaults/rust/libhashbrown/android_arm64_armv8-a_rlib/libhashbrown.rlib", - "out/soong/.intermediates/defaults/rust/liblibc/android_arm64_armv8-a_rlib/liblibc.rlib", - "out/soong/.intermediates/defaults/rust/libmemchr/android_arm64_armv8-a_rlib/libmemchr.rlib", - "out/soong/.intermediates/defaults/rust/libminiz_oxide/android_arm64_armv8-a_rlib/libminiz_oxide.rlib", - "out/soong/.intermediates/defaults/rust/libobject/android_arm64_armv8-a_rlib/libobject.rlib", - "out/soong/.intermediates/defaults/rust/libpanic_unwind/android_arm64_armv8-a_rlib/libpanic_unwind.rlib", - "out/soong/.intermediates/defaults/rust/librustc_demangle/android_arm64_armv8-a_rlib/librustc_demangle.rlib", - "out/soong/.intermediates/defaults/rust/librustc_std_workspace_alloc/android_arm64_armv8-a_rlib/librustc_std_workspace_alloc.rlib", - "out/soong/.intermediates/defaults/rust/librustc_std_workspace_core/android_arm64_armv8-a_rlib/librustc_std_workspace_core.rlib", - "out/soong/.intermediates/defaults/rust/libstd_detect/android_arm64_armv8-a_rlib/libstd_detect.rlib", - "build/soong/scripts/mkcratersp.py", - "defaults/rust/linux-x86/1.69.0/bin/rustc", - "defaults/rust/linux-x86/1.69.0/lib/libstd.so", - "defaults/rust/linux-x86/1.69.0/lib64/libc++.so.1", - } - sboxCompilationFilesWithCc = []string{ - "defaults/cc/common", - "out/soong/.intermediates/defaults/cc/common/libc/android_arm64_armv8-a_shared/libc.so", - "out/soong/.intermediates/defaults/cc/common/libc/android_arm64_armv8-a_shared/libc.so.toc", - "out/soong/.intermediates/defaults/cc/common/libdl/android_arm64_armv8-a_shared/libdl.so", - "out/soong/.intermediates/defaults/cc/common/libdl/android_arm64_armv8-a_shared/libdl.so.toc", - "out/soong/.intermediates/defaults/cc/common/libm/android_arm64_armv8-a_shared/libm.so", - "out/soong/.intermediates/defaults/cc/common/libm/android_arm64_armv8-a_shared/libm.so.toc", - "out/soong/.intermediates/defaults/rust/liblog/android_arm64_armv8-a_shared/liblog.so", - "out/soong/.intermediates/defaults/rust/liblog/android_arm64_armv8-a_shared/liblog.so.toc", - } -) - -func TestSandboxCompilation(t *testing.T) { - ctx := testRust(t, ` - filegroup { - name: "libsrcs1", - srcs: ["src_filegroup1.rs"], - } - filegroup { - name: "libsrcs2", - srcs: ["src_filegroup2.rs"], - } - rust_library { - name: "libfizz_buzz", - crate_name:"fizz_buzz", - crate_root: "foo.rs", - srcs: [ - "src_lib*.rs", - ":libsrcs1", - ":libsrcs2", - ], - compile_data: [ - "compile_data1.txt", - "compile_data2.txt", - ], - dylib: { - srcs: ["dylib_only.rs"], - }, - rlib: { - srcs: ["rlib_only.rs"], - }, - } - rust_binary { - name: "fizz_buzz", - crate_name:"fizz_buzz", - crate_root: "foo.rs", - srcs: [ - "src_lib*.rs", - ":libsrcs1", - ":libsrcs2", - ], - } - rust_ffi { - name: "librust_ffi", - crate_name: "rust_ffi", - crate_root: "foo.rs", - static: { - srcs: ["static_only.rs"], - }, - shared: { - srcs: ["shared_only.rs"], - }, - srcs: ["src1.rs"], - } - cc_library_static { - name: "cc_dep_static", - } - cc_library_shared { - name: "cc_dep_shared", - } - rust_library { - name: "libfizz_buzz_cc_deps", - crate_name:"fizz_buzz", - crate_root: "foo.rs", - srcs: ["src*.rs"], - shared_libs: ["cc_dep_shared"], - static_libs: ["cc_dep_static"], - } - rust_library { - name: "libfizz_buzz_intermediate_cc_deps", - crate_name:"fizz_buzz", - crate_root: "foo.rs", - srcs: ["src*.rs"], - rustlibs: ["libfizz_buzz_cc_deps"], - } - rust_library { - name: "libfizz_buzz_transitive_cc_deps", - crate_name:"fizz_buzz", - crate_root: "foo.rs", - srcs: ["src*.rs"], - rustlibs: ["libfizz_buzz_intermediate_cc_deps"], - } - `, - android.FixtureMergeMockFs(android.MockFS{ - "src_lib1.rs": nil, - "src_lib2.rs": nil, - "src_lib3.rs": nil, - "src_lib4.rs": nil, - "src_filegroup1.rs": nil, - "src_filegroup2.rs": nil, - "static_only.rs": nil, - "shared_only.rs": nil, - }), - ) - - testcases := []struct { - name string - moduleName string - variant string - rustcExpectedFilesToCopy []string - expectedFlags []string - }{ - { - name: "rust_library (dylib)", - moduleName: "libfizz_buzz", - variant: "android_arm64_armv8-a_dylib", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, sboxCompilationFilesWithCc, []string{ - "foo.rs", - "src_lib1.rs", - "src_lib2.rs", - "src_lib3.rs", - "src_lib4.rs", - "src_filegroup1.rs", - "src_filegroup2.rs", - "compile_data1.txt", - "compile_data2.txt", - "dylib_only.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/out/src_filegroup1.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/out/src_filegroup2.rs", - - "out/soong/.intermediates/defaults/cc/common/libc/android_arm64_armv8-a_shared/libc.so", - "out/soong/.intermediates/defaults/cc/common/libc/android_arm64_armv8-a_shared/libc.so.toc", - "out/soong/.intermediates/defaults/cc/common/libm/android_arm64_armv8-a_shared/libm.so", - "out/soong/.intermediates/defaults/cc/common/libm/android_arm64_armv8-a_shared/libm.so.toc", - "out/soong/.intermediates/defaults/cc/common/libdl/android_arm64_armv8-a_shared/libdl.so", - "out/soong/.intermediates/defaults/cc/common/libdl/android_arm64_armv8-a_shared/libdl.so.toc", - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_dylib/unstripped/libstd.dylib.so", - "out/soong/.intermediates/defaults/cc/common/crtbegin_so/android_arm64_armv8-a/crtbegin_so.o", - "out/soong/.intermediates/defaults/cc/common/crtend_so/android_arm64_armv8-a/crtend_so.o", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.clippy", - }), - expectedFlags: []string{ - "-C linker=build/soong/scripts/mkcratersp.py", - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/libfizz_buzz.dylib.so.rsp", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/libfizz_buzz.dylib.so.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_library (rlib dylib-std)", - moduleName: "libfizz_buzz", - variant: "android_arm64_armv8-a_rlib_dylib-std", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, []string{ - "foo.rs", - "src_lib1.rs", - "src_lib2.rs", - "src_lib3.rs", - "src_lib4.rs", - "src_filegroup1.rs", - "src_filegroup2.rs", - "rlib_only.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/out/src_filegroup1.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/out/src_filegroup2.rs", - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_dylib/unstripped/libstd.dylib.so", - }), - expectedFlags: []string{ - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/libfizz_buzz.rlib", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/libfizz_buzz.rlib.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_library (rlib rlib-std)", - moduleName: "libfizz_buzz", - variant: "android_arm64_armv8-a_rlib_rlib-std", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, []string{ - "foo.rs", - "src_lib1.rs", - "src_lib2.rs", - "src_lib3.rs", - "src_lib4.rs", - "src_filegroup1.rs", - "src_filegroup2.rs", - "rlib_only.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/out/src_filegroup1.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/out/src_filegroup2.rs", - "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/libfizz_buzz.rlib.clippy", - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_rlib/libstd.rlib", - }), - expectedFlags: []string{ - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/libfizz_buzz.rlib", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/libfizz_buzz.rlib.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_binary", - moduleName: "fizz_buzz", - variant: "android_arm64_armv8-a", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, sboxCompilationFilesWithCc, []string{ - "foo.rs", - "src_lib1.rs", - "src_lib2.rs", - "src_lib3.rs", - "src_lib4.rs", - "src_filegroup1.rs", - "src_filegroup2.rs", - "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/out/src_filegroup1.rs", - "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/out/src_filegroup2.rs", - - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_dylib/unstripped/libstd.dylib.so", - "out/soong/.intermediates/defaults/cc/common/crtbegin_dynamic/android_arm64_armv8-a/crtbegin_dynamic.o", - "out/soong/.intermediates/defaults/cc/common/crtend_android/android_arm64_armv8-a/crtend_android.o", - "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.clippy", - }), - expectedFlags: []string{ - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/fizz_buzz", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/fizz_buzz.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_ffi static lib variant", - moduleName: "librust_ffi", - variant: "android_arm64_armv8-a_static", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, []string{ - "foo.rs", - "src1.rs", - "static_only.rs", - "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a.clippy", - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_rlib/libstd.rlib", - }), - expectedFlags: []string{ - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/librust_ffi.a", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/librust_ffi.a.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_ffi shared lib variant", - moduleName: "librust_ffi", - variant: "android_arm64_armv8-a_shared", - rustcExpectedFilesToCopy: android.Concat(sboxCompilationFiles, sboxCompilationFilesWithCc, []string{ - "foo.rs", - "src1.rs", - "shared_only.rs", - - "out/soong/.intermediates/defaults/rust/libstd/android_arm64_armv8-a_dylib/unstripped/libstd.dylib.so", - "out/soong/.intermediates/defaults/cc/common/crtbegin_so/android_arm64_armv8-a/crtbegin_so.o", - "out/soong/.intermediates/defaults/cc/common/crtend_so/android_arm64_armv8-a/crtend_so.o", - "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.clippy", - }), - expectedFlags: []string{ - "--emit link", - "-o __SBOX_SANDBOX_DIR__/out/librust_ffi.so", - "--emit dep-info=__SBOX_SANDBOX_DIR__/out/librust_ffi.so.d.raw", - "foo.rs", // this is the entry point - }, - }, - { - name: "rust_library with cc deps (dylib)", - moduleName: "libfizz_buzz_cc_deps", - variant: "android_arm64_armv8-a_dylib", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - { - name: "rust_library with cc deps (rlib rlib-std)", - moduleName: "libfizz_buzz_cc_deps", - variant: "android_arm64_armv8-a_rlib_rlib-std", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - { - name: "rust_library with cc deps (rlib dylib-std)", - moduleName: "libfizz_buzz_cc_deps", - variant: "android_arm64_armv8-a_rlib_dylib-std", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - { - name: "rust_library with transitive cc deps (dylib)", - moduleName: "libfizz_buzz_transitive_cc_deps", - variant: "android_arm64_armv8-a_dylib", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - { - name: "rust_library with transitive cc deps (rlib rlib-std)", - moduleName: "libfizz_buzz_transitive_cc_deps", - variant: "android_arm64_armv8-a_rlib_rlib-std", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - { - name: "rust_library with transitive cc deps (rlib dylib-std)", - moduleName: "libfizz_buzz_transitive_cc_deps", - variant: "android_arm64_armv8-a_rlib_dylib-std", - rustcExpectedFilesToCopy: []string{ - "out/soong/.intermediates/cc_dep_static/android_arm64_armv8-a_static/cc_dep_static.a", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so", - "out/soong/.intermediates/cc_dep_shared/android_arm64_armv8-a_shared/cc_dep_shared.so.toc", - }, - }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - writeFile := ctx.ModuleForTests(tc.moduleName, tc.variant).Rule("unescapedWriteFile") - contents := writeFile.BuildParams.Args["content"] - manifestProto := sbox_proto.Manifest{} - err := prototext.Unmarshal([]byte(contents), &manifestProto) - if err != nil { - t.Errorf("expected no errors unmarshaling manifest proto; got %v", err) - } - - if len(manifestProto.Commands) != 1 { - t.Errorf("expected 1 command; got %v", len(manifestProto.Commands)) - } - - // check that sandbox contains correct files - rustc := manifestProto.Commands[0] - actualFilesToCopy := []string{} - for _, copy := range rustc.CopyBefore { - actualFilesToCopy = append(actualFilesToCopy, copy.GetFrom()) - } - _, expectedFilesNotCopied, _ := android.ListSetDifference(tc.rustcExpectedFilesToCopy, actualFilesToCopy) - if len(expectedFilesNotCopied) > 0 { - t.Errorf("did not copy expected files to sbox: %v;\n files copied: %v", expectedFilesNotCopied, actualFilesToCopy) - } - - rustcCmd := proptools.String(rustc.Command) - for _, flag := range tc.expectedFlags { - android.AssertStringDoesContain( - t, - fmt.Sprintf( - "missing flag in rustc invocation; expected to find substring %q; got %q", - flag, - rustcCmd, - ), - rustcCmd, - flag, - ) - } - }) - } -} diff --git a/rust/sanitize_test.go b/rust/sanitize_test.go index d6a14b295..43e95f477 100644 --- a/rust/sanitize_test.go +++ b/rust/sanitize_test.go @@ -35,7 +35,7 @@ func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNo note_sync := "note_memtag_heap_sync" found := None - implicits := m.Rule("rustc").Implicits + implicits := m.Rule("rustLink").Implicits for _, lib := range implicits { if strings.Contains(lib.Rel(), note_async) { found = Async diff --git a/rust/testing.go b/rust/testing.go index 9951937be..3fe751e17 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -52,22 +52,6 @@ var PrepareForTestWithRustIncludeVndk = android.GroupFixturePreparers( func GatherRequiredDepsForTest() string { bp := ` - prebuilt_build_tool { - name: "rustc", - src: "linux-x86/1.69.0/bin/rustc", - deps: [ - "linux-x86/1.69.0/lib/libstd.so", - "linux-x86/1.69.0/lib64/libc++.so.1", - ], - } - prebuilt_build_tool { - name: "clippy-driver", - src: "linux-x86/1.69.0/bin/clippy-driver", - } - prebuilt_build_tool { - name: "rustdoc", - src: "linux-x86/1.69.0/bin/rustdoc", - } rust_prebuilt_library { name: "libstd", crate_name: "std", @@ -79,25 +63,6 @@ func GatherRequiredDepsForTest() string { }, host_supported: true, sysroot: true, - rlibs: [ - "libaddr2line", - "libadler", - "liballoc", - "libcfg_if", - "libcompiler_builtins", - "libcore", - "libgimli", - "libhashbrown", - "liblibc", - "libmemchr", - "libminiz_oxide", - "libobject", - "libpanic_unwind", - "librustc_demangle", - "librustc_std_workspace_alloc", - "librustc_std_workspace_core", - "libstd_detect", - ], } ////////////////////////////// // Device module requirements @@ -134,278 +99,6 @@ func GatherRequiredDepsForTest() string { nocrt: true, system_shared_libs: [], } - rust_library_rlib { - name: "libaddr2line", - crate_name: "addr2line", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libadler", - crate_name: "adler", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "liballoc", - crate_name: "alloc", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libcfg_if", - crate_name: "cfg_if", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libcompiler_builtins", - crate_name: "compiler_builtins", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libcore", - crate_name: "core", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libgimli", - crate_name: "gimli", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libhashbrown", - crate_name: "hashbrown", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "liblibc", - crate_name: "libc", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libmemchr", - crate_name: "memchr", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libminiz_oxide", - crate_name: "miniz_oxide", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libobject", - crate_name: "object", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libpanic_unwind", - crate_name: "panic_unwind", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "librustc_demangle", - crate_name: "rustc_demangle", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "librustc_std_workspace_alloc", - crate_name: "rustc_std_workspace_alloc", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "librustc_std_workspace_core", - crate_name: "rustc_std_workspace_core", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } - rust_library_rlib { - name: "libstd_detect", - crate_name: "std_detect", - enabled:true, - srcs: ["foo.rs"], - no_stdlibs: true, - product_available: true, - host_supported: true, - vendor_available: true, - vendor_ramdisk_available: true, - recovery_available: true, - native_coverage: false, - sysroot: true, - apex_available: ["//apex_available:platform", "//apex_available:anyapex"], - min_sdk_version: "29", - } rust_library { name: "libstd", crate_name: "std", @@ -420,25 +113,6 @@ func GatherRequiredDepsForTest() string { sysroot: true, apex_available: ["//apex_available:platform", "//apex_available:anyapex"], min_sdk_version: "29", - rlibs: [ - "libaddr2line", - "libadler", - "liballoc", - "libcfg_if", - "libcompiler_builtins", - "libcore", - "libgimli", - "libhashbrown", - "liblibc", - "libmemchr", - "libminiz_oxide", - "libobject", - "libpanic_unwind", - "librustc_demangle", - "librustc_std_workspace_alloc", - "librustc_std_workspace_core", - "libstd_detect", - ], } rust_library { name: "libtest", diff --git a/rust/toolchain_library.go b/rust/toolchain_library.go index cb345a4b6..054104ccc 100644 --- a/rust/toolchain_library.go +++ b/rust/toolchain_library.go @@ -89,7 +89,7 @@ func initToolchainLibrary(module *Module, library *libraryDecorator) android.Mod func rustSetToolchainSource(ctx android.LoadHookContext) { if toolchainLib, ok := ctx.Module().(*Module).compiler.(*toolchainLibraryDecorator); ok { - prefix := filepath.Join(config.HostPrebuiltTag(ctx.Config()), GetRustPrebuiltVersion(ctx)) + prefix := filepath.Join("linux-x86", GetRustPrebuiltVersion(ctx)) versionedCrateRoot := path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_crate_root)) versionedSrcs := make([]string, len(toolchainLib.Properties.Toolchain_srcs)) for i, src := range toolchainLib.Properties.Toolchain_srcs { diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go index 621a7246c..1e7e7d322 100644 --- a/rust/vendor_snapshot_test.go +++ b/rust/vendor_snapshot_test.go @@ -1051,7 +1051,7 @@ func TestVendorSnapshotUse(t *testing.T) { ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31") // libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot - libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").RuleParams.Command + libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustLink").Args["linkFlags"] for _, input := range [][]string{ []string{sharedVariant, "libvndk.vndk.30.arm64"}, []string{staticVariant, "libvendor.vendor_static.30.arm64"}, @@ -1119,7 +1119,7 @@ func TestVendorSnapshotUse(t *testing.T) { t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName) } - binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").RuleParams.Command + binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"] libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"}) if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) { t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v", diff --git a/ui/build/build.go b/ui/build/build.go index 14d23a7da..9d5c330e1 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -15,11 +15,13 @@ package build import ( + "fmt" "io/ioutil" "os" "path/filepath" "sync" "text/template" + "time" "android/soong/ui/metrics" ) @@ -29,6 +31,7 @@ import ( func SetupOutDir(ctx Context, config Config) { ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk")) ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk")) + ensureEmptyDirectoriesExist(ctx, config.TempDir()) // Potentially write a marker file for whether kati is enabled. This is used by soong_build to // potentially run the AndroidMk singleton and postinstall commands. @@ -56,6 +59,31 @@ func SetupOutDir(ctx Context, config Config) { } else { ctx.Fatalln("Missing BUILD_DATETIME_FILE") } + + // BUILD_NUMBER should be set to the source control value that + // represents the current state of the source code. E.g., a + // perforce changelist number or a git hash. Can be an arbitrary string + // (to allow for source control that uses something other than numbers), + // but must be a single word and a valid file name. + // + // If no BUILD_NUMBER is set, create a useful "I am an engineering build + // from this date/time" value. Make it start with a non-digit so that + // anyone trying to parse it as an integer will probably get "0". + buildNumber, ok := config.environ.Get("BUILD_NUMBER") + if ok { + writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", buildNumber) + } else { + var username string + if username, ok = config.environ.Get("BUILD_USERNAME"); !ok { + ctx.Fatalln("Missing BUILD_USERNAME") + } + buildNumber = fmt.Sprintf("eng.%.6s.%s", username, time.Now().Format("20060102.150405" /* YYYYMMDD.HHMMSS */)) + writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username) + } + // Write the build number to a file so it can be read back in + // without changing the command line every time. Avoids rebuilds + // when using ninja. + writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber) } var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(` @@ -246,8 +274,6 @@ func Build(ctx Context, config Config) { // checkCaseSensitivity issues a warning if a case-insensitive file system is being used. checkCaseSensitivity(ctx, config) - ensureEmptyDirectoriesExist(ctx, config.TempDir()) - SetupPath(ctx, config) what := evaluateWhatToRun(config, ctx.Verboseln) diff --git a/ui/build/config.go b/ui/build/config.go index 084d28d83..f80868c33 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -22,6 +22,7 @@ import ( "math/rand" "os" "os/exec" + "os/user" "path/filepath" "runtime" "strconv" @@ -455,6 +456,16 @@ func NewConfig(ctx Context, args ...string) Config { ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile) + if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok { + username := "unknown" + if u, err := user.Current(); err == nil { + username = u.Username + } else { + ctx.Println("Failed to get current user:", err) + } + ret.environ.Set("BUILD_USERNAME", username) + } + if ret.UseRBE() { for k, v := range getRBEVars(ctx, Config{ret}) { ret.environ.Set(k, v) diff --git a/ui/build/kati.go b/ui/build/kati.go index aea56d31a..31e744029 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -15,6 +15,8 @@ package build import ( + "android/soong/ui/metrics" + "android/soong/ui/status" "crypto/md5" "fmt" "io/ioutil" @@ -22,10 +24,6 @@ import ( "os/user" "path/filepath" "strings" - "time" - - "android/soong/ui/metrics" - "android/soong/ui/status" ) var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_") @@ -198,32 +196,14 @@ func runKati(ctx Context, config Config, extraSuffix string, args []string, envF } } writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname) - - // BUILD_NUMBER should be set to the source control value that - // represents the current state of the source code. E.g., a - // perforce changelist number or a git hash. Can be an arbitrary string - // (to allow for source control that uses something other than numbers), - // but must be a single word and a valid file name. - // - // If no BUILD_NUMBER is set, create a useful "I am an engineering build - // from this date/time" value. Make it start with a non-digit so that - // anyone trying to parse it as an integer will probably get "0". - cmd.Environment.Unset("HAS_BUILD_NUMBER") - buildNumber, ok := cmd.Environment.Get("BUILD_NUMBER") + _, ok = cmd.Environment.Get("BUILD_NUMBER") // Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file. cmd.Environment.Unset("BUILD_NUMBER") if ok { cmd.Environment.Set("HAS_BUILD_NUMBER", "true") - writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", buildNumber) } else { - buildNumber = fmt.Sprintf("eng.%.6s.%s", username, time.Now().Format("20060102.150405" /* YYYYMMDD.HHMMSS */)) cmd.Environment.Set("HAS_BUILD_NUMBER", "false") - writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username) } - // Write the build number to a file so it can be read back in - // without changing the command line every time. Avoids rebuilds - // when using ninja. - writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber) // Apply the caller's function closure to mutate the environment variables. envFunc(cmd.Environment) |