Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d243da5 authored by Spandan Das's avatar Spandan Das Committed by Gerrit Code Review
Browse files

Merge "bp2build for ndk_headers"

parents 1f03a9f9 0773a603
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+164 −0
Original line number Diff line number Diff line
// 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},
	})
}
+68 −7
Original line number Diff line number Diff line
@@ -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,15 +329,18 @@ 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",
//
// }
//
// Will invoke the preprocessor as:
+9 −6
Original line number Diff line number Diff line
@@ -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)
}