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

Commit d3e10104 authored by Rupert Shuttleworth's avatar Rupert Shuttleworth Committed by Gerrit Code Review
Browse files

Merge "Add bp2build support for cc_library_static."

parents 958408d9 21e743df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ bootstrap_go_package {
        "build_conversion_test.go",
        "bzl_conversion_test.go",
        "cc_library_headers_conversion_test.go",
        "cc_library_static_conversion_test.go",
        "cc_object_conversion_test.go",
        "conversion_test.go",
        "python_binary_conversion_test.go",
+2 −1
Original line number Diff line number Diff line
@@ -123,7 +123,8 @@ 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"],

    // TODO: Also support export_header_lib_headers
    bazel_module: { bp2build_available: true },
}`,
			expectedBazelTargets: []string{`cc_library_headers(
+307 −0
Original line number Diff line number Diff line
// 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
	soongCcLibraryStaticPreamble = `
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 TestCcLibraryStaticLoadStatement(t *testing.T) {
	testCases := []struct {
		bazelTargets           BazelTargets
		expectedLoadStatements string
	}{
		{
			bazelTargets: BazelTargets{
				BazelTarget{
					name:      "cc_library_static_target",
					ruleClass: "cc_library_static",
					// 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 TestCcLibraryStaticBp2Build(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_static test",
			moduleTypeUnderTest:                "cc_library_static",
			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
			filesystem: map[string]string{
				// NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
				"include_dir_1/include_dir_1_a.h": "",
				"include_dir_1/include_dir_1_b.h": "",
				"include_dir_2/include_dir_2_a.h": "",
				"include_dir_2/include_dir_2_b.h": "",
				// NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?)
				"local_include_dir_1/local_include_dir_1_a.h": "",
				"local_include_dir_1/local_include_dir_1_b.h": "",
				"local_include_dir_2/local_include_dir_2_a.h": "",
				"local_include_dir_2/local_include_dir_2_b.h": "",
				// NOTE: export_include_dir headers *should* appear in Bazel hdrs later
				"export_include_dir_1/export_include_dir_1_a.h": "",
				"export_include_dir_1/export_include_dir_1_b.h": "",
				"export_include_dir_2/export_include_dir_2_a.h": "",
				"export_include_dir_2/export_include_dir_2_b.h": "",
			},
			bp: soongCcLibraryStaticPreamble + `
cc_library_headers {
    name: "header_lib_1",
    export_include_dirs: ["header_lib_1"],
}

cc_library_headers {
    name: "header_lib_2",
    export_include_dirs: ["header_lib_2"],
}

cc_library_static {
    name: "static_lib_1",
    srcs: ["static_lib_1.cc"],
    bazel_module: { bp2build_available: true },
}

cc_library_static {
    name: "static_lib_2",
    srcs: ["static_lib_2.cc"],
    bazel_module: { bp2build_available: true },
}

cc_library_static {
    name: "whole_static_lib_1",
    srcs: ["whole_static_lib_1.cc"],
    bazel_module: { bp2build_available: true },
}

cc_library_static {
    name: "whole_static_lib_2",
    srcs: ["whole_static_lib_2.cc"],
    bazel_module: { bp2build_available: true },
}

cc_library_static {
    name: "foo_static",
    srcs: [
        "foo_static1.cc",
	"foo_static2.cc",
    ],
    cflags: [
        "-Dflag1",
	"-Dflag2"
    ],
    static_libs: [
        "static_lib_1",
	"static_lib_2"
    ],
    whole_static_libs: [
        "whole_static_lib_1",
	"whole_static_lib_2"
    ],
    include_dirs: [
	"include_dir_1",
	"include_dir_2",
    ],
    local_include_dirs: [
        "local_include_dir_1",
	"local_include_dir_2",
    ],
    export_include_dirs: [
	"export_include_dir_1",
	"export_include_dir_2"
    ],
    header_libs: [
        "header_lib_1",
	"header_lib_2"
    ],

    // TODO: Also support export_header_lib_headers

    bazel_module: { bp2build_available: true },
}`,
			expectedBazelTargets: []string{`cc_library_static(
    name = "foo_static",
    copts = [
        "-Dflag1",
        "-Dflag2",
    ],
    deps = [
        ":header_lib_1",
        ":header_lib_2",
        ":static_lib_1",
        ":static_lib_2",
        ":whole_static_lib_1",
        ":whole_static_lib_2",
    ],
    hdrs = [
        "export_include_dir_1/export_include_dir_1_a.h",
        "export_include_dir_1/export_include_dir_1_b.h",
        "export_include_dir_2/export_include_dir_2_a.h",
        "export_include_dir_2/export_include_dir_2_b.h",
    ],
    includes = [
        "export_include_dir_1",
        "export_include_dir_2",
        "include_dir_1",
        "include_dir_2",
        "local_include_dir_1",
        "local_include_dir_2",
    ],
    linkstatic = True,
    srcs = [
        "foo_static1.cc",
        "foo_static2.cc",
    ],
)`, `cc_library_static(
    name = "static_lib_1",
    linkstatic = True,
    srcs = [
        "static_lib_1.cc",
    ],
)`, `cc_library_static(
    name = "static_lib_2",
    linkstatic = True,
    srcs = [
        "static_lib_2.cc",
    ],
)`, `cc_library_static(
    name = "whole_static_lib_1",
    linkstatic = True,
    srcs = [
        "whole_static_lib_1.cc",
    ],
)`, `cc_library_static(
    name = "whole_static_lib_2",
    linkstatic = True,
    srcs = [
        "whole_static_lib_2.cc",
    ],
)`},
		},
	}

	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("cc_library_headers", cc.LibraryHeaderFactory)

		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
		}
		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
		bazelTargets := generateBazelTargetsForDir(codegenCtx, 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,
					)
				}
			}
		}
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ bootstrap_go_package {
        "blueprint-pathtools",
        "soong",
        "soong-android",
        "soong-bazel",
        "soong-cc-config",
        "soong-etc",
        "soong-genrule",
+137 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import (
	"github.com/google/blueprint/pathtools"

	"android/soong/android"
	"android/soong/bazel"
	"android/soong/cc/config"
)

@@ -200,6 +201,8 @@ type FlagExporterProperties struct {

func init() {
	RegisterLibraryBuildComponents(android.InitRegistrationContext)

	android.RegisterBp2BuildMutator("cc_library_static", CcLibraryStaticBp2Build)
}

func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
@@ -2024,3 +2027,137 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu

	return outputFile
}

func Bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelList {
	var headerLibs []string
	for _, linkerProps := range module.linker.linkerProps() {
		if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
			headerLibs = baseLinkerProps.Header_libs
			// FIXME: re-export include dirs from baseLinkerProps.Export_header_lib_headers?
			break
		}
	}

	headerLibsLabels := android.BazelLabelForModuleDeps(ctx, headerLibs)
	return headerLibsLabels
}

func Bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.LabelList, bazel.LabelList) {
	libraryDecorator := module.linker.(*libraryDecorator)

	includeDirs := libraryDecorator.flagExporter.Properties.Export_system_include_dirs
	includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)

	includeDirsLabels := android.BazelLabelForModuleSrc(ctx, includeDirs)

	var includeDirGlobs []string
	for _, includeDir := range includeDirs {
		includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.h")
		includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.inc")
		includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.hpp")
	}

	headersLabels := android.BazelLabelForModuleSrc(ctx, includeDirGlobs)

	return includeDirsLabels, headersLabels
}

type bazelCcLibraryStaticAttributes struct {
	Copts      []string
	Srcs       bazel.LabelList
	Deps       bazel.LabelList
	Linkstatic bool
	Includes   bazel.LabelList
	Hdrs       bazel.LabelList
}

type bazelCcLibraryStatic struct {
	android.BazelTargetModuleBase
	bazelCcLibraryStaticAttributes
}

func BazelCcLibraryStaticFactory() android.Module {
	module := &bazelCcLibraryStatic{}
	module.AddProperties(&module.bazelCcLibraryStaticAttributes)
	android.InitBazelTargetModule(module)
	return module
}

func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) {
	module, ok := ctx.Module().(*Module)
	if !ok {
		// Not a cc module
		return
	}
	if !module.ConvertWithBp2build() {
		return
	}
	if ctx.ModuleType() != "cc_library_static" {
		return
	}

	var copts []string
	var srcs []string
	var includeDirs []string
	var localIncludeDirs []string
	for _, props := range module.compiler.compilerProps() {
		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
			copts = baseCompilerProps.Cflags
			srcs = baseCompilerProps.Srcs
			includeDirs = baseCompilerProps.Include_dirs
			localIncludeDirs = baseCompilerProps.Local_include_dirs
			break
		}
	}
	srcsLabels := android.BazelLabelForModuleSrc(ctx, srcs)

	var staticLibs []string
	var wholeStaticLibs []string
	for _, props := range module.linker.linkerProps() {
		if baseLinkerProperties, ok := props.(*BaseLinkerProperties); ok {
			staticLibs = baseLinkerProperties.Static_libs
			wholeStaticLibs = baseLinkerProperties.Whole_static_libs
			break
		}
	}

	// FIXME: Treat Static_libs and Whole_static_libs differently?
	allDeps := staticLibs
	allDeps = append(allDeps, wholeStaticLibs...)

	depsLabels := android.BazelLabelForModuleDeps(ctx, allDeps)

	// FIXME: Unify absolute vs relative paths
	// FIXME: Use -I copts instead of setting includes= ?
	allIncludes := includeDirs
	allIncludes = append(allIncludes, localIncludeDirs...)
	includesLabels := android.BazelLabelForModuleSrc(ctx, allIncludes)

	exportedIncludesLabels, exportedIncludesHeadersLabels := Bp2BuildParseExportedIncludes(ctx, module)
	includesLabels.Append(exportedIncludesLabels)

	headerLibsLabels := Bp2BuildParseHeaderLibs(ctx, module)
	depsLabels.Append(headerLibsLabels)

	attrs := &bazelCcLibraryStaticAttributes{
		Copts:      copts,
		Srcs:       bazel.UniqueBazelLabelList(srcsLabels),
		Deps:       bazel.UniqueBazelLabelList(depsLabels),
		Linkstatic: true,
		Includes:   bazel.UniqueBazelLabelList(includesLabels),
		Hdrs:       bazel.UniqueBazelLabelList(exportedIncludesHeadersLabels),
	}

	props := bazel.BazelTargetModuleProperties{
		Rule_class:        "cc_library_static",
		Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
	}

	ctx.CreateBazelTargetModule(BazelCcLibraryStaticFactory, module.Name(), props, attrs)
}

func (m *bazelCcLibraryStatic) Name() string {
	return m.BaseModuleName()
}

func (m *bazelCcLibraryStatic) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
Loading