This patchset changes bazel_overlay to generate soong_module as a macro, instead of a rule, and generate module properties in the BUILD files as kwargs to the soong_module macro. Here's a sample of the new BUILD files with module properties: bionic/libdl/BUILD.bazel: https://paste.googleplex.com/6484466996346880?raw art/build/apex/BUILD.bazel: https://paste.googleplex.com/5461276001042432?raw bionic/apex/BUILD.bazel: https://paste.googleplex.com/4932795173437440?raw soong_module is now a macro that conditionally expands to underlying soong_<module type> rules with statically defined attributes. In this CL, we are starting with a hardcoded filegroup rule definition to demonstrate the conditional rule loading within the soong_module macro. If the module_type matches an existing Bazel rule, soong_module forwards the entire **kwargs into the rule, which Bazel typechecks. Non-filegroup module types will be expanded into generic_soong_module, but with the kwargs dropped. This approach allows us to: 1) Programmtically generate soong_<module type> rules for all module types available in Soong, together with the statically defined attribute types in `attrs`. 2) Incrementally migrate and test individual module types from generic_soong_module to their module rule shims. 3) Swap out the module rule shims to the actual Bazel rules (e.g cc_library, java_library) and perform attribute manipulation in Starlark itself. Example of querying against the 'srcs' attribute in soong_filegroup: ``` $ bazel cquery 'kind(soong_filegroup, //...)' | wc -l 590 $ bazel cquery --output=build 'attr(srcs, "linker.cpp", kind(soong_filegroup, //bionic/...))' INFO: Analyzed 3907 targets (0 packages loaded, 0 targets configured). INFO: Found 3907 targets... /usr/local/google/home/jingwen/aosp/out/soong/bazel_overlay/bionic/linker/BUILD.bazel:4144:13 soong_filegroup( name = "linker_sources", generator_name = "linker_sources", generator_function = "soong_module", generator_location = "bionic/linker/BUILD.bazel:4144:13", srcs = ["dlfcn.cpp", "linker.cpp", "linker_block_allocator.cpp", "linker_dlwarning.cpp", "linker_cfi.cpp", "linker_config.cpp", "linker_debug.cpp", "linker_gdb_support.cpp", "linker_globals.cpp", "linker_libc_support.c", "linker_libcxx_support.cpp", "linker_namespaces.cpp", "linker_logger.cpp", "linker_mapped_file_fragment.cpp", "linker_phdr.cpp", "linker_relocate.cpp", "linker_sdk_versions.cpp", "linker_soinfo.cpp", "linker_tls.cpp", "linker_utils.cpp", "rt.cpp"], deps = [], ) /usr/local/google/home/jingwen/aosp/out/soong/bazel_overlay/soong_module.bzl:32:23 in <toplevel> ``` This CL is known to be lacking the following features, and will be looked at in follow up CLs: 1) Pretty printing reflect.Interface properties, like arch, multilib and dists. 2) Generating module Bazel rule shims for all module types, instead of hardcoding them like `soong_filegroup`. Bug: 162720644 Test: bazel_overlay_test.go (soong build test) Test: m bazel_overlay && cd out/soong/bazel_overlay && bazel cquery //... Signed-off-by: Jingwen Chen <jingwen@google.com> Change-Id: Ic1e448887eb540ed15a55bc4090cf75a4d832d41
256 lines
4.6 KiB
Go
256 lines
4.6 KiB
Go
// Copyright 2020 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 main
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
var buildDir string
|
|
|
|
func setUp() {
|
|
var err error
|
|
buildDir, err = ioutil.TempDir("", "bazel_overlay_test")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func tearDown() {
|
|
os.RemoveAll(buildDir)
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
run := func() int {
|
|
setUp()
|
|
defer tearDown()
|
|
|
|
return m.Run()
|
|
}
|
|
|
|
os.Exit(run())
|
|
}
|
|
|
|
type customModule struct {
|
|
android.ModuleBase
|
|
}
|
|
|
|
func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
// nothing for now.
|
|
}
|
|
|
|
func customModuleFactory() android.Module {
|
|
module := &customModule{}
|
|
android.InitAndroidModule(module)
|
|
return module
|
|
}
|
|
|
|
func TestGenerateBazelOverlayFromBlueprint(t *testing.T) {
|
|
testCases := []struct {
|
|
bp string
|
|
expectedBazelTarget string
|
|
}{
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
ramdisk: true,
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
ramdisk = True,
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
required: ["bar"],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
required = [
|
|
"bar",
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
target_required: ["qux", "bazqux"],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
target_required = [
|
|
"qux",
|
|
"bazqux",
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
dist: {
|
|
targets: ["goal_foo"],
|
|
tag: ".foo",
|
|
},
|
|
dists: [
|
|
{
|
|
targets: ["goal_bar"],
|
|
tag: ".bar",
|
|
},
|
|
],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
dist = {
|
|
"tag": ".foo",
|
|
"targets": [
|
|
"goal_foo",
|
|
],
|
|
},
|
|
dists = [
|
|
{
|
|
"tag": ".bar",
|
|
"targets": [
|
|
"goal_bar",
|
|
],
|
|
},
|
|
],
|
|
)`,
|
|
},
|
|
{
|
|
bp: `custom {
|
|
name: "foo",
|
|
required: ["bar"],
|
|
target_required: ["qux", "bazqux"],
|
|
ramdisk: true,
|
|
owner: "custom_owner",
|
|
dists: [
|
|
{
|
|
tag: ".tag",
|
|
targets: ["my_goal"],
|
|
},
|
|
],
|
|
}
|
|
`,
|
|
expectedBazelTarget: `soong_module(
|
|
name = "foo",
|
|
module_name = "foo",
|
|
module_type = "custom",
|
|
module_variant = "",
|
|
deps = [
|
|
],
|
|
dists = [
|
|
{
|
|
"tag": ".tag",
|
|
"targets": [
|
|
"my_goal",
|
|
],
|
|
},
|
|
],
|
|
owner = "custom_owner",
|
|
ramdisk = True,
|
|
required = [
|
|
"bar",
|
|
],
|
|
target_required = [
|
|
"qux",
|
|
"bazqux",
|
|
],
|
|
)`,
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
|
|
ctx := android.NewTestContext()
|
|
ctx.RegisterModuleType("custom", customModuleFactory)
|
|
ctx.Register(config)
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
android.FailIfErrored(t, errs)
|
|
_, errs = ctx.PrepareBuildActions(config)
|
|
android.FailIfErrored(t, errs)
|
|
|
|
module := ctx.ModuleForTests("foo", "").Module().(*customModule)
|
|
blueprintCtx := ctx.Context.Context
|
|
|
|
actualBazelTarget := generateSoongModuleTarget(blueprintCtx, module)
|
|
if actualBazelTarget != testCase.expectedBazelTarget {
|
|
t.Errorf(
|
|
"Expected generated Bazel target to be '%s', got '%s'",
|
|
testCase.expectedBazelTarget,
|
|
actualBazelTarget,
|
|
)
|
|
}
|
|
}
|
|
}
|