Merge "bp2build: cc_object converter."

This commit is contained in:
Jingwen Chen
2021-02-19 03:54:43 +00:00
committed by Gerrit Code Review
7 changed files with 269 additions and 9 deletions

View File

@@ -22,7 +22,8 @@ bootstrap_go_package {
testSrcs: [ testSrcs: [
"build_conversion_test.go", "build_conversion_test.go",
"bzl_conversion_test.go", "bzl_conversion_test.go",
"cc_conversion_test.go", "cc_library_headers_conversion_test.go",
"cc_object_conversion_test.go",
"conversion_test.go", "conversion_test.go",
"sh_conversion_test.go", "sh_conversion_test.go",
"testing.go", "testing.go",

View File

@@ -0,0 +1,186 @@
// Copyright 2021 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bp2build
import (
"android/soong/android"
"android/soong/cc"
"fmt"
"strings"
"testing"
)
func TestCcObjectBp2Build(t *testing.T) {
testCases := []struct {
description string
moduleTypeUnderTest string
moduleTypeUnderTestFactory android.ModuleFactory
moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
blueprint string
expectedBazelTargets []string
filesystem map[string]string
}{
{
description: "simple cc_object generates cc_object with include header dep",
moduleTypeUnderTest: "cc_object",
moduleTypeUnderTestFactory: cc.ObjectFactory,
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
filesystem: map[string]string{
"a/b/foo.h": "",
"a/b/bar.h": "",
"a/b/c.c": "",
},
blueprint: `cc_object {
name: "foo",
local_include_dirs: ["include"],
cflags: [
"-Wno-gcc-compat",
"-Wall",
"-Werror",
],
srcs: [
"a/b/*.h",
"a/b/c.c"
],
bazel_module: { bp2build_available: true },
}
`,
expectedBazelTargets: []string{`cc_object(
name = "foo",
copts = [
"-fno-addrsig",
"-Wno-gcc-compat",
"-Wall",
"-Werror",
],
local_include_dirs = [
"include",
],
srcs = [
"a/b/bar.h",
"a/b/foo.h",
"a/b/c.c",
],
)`,
},
},
{
description: "simple cc_object with defaults",
moduleTypeUnderTest: "cc_object",
moduleTypeUnderTestFactory: cc.ObjectFactory,
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
local_include_dirs: ["include"],
srcs: [
"a/b/*.h",
"a/b/c.c"
],
defaults: ["foo_defaults"],
bazel_module: { bp2build_available: true },
}
cc_defaults {
name: "foo_defaults",
defaults: ["foo_bar_defaults"],
// TODO(b/178130668): handle configurable attributes that depend on the platform
arch: {
x86: {
cflags: ["-fPIC"],
},
x86_64: {
cflags: ["-fPIC"],
},
},
}
cc_defaults {
name: "foo_bar_defaults",
cflags: [
"-Wno-gcc-compat",
"-Wall",
"-Werror",
],
}
`,
expectedBazelTargets: []string{`cc_object(
name = "foo",
copts = [
"-Wno-gcc-compat",
"-Wall",
"-Werror",
"-fno-addrsig",
],
local_include_dirs = [
"include",
],
srcs = [
"a/b/c.c",
],
)`,
},
},
}
dir := "."
for _, testCase := range testCases {
filesystem := make(map[string][]byte)
toParse := []string{
"Android.bp",
}
for f, content := range testCase.filesystem {
if strings.HasSuffix(f, "Android.bp") {
toParse = append(toParse, f)
}
filesystem[f] = []byte(content)
}
config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
ctx := android.NewTestContext(config)
// Always register cc_defaults module factory
ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
if Errored(t, testCase.description, errs) {
continue
}
_, errs = ctx.ResolveDependencies(config)
if Errored(t, testCase.description, errs) {
continue
}
bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
fmt.Println(bazelTargets)
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
} else {
for i, target := range bazelTargets {
if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
t.Errorf(
"%s: Expected generated Bazel target to be '%s', got '%s'",
testCase.description,
w,
g,
)
}
}
}
}
}

View File

@@ -28,6 +28,7 @@ import (
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
"android/soong/android" "android/soong/android"
"android/soong/bazel"
"android/soong/cc/config" "android/soong/cc/config"
"android/soong/genrule" "android/soong/genrule"
) )
@@ -364,6 +365,8 @@ type BaseProperties struct {
// can depend on libraries that are not exported by the APEXes and use private symbols // can depend on libraries that are not exported by the APEXes and use private symbols
// from the exported libraries. // from the exported libraries.
Test_for []string Test_for []string
bazel.Properties
} }
type VendorProperties struct { type VendorProperties struct {

View File

@@ -27,7 +27,6 @@ import (
"github.com/google/blueprint/pathtools" "github.com/google/blueprint/pathtools"
"android/soong/android" "android/soong/android"
"android/soong/bazel"
"android/soong/cc/config" "android/soong/cc/config"
) )
@@ -121,9 +120,6 @@ type LibraryProperties struct {
// If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from // If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from
// the module pointed to by llndk_stubs if it is set. // the module pointed to by llndk_stubs if it is set.
Llndk llndkLibraryProperties Llndk llndkLibraryProperties
// Properties for Bazel migration purposes.
bazel.Properties
} }
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a // StaticProperties is a properties stanza to affect only attributes of the "static" variants of a

View File

@@ -86,6 +86,10 @@ func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
return return
} }
if !module.Properties.Bazel_module.Bp2build_available {
return
}
lib, ok := module.linker.(*libraryDecorator) lib, ok := module.linker.(*libraryDecorator)
if !ok { if !ok {
// Not a cc_library module // Not a cc_library module
@@ -96,10 +100,6 @@ func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
return return
} }
if !lib.Properties.Bazel_module.Bp2build_available {
return
}
// list of directories that will be added to the include path (using -I) for this // list of directories that will be added to the include path (using -I) for this
// module and any module that links against this module. // module and any module that links against this module.
includeDirs := lib.flagExporter.Properties.Export_system_include_dirs includeDirs := lib.flagExporter.Properties.Export_system_include_dirs

View File

@@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"android/soong/android" "android/soong/android"
"android/soong/bazel"
) )
// //
@@ -27,6 +28,8 @@ import (
func init() { func init() {
android.RegisterModuleType("cc_object", ObjectFactory) android.RegisterModuleType("cc_object", ObjectFactory)
android.RegisterSdkMemberType(ccObjectSdkMemberType) android.RegisterSdkMemberType(ccObjectSdkMemberType)
android.RegisterBp2BuildMutator("cc_object", ObjectBp2Build)
} }
var ccObjectSdkMemberType = &librarySdkMemberType{ var ccObjectSdkMemberType = &librarySdkMemberType{
@@ -82,9 +85,80 @@ func ObjectFactory() android.Module {
module.compiler.appendCflags([]string{"-fno-addrsig"}) module.compiler.appendCflags([]string{"-fno-addrsig"})
module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType} module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType}
return module.Init() return module.Init()
} }
// For bp2build conversion.
type bazelObjectAttributes struct {
Srcs bazel.LabelList
Copts []string
Local_include_dirs []string
}
type bazelObject struct {
android.BazelTargetModuleBase
bazelObjectAttributes
}
func (m *bazelObject) Name() string {
return m.BaseModuleName()
}
func (m *bazelObject) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
func BazelObjectFactory() android.Module {
module := &bazelObject{}
module.AddProperties(&module.bazelObjectAttributes)
android.InitBazelTargetModule(module)
return module
}
// 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, ok := ctx.Module().(*Module)
if !ok || !m.Properties.Bazel_module.Bp2build_available {
return
}
// a Module can be something other than a cc_object.
if ctx.ModuleType() != "cc_object" {
return
}
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")
}
var copts []string
var srcs []string
var localIncludeDirs []string
for _, props := range m.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
copts = baseCompilerProps.Cflags
srcs = baseCompilerProps.Srcs
localIncludeDirs = baseCompilerProps.Local_include_dirs
break
}
}
attrs := &bazelObjectAttributes{
Srcs: android.BazelLabelForModuleSrc(ctx, srcs),
Copts: copts,
Local_include_dirs: localIncludeDirs,
}
props := bazel.NewBazelTargetModuleProperties(
m.Name(),
"cc_object",
"//build/bazel/rules:cc_object.bzl",
)
ctx.CreateBazelTargetModule(BazelObjectFactory, props, attrs)
}
func (object *objectLinker) appendLdflags(flags []string) { func (object *objectLinker) appendLdflags(flags []string) {
panic(fmt.Errorf("appendLdflags on objectLinker not supported")) panic(fmt.Errorf("appendLdflags on objectLinker not supported"))
} }