Add cc_library_headers support to bp2build.

Test: Added cc_conversion_test.go.
Change-Id: Id4459d2c2fa02687a374cd9fb25d687e9678218c
This commit is contained in:
Rupert Shuttleworth 2021-02-15 11:04:32 +00:00
parent 36eb24b3ab
commit 54e7841b90
4 changed files with 316 additions and 1 deletions

View File

@ -15,12 +15,14 @@ bootstrap_go_package {
deps: [
"soong-android",
"soong-bazel",
"soong-cc",
"soong-genrule",
"soong-sh",
],
testSrcs: [
"build_conversion_test.go",
"bzl_conversion_test.go",
"cc_conversion_test.go",
"conversion_test.go",
"testing.go",
],

View File

@ -0,0 +1,221 @@
// 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"
"strings"
"testing"
)
const (
// See cc/testing.go for more context
soongCcLibraryPreamble = `
cc_defaults {
name: "linux_bionic_supported",
}
toolchain_library {
name: "libclang_rt.builtins-x86_64-android",
defaults: ["linux_bionic_supported"],
vendor_available: true,
vendor_ramdisk_available: true,
product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
}
toolchain_library {
name: "libatomic",
defaults: ["linux_bionic_supported"],
vendor_available: true,
vendor_ramdisk_available: true,
product_available: true,
recovery_available: true,
native_bridge_supported: true,
src: "",
}`
)
func TestCcLibraryHeadersLoadStatement(t *testing.T) {
testCases := []struct {
bazelTargets BazelTargets
expectedLoadStatements string
}{
{
bazelTargets: BazelTargets{
BazelTarget{
name: "cc_library_headers_target",
ruleClass: "cc_library_headers",
// Note: no bzlLoadLocation for native rules
},
},
expectedLoadStatements: ``,
},
}
for _, testCase := range testCases {
actual := testCase.bazelTargets.LoadStatements()
expected := testCase.expectedLoadStatements
if actual != expected {
t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
}
}
}
func TestCcLibraryHeadersBp2Build(t *testing.T) {
testCases := []struct {
description string
moduleTypeUnderTest string
moduleTypeUnderTestFactory android.ModuleFactory
moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
preArchMutators []android.RegisterMutatorFunc
depsMutators []android.RegisterMutatorFunc
bp string
expectedBazelTargets []string
filesystem map[string]string
dir string
}{
{
description: "cc_library_headers test",
moduleTypeUnderTest: "cc_library_headers",
moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
filesystem: map[string]string{
"lib-1/lib1a.h": "",
"lib-1/lib1b.h": "",
"lib-2/lib2a.h": "",
"lib-2/lib2b.h": "",
"dir-1/dir1a.h": "",
"dir-1/dir1b.h": "",
"dir-2/dir2a.h": "",
"dir-2/dir2b.h": "",
},
bp: soongCcLibraryPreamble + `
cc_library_headers {
name: "lib-1",
export_include_dirs: ["lib-1"],
bazel_module: { bp2build_available: true },
}
cc_library_headers {
name: "lib-2",
export_include_dirs: ["lib-2"],
bazel_module: { bp2build_available: true },
}
cc_library_headers {
name: "foo_headers",
export_include_dirs: ["dir-1", "dir-2"],
header_libs: ["lib-1", "lib-2"],
export_header_lib_headers: ["lib-1", "lib-2"],
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "foo_headers",
deps = [
":lib-1",
":lib-2",
],
hdrs = [
"dir-1/dir1a.h",
"dir-1/dir1b.h",
"dir-2/dir2a.h",
"dir-2/dir2b.h",
],
includes = [
"dir-1",
"dir-2",
],
)`, `cc_library_headers(
name = "lib-1",
hdrs = [
"lib-1/lib1a.h",
"lib-1/lib1b.h",
],
includes = [
"lib-1",
],
)`, `cc_library_headers(
name = "lib-2",
hdrs = [
"lib-2/lib2a.h",
"lib-2/lib2b.h",
],
includes = [
"lib-2",
],
)`},
},
}
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.bp, filesystem)
ctx := android.NewTestContext(config)
cc.RegisterCCBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
for _, m := range testCase.depsMutators {
ctx.DepsBp2BuildMutators(m)
}
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
}
checkDir := dir
if testCase.dir != "" {
checkDir = testCase.dir
}
bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
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

@ -27,6 +27,7 @@ import (
"github.com/google/blueprint/pathtools"
"android/soong/android"
"android/soong/bazel"
"android/soong/cc/config"
)
@ -120,6 +121,9 @@ type LibraryProperties struct {
// 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.
Llndk llndkLibraryProperties
// Properties for Bazel migration purposes.
bazel.Properties
}
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a

View File

@ -14,13 +14,18 @@
package cc
import "android/soong/android"
import (
"android/soong/android"
"android/soong/bazel"
)
func init() {
RegisterLibraryHeadersBuildComponents(android.InitRegistrationContext)
// Register sdk member types.
android.RegisterSdkMemberType(headersLibrarySdkMemberType)
android.RegisterBp2BuildMutator("cc_library_headers", CcLibraryHeadersBp2Build)
}
var headersLibrarySdkMemberType = &librarySdkMemberType{
@ -55,3 +60,86 @@ func prebuiltLibraryHeaderFactory() android.Module {
library.HeaderOnly()
return module.Init()
}
type bazelCcLibraryHeadersAttributes struct {
Hdrs bazel.LabelList
Includes bazel.LabelList
Deps bazel.LabelList
}
type bazelCcLibraryHeaders struct {
android.BazelTargetModuleBase
bazelCcLibraryHeadersAttributes
}
func BazelCcLibraryHeadersFactory() android.Module {
module := &bazelCcLibraryHeaders{}
module.AddProperties(&module.bazelCcLibraryHeadersAttributes)
android.InitBazelTargetModule(module)
return module
}
func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
module, ok := ctx.Module().(*Module)
if !ok {
// Not a cc module
return
}
lib, ok := module.linker.(*libraryDecorator)
if !ok {
// Not a cc_library module
return
}
if !lib.header() {
// Not a cc_library_headers module
return
}
if !lib.Properties.Bazel_module.Bp2build_available {
return
}
// list of directories that will be added to the include path (using -I) for this
// module and any module that links against this module.
includeDirs := lib.flagExporter.Properties.Export_system_include_dirs
includeDirs = append(includeDirs, lib.flagExporter.Properties.Export_include_dirs...)
includeDirLabels := android.BazelLabelForModuleSrc(ctx, includeDirs)
var includeDirGlobs []string
for _, includeDir := range includeDirs {
includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.h")
}
headerLabels := android.BazelLabelForModuleSrc(ctx, includeDirGlobs)
// list of modules that should only provide headers for this module.
var headerLibs []string
for _, linkerProps := range lib.linkerProps() {
if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
headerLibs = baseLinkerProps.Export_header_lib_headers
break
}
}
headerLibLabels := android.BazelLabelForModuleDeps(ctx, headerLibs)
attrs := &bazelCcLibraryHeadersAttributes{
Includes: includeDirLabels,
Hdrs: headerLabels,
Deps: headerLibLabels,
}
props := bazel.NewBazelTargetModuleProperties(
module.Name(),
"cc_library_headers",
"//build/bazel/rules:cc_library_headers.bzl",
)
ctx.CreateBazelTargetModule(BazelCcLibraryHeadersFactory, props, attrs)
}
func (m *bazelCcLibraryHeaders) Name() string {
return m.BaseModuleName()
}
func (m *bazelCcLibraryHeaders) GenerateAndroidBuildActions(ctx android.ModuleContext) {}