Add bp2build support for cc_prebuilt_object
Add bp2build support for cc_prebuilt_object to allow buiiding
musl crt objects that use prebuilt clang_rt.crtbegin and
clang_rt.crtend.
Bug: 259266326
Test: //extenral/musl:libc_musl builds
Change-Id: Ic2b0375bc6e7336d31c9e2cf51bdc2ea894185aa
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 7c9af1a..2e01789 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -51,6 +51,7 @@
"cc_prebuilt_library_conversion_test.go",
"cc_prebuilt_library_shared_test.go",
"cc_prebuilt_library_static_test.go",
+ "cc_prebuilt_object_conversion_test.go",
"cc_test_conversion_test.go",
"cc_yasm_conversion_test.go",
"conversion_test.go",
diff --git a/bp2build/cc_prebuilt_object_conversion_test.go b/bp2build/cc_prebuilt_object_conversion_test.go
new file mode 100644
index 0000000..903c816
--- /dev/null
+++ b/bp2build/cc_prebuilt_object_conversion_test.go
@@ -0,0 +1,101 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package bp2build
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltObjectTestCase(t *testing.T, testCase Bp2buildTestCase) {
+ t.Helper()
+ description := fmt.Sprintf("cc_prebuilt_object: %s", testCase.Description)
+ testCase.ModuleTypeUnderTest = "cc_prebuilt_object"
+ testCase.ModuleTypeUnderTestFactory = cc.PrebuiltObjectFactory
+ testCase.Description = description
+ t.Run(description, func(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+}
+
+func TestPrebuiltObject(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "simple",
+ Filesystem: map[string]string{
+ "obj.o": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ srcs: ["obj.o"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_object", "objtest", AttrNameToString{
+ "src": `"obj.o"`,
+ })},
+ })
+}
+
+func TestPrebuiltObjectWithArchVariance(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "with arch variance",
+ Filesystem: map[string]string{
+ "obja.o": "",
+ "objb.o": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ arch: {
+ arm64: { srcs: ["obja.o"], },
+ arm: { srcs: ["objb.o"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_object", "objtest", AttrNameToString{
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "objb.o",
+ "//build/bazel/platforms/arch:arm64": "obja.o",
+ "//conditions:default": None,
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltObjectMultipleSrcsFails(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "fails because multiple sources",
+ Filesystem: map[string]string{
+ "obja": "",
+ "objb": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ srcs: ["obja.o", "objb.o"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf("Expected at most one source file"),
+ })
+}
+
+// TODO: nosrcs test
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6caa854..6ed62fc 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -337,6 +337,19 @@
}
}
+func bp2BuildParsePrebuiltObjectProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+ var srcLabelAttribute bazel.LabelAttribute
+ bp2BuildPropParseHelper(ctx, module, &prebuiltObjectProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if props, ok := props.(*prebuiltObjectProperties); ok {
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
+ }
+ })
+
+ return prebuiltAttributes{
+ Src: srcLabelAttribute,
+ }
+}
+
type baseAttributes struct {
compilerAttributes
linkerAttributes
diff --git a/cc/cc.go b/cc/cc.go
index 2ff5bba..29bb84e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3775,7 +3775,9 @@
testBinaryBp2build(ctx, c)
}
case object:
- if !prebuilt {
+ if prebuilt {
+ prebuiltObjectBp2Build(ctx, c)
+ } else {
objectBp2Build(ctx, c)
}
case fullLibrary:
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 9fbf879..45af303 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -32,7 +32,7 @@
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
- ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
+ ctx.RegisterModuleType("cc_prebuilt_object", PrebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", PrebuiltBinaryFactory)
}
@@ -572,6 +572,8 @@
func NewPrebuiltObject(hod android.HostOrDeviceSupported) *Module {
module := newObject(hod)
+ module.bazelHandler = &prebuiltObjectBazelHandler{module: module}
+ module.bazelable = true
prebuilt := &prebuiltObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
@@ -584,7 +586,55 @@
return module
}
-func prebuiltObjectFactory() android.Module {
+type prebuiltObjectBazelHandler struct {
+ module *Module
+}
+
+var _ BazelHandler = (*prebuiltObjectBazelHandler)(nil)
+
+func (h *prebuiltObjectBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (h *prebuiltObjectBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ outputs, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+ if len(outputs) != 1 {
+ ctx.ModuleErrorf("Expected a single output for `%s`, but got:\n%v", label, outputs)
+ return
+ }
+ out := android.PathForBazelOut(ctx, outputs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+ h.module.maybeUnhideFromMake()
+}
+
+type bazelPrebuiltObjectAttributes struct {
+ Src bazel.LabelAttribute
+}
+
+func prebuiltObjectBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := bp2BuildParsePrebuiltObjectProps(ctx, module)
+
+ attrs := &bazelPrebuiltObjectAttributes{
+ Src: prebuiltAttrs.Src,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_prebuilt_object",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_object.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ tags := android.ApexAvailableTags(module)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
+}
+
+func PrebuiltObjectFactory() android.Module {
module := NewPrebuiltObject(android.HostAndDeviceSupported)
return module.Init()
}