summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bp2build/Android.bp1
-rw-r--r--bp2build/ndk_headers_conversion_test.go164
-rw-r--r--cc/ndk_headers.go75
-rw-r--r--cc/ndk_sysroot.go15
4 files changed, 242 insertions, 13 deletions
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index da90f3080..3d9fc5a2b 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -64,6 +64,7 @@ bootstrap_go_package {
"java_plugin_conversion_test.go",
"java_proto_conversion_test.go",
"linker_config_conversion_test.go",
+ "ndk_headers_conversion_test.go",
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
diff --git a/bp2build/ndk_headers_conversion_test.go b/bp2build/ndk_headers_conversion_test.go
new file mode 100644
index 000000000..c7cc6b21a
--- /dev/null
+++ b/bp2build/ndk_headers_conversion_test.go
@@ -0,0 +1,164 @@
+// 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 TestNdkHeaderFilepaths(t *testing.T) {
+ bpTemplate := `
+ ndk_headers {
+ name: "foo",
+ srcs: %v,
+ exclude_srcs: %v,
+ }
+ `
+ testCases := []struct {
+ desc string
+ srcs string
+ excludeSrcs string
+ expectedHdrs string
+ }{
+ {
+ desc: "Single header file",
+ srcs: `["foo.h"]`,
+ excludeSrcs: `[]`,
+ expectedHdrs: `["foo.h"]`,
+ },
+ {
+ desc: "Multiple header files",
+ srcs: `["foo.h", "foo_other.h"]`,
+ excludeSrcs: `[]`,
+ expectedHdrs: `[
+ "foo.h",
+ "foo_other.h",
+ ]`,
+ },
+ {
+ desc: "Multiple header files with excludes",
+ srcs: `["foo.h", "foo_other.h"]`,
+ excludeSrcs: `["foo_other.h"]`,
+ expectedHdrs: `["foo.h"]`,
+ },
+ {
+ desc: "Multiple header files via Soong-supported globs",
+ srcs: `["*.h"]`,
+ excludeSrcs: `[]`,
+ expectedHdrs: `[
+ "foo.h",
+ "foo_other.h",
+ ]`,
+ },
+ }
+ for _, testCase := range testCases {
+ fs := map[string]string{
+ "foo.h": "",
+ "foo_other.h": "",
+ }
+ expectedApiContributionTargetName := "foo.contribution"
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_headers",
+ expectedApiContributionTargetName,
+ AttrNameToString{
+ "hdrs": testCase.expectedHdrs,
+ },
+ )
+ RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Description: testCase.desc,
+ Blueprint: fmt.Sprintf(bpTemplate, testCase.srcs, testCase.excludeSrcs),
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ Filesystem: fs,
+ })
+ }
+}
+
+func TestNdkHeaderIncludeDir(t *testing.T) {
+ bpTemplate := `
+ ndk_headers {
+ name: "foo",
+ from: %v,
+ to: "this/value/is/ignored",
+ }
+ `
+ testCases := []struct {
+ desc string
+ from string
+ expectedIncludeDir string
+ }{
+ {
+ desc: "Empty `from` value",
+ from: `""`,
+ expectedIncludeDir: `""`,
+ },
+ {
+ desc: "Non-Empty `from` value",
+ from: `"include"`,
+ expectedIncludeDir: `"include"`,
+ },
+ }
+ for _, testCase := range testCases {
+ expectedApiContributionTargetName := "foo.contribution"
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_headers",
+ expectedApiContributionTargetName,
+ AttrNameToString{
+ "include_dir": testCase.expectedIncludeDir,
+ },
+ )
+ RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Description: testCase.desc,
+ Blueprint: fmt.Sprintf(bpTemplate, testCase.from),
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+ }
+}
+
+func TestVersionedNdkHeaderFilepaths(t *testing.T) {
+ bp := `
+ versioned_ndk_headers {
+ name: "common_libc",
+ from: "include"
+ }
+ `
+ fs := map[string]string{
+ "include/math.h": "",
+ "include/stdio.h": "",
+ "include/arm/arm.h": "",
+ "include/x86/x86.h": "",
+ }
+ expectedApiContributionTargetName := "common_libc.contribution"
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_headers",
+ expectedApiContributionTargetName,
+ AttrNameToString{
+ "include_dir": `"include"`,
+ "hdrs": `[
+ "include/math.h",
+ "include/stdio.h",
+ "include/arm/arm.h",
+ "include/x86/x86.h",
+ ]`,
+ },
+ )
+ RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ Filesystem: fs,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index ef38a064a..5e0694880 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -19,8 +19,10 @@ import (
"path/filepath"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
)
var (
@@ -79,6 +81,7 @@ type headerProperties struct {
type headerModule struct {
android.ModuleBase
+ android.BazelModuleBase
properties headerProperties
@@ -144,6 +147,47 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
+const (
+ apiContributionSuffix = ".contribution"
+)
+
+// apiContributionTargetName returns the name of the cc_api(headers|contribution) bp2build target of ndk modules
+// A suffix is necessary to prevent a name collision with the base ndk_(library|header) target in the same bp2build bazel package
+func apiContributionTargetName(moduleName string) string {
+ return moduleName + apiContributionSuffix
+}
+
+// TODO(b/243196151): Populate `system` and `arch` metadata
+type bazelCcApiHeadersAttributes struct {
+ Hdrs bazel.LabelListAttribute
+ Include_dir *string
+}
+
+func createCcApiHeadersTarget(ctx android.TopDownMutatorContext, includes []string, excludes []string, include_dir *string) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_headers",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ attrs := &bazelCcApiHeadersAttributes{
+ Hdrs: bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrcExcludes(
+ ctx,
+ includes,
+ excludes,
+ ),
+ ),
+ Include_dir: include_dir,
+ }
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: apiContributionTargetName(ctx.ModuleName()),
+ }, attrs)
+}
+
+func (h *headerModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // Generate `cc_api_headers` target for Multi-tree API export
+ createCcApiHeadersTarget(ctx, h.properties.Srcs, h.properties.Exclude_srcs, h.properties.From)
+}
+
// 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:
@@ -158,6 +202,7 @@ func ndkHeadersFactory() android.Module {
module := &headerModule{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
+ android.InitBazelModule(module)
return module
}
@@ -190,6 +235,7 @@ type versionedHeaderProperties struct {
// Note that this is really only built to handle bionic/libc/include.
type versionedHeaderModule struct {
android.ModuleBase
+ android.BazelModuleBase
properties versionedHeaderProperties
@@ -197,6 +243,11 @@ type versionedHeaderModule struct {
licensePath android.Path
}
+// Return the glob pattern to find all .h files beneath `dir`
+func headerGlobPattern(dir string) string {
+ return filepath.Join(dir, "**", "*.h")
+}
+
func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if String(m.properties.License) == "" {
ctx.PropertyErrorf("license", "field is required")
@@ -206,7 +257,7 @@ 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(filepath.Join(fromSrcPath.String(), "**/*.h"), nil)
+ srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
var installPaths []android.WritablePath
for _, header := range srcFiles {
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
@@ -222,6 +273,13 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo
processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
}
+func (h *versionedHeaderModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // Glob all .h files under `From`
+ includePattern := headerGlobPattern(proptools.String(h.properties.From))
+ // Generate `cc_api_headers` target for Multi-tree API export
+ createCcApiHeadersTarget(ctx, []string{includePattern}, []string{}, h.properties.From)
+}
+
func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
srcFiles android.Paths, installPaths []android.WritablePath) android.Path {
// The versioner depends on a dependencies directory to simplify determining include paths
@@ -271,16 +329,19 @@ func versionedNdkHeadersFactory() android.Module {
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
+ android.InitBazelModule(module)
return module
}
-// preprocessed_ndk_header {
-// name: "foo",
-// preprocessor: "foo.sh",
-// srcs: [...],
-// to: "android",
-// }
+// preprocessed_ndk_header {
+//
+// name: "foo",
+// preprocessor: "foo.sh",
+// srcs: [...],
+// to: "android",
+//
+// }
//
// Will invoke the preprocessor as:
//
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 6c200f5dd..622558edf 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -57,15 +57,18 @@ import (
)
func init() {
- android.RegisterModuleType("ndk_headers", ndkHeadersFactory)
- android.RegisterModuleType("ndk_library", NdkLibraryFactory)
- android.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory)
- android.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory)
- android.RegisterSingletonType("ndk", NdkSingleton)
-
+ RegisterNdkModuleTypes(android.InitRegistrationContext)
pctx.Import("android/soong/android")
}
+func RegisterNdkModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
+ ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
+ ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory)
+ ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory)
+ ctx.RegisterSingletonType("ndk", NdkSingleton)
+}
+
func getNdkInstallBase(ctx android.PathContext) android.InstallPath {
return android.PathForNdkInstall(ctx)
}