diff options
137 files changed, 4499 insertions, 1464 deletions
diff --git a/aconfig/Android.bp b/aconfig/Android.bp index d2ddfdfc6..faa4ddbb6 100644 --- a/aconfig/Android.bp +++ b/aconfig/Android.bp @@ -32,6 +32,8 @@ bootstrap_go_package { "aconfig_values_test.go", "aconfig_value_set_test.go", "java_aconfig_library_test.go", + "cc_aconfig_library_test.go", + "rust_aconfig_library_test.go", ], pluginFor: ["soong_build"], } diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go index 5cdf5b605..f19ddb8be 100644 --- a/aconfig/aconfig_declarations.go +++ b/aconfig/aconfig_declarations.go @@ -15,16 +15,18 @@ package aconfig import ( - "android/soong/android" "fmt" "strings" + "android/soong/android" + "android/soong/bazel" "github.com/google/blueprint" ) type DeclarationsModule struct { android.ModuleBase android.DefaultableModuleBase + android.BazelModuleBase // Properties for "aconfig_declarations" properties struct { @@ -47,8 +49,7 @@ func DeclarationsFactory() android.Module { android.InitAndroidModule(module) android.InitDefaultableModule(module) module.AddProperties(&module.properties) - // TODO: bp2build - //android.InitBazelModule(module) + android.InitBazelModule(module) return module } @@ -73,7 +74,9 @@ func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that // match our package. valuesFromConfig := ctx.Config().ReleaseAconfigValueSets() - ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...) + if valuesFromConfig != "" { + ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig) + } } func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) { @@ -159,3 +162,26 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module }) } + +type bazelAconfigDeclarationsAttributes struct { + Srcs bazel.LabelListAttribute + Package string +} + +func (module *DeclarationsModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if ctx.ModuleType() != "aconfig_declarations" { + return + } + srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, module.properties.Srcs)) + + attrs := bazelAconfigDeclarationsAttributes{ + Srcs: srcs, + Package: module.properties.Package, + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "aconfig_declarations", + Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_declarations.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs) +} diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go index 252908fa3..cd178d480 100644 --- a/aconfig/aconfig_value_set.go +++ b/aconfig/aconfig_value_set.go @@ -16,6 +16,7 @@ package aconfig import ( "android/soong/android" + "android/soong/bazel" "github.com/google/blueprint" ) @@ -23,6 +24,7 @@ import ( type ValueSetModule struct { android.ModuleBase android.DefaultableModuleBase + android.BazelModuleBase properties struct { // aconfig_values modules @@ -36,8 +38,7 @@ func ValueSetFactory() android.Module { android.InitAndroidModule(module) android.InitDefaultableModule(module) module.AddProperties(&module.properties) - // TODO: bp2build - //android.InitBazelModule(module) + android.InitBazelModule(module) return module } @@ -90,3 +91,23 @@ func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleCont AvailablePackages: packages, }) } + +type bazelAconfigValueSetAttributes struct { + Values bazel.LabelListAttribute +} + +func (module *ValueSetModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if ctx.ModuleType() != "aconfig_value_set" { + return + } + + attrs := bazelAconfigValueSetAttributes{ + Values: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, module.properties.Values)), + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "aconfig_value_set", + Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_value_set.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs) +} diff --git a/aconfig/aconfig_values.go b/aconfig/aconfig_values.go index 91f1c9098..03a930dbd 100644 --- a/aconfig/aconfig_values.go +++ b/aconfig/aconfig_values.go @@ -16,6 +16,7 @@ package aconfig import ( "android/soong/android" + "android/soong/bazel" "github.com/google/blueprint" ) @@ -23,6 +24,7 @@ import ( type ValuesModule struct { android.ModuleBase android.DefaultableModuleBase + android.BazelModuleBase properties struct { // aconfig files, relative to this Android.bp file @@ -39,8 +41,7 @@ func ValuesFactory() android.Module { android.InitAndroidModule(module) android.InitDefaultableModule(module) module.AddProperties(&module.properties) - // TODO: bp2build - //android.InitBazelModule(module) + android.InitBazelModule(module) return module } @@ -68,3 +69,27 @@ func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContex } ctx.SetProvider(valuesProviderKey, providerData) } + +type bazelAconfigValuesAttributes struct { + Srcs bazel.LabelListAttribute + Package string +} + +func (module *ValuesModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if ctx.ModuleType() != "aconfig_values" { + return + } + + srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, module.properties.Srcs)) + + attrs := bazelAconfigValuesAttributes{ + Srcs: srcs, + Package: module.properties.Package, + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "aconfig_values", + Bzl_load_location: "//build/bazel/rules/aconfig:aconfig_values.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs) +} diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go index 14090bc90..0583befc0 100644 --- a/aconfig/cc_aconfig_library.go +++ b/aconfig/cc_aconfig_library.go @@ -16,8 +16,11 @@ package aconfig import ( "android/soong/android" + "android/soong/bazel" "android/soong/cc" + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "fmt" "strings" @@ -29,9 +32,14 @@ type ccDeclarationsTagType struct { var ccDeclarationsTag = ccDeclarationsTagType{} +const baseLibDep = "server_configurable_flags" + type CcAconfigLibraryProperties struct { // name of the aconfig_declarations module to generate a library for Aconfig_declarations string + + // whether to generate test mode version of the library + Test *bool } type CcAconfigLibraryCallbacks struct { @@ -67,7 +75,7 @@ func (this *CcAconfigLibraryCallbacks) GeneratorDeps(ctx cc.DepsContext, deps cc } // Add a dependency for the aconfig flags base library - deps.SharedLibs = append(deps.SharedLibs, "server_configurable_flags") + deps.SharedLibs = append(deps.SharedLibs, baseLibDep) // TODO: It'd be really nice if we could reexport this library and not make everyone do it. return deps @@ -113,6 +121,12 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex } declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) + var mode string + if proptools.Bool(this.properties.Test) { + mode = "test" + } else { + mode = "production" + } ctx.Build(pctx, android.BuildParams{ Rule: cppRule, Input: declarations.IntermediatePath, @@ -123,6 +137,37 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex Description: "cc_aconfig_library", Args: map[string]string{ "gendir": this.generatedDir.String(), + "mode": mode, }, }) } + +type bazelCcAconfigLibraryAttributes struct { + Aconfig_declarations bazel.LabelAttribute + Dynamic_deps bazel.LabelListAttribute +} + +// Convert the cc_aconfig_library module to bazel. +// +// This method is called from cc.ConvertWithBp2build to actually convert the +// cc_aconfig_library module. This is necessary since the factory method of this +// module type returns a cc library and the bp2build conversion is called on the +// cc library type. + +func (this *CcAconfigLibraryCallbacks) GeneratorBp2build(ctx android.Bp2buildMutatorContext) bool { + if ctx.ModuleType() != "cc_aconfig_library" { + return false + } + + attrs := bazelCcAconfigLibraryAttributes{ + Aconfig_declarations: *bazel.MakeLabelAttribute(android.BazelLabelForModuleDepSingle(ctx, this.properties.Aconfig_declarations).Label), + Dynamic_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, []string{baseLibDep})), + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_aconfig_library", + Bzl_load_location: "//build/bazel/rules/cc:cc_aconfig_library.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: ctx.ModuleName()}, &attrs) + return true +} diff --git a/aconfig/cc_aconfig_library_test.go b/aconfig/cc_aconfig_library_test.go new file mode 100644 index 000000000..6f17c7594 --- /dev/null +++ b/aconfig/cc_aconfig_library_test.go @@ -0,0 +1,67 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package aconfig + +import ( + "fmt" + "testing" + + "android/soong/android" + "android/soong/cc" +) + +var codegenModeTestData = []struct { + setting, expected string +}{ + {"", "production"}, + {"test: false,", "production"}, + {"test: true,", "test"}, +} + +func TestCCCodegenMode(t *testing.T) { + for _, testData := range codegenModeTestData { + testCCCodegenModeHelper(t, testData.setting, testData.expected) + } +} + +func testCCCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) { + t.Helper() + result := android.GroupFixturePreparers( + PrepareForTestWithAconfigBuildComponents, + cc.PrepareForTestWithCcDefaultModules). + ExtendWithErrorHandler(android.FixtureExpectsNoErrors). + RunTestWithBp(t, fmt.Sprintf(` + aconfig_declarations { + name: "my_aconfig_declarations", + package: "com.example.package", + srcs: ["foo.aconfig"], + } + + cc_library { + name: "server_configurable_flags", + srcs: ["server_configurable_flags.cc"], + } + + cc_aconfig_library { + name: "my_cc_aconfig_library", + aconfig_declarations: "my_aconfig_declarations", + %s + } + `, bpMode)) + + module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared") + rule := module.Rule("cc_aconfig_library") + android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode) +} diff --git a/aconfig/init.go b/aconfig/init.go index 797388d6c..3d62714bc 100644 --- a/aconfig/init.go +++ b/aconfig/init.go @@ -64,13 +64,14 @@ var ( Command: `rm -rf ${gendir}` + ` && mkdir -p ${gendir}` + ` && ${aconfig} create-cpp-lib` + + ` --mode ${mode}` + ` --cache ${in}` + ` --out ${gendir}`, CommandDeps: []string{ "$aconfig", "$soong_zip", }, - }, "gendir") + }, "gendir", "mode") rustRule = pctx.AndroidStaticRule("rust_aconfig_library", blueprint.RuleParams{ @@ -97,12 +98,12 @@ var ( ) func init() { - registerBuildComponents(android.InitRegistrationContext) + RegisterBuildComponents(android.InitRegistrationContext) pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("soong_zip", "soong_zip") } -func registerBuildComponents(ctx android.RegistrationContext) { +func RegisterBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory) ctx.RegisterModuleType("aconfig_values", ValuesFactory) ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory) diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go index 17385c3d1..90b09c814 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.AssertStringEquals( + android.AssertStringListContains( 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/aconfig/testing.go b/aconfig/testing.go index 60cefeb2b..f6489ec3f 100644 --- a/aconfig/testing.go +++ b/aconfig/testing.go @@ -20,7 +20,7 @@ import ( "android/soong/android" ) -var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents) +var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents) func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult { return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents). diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go index 7449d678c..2c0aef77f 100644 --- a/aidl_library/aidl_library.go +++ b/aidl_library/aidl_library.go @@ -64,7 +64,7 @@ type bazelAidlLibraryAttributes struct { Deps bazel.LabelListAttribute } -func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (lib *AidlLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { srcs := bazel.MakeLabelListAttribute( android.BazelLabelForModuleSrc( ctx, diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 8dbb64137..5c8e5e31c 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -65,6 +65,7 @@ var ( "build/bazel": Bp2BuildDefaultTrueRecursively, "build/make/target/product/security": Bp2BuildDefaultTrue, + "build/make/tools": Bp2BuildDefaultTrue, "build/make/tools/protos": Bp2BuildDefaultTrue, "build/make/tools/releasetools": Bp2BuildDefaultTrue, "build/make/tools/sbom": Bp2BuildDefaultTrue, @@ -79,7 +80,9 @@ var ( "build/soong/scripts": Bp2BuildDefaultTrueRecursively, "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively, - "cts/libs/json": Bp2BuildDefaultTrueRecursively, + "cts/libs/json": Bp2BuildDefaultTrueRecursively, + "cts/tests/tests/gesture": Bp2BuildDefaultTrueRecursively, + "platform_testing/libraries/annotations": Bp2BuildDefaultTrueRecursively, "dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively, @@ -193,6 +196,7 @@ var ( "external/openscreen": Bp2BuildDefaultTrueRecursively, "external/ow2-asm": Bp2BuildDefaultTrueRecursively, "external/pcre": Bp2BuildDefaultTrueRecursively, + "external/perfmark/api": Bp2BuildDefaultTrueRecursively, "external/protobuf": Bp2BuildDefaultTrueRecursively, "external/python/pyyaml/lib/yaml": Bp2BuildDefaultTrueRecursively, "external/python/six": Bp2BuildDefaultTrueRecursively, @@ -336,6 +340,7 @@ var ( "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively, "prebuilts/gradle-plugin": Bp2BuildDefaultTrueRecursively, "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively, + "prebuilts/module_sdk": Bp2BuildDefaultTrueRecursively, "prebuilts/sdk": Bp2BuildDefaultTrue, "prebuilts/sdk/current/androidx": Bp2BuildDefaultTrue, "prebuilts/sdk/current/androidx-legacy": Bp2BuildDefaultTrue, @@ -428,6 +433,7 @@ var ( "tools/apifinder": Bp2BuildDefaultTrue, "tools/apksig": Bp2BuildDefaultTrue, + "tools/dexter/slicer": Bp2BuildDefaultTrueRecursively, "tools/external_updater": Bp2BuildDefaultTrueRecursively, "tools/metalava": Bp2BuildDefaultTrueRecursively, "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively, @@ -848,6 +854,10 @@ var ( "libstagefright_headers", + // Apps with JNI libs + "SimpleJNI", + "libsimplejni", + // aidl "aidl", "libaidl-common", @@ -891,24 +901,79 @@ var ( "merge_annotation_zips_test", - // bouncycastle dep - "platform-test-annotations", - // java_resources with multiple resource_dirs "emma", + + // NDK STL + "ndk_libc++abi", + "ndk_libunwind", + "ndk_libc++_static", + "ndk_libc++_shared", + "ndk_system", + + // allowlist //prebuilts/common/misc/androidx-test/... + "androidx.test.runner", + "androidx.test.runner-nodeps", + "androidx.test.services.storage", + "androidx.test.services.storage-nodeps", + "androidx.test.monitor", + "androidx.test.monitor-nodeps", + "androidx.test.annotation", + "androidx.test.annotation-nodeps", + + // jni deps of an internal android_test (b/297405812) + "libdexmakerjvmtiagent", + "libopenjdkjvmti_headers", + "libstaticjvmtiagent", + + // tradefed deps + "tradefed-protos", + "grpc-java", + "grpc-java-api", + "grpc-java-auth", + "grpc-java-context", + "grpc-java-core", + "grpc-java-core-inprocess", + "grpc-java-core-internal", + "grpc-java-core-util", + "grpc-java-protobuf", + "grpc-java-protobuf-lite", + "grpc-java-stub", + "grpc-java-annotation-stubs", + "grpc-java-annotation-stubs-srcjar", + "gen_annotations", + "opencensus-java-contrib-grpc-metrics", + "opencensus-java-api", + "gson", + "GsonBuildConfig.java", + "gson_version_generator", } Bp2buildModuleTypeAlwaysConvertList = []string{ + // go/keep-sorted start + "aconfig_declarations", + "aconfig_value_set", + "aconfig_values", "aidl_interface_headers", "bpf", + "cc_aconfig_library", + "cc_prebuilt_library", + "cc_prebuilt_library_headers", + "cc_prebuilt_library_shared", + "cc_prebuilt_library_static", "combined_apis", - "license", - "linker_config", + "droiddoc_exported_dir", "java_import", "java_import_host", "java_sdk_library", + "java_sdk_library_import", + "license", + "linker_config", + "ndk_library", + "ndk_headers", "sysprop_library", "xsd_config", + // go/keep-sorted end } // Add the names of modules that bp2build should never convert, if it is @@ -984,7 +1049,6 @@ var ( "conscrypt-for-host", // TODO(b/210751803), we don't handle path property for filegroups "host-libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups "libprotobuf-internal-python-srcs", // TODO(b/210751803), we don't handle path property for filegroups - "libprotobuf-java-util-full", // TODO(b/210751803), we don't handle path property for filegroups // go deps: "analyze_bcpf", // depends on bpmodify a blueprint_go_binary. @@ -1637,6 +1701,20 @@ var ( // TODO(b/299974637) Fix linking error "libbinder_rpc_unstable", + + // TODO(b/297356704) sdk_version is unset. + "VendorAtomCodeGenJavaTest", + + // android_test from allowlisted packages, but with unconverted deps + "MtsLibnativehelperLazyTestCases", + "ObjenesisTck", + "DevCodelabTest", + "MtsTimeZoneDataTestCases", + "NanoAndroidTest", + "MtsLibnativehelperTestCases", + + // android_test_helper_app from allowlisted packages, but with unconverted deps + "SharedLibraryInfoTestApp", } // Bazel prod-mode allowlist. Modules in this list are built by Bazel diff --git a/android/bazel.go b/android/bazel.go index e764b1864..8634daba1 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -162,7 +162,7 @@ type Bazelable interface { // Modules must implement this function to be bp2build convertible. The function // must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or // its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible. - ConvertWithBp2build(ctx TopDownMutatorContext) + ConvertWithBp2build(ctx Bp2buildMutatorContext) // namespacedVariableProps is a map from a soong config variable namespace // (e.g. acme, android) to a map of interfaces{}, which are really diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 4b9834564..56ec17d02 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -665,7 +665,8 @@ func (context *mixedBuildBazelContext) createBazelCommand(config Config, runName command.expression, "--profile=" + shared.BazelMetricsFilename(context.paths, runName), - "--host_platform=@soong_injection//product_config_platforms:mixed_builds_product-" + context.targetBuildVariant + "_" + runtime.GOOS + "_x86_64", + "--host_platform=@soong_injection//product_config_platforms:mixed_builds_product_" + runtime.GOOS + "_x86_64", + "--//build/bazel/product_config:target_build_variant=" + context.targetBuildVariant, // Don't specify --platforms, because on some products/branches (like kernel-build-tools) // the main platform for mixed_builds_product-variant doesn't exist because an arch isn't // specified in product config. The derivative platforms that config_node transitions into @@ -720,9 +721,9 @@ func (context *mixedBuildBazelContext) mainBzlFileContents() []byte { ##################################################### def _config_node_transition_impl(settings, attr): if attr.os == "android" and attr.arch == "target": - target = "mixed_builds_product-{VARIANT}" + target = "mixed_builds_product" else: - target = "mixed_builds_product-{VARIANT}_%s_%s" % (attr.os, attr.arch) + target = "mixed_builds_product_%s_%s" % (attr.os, attr.arch) apex_name = "" if attr.within_apex: # //build/bazel/rules/apex:apex_name has to be set to a non_empty value, @@ -794,11 +795,7 @@ phony_root = rule( ) ` - productReplacer := strings.NewReplacer( - "{PRODUCT}", context.targetProduct, - "{VARIANT}", context.targetBuildVariant) - - return []byte(productReplacer.Replace(contents)) + return []byte(contents) } func (context *mixedBuildBazelContext) mainBuildFileContents() []byte { @@ -972,9 +969,9 @@ def get_arch(target): platform_name = platforms[0].name if platform_name == "host": return "HOST" - if not platform_name.startswith("mixed_builds_product-{TARGET_BUILD_VARIANT}"): - fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms)) - platform_name = platform_name.removeprefix("mixed_builds_product-{TARGET_BUILD_VARIANT}").removeprefix("_") + if not platform_name.startswith("mixed_builds_product"): + fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms)) + platform_name = platform_name.removeprefix("mixed_builds_product").removeprefix("_") config_key = "" if not platform_name: config_key = "target|android" @@ -983,7 +980,7 @@ def get_arch(target): elif platform_name.startswith("linux_"): config_key = platform_name.removeprefix("linux_") + "|linux" else: - fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms)) + fail("expected platform name of the form 'mixed_builds_product_android_<arch>' or 'mixed_builds_product_linux_<arch>', but was " + str(platforms)) within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex") apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version") @@ -1012,8 +1009,6 @@ def format(target): return id_string + ">>NONE" ` replacer := strings.NewReplacer( - "{TARGET_PRODUCT}", context.targetProduct, - "{TARGET_BUILD_VARIANT}", context.targetBuildVariant, "{LABEL_REGISTRATION_MAP_SECTION}", labelRegistrationMapSection, "{FUNCTION_DEF_SECTION}", functionDefSection, "{MAIN_SWITCH_SECTION}", mainSwitchSection) diff --git a/android/bazel_paths.go b/android/bazel_paths.go index 86829ce29..4ac58403c 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -487,6 +487,9 @@ func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) st if moduleDir == Bp2BuildTopLevel { moduleDir = "" } + if a, ok := module.(Module); ok && IsModulePrebuilt(a) { + moduleName = RemoveOptionalPrebuiltPrefix(moduleName) + } return fmt.Sprintf("//%s:%s", moduleDir, moduleName) } @@ -585,7 +588,7 @@ func PathsForBazelOut(ctx PathContext, paths []string) Paths { // For the first two cases, they are defined using the label attribute. For the third case, // it's defined with the string attribute. func BazelStringOrLabelFromProp( - ctx TopDownMutatorContext, + ctx Bp2buildMutatorContext, propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) { var labelAttr bazel.LabelAttribute diff --git a/android/bazel_test.go b/android/bazel_test.go index 15d3a6b52..e0145b527 100644 --- a/android/bazel_test.go +++ b/android/bazel_test.go @@ -469,7 +469,7 @@ func mixedBuildModuleFactory() Module { return m } -func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (m *mixedBuildModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) { } func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) { diff --git a/android/config.go b/android/config.go index 645a263cb..df282ec20 100644 --- a/android/config.go +++ b/android/config.go @@ -197,9 +197,22 @@ func (c Config) ReleaseVersion() string { return c.config.productVariables.ReleaseVersion } -// The flag values files passed to aconfig, derived from RELEASE_VERSION -func (c Config) ReleaseAconfigValueSets() []string { - return c.config.productVariables.ReleaseAconfigValueSets +// The aconfig value set passed to aconfig, derived from RELEASE_VERSION +func (c Config) ReleaseAconfigValueSets() string { + // This logic to handle both Soong module name and bazel target is temporary in order to + // provide backward compatibility where aosp and internal both have the release + // aconfig value set but can't be updated at the same time to use bazel target + value := strings.Split(c.config.productVariables.ReleaseAconfigValueSets, ":") + value_len := len(value) + if value_len > 2 { + // This shouldn't happen as this should be either a module name or a bazel target path. + panic(fmt.Errorf("config file: invalid value for release aconfig value sets: %s", + c.config.productVariables.ReleaseAconfigValueSets)) + } + if value_len > 0 { + return value[value_len-1] + } + return "" } // The flag default permission value passed to aconfig @@ -2060,6 +2073,11 @@ func (c *config) GetApiLibraries() map[string]struct{} { return c.apiLibraries } +// Bp2buildMode indicates whether the config is for bp2build mode of Soong +func (c *config) Bp2buildMode() bool { + return c.BuildMode == Bp2build +} + func (c *deviceConfig) CheckVendorSeappViolations() bool { return Bool(c.config.productVariables.CheckVendorSeappViolations) } diff --git a/android/defaults.go b/android/defaults.go index e0e6e5cf1..cc723f728 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -180,7 +180,7 @@ func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {} // ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are // *NOT* converted with bp2build -func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx Bp2buildMutatorContext) { // Defaults types are never convertible. ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") } diff --git a/android/depset_generic.go b/android/depset_generic.go index 45c193715..9f07596b5 100644 --- a/android/depset_generic.go +++ b/android/depset_generic.go @@ -95,6 +95,12 @@ 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 @@ -188,3 +194,14 @@ 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 6cc9232b6..a4bbcae99 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -93,7 +93,7 @@ func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) { } // ConvertWithBp2build performs bp2build conversion of filegroup -func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (fg *fileGroup) ConvertWithBp2build(ctx Bp2buildMutatorContext) { srcs := bazel.MakeLabelListAttribute( BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)) @@ -209,10 +209,10 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { } type FileGroupPath interface { - GetPath(ctx TopDownMutatorContext) string + GetPath(ctx Bp2buildMutatorContext) string } -func (fg *fileGroup) GetPath(ctx TopDownMutatorContext) string { +func (fg *fileGroup) GetPath(ctx Bp2buildMutatorContext) string { if fg.properties.Path != nil { return *fg.properties.Path } diff --git a/android/fixture.go b/android/fixture.go index 6660afd65..5ad47e8c9 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -275,6 +275,15 @@ func FixtureModifyContext(mutator func(ctx *TestContext)) FixturePreparer { }) } +// Sync the mock filesystem with the current config, then modify the context, +// This allows context modification that requires filesystem access. +func FixtureModifyContextWithMockFs(mutator func(ctx *TestContext)) FixturePreparer { + return newSimpleFixturePreparer(func(f *fixture) { + f.config.mockFileSystem("", f.mockFS) + mutator(f.ctx) + }) +} + func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer { return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) }) } diff --git a/android/license.go b/android/license.go index a09422b98..76f5115f5 100644 --- a/android/license.go +++ b/android/license.go @@ -71,7 +71,7 @@ type bazelLicenseAttributes struct { Visibility []string } -func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (m *licenseModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) { attrs := &bazelLicenseAttributes{ License_kinds: m.properties.License_kinds, Copyright_notice: m.properties.Copyright_notice, diff --git a/android/license_kind.go b/android/license_kind.go index 24b91e4c2..78df93835 100644 --- a/android/license_kind.go +++ b/android/license_kind.go @@ -50,7 +50,7 @@ type bazelLicenseKindAttributes struct { Visibility []string } -func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (m *licenseKindModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) { attrs := &bazelLicenseKindAttributes{ Conditions: m.properties.Conditions, Url: m.properties.Url, diff --git a/android/module.go b/android/module.go index 516810fcb..f48af4a03 100644 --- a/android/module.go +++ b/android/module.go @@ -1458,7 +1458,10 @@ func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, en // Returns a list of the constraint_value targets who enable this override. func productVariableConfigEnableAttribute(ctx *topDownMutatorContext) bazel.LabelListAttribute { result := bazel.LabelListAttribute{} - productVariableProps := ProductVariableProperties(ctx, ctx.Module()) + productVariableProps, errs := ProductVariableProperties(ctx, ctx.Module()) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } if productConfigProps, exists := productVariableProps["Enabled"]; exists { for productConfigProp, prop := range productConfigProps { flag, ok := prop.(*bool) @@ -1636,15 +1639,23 @@ func (b bp2buildInfo) BazelAttributes() []interface{} { } func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) { - if m.commonProperties.BazelConversionStatus.UnconvertedReason != nil { - panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name())) + 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 { - panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name())) + 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), @@ -3089,11 +3100,21 @@ func (b *baseModuleContext) ModuleFromName(name string) (blueprint.Module, bool) if !b.isBazelConversionMode() { panic("cannot call ModuleFromName if not in bazel conversion mode") } + var m blueprint.Module + var ok bool if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" { - return b.bp.ModuleFromName(moduleName) + m, ok = b.bp.ModuleFromName(moduleName) } else { - return b.bp.ModuleFromName(name) + m, ok = b.bp.ModuleFromName(name) + } + if !ok { + return m, ok + } + // If this module is not preferred, tried to get the prebuilt version instead + if a, aOk := m.(Module); aOk && !IsModulePrebuilt(a) && !IsModulePreferred(a) { + return b.ModuleFromName("prebuilt_" + name) } + return m, ok } func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) { diff --git a/android/mutator.go b/android/mutator.go index 41477b8ed..336f8f73c 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -15,9 +15,10 @@ package android import ( + "path/filepath" + "android/soong/bazel" "android/soong/ui/metrics/bp2build_metrics_proto" - "path/filepath" "github.com/google/blueprint" ) @@ -55,6 +56,7 @@ func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []Registe // TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should // evaluate the impact on conversion. RegisterPrebuiltsPreArchMutators, + RegisterPrebuiltsPostDepsMutators, }, bp2buildMutators...) @@ -229,37 +231,8 @@ var bp2buildPreArchMutators = []RegisterMutatorFunc{} // A minimal context for Bp2build conversion type Bp2buildMutatorContext interface { BazelConversionPathContext - - CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}) - CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute) -} - -// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules -// into Bazel BUILD targets that should run prior to deps and conversion. -func PreArchBp2BuildMutators(f RegisterMutatorFunc) { - bp2buildPreArchMutators = append(bp2buildPreArchMutators, f) -} - -type BaseMutatorContext interface { - BaseModuleContext - - // MutatorName returns the name that this mutator was registered with. - MutatorName() string - - // Rename all variants of a module. The new name is not visible to calls to ModuleName, - // AddDependency or OtherModuleName until after this mutator pass is complete. - Rename(name string) -} - -type TopDownMutator func(TopDownMutatorContext) - -type TopDownMutatorContext interface { BaseMutatorContext - // 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. - CreateModule(ModuleFactory, ...interface{}) Module - // CreateBazelTargetModule creates a BazelTargetModule by calling the // factory method, just like in CreateModule, but also requires // BazelTargetModuleProperties containing additional metadata for the @@ -290,6 +263,34 @@ type TopDownMutatorContext interface { CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string) } +// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules +// into Bazel BUILD targets that should run prior to deps and conversion. +func PreArchBp2BuildMutators(f RegisterMutatorFunc) { + bp2buildPreArchMutators = append(bp2buildPreArchMutators, f) +} + +type BaseMutatorContext interface { + BaseModuleContext + + // MutatorName returns the name that this mutator was registered with. + MutatorName() string + + // Rename all variants of a module. The new name is not visible to calls to ModuleName, + // AddDependency or OtherModuleName until after this mutator pass is complete. + Rename(name string) +} + +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. + CreateModule(ModuleFactory, ...interface{}) Module +} + type topDownMutatorContext struct { bp blueprint.TopDownMutatorContext baseModuleContext diff --git a/android/package.go b/android/package.go index 7fbc70041..ce0b15013 100644 --- a/android/package.go +++ b/android/package.go @@ -54,7 +54,7 @@ type packageModule struct { var _ Bazelable = &packageModule{} -func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) { +func (p *packageModule) ConvertWithBp2build(ctx Bp2buildMutatorContext) { defaultPackageMetadata := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses)) // If METADATA file exists in the package, add it to package(default_package_metadata=) using a // filegroup(name="default_metadata_file") which can be accessed later on each module in Bazel diff --git a/android/paths.go b/android/paths.go index 325a953c4..d4b1d6e29 100644 --- a/android/paths.go +++ b/android/paths.go @@ -171,6 +171,9 @@ 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". @@ -1012,6 +1015,12 @@ 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 @@ -1046,6 +1055,11 @@ 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) { @@ -1248,6 +1262,12 @@ 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 @@ -1280,6 +1300,11 @@ 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 @@ -1463,6 +1488,11 @@ 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 @@ -1507,6 +1537,11 @@ 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 @@ -1546,6 +1581,11 @@ 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 @@ -1570,6 +1610,11 @@ 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 @@ -1606,6 +1651,11 @@ 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.") { @@ -1922,6 +1972,11 @@ 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 { @@ -1947,6 +2002,11 @@ 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.go b/android/prebuilt.go index 95b772d41..e7b79796e 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -483,20 +483,55 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { // usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt // will be used if it is marked "prefer" or if the source module is disabled. func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module, prebuilt Module) bool { - if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 { - return false - } + if !ctx.Config().Bp2buildMode() { + if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 { + return false + } - // Skip prebuilt modules under unexported namespaces so that we won't - // end up shadowing non-prebuilt module when prebuilt module under same - // name happens to have a `Prefer` property set to true. - if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() { - return false + // Skip prebuilt modules under unexported namespaces so that we won't + // end up shadowing non-prebuilt module when prebuilt module under same + // name happens to have a `Prefer` property set to true. + if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() { + return false + } } // If source is not available or is disabled then always use the prebuilt. if source == nil || !source.Enabled() { - return true + // If in bp2build mode, we need to check product variables & Soong config variables, which may + // have overridden the "enabled" property but have not been merged into the property value as + // they would in a non-bp2build mode invocation + if ctx.Config().Bp2buildMode() && source != nil { + productVariableProps, errs := ProductVariableProperties(ctx, source) + if productConfigProps, exists := productVariableProps["Enabled"]; len(errs) == 0 && exists && len(productConfigProps) == 1 { + var prop ProductConfigOrSoongConfigProperty + var value bool + for p, v := range productConfigProps { + prop = p + actual, ok := v.(*bool) + if ok { + value = proptools.Bool(actual) + } + } + if scv, ok := prop.(SoongConfigProperty); ok { + // If the product config var is enabled but the value of enabled is false still, the + // prebuilt is preferred. Otherwise, check if the prebulit is explicitly preferred + if ctx.Config().VendorConfig(scv.namespace).Bool(strings.ToLower(scv.name)) && !value { + return true + } + } else { + // TODO: b/300998219 - handle product vars + // We don't handle product variables yet, so return based on the non-product specific + // value of enabled + return true + } + } else { + // No "enabled" property override, return true since this module isn't enabled + return true + } + } else { + return true + } } // If the use_source_config_var property is set then it overrides the prefer property setting. diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go index aeae20f48..c00b22ba4 100644 --- a/android/prebuilt_build_tool.go +++ b/android/prebuilt_build_tool.go @@ -14,10 +14,14 @@ package android -import "path/filepath" +import ( + "path/filepath" + + "github.com/google/blueprint" +) func init() { - RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory) + RegisterModuleType("prebuilt_build_tool", NewPrebuiltBuildTool) } type prebuiltBuildToolProperties struct { @@ -55,6 +59,13 @@ 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()) @@ -82,6 +93,11 @@ func (t *prebuiltBuildTool) GenerateAndroidBuildActions(ctx ModuleContext) { } t.toolPath = OptionalPathForPath(installedPath) + + ctx.SetProvider(PrebuiltBuildToolInfoProvider, PrebuiltBuildToolInfo{ + Src: sourcePath, + Deps: deps, + }) } func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) { @@ -101,10 +117,6 @@ var _ HostToolProvider = &prebuiltBuildTool{} // prebuilt_build_tool is to declare prebuilts to be used during the build, particularly for use // in genrules with the "tools" property. -func prebuiltBuildToolFactory() Module { - return NewPrebuiltBuildTool() -} - func NewPrebuiltBuildTool() Module { module := &prebuiltBuildTool{} module.AddProperties(&module.properties) diff --git a/android/register.go b/android/register.go index df97c75e4..f1c298691 100644 --- a/android/register.go +++ b/android/register.go @@ -15,9 +15,13 @@ package android import ( + "bufio" "fmt" + "path/filepath" "reflect" + "regexp" + "android/soong/shared" "github.com/google/blueprint" ) @@ -197,6 +201,56 @@ func (ctx *Context) RegisterForBazelConversion() { RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators) } +// RegisterExistingBazelTargets reads Bazel BUILD.bazel and BUILD files under +// the workspace, and returns a map containing names of Bazel targets defined in +// these BUILD files. +// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist. +func (c *Context) RegisterExistingBazelTargets(topDir string, existingBazelFiles []string) error { + result := map[string][]string{} + + // Search for instances of `name = "$NAME"` (with arbitrary spacing). + targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`) + + parseBuildFile := func(path string) error { + fullPath := shared.JoinPath(topDir, path) + sourceDir := filepath.Dir(path) + + fileInfo, err := c.Config().fs.Stat(fullPath) + if err != nil { + return fmt.Errorf("Error accessing Bazel file '%s': %s", path, err) + } + if !fileInfo.IsDir() && + (fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") { + f, err := c.Config().fs.Open(fullPath) + if err != nil { + return fmt.Errorf("Error reading Bazel file '%s': %s", path, err) + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + matches := targetNameRegex.FindAllStringSubmatch(line, -1) + for _, match := range matches { + result[sourceDir] = append(result[sourceDir], match[1]) + } + } + } + return nil + } + + for _, path := range existingBazelFiles { + if !c.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) { + continue + } + err := parseBuildFile(path) + if err != nil { + return err + } + } + c.Config().SetBazelBuildFileTargets(result) + return nil +} + // Register the pipeline of singletons, module types, and mutators for // generating build.ninja and other files for Kati, from Android.bp files. func (ctx *Context) Register() { diff --git a/android/rule_builder.go b/android/rule_builder.go index 777c1cfc3..245b759ca 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -474,13 +474,23 @@ func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderComma Inputs(depFiles.Paths()) } +// BuildWithNinjaVars adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for +// Outputs. This function will not escape Ninja variables, so it may be used to write sandbox manifests using Ninja variables. +func (r *RuleBuilder) BuildWithUnescapedNinjaVars(name string, desc string) { + r.build(name, desc, false) +} + // Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for // Outputs. func (r *RuleBuilder) Build(name string, desc string) { + r.build(name, desc, true) +} + +func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString bool) { name = ninjaNameEscape(name) if len(r.missingDeps) > 0 { - r.ctx.Build(pctx, BuildParams{ + r.ctx.Build(r.pctx, BuildParams{ Rule: ErrorRule, Outputs: r.Outputs(), Description: desc, @@ -619,12 +629,35 @@ func (r *RuleBuilder) Build(name string, desc string) { name, r.sboxManifestPath.String(), r.outDir.String()) } - // Create a rule to write the manifest as a the textproto. + // Create a rule to write the manifest as textproto. pbText, err := prototext.Marshal(&manifest) if err != nil { ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err) } - WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) + if ninjaEscapeCommandString { + WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) + } else { + // We need to have a rule to write files that is + // defined on the RuleBuilder's pctx in order to + // write Ninja variables in the string. + // The WriteFileRule function above rule can only write + // raw strings because it is defined on the android + // package's pctx, and it can't access variables defined + // in another context. + r.ctx.Build(r.pctx, BuildParams{ + Rule: r.ctx.Rule(r.pctx, "unescapedWriteFile", blueprint.RuleParams{ + Command: `rm -rf ${out} && cat ${out}.rsp > ${out}`, + Rspfile: "${out}.rsp", + RspfileContent: "${content}", + Description: "write file", + }, "content"), + Output: r.sboxManifestPath, + Description: "write sbox manifest " + r.sboxManifestPath.Base(), + Args: map[string]string{ + "content": string(pbText), + }, + }) + } // Generate a new string to use as the command line of the sbox rule. This uses // a RuleBuilderCommand as a convenience method of building the command line, then @@ -723,9 +756,13 @@ func (r *RuleBuilder) Build(name string, desc string) { pool = localPool } + if ninjaEscapeCommandString { + commandString = proptools.NinjaEscape(commandString) + } + r.ctx.Build(r.pctx, BuildParams{ - Rule: r.ctx.Rule(pctx, name, blueprint.RuleParams{ - Command: proptools.NinjaEscape(commandString), + Rule: r.ctx.Rule(r.pctx, name, blueprint.RuleParams{ + Command: commandString, CommandDeps: proptools.NinjaEscapeList(tools.Strings()), Restat: r.restat, Rspfile: proptools.NinjaEscape(rspFile), diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go index 86647eb22..a6b3a27a1 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -28,6 +28,17 @@ import ( "android/soong/shared" ) +var ( + pctx_ruleBuilderTest = NewPackageContext("android/soong/rule_builder") + pctx_ruleBuilderTestSubContext = NewPackageContext("android/soong/rule_builder/config") +) + +func init() { + pctx_ruleBuilderTest.Import("android/soong/rule_builder/config") + pctx_ruleBuilderTest.StaticVariable("cmdFlags", "${config.ConfigFlags}") + pctx_ruleBuilderTestSubContext.StaticVariable("ConfigFlags", "--some-clang-flag") +} + func builderContext() BuilderContext { return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{ "ld": nil, @@ -496,11 +507,13 @@ func testRuleBuilderFactory() Module { type testRuleBuilderModule struct { ModuleBase properties struct { - Srcs []string + Srcs []string + Flags []string - Restat bool - Sbox bool - Sbox_inputs bool + Restat bool + Sbox bool + Sbox_inputs bool + Unescape_ninja_vars bool } } @@ -518,8 +531,9 @@ func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) { rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"}) manifestPath := PathForModuleOut(ctx, "sbox.textproto") - testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir, - manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, + testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags, + out, outDep, outDir, + manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, t.properties.Unescape_ninja_vars, rspFile, rspFileContents, rspFile2, rspFileContents2) } @@ -543,17 +557,18 @@ func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) { rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"}) manifestPath := PathForOutput(ctx, "singleton/sbox.textproto") - testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir, - manifestPath, true, false, false, + testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir, + manifestPath, true, false, false, false, rspFile, rspFileContents, rspFile2, rspFileContents2) } func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path, + flags []string, out, outDep, outDir, manifestPath WritablePath, - restat, sbox, sboxInputs bool, + restat, sbox, sboxInputs, unescapeNinjaVars bool, rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) { - rule := NewRuleBuilder(pctx, ctx) + rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx) if sbox { rule.Sbox(outDir, manifestPath) @@ -564,6 +579,7 @@ func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, va rule.Command(). Tool(PathForSource(ctx, "cp")). + Flags(flags). Inputs(in). Implicit(implicit). OrderOnly(orderOnly). @@ -577,7 +593,11 @@ func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, va rule.Restat() } - rule.Build("rule", "desc") + if unescapeNinjaVars { + rule.BuildWithUnescapedNinjaVars("rule", "desc") + } else { + rule.Build("rule", "desc") + } } var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) { @@ -792,3 +812,47 @@ func TestRuleBuilderHashInputs(t *testing.T) { }) } } + +func TestRuleBuilderWithNinjaVarEscaping(t *testing.T) { + bp := ` + rule_builder_test { + name: "foo_sbox_escaped_ninja", + flags: ["${cmdFlags}"], + sbox: true, + sbox_inputs: true, + } + rule_builder_test { + name: "foo_sbox", + flags: ["${cmdFlags}"], + sbox: true, + sbox_inputs: true, + unescape_ninja_vars: true, + } + ` + result := GroupFixturePreparers( + prepareForRuleBuilderTest, + FixtureWithRootAndroidBp(bp), + ).RunTest(t) + + escapedNinjaMod := result.ModuleForTests("foo_sbox_escaped_ninja", "").Rule("writeFile") + AssertStringDoesContain( + t, + "", + escapedNinjaMod.BuildParams.Args["content"], + "$${cmdFlags}", + ) + + unescapedNinjaMod := result.ModuleForTests("foo_sbox", "").Rule("unescapedWriteFile") + AssertStringDoesContain( + t, + "", + unescapedNinjaMod.BuildParams.Args["content"], + "${cmdFlags}", + ) + AssertStringDoesNotContain( + t, + "", + unescapedNinjaMod.BuildParams.Args["content"], + "$${cmdFlags}", + ) +} diff --git a/android/util.go b/android/util.go index 5375373a6..7f6af2d68 100644 --- a/android/util.go +++ b/android/util.go @@ -33,12 +33,17 @@ func CopyOf[T any](s []T) []T { return append([]T{}, s...) } -// Concat returns a new slice concatenated from the two input slices. It does not change the input +// Concat returns a new slice concatenated from the input slices. It does not change the input // slices. -func Concat[T any](s1, s2 []T) []T { - res := make([]T, 0, len(s1)+len(s2)) - res = append(res, s1...) - res = append(res, s2...) +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...) + } return res } diff --git a/android/variable.go b/android/variable.go index 524cdf75c..d33294c16 100644 --- a/android/variable.go +++ b/android/variable.go @@ -476,14 +476,20 @@ type ProductVariables struct { ProductBrand string `json:",omitempty"` BuildVersionTags []string `json:",omitempty"` - ReleaseVersion string `json:",omitempty"` - ReleaseAconfigValueSets []string `json:",omitempty"` + ReleaseVersion string `json:",omitempty"` + ReleaseAconfigValueSets string `json:",omitempty"` ReleaseAconfigFlagDefaultPermission string `json:",omitempty"` KeepVndk *bool `json:",omitempty"` 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"` } func boolPtr(v bool) *bool { @@ -669,7 +675,8 @@ type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]i // ProductVariableProperties returns a ProductConfigProperties containing only the properties which // have been set for the given module. -func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductConfigProperties { +func ProductVariableProperties(ctx ArchVariantContext, module Module) (ProductConfigProperties, []error) { + var errs []error moduleBase := module.base() productConfigProperties := ProductConfigProperties{} @@ -693,12 +700,15 @@ func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductCon for namespace, namespacedVariableProps := range m.namespacedVariableProps() { for _, namespacedVariableProp := range namespacedVariableProps { variableValues := reflect.ValueOf(namespacedVariableProp).Elem().FieldByName(soongconfig.SoongConfigProperty) - productConfigProperties.AddSoongConfigProperties(namespace, variableValues) + err := productConfigProperties.AddSoongConfigProperties(namespace, variableValues) + if err != nil { + errs = append(errs, err) + } } } } - return productConfigProperties + return productConfigProperties, errs } func (p *ProductConfigProperties) AddProductConfigProperty( @@ -820,7 +830,7 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti } -func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) { +func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error { // // Example of soong_config_variables: // @@ -917,7 +927,7 @@ func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties if propertyName == "Target" { productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k)) } else if propertyName == "Arch" || propertyName == "Multilib" { - panic("Arch/Multilib are not currently supported in soong config variable structs") + return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs") } else { productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface()) } @@ -928,13 +938,14 @@ func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties if propertyOrValueName == "Target" { productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct) } else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" { - panic("Arch/Multilib are not currently supported in soong config variable structs") + return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs") } else { productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface()) } } } } + return nil } func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) { diff --git a/apex/apex.go b/apex/apex.go index a116b85ee..090d9c4fe 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2623,7 +2623,7 @@ func OverrideApexFactory() android.Module { return m } -func (o *OverrideApex) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (o *OverrideApex) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if ctx.ModuleType() != "override_apex" { return } @@ -3261,7 +3261,7 @@ const ( ) // ConvertWithBp2build performs bp2build conversion of an apex -func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (a *apexBundle) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { // We only convert apex and apex_test modules at this time if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" { return @@ -3272,7 +3272,7 @@ func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) { ctx.CreateBazelTargetModule(props, commonAttrs, &attrs) } -func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) { +func convertWithBp2build(a *apexBundle, ctx android.Bp2buildMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) { var manifestLabelAttribute bazel.LabelAttribute manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))) @@ -3298,7 +3298,10 @@ func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (baze cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config)) } - productVariableProps := android.ProductVariableProperties(ctx, a) + productVariableProps, errs := android.ProductVariableProperties(ctx, a) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but // given it's coming via config, we probably don't want to put it in here. var minSdkVersion bazel.StringAttribute @@ -3429,7 +3432,7 @@ func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (baze // both, 32/32, 64/none, 32&64/32, 64/32 // first, 32/32, 64/none, 64/32, 64/32 -func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string, +func convert32Libs(ctx android.Bp2buildMutatorContext, compileMultilb string, libs []string, nativeSharedLibs *convertedNativeSharedLibs) { libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) switch compileMultilb { @@ -3444,7 +3447,7 @@ func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string, } } -func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string, +func convert64Libs(ctx android.Bp2buildMutatorContext, compileMultilb string, libs []string, nativeSharedLibs *convertedNativeSharedLibs) { libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) switch compileMultilb { @@ -3457,7 +3460,7 @@ func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string, } } -func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string, +func convertBothLibs(ctx android.Bp2buildMutatorContext, compileMultilb string, libs []string, nativeSharedLibs *convertedNativeSharedLibs) { libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) switch compileMultilb { @@ -3475,7 +3478,7 @@ func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string, } } -func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string, +func convertFirstLibs(ctx android.Bp2buildMutatorContext, compileMultilb string, libs []string, nativeSharedLibs *convertedNativeSharedLibs) { libsLabelList := android.BazelLabelForModuleDeps(ctx, libs) switch compileMultilb { @@ -3518,7 +3521,7 @@ func makeSharedLibsAttributes(config string, libsLabelList bazel.LabelList, labelListAttr.Append(list) } -func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) { +func invalidCompileMultilib(ctx android.Bp2buildMutatorContext, value string) { ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 9475f5da3..3a6af1e44 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("rustLink").Args["linkFlags"] + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").RuleParams.Command 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("rustLink").Args["linkFlags"] + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").RuleParams.Command 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/apex/key.go b/apex/key.go index 65e739a90..fc1456b96 100644 --- a/apex/key.go +++ b/apex/key.go @@ -208,11 +208,11 @@ type bazelApexKeyAttributes struct { } // ConvertWithBp2build performs conversion apexKey for bp2build -func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *apexKey) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { apexKeyBp2BuildInternal(ctx, m) } -func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) { +func apexKeyBp2BuildInternal(ctx android.Bp2buildMutatorContext, module *apexKey) { privateKeyLabelAttribute, privateKeyNameAttribute := android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key) diff --git a/bazel/configurability.go b/bazel/configurability.go index 1fe844219..a28432c01 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -71,6 +71,7 @@ const ( AndroidAndInApex = "android-in_apex" AndroidPlatform = "system" + Unbundled_app = "unbundled_app" InApex = "in_apex" NonApex = "non_apex" @@ -207,6 +208,7 @@ var ( osAndInApexMap = map[string]string{ AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex", AndroidPlatform: "//build/bazel/rules/apex:system", + Unbundled_app: "//build/bazel/rules/apex:unbundled_app", OsDarwin: "//build/bazel/platforms/os:darwin", OsLinux: "//build/bazel/platforms/os:linux_glibc", osLinuxMusl: "//build/bazel/platforms/os:linux_musl", diff --git a/bp2build/Android.bp b/bp2build/Android.bp index b675e5e28..e30e53d86 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -44,6 +44,7 @@ bootstrap_go_package { "aidl_library_conversion_test.go", "android_app_certificate_conversion_test.go", "android_app_conversion_test.go", + "android_test_conversion_test.go", "apex_conversion_test.go", "apex_key_conversion_test.go", "build_conversion_test.go", @@ -62,6 +63,8 @@ bootstrap_go_package { "cc_test_conversion_test.go", "cc_yasm_conversion_test.go", "conversion_test.go", + "droiddoc_exported_dir_conversion_test.go", + "fdo_profile_conversion_test.go", "filegroup_conversion_test.go", "genrule_conversion_test.go", "gensrcs_conversion_test.go", @@ -72,6 +75,8 @@ bootstrap_go_package { "java_library_host_conversion_test.go", "java_plugin_conversion_test.go", "java_proto_conversion_test.go", + "java_sdk_library_conversion_test.go", + "java_sdk_library_import_conversion_test.go", "license_conversion_test.go", "license_kind_conversion_test.go", "linker_config_conversion_test.go", diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go index 13bb167c2..59aacbb15 100644 --- a/bp2build/aar_conversion_test.go +++ b/bp2build/aar_conversion_test.go @@ -15,11 +15,10 @@ package bp2build import ( + "testing" + "android/soong/android" "android/soong/java" - "fmt" - - "testing" ) func TestConvertAndroidLibrary(t *testing.T) { @@ -35,7 +34,8 @@ func TestConvertAndroidLibrary(t *testing.T) { "res/res.png": "", "manifest/AndroidManifest.xml": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` + StubbedBuildDefinitions: []string{"static_lib_dep"}, + Blueprint: simpleModule("android_library", "static_lib_dep") + ` android_library { name: "TestLib", srcs: ["lib.java"], @@ -82,7 +82,7 @@ func TestConvertAndroidLibraryWithNoSources(t *testing.T) { "res/res.png": "", "AndroidManifest.xml": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "lib_dep") + ` + Blueprint: simpleModule("android_library", "lib_dep") + ` android_library { name: "TestLib", srcs: [], @@ -91,7 +91,6 @@ android_library { sdk_version: "current", } `, - ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."), ExpectedBazelTargets: []string{}, }) } @@ -109,18 +108,24 @@ func TestConvertAndroidLibraryImport(t *testing.T) { ModuleTypeUnderTestFactory: java.AARImportFactory, Filesystem: map[string]string{ "import.aar": "", + "dep.aar": "", }, + StubbedBuildDefinitions: []string{"static_lib_dep", "prebuilt_static_import_dep"}, // 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 - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + - SimpleModuleDoNotConvertBp2build("android_library_import", "static_import_dep") + ` + Blueprint: simpleModule("android_library", "static_lib_dep") + ` android_library_import { name: "TestImport", aars: ["import.aar"], static_libs: ["static_lib_dep", "static_import_dep"], 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", +} `, ExpectedBazelTargets: []string{ MakeBazelTarget( diff --git a/bp2build/aconfig_conversion_test.go b/bp2build/aconfig_conversion_test.go new file mode 100644 index 000000000..cbf42ac06 --- /dev/null +++ b/bp2build/aconfig_conversion_test.go @@ -0,0 +1,137 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "testing" + + "android/soong/aconfig" + "android/soong/android" + "android/soong/cc" +) + +func registerAconfigModuleTypes(ctx android.RegistrationContext) { + aconfig.RegisterBuildComponents(ctx) + ctx.RegisterModuleType("cc_library", cc.LibraryFactory) +} + +func TestAconfigDeclarations(t *testing.T) { + bp := ` + aconfig_declarations { + name: "foo", + srcs: [ + "foo1.aconfig", + "test/foo2.aconfig", + ], + package: "com.android.foo", + } + ` + expectedBazelTarget := MakeBazelTargetNoRestrictions( + "aconfig_declarations", + "foo", + AttrNameToString{ + "srcs": `[ + "foo1.aconfig", + "test/foo2.aconfig", + ]`, + "package": `"com.android.foo"`, + }, + ) + RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{ + Blueprint: bp, + ExpectedBazelTargets: []string{expectedBazelTarget}, + }) +} + +func TestAconfigValues(t *testing.T) { + bp := ` + aconfig_values { + name: "foo", + srcs: [ + "foo1.textproto", + ], + package: "com.android.foo", + } + aconfig_value_set { + name: "bar", + values: [ + "foo" + ] + } + ` + expectedBazelTargets := []string{ + MakeBazelTargetNoRestrictions( + "aconfig_values", + "foo", + AttrNameToString{ + "srcs": `["foo1.textproto"]`, + "package": `"com.android.foo"`, + }, + ), + MakeBazelTargetNoRestrictions( + "aconfig_value_set", + "bar", + AttrNameToString{ + "values": `[":foo"]`, + }, + )} + RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{ + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + }) +} + +func TestCcAconfigLibrary(t *testing.T) { + bp := ` + aconfig_declarations { + name: "foo_aconfig_declarations", + srcs: [ + "foo1.aconfig", + ], + package: "com.android.foo", + } + cc_library { + name: "server_configurable_flags", + srcs: ["bar.cc"], + bazel_module: { bp2build_available: false }, + } + cc_aconfig_library { + name: "foo", + aconfig_declarations: "foo_aconfig_declarations", + } + ` + expectedBazelTargets := []string{ + MakeBazelTargetNoRestrictions( + "aconfig_declarations", + "foo_aconfig_declarations", + AttrNameToString{ + "srcs": `["foo1.aconfig"]`, + "package": `"com.android.foo"`, + }, + ), + MakeBazelTargetNoRestrictions( + "cc_aconfig_library", + "foo", + AttrNameToString{ + "aconfig_declarations": `":foo_aconfig_declarations"`, + "dynamic_deps": `[":server_configurable_flags"]`, + "target_compatible_with": `["//build/bazel/platforms/os:android"]`, + }, + )} + RunBp2BuildTestCase(t, registerAconfigModuleTypes, Bp2buildTestCase{ + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + }) +} diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go index 0d206b0e7..8ec4b3566 100644 --- a/bp2build/android_app_conversion_test.go +++ b/bp2build/android_app_conversion_test.go @@ -16,6 +16,7 @@ package bp2build import ( "android/soong/android" + "android/soong/cc" "android/soong/java" "testing" @@ -29,6 +30,7 @@ func runAndroidAppTestCase(t *testing.T, tc Bp2buildTestCase) { func registerAndroidAppModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("filegroup", android.FileGroupFactory) ctx.RegisterModuleType("java_library", java.LibraryFactory) + ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory) } func TestMinimalAndroidApp(t *testing.T) { @@ -78,7 +80,9 @@ func TestAndroidAppAllSupportedFields(t *testing.T) { "manifest/AndroidManifest.xml": "", "assets_/asset.png": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + ` + StubbedBuildDefinitions: []string{"static_lib_dep", "jni_lib"}, + Blueprint: simpleModule("android_app", "static_lib_dep") + + simpleModule("cc_library_shared", "jni_lib") + ` android_app { name: "TestApp", srcs: ["app.java"], @@ -99,6 +103,7 @@ android_app { obfuscate: false, ignore_warnings: true, }, + jni_libs: ["jni_lib"], } `, ExpectedBazelTargets: []string{ @@ -109,10 +114,13 @@ android_app { "resa/res.png", "resb/res.png", ]`, - "assets": `["assets_/asset.png"]`, - "assets_dir": `"assets_"`, - "custom_package": `"com.google"`, - "deps": `[":static_lib_dep"]`, + "assets": `["assets_/asset.png"]`, + "assets_dir": `"assets_"`, + "custom_package": `"com.google"`, + "deps": `[ + ":static_lib_dep", + ":jni_lib", + ]`, "java_version": `"7"`, "sdk_version": `"current"`, "certificate_name": `"foocert"`, @@ -177,7 +185,8 @@ func TestAndroidAppCertIsModule(t *testing.T) { ModuleTypeUnderTest: "android_app", ModuleTypeUnderTestFactory: java.AndroidAppFactory, Filesystem: map[string]string{}, - Blueprint: SimpleModuleDoNotConvertBp2build("filegroup", "foocert") + ` + StubbedBuildDefinitions: []string{"foocert"}, + Blueprint: simpleModule("filegroup", "foocert") + ` android_app { name: "TestApp", certificate: ":foocert", @@ -262,7 +271,8 @@ func TestAndroidAppLibs(t *testing.T) { ModuleTypeUnderTest: "android_app", ModuleTypeUnderTestFactory: java.AndroidAppFactory, Filesystem: map[string]string{}, - Blueprint: SimpleModuleDoNotConvertBp2build("java_library", "barLib") + ` + StubbedBuildDefinitions: []string{"barLib"}, + Blueprint: simpleModule("java_library", "barLib") + ` android_app { name: "foo", libs: ["barLib"], @@ -291,8 +301,9 @@ func TestAndroidAppKotlinSrcs(t *testing.T) { Filesystem: map[string]string{ "res/res.png": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("filegroup", "foocert") + - SimpleModuleDoNotConvertBp2build("java_library", "barLib") + ` + StubbedBuildDefinitions: []string{"foocert", "barLib"}, + Blueprint: simpleModule("filegroup", "foocert") + + simpleModule("java_library", "barLib") + ` android_app { name: "foo", srcs: ["a.java", "b.kt"], @@ -334,6 +345,7 @@ func TestAndroidAppCommonSrcs(t *testing.T) { Filesystem: map[string]string{ "res/res.png": "", }, + StubbedBuildDefinitions: []string{"barLib"}, Blueprint: ` android_app { name: "foo", @@ -348,7 +360,6 @@ android_app { } java_library{ name: "barLib", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -423,7 +434,6 @@ android_app { name: "foo", sdk_version: "current", min_sdk_version: "24", - max_sdk_version: "30", target_sdk_version: "29", optimize: { enabled: false, @@ -435,7 +445,6 @@ android_app { "manifest": `"AndroidManifest.xml"`, "resource_files": `[]`, "manifest_values": `{ - "maxSdkVersion": "30", "minSdkVersion": "24", "targetSdkVersion": "29", }`, @@ -464,12 +473,8 @@ android_app { MakeBazelTarget("android_binary", "foo", AttrNameToString{ "manifest": `"AndroidManifest.xml"`, "resource_files": `[]`, - "manifest_values": `{ - "minSdkVersion": "30", - "targetSdkVersion": "30", - }`, - "sdk_version": `"30"`, - "optimize": `False`, + "sdk_version": `"30"`, + "optimize": `False`, }), }}) } diff --git a/bp2build/android_test_conversion_test.go b/bp2build/android_test_conversion_test.go new file mode 100644 index 000000000..52413fad5 --- /dev/null +++ b/bp2build/android_test_conversion_test.go @@ -0,0 +1,103 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "android/soong/android" + "android/soong/java" + + "testing" +) + +func runAndroidTestTestCase(t *testing.T, tc Bp2buildTestCase) { + t.Helper() + RunBp2BuildTestCase(t, registerAndroidTestModuleTypes, tc) +} + +func registerAndroidTestModuleTypes(ctx android.RegistrationContext) { + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) + ctx.RegisterModuleType("java_library", java.LibraryFactory) +} + +func TestMinimalAndroidTest(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: { + shrink: true, + optimize: true, + obfuscate: true, + }, +} +`, + 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"`, + }), + }}) +} + +func TestMinimalAndroidTestHelperApp(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: { + shrink: true, + optimize: true, + obfuscate: true, + }, +} +`, + 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`, + }), + }}) +} diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go index 5aed4ad66..60de28cc5 100644 --- a/bp2build/apex_conversion_test.go +++ b/bp2build/apex_conversion_test.go @@ -74,38 +74,34 @@ func TestApexBundleSimple(t *testing.T) { ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.key", "com.android.apogee.certificate", "native_shared_lib_1", "native_shared_lib_2", + "prebuilt_1", "prebuilt_2", "com.android.apogee-file_contexts", "cc_binary_1", "sh_binary_2"}, Blueprint: ` apex_key { name: "com.android.apogee.key", public_key: "com.android.apogee.avbpubkey", private_key: "com.android.apogee.pem", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_1", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_2", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_1", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_2", - bazel_module: { bp2build_available: false }, } filegroup { @@ -113,11 +109,10 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } -cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } } -sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } } +cc_binary { name: "cc_binary_1"} +sh_binary { name: "sh_binary_2"} apex { name: "com.android.apogee", @@ -202,6 +197,7 @@ func TestApexBundleSimple_fileContextsInAnotherAndroidBp(t *testing.T) { Description: "apex - file contexts is a module in another Android.bp", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: []string{"//a/b:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "a/b/Android.bp": ` filegroup { @@ -209,7 +205,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -252,6 +247,7 @@ func TestApexBundleSimple_fileContextsIsNotSpecified(t *testing.T) { Description: "apex - file contexts is not specified", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { @@ -259,7 +255,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -281,12 +276,12 @@ func TestApexBundleCompileMultilibBoth(t *testing.T) { Description: "apex - example with compile_multilib=both", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"), Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -373,12 +368,12 @@ func TestApexBundleCompileMultilibFirstAndDefaultValue(t *testing.T) { Description: "apex - example with " + compileMultiLibProp, ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"), Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -393,12 +388,12 @@ func TestApexBundleCompileMultilib32(t *testing.T) { Description: "apex - example with compile_multilib=32", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"), Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -425,12 +420,12 @@ func TestApexBundleCompileMultilib64(t *testing.T) { Description: "apex - example with compile_multilib=64", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: append(multilibStubNames(), "//system/sepolicy/apex:com.android.apogee-file_contexts"), Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -458,31 +453,31 @@ filegroup { }}) } +func multilibStubNames() []string { + return []string{"native_shared_lib_for_both", "native_shared_lib_for_first", "native_shared_lib_for_lib32", "native_shared_lib_for_lib64", + "native_shared_lib_for_lib64", "unnested_native_shared_lib"} +} + func createMultilibBlueprint(compile_multilib string) string { return fmt.Sprintf(` cc_library { name: "native_shared_lib_for_both", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_for_first", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_for_lib32", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_for_lib64", - bazel_module: { bp2build_available: false }, } cc_library { name: "unnested_native_shared_lib", - bazel_module: { bp2build_available: false }, } apex { @@ -519,12 +514,12 @@ func TestApexBundleDefaultPropertyValues(t *testing.T) { Description: "apex - default property values", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: []string{"//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -546,12 +541,12 @@ func TestApexBundleHasBazelModuleProps(t *testing.T) { Description: "apex - has bazel module props", ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, + StubbedBuildDefinitions: []string{"//system/sepolicy/apex:apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } `, }, @@ -575,38 +570,35 @@ func TestBp2BuildOverrideApex(t *testing.T) { ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.key", "com.android.apogee.certificate", "native_shared_lib_1", + "native_shared_lib_2", "prebuilt_1", "prebuilt_2", "com.android.apogee-file_contexts", "cc_binary_1", + "sh_binary_2", "com.android.apogee", "com.google.android.apogee.key", "com.google.android.apogee.certificate"}, Blueprint: ` apex_key { name: "com.android.apogee.key", public_key: "com.android.apogee.avbpubkey", private_key: "com.android.apogee.pem", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_1", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_2", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_1", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_2", - bazel_module: { bp2build_available: false }, } filegroup { @@ -614,11 +606,10 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } -cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } } -sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } } +cc_binary { name: "cc_binary_1" } +sh_binary { name: "sh_binary_2" } apex { name: "com.android.apogee", @@ -643,20 +634,17 @@ apex { "prebuilt_1", "prebuilt_2", ], - bazel_module: { bp2build_available: false }, } apex_key { name: "com.google.android.apogee.key", public_key: "com.google.android.apogee.avbpubkey", private_key: "com.google.android.apogee.pem", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.google.android.apogee.certificate", certificate: "com.google.android.apogee", - bazel_module: { bp2build_available: false }, } override_apex { @@ -717,28 +705,27 @@ func TestOverrideApexTest(t *testing.T) { ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.certificate", "native_shared_lib_1", + "prebuilt_1", "com.android.apogee-file_contexts", "cc_binary_1", "sh_binary_2", + "com.android.apogee", "com.google.android.apogee.key", "com.google.android.apogee.certificate", "com.android.apogee.key"}, Blueprint: ` apex_key { name: "com.android.apogee.key", public_key: "com.android.apogee.avbpubkey", private_key: "com.android.apogee.pem", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } cc_library { name: "native_shared_lib_1", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_1", - bazel_module: { bp2build_available: false }, } filegroup { @@ -746,11 +733,10 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } -cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } } -sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } } +cc_binary { name: "cc_binary_1"} +sh_binary { name: "sh_binary_2"} apex_test { name: "com.android.apogee", @@ -773,20 +759,17 @@ apex_test { prebuilts: [ "prebuilt_1", ], - bazel_module: { bp2build_available: false }, } apex_key { name: "com.google.android.apogee.key", public_key: "com.google.android.apogee.avbpubkey", private_key: "com.google.android.apogee.pem", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.google.android.apogee.certificate", certificate: "com.google.android.apogee", - bazel_module: { bp2build_available: false }, } override_apex { @@ -835,17 +818,16 @@ func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInDifferentAndroid Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"//a/b:com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, "a/b/Android.bp": ` apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, } `, }, @@ -869,18 +851,17 @@ func TestApexBundleSimple_manifestIsSet_baseApexOverrideApexInDifferentAndroidBp Description: "override_apex - manifest of base apex is set, base apex and override_apex is in different Android.bp", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"//a/b:com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, "a/b/Android.bp": ` apex { name: "com.android.apogee", manifest: "apogee_manifest.json", - bazel_module: { bp2build_available: false }, } `, }, @@ -904,18 +885,17 @@ func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInSameAndroidBp(t Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in same Android.bp", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, } override_apex { @@ -937,19 +917,18 @@ func TestApexBundleSimple_manifestIsSet_baseApexOverrideApexInSameAndroidBp(t *t Description: "override_apex - manifest of base apex is set, base apex and override_apex is in same Android.bp", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` apex { name: "com.android.apogee", manifest: "apogee_manifest.json", - bazel_module: { bp2build_available: false }, } override_apex { @@ -971,18 +950,17 @@ func TestApexBundleSimple_packageNameOverride(t *testing.T) { Description: "override_apex - override package name", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, } override_apex { @@ -1006,24 +984,22 @@ func TestApexBundleSimple_NoPrebuiltsOverride(t *testing.T) { Description: "override_apex - no override", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"prebuilt_file", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` prebuilt_etc { name: "prebuilt_file", - bazel_module: { bp2build_available: false }, } apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, - prebuilts: ["prebuilt_file"] + prebuilts: ["prebuilt_file"] } override_apex { @@ -1046,35 +1022,32 @@ func TestApexBundleSimple_PrebuiltsOverride(t *testing.T) { Description: "override_apex - ooverride", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"prebuilt_file", "prebuilt_file2", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` prebuilt_etc { name: "prebuilt_file", - bazel_module: { bp2build_available: false }, } prebuilt_etc { name: "prebuilt_file2", - bazel_module: { bp2build_available: false }, } apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, - prebuilts: ["prebuilt_file"] + prebuilts: ["prebuilt_file"] } override_apex { name: "com.google.android.apogee", base: ":com.android.apogee", - prebuilts: ["prebuilt_file2"] + prebuilts: ["prebuilt_file2"] } `, ExpectedBazelTargets: []string{ @@ -1092,24 +1065,22 @@ func TestApexBundleSimple_PrebuiltsOverrideEmptyList(t *testing.T) { Description: "override_apex - override with empty list", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"prebuilt_file", "com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` prebuilt_etc { name: "prebuilt_file", - bazel_module: { bp2build_available: false }, } apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, - prebuilts: ["prebuilt_file"] + prebuilts: ["prebuilt_file"] } override_apex { @@ -1133,18 +1104,17 @@ func TestApexBundleSimple_NoLoggingParentOverride(t *testing.T) { Description: "override_apex - logging_parent - no override", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, logging_parent: "foo.bar.baz", } @@ -1168,18 +1138,17 @@ func TestApexBundleSimple_LoggingParentOverride(t *testing.T) { Description: "override_apex - logging_parent - override", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"com.android.apogee", "//system/sepolicy/apex:com.android.apogee-file_contexts"}, Filesystem: map[string]string{ "system/sepolicy/apex/Android.bp": ` filegroup { name: "com.android.apogee-file_contexts", srcs: [ "apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, }`, }, Blueprint: ` apex { name: "com.android.apogee", - bazel_module: { bp2build_available: false }, logging_parent: "foo.bar.baz", } @@ -1205,11 +1174,11 @@ func TestBp2BuildOverrideApex_CertificateNil(t *testing.T) { ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.certificate", "com.android.apogee-file_contexts", "com.android.apogee"}, Blueprint: ` android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } filegroup { @@ -1217,7 +1186,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } apex { @@ -1225,7 +1193,6 @@ apex { manifest: "apogee_manifest.json", file_contexts: ":com.android.apogee-file_contexts", certificate: ":com.android.apogee.certificate", - bazel_module: { bp2build_available: false }, } override_apex { @@ -1250,11 +1217,11 @@ func TestApexCertificateIsModule(t *testing.T) { ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee-file_contexts", "com.android.apogee.certificate"}, Blueprint: ` android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } apex { @@ -1263,7 +1230,7 @@ apex { file_contexts: ":com.android.apogee-file_contexts", certificate: ":com.android.apogee.certificate", } -` + SimpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"), +` + simpleModule("filegroup", "com.android.apogee-file_contexts"), ExpectedBazelTargets: []string{ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "certificate": `":com.android.apogee.certificate"`, @@ -1279,6 +1246,7 @@ func TestApexWithStubLib(t *testing.T) { ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"myapex-file_contexts"}, Blueprint: ` cc_library{ name: "foo", @@ -1299,7 +1267,7 @@ apex { binaries: ["bar"], native_shared_libs: ["foo"], } -` + SimpleModuleDoNotConvertBp2build("filegroup", "myapex-file_contexts"), +` + simpleModule("filegroup", "myapex-file_contexts"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_binary", "bar", AttrNameToString{ "local_includes": `["."]`, @@ -1315,6 +1283,7 @@ apex { "tags": `["apex_available=myapex"]`, }), MakeBazelTarget("cc_stub_suite", "foo_stub_libs", AttrNameToString{ + "api_surface": `"module-libapi"`, "soname": `"foo.so"`, "source_library_label": `"//:foo"`, "symbol_file": `"foo.map.txt"`, @@ -1349,6 +1318,7 @@ func TestApexCertificateIsSrc(t *testing.T) { ModuleTypeUnderTest: "apex", ModuleTypeUnderTestFactory: apex.BundleFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee-file_contexts"}, Blueprint: ` apex { name: "com.android.apogee", @@ -1356,7 +1326,7 @@ apex { file_contexts: ":com.android.apogee-file_contexts", certificate: "com.android.apogee.certificate", } -` + SimpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"), +` + simpleModule("filegroup", "com.android.apogee-file_contexts"), ExpectedBazelTargets: []string{ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "certificate_name": `"com.android.apogee.certificate"`, @@ -1372,11 +1342,12 @@ func TestBp2BuildOverrideApex_CertificateIsModule(t *testing.T) { ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.certificate", "com.android.apogee-file_contexts", + "com.android.apogee", "com.google.android.apogee.certificate"}, Blueprint: ` android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } filegroup { @@ -1384,7 +1355,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } apex { @@ -1392,13 +1362,11 @@ apex { manifest: "apogee_manifest.json", file_contexts: ":com.android.apogee-file_contexts", certificate: ":com.android.apogee.certificate", - bazel_module: { bp2build_available: false }, } android_app_certificate { name: "com.google.android.apogee.certificate", certificate: "com.google.android.apogee", - bazel_module: { bp2build_available: false }, } override_apex { @@ -1423,11 +1391,11 @@ func TestBp2BuildOverrideApex_CertificateIsSrc(t *testing.T) { ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee", "com.android.apogee.certificate", "com.android.apogee", "com.android.apogee-file_contexts"}, Blueprint: ` android_app_certificate { name: "com.android.apogee.certificate", certificate: "com.android.apogee", - bazel_module: { bp2build_available: false }, } filegroup { @@ -1435,7 +1403,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } apex { @@ -1443,7 +1410,6 @@ apex { manifest: "apogee_manifest.json", file_contexts: ":com.android.apogee-file_contexts", certificate: ":com.android.apogee.certificate", - bazel_module: { bp2build_available: false }, } override_apex { @@ -1468,8 +1434,9 @@ func TestApexTestBundleSimple(t *testing.T) { ModuleTypeUnderTest: "apex_test", ModuleTypeUnderTestFactory: apex.TestApexBundleFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"cc_test_1"}, Blueprint: ` -cc_test { name: "cc_test_1", bazel_module: { bp2build_available: false } } +cc_test { name: "cc_test_1"} apex_test { name: "test_com.android.apogee", @@ -1496,6 +1463,7 @@ func TestApexBundle_overridePlusProductVars(t *testing.T) { Description: "apex - overriding a module that uses product vars", ModuleTypeUnderTest: "override_apex", ModuleTypeUnderTestFactory: apex.OverrideApexFactory, + StubbedBuildDefinitions: []string{"foo-file_contexts"}, Blueprint: ` soong_config_string_variable { name: "library_linking_strategy", @@ -1534,7 +1502,6 @@ filegroup { srcs: [ "com.android.apogee-file_contexts", ], - bazel_module: { bp2build_available: false }, } apex { diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go index 8f6e843c5..140afb76a 100644 --- a/bp2build/apex_key_conversion_test.go +++ b/bp2build/apex_key_conversion_test.go @@ -83,14 +83,15 @@ func TestApexKey_KeysAreModules(t *testing.T) { ModuleTypeUnderTest: "apex_key", ModuleTypeUnderTestFactory: apex.ApexKeyFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"com.android.apogee.avbpubkey", "com.android.apogee.pem"}, Blueprint: ` apex_key { name: "com.android.apogee.key", public_key: ":com.android.apogee.avbpubkey", private_key: ":com.android.apogee.pem", } -` + SimpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") + - SimpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"), +` + simpleModule("filegroup", "com.android.apogee.avbpubkey") + + simpleModule("filegroup", "com.android.apogee.pem"), ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{ "private_key": `":com.android.apogee.pem"`, "public_key": `":com.android.apogee.avbpubkey"`, diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go index 50b83582a..7c26262ae 100644 --- a/bp2build/bp2build_product_config.go +++ b/bp2build/bp2build_product_config.go @@ -53,9 +53,10 @@ func createProductConfigFiles( return res, err } - // TODO(b/249685973): the name is product_config_platforms because product_config - // was already used for other files. Deduplicate them. - currentProductFolder := fmt.Sprintf("product_config_platforms/products/%s-%s", targetProduct, targetBuildVariant) + currentProductFolder := fmt.Sprintf("build/bazel/products/%s", targetProduct) + if len(productVariables.PartitionVars.ProductDirectory) > 0 { + currentProductFolder = fmt.Sprintf("%s%s", productVariables.PartitionVars.ProductDirectory, targetProduct) + } productReplacer := strings.NewReplacer( "{PRODUCT}", targetProduct, @@ -72,7 +73,7 @@ func createProductConfigFiles( } productLabelsToVariables := make(map[string]*android.ProductVariables) - productLabelsToVariables[productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}")] = &productVariables + productLabelsToVariables[productReplacer.Replace("@//{PRODUCT_FOLDER}:{PRODUCT}")] = &productVariables for product, productVariablesStarlark := range productsForTestingMap { productVariables, err := starlarkMapToProductVariables(productVariablesStarlark) if err != nil { @@ -81,7 +82,30 @@ func createProductConfigFiles( productLabelsToVariables["@//build/bazel/tests/products:"+product] = &productVariables } - res.bp2buildTargets = createTargets(productLabelsToVariables) + res.bp2buildTargets = make(map[string]BazelTargets) + res.bp2buildTargets[currentProductFolder] = append(res.bp2buildTargets[currentProductFolder], BazelTarget{ + name: productReplacer.Replace("{PRODUCT}"), + packageName: currentProductFolder, + content: productReplacer.Replace(`android_product( + name = "{PRODUCT}", + soong_variables = _soong_variables, +)`), + ruleClass: "android_product", + loads: []BazelLoad{ + { + file: ":soong.variables.bzl", + symbols: []BazelLoadSymbol{{ + symbol: "variables", + alias: "_soong_variables", + }}, + }, + { + file: "//build/bazel/product_config:android_product.bzl", + symbols: []BazelLoadSymbol{{symbol: "android_product"}}, + }, + }, + }) + createTargets(productLabelsToVariables, res.bp2buildTargets) platformMappingContent, err := platformMappingContent( productLabelsToVariables, @@ -93,26 +117,6 @@ func createProductConfigFiles( res.injectionFiles = []BazelFile{ newFile( - currentProductFolder, - "soong.variables.bzl", - `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`), - newFile( - currentProductFolder, - "BUILD", - productReplacer.Replace(` -package(default_visibility=[ - "@soong_injection//product_config_platforms:__subpackages__", - "@//build/bazel/product_config:__subpackages__", -]) -load(":soong.variables.bzl", _soong_variables = "variables") -load("@//build/bazel/product_config:android_product.bzl", "android_product") - -android_product( - name = "{PRODUCT}-{VARIANT}", - soong_variables = _soong_variables, -) -`)), - newFile( "product_config_platforms", "BUILD.bazel", productReplacer.Replace(` @@ -121,7 +125,7 @@ package(default_visibility = [ "@soong_injection//product_config_platforms:__subpackages__", ]) -load("//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables") +load("@//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables") load("@//build/bazel/product_config:android_product.bzl", "android_product") # Bazel will qualify its outputs by the platform name. When switching between products, this @@ -130,7 +134,7 @@ load("@//build/bazel/product_config:android_product.bzl", "android_product") # extra rebuilding, make mixed builds always use a single platform so that the bazel artifacts # are always under the same path. android_product( - name = "mixed_builds_product-{VARIANT}", + name = "mixed_builds_product", soong_variables = _soong_variables, extra_constraints = ["@//build/bazel/platforms:mixed_builds"], ) @@ -144,34 +148,35 @@ android_product( # TODO: When we start generating the platforms for more than just the # currently lunched product, they should all be listed here product_labels = [ - "@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}", - "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}", + "@soong_injection//product_config_platforms:mixed_builds_product", + "@//{PRODUCT_FOLDER}:{PRODUCT}", `)+strings.Join(productsForTesting, "\n")+"\n]\n"), newFile( "product_config_platforms", "common.bazelrc", productReplacer.Replace(` build --platform_mappings=platform_mappings -build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 - -build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT} -build:linux_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86 -build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 -build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64 -build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86 -build:linux_musl_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64 +build --platforms @//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64 +build --//build/bazel/product_config:target_build_variant={VARIANT} + +build:android --platforms=@//{PRODUCT_FOLDER}:{PRODUCT} +build:linux_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86 +build:linux_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64 +build:linux_bionic_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_bionic_x86_64 +build:linux_musl_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_musl_x86 +build:linux_musl_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}_linux_musl_x86_64 `)), newFile( "product_config_platforms", "linux.bazelrc", productReplacer.Replace(` -build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 +build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_linux_x86_64 `)), newFile( "product_config_platforms", "darwin.bazelrc", productReplacer.Replace(` -build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64 +build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}_darwin_x86_64 `)), } res.bp2buildFiles = []BazelFile{ @@ -179,6 +184,10 @@ build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_dar "", "platform_mappings", platformMappingContent), + newFile( + currentProductFolder, + "soong.variables.bzl", + `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`), } return res, nil @@ -229,12 +238,6 @@ func platformMappingSingleProduct( soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions, convertedModulePathMap map[string]string, result *strings.Builder) { - targetBuildVariant := "user" - if proptools.Bool(productVariables.Eng) { - targetBuildVariant = "eng" - } else if proptools.Bool(productVariables.Debuggable) { - targetBuildVariant = "userdebug" - } platform_sdk_version := -1 if productVariables.Platform_sdk_version != nil { @@ -262,7 +265,6 @@ func platformMappingSingleProduct( result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ","))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ","))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:compressed_apex=%t\n", proptools.Bool(productVariables.CompressedApex))) - result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:debuggable=%t\n", proptools.Bool(productVariables.Debuggable))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate=%s\n", proptools.String(productVariables.DefaultAppCertificate))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate_filegroup=%s\n", defaultAppCertificateFilegroup)) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ","))) @@ -273,7 +275,6 @@ func platformMappingSingleProduct( result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_platform=%s\n", label)) 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:eng=%t\n", proptools.Bool(productVariables.Eng))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_pattern_fill_contents=%t\n", proptools.Bool(productVariables.Malloc_pattern_fill_contents))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_zero_contents=%t\n", proptools.Bool(productVariables.Malloc_zero_contents))) @@ -282,12 +283,18 @@ func platformMappingSingleProduct( result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:memtag_heap_sync_include_paths=%s\n", strings.Join(productVariables.MemtagHeapSyncIncludePaths, ","))) 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_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)) + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:release_aconfig_flag_default_permission=%s\n", productVariables.ReleaseAconfigFlagDefaultPermission)) + // Empty string can't be used as label_flag on the bazel side + if len(productVariables.ReleaseAconfigValueSets) > 0 { + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:release_aconfig_value_sets=%s\n", productVariables.ReleaseAconfigValueSets)) + } + result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:release_version=%s\n", productVariables.ReleaseVersion)) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_sdk_version=%d\n", platform_sdk_version)) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:safestack=%t\n", proptools.Bool(productVariables.Safestack))) - result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:target_build_variant=%s\n", targetBuildVariant)) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:treble_linker_namespaces=%t\n", proptools.Bool(productVariables.Treble_linker_namespaces))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:tidy_checks=%s\n", proptools.String(productVariables.TidyChecks))) result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:uml=%t\n", proptools.Bool(productVariables.Uml))) @@ -415,8 +422,11 @@ func starlarkMapToProductVariables(in map[string]starlark.Value) (android.Produc return result, nil } -func createTargets(productLabelsToVariables map[string]*android.ProductVariables) map[string]BazelTargets { - res := make(map[string]BazelTargets) +func createTargets(productLabelsToVariables map[string]*android.ProductVariables, res map[string]BazelTargets) { + createGeneratedAndroidCertificateDirectories(productLabelsToVariables, res) +} + +func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[string]*android.ProductVariables, targets map[string]BazelTargets) { var allDefaultAppCertificateDirs []string for _, productVariables := range productLabelsToVariables { if proptools.String(productVariables.DefaultAppCertificate) != "" { @@ -427,20 +437,20 @@ func createTargets(productLabelsToVariables map[string]*android.ProductVariables } } for _, dir := range allDefaultAppCertificateDirs { - content := fmt.Sprintf(ruleTargetTemplate, "filegroup", "generated_android_certificate_directory", propsToAttributes(map[string]string{ - "srcs": `glob([ + content := `filegroup( + name = "generated_android_certificate_directory", + srcs = glob([ "*.pk8", "*.pem", "*.avbpubkey", - ])`, - "visibility": `["//visibility:public"]`, - })) - res[dir] = append(res[dir], BazelTarget{ + ]), + visibility = ["//visibility:public"], +)` + targets[dir] = append(targets[dir], BazelTarget{ name: "generated_android_certificate_directory", packageName: dir, content: content, ruleClass: "filegroup", }) } - return res } diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index 906036330..15b77669c 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -39,18 +39,24 @@ type BazelAttributes struct { Attrs map[string]string } -type BazelTarget struct { - name string - packageName string - content string - ruleClass string - bzlLoadLocation string +type BazelLoadSymbol struct { + // The name of the symbol in the file being loaded + symbol string + // The name the symbol wil have in this file. Can be left blank to use the same name as symbol. + alias string +} + +type BazelLoad struct { + file string + symbols []BazelLoadSymbol } -// IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file, -// as opposed to a native rule built into Bazel. -func (t BazelTarget) IsLoadedFromStarlark() bool { - return t.bzlLoadLocation != "" +type BazelTarget struct { + name string + packageName string + content string + ruleClass string + loads []BazelLoad } // Label is the fully qualified Bazel label constructed from the BazelTarget's @@ -110,30 +116,62 @@ func (targets BazelTargets) String() string { // LoadStatements return the string representation of the sorted and deduplicated // Starlark rule load statements needed by a group of BazelTargets. func (targets BazelTargets) LoadStatements() string { - bzlToLoadedSymbols := map[string][]string{} + // First, merge all the load statements from all the targets onto one list + bzlToLoadedSymbols := map[string][]BazelLoadSymbol{} for _, target := range targets { - if target.IsLoadedFromStarlark() { - bzlToLoadedSymbols[target.bzlLoadLocation] = - append(bzlToLoadedSymbols[target.bzlLoadLocation], target.ruleClass) + for _, load := range target.loads { + outer: + for _, symbol := range load.symbols { + alias := symbol.alias + if alias == "" { + alias = symbol.symbol + } + for _, otherSymbol := range bzlToLoadedSymbols[load.file] { + otherAlias := otherSymbol.alias + if otherAlias == "" { + otherAlias = otherSymbol.symbol + } + if symbol.symbol == otherSymbol.symbol && alias == otherAlias { + continue outer + } else if alias == otherAlias { + panic(fmt.Sprintf("Conflicting destination (%s) for loads of %s and %s", alias, symbol.symbol, otherSymbol.symbol)) + } + } + bzlToLoadedSymbols[load.file] = append(bzlToLoadedSymbols[load.file], symbol) + } } } - var loadStatements []string - for bzl, ruleClasses := range bzlToLoadedSymbols { - loadStatement := "load(\"" - loadStatement += bzl - loadStatement += "\", " - ruleClasses = android.SortedUniqueStrings(ruleClasses) - for i, ruleClass := range ruleClasses { - loadStatement += "\"" + ruleClass + "\"" - if i != len(ruleClasses)-1 { - loadStatement += ", " + var loadStatements strings.Builder + for i, bzl := range android.SortedKeys(bzlToLoadedSymbols) { + symbols := bzlToLoadedSymbols[bzl] + loadStatements.WriteString("load(\"") + loadStatements.WriteString(bzl) + loadStatements.WriteString("\", ") + sort.Slice(symbols, func(i, j int) bool { + if symbols[i].symbol < symbols[j].symbol { + return true + } + return symbols[i].alias < symbols[j].alias + }) + for j, symbol := range symbols { + if symbol.alias != "" && symbol.alias != symbol.symbol { + loadStatements.WriteString(symbol.alias) + loadStatements.WriteString(" = ") + } + loadStatements.WriteString("\"") + loadStatements.WriteString(symbol.symbol) + loadStatements.WriteString("\"") + if j != len(symbols)-1 { + loadStatements.WriteString(", ") } } - loadStatement += ")" - loadStatements = append(loadStatements, loadStatement) + loadStatements.WriteString(")") + if i != len(bzlToLoadedSymbols)-1 { + loadStatements.WriteString("\n") + } } - return strings.Join(android.SortedUniqueStrings(loadStatements), "\n") + return loadStatements.String() } type bpToBuildContext interface { @@ -799,7 +837,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers for dir := range dirs { buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{ name: "bp2build_all_srcs", - content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`, + content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]), tags = ["manual"])`, ruleClass: "filegroup", }) } @@ -857,12 +895,19 @@ func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) (BazelTarget, e } else { content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes) } + var loads []BazelLoad + if bzlLoadLocation != "" { + loads = append(loads, BazelLoad{ + file: bzlLoadLocation, + symbols: []BazelLoadSymbol{{symbol: ruleClass}}, + }) + } return BazelTarget{ - name: targetName, - packageName: m.TargetPackage(), - ruleClass: ruleClass, - bzlLoadLocation: bzlLoadLocation, - content: content, + name: targetName, + packageName: m.TargetPackage(), + ruleClass: ruleClass, + loads: loads, + content: content, }, nil } diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 489756633..329c907f8 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -773,9 +773,12 @@ func TestLoadStatements(t *testing.T) { { bazelTargets: BazelTargets{ BazelTarget{ - name: "foo", - ruleClass: "cc_library", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "foo", + ruleClass: "cc_library", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_library"}}, + }}, }, }, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, @@ -783,14 +786,20 @@ func TestLoadStatements(t *testing.T) { { bazelTargets: BazelTargets{ BazelTarget{ - name: "foo", - ruleClass: "cc_library", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "foo", + ruleClass: "cc_library", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_library"}}, + }}, }, BazelTarget{ - name: "bar", - ruleClass: "cc_library", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "bar", + ruleClass: "cc_library", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_library"}}, + }}, }, }, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, @@ -798,14 +807,20 @@ func TestLoadStatements(t *testing.T) { { bazelTargets: BazelTargets{ BazelTarget{ - name: "foo", - ruleClass: "cc_library", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "foo", + ruleClass: "cc_library", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_library"}}, + }}, }, BazelTarget{ - name: "bar", - ruleClass: "cc_binary", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "bar", + ruleClass: "cc_binary", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_binary"}}, + }}, }, }, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`, @@ -813,19 +828,28 @@ func TestLoadStatements(t *testing.T) { { bazelTargets: BazelTargets{ BazelTarget{ - name: "foo", - ruleClass: "cc_library", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "foo", + ruleClass: "cc_library", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_library"}}, + }}, }, BazelTarget{ - name: "bar", - ruleClass: "cc_binary", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "bar", + ruleClass: "cc_binary", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_binary"}}, + }}, }, BazelTarget{ - name: "baz", - ruleClass: "java_binary", - bzlLoadLocation: "//build/bazel/rules:java.bzl", + name: "baz", + ruleClass: "java_binary", + loads: []BazelLoad{{ + file: "//build/bazel/rules:java.bzl", + symbols: []BazelLoadSymbol{{symbol: "java_binary"}}, + }}, }, }, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library") @@ -834,19 +858,25 @@ load("//build/bazel/rules:java.bzl", "java_binary")`, { bazelTargets: BazelTargets{ BazelTarget{ - name: "foo", - ruleClass: "cc_binary", - bzlLoadLocation: "//build/bazel/rules:cc.bzl", + name: "foo", + ruleClass: "cc_binary", + loads: []BazelLoad{{ + file: "//build/bazel/rules:cc.bzl", + symbols: []BazelLoadSymbol{{symbol: "cc_binary"}}, + }}, }, BazelTarget{ - name: "bar", - ruleClass: "java_binary", - bzlLoadLocation: "//build/bazel/rules:java.bzl", + name: "bar", + ruleClass: "java_binary", + loads: []BazelLoad{{ + file: "//build/bazel/rules:java.bzl", + symbols: []BazelLoadSymbol{{symbol: "java_binary"}}, + }}, }, BazelTarget{ name: "baz", ruleClass: "genrule", - // Note: no bzlLoadLocation for native rules + // Note: no loads for native rules }, }, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary") @@ -1743,7 +1773,8 @@ func TestCommonBp2BuildModuleAttrs(t *testing.T) { Description: "Required into data test", ModuleTypeUnderTest: "filegroup", ModuleTypeUnderTestFactory: android.FileGroupFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` + StubbedBuildDefinitions: []string{"reqd"}, + Blueprint: simpleModule("filegroup", "reqd") + ` filegroup { name: "fg_foo", required: ["reqd"], @@ -1759,7 +1790,8 @@ filegroup { Description: "Required into data test, cyclic self reference is filtered out", ModuleTypeUnderTest: "filegroup", ModuleTypeUnderTestFactory: android.FileGroupFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` + StubbedBuildDefinitions: []string{"reqd"}, + Blueprint: simpleModule("filegroup", "reqd") + ` filegroup { name: "fg_foo", required: ["reqd", "fg_foo"], @@ -1775,8 +1807,9 @@ filegroup { Description: "Required via arch into data test", ModuleTypeUnderTest: "python_library", ModuleTypeUnderTestFactory: python.PythonLibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("python_library", "reqdx86") + - SimpleModuleDoNotConvertBp2build("python_library", "reqdarm") + ` + StubbedBuildDefinitions: []string{"reqdx86", "reqdarm"}, + Blueprint: simpleModule("python_library", "reqdx86") + + simpleModule("python_library", "reqdarm") + ` python_library { name: "fg_foo", arch: { @@ -1809,7 +1842,8 @@ python_library { "data.bin": "", "src.py": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("python_library", "reqd") + ` + StubbedBuildDefinitions: []string{"reqd"}, + Blueprint: simpleModule("python_library", "reqd") + ` python_library { name: "fg_foo", data: ["data.bin"], @@ -1831,7 +1865,8 @@ python_library { Description: "All props-to-attrs at once together test", ModuleTypeUnderTest: "filegroup", ModuleTypeUnderTestFactory: android.FileGroupFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("filegroup", "reqd") + ` + StubbedBuildDefinitions: []string{"reqd"}, + Blueprint: simpleModule("filegroup", "reqd") + ` filegroup { name: "fg_foo", required: ["reqd"], @@ -1926,6 +1961,69 @@ func TestPrettyPrintSelectMapEqualValues(t *testing.T) { android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual) } +func TestAlreadyPresentBuildTarget(t *testing.T) { + bp := ` + custom { + name: "foo", + } + custom { + name: "bar", + } + ` + alreadyPresentBuildFile := + MakeBazelTarget( + "custom", + "foo", + 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.", + }) +} + +// 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". +func TestBuildTargetPresentOtherDirectory(t *testing.T) { + bp := ` + custom { + name: "foo", + } + ` + expectedBazelTargets := []string{ + MakeBazelTarget( + "custom", + "foo", + AttrNameToString{}, + ), + } + registerCustomModule := func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice) + } + RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{ + KeepBuildFileForDirs: []string{"other_pkg"}, + Filesystem: map[string]string{ + "other_pkg/BUILD.bazel": MakeBazelTarget("custom", "foo", AttrNameToString{}), + }, + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + Description: "Not treating a BUILD target as the bazel definition for a module in another package", + }) +} + // If CommonAttributes.Dir is set, the bazel target should be created in that dir func TestCreateBazelTargetInDifferentDir(t *testing.T) { t.Parallel() diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 3d3b860fa..c67970375 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -44,10 +44,11 @@ func generateBazelTargetsForTest(targets []testBazelTarget, hod android.HostOrDe } type ccBinaryBp2buildTestCase struct { - description string - filesystem map[string]string - blueprint string - targets []testBazelTarget + description string + filesystem map[string]string + blueprint string + targets []testBazelTarget + stubbedBuildDefinitions []string } func registerCcBinaryModuleTypes(ctx android.RegistrationContext) { @@ -81,6 +82,7 @@ func runCcBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) { Description: description, Blueprint: binaryReplacer.Replace(testCase.blueprint), Filesystem: testCase.filesystem, + StubbedBuildDefinitions: testCase.stubbedBuildDefinitions, }) }) } @@ -97,6 +99,7 @@ func runCcHostBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) { Description: description, Blueprint: hostBinaryReplacer.Replace(testCase.blueprint), Filesystem: testCase.filesystem, + StubbedBuildDefinitions: testCase.stubbedBuildDefinitions, }) }) } @@ -107,6 +110,7 @@ func TestBasicCcBinary(t *testing.T) { filesystem: map[string]string{ soongCcVersionLibBpPath: soongCcVersionLibBp, }, + stubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion"}, blueprint: ` {rule_name} { name: "foo", @@ -264,7 +268,8 @@ func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) { func TestCcBinarySplitSrcsByLang(t *testing.T) { runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{ - description: "split srcs by lang", + description: "split srcs by lang", + stubbedBuildDefinitions: []string{"fg_foo"}, blueprint: ` {rule_name} { name: "foo", @@ -276,7 +281,7 @@ func TestCcBinarySplitSrcsByLang(t *testing.T) { ], include_build_directory: false, } -` + SimpleModuleDoNotConvertBp2build("filegroup", "fg_foo"), +` + simpleModule("filegroup", "fg_foo"), targets: []testBazelTarget{ {"cc_binary", "foo", AttrNameToString{ "srcs": `[ @@ -300,17 +305,17 @@ func TestCcBinarySplitSrcsByLang(t *testing.T) { func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) { runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ description: "no implementation deps", + stubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr", "static_dep", "implementation_static_dep", + "whole_static_dep", "not_explicitly_exported_whole_static_dep", "shared_dep", "implementation_shared_dep"}, blueprint: ` genrule { name: "generated_hdr", cmd: "nothing to see here", - bazel_module: { bp2build_available: false }, } genrule { name: "export_generated_hdr", cmd: "nothing to see here", - bazel_module: { bp2build_available: false }, } {rule_name} { @@ -326,12 +331,12 @@ genrule { export_generated_headers: ["export_generated_hdr"], } ` + - SimpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") + - SimpleModuleDoNotConvertBp2build("cc_library", "shared_dep") + - SimpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"), + simpleModule("cc_library_static", "static_dep") + + simpleModule("cc_library_static", "implementation_static_dep") + + simpleModule("cc_library_static", "whole_static_dep") + + simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep") + + simpleModule("cc_library", "shared_dep") + + simpleModule("cc_library", "implementation_shared_dep"), targets: []testBazelTarget{ {"cc_binary", "foo", AttrNameToString{ "deps": `[ @@ -502,6 +507,7 @@ func TestCcBinaryPropertiesToFeatures(t *testing.T) { func TestCcBinarySharedProto(t *testing.T) { runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + stubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, blueprint: soongCcProtoLibraries + `{rule_name} { name: "foo", srcs: ["foo.proto"], @@ -524,6 +530,7 @@ func TestCcBinarySharedProto(t *testing.T) { func TestCcBinaryStaticProto(t *testing.T) { runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + stubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, blueprint: soongCcProtoLibraries + `{rule_name} { name: "foo", srcs: ["foo.proto"], @@ -1224,13 +1231,13 @@ func TestCCBinaryRscriptSrc(t *testing.T) { func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) { runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ - description: "cc_library_static system_shared_lib empty for linux_bionic variant", + stubbedBuildDefinitions: []string{"libm", "libc"}, + description: "cc_library_static system_shared_lib empty for linux_bionic variant", blueprint: soongCcLibraryStaticPreamble + - SimpleModuleDoNotConvertBp2build("cc_library", "libc") + ` + simpleModule("cc_library", "libc") + ` cc_library { name: "libm", - bazel_module: { bp2build_available: false }, } cc_binary { diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 7af788eba..560123ea4 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -35,19 +35,16 @@ cc_defaults { soongCcVersionLibBp = ` cc_library_static { name: "libbuildversion", - bazel_module: { bp2build_available: false }, } ` soongCcProtoLibraries = ` cc_library { name: "libprotobuf-cpp-lite", - bazel_module: { bp2build_available: false }, } cc_library { name: "libprotobuf-cpp-full", - bazel_module: { bp2build_available: false }, }` soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries @@ -55,6 +52,7 @@ cc_library { func runCcLibraryTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() + tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "libprotobuf-cpp-lite", "libprotobuf-cpp-full") RunBp2BuildTestCase(t, registerCcLibraryModuleTypes, tc) } @@ -65,6 +63,7 @@ func registerCcLibraryModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory) ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory) + ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory) } func TestCcLibrarySimple(t *testing.T) { @@ -72,6 +71,7 @@ func TestCcLibrarySimple(t *testing.T) { Description: "cc_library - simple example", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion", "some-headers"}, Filesystem: map[string]string{ soongCcVersionLibBpPath: soongCcVersionLibBp, "android.cpp": "", @@ -94,7 +94,7 @@ func TestCcLibrarySimple(t *testing.T) { "foo-dir/a.h": "", }, Blueprint: soongCcLibraryPreamble + - SimpleModuleDoNotConvertBp2build("cc_library_headers", "some-headers") + ` + simpleModule("cc_library_headers", "some-headers") + ` cc_library { name: "foo-lib", srcs: ["impl.cpp"], @@ -168,6 +168,7 @@ func TestCcLibraryTrimmedLdAndroid(t *testing.T) { Description: "cc_library - trimmed example of //bionic/linker:ld-android", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc_headers"}, Filesystem: map[string]string{ "ld-android.cpp": "", "linked_list.h": "", @@ -176,7 +177,7 @@ func TestCcLibraryTrimmedLdAndroid(t *testing.T) { "linker_cfi.h": "", }, Blueprint: soongCcLibraryPreamble + - SimpleModuleDoNotConvertBp2build("cc_library_headers", "libc_headers") + ` + simpleModule("cc_library_headers", "libc_headers") + ` cc_library { name: "fake-ld-android", srcs: ["ld_android.cpp"], @@ -319,54 +320,49 @@ cc_library { cc_library_static { name: "static_dep_for_shared", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep_for_static", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep_for_both", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_for_shared", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_for_static", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_for_both", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_and_static_lib_for_both", - bazel_module: { bp2build_available: false }, } cc_library { name: "shared_dep_for_shared", - bazel_module: { bp2build_available: false }, } cc_library { name: "shared_dep_for_static", - bazel_module: { bp2build_available: false }, } cc_library { name: "shared_dep_for_both", - bazel_module: { bp2build_available: false }, } `, + StubbedBuildDefinitions: []string{"static_dep_for_shared", "static_dep_for_static", + "static_dep_for_both", "whole_static_lib_for_shared", "whole_static_lib_for_static", + "whole_static_lib_for_both", "whole_and_static_lib_for_both", "shared_dep_for_shared", + "shared_dep_for_static", "shared_dep_for_both", + }, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "copts": `[ @@ -457,24 +453,34 @@ cc_library { }, include_build_directory: false, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_both") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_both") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_both") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") + - SimpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_shared") + - SimpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") + - SimpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") + - SimpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"), +` + simpleModule("cc_library_static", "static_dep_for_shared") + + simpleModule("cc_library_static", "implementation_static_dep_for_shared") + + simpleModule("cc_library_static", "static_dep_for_static") + + simpleModule("cc_library_static", "implementation_static_dep_for_static") + + simpleModule("cc_library_static", "static_dep_for_both") + + simpleModule("cc_library_static", "implementation_static_dep_for_both") + + simpleModule("cc_library_static", "whole_static_dep_for_shared") + + simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") + + simpleModule("cc_library_static", "whole_static_dep_for_static") + + simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") + + simpleModule("cc_library_static", "whole_static_dep_for_both") + + simpleModule("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") + + simpleModule("cc_library", "shared_dep_for_shared") + + simpleModule("cc_library", "implementation_shared_dep_for_shared") + + simpleModule("cc_library", "shared_dep_for_static") + + simpleModule("cc_library", "implementation_shared_dep_for_static") + + simpleModule("cc_library", "shared_dep_for_both") + + simpleModule("cc_library", "implementation_shared_dep_for_both"), + StubbedBuildDefinitions: []string{"static_dep_for_shared", "implementation_static_dep_for_shared", + "static_dep_for_static", "implementation_static_dep_for_static", "static_dep_for_both", + "implementation_static_dep_for_both", "whole_static_dep_for_shared", + "not_explicitly_exported_whole_static_dep_for_shared", "whole_static_dep_for_static", + "not_explicitly_exported_whole_static_dep_for_static", "whole_static_dep_for_both", + "not_explicitly_exported_whole_static_dep_for_both", "shared_dep_for_shared", + "implementation_shared_dep_for_shared", "shared_dep_for_static", + "implementation_shared_dep_for_static", "shared_dep_for_both", + "implementation_shared_dep_for_both", + }, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "copts": `[ @@ -549,6 +555,8 @@ func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) { ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, Dir: "foo/bar", + StubbedBuildDefinitions: []string{"//foo/bar:prebuilt_whole_static_lib_for_shared", "//foo/bar:prebuilt_whole_static_lib_for_static", + "//foo/bar:prebuilt_whole_static_lib_for_both"}, Filesystem: map[string]string{ "foo/bar/Android.bp": ` cc_library { @@ -665,6 +673,10 @@ cc_library_static { name: "x86_dep_for_static" } cc_library_static { name: "android_dep_for_shared" } `, }, + StubbedBuildDefinitions: []string{"//foo/bar:static_dep_for_shared", "//foo/bar:static_dep_for_static", + "//foo/bar:static_dep_for_both", "//foo/bar:arm_static_dep_for_shared", "//foo/bar:arm_whole_static_dep_for_shared", + "//foo/bar:arm_shared_dep_for_shared", "//foo/bar:x86_dep_for_static", "//foo/bar:android_dep_for_shared", + }, Blueprint: soongCcLibraryPreamble, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ @@ -746,6 +758,7 @@ func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) { ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, Dir: "foo/bar", + StubbedBuildDefinitions: []string{"//foo/bar:shared_filegroup", "//foo/bar:static_filegroup", "//foo/bar:both_filegroup"}, Filesystem: map[string]string{ "foo/bar/both_source.cpp": "", "foo/bar/both_source.cc": "", @@ -1017,10 +1030,10 @@ func TestCcLibrarySharedLibs(t *testing.T) { Description: "cc_library shared_libs", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"mylib"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "mylib", - bazel_module: { bp2build_available: false }, } cc_library { @@ -1181,6 +1194,10 @@ func TestCcLibraryExcludeLibs(t *testing.T) { ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"arm_whole_static_lib_excludes", "malloc_not_svelte_whole_static_lib", + "arm_static_lib_excludes", "malloc_not_svelte_whole_static_lib_excludes", "arm_shared_lib_excludes", + "malloc_not_svelte_static_lib_excludes", "arm_shared_lib_excludes", "malloc_not_svelte_shared_lib", + }, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "foo_static", @@ -1222,37 +1239,30 @@ cc_library { cc_library { name: "arm_whole_static_lib_excludes", - bazel_module: { bp2build_available: false }, } cc_library { name: "malloc_not_svelte_whole_static_lib", - bazel_module: { bp2build_available: false }, } cc_library { name: "malloc_not_svelte_whole_static_lib_excludes", - bazel_module: { bp2build_available: false }, } cc_library { name: "arm_static_lib_excludes", - bazel_module: { bp2build_available: false }, } cc_library { name: "malloc_not_svelte_static_lib_excludes", - bazel_module: { bp2build_available: false }, } cc_library { name: "arm_shared_lib_excludes", - bazel_module: { bp2build_available: false }, } cc_library { name: "malloc_not_svelte_shared_lib", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{ @@ -1288,6 +1298,7 @@ func TestCcLibraryProductVariablesHeaderLibs(t *testing.T) { ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"malloc_not_svelte_header_lib"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "foo_static", @@ -1302,7 +1313,6 @@ cc_library { cc_library { name: "malloc_not_svelte_header_lib", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{ @@ -1812,10 +1822,10 @@ func TestCcLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) { Description: "cc_library system_shared_libs empty for linux_bionic variant", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library { @@ -1843,10 +1853,10 @@ func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) { Description: "cc_library system_shared_libs empty for bionic variant", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library { @@ -1874,10 +1884,10 @@ func TestCcLibrary_SystemSharedLibsMuslEmpty(t *testing.T) { Description: "cc_library system_shared_lib empty for musl variant", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library { @@ -1901,10 +1911,10 @@ func TestCcLibrary_SystemSharedLibsLinuxMuslEmpty(t *testing.T) { Description: "cc_library system_shared_lib empty for linux_musl variant", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library { @@ -1927,14 +1937,13 @@ func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) { Description: "cc_library system_shared_libs set for shared and root", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"libc", "libm"}, Blueprint: soongCcLibraryPreamble + ` cc_library { name: "libc", - bazel_module: { bp2build_available: false }, } cc_library { name: "libm", - bazel_module: { bp2build_available: false }, } cc_library { @@ -2505,6 +2514,7 @@ func TestCcLibraryExternalConvertedProtoFilegroups(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"//path/to/A:a_fg_proto"}, Filesystem: map[string]string{ "path/to/A/Android.bp": ` filegroup { @@ -2548,11 +2558,12 @@ func TestCcLibraryProtoFilegroups(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"a_fg_proto", "b_protos", "c-proto-srcs", "proto-srcs-d"}, Blueprint: soongCcProtoPreamble + - SimpleModuleDoNotConvertBp2build("filegroup", "a_fg_proto") + - SimpleModuleDoNotConvertBp2build("filegroup", "b_protos") + - SimpleModuleDoNotConvertBp2build("filegroup", "c-proto-srcs") + - SimpleModuleDoNotConvertBp2build("filegroup", "proto-srcs-d") + ` + simpleModule("filegroup", "a_fg_proto") + + simpleModule("filegroup", "b_protos") + + simpleModule("filegroup", "c-proto-srcs") + + simpleModule("filegroup", "proto-srcs-d") + ` cc_library { name: "a", srcs: [":a_fg_proto"], @@ -2809,6 +2820,7 @@ func TestCcLibraryStubs(t *testing.T) { "stubs_symbol_file": `"a.map.txt"`, }) expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{ + "api_surface": `"module-libapi"`, "soname": `"a.so"`, "source_library_label": `"//foo/bar:a"`, "stubs_symbol_file": `"a.map.txt"`, @@ -2847,11 +2859,11 @@ func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) { Filesystem: map[string]string{ "bar.map.txt": "", }, + StubbedBuildDefinitions: []string{"barlib"}, Blueprint: ` cc_library { name: "barlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, } cc_library { name: "foolib", @@ -2882,16 +2894,15 @@ func TestCcLibraryExcludesLibsHost(t *testing.T) { Filesystem: map[string]string{ "bar.map.txt": "", }, - Blueprint: SimpleModuleDoNotConvertBp2build("cc_library", "bazlib") + ` + StubbedBuildDefinitions: []string{"bazlib", "quxlib", "barlib"}, + Blueprint: simpleModule("cc_library", "bazlib") + ` cc_library { name: "quxlib", stubs: { symbol_file: "bar.map.txt", versions: ["current"] }, - bazel_module: { bp2build_available: false }, } cc_library { name: "barlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, } cc_library { name: "foolib", @@ -3005,18 +3016,18 @@ func TestCCLibraryRuntimeDeps(t *testing.T) { cc_library { name: "foo", - runtime_libs: ["foo"], + runtime_libs: ["bar"], }`, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ - "runtime_deps": `[":foo"]`, + "runtime_deps": `[":bar"]`, "local_includes": `["."]`, }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "runtime_deps": `[":foo"]`, + "runtime_deps": `[":bar"]`, "local_includes": `["."]`, }), }, @@ -3227,6 +3238,7 @@ func TestCcLibraryWithNonAdjacentAidlFilegroup(t *testing.T) { Description: "cc_library with non aidl filegroup", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"//path/to/A:A_aidl"}, Filesystem: map[string]string{ "path/to/A/Android.bp": ` filegroup { @@ -3516,6 +3528,7 @@ func TestCcLibraryWithAidlAndLibs(t *testing.T) { Description: "cc_aidl_library depends on libs from parent cc_library_static", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"bar-static", "baz-static", "bar-shared", "baz-shared"}, Blueprint: ` cc_library_static { name: "foo", @@ -3537,10 +3550,10 @@ cc_library_static { "baz-shared", ], }` + - SimpleModuleDoNotConvertBp2build("cc_library_static", "bar-static") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "baz-static") + - SimpleModuleDoNotConvertBp2build("cc_library", "bar-shared") + - SimpleModuleDoNotConvertBp2build("cc_library", "baz-shared"), + simpleModule("cc_library_static", "bar-static") + + simpleModule("cc_library_static", "baz-static") + + simpleModule("cc_library", "bar-shared") + + simpleModule("cc_library", "baz-shared"), ExpectedBazelTargets: []string{ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{ "srcs": `["Foo.aidl"]`, @@ -3639,8 +3652,8 @@ cc_library { { description: "cc_library with afdo enabled and existing profile", filesystem: map[string]string{ - "vendor/google_data/pgo_profile/sampling/BUILD": "", - "vendor/google_data/pgo_profile/sampling/foo.afdo": "", + "vendor/google_data/pgo_profile/sampling/Android.bp": "", + "vendor/google_data/pgo_profile/sampling/foo.afdo": "", }, expectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), @@ -3652,8 +3665,8 @@ cc_library { { description: "cc_library with afdo enabled and existing profile in AOSP", filesystem: map[string]string{ - "toolchain/pgo-profiles/sampling/BUILD": "", - "toolchain/pgo-profiles/sampling/foo.afdo": "", + "toolchain/pgo-profiles/sampling/Android.bp": "", + "toolchain/pgo-profiles/sampling/foo.afdo": "", }, expectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), @@ -3665,8 +3678,8 @@ cc_library { { description: "cc_library with afdo enabled but profile filename doesn't match with module name", filesystem: map[string]string{ - "toolchain/pgo-profiles/sampling/BUILD": "", - "toolchain/pgo-profiles/sampling/bar.afdo": "", + "toolchain/pgo-profiles/sampling/Android.bp": "", + "toolchain/pgo-profiles/sampling/bar.afdo": "", }, expectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), @@ -4084,17 +4097,16 @@ func TestCcLibraryInApexWithStubSharedLibs(t *testing.T) { Description: "cc_library with in apex with stub shared_libs and export_shared_lib_headers", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"barlib", "bazlib"}, Blueprint: ` cc_library { name: "barlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, apex_available: ["//apex_available:platform",], } cc_library { name: "bazlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, apex_available: ["//apex_available:platform",], } cc_library { @@ -4470,6 +4482,7 @@ func TestCcLibraryYaccConversion(t *testing.T) { Description: "cc_library is built from .y/.yy files", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, + StubbedBuildDefinitions: []string{"staticlib", "sharedlib"}, Blueprint: soongCcLibraryPreamble + `cc_library { name: "a", srcs: [ @@ -4486,11 +4499,9 @@ func TestCcLibraryYaccConversion(t *testing.T) { } cc_library_static { name: "staticlib", - bazel_module: { bp2build_available: false }, } cc_library { name: "sharedlib", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -4744,7 +4755,7 @@ cc_library_static { canonical_path_from_root: true, } } -` + SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), +` + simpleModule("cc_library", "libprotobuf-cpp-lite"), Filesystem: map[string]string{ "bar/Android.bp": "", "baz/subbaz/Android.bp": "", @@ -4812,7 +4823,7 @@ cc_library_static { canonical_path_from_root: false, } } -` + SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), +` + simpleModule("cc_library", "libprotobuf-cpp-lite"), Filesystem: map[string]string{ "bar/Android.bp": "", "baz/subbaz/Android.bp": "", @@ -4882,7 +4893,7 @@ cc_library_static { include_dirs: ["bar"], } } -` + SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), +` + simpleModule("cc_library", "libprotobuf-cpp-lite"), Filesystem: map[string]string{ "bar/Android.bp": "", "bar/bar.proto": "", @@ -4953,7 +4964,7 @@ cc_library_static { include_dirs: ["baz"], } } -` + SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), +` + simpleModule("cc_library", "libprotobuf-cpp-lite"), Filesystem: map[string]string{ "bar/Android.bp": "", // package boundary "baz/Android.bp": "", @@ -4988,7 +4999,14 @@ func TestProtoLocalIncludeDirs(t *testing.T) { Description: "cc_library depends on .proto files using proto.local_include_dirs", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), + Blueprint: ` +cc_library { + name: "libprotobuf-cpp-lite", + // TODO: b/285631638 - A stubbed proto library dependency does not work as a protolib + // dependency of cc_library_static. + bazel_module: { bp2build_available: false }, +} +`, Filesystem: map[string]string{ "foo/Android.bp": `cc_library_static { name: "foo", @@ -5045,7 +5063,7 @@ func TestProtoLibraryForIncludeDirsIsOsAgnostic(t *testing.T) { Description: "proto_library generated for proto.include_dirs is compatible for all axes", ModuleTypeUnderTest: "cc_library", ModuleTypeUnderTestFactory: cc.LibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite") + ` + Blueprint: simpleModule("cc_library", "libprotobuf-cpp-lite") + ` cc_library { name: "foo_device", device_supported: true, // this is the default behavior, but added explicitly here for illustration @@ -5130,3 +5148,65 @@ cc_library { } runCcLibraryTestCase(t, tc) } + +func TestNdkLibraryConversion(t *testing.T) { + tc := Bp2buildTestCase{ + Description: "ndk_library conversion", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: ` +cc_library { + name: "libfoo", + bazel_module: { bp2build_available: false }, +} +ndk_library { + name: "libfoo", + first_version: "29", + symbol_file: "libfoo.map.txt", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_stub_suite", "libfoo.ndk_stub_libs", AttrNameToString{ + "api_surface": `"publicapi"`, + "soname": `"libfoo.so"`, + "source_library_label": `"//:libfoo"`, + "symbol_file": `"libfoo.map.txt"`, + "versions": `[ + "29", + "30", + "S", + "Tiramisu", + "current", + ]`, + }), + }, + } + runCcLibraryTestCase(t, tc) +} + +func TestNdkHeadersConversion(t *testing.T) { + tc := Bp2buildTestCase{ + Description: "ndk_headers conversion", + ModuleTypeUnderTest: "ndk_headers", + ModuleTypeUnderTestFactory: cc.NdkHeadersFactory, + Blueprint: ` +ndk_headers { + name: "libfoo_headers", + from: "from", + to: "to", + srcs: ["foo.h", "foo_other.h"] +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("ndk_headers", "libfoo_headers", AttrNameToString{ + "strip_import_prefix": `"from"`, + "import_prefix": `"to"`, + "hdrs": `[ + "foo.h", + "foo_other.h", + ]`, + }), + }, + } + runCcLibraryTestCase(t, tc) +} diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 40e84510b..fde4c973e 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -57,6 +57,8 @@ func TestCcLibraryHeadersLoadStatement(t *testing.T) { func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) { cc.RegisterCCBuildComponents(ctx) + cc.RegisterLibraryHeadersBuildComponents(ctx) + ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory) } func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) { @@ -66,9 +68,7 @@ func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) { func TestCcLibraryHeadersSimple(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers test", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, + Description: "cc_library_headers test", Filesystem: map[string]string{ "lib-1/lib1a.h": "", "lib-1/lib1b.h": "", @@ -127,34 +127,28 @@ cc_library_headers { // variant info(select) should go before general info. func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers test with os-specific header_libs props", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers test with os-specific header_libs props", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"android-lib", "base-lib", "darwin-lib", + "linux-lib", "linux_bionic-lib", "windows-lib"}, Blueprint: soongCcLibraryPreamble + ` cc_library_headers { name: "android-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "base-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "darwin-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "linux-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "linux_bionic-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "windows-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "foo_headers", @@ -201,18 +195,15 @@ cc_library_headers { func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"android-lib", "exported-lib"}, Blueprint: soongCcLibraryPreamble + ` cc_library_headers { name: "android-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "exported-lib", - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "foo_headers", @@ -237,10 +228,8 @@ cc_library_headers { func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props", + Filesystem: map[string]string{}, Blueprint: soongCcLibraryPreamble + `cc_library_headers { name: "foo_headers", export_system_include_dirs: [ @@ -296,9 +285,7 @@ func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers test", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, + Description: "cc_library_headers test", Filesystem: map[string]string{ "lib-1/lib1a.h": "", "lib-1/lib1b.h": "", @@ -329,10 +316,9 @@ cc_library_headers { func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers exported_static_lib_headers is reexported", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers exported_static_lib_headers is reexported", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"foo_export"}, Blueprint: soongCcLibraryHeadersPreamble + ` cc_library_headers { name: "foo_headers", @@ -340,7 +326,7 @@ cc_library_headers { static_libs: ["foo_export", "foo_no_reexport"], bazel_module: { bp2build_available: true }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), +` + simpleModule("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, @@ -351,10 +337,9 @@ cc_library_headers { func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers exported_shared_lib_headers is reexported", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers exported_shared_lib_headers is reexported", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"foo_export"}, Blueprint: soongCcLibraryHeadersPreamble + ` cc_library_headers { name: "foo_headers", @@ -362,7 +347,7 @@ cc_library_headers { shared_libs: ["foo_export", "foo_no_reexport"], bazel_module: { bp2build_available: true }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), +` + simpleModule("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, @@ -373,10 +358,9 @@ cc_library_headers { func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers exported_header_lib_headers is reexported", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers exported_header_lib_headers is reexported", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"foo_export"}, Blueprint: soongCcLibraryHeadersPreamble + ` cc_library_headers { name: "foo_headers", @@ -384,7 +368,7 @@ cc_library_headers { header_libs: ["foo_export", "foo_no_reexport"], bazel_module: { bp2build_available: true }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), +` + simpleModule("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, @@ -395,17 +379,16 @@ cc_library_headers { func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ - Description: "cc_library_headers whole_static_libs is reexported", - ModuleTypeUnderTest: "cc_library_headers", - ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, - Filesystem: map[string]string{}, + Description: "cc_library_headers whole_static_libs is reexported", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"foo_export"}, Blueprint: soongCcLibraryHeadersPreamble + ` cc_library_headers { name: "foo_headers", whole_static_libs: ["foo_export"], bazel_module: { bp2build_available: true }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), +` + simpleModule("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, @@ -413,3 +396,89 @@ cc_library_headers { }, }) } + +func TestPrebuiltCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) { + runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ + Description: "cc_library_headers whole_static_libs is reexported", + Filesystem: map[string]string{ + "foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"), + }, + StubbedBuildDefinitions: []string{"foo_export"}, + Blueprint: soongCcLibraryHeadersPreamble + ` +cc_prebuilt_library_headers { + name: "foo_headers", + whole_static_libs: ["foo_export"], + bazel_module: { bp2build_available: true }, +} +` + simpleModule("cc_library_headers", "foo_export"), + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + "deps": `[":foo_export"]`, + }), + }, + }) +} + +func TestPrebuiltCcLibraryHeadersPreferredRdepUpdated(t *testing.T) { + runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ + Description: "cc_library_headers prebuilt preferred is used as rdep", + StubbedBuildDefinitions: []string{"foo_export"}, + Filesystem: map[string]string{ + "foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"), + }, + Blueprint: soongCcLibraryHeadersPreamble + ` +cc_prebuilt_library_headers { + name: "foo_headers", + whole_static_libs: ["foo_export"], + bazel_module: { bp2build_available: true }, + prefer: true, +} + +cc_library_shared { + name: "foo", + header_libs: ["foo_headers"], + include_build_directory: false, +} +` + simpleModule("cc_library_headers", "foo_export"), + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + "deps": `[":foo_export"]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "implementation_deps": `[":foo_headers"]`, + }), + }, + }) +} + +func TestPrebuiltCcLibraryHeadersRdepUpdated(t *testing.T) { + runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ + Description: "cc_library_headers not preferred is not used for rdep", + StubbedBuildDefinitions: []string{"foo_export"}, + Filesystem: map[string]string{ + "foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"), + }, + Blueprint: soongCcLibraryHeadersPreamble + ` +cc_prebuilt_library_headers { + name: "foo_headers", + whole_static_libs: ["foo_export"], + bazel_module: { bp2build_available: true }, + prefer: false, +} + +cc_library_shared { + name: "foo", + header_libs: ["foo_headers"], + include_build_directory: false, +} +` + simpleModule("cc_library_headers", "foo_export"), + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + "deps": `[":foo_export"]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "implementation_deps": `["//foo/bar:foo_headers"]`, + }), + }, + }) +} diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 44b97227e..bdde996eb 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -32,11 +32,13 @@ func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) ctx.RegisterModuleType("cc_library", cc.LibraryFactory) + ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory) } func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() t.Parallel() + tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "libbuildversion", "libprotobuf-cpp-lite", "libprotobuf-cpp-full") (&tc).ModuleTypeUnderTest = "cc_library_shared" (&tc).ModuleTypeUnderTestFactory = cc.LibrarySharedFactory RunBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc) @@ -44,7 +46,8 @@ func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) { func TestCcLibrarySharedSimple(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ - Description: "cc_library_shared simple overall test", + Description: "cc_library_shared simple overall test", + StubbedBuildDefinitions: []string{"header_lib_1", "header_lib_2", "whole_static_lib_1", "whole_static_lib_2", "shared_lib_1", "shared_lib_2"}, Filesystem: map[string]string{ // NOTE: include_dir headers *should not* appear in Bazel hdrs later (?) "include_dir_1/include_dir_1_a.h": "", @@ -69,37 +72,31 @@ func TestCcLibrarySharedSimple(t *testing.T) { cc_library_headers { name: "header_lib_1", export_include_dirs: ["header_lib_1"], - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "header_lib_2", export_include_dirs: ["header_lib_2"], - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "shared_lib_1", srcs: ["shared_lib_1.cc"], - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "shared_lib_2", srcs: ["shared_lib_2.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_1", srcs: ["whole_static_lib_1.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_2", srcs: ["whole_static_lib_2.cc"], - bazel_module: { bp2build_available: false }, } cc_library_shared { @@ -185,16 +182,15 @@ cc_library_shared { func TestCcLibrarySharedArchSpecificSharedLib(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ - Description: "cc_library_shared arch-specific shared_libs with whole_static_libs", - Filesystem: map[string]string{}, + Description: "cc_library_shared arch-specific shared_libs with whole_static_libs", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"static_dep", "shared_dep"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_static { name: "static_dep", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "shared_dep", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "foo_shared", @@ -218,12 +214,12 @@ cc_library_shared { func TestCcLibrarySharedOsSpecificSharedLib(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ - Description: "cc_library_shared os-specific shared_libs", - Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"shared_dep"}, + Description: "cc_library_shared os-specific shared_libs", + Filesystem: map[string]string{}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "shared_dep", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "foo_shared", @@ -243,20 +239,18 @@ cc_library_shared { func TestCcLibrarySharedBaseArchOsSpecificSharedLib(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ - Description: "cc_library_shared base, arch, and os-specific shared_libs", - Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"shared_dep", "shared_dep2", "shared_dep3"}, + Description: "cc_library_shared base, arch, and os-specific shared_libs", + Filesystem: map[string]string{}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "shared_dep", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "shared_dep2", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "shared_dep3", - bazel_module: { bp2build_available: false }, } cc_library_shared { name: "foo_shared", @@ -511,6 +505,7 @@ func TestCcLibrarySharedUseVersionLib(t *testing.T) { Filesystem: map[string]string{ soongCcVersionLibBpPath: soongCcVersionLibBp, }, + StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion"}, Blueprint: soongCcProtoPreamble + `cc_library_shared { name: "foo", use_version_lib: true, @@ -543,6 +538,7 @@ cc_library_shared { }, Blueprint: soongCcLibraryPreamble, ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{ + "api_surface": `"module-libapi"`, "soname": `"a.so"`, "source_library_label": `"//foo/bar:a"`, "stubs_symbol_file": `"a.map.txt"`, @@ -564,11 +560,11 @@ func TestCcLibrarySharedStubs_UseImplementationInSameApex(t *testing.T) { Description: "cc_library_shared stubs", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "a", stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, include_build_directory: false, apex_available: ["made_up_apex"], } @@ -593,11 +589,11 @@ func TestCcLibrarySharedStubs_UseStubsInDifferentApex(t *testing.T) { Description: "cc_library_shared stubs", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "a", stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, include_build_directory: false, apex_available: ["apex_a"], } @@ -627,19 +623,18 @@ func TestCcLibrarySharedStubs_UseStubsFromMultipleApiDomains(t *testing.T) { Description: "cc_library_shared stubs", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"libplatform_stable", "libapexfoo_stable"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "libplatform_stable", stubs: { symbol_file: "libplatform_stable.map.txt", versions: ["28", "29", "current"] }, apex_available: ["//apex_available:platform"], - bazel_module: { bp2build_available: false }, include_build_directory: false, } cc_library_shared { name: "libapexfoo_stable", stubs: { symbol_file: "libapexfoo_stable.map.txt", versions: ["28", "29", "current"] }, apex_available: ["apexfoo"], - bazel_module: { bp2build_available: false }, include_build_directory: false, } cc_library_shared { @@ -684,11 +679,11 @@ func TestCcLibrarySharedStubs_IgnorePlatformAvailable(t *testing.T) { Description: "cc_library_shared stubs", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "a", stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, include_build_directory: false, apex_available: ["//apex_available:platform", "apex_a"], } @@ -720,11 +715,11 @@ func TestCcLibraryDoesNotDropStubDepIfNoVariationAcrossAxis(t *testing.T) { Description: "cc_library depeends on impl for all configurations", ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "a", stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, apex_available: ["//apex_available:platform"], } cc_library_shared { @@ -747,11 +742,11 @@ func TestCcLibrarySharedStubs_MultipleApexAvailable(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library_shared", ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: soongCcLibrarySharedPreamble + ` cc_library_shared { name: "a", stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, - bazel_module: { bp2build_available: false }, include_build_directory: false, apex_available: ["//apex_available:platform", "apex_a", "apex_b"], } @@ -929,14 +924,14 @@ func TestCCLibrarySharedRuntimeDeps(t *testing.T) { cc_library_shared { name: "foo", - runtime_libs: ["foo"], + runtime_libs: ["bar"], }`, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "runtime_deps": `[":foo"]`, + "runtime_deps": `[":bar"]`, "local_includes": `["."]`, }), }, @@ -1442,6 +1437,7 @@ cc_library_shared { `, ExpectedBazelTargets: []string{ makeCcStubSuiteTargets("a", AttrNameToString{ + "api_surface": `"module-libapi"`, "soname": `"a.so"`, "source_library_label": `"//:a"`, "stubs_symbol_file": `"a.map.txt"`, @@ -1456,6 +1452,7 @@ cc_library_shared { "stubs_symbol_file": `"a.map.txt"`, }), makeCcStubSuiteTargets("b", AttrNameToString{ + "api_surface": `"module-libapi"`, "soname": `"b.so"`, "source_library_label": `"//:b"`, "stubs_symbol_file": `"b.map.txt"`, @@ -1592,3 +1589,62 @@ cc_library_shared{ ]`, })}}) } + +func TestCcLibrarySdkVariantUsesStubs(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared stubs", + ModuleTypeUnderTest: "cc_library_shared", + ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + StubbedBuildDefinitions: []string{"libNoStubs", "libHasApexStubs", "libHasApexAndNdkStubs"}, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "libUsesSdk", + sdk_version: "current", + shared_libs: [ + "libNoStubs", + "libHasApexStubs", + "libHasApexAndNdkStubs", + ] +} +cc_library_shared { + name: "libNoStubs", +} +cc_library_shared { + name: "libHasApexStubs", + stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, + apex_available: ["apex_a"], +} +cc_library_shared { + name: "libHasApexAndNdkStubs", + stubs: { symbol_file: "b.map.txt", versions: ["28", "29", "current"] }, + apex_available: ["apex_b"], +} +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 }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "libUsesSdk", AttrNameToString{ + "implementation_dynamic_deps": `[":libNoStubs"] + select({ + "//build/bazel/rules/apex:system": [ + "@api_surfaces//module-libapi/current:libHasApexStubs", + "@api_surfaces//module-libapi/current:libHasApexAndNdkStubs", + ], + "//build/bazel/rules/apex:unbundled_app": [ + ":libHasApexStubs", + "//.:libHasApexAndNdkStubs.ndk_stub_libs-current", + ], + "//conditions:default": [ + ":libHasApexStubs", + ":libHasApexAndNdkStubs", + ], + })`, + "local_includes": `["."]`, + "sdk_version": `"current"`, + }), + }, + }) +} diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index b9508e95b..7b97b3906 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -96,41 +96,37 @@ func TestCcLibraryStaticSimple(t *testing.T) { "implicit_include_1.h": "", "implicit_include_2.h": "", }, + StubbedBuildDefinitions: []string{"header_lib_1", "header_lib_2", + "static_lib_1", "static_lib_2", "whole_static_lib_1", "whole_static_lib_2"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library_headers { name: "header_lib_1", export_include_dirs: ["header_lib_1"], - bazel_module: { bp2build_available: false }, } cc_library_headers { name: "header_lib_2", export_include_dirs: ["header_lib_2"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_lib_1", srcs: ["static_lib_1.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_lib_2", srcs: ["static_lib_2.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_1", srcs: ["whole_static_lib_1.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { name: "whole_static_lib_2", srcs: ["whole_static_lib_2.cc"], - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -392,16 +388,15 @@ cc_library_static { func TestCcLibraryStaticArchSpecificStaticLib(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static arch-specific static_libs", - Filesystem: map[string]string{}, + Description: "cc_library_static arch-specific static_libs", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"static_dep", "static_dep2"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library_static { name: "static_dep", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep2", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "foo_static", @@ -425,16 +420,15 @@ cc_library_static { func TestCcLibraryStaticOsSpecificStaticLib(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static os-specific static_libs", - Filesystem: map[string]string{}, + Description: "cc_library_static os-specific static_libs", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"static_dep", "static_dep2"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library_static { name: "static_dep", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep2", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "foo_static", @@ -460,22 +454,20 @@ func TestCcLibraryStaticBaseArchOsSpecificStaticLib(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ Description: "cc_library_static base, arch and os-specific static_libs", Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"static_dep", "static_dep2", "static_dep3", + "static_dep4"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library_static { name: "static_dep", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep2", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep3", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "static_dep4", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "foo_static", @@ -756,12 +748,12 @@ cc_library_static { func TestCcLibraryStaticMultipleDepSameName(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static multiple dep same name panic", - Filesystem: map[string]string{}, + Description: "cc_library_static multiple dep same name panic", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"static_dep"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library_static { name: "static_dep", - bazel_module: { bp2build_available: false }, } cc_library_static { name: "foo_static", @@ -961,17 +953,16 @@ cc_library_static { func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr"}, Blueprint: soongCcLibraryStaticPreamble + ` genrule { name: "generated_hdr", cmd: "nothing to see here", - bazel_module: { bp2build_available: false }, } genrule { name: "export_generated_hdr", cmd: "nothing to see here", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1005,19 +996,18 @@ cc_library_static { func TestCcLibraryStaticGeneratedHeadersMultipleExports(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"generated_hdr", "export_generated_hdr"}, Blueprint: soongCcLibraryStaticPreamble + ` genrule { name: "generated_hdr", cmd: "nothing to see here", export_include_dirs: ["foo", "bar"], - bazel_module: { bp2build_available: false }, } genrule { name: "export_generated_hdr", cmd: "nothing to see here", export_include_dirs: ["a", "b"], - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1040,22 +1030,26 @@ cc_library_static { func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ Description: "cc_library_static arch srcs/exclude_srcs with generated files", + StubbedBuildDefinitions: []string{"//dep:generated_src_other_pkg", "//dep:generated_hdr_other_pkg", + "//dep:generated_src_other_pkg_x86", "//dep:generated_hdr_other_pkg_x86", "//dep:generated_hdr_other_pkg_android", + "generated_src", "generated_src_not_x86", "generated_src_android", "generated_hdr", + }, Filesystem: map[string]string{ "common.cpp": "", "for-x86.cpp": "", "not-for-x86.cpp": "", "not-for-everything.cpp": "", - "dep/Android.bp": SimpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg_x86") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_x86") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_android"), + "dep/Android.bp": simpleModule("genrule", "generated_src_other_pkg") + + simpleModule("genrule", "generated_hdr_other_pkg") + + simpleModule("genrule", "generated_src_other_pkg_x86") + + simpleModule("genrule", "generated_hdr_other_pkg_x86") + + simpleModule("genrule", "generated_hdr_other_pkg_android"), }, Blueprint: soongCcLibraryStaticPreamble + - SimpleModuleDoNotConvertBp2build("genrule", "generated_src") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_src_not_x86") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_src_android") + - SimpleModuleDoNotConvertBp2build("genrule", "generated_hdr") + ` + simpleModule("genrule", "generated_src") + + simpleModule("genrule", "generated_src_not_x86") + + simpleModule("genrule", "generated_src_android") + + simpleModule("genrule", "generated_hdr") + ` cc_library_static { name: "foo_static", srcs: ["common.cpp", "not-for-*.cpp"], @@ -1340,11 +1334,11 @@ cc_library_static { func TestStaticLibrary_SystemSharedLibsBionicEmpty(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_lib empty for bionic variant", + Description: "cc_library_static system_shared_lib empty for bionic variant", + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1374,11 +1368,11 @@ func TestStaticLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) { // only for linux_bionic, but `android` had `["libc", "libdl", "libm"]. // b/195791252 tracks the fix. runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_lib empty for linux_bionic variant", + Description: "cc_library_static system_shared_lib empty for linux_bionic variant", + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1404,11 +1398,11 @@ cc_library_static { func TestStaticLibrary_SystemSharedLibsMuslEmpty(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_lib empty for musl variant", + Description: "cc_library_static system_shared_lib empty for musl variant", + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1431,11 +1425,11 @@ cc_library_static { func TestStaticLibrary_SystemSharedLibsLinuxMuslEmpty(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_lib empty for linux_musl variant", + Description: "cc_library_static system_shared_lib empty for linux_musl variant", + StubbedBuildDefinitions: []string{"libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1458,12 +1452,12 @@ cc_library_static { func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_libs set for bionic variant", + Description: "cc_library_static system_shared_libs set for bionic variant", + StubbedBuildDefinitions: []string{"libc", "libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + - SimpleModuleDoNotConvertBp2build("cc_library", "libc") + ` + simpleModule("cc_library", "libc") + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1491,13 +1485,13 @@ cc_library_static { func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_libs set for root and linux_bionic variant", + Description: "cc_library_static system_shared_libs set for root and linux_bionic variant", + StubbedBuildDefinitions: []string{"libc", "libm", "libc_musl"}, Blueprint: soongCcLibraryStaticPreamble + - SimpleModuleDoNotConvertBp2build("cc_library", "libc") + - SimpleModuleDoNotConvertBp2build("cc_library", "libm") + ` + simpleModule("cc_library", "libc") + + simpleModule("cc_library", "libm") + ` cc_library { name: "libc_musl", - bazel_module: { bp2build_available: false }, } cc_library_static { @@ -1525,9 +1519,10 @@ cc_library_static { func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ - Description: "cc_library_static system_shared_lib empty for linux_bionic variant", + Description: "cc_library_static system_shared_lib empty for linux_bionic variant", + StubbedBuildDefinitions: []string{"libc", "libm"}, Blueprint: soongCcLibraryStaticPreamble + - SimpleModuleDoNotConvertBp2build("cc_library", "libc") + ` + simpleModule("cc_library", "libc") + ` cc_library { name: "libm", @@ -1535,7 +1530,6 @@ cc_library { symbol_file: "libm.map.txt", versions: ["current"], }, - bazel_module: { bp2build_available: false }, apex_available: ["com.android.runtime"], } @@ -1613,6 +1607,7 @@ cc_library_static { func TestCcLibraryStaticProto(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, Blueprint: soongCcProtoPreamble + `cc_library_static { name: "foo", srcs: ["foo.proto"], @@ -1639,6 +1634,7 @@ func TestCcLibraryStaticUseVersionLib(t *testing.T) { Filesystem: map[string]string{ soongCcVersionLibBpPath: soongCcVersionLibBp, }, + StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion", "libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, Blueprint: soongCcProtoPreamble + `cc_library_static { name: "foo", use_version_lib: true, @@ -1658,6 +1654,8 @@ func TestCcLibraryStaticUseVersionLibHasDep(t *testing.T) { Filesystem: map[string]string{ soongCcVersionLibBpPath: soongCcVersionLibBp, }, + StubbedBuildDefinitions: []string{"//build/soong/cc/libbuildversion:libbuildversion", "libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, + Blueprint: soongCcProtoPreamble + `cc_library_static { name: "foo", use_version_lib: true, @@ -1674,6 +1672,7 @@ func TestCcLibraryStaticUseVersionLibHasDep(t *testing.T) { func TestCcLibraryStaticStdInFlags(t *testing.T) { runCcLibraryStaticTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"libprotobuf-cpp-full", "libprotobuf-cpp-lite"}, Blueprint: soongCcProtoPreamble + `cc_library_static { name: "foo", cflags: ["-std=candcpp"], @@ -1767,14 +1766,14 @@ func TestCCLibraryStaticRuntimeDeps(t *testing.T) { cc_library_static { name: "foo", - runtime_libs: ["foo"], + runtime_libs: ["bar"], }`, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), MakeBazelTarget("cc_library_static", "foo", AttrNameToString{ - "runtime_deps": `[":foo"]`, + "runtime_deps": `[":bar"]`, "local_includes": `["."]`, }), }, @@ -2260,6 +2259,7 @@ func TestCcLibraryWithProtoInGeneratedSrcs(t *testing.T) { Description: "cc_library with a .proto file generated from a genrule", ModuleTypeUnderTest: "cc_library_static", ModuleTypeUnderTestFactory: cc.LibraryStaticFactory, + StubbedBuildDefinitions: []string{"libprotobuf-cpp-lite"}, Blueprint: soongCcLibraryPreamble + ` cc_library_static { name: "mylib", @@ -2269,7 +2269,7 @@ genrule { name: "myprotogen", out: ["myproto.proto"], } -` + SimpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"), +` + simpleModule("cc_library", "libprotobuf-cpp-lite"), ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "mylib", AttrNameToString{ "local_includes": `["."]`, diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go index ecfcb5a93..e1e2f43d7 100644 --- a/bp2build/cc_object_conversion_test.go +++ b/bp2build/cc_object_conversion_test.go @@ -317,7 +317,8 @@ func TestCcObjectLinkerScript(t *testing.T) { func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) { runCcObjectTestCase(t, Bp2buildTestCase{ - Description: "cc_object setting deps and linker_script across archs", + Description: "cc_object setting deps and linker_script across archs", + StubbedBuildDefinitions: []string{"x86_obj", "x86_64_obj", "arm_obj"}, Blueprint: `cc_object { name: "foo", srcs: ["base.cpp"], @@ -343,7 +344,6 @@ cc_object { system_shared_libs: [], srcs: ["x86.cpp"], include_build_directory: false, - bazel_module: { bp2build_available: false }, } cc_object { @@ -351,7 +351,6 @@ cc_object { system_shared_libs: [], srcs: ["x86_64.cpp"], include_build_directory: false, - bazel_module: { bp2build_available: false }, } cc_object { @@ -359,7 +358,6 @@ cc_object { system_shared_libs: [], srcs: ["arm.cpp"], include_build_directory: false, - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go index b88960e0e..8c33be3c9 100644 --- a/bp2build/cc_prebuilt_library_conversion_test.go +++ b/bp2build/cc_prebuilt_library_conversion_test.go @@ -17,6 +17,7 @@ import ( "fmt" "testing" + "android/soong/android" "android/soong/cc" ) @@ -360,3 +361,52 @@ cc_prebuilt_library { }, }) } + +func TestPrebuiltNdkStlConversion(t *testing.T) { + registerNdkStlModuleTypes := func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("ndk_prebuilt_static_stl", cc.NdkPrebuiltStaticStlFactory) + ctx.RegisterModuleType("ndk_prebuilt_shared_stl", cc.NdkPrebuiltSharedStlFactory) + } + RunBp2BuildTestCase(t, registerNdkStlModuleTypes, Bp2buildTestCase{ + Description: "TODO", + Blueprint: ` +ndk_prebuilt_static_stl { + name: "ndk_libfoo_static", + export_include_dirs: ["dir1", "dir2"], +} +ndk_prebuilt_shared_stl { + name: "ndk_libfoo_shared", + export_include_dirs: ["dir1", "dir2"], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_prebuilt_library_static", "ndk_libfoo_static", AttrNameToString{ + "static_library": `select({ + "//build/bazel/platforms/os_arch:android_arm": "current/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libfoo_static.a", + "//build/bazel/platforms/os_arch:android_arm64": "current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libfoo_static.a", + "//build/bazel/platforms/os_arch:android_riscv64": "current/sources/cxx-stl/llvm-libc++/libs/riscv64/libfoo_static.a", + "//build/bazel/platforms/os_arch:android_x86": "current/sources/cxx-stl/llvm-libc++/libs/x86/libfoo_static.a", + "//build/bazel/platforms/os_arch:android_x86_64": "current/sources/cxx-stl/llvm-libc++/libs/x86_64/libfoo_static.a", + "//conditions:default": None, + })`, + "export_system_includes": `[ + "dir1", + "dir2", + ]`, + }), + MakeBazelTarget("cc_prebuilt_library_shared", "ndk_libfoo_shared", AttrNameToString{ + "shared_library": `select({ + "//build/bazel/platforms/os_arch:android_arm": "current/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libfoo_shared.so", + "//build/bazel/platforms/os_arch:android_arm64": "current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libfoo_shared.so", + "//build/bazel/platforms/os_arch:android_riscv64": "current/sources/cxx-stl/llvm-libc++/libs/riscv64/libfoo_shared.so", + "//build/bazel/platforms/os_arch:android_x86": "current/sources/cxx-stl/llvm-libc++/libs/x86/libfoo_shared.so", + "//build/bazel/platforms/os_arch:android_x86_64": "current/sources/cxx-stl/llvm-libc++/libs/x86_64/libfoo_shared.so", + "//conditions:default": None, + })`, + "export_system_includes": `[ + "dir1", + "dir2", + ]`, + }), + }, + }) +} diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go index 74a5c0d11..679a36461 100644 --- a/bp2build/cc_test_conversion_test.go +++ b/bp2build/cc_test_conversion_test.go @@ -24,10 +24,11 @@ import ( ) type ccTestBp2buildTestCase struct { - description string - blueprint string - filesystem map[string]string - targets []testBazelTarget + description string + blueprint string + filesystem map[string]string + targets []testBazelTarget + stubbedBuildDefinitions []string } func registerCcTestModuleTypes(ctx android.RegistrationContext) { @@ -52,6 +53,7 @@ func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) { ModuleTypeUnderTestFactory: cc.TestFactory, Description: description, Blueprint: testCase.blueprint, + StubbedBuildDefinitions: testCase.stubbedBuildDefinitions, }) }) } @@ -59,6 +61,8 @@ func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) { func TestBasicCcTest(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ description: "basic cc_test with commonly used attributes", + stubbedBuildDefinitions: []string{"libbuildversion", "libprotobuf-cpp-lite", "libprotobuf-cpp-full", + "foolib", "hostlib", "data_mod", "cc_bin", "cc_lib", "cc_test_lib2", "libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest", @@ -89,14 +93,14 @@ cc_test_library { host_supported: true, include_build_directory: false, } -` + SimpleModuleDoNotConvertBp2build("cc_library", "foolib") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "hostlib") + - SimpleModuleDoNotConvertBp2build("genrule", "data_mod") + - SimpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") + - SimpleModuleDoNotConvertBp2build("cc_library", "cc_lib") + - SimpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library", "foolib") + + simpleModule("cc_library_static", "hostlib") + + simpleModule("genrule", "data_mod") + + simpleModule("cc_binary", "cc_bin") + + simpleModule("cc_library", "cc_lib") + + simpleModule("cc_test_library", "cc_test_lib2") + + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_library_shared", "cc_test_lib1", AttrNameToString{}}, {"cc_library_static", "cc_test_lib1_bp2build_cc_library_static", AttrNameToString{}}, @@ -188,7 +192,8 @@ cc_test { func TestCcTest_TestOptions_Tags(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test with test_options.tags converted to tags", + description: "cc test with test_options.tags converted to tags", + stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest", @@ -196,8 +201,8 @@ cc_test { srcs: ["test.cpp"], test_options: { tags: ["no-remote"] }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "tags": `["no-remote"]`, @@ -230,14 +235,15 @@ func TestCcTest_TestConfig(t *testing.T) { filesystem: map[string]string{ "test_config.xml": "", }, + stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest", srcs: ["test.cpp"], test_config: "test_config.xml", } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -269,13 +275,14 @@ func TestCcTest_TestConfigAndroidTestXML(t *testing.T) { "AndroidTest.xml": "", "DynamicConfig.xml": "", }, + stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest", srcs: ["test.cpp"], } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -307,6 +314,7 @@ func TestCcTest_TestConfigTemplateOptions(t *testing.T) { filesystem: map[string]string{ "test_config_template.xml": "", }, + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", @@ -315,8 +323,8 @@ cc_test { auto_gen_config: true, isolated: true, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "auto_generate_test_config": "True", @@ -347,15 +355,16 @@ cc_test { func TestCcTest_WithExplicitGTestDepInAndroidBp(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file", + description: "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file", + stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest", srcs: ["test.cpp"], static_libs: ["libgtest"], } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -382,15 +391,16 @@ cc_test { func TestCcTest_WithIsolatedTurnedOn(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main", + description: "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main", + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", srcs: ["test.cpp"], isolated: true, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -415,7 +425,8 @@ cc_test { func TestCcTest_GtestExplicitlySpecifiedInAndroidBp(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well", + description: "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well", + stubbedBuildDefinitions: []string{"libgtest_main", "libgtest"}, blueprint: ` cc_test { name: "mytest_with_gtest", @@ -425,8 +436,8 @@ cc_test { name: "mytest_with_no_gtest", gtest: false, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") + - SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"), +` + simpleModule("cc_library_static", "libgtest_main") + + simpleModule("cc_library_static", "libgtest"), targets: []testBazelTarget{ {"cc_test", "mytest_with_gtest", AttrNameToString{ "local_includes": `["."]`, @@ -466,7 +477,8 @@ cc_test { func TestCcTest_DisableMemtagHeap(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that disable memtag_heap", + description: "cc test that disable memtag_heap", + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", @@ -477,8 +489,8 @@ cc_test { memtag_heap: false, }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -499,7 +511,8 @@ cc_test { func TestCcTest_RespectArm64MemtagHeap(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that disable memtag_heap", + description: "cc test that disable memtag_heap", + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", @@ -513,8 +526,8 @@ cc_test { } }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -535,7 +548,8 @@ cc_test { func TestCcTest_IgnoreNoneArm64MemtagHeap(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that disable memtag_heap", + description: "cc test that disable memtag_heap", + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", @@ -549,8 +563,8 @@ cc_test { } }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, @@ -574,7 +588,8 @@ cc_test { func TestCcTest_Arm64MemtagHeapOverrideNoConfigOne(t *testing.T) { runCcTestTestCase(t, ccTestBp2buildTestCase{ - description: "cc test that disable memtag_heap", + description: "cc test that disable memtag_heap", + stubbedBuildDefinitions: []string{"libgtest_isolated_main", "liblog"}, blueprint: ` cc_test { name: "mytest", @@ -594,8 +609,8 @@ cc_test { } }, } -` + SimpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") + - SimpleModuleDoNotConvertBp2build("cc_library", "liblog"), +` + simpleModule("cc_library_static", "libgtest_isolated_main") + + simpleModule("cc_library", "liblog"), targets: []testBazelTarget{ {"cc_test", "mytest", AttrNameToString{ "local_includes": `["."]`, diff --git a/bp2build/droiddoc_exported_dir_conversion_test.go b/bp2build/droiddoc_exported_dir_conversion_test.go new file mode 100644 index 000000000..dee67f4ed --- /dev/null +++ b/bp2build/droiddoc_exported_dir_conversion_test.go @@ -0,0 +1,60 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "regexp" + "testing" + + "android/soong/java" +) + +func TestDroiddocExportedDir(t *testing.T) { + bp := ` + droiddoc_exported_dir { + name: "test-module", + path: "docs", + } + ` + p := regexp.MustCompile(`\t*\|`) + dedent := func(s string) string { + return p.ReplaceAllString(s, "") + } + expectedBazelTargets := []string{ + MakeBazelTargetNoRestrictions( + "droiddoc_exported_dir", + "test-module", + AttrNameToString{ + "dir": `"docs"`, + "srcs": dedent(`[ + | "docs/android/1.txt", + | "docs/android/nested-1/2.txt", + | "//docs/android/nested-2:3.txt", + | "//docs/android/nested-2:Android.bp", + | ]`), + }), + //note we are not excluding Android.bp files from subpackages for now + } + RunBp2BuildTestCase(t, java.RegisterDocsBuildComponents, Bp2buildTestCase{ + Blueprint: bp, + ExpectedBazelTargets: expectedBazelTargets, + Filesystem: map[string]string{ + "docs/android/1.txt": "", + "docs/android/nested-1/2.txt": "", + "docs/android/nested-2/Android.bp": "", + "docs/android/nested-2/3.txt": "", + }, + }) +} diff --git a/bp2build/fdo_profile_conversion_test.go b/bp2build/fdo_profile_conversion_test.go new file mode 100644 index 000000000..4d04283ca --- /dev/null +++ b/bp2build/fdo_profile_conversion_test.go @@ -0,0 +1,85 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "testing" + + "android/soong/android" + "android/soong/cc" +) + +func runFdoProfileTestCase(t *testing.T, tc Bp2buildTestCase) { + t.Helper() + (&tc).ModuleTypeUnderTest = "fdo_profile" + (&tc).ModuleTypeUnderTestFactory = cc.FdoProfileFactory + RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc) +} + +func TestFdoProfile(t *testing.T) { + testcases := []struct { + name string + bp string + expectedBazelAttrs AttrNameToString + }{ + { + name: "fdo_profile with arch-specific profiles", + bp: ` +fdo_profile { + name: "foo", + arch: { + arm: { + profile: "foo_arm.afdo", + }, + arm64: { + profile: "foo_arm64.afdo", + } + } +}`, + expectedBazelAttrs: AttrNameToString{ + "profile": `select({ + "//build/bazel/platforms/arch:arm": "foo_arm.afdo", + "//build/bazel/platforms/arch:arm64": "foo_arm64.afdo", + "//conditions:default": None, + })`, + }, + }, + { + name: "fdo_profile with arch-agnostic profile", + bp: ` +fdo_profile { + name: "foo", + profile: "foo.afdo", +}`, + expectedBazelAttrs: AttrNameToString{ + "profile": `"foo.afdo"`, + }, + }, + } + + for _, test := range testcases { + t.Run(test.name, func(t *testing.T) { + expectedBazelTargets := []string{ + // TODO(b/276287371): Add device-only restriction back to fdo_profile targets + MakeBazelTargetNoRestrictions("fdo_profile", "foo", test.expectedBazelAttrs), + } + runFdoProfileTestCase(t, Bp2buildTestCase{ + Description: test.name, + Blueprint: test.bp, + ExpectedBazelTargets: expectedBazelTargets, + }) + }) + } +} diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go index 2a10a14d4..7e9b17bca 100644 --- a/bp2build/genrule_conversion_test.go +++ b/bp2build/genrule_conversion_test.go @@ -93,7 +93,6 @@ func TestGenruleCliVariableReplacement(t *testing.T) { out: ["foo_tool.out"], srcs: ["foo_tool.in"], cmd: "cp $(in) $(out)", - bazel_module: { bp2build_available: false }, } %s { @@ -124,6 +123,7 @@ func TestGenruleCliVariableReplacement(t *testing.T) { ModuleTypeUnderTestFactory: tc.factory, Blueprint: fmt.Sprintf(bp, tc.moduleType, tc.moduleType), ExpectedBazelTargets: expectedBazelTargets, + StubbedBuildDefinitions: []string{"foo.tool", "other.tool"}, }) }) } @@ -262,6 +262,7 @@ func TestGenruleLocationsAbsoluteLabel(t *testing.T) { Blueprint: fmt.Sprintf(bp, tc.moduleType), ExpectedBazelTargets: expectedBazelTargets, Filesystem: otherGenruleBp(tc.moduleType), + StubbedBuildDefinitions: []string{"//other:foo.tool"}, }) }) } @@ -326,6 +327,7 @@ func TestGenruleSrcsLocationsAbsoluteLabel(t *testing.T) { Blueprint: fmt.Sprintf(bp, tc.moduleType), ExpectedBazelTargets: expectedBazelTargets, Filesystem: otherGenruleBp(tc.moduleType), + StubbedBuildDefinitions: []string{"//other:foo.tool", "//other:other.tool"}, }) }) } @@ -390,6 +392,7 @@ func TestGenruleLocationLabelShouldSubstituteFirstToolLabel(t *testing.T) { Blueprint: fmt.Sprintf(bp, tc.moduleType), ExpectedBazelTargets: expectedBazelTargets, Filesystem: otherGenruleBp(tc.moduleType), + StubbedBuildDefinitions: []string{"//other:foo.tool", "//other:other.tool"}, }) }) } @@ -454,6 +457,7 @@ func TestGenruleLocationsLabelShouldSubstituteFirstToolLabel(t *testing.T) { Blueprint: fmt.Sprintf(bp, tc.moduleType), ExpectedBazelTargets: expectedBazelTargets, Filesystem: otherGenruleBp(tc.moduleType), + StubbedBuildDefinitions: []string{"//other:foo.tool", "//other:other.tool"}, }) }) } @@ -948,6 +952,7 @@ genrule { ModuleTypeUnderTest: "genrule", ModuleTypeUnderTestFactory: genrule.GenRuleFactory, ExpectedBazelTargets: expectedBazelTargets, + StubbedBuildDefinitions: []string{"//mynamespace/dir:mymodule"}, }) }) diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go index 39e55c410..7d8ab635a 100644 --- a/bp2build/java_binary_host_conversion_test.go +++ b/bp2build/java_binary_host_conversion_test.go @@ -26,6 +26,7 @@ func runJavaBinaryHostTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() (&tc).ModuleTypeUnderTest = "java_binary_host" (&tc).ModuleTypeUnderTestFactory = java.BinaryHostFactory + tc.StubbedBuildDefinitions = append(tc.StubbedBuildDefinitions, "//other:jni-lib-1") RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory) ctx.RegisterModuleType("java_library", java.LibraryFactory) @@ -81,8 +82,9 @@ func TestJavaBinaryHost(t *testing.T) { func TestJavaBinaryHostRuntimeDeps(t *testing.T) { runJavaBinaryHostTestCase(t, Bp2buildTestCase{ - Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.", - Filesystem: testFs, + Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.", + Filesystem: testFs, + StubbedBuildDefinitions: []string{"java-dep-1"}, Blueprint: `java_binary_host { name: "java-binary-host-1", static_libs: ["java-dep-1"], @@ -93,7 +95,6 @@ func TestJavaBinaryHostRuntimeDeps(t *testing.T) { java_library { name: "java-dep-1", srcs: ["a.java"], - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -111,8 +112,9 @@ java_library { func TestJavaBinaryHostLibs(t *testing.T) { runJavaBinaryHostTestCase(t, Bp2buildTestCase{ - Description: "java_binary_host with srcs, libs.", - Filesystem: testFs, + Description: "java_binary_host with srcs, libs.", + Filesystem: testFs, + StubbedBuildDefinitions: []string{"prebuilt_java-lib-dep-1"}, Blueprint: `java_binary_host { name: "java-binary-host-libs", libs: ["java-lib-dep-1"], @@ -123,7 +125,6 @@ func TestJavaBinaryHostLibs(t *testing.T) { java_import_host{ name: "java-lib-dep-1", jars: ["foo.jar"], - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go index 8c782172e..7e4e44ec8 100644 --- a/bp2build/java_library_conversion_test.go +++ b/bp2build/java_library_conversion_test.go @@ -15,7 +15,6 @@ package bp2build import ( - "fmt" "testing" "android/soong/android" @@ -70,6 +69,7 @@ java_library { func TestJavaLibraryConvertsStaticLibsToDepsAndExports(t *testing.T) { runJavaLibraryTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"java-lib-2", "java-lib-3"}, Blueprint: `java_library { name: "java-lib-1", srcs: ["a.java"], @@ -83,14 +83,12 @@ java_library { name: "java-lib-2", srcs: ["b.java"], sdk_version: "current", - bazel_module: { bp2build_available: false }, } java_library { name: "java-lib-3", srcs: ["c.java"], sdk_version: "current", - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ @@ -109,6 +107,7 @@ java_library { func TestJavaLibraryConvertsStaticLibsToExportsIfNoSrcs(t *testing.T) { runJavaLibraryTestCase(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"java-lib-2"}, Blueprint: `java_library { name: "java-lib-1", static_libs: ["java-lib-2"], @@ -119,7 +118,6 @@ func TestJavaLibraryConvertsStaticLibsToExportsIfNoSrcs(t *testing.T) { java_library { name: "java-lib-2", srcs: ["a.java"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ @@ -143,28 +141,9 @@ java_library { }) } -func TestJavaLibraryFailsToConvertLibsWithNoSrcs(t *testing.T) { - runJavaLibraryTestCase(t, Bp2buildTestCase{ - ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."), - Blueprint: `java_library { - name: "java-lib-1", - libs: ["java-lib-2"], - sdk_version: "current", - bazel_module: { bp2build_available: true }, -} - -java_library { - name: "java-lib-2", - srcs: ["a.java"], - sdk_version: "current", - bazel_module: { bp2build_available: false }, -}`, - ExpectedBazelTargets: []string{}, - }) -} - func TestJavaLibraryPlugins(t *testing.T) { runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"java-plugin-1"}, Blueprint: `java_library { name: "java-lib-1", plugins: ["java-plugin-1"], @@ -175,7 +154,6 @@ func TestJavaLibraryPlugins(t *testing.T) { java_plugin { name: "java-plugin-1", srcs: ["a.java"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ @@ -216,6 +194,7 @@ func TestJavaLibraryJavaVersion(t *testing.T) { func TestJavaLibraryErrorproneEnabledManually(t *testing.T) { runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{ + StubbedBuildDefinitions: []string{"plugin2"}, Blueprint: `java_library { name: "java-lib-1", srcs: ["a.java"], @@ -230,7 +209,6 @@ func TestJavaLibraryErrorproneEnabledManually(t *testing.T) { java_plugin { name: "plugin2", srcs: ["a.java"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ @@ -441,13 +419,12 @@ func TestJavaLibraryResourcesExcludeFile(t *testing.T) { func TestJavaLibraryResourcesWithMultipleDirs(t *testing.T) { runJavaLibraryTestCase(t, Bp2buildTestCase{ Filesystem: map[string]string{ - "res/a.res": "", - "res1/b.res": "", - "res2/b.java": "", + "res/a.res": "", + "res1/b.res": "", }, Blueprint: `java_library { name: "java-lib-1", - java_resource_dirs: ["res", "res1", "res2"], + java_resource_dirs: ["res", "res1"], sdk_version: "current", }`, ExpectedBazelTargets: []string{ @@ -640,6 +617,7 @@ func TestJavaLibraryAidlNonAdjacentAidlFilegroup(t *testing.T) { Description: "java_library with non adjacent aidl filegroup", ModuleTypeUnderTest: "java_library", ModuleTypeUnderTestFactory: java.LibraryFactory, + StubbedBuildDefinitions: []string{"A_aidl"}, Filesystem: map[string]string{ "path/to/A/Android.bp": ` filegroup { @@ -677,7 +655,7 @@ func TestConvertArmNeonVariant(t *testing.T) { Description: "Android Library - simple arch feature", ModuleTypeUnderTest: "android_library", ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` + Blueprint: simpleModule("android_library", "static_lib_dep") + ` android_library { name: "TestLib", manifest: "manifest/AndroidManifest.xml", @@ -715,7 +693,7 @@ func TestConvertMultipleArchFeatures(t *testing.T) { Description: "Android Library - multiple arch features", ModuleTypeUnderTest: "android_library", ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` + Blueprint: simpleModule("android_library", "static_lib_dep") + ` android_library { name: "TestLib", manifest: "manifest/AndroidManifest.xml", @@ -761,7 +739,7 @@ func TestConvertExcludeSrcsArchFeature(t *testing.T) { Description: "Android Library - exclude_srcs with arch feature", ModuleTypeUnderTest: "android_library", ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, - Blueprint: SimpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` + Blueprint: simpleModule("android_library", "static_lib_dep") + ` android_library { name: "TestLib", manifest: "manifest/AndroidManifest.xml", @@ -871,7 +849,8 @@ func TestJavaLibraryKotlinCommonSrcs(t *testing.T) { func TestJavaLibraryArchVariantDeps(t *testing.T) { runJavaLibraryTestCase(t, Bp2buildTestCase{ - Description: "java_library with arch variant libs", + Description: "java_library with arch variant libs", + StubbedBuildDefinitions: []string{"java-lib-2", "java-lib-3", "java-lib-4"}, Blueprint: `java_library { name: "java-lib-1", srcs: ["a.java"], @@ -888,17 +867,14 @@ func TestJavaLibraryArchVariantDeps(t *testing.T) { java_library{ name: "java-lib-2", - bazel_module: { bp2build_available: false }, } java_library{ name: "java-lib-3", - bazel_module: { bp2build_available: false }, } java_library{ name: "java-lib-4", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -1047,14 +1023,3 @@ filegroup { ctx.RegisterModuleType("filegroup", android.FileGroupFactory) }) } - -func TestJavaSdkVersionCorePlatformDoesNotConvert(t *testing.T) { - runJavaLibraryTestCase(t, Bp2buildTestCase{ - Blueprint: `java_library { - name: "java-lib-1", - sdk_version: "core_platform", - bazel_module: { bp2build_available: true }, -}`, - ExpectedBazelTargets: []string{}, - }) -} diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go index f2b6f20a4..dcc17b5ce 100644 --- a/bp2build/java_plugin_conversion_test.go +++ b/bp2build/java_plugin_conversion_test.go @@ -32,7 +32,8 @@ func runJavaPluginTestCase(t *testing.T, tc Bp2buildTestCase) { func TestJavaPlugin(t *testing.T) { runJavaPluginTestCase(t, Bp2buildTestCase{ - Description: "java_plugin with srcs, libs, static_libs", + Description: "java_plugin with srcs, libs, static_libs", + StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"}, Blueprint: `java_plugin { name: "java-plug-1", srcs: ["a.java", "b.java"], @@ -45,13 +46,11 @@ func TestJavaPlugin(t *testing.T) { java_library { name: "java-lib-1", srcs: ["b.java"], - bazel_module: { bp2build_available: false }, } java_library { name: "java-lib-2", srcs: ["c.java"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ @@ -75,7 +74,8 @@ java_library { func TestJavaPluginNoSrcs(t *testing.T) { runJavaPluginTestCase(t, Bp2buildTestCase{ - Description: "java_plugin without srcs converts (static) libs to deps", + Description: "java_plugin without srcs converts (static) libs to deps", + StubbedBuildDefinitions: []string{"java-lib-1", "java-lib-2"}, Blueprint: `java_plugin { name: "java-plug-1", libs: ["java-lib-1"], @@ -86,13 +86,11 @@ func TestJavaPluginNoSrcs(t *testing.T) { java_library { name: "java-lib-1", srcs: ["b.java"], - bazel_module: { bp2build_available: false }, } java_library { name: "java-lib-2", srcs: ["c.java"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go index dfef6973c..3d55eb27a 100644 --- a/bp2build/java_proto_conversion_test.go +++ b/bp2build/java_proto_conversion_test.go @@ -140,7 +140,8 @@ func TestJavaProtoDefault(t *testing.T) { func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) { runJavaProtoTestCase(t, Bp2buildTestCase{ - Description: "java_library that has only proto srcs", + Description: "java_library that has only proto srcs", + StubbedBuildDefinitions: []string{"java-lib"}, Blueprint: `java_library_static { name: "java-protos", srcs: ["a.proto"], @@ -151,7 +152,6 @@ func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) { java_library_static { name: "java-lib", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -167,10 +167,7 @@ java_library_static { "sdk_version": `"current"`, }), MakeBazelTarget("java_library", "java-protos", AttrNameToString{ - "exports": `[ - ":java-protos_java_proto_lite", - ":java-lib-neverlink", - ]`, + "exports": `[":java-protos_java_proto_lite"]`, "java_version": `"7"`, "sdk_version": `"current"`, }), diff --git a/bp2build/java_sdk_library_import_conversion_test.go b/bp2build/java_sdk_library_import_conversion_test.go new file mode 100644 index 000000000..456f87268 --- /dev/null +++ b/bp2build/java_sdk_library_import_conversion_test.go @@ -0,0 +1,84 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "testing" + + "android/soong/java" +) + +func runJavaSdkLibraryImportTestCase(t *testing.T, tc Bp2buildTestCase) { + t.Helper() + RunBp2BuildTestCase(t, java.RegisterSdkLibraryBuildComponents, tc) +} + +func TestJavaSdkLibraryImport(t *testing.T) { + runJavaSdkLibraryImportTestCase(t, Bp2buildTestCase{ + Blueprint: ` +java_sdk_library_import { + name : "foo", + public: { + current_api: "foo_current.txt", + }, + system: { + current_api: "system_foo_current.txt", + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_sdk_library", "foo", AttrNameToString{ + "public": `"foo_current.txt"`, + "system": `"system_foo_current.txt"`, + }), + }, + }) +} + +func TestJavaSdkLibraryImportPrebuiltPrefixRemoved(t *testing.T) { + runJavaSdkLibraryImportTestCase(t, Bp2buildTestCase{ + Filesystem: map[string]string{ + "foobar/Android.bp": ` +java_sdk_library { + name: "foo", + srcs: ["**/*.java"], +} +`, + "foobar/api/current.txt": "", + "foobar/api/system-current.txt": "", + "foobar/api/test-current.txt": "", + "foobar/api/removed.txt": "", + "foobar/api/system-removed.txt": "", + "foobar/api/test-removed.txt": "", + }, + Blueprint: ` +java_sdk_library_import { + name : "foo", + public: { + current_api: "foo_current.txt", + }, + system: { + current_api: "system_foo_current.txt", + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_sdk_library", "foo", AttrNameToString{ + "public": `"foo_current.txt"`, + "system": `"system_foo_current.txt"`, + }), + }, + }) +} diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go index f41345e87..95c239dbf 100644 --- a/bp2build/java_test_host_conversion_test.go +++ b/bp2build/java_test_host_conversion_test.go @@ -32,8 +32,9 @@ func runJavaTestHostTestCase(t *testing.T, tc Bp2buildTestCase) { func TestJavaTestHostGeneral(t *testing.T) { runJavaTestHostTestCase(t, Bp2buildTestCase{ - Description: "java_test_host general", - Filesystem: map[string]string{}, + Description: "java_test_host general", + Filesystem: map[string]string{}, + StubbedBuildDefinitions: []string{"lib_a", "lib_b"}, Blueprint: ` java_test_host { name: "java_test_host-1", @@ -47,12 +48,10 @@ java_test_host { java_library { name: "lib_a", - bazel_module: { bp2build_available: false }, } java_library { name: "static_libs_a", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ diff --git a/bp2build/platform_compat_config_conversion_test.go b/bp2build/platform_compat_config_conversion_test.go index 4dfcce3a3..d74db5d0b 100644 --- a/bp2build/platform_compat_config_conversion_test.go +++ b/bp2build/platform_compat_config_conversion_test.go @@ -37,6 +37,7 @@ func TestPlatformCompatConfig(t *testing.T) { name: "foo", src: ":lib", }`, + StubbedBuildDefinitions: []string{"//a/b:lib"}, Filesystem: map[string]string{ "a/b/Android.bp": ` java_library { diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go index 4ccdba786..b69c4eab7 100644 --- a/bp2build/python_binary_conversion_test.go +++ b/bp2build/python_binary_conversion_test.go @@ -30,6 +30,7 @@ func TestPythonBinaryHostSimple(t *testing.T) { "b/e.py": "", "files/data.txt": "", }, + StubbedBuildDefinitions: []string{"bar"}, Blueprint: `python_binary_host { name: "foo", main: "a.py", @@ -42,7 +43,6 @@ func TestPythonBinaryHostSimple(t *testing.T) { python_library_host { name: "bar", srcs: ["b/e.py"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("py_binary", "foo", AttrNameToString{ @@ -196,6 +196,7 @@ func TestPythonBinaryMainIsLabel(t *testing.T) { Description: "python_binary_host main label in same package", ModuleTypeUnderTest: "python_binary_host", ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory, + StubbedBuildDefinitions: []string{"a"}, Blueprint: `python_binary_host { name: "foo", main: ":a", @@ -204,7 +205,6 @@ func TestPythonBinaryMainIsLabel(t *testing.T) { genrule { name: "a", - bazel_module: { bp2build_available: false }, } `, ExpectedBazelTargets: []string{ @@ -282,6 +282,7 @@ func TestPythonBinaryDuplicatesInRequired(t *testing.T) { Description: "python_binary_host duplicates in required attribute of the module and its defaults", ModuleTypeUnderTest: "python_binary_host", ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory, + StubbedBuildDefinitions: []string{"r1", "r2"}, Blueprint: `python_binary_host { name: "foo", main: "a.py", @@ -298,8 +299,8 @@ python_defaults { "r1", "r2", ], -}` + SimpleModuleDoNotConvertBp2build("genrule", "r1") + - SimpleModuleDoNotConvertBp2build("genrule", "r2"), +}` + simpleModule("genrule", "r1") + + simpleModule("genrule", "r2"), ExpectedBazelTargets: []string{ MakeBazelTarget("py_binary", "foo", AttrNameToString{ diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go index 595acd2e4..497df8091 100644 --- a/bp2build/python_library_conversion_test.go +++ b/bp2build/python_library_conversion_test.go @@ -13,12 +13,13 @@ import ( type PythonLibBp2Build func(ctx android.TopDownMutatorContext) type pythonLibBp2BuildTestCase struct { - description string - filesystem map[string]string - blueprint string - expectedBazelTargets []testBazelTarget - dir string - expectedError error + description string + filesystem map[string]string + blueprint string + expectedBazelTargets []testBazelTarget + dir string + expectedError error + stubbedBuildDefinitions []string } func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) Bp2buildTestCase { @@ -44,12 +45,13 @@ func convertPythonLibTestCaseToBp2build(tc pythonLibBp2BuildTestCase) Bp2buildTe filesystemCopy[k] = v } return Bp2buildTestCase{ - Description: tc.description, - Filesystem: filesystemCopy, - Blueprint: tc.blueprint, - ExpectedBazelTargets: bp2BuildTargets, - Dir: tc.dir, - ExpectedErr: tc.expectedError, + Description: tc.description, + Filesystem: filesystemCopy, + Blueprint: tc.blueprint, + ExpectedBazelTargets: bp2BuildTargets, + Dir: tc.dir, + ExpectedErr: tc.expectedError, + StubbedBuildDefinitions: tc.stubbedBuildDefinitions, } } @@ -104,6 +106,7 @@ func TestSimplePythonLib(t *testing.T) { "b/e.py": "", "files/data.txt": "", }, + stubbedBuildDefinitions: []string{"bar"}, blueprint: `%s { name: "foo", srcs: ["**/*.py"], @@ -115,7 +118,6 @@ func TestSimplePythonLib(t *testing.T) { python_library { name: "bar", srcs: ["b/e.py"], - bazel_module: { bp2build_available: false }, }`, expectedBazelTargets: []testBazelTarget{ { diff --git a/bp2build/python_test_conversion_test.go b/bp2build/python_test_conversion_test.go index 4ff1fa16d..fa2e48507 100644 --- a/bp2build/python_test_conversion_test.go +++ b/bp2build/python_test_conversion_test.go @@ -15,8 +15,9 @@ package bp2build import ( - "android/soong/python" "testing" + + "android/soong/python" ) func TestPythonTestHostSimple(t *testing.T) { @@ -31,6 +32,7 @@ func TestPythonTestHostSimple(t *testing.T) { "b/e.py": "", "files/data.txt": "", }, + StubbedBuildDefinitions: []string{"bar"}, Blueprint: `python_test_host { name: "foo", main: "a.py", @@ -43,7 +45,6 @@ func TestPythonTestHostSimple(t *testing.T) { python_library_host { name: "bar", srcs: ["b/e.py"], - bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ MakeBazelTarget("py_test", "foo", AttrNameToString{ diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go index 8302ce87b..5ec6bab29 100644 --- a/bp2build/soong_config_module_type_conversion_test.go +++ b/bp2build/soong_config_module_type_conversion_test.go @@ -15,10 +15,11 @@ package bp2build import ( - "android/soong/android" - "android/soong/cc" "fmt" "testing" + + "android/soong/android" + "android/soong/cc" ) func runSoongConfigModuleTypeTest(t *testing.T, tc Bp2buildTestCase) { @@ -364,9 +365,9 @@ custom_cc_library_static { }` otherDeps := ` -cc_library_static { name: "soc_a_dep", bazel_module: { bp2build_available: false } } -cc_library_static { name: "soc_b_dep", bazel_module: { bp2build_available: false } } -cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_available: false } } +cc_library_static { name: "soc_a_dep"} +cc_library_static { name: "soc_b_dep"} +cc_library_static { name: "soc_default_static_dep"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ @@ -377,6 +378,7 @@ cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_ava Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, }, + StubbedBuildDefinitions: []string{"//foo/bar:soc_a_dep", "//foo/bar:soc_b_dep", "//foo/bar:soc_default_static_dep"}, ExpectedBazelTargets: []string{`cc_library_static( name = "foo", copts = select({ @@ -763,9 +765,9 @@ cc_binary { }` otherDeps := ` -cc_library { name: "lib_a", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } +cc_library { name: "lib_a"} +cc_library { name: "lib_b"} +cc_library { name: "lib_default"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ @@ -773,6 +775,7 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } ModuleTypeUnderTest: "cc_binary", ModuleTypeUnderTestFactory: cc.BinaryFactory, Blueprint: bp, + StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"}, Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, }, @@ -852,15 +855,16 @@ cc_binary { }` otherDeps := ` -cc_library { name: "lib_a", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_c", bazel_module: { bp2build_available: false } } +cc_library { name: "lib_a"} +cc_library { name: "lib_b"} +cc_library { name: "lib_c"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ Description: "soong config variables - generates selects for library_linking_strategy", ModuleTypeUnderTest: "cc_binary", ModuleTypeUnderTestFactory: cc.BinaryFactory, + StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_c"}, Blueprint: bp, Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, @@ -949,9 +953,9 @@ cc_binary { }` otherDeps := ` -cc_library { name: "lib_a", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } +cc_library { name: "lib_a"} +cc_library { name: "lib_b"} +cc_library { name: "lib_default"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ @@ -962,6 +966,7 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, }, + StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"}, ExpectedBazelTargets: []string{`cc_binary( name = "library_linking_strategy_sample_binary", deps = select({ @@ -1031,8 +1036,8 @@ cc_binary { }` otherDeps := ` -cc_library { name: "lib_a", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } +cc_library { name: "lib_a"} +cc_library { name: "lib_b"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ @@ -1040,6 +1045,7 @@ cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } ModuleTypeUnderTest: "cc_binary", ModuleTypeUnderTestFactory: cc.BinaryFactory, Blueprint: bp, + StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b"}, Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, }, @@ -1118,9 +1124,9 @@ cc_binary { }` otherDeps := ` -cc_library { name: "lib_a", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_b", bazel_module: { bp2build_available: false } } -cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } +cc_library { name: "lib_a"} +cc_library { name: "lib_b"} +cc_library { name: "lib_default"} ` runSoongConfigModuleTypeTest(t, Bp2buildTestCase{ @@ -1131,6 +1137,7 @@ cc_library { name: "lib_default", bazel_module: { bp2build_available: false } } Filesystem: map[string]string{ "foo/bar/Android.bp": otherDeps, }, + StubbedBuildDefinitions: []string{"//foo/bar:lib_a", "//foo/bar:lib_b", "//foo/bar:lib_default"}, ExpectedBazelTargets: []string{`cc_binary( name = "alphabet_binary", deps = select({ diff --git a/bp2build/testing.go b/bp2build/testing.go index 0e7ef4463..a81070942 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -21,6 +21,8 @@ specific-but-shared functionality among tests in package import ( "fmt" + "path/filepath" + "regexp" "sort" "strings" "testing" @@ -36,6 +38,9 @@ var ( buildDir string ) +var labelRegex = regexp.MustCompile(`^//([^: ]+):([^ ]+)$`) +var simpleModuleNameRegex = regexp.MustCompile(`^[^: /]+$`) + func checkError(t *testing.T, errs []error, expectedErr error) bool { t.Helper() @@ -82,7 +87,19 @@ 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 - Filesystem map[string]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. + AlreadyExistingBuildContents string + + // StubbedBuildDefinitions, if non-empty, adds stub definitions to already-present source + // BUILD files for each bazel label given. The BUILD files with these stub definitions + // are added to the BUILD file given in AlreadyExistingBuildContents. + // Labels may be of the form //pkg/to:target_name (which would be defined in pkg/to/BUILD.bazel) + // or `target_name` (which would be defined in ./BUILD.bazel). + StubbedBuildDefinitions []string + + Filesystem map[string]string // Dir sets the directory which will be compared against the targets in ExpectedBazelTargets. // This should used in conjunction with the Filesystem property to check for targets // generated from a directory that is not the root. @@ -110,12 +127,51 @@ func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) { t.Helper() - dir := "." + if tc.Filesystem == nil { + tc.Filesystem = map[string]string{} + } + checkDir := "." + if tc.Dir != "" { + checkDir = tc.Dir + } + keepExistingBuildDirs := tc.KeepBuildFileForDirs + buildFilesToParse := []string{} + + if len(tc.StubbedBuildDefinitions) > 0 { + for _, buildDef := range tc.StubbedBuildDefinitions { + globalLabelMatch := labelRegex.FindStringSubmatch(buildDef) + var dir, targetName string + if len(globalLabelMatch) > 0 { + dir = globalLabelMatch[1] + targetName = globalLabelMatch[2] + } else { + if !simpleModuleNameRegex.MatchString(buildDef) { + t.Errorf("Stubbed build definition '%s' must be either a simple module name or of global target syntax (//foo/bar:baz).", buildDef) + return + } + dir = "." + targetName = buildDef + } + buildFilePath := filepath.Join(dir, "BUILD") + tc.Filesystem[buildFilePath] += + MakeBazelTarget( + "bp2build_test_stub", + targetName, + AttrNameToString{}) + keepExistingBuildDirs = append(keepExistingBuildDirs, dir) + buildFilesToParse = append(buildFilesToParse, buildFilePath) + } + } + if len(tc.AlreadyExistingBuildContents) > 0 { + buildFilePath := filepath.Join(checkDir, "BUILD") + tc.Filesystem[buildFilePath] += tc.AlreadyExistingBuildContents + keepExistingBuildDirs = append(keepExistingBuildDirs, checkDir) + buildFilesToParse = append(buildFilesToParse, buildFilePath) + } filesystem := make(map[string][]byte) for f, content := range tc.Filesystem { filesystem[f] = []byte(content) } - preparers := []android.FixturePreparer{ extraPreparer, android.FixtureMergeMockFs(filesystem), @@ -123,7 +179,7 @@ func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePre android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory) }), - android.FixtureModifyContext(func(ctx *android.TestContext) { + android.FixtureModifyContextWithMockFs(func(ctx *android.TestContext) { // A default configuration for tests to not have to specify bp2build_available on top level // targets. bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig( @@ -131,7 +187,7 @@ func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePre android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively, }, ) - for _, f := range tc.KeepBuildFileForDirs { + for _, f := range keepExistingBuildDirs { bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{ f: /*recursive=*/ false, }) @@ -141,6 +197,10 @@ func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePre // from cloning modules to their original state after mutators run. This // would lose some data intentionally set by these mutators. ctx.SkipCloneModulesAfterMutators = true + err := ctx.RegisterExistingBazelTargets(".", buildFilesToParse) + if err != nil { + t.Errorf("error parsing build files in test setup: %s", err) + } }), android.FixtureModifyEnv(func(env map[string]string) { if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps { @@ -159,10 +219,6 @@ func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePre return } - checkDir := dir - if tc.Dir != "" { - checkDir = tc.Dir - } expectedTargets := map[string][]string{ checkDir: tc.ExpectedBazelTargets, } @@ -441,7 +497,7 @@ func (m *customModule) dir() *string { return m.props.Dir } -func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *customModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if p := m.props.One_to_many_prop; p != nil && *p { customBp2buildOneToMany(ctx, m) return @@ -461,7 +517,10 @@ func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } } } - productVariableProps := android.ProductVariableProperties(ctx, ctx.Module()) + productVariableProps, errs := android.ProductVariableProperties(ctx, ctx.Module()) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } if props, ok := productVariableProps["String_literal_prop"]; ok { for c, p := range props { if val, ok := p.(*string); ok { @@ -496,7 +555,7 @@ func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } -func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) { +func (m *customModule) createConfigSetting(ctx android.Bp2buildMutatorContext) { csa := bazel.ConfigSettingAttributes{ Flag_values: bazel.StringMapAttribute{ "//build/bazel/rules/my_string_setting": m.Name(), @@ -531,7 +590,7 @@ func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) // A bp2build mutator that uses load statements and creates a 1:M mapping from // module to target. -func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) { +func customBp2buildOneToMany(ctx android.Bp2buildMutatorContext, m *customModule) { baseName := m.Name() attrs := &customBazelModuleAttributes{} @@ -570,11 +629,10 @@ func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) { ctx.RegisterForBazelConversion() } -func SimpleModuleDoNotConvertBp2build(typ, name string) string { +func simpleModule(typ, name string) string { return fmt.Sprintf(` %s { name: "%s", - bazel_module: { bp2build_available: false }, }`, typ, name) } @@ -644,6 +702,7 @@ func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string { return "" } STUB_SUITE_ATTRS := map[string]string{ + "api_surface": "api_surface", "stubs_symbol_file": "symbol_file", "stubs_versions": "versions", "soname": "soname", diff --git a/bpf/bpf.go b/bpf/bpf.go index ee2a5b6bf..ba825cf28 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -311,7 +311,7 @@ type bazelBpfAttributes struct { } // bpf bp2build converter -func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (b *bpf) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if ctx.ModuleType() != "bpf" { return } diff --git a/cc/binary.go b/cc/binary.go index 4606b623e..0722f8110 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -599,7 +599,7 @@ func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.Modul handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo) } -func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes { +func binaryBp2buildAttrs(ctx android.Bp2buildMutatorContext, m *Module) binaryAttributes { baseAttrs := bp2BuildParseBaseProps(ctx, m) binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) @@ -661,7 +661,7 @@ func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAtt return attrs } -func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func binaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { // shared with cc_test binaryAttrs := binaryBp2buildAttrs(ctx, m) diff --git a/cc/bp2build.go b/cc/bp2build.go index 039a3cf74..569f721a5 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -944,7 +944,10 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) nativeCoverage = BoolPtr(false) } - productVariableProps := android.ProductVariableProperties(ctx, ctx.Module()) + productVariableProps, errs := android.ProductVariableProperties(ctx, ctx.Module()) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } (&compilerAttrs).convertProductVariables(ctx, productVariableProps) (&linkerAttrs).convertProductVariables(ctx, productVariableProps) @@ -1000,6 +1003,8 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) if module.afdo != nil && module.afdo.Properties.Afdo { fdoProfileDep := bp2buildFdoProfile(ctx, module) if fdoProfileDep != nil { + // TODO(b/276287371): Only set fdo_profile for android platform + // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/afdo.go;l=105;drc=2dbe160d1af445de32725098570ec594e3944fc5 (&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep) } } @@ -1109,22 +1114,15 @@ func bp2buildFdoProfile( ctx android.Bp2buildMutatorContext, m *Module, ) *bazel.Label { + // TODO(b/267229066): Convert to afdo boolean attribute and let Bazel handles finding + // fdo_profile target from AfdoProfiles product var for _, project := range globalAfdoProfileProjects { - // Ensure handcrafted BUILD file exists in the project - BUILDPath := android.ExistentPathForSource(ctx, project, "BUILD") - if BUILDPath.Valid() { - // We handcraft a BUILD file with fdo_profile targets that use the existing profiles in the project - // This implementation is assuming that every afdo profile in globalAfdoProfileProjects already has - // an associated fdo_profile target declared in the same package. + // Ensure it's a Soong package + bpPath := android.ExistentPathForSource(ctx, project, "Android.bp") + if bpPath.Valid() { // TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`) path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo") if path.Valid() { - // FIXME: Some profiles only exist internally and are not released to AOSP. - // When generated BUILD files are checked in, we'll run into merge conflict. - // The cc_library_shared target in AOSP won't have reference to an fdo_profile target because - // the profile doesn't exist. Internally, the same cc_library_shared target will - // have reference to the fdo_profile. - // For more context, see b/258682955#comment2 fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name() return &bazel.Label{ Label: fdoProfileLabel, @@ -1583,6 +1581,12 @@ func useStubOrImplInApexWithName(ssi stubSelectionInfo) { } } +// hasNdkStubs returns true for libfoo if there exists a libfoo.ndk of type ndk_library +func hasNdkStubs(ctx android.BazelConversionPathContext, c *Module) bool { + mod, exists := ctx.ModuleFromName(c.Name() + ndkLibrarySuffix) + 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) { @@ -1643,6 +1647,29 @@ func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.C useStubOrImplInApexWithName(ssi) } } + + // If the library has an sdk variant, create additional selects to build this variant against the ndk + // The config setting for this variant will be //build/bazel/rules/apex:unbundled_app + if c, ok := ctx.Module().(*Module); ok && c.Properties.Sdk_version != nil { + for _, l := range dynamicLibs.Includes { + dep, _ := ctx.ModuleFromName(l.OriginalModuleName) + label := l // use the implementation by default + if depC, ok := dep.(*Module); ok && hasNdkStubs(ctx, depC) { + // If the dependency has ndk stubs, build against the ndk stubs + // https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=2642-2643;drc=e12d252e22dd8afa654325790d3298a0d67bd9d6;bpv=1;bpt=0 + ver := proptools.String(c.Properties.Sdk_version) + // TODO - b/298085502: Add bp2build support for sdk_version: "minimum" + ndkLibModule, _ := ctx.ModuleFromName(dep.Name() + ndkLibrarySuffix) + label = bazel.Label{ + Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs-" + ver, + } + } + // add the ndk lib label to this axis + existingValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app") + existingValue.Append(bazel.MakeLabelList([]bazel.Label{label})) + dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue)) + } + } } func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { @@ -589,6 +589,7 @@ type Generator interface { GeneratorFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags GeneratorSources(ctx ModuleContext) GeneratedSource GeneratorBuildActions(ctx ModuleContext, flags Flags, deps PathDeps) + GeneratorBp2build(ctx android.Bp2buildMutatorContext) bool } // compiler is the interface for a compiler helper object. Different module decorators may implement @@ -879,16 +880,16 @@ type Module struct { installer installer bazelHandler BazelHandler - features []feature - stl *stl - sanitize *sanitize - coverage *coverage - fuzzer *fuzzer - sabi *sabi - vndkdep *vndkdep - lto *lto - afdo *afdo - pgo *pgo + features []feature + stl *stl + sanitize *sanitize + coverage *coverage + fuzzer *fuzzer + sabi *sabi + vndkdep *vndkdep + lto *lto + afdo *afdo + pgo *pgo orderfile *orderfile library libraryInterface @@ -1104,6 +1105,16 @@ func (c *Module) CcLibraryInterface() bool { return false } +func (c *Module) IsNdkPrebuiltStl() bool { + if c.linker == nil { + return false + } + if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok { + return true + } + return false +} + func (c *Module) RlibStd() bool { panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName())) } @@ -4158,6 +4169,7 @@ const ( headerLibrary testBin // testBinary already declared ndkLibrary + ndkPrebuiltStl ) func (c *Module) typ() moduleType { @@ -4196,12 +4208,24 @@ func (c *Module) typ() moduleType { return sharedLibrary } else if c.isNDKStubLibrary() { return ndkLibrary + } else if c.IsNdkPrebuiltStl() { + return ndkPrebuiltStl } return unknownType } // ConvertWithBp2build converts Module to Bazel for bp2build. -func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (c *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if len(c.generators) > 0 { + allConverted := true + for _, generator := range c.generators { + allConverted = allConverted && generator.GeneratorBp2build(ctx) + } + if allConverted { + return + } + } + prebuilt := c.IsPrebuilt() switch c.typ() { case binary: @@ -4240,6 +4264,10 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } else { sharedOrStaticLibraryBp2Build(ctx, c, false) } + case ndkPrebuiltStl: + ndkPrebuiltStlBp2build(ctx, c) + case ndkLibrary: + ndkLibraryBp2build(ctx, c) default: ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") } diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go index 7fbe71940..05a8f464b 100644 --- a/cc/fdo_profile.go +++ b/cc/fdo_profile.go @@ -16,8 +16,10 @@ package cc import ( "android/soong/android" + "android/soong/bazel" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) func init() { @@ -25,11 +27,12 @@ func init() { } func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterModuleType("fdo_profile", fdoProfileFactory) + ctx.RegisterModuleType("fdo_profile", FdoProfileFactory) } type fdoProfile struct { android.ModuleBase + android.BazelModuleBase properties fdoProfileProperties } @@ -38,6 +41,49 @@ type fdoProfileProperties struct { Profile *string `android:"arch_variant"` } +type bazelFdoProfileAttributes struct { + Profile bazel.StringAttribute +} + +func (fp *fdoProfile) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + var profileAttr bazel.StringAttribute + + archVariantProps := fp.GetArchVariantProperties(ctx, &fdoProfileProperties{}) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*fdoProfileProperties); ok { + if axis.String() == "arch" || axis.String() == "no_config" { + if archProps.Profile != nil { + profileAttr.SetSelectValue(axis, config, archProps.Profile) + } + } + } + } + } + + // Ideally, cc_library_shared's fdo_profile attr can be a select statement so that we + // don't lift the restriction here. However, in cc_library_shared macro, fdo_profile + // is used as a string, we need to temporarily lift the host restriction until we can + // pass use fdo_profile attr with select statement + // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/cc_library_shared.bzl;l=127;drc=cc01bdfd39857eddbab04ef69ab6db22dcb1858a + // TODO(b/276287371): Drop the restriction override after fdo_profile path is handled properly + var noRestriction bazel.BoolAttribute + noRestriction.SetSelectValue(bazel.NoConfigAxis, "", proptools.BoolPtr(true)) + + ctx.CreateBazelTargetModuleWithRestrictions( + bazel.BazelTargetModuleProperties{ + Rule_class: "fdo_profile", + }, + android.CommonAttributes{ + Name: fp.Name(), + }, + &bazelFdoProfileAttributes{ + Profile: profileAttr, + }, + noRestriction, + ) +} + // FdoProfileInfo is provided by FdoProfileProvider type FdoProfileInfo struct { Path android.Path @@ -77,9 +123,10 @@ func fdoProfileMutator(ctx android.BottomUpMutatorContext) { } } -func fdoProfileFactory() android.Module { +func FdoProfileFactory() android.Module { m := &fdoProfile{} m.AddProperties(&m.properties) android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth) + android.InitBazelModule(m) return m } diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go index 55e19f9a9..8428e9420 100644 --- a/cc/generated_cc_library.go +++ b/cc/generated_cc_library.go @@ -28,9 +28,8 @@ func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) and staticAndSharedLibrarySdkMemberType, } - // TODO: Need to be bazelable - // module.bazelable = true - // module.bazelHandler = &ccLibraryBazelHandler{module: module} + module.bazelable = true + module.bazelHandler = &ccLibraryBazelHandler{module: module} module.generators = append(module.generators, callbacks) diff --git a/cc/library.go b/cc/library.go index 2d4d60440..b9dc71b32 100644 --- a/cc/library.go +++ b/cc/library.go @@ -308,7 +308,7 @@ func stripAttrsFromLinkerAttrs(la *linkerAttributes) stripAttributes { } } -func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { +func libraryBp2Build(ctx android.Bp2buildMutatorContext, m *Module) { sharedAttrs := bp2BuildParseSharedProps(ctx, m) staticAttrs := bp2BuildParseStaticProps(ctx, m) baseAttributes := bp2BuildParseBaseProps(ctx, m) @@ -480,7 +480,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes) } -func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) { +func createStubsBazelTargetIfNeeded(ctx android.Bp2buildMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) { if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 { stubSuitesProps := bazel.BazelTargetModuleProperties{ Rule_class: "cc_stub_suite", @@ -494,6 +494,7 @@ func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module Soname: &soname, Source_library_label: proptools.StringPtr(m.GetBazelLabel(ctx, m)), Deps: baseAttributes.deps, + Api_surface: proptools.StringPtr("module-libapi"), } ctx.CreateBazelTargetModule(stubSuitesProps, android.CommonAttributes{Name: m.Name() + "_stub_libs"}, @@ -2885,7 +2886,7 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu return outputFile } -func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes { +func bp2buildParseAbiCheckerProps(ctx android.Bp2buildMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes { lib, ok := module.linker.(*libraryDecorator) if !ok { return bazelCcHeaderAbiCheckerAttributes{} @@ -2908,7 +2909,7 @@ func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Mod return abiCheckerAttrs } -func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) { +func sharedOrStaticLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) { baseAttributes := bp2BuildParseBaseProps(ctx, module) compilerAttrs := baseAttributes.compilerAttributes linkerAttrs := baseAttributes.linkerAttributes @@ -3121,6 +3122,7 @@ type bazelCcStubSuiteAttributes struct { Source_library_label *string Soname *string Deps bazel.LabelListAttribute + Api_surface *string } type bazelCcHeaderAbiCheckerAttributes struct { diff --git a/cc/library_headers.go b/cc/library_headers.go index ce9c4aacf..5eba6ab96 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -129,7 +129,7 @@ type bazelCcLibraryHeadersAttributes struct { sdkAttributes } -func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func libraryHeadersBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { baseAttributes := bp2BuildParseBaseProps(ctx, module) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes) linkerAttrs := baseAttributes.linkerAttributes @@ -153,8 +153,13 @@ func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module) + name := module.Name() + if module.IsPrebuilt() { + name = android.RemoveOptionalPrebuiltPrefix(name) + } + ctx.CreateBazelTargetModule(props, android.CommonAttributes{ - Name: module.Name(), + Name: name, Tags: tags, }, attrs) } diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index d0ae4a56d..da5db1c19 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -21,6 +21,7 @@ import ( "github.com/google/blueprint" "android/soong/android" + "android/soong/bazel" ) var ( @@ -79,9 +80,11 @@ type headerProperties struct { type headerModule struct { android.ModuleBase + android.BazelModuleBase properties headerProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -125,8 +128,8 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License)) - srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs) - for _, header := range srcFiles { + m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs) + for _, header := range m.srcPaths { installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To)) installedPath := ctx.InstallFile(installDir, header.Base(), header) @@ -144,6 +147,29 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } +type bazelNdkHeadersAttributes struct { + Strip_import_prefix *string + Import_prefix *string + Hdrs bazel.LabelListAttribute +} + +func (h *headerModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "ndk_headers", + Bzl_load_location: "//build/bazel/rules/cc:ndk_headers.bzl", + } + attrs := &bazelNdkHeadersAttributes{ + Strip_import_prefix: h.properties.From, + Import_prefix: h.properties.To, + Hdrs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, h.properties.Srcs, h.properties.Exclude_srcs)), + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{Name: h.Name()}, + attrs, + ) +} + // ndk_headers installs the sets of ndk headers defined in the srcs property // to the sysroot base + "usr/include" + to directory + directory component. // ndk_headers requires the license file to be specified. Example: @@ -154,10 +180,11 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // to = "bar" // header = "include/foo/woodly/doodly.h" // output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h" -func ndkHeadersFactory() android.Module { +func NdkHeadersFactory() android.Module { module := &headerModule{} module.AddProperties(&module.properties) android.InitAndroidModule(module) + android.InitBazelModule(module) return module } @@ -193,6 +220,7 @@ type versionedHeaderModule struct { properties versionedHeaderProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -211,9 +239,9 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From)) toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To)) - srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil) + m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil) var installPaths []android.WritablePath - for _, header := range srcFiles { + for _, header := range m.srcPaths { installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To)) installPath := installDir.Join(ctx, header.Base()) installPaths = append(installPaths, installPath) @@ -224,11 +252,11 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From)) } - processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths) + processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths) } func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path, - srcFiles android.Paths, installPaths []android.WritablePath) android.Path { + srcPaths android.Paths, installPaths []android.WritablePath) android.Path { // The versioner depends on a dependencies directory to simplify determining include paths // when parsing headers. This directory contains architecture specific directories as well // as a common directory, each of which contains symlinks to the actually directories to @@ -253,7 +281,7 @@ func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir andro Rule: versionBionicHeaders, Description: "versioner preprocess " + srcDir.Rel(), Output: timestampFile, - Implicits: append(srcFiles, depsGlob...), + Implicits: append(srcPaths, depsGlob...), ImplicitOutputs: installPaths, Args: map[string]string{ "depsPath": depsPath.String(), @@ -317,6 +345,7 @@ type preprocessedHeadersModule struct { properties preprocessedHeadersProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -329,9 +358,9 @@ func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.Modu preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor)) m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License)) - srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs) + m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs) installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To)) - for _, src := range srcFiles { + for _, src := range m.srcPaths { installPath := installDir.Join(ctx, src.Base()) m.installPaths = append(m.installPaths, installPath) diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 9281aebb5..b3bb2da15 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -43,11 +43,17 @@ var ( CommandDeps: []string{"$ndkStubGenerator"}, }, "arch", "apiLevel", "apiMap", "flags") + // $headersList should include paths to public headers. All types + // that are defined outside of public headers will be excluded from + // ABI monitoring. + // + // STG tool doesn't access content of files listed in $headersList, + // so there is no need to add them to dependencies. stg = pctx.AndroidStaticRule("stg", blueprint.RuleParams{ - Command: "$stg -S :$symbolList --elf $in -o $out", + Command: "$stg -S :$symbolList --file-filter :$headersList --elf $in -o $out", CommandDeps: []string{"$stg"}, - }, "symbolList") + }, "symbolList", "headersList") stgdiff = pctx.AndroidStaticRule("stgdiff", blueprint.RuleParams{ @@ -347,14 +353,19 @@ func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) { this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx, this.apiLevel.String(), ctx.Arch().ArchType.String(), this.libraryName(ctx), "abi.stg") + headersList := getNdkABIHeadersFile(ctx) ctx.Build(pctx, android.BuildParams{ Rule: stg, Description: fmt.Sprintf("stg %s", implementationLibrary), Input: implementationLibrary, - Implicit: symbolList, - Output: this.abiDumpPath, + Implicits: []android.Path{ + symbolList, + headersList, + }, + Output: this.abiDumpPath, Args: map[string]string{ - "symbolList": symbolList.String(), + "symbolList": symbolList.String(), + "headersList": headersList.String(), }, }) } @@ -404,7 +415,7 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { // Also ensure that the ABI of the next API level (if there is one) matches // this API level. *New* ABI is allowed, but any changes to APIs that exist // in this API level are disallowed. - if !this.apiLevel.IsCurrent() { + if !this.apiLevel.IsCurrent() && prebuiltAbiDump.Valid() { nextApiLevel := findNextApiLevel(ctx, this.apiLevel) if nextApiLevel == nil { panic(fmt.Errorf("could not determine which API level follows "+ @@ -424,10 +435,12 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { } else { ctx.Build(pctx, android.BuildParams{ Rule: stgdiff, - Description: fmt.Sprintf("abidiff %s %s", this.abiDumpPath, - nextAbiDump), + Description: fmt.Sprintf( + "Comparing ABI to the next API level %s %s", + prebuiltAbiDump, nextAbiDump), Output: nextAbiDiffPath, - Inputs: android.Paths{this.abiDumpPath, nextAbiDump.Path()}, + Inputs: android.Paths{ + prebuiltAbiDump.Path(), nextAbiDump.Path()}, Args: map[string]string{ "args": "--format=small --ignore=interface_addition", }, @@ -570,3 +583,40 @@ func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel. } return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix) } + +func ndkLibraryBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + ndk, _ := c.linker.(*stubDecorator) + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_stub_suite", + Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl", + } + sourceLibraryName := strings.TrimSuffix(c.Name(), ".ndk") + fromApiLevel, err := android.ApiLevelFromUser(ctx, proptools.String(ndk.properties.First_version)) + if err != nil { + ctx.PropertyErrorf("first_version", "error converting first_version %v", proptools.String(ndk.properties.First_version)) + } + symbolFileLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(ndk.properties.Symbol_file)) + attrs := &bazelCcStubSuiteAttributes{ + // TODO - b/300504837 Add ndk headers + Symbol_file: proptools.StringPtr(symbolFileLabel.Label), + Soname: proptools.StringPtr(sourceLibraryName + ".so"), + Api_surface: proptools.StringPtr(android.PublicApi.String()), + } + if sourceLibrary, exists := ctx.ModuleFromName(sourceLibraryName); exists { + // the source library might not exist in minimal/unbuildable branches like kernel-build-tools. + // check for its existence + attrs.Source_library_label = proptools.StringPtr(c.GetBazelLabel(ctx, sourceLibrary)) + } + if ctx.Config().RawPlatformSdkVersion() != nil { + // This is a hack to populate `versions` only on branches that set a platform_sdk_version + // This prevents errors on branches such as kernel-build-tools + // This hack is acceptable since we are not required to support NDK Bazel builds on those branches + attrs.Versions = bazel.MakeStringListAttribute(ndkLibraryVersions(ctx, fromApiLevel)) + } + + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{Name: c.Name() + "_stub_libs"}, + attrs, + ) +} diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go index d3a0a002e..c3e65106a 100644 --- a/cc/ndk_prebuilt.go +++ b/cc/ndk_prebuilt.go @@ -15,9 +15,11 @@ package cc import ( + "path/filepath" "strings" "android/soong/android" + "android/soong/bazel" ) func init() { @@ -64,6 +66,7 @@ func NdkPrebuiltSharedStlFactory() android.Module { module.Properties.Sdk_version = StringPtr("minimum") module.Properties.AlwaysSdk = true module.stl.Properties.Stl = StringPtr("none") + module.bazelable = true return module.Init() } @@ -84,12 +87,16 @@ func NdkPrebuiltStaticStlFactory() android.Module { module.Properties.AlwaysSdk = true module.Properties.Sdk_version = StringPtr("current") module.stl.Properties.Stl = StringPtr("none") + module.bazelable = true return module.Init() } +const ( + libDir = "current/sources/cxx-stl/llvm-libc++/libs" +) + func getNdkStlLibDir(ctx android.ModuleContext) android.SourcePath { - libDir := "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs" - return android.PathForSource(ctx, libDir).Join(ctx, ctx.Arch().Abi[0]) + return android.PathForSource(ctx, ctx.ModuleDir(), libDir).Join(ctx, ctx.Arch().Abi[0]) } func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, @@ -128,3 +135,81 @@ func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, return lib } + +var ( + archToAbiDirMap = map[string]string{ + "android_arm": "armeabi-v7a", + "android_arm64": "arm64-v8a", + "android_riscv64": "riscv64", + "android_x86": "x86", + "android_x86_64": "x86_64", + } +) + +// stlSrcBp2build returns a bazel label for the checked-in .so/.a file +// It contains a select statement for each ABI +func stlSrcBp2build(ctx android.Bp2buildMutatorContext, c *Module) bazel.LabelAttribute { + libName := strings.TrimPrefix(c.Name(), "ndk_") + libExt := ".so" // TODO - b/201079053: Support windows + if ctx.ModuleType() == "ndk_prebuilt_static_stl" { + libExt = ".a" + } + src := bazel.LabelAttribute{} + for arch, abiDir := range archToAbiDirMap { + srcPath := filepath.Join(libDir, abiDir, libName+libExt) + src.SetSelectValue( + bazel.OsArchConfigurationAxis, + arch, + android.BazelLabelForModuleSrcSingle(ctx, srcPath), + ) + } + return src +} + +// stlIncludesBp2build returns the includes exported by the STL +func stlIncludesBp2build(c *Module) bazel.StringListAttribute { + linker, _ := c.linker.(*ndkPrebuiltStlLinker) + includeDirs := append( + []string{}, + linker.libraryDecorator.flagExporter.Properties.Export_include_dirs..., + ) + includeDirs = append( + includeDirs, + linker.libraryDecorator.flagExporter.Properties.Export_system_include_dirs..., + ) + return bazel.MakeStringListAttribute(android.FirstUniqueStrings(includeDirs)) +} + +func ndkPrebuiltStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + if ctx.ModuleType() == "ndk_prebuilt_static_stl" { + ndkPrebuiltStaticStlBp2build(ctx, c) + } else { + ndkPrebuiltSharedStlBp2build(ctx, c) + } +} + +func ndkPrebuiltStaticStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_prebuilt_library_static", + Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", + } + attrs := &bazelPrebuiltLibraryStaticAttributes{ + Static_library: stlSrcBp2build(ctx, c), + Export_system_includes: stlIncludesBp2build(c), // The exports are always as system + } + // TODO: min_sdk_version + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs) +} + +func ndkPrebuiltSharedStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_prebuilt_library_shared", + Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl", + } + attrs := &bazelPrebuiltLibrarySharedAttributes{ + Shared_library: stlSrcBp2build(ctx, c), + Export_system_includes: stlIncludesBp2build(c), // The exports are always as system + } + // TODO: min_sdk_version + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs) +} diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index feb388037..54a2ee267 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -54,6 +54,7 @@ package cc import ( "android/soong/android" + "strings" ) func init() { @@ -61,7 +62,7 @@ func init() { } func RegisterNdkModuleTypes(ctx android.RegistrationContext) { - ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory) + ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory) ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) @@ -96,15 +97,56 @@ func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath { return android.PathForOutput(ctx, "ndk.timestamp") } +// The list of all NDK headers as they are located in the repo. +// Used for ABI monitoring to track only structures defined in NDK headers. +func getNdkABIHeadersFile(ctx android.PathContext) android.WritablePath { + return android.PathForOutput(ctx, "ndk_abi_headers.txt") +} + func NdkSingleton() android.Singleton { return &ndkSingleton{} } +// Collect all NDK exported headers paths into a file that is used to +// detect public types that should be ABI monitored. +// +// Assume that we have the following code in exported header: +// +// typedef struct Context Context; +// typedef struct Output { +// ... +// } Output; +// void DoSomething(Context* ctx, Output* output); +// +// If none of public headers exported to end-users contain definition of +// "struct Context", then "struct Context" layout and members shouldn't be +// monitored. However we use DWARF information from a real library, which +// may have access to the definition of "string Context" from +// implementation headers, and it will leak to ABI. +// +// STG tool doesn't access source and header files, only DWARF information +// from compiled library. And the DWARF contains file name where a type is +// defined. So we need a rule to build a list of paths to public headers, +// so STG can distinguish private types from public and do not monitor +// private types that are not accessible to library users. +func writeNdkAbiSrcFilter(ctx android.BuilderContext, + headerSrcPaths android.Paths, outputFile android.WritablePath) { + var filterBuilder strings.Builder + filterBuilder.WriteString("[decl_file_allowlist]\n") + for _, headerSrcPath := range headerSrcPaths { + filterBuilder.WriteString(headerSrcPath.String()) + filterBuilder.WriteString("\n") + } + + android.WriteFileRule(ctx, outputFile, filterBuilder.String()) +} + type ndkSingleton struct{} func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { var staticLibInstallPaths android.Paths - var headerPaths android.Paths + var headerSrcPaths android.Paths + var headerInstallPaths android.Paths var installPaths android.Paths var licensePaths android.Paths ctx.VisitAllModules(func(module android.Module) { @@ -113,19 +155,22 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { } if m, ok := module.(*headerModule); ok { - headerPaths = append(headerPaths, m.installPaths...) + headerSrcPaths = append(headerSrcPaths, m.srcPaths...) + headerInstallPaths = append(headerInstallPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } if m, ok := module.(*versionedHeaderModule); ok { - headerPaths = append(headerPaths, m.installPaths...) + headerSrcPaths = append(headerSrcPaths, m.srcPaths...) + headerInstallPaths = append(headerInstallPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } if m, ok := module.(*preprocessedHeadersModule); ok { - headerPaths = append(headerPaths, m.installPaths...) + headerSrcPaths = append(headerSrcPaths, m.srcPaths...) + headerInstallPaths = append(headerInstallPaths, m.installPaths...) installPaths = append(installPaths, m.installPaths...) licensePaths = append(licensePaths, m.licensePath) } @@ -175,9 +220,11 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { ctx.Build(pctx, android.BuildParams{ Rule: android.Touch, Output: getNdkHeadersTimestampFile(ctx), - Implicits: headerPaths, + Implicits: headerInstallPaths, }) + writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx)) + fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx)) // There's a phony "ndk" rule defined in core/main.mk that depends on this. diff --git a/cc/object.go b/cc/object.go index ca1484538..a3000e06e 100644 --- a/cc/object.go +++ b/cc/object.go @@ -156,7 +156,7 @@ type bazelObjectAttributes struct { // objectBp2Build is the bp2build converter from cc_object modules to the // Bazel equivalent target, plus any necessary include deps for the cc_object. -func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) { +func objectBp2Build(ctx android.Bp2buildMutatorContext, m *Module) { if m.compiler == nil { // a cc_object must have access to the compiler decorator for its props. ctx.ModuleErrorf("compiler must not be nil for a cc_object module") diff --git a/cc/prebuilt.go b/cc/prebuilt.go index a4ca59050..b4819b013 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -363,12 +363,12 @@ type bazelPrebuiltLibraryStaticAttributes struct { // all variants // // In all cases, cc_prebuilt_library_static target names will be appended with "_bp2build_cc_library_static". -func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltLibraryStaticBp2Build(ctx, module, true) prebuiltLibrarySharedBp2Build(ctx, module) } -func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module, fullBuild bool) { +func prebuiltLibraryStaticBp2Build(ctx android.Bp2buildMutatorContext, module *Module, fullBuild bool) { prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, true) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil) @@ -404,7 +404,7 @@ type bazelPrebuiltLibrarySharedAttributes struct { Export_system_includes bazel.StringListAttribute } -func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltLibrarySharedBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, false) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil) @@ -637,7 +637,7 @@ type bazelPrebuiltObjectAttributes struct { Src bazel.LabelAttribute } -func prebuiltObjectBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltObjectBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := bp2BuildParsePrebuiltObjectProps(ctx, module) attrs := &bazelPrebuiltObjectAttributes{ @@ -797,7 +797,7 @@ type bazelPrebuiltBinaryAttributes struct { Strip stripAttributes } -func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltBinaryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module) var la linkerAttributes diff --git a/cc/sanitize.go b/cc/sanitize.go index 0abdafc32..9ceb1c8a0 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -679,12 +679,6 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Integer_overflow = nil } - // TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work. - if ctx.Arch().ArchType == android.Riscv64 { - s.Cfi = nil - s.Diag.Cfi = nil - } - // Disable CFI for musl if ctx.toolchain().Musl() { s.Cfi = nil diff --git a/cc/test.go b/cc/test.go index ae621287c..7a6cf1b4e 100644 --- a/cc/test.go +++ b/cc/test.go @@ -700,7 +700,7 @@ type testBinaryAttributes struct { // TODO(b/244432609): handle `isolated` property. // TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not // default to bazel. (see linkerInit function) -func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func testBinaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { var testBinaryAttrs testBinaryAttributes testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m) diff --git a/cc/testing.go b/cc/testing.go index d1632aaa6..36bc261e0 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -35,13 +35,14 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { multitree.RegisterApiImportsModule(ctx) + ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool) ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory) ctx.RegisterModuleType("cc_object", ObjectFactory) ctx.RegisterModuleType("cc_genrule", GenRuleFactory) ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory) ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory) ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) - ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory) + ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory) } func GatherRequiredDepsForTest(oses ...android.OsType) string { @@ -67,6 +68,26 @@ 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, @@ -558,7 +579,7 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( // This includes files that are needed by all, or at least most, instances of a cc module type. android.MockFS{ // Needed for ndk_prebuilt_(shared|static)_stl. - "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs": nil, + "defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil, }.AddToFixture(), ) @@ -568,6 +589,12 @@ 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, @@ -671,7 +698,7 @@ var PrepareForTestWithHostMusl = android.GroupFixturePreparers( // PrepareForTestWithFdoProfile registers module types to test with fdo_profile var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory) - ctx.RegisterModuleType("fdo_profile", fdoProfileFactory) + ctx.RegisterModuleType("fdo_profile", FdoProfileFactory) }) // TestConfig is the legacy way of creating a test Config for testing cc modules. diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go index fc56dd526..3364f503f 100644 --- a/cmd/sbox/sbox.go +++ b/cmd/sbox/sbox.go @@ -119,6 +119,9 @@ func run() error { } manifest, err := readManifest(manifestFile) + if err != nil { + return err + } if len(manifest.Commands) == 0 { return fmt.Errorf("at least one commands entry is required in %q", manifestFile) diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 626f076a3..d20847bb2 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -21,7 +21,6 @@ import ( "fmt" "os" "path/filepath" - "regexp" "strings" "time" @@ -617,43 +616,6 @@ func excludedFromSymlinkForest(ctx *android.Context, verbose bool) []string { return excluded } -// buildTargetsByPackage parses Bazel BUILD.bazel and BUILD files under -// the workspace, and returns a map containing names of Bazel targets defined in -// these BUILD files. -// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist. -func buildTargetsByPackage(ctx *android.Context) map[string][]string { - existingBazelFiles, err := getExistingBazelRelatedFiles(topDir) - maybeQuit(err, "Error determining existing Bazel-related files") - - result := map[string][]string{} - - // Search for instances of `name = "$NAME"` (with arbitrary spacing). - targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`) - - for _, path := range existingBazelFiles { - if !ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) { - continue - } - fullPath := shared.JoinPath(topDir, path) - sourceDir := filepath.Dir(path) - fileInfo, err := os.Stat(fullPath) - maybeQuit(err, "Error accessing Bazel file '%s'", fullPath) - - if !fileInfo.IsDir() && - (fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") { - // Process this BUILD file. - buildFileContent, err := os.ReadFile(fullPath) - maybeQuit(err, "Error reading Bazel file '%s'", fullPath) - - matches := targetNameRegex.FindAllStringSubmatch(string(buildFileContent), -1) - for _, match := range matches { - result[sourceDir] = append(result[sourceDir], match[1]) - } - } - } - return result -} - // Run Soong in the bp2build mode. This creates a standalone context that registers // an alternate pipeline of mutators and singletons specifically for generating // Bazel BUILD files instead of Ninja files. @@ -662,7 +624,11 @@ func runBp2Build(ctx *android.Context, extraNinjaDeps []string, metricsDir strin ctx.EventHandler.Do("bp2build", func() { ctx.EventHandler.Do("read_build", func() { - ctx.Config().SetBazelBuildFileTargets(buildTargetsByPackage(ctx)) + existingBazelFiles, err := getExistingBazelRelatedFiles(topDir) + maybeQuit(err, "Error determining existing Bazel-related files") + + err = ctx.RegisterExistingBazelTargets(topDir, existingBazelFiles) + maybeQuit(err, "Error parsing existing Bazel-related files") }) // Propagate "allow misssing dependencies" bit. This is normally set in diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index 4097e8a3f..3b8f4f5a4 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -289,10 +289,7 @@ func logAndSymlinkSetup(buildCtx build.Context, config build.Config) { } } - // Fix up the source tree due to a repo bug where it doesn't remove - // linkfiles that have been removed - fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp") - fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk") + removeBadTargetRename(buildCtx, config) // Create a source finder. f := build.NewSourceFinder(buildCtx, config) @@ -300,16 +297,26 @@ func logAndSymlinkSetup(buildCtx build.Context, config build.Config) { build.FindSources(buildCtx, config, f) } -func fixBadDanglingLink(ctx build.Context, name string) { - _, err := os.Lstat(name) +func removeBadTargetRename(ctx build.Context, config build.Config) { + log := ctx.ContextImpl.Logger + // find bad paths + m, err := filepath.Glob(filepath.Join(config.OutDir(), "bazel", "output", "execroot", "__main__", "bazel-out", "mixed_builds_product-*", "bin", "tools", "metalava", "metalava")) if err != nil { - return + log.Fatalf("Glob for invalid file failed %s", err) } - _, err = os.Stat(name) - if os.IsNotExist(err) { - err = os.Remove(name) + for _, f := range m { + info, err := os.Stat(f) if err != nil { - ctx.Fatalf("Failed to remove dangling link %q: %v", name, err) + log.Fatalf("Stat of invalid file %q failed %s", f, err) + } + // if it's a directory, leave it, but remove the files + if !info.IsDir() { + err = os.Remove(f) + if err != nil { + log.Fatalf("Remove of invalid file %q failed %s", f, err) + } else { + log.Verbosef("Removed %q", f) + } } } } diff --git a/compliance/OWNERS b/compliance/OWNERS deleted file mode 100644 index f52e201c1..000000000 --- a/compliance/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -# OSEP Build -bbadour@google.com -kanouche@google.com -napier@google.com - -# Open Source Compliance Tools -rtp@google.com -austinyuan@google.com diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index c48bafa26..94235319a 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -712,7 +712,7 @@ type bazelPrebuiltFileAttributes struct { // Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion // of prebuilt_* modules. bazelPrebuiltFileAttributes has the common attributes // used by both prebuilt_etc_xml and other prebuilt_* moodules -func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) (*bazelPrebuiltFileAttributes, bool) { +func (module *PrebuiltEtc) Bp2buildHelper(ctx android.Bp2buildMutatorContext) (*bazelPrebuiltFileAttributes, bool) { var src bazel.LabelAttribute for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) { for config, p := range configToProps { @@ -730,8 +730,11 @@ func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) (*b src.SetSelectValue(axis, config, label) } } - - for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) { + productVarProperties, errs := android.ProductVariableProperties(ctx, ctx.Module()) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } + for propName, productConfigProps := range productVarProperties { for configProp, propVal := range productConfigProps { if propName == "Src" { props, ok := propVal.(*string) @@ -791,7 +794,7 @@ func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) (*b // ConvertWithBp2build performs bp2build conversion of PrebuiltEtc // prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc, // which we treat as *PrebuiltFile* -func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { var dir = module.installDirBase // prebuilt_file supports only `etc` or `usr/share` if !(dir == "etc" || dir == "usr/share") { diff --git a/genrule/genrule.go b/genrule/genrule.go index d1c2f1378..01cac5b1f 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -920,7 +920,7 @@ type BazelGenruleAttributes struct { } // ConvertWithBp2build converts a Soong module -> Bazel target. -func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { // Bazel only has the "tools" attribute. tools_prop := android.BazelLabelForModuleDeps(ctx, m.properties.Tools) tool_files_prop := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files) @@ -993,7 +993,10 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { var cmdProp bazel.StringAttribute cmdProp.SetValue(replaceVariables(proptools.String(m.properties.Cmd))) - allProductVariableProps := android.ProductVariableProperties(ctx, m) + allProductVariableProps, errs := android.ProductVariableProperties(ctx, m) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } if productVariableProps, ok := allProductVariableProps["Cmd"]; ok { for productVariable, value := range productVariableProps { var cmd string diff --git a/java/aar.go b/java/aar.go index 021619603..f28d97149 100644 --- a/java/aar.go +++ b/java/aar.go @@ -993,7 +993,7 @@ var extractJNI = pctx.AndroidStaticRule("extractJNI", `jni_files=$$(find $outDir/jni -type f) && ` + // print error message if there are no JNI libs for this arch `[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` + - `${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` + + `${config.SoongZipCmd} -o $out -L 0 -P 'lib/${archString}' ` + `-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`, CommandDeps: []string{"${config.SoongZipCmd}"}, }, @@ -1239,7 +1239,7 @@ type bazelAndroidLibraryImport struct { Sdk_version bazel.StringAttribute } -func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) (*bazelAapt, bool) { +func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.Bp2buildMutatorContext) (*bazelAapt, bool) { manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml") resourceFiles := bazel.LabelList{ @@ -1275,7 +1275,7 @@ func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) ( }, true } -func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (a *AARImport) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { 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. @@ -1328,7 +1328,7 @@ func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperti } } -func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (a *AndroidLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { commonAttrs, bp2buildInfo, supported := a.convertLibraryAttrsBp2Build(ctx) if !supported { return @@ -1340,7 +1340,10 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) 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.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") + ctx.MarkBp2buildUnconvertible( + bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, + "Module has direct dependencies but no sources. Bazel will not allow this.") + return } name := a.Name() props := AndroidLibraryBazelTargetModuleProperties() diff --git a/java/app.go b/java/app.go index 7ee0e3857..dabc3192e 100755 --- a/java/app.go +++ b/java/app.go @@ -31,6 +31,7 @@ import ( "android/soong/dexpreopt" "android/soong/genrule" "android/soong/tradefed" + "android/soong/ui/metrics/bp2build_metrics_proto" ) func init() { @@ -1115,6 +1116,8 @@ type AndroidTest struct { testConfig android.Path extraTestConfigs android.Paths data android.Paths + + android.BazelModuleBase } func (a *AndroidTest) InstallInTestcases() bool { @@ -1232,6 +1235,8 @@ func AndroidTestFactory() android.Module { android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) android.InitOverridableModule(module, &module.overridableAppProperties.Overrides) + + android.InitBazelModule(module) return module } @@ -1253,6 +1258,8 @@ type AndroidTestHelperApp struct { AndroidApp appTestHelperAppProperties appTestHelperAppProperties + + android.BazelModuleBase } func (a *AndroidTestHelperApp) InstallInTestcases() bool { @@ -1284,6 +1291,7 @@ func AndroidTestHelperAppFactory() android.Module { android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) android.InitApexModule(module) + android.InitBazelModule(module) return module } @@ -1590,11 +1598,11 @@ type bazelAndroidAppCertificateAttributes struct { Certificate string } -func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { androidAppCertificateBp2Build(ctx, m) } -func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) { +func androidAppCertificateBp2Build(ctx android.Bp2buildMutatorContext, module *AndroidAppCertificate) { var certificate string if module.properties.Certificate != nil { certificate = *module.properties.Certificate @@ -1614,7 +1622,6 @@ func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *An type manifestValueAttribute struct { MinSdkVersion *string - MaxSdkVersion *string TargetSdkVersion *string } @@ -1628,38 +1635,34 @@ type bazelAndroidAppAttributes struct { Manifest_values *manifestValueAttribute Optimize *bool Proguard_specs bazel.LabelListAttribute + Updatable *bool } -// ConvertWithBp2build is used to convert android_app to Bazel. -func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func convertWithBp2build(ctx android.Bp2buildMutatorContext, a *AndroidApp) (bool, android.CommonAttributes, *bazelAndroidAppAttributes) { aapt, supported := a.convertAaptAttrsWithBp2Build(ctx) if !supported { - return + return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} } - certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate) - - manifestValues := &manifestValueAttribute{} - // TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build - // MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set - minSdkVersion := a.MinSdkVersion(ctx) - if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() { - if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil { - manifestValues.MinSdkVersion = &minSdkStr - } + if a.appProperties.Jni_uses_platform_apis != nil { + ctx.MarkBp2buildUnconvertible( + bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, + "TODO - b/299360988: Add bp2build support for jni_uses_platform_apis", + ) + return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} } - - maxSdkVersion := a.MaxSdkVersion(ctx) - if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() { - if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil { - manifestValues.MaxSdkVersion = &maxSdkStr - } + if a.appProperties.Jni_uses_sdk_apis != nil { + ctx.MarkBp2buildUnconvertible( + bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, + "TODO - b/299360988: Add bp2build support for jni_uses_sdk_apis", + ) + return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} } - targetSdkVersion := a.TargetSdkVersion(ctx) - if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() { - if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil { - manifestValues.TargetSdkVersion = &targetSdkStr - } + certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate) + + manifestValues := &manifestValueAttribute{ + MinSdkVersion: a.deviceProperties.Min_sdk_version, + TargetSdkVersion: a.deviceProperties.Target_sdk_version, } appAttrs := &bazelAndroidAppAttributes{ @@ -1668,6 +1671,7 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { Certificate: certificate, Certificate_name: certificateName, Manifest_values: manifestValues, + Updatable: a.appProperties.Updatable, } if !BoolDefault(a.dexProperties.Optimize.Enabled, true) { @@ -1706,17 +1710,26 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx) if !supported { - return + return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{} } depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps deps.Append(depLabels.StaticDeps) - props := bazel.BazelTargetModuleProperties{ - Rule_class: "android_binary", - Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", + var jniDeps bazel.LabelListAttribute + archVariantProps := a.GetArchVariantProperties(ctx, &appProperties{}) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*appProperties); ok { + archJniLibs := android.BazelLabelForModuleDeps( + ctx, + android.LastUniqueStrings(android.CopyOf(archProps.Jni_libs))) + jniDeps.SetSelectValue(axis, config, archJniLibs) + } + } } + deps.Append(jniDeps) if !bp2BuildInfo.hasKotlin { appAttrs.javaCommonAttributes = commonAttrs @@ -1743,10 +1756,55 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } } - ctx.CreateBazelTargetModule( - props, - android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, - appAttrs, - ) + return true, android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)}, appAttrs +} + +// 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", + } + ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs) + } + +} + +// ConvertWithBp2build is used to convert android_test to Bazel. +func (at *AndroidTest) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, &at.AndroidApp); ok { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "android_test", + Bzl_load_location: "//build/bazel/rules/android:android_test.bzl", + } + + ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs) + } + +} + +func (atha *AndroidTestHelperApp) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if ok, commonAttrs, appAttrs := convertWithBp2build(ctx, &atha.AndroidApp); ok { + // 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, + // 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) + + props := bazel.BazelTargetModuleProperties{ + Rule_class: "android_binary", + Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", + } + + ctx.CreateBazelTargetModule(props, commonAttrs, appAttrs) + } } diff --git a/java/base.go b/java/base.go index 8f483989e..a110aff56 100644 --- a/java/base.go +++ b/java/base.go @@ -1077,8 +1077,8 @@ func (j *Module) AddJSONData(d *map[string]interface{}) { } -func (module *Module) addGeneratedSrcJars(path android.Path) { - module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path) +func (j *Module) addGeneratedSrcJars(path android.Path) { + j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path) } func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) { @@ -2359,7 +2359,7 @@ type ModuleWithStem interface { var _ ModuleWithStem = (*Module)(nil) -func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (j *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { switch ctx.ModuleType() { case "java_library", "java_library_host", "java_library_static", "tradefed_java_library_host": if lib, ok := ctx.Module().(*Library); ok { diff --git a/java/device_host_converter.go b/java/device_host_converter.go index 5460dc993..c5ba245ea 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -198,7 +198,7 @@ type bazelDeviceHostConverterAttributes struct { Exports bazel.LabelListAttribute } -func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "java_host_for_device", diff --git a/java/dex.go b/java/dex.go index 5b8cf3dfb..c1d51c7bf 100644 --- a/java/dex.go +++ b/java/dex.go @@ -315,15 +315,14 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl if BoolDefault(opt.Proguard_compatibility, true) { r8Flags = append(r8Flags, "--force-proguard-compatibility") - } else { + } + + if Bool(opt.Optimize) || Bool(opt.Obfuscate) { // TODO(b/213833843): Allow configuration of the prefix via a build variable. var sourceFilePrefix = "go/retraceme " var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\"" - // TODO(b/200967150): Also tag the source file in compat builds. - if Bool(opt.Optimize) || Bool(opt.Obfuscate) { - r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH") - r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate) - } + r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH") + r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate) } // TODO(ccross): Don't shrink app instrumentation tests by default. diff --git a/java/droiddoc.go b/java/droiddoc.go index 3ba306554..d5547d05c 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -22,6 +22,7 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bazel" "android/soong/java/config" ) @@ -844,6 +845,7 @@ type ExportedDroiddocDirProperties struct { type ExportedDroiddocDir struct { android.ModuleBase + android.BazelModuleBase properties ExportedDroiddocDirProperties @@ -856,6 +858,7 @@ func ExportedDroiddocDirFactory() android.Module { module := &ExportedDroiddocDir{} module.AddProperties(&module.properties) android.InitAndroidModule(module) + android.InitBazelModule(module) return module } @@ -867,6 +870,28 @@ func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleCont d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")}) } +// ConvertWithBp2build implements android.BazelModule. +func (d *ExportedDroiddocDir) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + props := bazel.BazelTargetModuleProperties{ + // Use the native py_library rule. + Rule_class: "droiddoc_exported_dir", + Bzl_load_location: "//build/bazel/rules/droiddoc:droiddoc_exported_dir.bzl", + } + + type BazelAttrs struct { + Dir *string + Srcs bazel.LabelListAttribute + } + + attrs := &BazelAttrs{ + Dir: proptools.StringPtr(*d.properties.Path), + Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, []string{filepath.Join(*d.properties.Path, "**/*")})), + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: d.Name()}, attrs) + +} + // Defaults type DocDefaults struct { android.ModuleBase diff --git a/java/java.go b/java/java.go index 270f45615..d5aeb7cb2 100644 --- a/java/java.go +++ b/java/java.go @@ -64,6 +64,7 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("dex_import", DexImportFactory) ctx.RegisterModuleType("java_api_library", ApiLibraryFactory) ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory) + ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory) // This mutator registers dependencies on dex2oat for modules that should be // dexpreopted. This is done late when the final variants have been @@ -1623,7 +1624,8 @@ func ApiContributionFactory() android.Module { } type JavaApiImportInfo struct { - ApiFile android.Path + ApiFile android.Path + ApiSurface string } var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{}) @@ -1635,7 +1637,8 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon } ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{ - ApiFile: apiFile, + ApiFile: apiFile, + ApiSurface: proptools.String(ap.properties.Api_surface), }) } @@ -1821,18 +1824,29 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { var scopeOrderedSourceFileNames = allApiScopes.Strings( func(s *apiScope) string { return s.apiFilePrefix + "current.txt" }) -func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths { - sortedSrcFiles := android.Paths{} +func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo, apiFiles android.Paths) android.Paths { + var sortedSrcFiles android.Paths - for _, scopeSourceFileName := range scopeOrderedSourceFileNames { - for _, sourceFileName := range srcFiles { - if sourceFileName.Base() == scopeSourceFileName { - sortedSrcFiles = append(sortedSrcFiles, sourceFileName) + 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) } } } - if len(srcFiles) != len(sortedSrcFiles) { - ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles) + + 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 @@ -1853,7 +1867,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { homeDir := android.PathForModuleOut(ctx, "metalava", "home") - var srcFiles android.Paths + var srcFilesInfo []JavaApiImportInfo var classPaths android.Paths var staticLibs android.Paths var depApiSrcsStubsJar android.Path @@ -1862,11 +1876,10 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { switch tag { case javaApiContributionTag: provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo) - providerApiFile := provider.ApiFile - if providerApiFile == nil && !ctx.Config().AllowMissingDependencies() { + if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name()) } - srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String())) + srcFilesInfo = append(srcFilesInfo, provider) case libTag: provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) classPaths = append(classPaths, provider.HeaderJars...) @@ -1880,16 +1893,19 @@ 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 { - srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api)) + apiFiles = append(apiFiles, android.PathForModuleSrc(ctx, api)) } + srcFiles := al.sortApiFilesByApiScope(ctx, srcFilesInfo, apiFiles) + if srcFiles == nil && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName()) } - srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles) - cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir) al.stubsFlags(ctx, cmd, stubsDir) @@ -2759,7 +2775,7 @@ type javaResourcesAttributes struct { Additional_resources bazel.LabelListAttribute } -func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorContext, resourceFilegroup string) (*string, bool) { +func (m *Library) getResourceFilegroupStripPrefix(ctx android.Bp2buildMutatorContext, resourceFilegroup string) (*string, bool) { if otherM, ok := ctx.ModuleFromName(resourceFilegroup); ok { if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup { return proptools.StringPtr(filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx))), true @@ -2768,7 +2784,7 @@ func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorCont return proptools.StringPtr(""), false } -func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes { +func (m *Library) convertJavaResourcesAttributes(ctx android.Bp2buildMutatorContext) *javaResourcesAttributes { var resources bazel.LabelList var resourceStripPrefix *string @@ -2886,9 +2902,8 @@ type javaAidlLibraryAttributes struct { // depending on the module type. type bp2BuildJavaInfo struct { // separates dependencies into dynamic dependencies and static dependencies. - DepLabels *javaDependencyLabels - hasKotlin bool - onlyProtoInSrcs bool + DepLabels *javaDependencyLabels + hasKotlin bool } func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string { @@ -2900,7 +2915,7 @@ func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string { // which has other non-attribute information needed for bp2build conversion // that needs different handling depending on the module types, and thus needs // to be returned to the calling function. -func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) { +func (m *Library) convertLibraryAttrsBp2Build(ctx android.Bp2buildMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) { var srcs bazel.LabelListAttribute var deps bazel.LabelListAttribute var staticDeps bazel.LabelListAttribute @@ -2951,9 +2966,6 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) staticDeps.Append(srcPartitions[xsdSrcPartition]) - _, protoInSrcs := srcPartitions[protoSrcPartition] - onlyProtoInSrcs := protoInSrcs && len(srcPartitions) == 1 - if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" ctx.CreateBazelTargetModule( @@ -3091,9 +3103,8 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } bp2BuildInfo := &bp2BuildJavaInfo{ - DepLabels: depLabels, - hasKotlin: hasKotlin, - onlyProtoInSrcs: onlyProtoInSrcs, + DepLabels: depLabels, + hasKotlin: hasKotlin, } return commonAttrs, bp2BuildInfo, true @@ -3125,7 +3136,7 @@ func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties } } -func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { +func javaLibraryBp2Build(ctx android.Bp2buildMutatorContext, m *Library) { commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) if !supported { return @@ -3137,19 +3148,12 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { if !commonAttrs.Srcs.IsEmpty() { deps.Append(exports) // we should only append these if there are sources to use them } else if !deps.IsEmpty() { - if bp2BuildInfo.onlyProtoInSrcs { - // java_library does not accept deps when there are no srcs because - // there is no compilation happening, but it accepts exports. - // bp2build converts this module to 2 java_libraries + java_xx_proto_library + proto_library - // the non-empty deps here are not necessary for compiling the protos, in which case - // they're unnecessary as deps on the java_library as well since they aren't - // being propagated to any dependencies. - // so we can put the deps to exports and drop deps here. - exports.Append(deps) - deps = bazel.LabelListAttribute{} - } else { - ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") - } + // java_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 java_library + // since they aren't being propagated to any dependencies. + // So we can drop deps here. + deps = bazel.LabelListAttribute{} } var props bazel.BazelTargetModuleProperties attrs := &javaLibraryAttributes{ @@ -3188,7 +3192,7 @@ type javaBinaryHostAttributes struct { } // JavaBinaryHostBp2Build is for java_binary_host bp2build. -func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { +func javaBinaryHostBp2Build(ctx android.Bp2buildMutatorContext, m *Binary) { commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) if !supported { return @@ -3275,7 +3279,7 @@ type javaTestHostAttributes struct { } // javaTestHostBp2Build is for java_test_host bp2build. -func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) { +func javaTestHostBp2Build(ctx android.Bp2buildMutatorContext, m *TestHost) { commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) if !supported { return @@ -3328,7 +3332,7 @@ type libraryCreationInfo struct { // helper function that creates java_library target from java_binary_host or java_test_host, // and returns the library target name, -func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string { +func createLibraryTarget(ctx android.Bp2buildMutatorContext, libInfo libraryCreationInfo) string { libName := libInfo.baseName + "_lib" var libProps bazel.BazelTargetModuleProperties if libInfo.hasKotlin { @@ -3351,7 +3355,7 @@ type bazelJavaImportAttributes struct { } // java_import bp2Build converter. -func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (i *Import) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { var jars bazel.LabelListAttribute archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{}) for axis, configToProps := range archVariantProps { @@ -3387,7 +3391,6 @@ func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { javaLibraryBazelTargetModuleProperties(), android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs) - } var _ android.MixedBuildBuildable = (*Import)(nil) @@ -3440,3 +3443,30 @@ func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) { func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool { return true } + +type JavaApiContributionImport struct { + JavaApiContribution + + prebuilt android.Prebuilt +} + +func ApiContributionImportFactory() android.Module { + module := &JavaApiContributionImport{} + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + android.InitPrebuiltModule(module, &[]string{""}) + module.AddProperties(&module.properties) + return module +} + +func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt { + return &module.prebuilt +} + +func (module *JavaApiContributionImport) Name() string { + return module.prebuilt.Name(module.ModuleBase.Name()) +} + +func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { + ap.JavaApiContribution.GenerateAndroidBuildActions(ctx) +} diff --git a/java/java_test.go b/java/java_test.go index 27933c3bf..2ee05ec73 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1865,11 +1865,13 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := `java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` ctx, _ := testJavaWithFS(t, ` @@ -1919,24 +1921,28 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := ` java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` provider_bp_c := ` java_api_contribution { name: "foo3", - api_file: "current.txt", + api_file: "system-current.txt", + api_surface: "system", } ` provider_bp_d := ` java_api_contribution { name: "foo4", - api_file: "current.txt", + api_file: "system-current.txt", + api_surface: "system", } ` ctx, _ := testJavaWithFS(t, ` @@ -1992,8 +1998,9 @@ func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"}, }, { - moduleName: "bar3", - sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"}, + 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"}, }, } for _, c := range testcases { @@ -2011,12 +2018,14 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := ` java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` ctx, _ := testJavaWithFS(t, ` @@ -2064,12 +2073,14 @@ func TestJavaApiLibraryLibsLink(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := ` java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` lib_bp_a := ` @@ -2139,12 +2150,14 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := ` java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` lib_bp_a := ` @@ -2213,12 +2226,14 @@ func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) { java_api_contribution { name: "foo1", api_file: "current.txt", + api_surface: "public", } ` provider_bp_b := ` java_api_contribution { name: "foo2", api_file: "current.txt", + api_surface: "public", } ` lib_bp_a := ` @@ -2388,3 +2403,23 @@ func TestHeadersOnly(t *testing.T) { javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac") android.AssertDeepEquals(t, "javac rule", nil, javac.Rule) } + +func TestJavaApiContributionImport(t *testing.T) { + ctx, _ := testJava(t, ` + java_api_library { + name: "foo", + api_contributions: ["bar"], + } + java_api_contribution_import { + name: "bar", + api_file: "current.txt", + api_surface: "public", + } + `) + m := ctx.ModuleForTests("foo", "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + sourceFilesFlag := "--source-files current.txt" + android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) +} diff --git a/java/kotlin.go b/java/kotlin.go index 3637e2e71..aa2db0ecd 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -145,7 +145,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp `$kaptProcessorPath ` + `$kaptProcessor ` + `-Xbuild-file=$kotlinBuildFile && ` + - `${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` + + `${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ "${config.KotlincCmd}", @@ -157,6 +157,7 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp }, Rspfile: "$out.rsp", RspfileContent: `$in`, + Restat: true, }, "kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget", diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 124827523..662a2d768 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -130,7 +130,7 @@ type bazelPlatformCompatConfigAttributes struct { Src bazel.LabelAttribute } -func (p *platformCompatConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *platformCompatConfig) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { props := bazel.BazelTargetModuleProperties{ Rule_class: "platform_compat_config", Bzl_load_location: "//build/bazel/rules/java:platform_compat_config.bzl", diff --git a/java/plugin.go b/java/plugin.go index 51272981b..4d4c199f7 100644 --- a/java/plugin.go +++ b/java/plugin.go @@ -64,7 +64,7 @@ type pluginAttributes struct { } // ConvertWithBp2build is used to convert android_app to Bazel. -func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *Plugin) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { pluginName := p.Name() commonAttrs, bp2BuildInfo, supported := p.convertLibraryAttrsBp2Build(ctx) if !supported { diff --git a/java/sdk_library.go b/java/sdk_library.go index d1620af9f..27f862662 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2276,27 +2276,25 @@ func SdkLibraryFactory() android.Module { } type bazelSdkLibraryAttributes struct { - Public bazel.StringAttribute - System bazel.StringAttribute - Test bazel.StringAttribute - Module_lib bazel.StringAttribute - System_server bazel.StringAttribute + Public *bazel.Label + System *bazel.Label + Test *bazel.Label + Module_lib *bazel.Label + System_server *bazel.Label } // java_sdk_library bp2build converter -func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (module *SdkLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if ctx.ModuleType() != "java_sdk_library" { ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") return } - nameToAttr := make(map[string]bazel.StringAttribute) + nameToAttr := make(map[string]*bazel.Label) for _, scope := range module.getGeneratedApiScopes(ctx) { - apiSurfaceFile := path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt") - var scopeStringAttribute bazel.StringAttribute - scopeStringAttribute.SetValue(apiSurfaceFile) - nameToAttr[scope.name] = scopeStringAttribute + apiSurfaceFile := android.BazelLabelForModuleSrcSingle(ctx, path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt")) + nameToAttr[scope.name] = &apiSurfaceFile } attrs := bazelSdkLibraryAttributes{ @@ -2355,6 +2353,7 @@ type sdkLibraryImportProperties struct { type SdkLibraryImport struct { android.ModuleBase android.DefaultableModuleBase + android.BazelModuleBase prebuilt android.Prebuilt android.ApexModuleBase @@ -2438,6 +2437,7 @@ func sdkLibraryImportFactory() android.Module { android.InitPrebuiltModule(module, &[]string{""}) android.InitApexModule(module) + android.InitBazelModule(module) InitJavaModule(module, android.HostAndDeviceSupported) module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { @@ -2448,6 +2448,33 @@ func sdkLibraryImportFactory() android.Module { return module } +// java_sdk_library bp2build converter +func (i *SdkLibraryImport) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + nameToAttr := make(map[string]*bazel.Label) + + for scope, props := range i.scopeProperties { + if api := proptools.String(props.Current_api); api != "" { + apiSurfaceFile := android.BazelLabelForModuleSrcSingle(ctx, api) + nameToAttr[scope.name] = &apiSurfaceFile + } + } + + attrs := bazelSdkLibraryAttributes{ + Public: nameToAttr["public"], + System: nameToAttr["system"], + Test: nameToAttr["test"], + Module_lib: nameToAttr["module-lib"], + System_server: nameToAttr["system-server"], + } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "java_sdk_library", + Bzl_load_location: "//build/bazel/rules/java:sdk_library.bzl", + } + + name := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, &attrs) +} + var _ PermittedPackagesForUpdatableBootJars = (*SdkLibraryImport)(nil) func (module *SdkLibraryImport) PermittedPackagesForUpdatableBootJars() []string { @@ -2479,6 +2506,10 @@ func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHo if len(scopeProperties.Stub_srcs) > 0 { module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties) } + + if scopeProperties.Current_api != nil { + module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties) + } } javaSdkLibraries := javaSdkLibraries(mctx.Config()) @@ -2534,6 +2565,25 @@ func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.Defaulta mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) } +func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { + api_file := scopeProperties.Current_api + api_surface := &apiScope.name + + props := struct { + Name *string + Api_surface *string + Api_file *string + Visibility []string + }{} + + props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution") + props.Api_surface = api_surface + props.Api_file = api_file + props.Visibility = []string{"//visibility:override", "//visibility:public"} + + mctx.CreateModule(ApiContributionImportFactory, &props) +} + // Add the dependencies on the child module in the component deps mutator so that it // creates references to the prebuilt and not the source modules. func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 868d697ce..0b46919d2 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -74,6 +74,8 @@ func TestJavaSdkLibrary(t *testing.T) { name: "quuz", public: { jars: ["c.jar"], + current_api: "api/current.txt", + removed_api: "api/removed.txt", }, } java_sdk_library_import { @@ -173,6 +175,9 @@ func TestJavaSdkLibrary(t *testing.T) { android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs) } + // test if quuz have created the api_contribution module + result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "") + fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8") // tests if kotlinc generated files are NOT excluded from output of foo. android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go index 165697dfa..dad589256 100644 --- a/linkerconfig/linkerconfig.go +++ b/linkerconfig/linkerconfig.go @@ -107,7 +107,7 @@ type linkerConfigAttributes struct { Src bazel.LabelAttribute } -func (l *linkerConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (l *linkerConfig) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if l.properties.Src == nil { ctx.PropertyErrorf("src", "empty src is not supported") ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "") diff --git a/python/bp2build.go b/python/bp2build.go index 8bc3d0a3e..3b283e432 100644 --- a/python/bp2build.go +++ b/python/bp2build.go @@ -54,7 +54,7 @@ type baseAttributes struct { Imports bazel.StringListAttribute } -func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext) baseAttributes { +func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.Bp2buildMutatorContext) baseAttributes { var attrs baseAttributes archVariantBaseProps := m.GetArchVariantProperties(ctx, &BaseProperties{}) for axis, configToProps := range archVariantBaseProps { @@ -123,7 +123,7 @@ func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownM return attrs } -func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.TopDownMutatorContext) *string { +func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.Bp2buildMutatorContext) *string { py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true) py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false) if py2Enabled && !py3Enabled { @@ -146,7 +146,7 @@ type bazelPythonBinaryAttributes struct { Imports bazel.StringListAttribute } -func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { // TODO(b/182306917): this doesn't fully handle all nested props versioned // by the python version, which would have been handled by the version split // mutator. This is sufficient for very simple python_library modules under @@ -176,7 +176,7 @@ func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorCont }, attrs) } -func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.TopDownMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) { +func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.Bp2buildMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) { // TODO(b/182306917): this doesn't fully handle all nested props versioned // by the python version, which would have been handled by the version split // mutator. This is sufficient for very simple python_binary_host modules @@ -209,7 +209,7 @@ func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.TopDownMutator return attrs, baseAttrs.Data } -func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { attrs, data := p.bp2buildBinaryProperties(ctx) props := bazel.BazelTargetModuleProperties{ @@ -223,7 +223,7 @@ func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorConte }, attrs) } -func (p *PythonTestModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *PythonTestModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { // Python tests are currently exactly the same as binaries, but with a different module type attrs, data := p.bp2buildBinaryProperties(ctx) diff --git a/rust/afdo_test.go b/rust/afdo_test.go index 0cdf70491..80327af2a 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.Args["rustcFlags"], expectedCFlag) { - t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"]) + 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) } } @@ -96,17 +96,17 @@ func TestAfdoEnabledWithMultiArchs(t *testing.T) { rustMockedFiles.AddToFixture(), ).RunTestWithBp(t, bp) - fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc") - fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc") + fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Description("rustc") + fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Description("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.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(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(fooArm64.Args["rustcFlags"], expectedCFlagArm64) { - t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm64, fooArm64.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) } } diff --git a/rust/binary.go b/rust/binary.go index 1e24bebab..353381d78 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -15,9 +15,10 @@ package rust import ( + "fmt" + "android/soong/android" "android/soong/bazel" - "fmt" ) func init() { @@ -137,13 +138,17 @@ func (binary *binaryDecorator) preferRlib() bool { func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix() - srcPath, _ := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs) outputFile := android.PathForModuleOut(ctx, fileName) ret := buildOutput{outputFile: outputFile} + var crateRootPath android.Path + if binary.baseCompiler.Properties.Crate_root == nil { + crateRootPath, _ = srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs) + } else { + crateRootPath = android.PathForModuleSrc(ctx, *binary.baseCompiler.Properties.Crate_root) + } 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 @@ -154,7 +159,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path } binary.baseCompiler.unstrippedOutputFile = outputFile - ret.kytheFile = TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrcToBinary(ctx, binary, crateRootPath, deps, flags, outputFile).kytheFile return ret } @@ -199,7 +204,7 @@ type rustBinaryLibraryAttributes struct { Rustc_flags bazel.StringListAttribute } -func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func binaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { binary := m.compiler.(*binaryDecorator) var srcs bazel.LabelList diff --git a/rust/binary_test.go b/rust/binary_test.go index dff94ac95..ab1d2bc36 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.Args["rustcFlags"] + flags := fizzBuzz.RuleParams.Command 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("rustLink") + foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc") flag := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker64" - if !strings.Contains(foo.Args["linkFlags"], flag) { - t.Errorf("missing link flag to use bootstrap linker, expecting %#v, linkFlags: %#v", flag, foo.Args["linkFlags"]) + if !strings.Contains(foo.RuleParams.Command, flag) { + t.Errorf("missing link flag to use bootstrap linker, expecting %#v, command: %#v", flag, foo.RuleParams.Command) } } @@ -167,19 +167,17 @@ 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.Args["rustcFlags"] - linkFlags := fizzOutLink.Args["linkFlags"] + flags := fizzOut.RuleParams.Command if !strings.Contains(flags, "-C relocation-model=static") { - t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags) + t.Errorf("static binary missing '-C relocation-model=static' in command, found: %#v", flags) } if !strings.Contains(flags, "-C panic=abort") { - t.Errorf("static binary missing '-C panic=abort' in rustcFlags, found: %#v", flags) + t.Errorf("static binary missing '-C panic=abort' in command, found: %#v", flags) } - if !strings.Contains(linkFlags, "-static") { - t.Errorf("static binary missing '-static' in linkFlags, found: %#v", flags) + if !strings.Contains(flags, "-static") { + t.Errorf("static binary missing '-static' in command, found: %#v", flags) } if !android.InList("libc", fizzMod.Properties.AndroidMkStaticLibs) { @@ -201,10 +199,9 @@ func TestLinkObjects(t *testing.T) { name: "libfoo", }`) - 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) + 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) } } diff --git a/rust/builder.go b/rust/builder.go index b1f049d15..07405183e 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -15,6 +15,7 @@ package rust import ( + "fmt" "path/filepath" "strings" @@ -25,54 +26,6 @@ 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", @@ -81,7 +34,7 @@ var ( RspfileContent: "$in", }) - cp = pctx.AndroidStaticRule("cp", + cpDir = pctx.AndroidStaticRule("cpDir", blueprint.RuleParams{ Command: "cp `cat $outDir.rsp` $outDir", Rspfile: "${outDir}.rsp", @@ -89,6 +42,12 @@ 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") @@ -96,23 +55,6 @@ 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 { @@ -124,40 +66,40 @@ func init() { pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") } -func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrcToBinary(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "bin") } -func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoRlib(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "rlib") } -func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoDylib(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "dylib") } -func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoStatic(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "staticlib") } -func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, +func TransformSrctoShared(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin") - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "cdylib") } -func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps, +func TransformSrctoProcMacro(ctx ModuleContext, c compiler, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath) buildOutput { - return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro") + return transformSrctoCrate(ctx, c, mainSrc, deps, flags, outputFile, "proc-macro") } func rustLibsToPaths(libs RustLibraries) android.Paths { @@ -168,28 +110,46 @@ func rustLibsToPaths(libs RustLibraries) android.Paths { return paths } -func makeLibFlags(deps PathDeps) []string { +func makeLibFlags(deps PathDeps, ruleCmd *android.RuleBuilderCommand) []string { var libFlags []string // Collect library/crate flags - for _, lib := range deps.RLibs { - libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String()) + for _, lib := range deps.Rlibs.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 _, lib := range deps.Dylibs.ToListDirect() { + libPath := ruleCmd.PathForInput(lib.Path) + libFlags = append(libFlags, "--extern "+lib.CrateName+"="+libPath) } - for _, proc_macro := range deps.ProcMacros { - libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String()) + for _, procMacro := range deps.ProcMacros.ToListDirect() { + procMacroPath := ruleCmd.PathForInput(procMacro.Path) + libFlags = append(libFlags, "--extern "+procMacro.CrateName+"="+procMacroPath) } for _, path := range deps.linkDirs { - libFlags = append(libFlags, "-L "+path) + libFlags = append(libFlags, "-L "+ruleCmd.PathForInput(path)) } return libFlags } -func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { +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 { var envVars []string // libstd requires a specific environment variable to be set. This is @@ -203,15 +163,17 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { 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 outDirPrefix string - if !filepath.IsAbs(moduleGenDir.String()) { + 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() { // If OUT_DIR is not absolute, we use $$PWD to generate an absolute path (os.Getwd() returns '/') - outDirPrefix = "$$PWD/" + outDir = filepath.Join("$$PWD/", cmd.PathForInput(moduleGenDir.Path())) } else { - // If OUT_DIR is absolute, then moduleGenDir will be an absolute path, so we don't need to set this to anything. - outDirPrefix = "" + outDir = "$$PWD/" } - envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String())) + envVars = append(envVars, "OUT_DIR="+outDir) } else { // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value. envVars = append(envVars, "OUT_DIR=out") @@ -242,7 +204,7 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { } } - envVars = append(envVars, "AR=${cc_config.ClangBin}/llvm-ar") + envVars = append(envVars, "AR="+cmd.PathForTool(deps.Llvm_ar)) if ctx.Darwin() { envVars = append(envVars, "ANDROID_RUST_DARWIN=true") @@ -251,21 +213,18 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string { return envVars } -func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags, +func transformSrctoCrate(ctx ModuleContext, comp compiler, 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 @@ -286,7 +245,6 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl // 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) } @@ -298,36 +256,16 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl // Collect linker flags if !ctx.Darwin() { - 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) + earlyLinkFlags = append(earlyLinkFlags, "-Wl,--as-needed") } - libFlags := makeLibFlags(deps) - // Collect dependencies - 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...) + var linkImplicits android.Paths + implicits := collectImplicits(deps) + toolImplicits := android.Concat(deps.BuildToolDeps) linkImplicits = append(linkImplicits, deps.CrtBegin...) linkImplicits = append(linkImplicits, deps.CrtEnd...) - - linkOrderOnly = append(linkOrderOnly, deps.linkObjects...) + implicits = append(implicits, comp.compilationSourcesAndData(ctx)...) if len(deps.SrcDeps) > 0 { moduleGenDir := ctx.RustModule().compiler.CargoOutDir() @@ -342,7 +280,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl } ctx.Build(pctx, android.BuildParams{ - Rule: cp, + Rule: cpDir, Description: "cp " + moduleGenDir.Path().Rel(), Outputs: outputs, Inputs: deps.SrcDeps, @@ -354,81 +292,176 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl } 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") - 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, " "), - }, - }) + 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()) + // Declare the clippy build as an implicit dependency of the original crate. implicits = append(implicits, clippyFile) } - rustcOutputFile := outputFile + 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") + 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 { - rustcOutputFile = android.PathForModuleOut(ctx, outputFile.Base()+".rsp") + rustSboxOutputFile = android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".rsp") + rustcImplicitOutputs = android.WritablePaths{ + android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".whole.a"), + android.PathForModuleOut(ctx, sboxDirectory, rustSboxOutputFile.Base()+".a"), + } } - ctx.Build(pctx, android.BuildParams{ - Rule: rustc, - Description: "rustc " + main.Rel(), - Output: rustcOutputFile, - Inputs: inputs, - Implicits: implicits, - Args: map[string]string{ - "rustcFlags": strings.Join(rustcFlags, " "), - "libFlags": strings.Join(libFlags, " "), - "envVars": strings.Join(envVars, " "), - }, - }) + // TODO(b/298461712) remove this hack to let slim manifest branches build + if deps.Rustc == nil { + deps.Rustc = config.RustPath(ctx, "bin/rustc") + } - if usesLinker { + 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: 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(), " "), - }, + 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: cp, + Input: linkerSboxOutputFile, + Output: outputFile, }) } + 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") - 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, " "), - }, - }) + 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()) output.kytheFile = kytheFile } return output } -func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, - flags Flags) android.ModuleOutPath { +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() rustdocFlags := append([]string{}, flags.RustdocFlags...) rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null") @@ -447,7 +480,7 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, crateName := ctx.RustModule().CrateName() rustdocFlags = append(rustdocFlags, "--crate-name "+crateName) - rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...) + rustdocFlags = append(rustdocFlags, makeLibFlags(deps, rustdocCmd)...) docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp") // Silence warnings about renamed lints for third-party crates @@ -463,18 +496,26 @@ func Rustdoc(ctx ModuleContext, main android.Path, deps PathDeps, // https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146 docDir := android.PathForOutput(ctx, "rustdoc") - 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), " "), - }, - }) + rustdocCmd. + Flags(rustEnvVars(ctx, deps, rustdocCmd)). + Tool(deps.Rustdoc). + Flags(rustdocFlags). + Input(main). + Flag("-o "+docDir.String()). + FlagWithOutput("&& touch ", docTimestampFile). + Implicit(ctx.RustModule().UnstrippedOutputFile()) + 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/clippy_test.go b/rust/clippy_test.go index bd3bfb151..2703a1c6a 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.AssertStringEquals(t, "libfoo flags", tc.fooFlags, r.Args["clippyFlags"]) + android.AssertStringDoesContain(t, "libfoo flags", r.RuleParams.Command, tc.fooFlags) r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy") - android.AssertStringEquals(t, "libbar flags", "${config.ClippyDefaultLints}", r.Args["clippyFlags"]) + android.AssertStringDoesContain(t, "libbar flags", r.RuleParams.Command, "${config.ClippyDefaultLints}") 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: clippyFlags=%q", r.Args["clippyFlags"]) + t.Errorf("libfoobar is setup to use clippy when explicitly disabled: command=%q", r.RuleParams.Command) } }) } diff --git a/rust/compiler.go b/rust/compiler.go index e6a7a9356..3fa3ccd69 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -73,6 +73,18 @@ type BaseCompilerProperties struct { // If no source file is defined, a single generated source module can be defined to be used as the main source. Srcs []string `android:"path,arch_variant"` + // Entry point that is passed to rustc to begin the compilation. E.g. main.rs or lib.rs. + // When this property is set, + // * sandboxing is enabled for this module, and + // * the srcs attribute is interpreted as a list of all source files potentially + // used in compilation, including the entrypoint, and + // * compile_data can be used to add additional files used in compilation that + // 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 @@ -334,6 +346,23 @@ 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 { @@ -511,6 +540,8 @@ func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, andr ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.") } + // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper + // entry point file from Srcs rather than taking the first one paths := android.PathsForModuleSrc(ctx, srcs) return paths[srcIndex], paths[1:] } diff --git a/rust/compiler_test.go b/rust/compiler_test.go index ec6829a1b..e5cc8884e 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.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"]) + 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) } } @@ -57,9 +57,9 @@ func TestCfgsToFlags(t *testing.T) { libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") - 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"]) + 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) } } @@ -146,14 +146,14 @@ func TestCargoCompat(t *testing.T) { fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc") - 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_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_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_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_PKG_VERSION=1.0.0") { - t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' 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) } } @@ -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.Args["rustcFlags"], tc.fooFlags) + android.AssertStringDoesContain(t, "libfoo flags", r.RuleParams.Command, tc.fooFlags) r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}") + android.AssertStringDoesContain(t, "libbar flags", r.RuleParams.Command, "${config.RustDefaultLints}") r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc") - android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}") + android.AssertStringDoesContain(t, "libfoobar flags", r.RuleParams.Command, "${config.RustAllowAllLints}") }) } } diff --git a/rust/config/global.go b/rust/config/global.go index 4bd495d86..0ddc11637 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -25,7 +25,7 @@ var ( pctx = android.NewPackageContext("android/soong/rust/config") exportedVars = android.NewExportedVariables(pctx) - RustDefaultVersion = "1.71.0" + RustDefaultVersion = "1.72.0" RustDefaultBase = "prebuilts/rust/" DefaultEdition = "2021" Stdlibs = []string{ @@ -81,13 +81,7 @@ var ( func init() { pctx.SourcePathVariable("RustDefaultBase", RustDefaultBase) - pctx.VariableConfigMethod("HostPrebuiltTag", func(config android.Config) string { - if config.UseHostMusl() { - return "linux-musl-x86" - } else { - return config.PrebuiltOS() - } - }) + pctx.VariableConfigMethod("HostPrebuiltTag", HostPrebuiltTag) pctx.VariableFunc("RustBase", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("RUST_PREBUILTS_BASE"); override != "" { @@ -109,6 +103,14 @@ func init() { exportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion) } +func HostPrebuiltTag(config android.Config) string { + if config.UseHostMusl() { + return "linux-musl-x86" + } else { + return config.PrebuiltOS() + } +} + func getRustVersionPctx(ctx android.PackageVarContext) string { return GetRustVersion(ctx) } @@ -124,3 +126,27 @@ 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/config/riscv64_device.go b/rust/config/riscv64_device.go index e9aa8ef61..0a9c61a64 100644 --- a/rust/config/riscv64_device.go +++ b/rust/config/riscv64_device.go @@ -24,8 +24,12 @@ var ( Riscv64RustFlags = []string{ "-C force-frame-pointers=y", } - Riscv64ArchFeatureRustFlags = map[string][]string{"": {}} - Riscv64LinkFlags = []string{} + Riscv64ArchFeatureRustFlags = map[string][]string{ + "riscv64": { + "-C target-feature=+V,+Zba,+Zbb,+Zbs", + }, + } + Riscv64LinkFlags = []string{} Riscv64ArchVariantRustFlags = map[string][]string{"": {}} ) diff --git a/rust/coverage.go b/rust/coverage.go index 5216d6098..b312194f2 100644 --- a/rust/coverage.go +++ b/rust/coverage.go @@ -17,6 +17,7 @@ package rust import ( "github.com/google/blueprint" + "android/soong/android" "android/soong/cc" ) @@ -70,7 +71,10 @@ 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 = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile().Path(), CrateName: profiler_builtins.CrateName()}) + deps.Rlibs = android.AddDirectToDepSet[RustLibrary](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 64077cf00..1466e0ce4 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("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") + 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") 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.Args["rustcFlags"], flag) { - t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.Args["rustcFlags"]) + if !strings.Contains(fizzCov.RuleParams.Command, flag) { + t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.RuleParams.Command) } - if !strings.Contains(libfooCov.Args["rustcFlags"], flag) { - t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.Args["rustcFlags"]) + if !strings.Contains(libfooCov.RuleParams.Command, flag) { + t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.RuleParams.Command) } - if strings.Contains(buzzNoCov.Args["rustcFlags"], flag) { - t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.Args["rustcFlags"]) + if strings.Contains(buzzNoCov.RuleParams.Command, flag) { + t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.RuleParams.Command) } - if strings.Contains(libbarNoCov.Args["rustcFlags"], flag) { - t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.Args["rustcFlags"]) + if strings.Contains(libbarNoCov.RuleParams.Command, flag) { + t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.RuleParams.Command) } } @@ -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.Args["linkFlags"], flag) { - t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.Args["linkFlags"]) + if !strings.Contains(fizzCovLink.RuleParams.Command, flag) { + t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.RuleParams.Command) } - if !strings.Contains(libfooCovLink.Args["linkFlags"], flag) { - t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.Args["linkFlags"]) + if !strings.Contains(libfooCovLink.RuleParams.Command, flag) { + t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.RuleParams.Command) } - if strings.Contains(buzzNoCovLink.Args["linkFlags"], flag) { - t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.Args["linkFlags"]) + if strings.Contains(buzzNoCovLink.RuleParams.Command, flag) { + t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.RuleParams.Command) } - if strings.Contains(libbarNoCovLink.Args["linkFlags"], flag) { - t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.Args["linkFlags"]) + if strings.Contains(libbarNoCovLink.RuleParams.Command, flag) { + t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.RuleParams.Command) } } @@ -107,8 +107,8 @@ func TestCoverageDeps(t *testing.T) { srcs: ["foo.rs"], }`) - 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"]) + 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) } } diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go index ee28c6d3a..ea3590556 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.Args["rustcFlags"], "-C passes='sancov-module'") || - !strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") { + if !strings.Contains(fuzz_libtest.RuleParams.Command, "-C passes='sancov-module'") || + !strings.Contains(fuzz_libtest.RuleParams.Command, "--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.Args["rustcFlags"], "-C passes='sancov-module'") || - !strings.Contains(host_fuzzer.Args["rustcFlags"], "--cfg fuzzing") { + if !strings.Contains(host_fuzzer.RuleParams.Command, "-C passes='sancov-module'") || + !strings.Contains(host_fuzzer.RuleParams.Command, "--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").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).") + 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) } } diff --git a/rust/image_test.go b/rust/image_test.go index fb4d9c170..813c5bcdd 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.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_vndk'") { + t.Errorf("missing \"--cfg 'android_vndk'\" 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_vendor'") { + t.Errorf("missing \"--cfg 'android_vendor'\" 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"]) + if strings.Contains(vendor.RuleParams.Command, "--cfg 'android_product'") { + t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.RuleParams.Command) } product := ctx.ModuleForTests("libfoo", "android_product.29_arm64_armv8-a_static").Rule("rustc") - 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_vndk'") { + t.Errorf("missing \"--cfg 'android_vndk'\" 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_vendor'") { + t.Errorf("unexpected \"--cfg 'android_vendor'\" 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"]) + if !strings.Contains(product.RuleParams.Command, "--cfg 'android_product'") { + t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.RuleParams.Command) } system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Rule("rustc") - 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_vndk'") { + t.Errorf("unexpected \"--cfg 'android_vndk'\" 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_vendor'") { + t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.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"]) + if strings.Contains(system.RuleParams.Command, "--cfg 'android_product'") { + t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.RuleParams.Command) } } diff --git a/rust/library.go b/rust/library.go index 3f031c10c..7bb82bcc2 100644 --- a/rust/library.go +++ b/rust/library.go @@ -485,11 +485,28 @@ 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 var fileName string - srcPath := library.srcPath(ctx, deps) + crateRootPath := library.crateRootPath(ctx, deps) if library.sourceProvider != nil { deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...) @@ -525,7 +542,6 @@ 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: @@ -536,13 +552,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, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoRlib(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile } else if library.dylib() { - ret.kytheFile = TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoDylib(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile } else if library.static() { - ret.kytheFile = TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoStatic(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile } else if library.shared() { - ret.kytheFile = TransformSrctoShared(ctx, srcPath, deps, flags, outputFile).kytheFile + ret.kytheFile = TransformSrctoShared(ctx, library, crateRootPath, deps, flags, outputFile).kytheFile } if library.rlib() || library.dylib() { @@ -585,13 +601,15 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa return ret } -func (library *libraryDecorator) srcPath(ctx ModuleContext, _ PathDeps) android.Path { +func (library *libraryDecorator) crateRootPath(ctx ModuleContext, _ PathDeps) android.Path { if library.sourceProvider != nil { // Assume the first source from the source provider is the library entry point. return library.sourceProvider.Srcs()[0] - } else { + } else if library.baseCompiler.Properties.Crate_root == nil { path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) return path + } else { + return android.PathForModuleSrc(ctx, *library.baseCompiler.Properties.Crate_root) } } @@ -606,7 +624,7 @@ func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags, return android.OptionalPath{} } - return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps), + return android.OptionalPathForPath(Rustdoc(ctx, library.crateRootPath(ctx, deps), deps, flags)) } @@ -810,7 +828,7 @@ type rustLibraryAttributes struct { Proc_macro_deps bazel.LabelListAttribute } -func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func libraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { lib := m.compiler.(*libraryDecorator) srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler) @@ -887,7 +905,7 @@ type cargoBuildScriptAttributes struct { Version bazel.StringAttribute } -func cargoBuildScriptBp2build(ctx android.TopDownMutatorContext, m *Module) *string { +func cargoBuildScriptBp2build(ctx android.Bp2buildMutatorContext, m *Module) *string { // Soong treats some crates like libprotobuf as special in that they have // cargo build script ran to produce an out folder and check it into AOSP // For example, https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/out/ diff --git a/rust/library_test.go b/rust/library_test.go index 30ef333b9..dab938159 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.Args["rustcFlags"], "crate-type="+rlibCrateType) { - t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.Args["rustcFlags"]) + 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) } // Test crate type for dylib is correct. - 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"]) + 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) } // Test crate type for C static libraries is correct. - 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"]) + 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) } // Test crate type for C shared libraries is correct. - 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"]) + 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) } } @@ -78,10 +78,10 @@ func TestDylibPreferDynamic(t *testing.T) { crate_name: "foo", }`) - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Description("rustc") - if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") { - t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) + if !strings.Contains(libfooDylib.RuleParams.Command, "prefer-dynamic") { + t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.RuleParams.Command) } } @@ -94,10 +94,10 @@ func TestAndroidDylib(t *testing.T) { crate_name: "foo", }`) - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Description("rustc") - if !strings.Contains(libfooDylib.Args["rustcFlags"], "--cfg 'android_dylib'") { - t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) + if !strings.Contains(libfooDylib.RuleParams.Command, "--cfg 'android_dylib'") { + t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.RuleParams.Command) } } @@ -148,10 +148,10 @@ func TestSharedLibrary(t *testing.T) { libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared") - libfooOutput := libfoo.Rule("rustLink") - if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") { + libfooOutput := libfoo.Rule("rustc") + if !strings.Contains(libfooOutput.RuleParams.Command, "-Wl,-soname=libfoo.so") { t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", - libfooOutput.Args["linkFlags"]) + libfooOutput.RuleParams.Command) } if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkDylibs) { @@ -237,19 +237,21 @@ 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").Args["libFlags"], - "-L out/soong/.intermediates/shared_cc_dep/android_arm64_armv8-a_shared/") { + if !strings.Contains(module.Rule("rustc").RuleParams.Command, expectedSharedFlag) { t.Errorf( - "missing -L flag for shared_cc_dep, rustcFlags: %#v", - rustRlibRlibStd.Rule("rustc").Args["libFlags"], + "expected to find shared library linkdir flag %q, rustcFlags: %#v", + expectedSharedFlag, + rustRlibRlibStd.Rule("rustc").RuleParams.Command, ) } - if !strings.Contains(module.Rule("rustc").Args["libFlags"], - "-L out/soong/.intermediates/static_cc_dep/android_arm64_armv8-a_static/") { + if !strings.Contains(module.Rule("rustc").RuleParams.Command, expectedStaticFlag) { t.Errorf( - "missing -L flag for static_cc_dep, rustcFlags: %#v", - rustRlibRlibStd.Rule("rustc").Args["libFlags"], + "expected to find static library linkdir flag %q, rustcFlags: %#v", + expectedStaticFlag, + rustRlibRlibStd.Rule("rustc").RuleParams.Command, ) } } diff --git a/rust/prebuilt.go b/rust/prebuilt.go index fe9d0b5dd..d012680f0 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -146,7 +146,10 @@ func (prebuilt *prebuiltLibraryDecorator) compilerProps() []interface{} { } func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput { - prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) + 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.setProvider(ctx) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) @@ -203,7 +206,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).Strings()...) + prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs)...) prebuilt.flagExporter.setProvider(ctx) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 26227d048..3f0d17a73 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -15,9 +15,10 @@ package rust import ( + "fmt" + "android/soong/android" "android/soong/bazel" - "fmt" ) func init() { @@ -79,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, srcPath, deps, flags, outputFile) + ret := TransformSrctoProcMacro(ctx, procMacro, srcPath, deps, flags, outputFile) procMacro.baseCompiler.unstrippedOutputFile = outputFile return ret } @@ -114,7 +115,7 @@ type procMacroAttributes struct { Rustc_flags bazel.StringListAttribute } -func procMacroBp2build(ctx android.TopDownMutatorContext, m *Module) { +func procMacroBp2build(ctx android.Bp2buildMutatorContext, m *Module) { procMacro := m.compiler.(*procMacroDecorator) srcs, compileData := srcsAndCompileDataAttrs(ctx, *procMacro.baseCompiler) deps := android.BazelLabelForModuleDeps(ctx, append( diff --git a/rust/proc_macro_test.go b/rust/proc_macro_test.go index cc8193858..a547926fc 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.Args["rustcFlags"], "--extern proc_macro") { - t.Errorf("--extern proc_macro flag not being passed to rustc for proc macro %#v", libprocmacro.Args["rustcFlags"]) + 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) } } diff --git a/rust/protobuf.go b/rust/protobuf.go index ae828442b..c8d2bdaeb 100644 --- a/rust/protobuf.go +++ b/rust/protobuf.go @@ -282,7 +282,7 @@ type protoLibraryAttributes struct { Srcs bazel.LabelListAttribute } -func protoLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func protoLibraryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { var protoFiles []string for _, propsInterface := range m.sourceProvider.SourceProviderProps() { diff --git a/rust/rust.go b/rust/rust.go index 1ee99cdb1..6d6b55efe 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -15,11 +15,12 @@ package rust import ( + "fmt" + "strings" + "android/soong/bazel" "android/soong/bloaty" "android/soong/ui/metrics/bp2build_metrics_proto" - "fmt" - "strings" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -437,12 +438,18 @@ type Deps struct { } type PathDeps struct { - DyLibs RustLibraries - RLibs RustLibraries + Dylibs *android.DepSet[RustLibrary] + Rlibs *android.DepSet[RustLibrary] + ProcMacros *android.DepSet[RustLibrary] 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 @@ -450,7 +457,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 []string + linkDirs android.Paths linkObjects android.Paths // Used by bindgen modules which call clang @@ -465,6 +472,13 @@ 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 @@ -484,6 +498,8 @@ 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. @@ -513,7 +529,7 @@ type compiler interface { } type exportedFlagsProducer interface { - exportLinkDirs(...string) + exportLinkDirs(...android.Path) exportLinkObjects(...android.Path) } @@ -522,13 +538,13 @@ type xref interface { } type flagExporter struct { - linkDirs []string + linkDirs android.Paths linkObjects android.Paths libDeps android.Paths } -func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { - flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) +func (flagExporter *flagExporter) exportLinkDirs(dirs ...android.Path) { + flagExporter.linkDirs = android.FirstUniquePaths(append(flagExporter.linkDirs, dirs...)) } func (flagExporter *flagExporter) exportLinkObjects(flags ...android.Path) { @@ -555,7 +571,7 @@ func NewFlagExporter() *flagExporter { type FlagExporterInfo struct { Flags []string - LinkDirs []string // TODO: this should be android.Paths + LinkDirs android.Paths LinkObjects android.Paths LibDeps android.Paths } @@ -925,6 +941,14 @@ 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, @@ -1034,6 +1058,12 @@ 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 { @@ -1092,6 +1122,7 @@ 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} @@ -1225,7 +1256,9 @@ 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) @@ -1238,6 +1271,17 @@ 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) @@ -1252,9 +1296,12 @@ 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) @@ -1263,10 +1310,18 @@ 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(), + }) } transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs) @@ -1302,9 +1357,8 @@ 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(linkDir) + lib.exportLinkDirs(linkFile.Dir()) } } @@ -1331,7 +1385,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - linkPath := linkPathFromFilePath(linkObject.Path()) + linkPath := linkObject.Path().Dir() exportDep := false switch { @@ -1385,7 +1439,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } return } - linkPath = linkPathFromFilePath(linkObject.Path()) + linkPath = linkObject.Path().Dir() depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...) @@ -1420,6 +1474,25 @@ 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: @@ -1435,21 +1508,6 @@ 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()) @@ -1473,20 +1531,22 @@ 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.FirstUniqueStrings(depPaths.linkDirs) + depPaths.linkDirs = android.FirstUniquePaths(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 } @@ -1509,10 +1569,6 @@ 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() @@ -1555,6 +1611,15 @@ 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 { @@ -1845,7 +1910,7 @@ func (c *Module) Partition() string { return "" } -func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { if ctx.ModuleType() == "rust_library_host" || ctx.ModuleType() == "rust_library" { libraryBp2build(ctx, m) } else if ctx.ModuleType() == "rust_proc_macro" { @@ -1864,7 +1929,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { // TODO(b/297344471): When crate_root prop is set which enforces inputs sandboxing, // always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes // instead of using globs. -func srcsAndCompileDataAttrs(ctx android.TopDownMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) { +func srcsAndCompileDataAttrs(ctx android.Bp2buildMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) { var srcs bazel.LabelList var compileData bazel.LabelList diff --git a/rust/rust_test.go b/rust/rust_test.go index 835114c13..576209d04 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -15,14 +15,17 @@ 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" ) @@ -64,11 +67,14 @@ 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) *android.TestContext { +func testRust(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext { skipTestIfOsNotSupported(t) result := android.GroupFixturePreparers( prepareForRustTest, rustMockedFiles.AddToFixture(), + android.GroupFixturePreparers( + preparers..., + ), ). RunTestWithBp(t, bp) return result.TestContext @@ -202,11 +208,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 := linkPathFromFilePath(barPath) - expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/" + libName := barPath.Dir() + expectedResult := "out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared" - if libName != expectedResult { - t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName) + if libName.String() != expectedResult { + t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName.String()) } } @@ -256,7 +262,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("rustLink") + rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc") // 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) { @@ -275,16 +281,16 @@ func TestDepsTracking(t *testing.T) { t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)") } - 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(rustc.RuleParams.Command, "-lstatic=wholestatic") { + t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.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 !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 !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") { + t.Errorf("shared cc dep not being passed as implicit to rustc %#v", rustLink.OrderOnly.Strings()) } if !android.SuffixInList(rustLink.Implicits.Strings(), "cc_stubs_dep.so.toc") { @@ -427,7 +433,7 @@ func TestProcMacroDeviceDeps(t *testing.T) { `) rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc") - if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") { + if !strings.Contains(rustc.RuleParams.Command, "libbar/linux_glibc_x86_64") { t.Errorf("Proc_macro is not using host variant of dependent modules.") } } @@ -480,3 +486,396 @@ 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 43e95f477..d6a14b295 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("rustLink").Implicits + implicits := m.Rule("rustc").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 3fe751e17..9951937be 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -52,6 +52,22 @@ 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", @@ -63,6 +79,25 @@ 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 @@ -99,6 +134,278 @@ 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", @@ -113,6 +420,25 @@ 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 326d52924..cb345a4b6 100644 --- a/rust/toolchain_library.go +++ b/rust/toolchain_library.go @@ -18,9 +18,12 @@ package rust import ( "path" + "path/filepath" "android/soong/android" "android/soong/rust/config" + + "github.com/google/blueprint/proptools" ) // This module is used to compile the rust toolchain libraries @@ -33,11 +36,15 @@ func init() { rustToolchainLibraryRlibFactory) android.RegisterModuleType("rust_toolchain_library_dylib", rustToolchainLibraryDylibFactory) + android.RegisterModuleType("rust_toolchain_rustc_prebuilt", + rustToolchainRustcPrebuiltFactory) } type toolchainLibraryProperties struct { - // path to the toolchain source, relative to the top of the toolchain source - Toolchain_src *string `android:"arch_variant"` + // path to the toolchain crate root, relative to the top of the toolchain source + Toolchain_crate_root *string `android:"arch_variant"` + // path to the rest of the toolchain srcs, relative to the top of the toolchain source + Toolchain_srcs []string `android:"arch_variant"` } type toolchainLibraryDecorator struct { @@ -82,16 +89,21 @@ func initToolchainLibrary(module *Module, library *libraryDecorator) android.Mod func rustSetToolchainSource(ctx android.LoadHookContext) { if toolchainLib, ok := ctx.Module().(*Module).compiler.(*toolchainLibraryDecorator); ok { - prefix := "linux-x86/" + GetRustPrebuiltVersion(ctx) - newSrcs := []string{path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_src))} + prefix := filepath.Join(config.HostPrebuiltTag(ctx.Config()), 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 { + versionedSrcs[i] = path.Join(prefix, src) + } type props struct { - Srcs []string + Crate_root *string + Srcs []string } p := &props{} - p.Srcs = newSrcs + p.Crate_root = &versionedCrateRoot + p.Srcs = versionedSrcs ctx.AppendProperties(p) - } else { ctx.ModuleErrorf("Called rustSetToolchainSource on a non-Rust Module.") } @@ -101,3 +113,47 @@ func rustSetToolchainSource(ctx android.LoadHookContext) { func GetRustPrebuiltVersion(ctx android.LoadHookContext) string { return ctx.AConfig().GetenvWithDefault("RUST_PREBUILTS_VERSION", config.RustDefaultVersion) } + +type toolchainRustcPrebuiltProperties struct { + // path to rustc prebuilt, relative to the top of the toolchain source + Toolchain_prebuilt_src *string + // path to deps, relative to the top of the toolchain source + Toolchain_deps []string + // path to deps, relative to module directory + Deps []string +} + +func rustToolchainRustcPrebuiltFactory() android.Module { + module := android.NewPrebuiltBuildTool() + module.AddProperties(&toolchainRustcPrebuiltProperties{}) + android.AddLoadHook(module, func(ctx android.LoadHookContext) { + var toolchainProps *toolchainRustcPrebuiltProperties + for _, p := range ctx.Module().GetProperties() { + toolchainProperties, ok := p.(*toolchainRustcPrebuiltProperties) + if ok { + toolchainProps = toolchainProperties + } + } + + if toolchainProps.Toolchain_prebuilt_src == nil { + ctx.PropertyErrorf("toolchain_prebuilt_src", "must set path to rustc prebuilt") + } + + prefix := filepath.Join(config.HostPrebuiltTag(ctx.Config()), GetRustPrebuiltVersion(ctx)) + deps := make([]string, 0, len(toolchainProps.Toolchain_deps)+len(toolchainProps.Deps)) + for _, d := range toolchainProps.Toolchain_deps { + deps = append(deps, path.Join(prefix, d)) + } + deps = append(deps, toolchainProps.Deps...) + + props := struct { + Src *string + Deps []string + }{ + Src: proptools.StringPtr(path.Join(prefix, *toolchainProps.Toolchain_prebuilt_src)), + Deps: deps, + } + ctx.AppendProperties(&props) + }) + return module +} diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go index 1e7e7d322..621a7246c 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("rustLink").Args["linkFlags"] + libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").RuleParams.Command 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("rustLink").Args["linkFlags"] + binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").RuleParams.Command 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/sh/sh_binary.go b/sh/sh_binary.go index 00794cdbe..79a885fa9 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -190,6 +190,15 @@ func (s *ShBinary) OutputFile() android.OutputPath { return s.outputFilePath } +func (s *ShBinary) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + return android.Paths{s.outputFilePath}, nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + func (s *ShBinary) SubDir() string { return proptools.String(s.properties.Sub_dir) } @@ -574,7 +583,7 @@ type bazelShTestAttributes struct { Auto_gen_config *bool } -func (m *ShBinary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *ShBinary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { srcs := bazel.MakeLabelListAttribute( android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src})) @@ -602,7 +611,7 @@ func (m *ShBinary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) } -func (m *ShTest) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *ShTest) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { srcs := bazel.MakeLabelListAttribute( android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src})) diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index a2c0fb731..d16bf32f9 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -591,7 +591,7 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { } // TODO(b/240463568): Additional properties will be added for API validation -func (m *syspropLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (m *syspropLibrary) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { labels := cc.SyspropLibraryLabels{ SyspropLibraryLabel: m.BaseModuleName(), SharedLibraryLabel: m.CcImplementationModuleName(), diff --git a/tradefed/autogen_bazel.go b/tradefed/autogen_bazel.go index 8283984c9..cc16176c8 100644 --- a/tradefed/autogen_bazel.go +++ b/tradefed/autogen_bazel.go @@ -49,7 +49,7 @@ type TestConfigAttributes struct { } func GetTestConfigAttributes( - ctx android.TopDownMutatorContext, + ctx android.Bp2buildMutatorContext, testConfig *string, extraTestConfigs []string, autoGenConfig *bool, @@ -93,7 +93,7 @@ func GetTestConfigAttributes( } func GetTestConfig( - ctx android.TopDownMutatorContext, + ctx android.Bp2buildMutatorContext, testConfig *string, ) *bazel.Label { diff --git a/xml/xml.go b/xml/xml.go index 20a26f562..65fe12a8e 100644 --- a/xml/xml.go +++ b/xml/xml.go @@ -145,7 +145,7 @@ type bazelPrebuiltEtcXmlAttributes struct { Schema *string } -func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) { +func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { baseAttrs, convertible := p.PrebuiltEtc.Bp2buildHelper(ctx) if !convertible { |