Merge changes from topic "notice"

* changes:
  Implement bp2build for the `package` module
  Implement bp2build for the `license_kind` module
  Implement bp2build for the `license` module
  Handle nameless modules during bp2build conversion.
This commit is contained in:
Alexander Smundak 2022-09-16 23:22:07 +00:00 committed by Gerrit Code Review
commit efc64e3a03
14 changed files with 399 additions and 21 deletions

View file

@ -37,6 +37,7 @@ const (
var (
Bp2buildDefaultConfig = Bp2BuildConfig{
"art": Bp2BuildDefaultTrue,
"art/libartbase": Bp2BuildDefaultTrueRecursively,
"art/libartpalette": Bp2BuildDefaultTrueRecursively,
"art/libdexfile": Bp2BuildDefaultTrueRecursively,
@ -54,6 +55,7 @@ var (
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
"build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
"build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
"build/soong/licenses": Bp2BuildDefaultTrue,
"build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
"build/soong/scripts": Bp2BuildDefaultTrueRecursively,
@ -98,6 +100,7 @@ var (
"external/aac": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
"external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto": Bp2BuildDefaultTrue,
"external/auto/common": Bp2BuildDefaultTrueRecursively,
"external/auto/service": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
@ -234,6 +237,7 @@ var (
"prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
"prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
"prebuilts/sdk/current/support": Bp2BuildDefaultTrue,
"prebuilts/tools": Bp2BuildDefaultTrue,
"prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
@ -275,6 +279,7 @@ var (
"system/libprocinfo": Bp2BuildDefaultTrue,
"system/libziparchive": Bp2BuildDefaultTrueRecursively,
"system/logging": Bp2BuildDefaultTrueRecursively,
"system/media": Bp2BuildDefaultTrue,
"system/media/audio": Bp2BuildDefaultTrueRecursively,
"system/media/audio_utils": Bp2BuildDefaultTrueRecursively,
"system/memory/libion": Bp2BuildDefaultTrueRecursively,
@ -306,6 +311,7 @@ var (
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
"external/bazelbuild-rules_android":/* recursive = */ true,
"external/bazelbuild-rules_license":/* recursive = */ true,
"external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
"external/guava":/* recursive = */ true,
@ -494,6 +500,7 @@ var (
}
Bp2buildModuleTypeAlwaysConvertList = []string{
"license",
"linker_config",
"java_import",
"java_import_host",

View file

@ -15,7 +15,10 @@
package android
import (
"android/soong/bazel"
"fmt"
"github.com/google/blueprint"
"os"
)
type licenseKindDependencyTag struct {
@ -48,14 +51,55 @@ type licenseProperties struct {
Visibility []string
}
var _ Bazelable = &licenseModule{}
type licenseModule struct {
ModuleBase
DefaultableModuleBase
SdkBase
BazelModuleBase
properties licenseProperties
}
type bazelLicenseAttributes struct {
License_kinds []string
Copyright_notice *string
License_text bazel.LabelAttribute
Package_name *string
Visibility []string
}
func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
attrs := &bazelLicenseAttributes{
License_kinds: m.properties.License_kinds,
Copyright_notice: m.properties.Copyright_notice,
Package_name: m.properties.Package_name,
Visibility: m.properties.Visibility,
}
// TODO(asmundak): Soong supports multiple license texts while Bazel's license
// rule does not. Have android_license create a genrule to concatenate multiple
// license texts.
if len(m.properties.License_text) > 1 && ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
fmt.Fprintf(os.Stderr, "warning: using only the first license_text item from //%s:%s\n",
ctx.ModuleDir(), m.Name())
}
if len(m.properties.License_text) >= 1 {
attrs.License_text.SetValue(BazelLabelForModuleSrcSingle(ctx, m.properties.License_text[0]))
}
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "android_license",
Bzl_load_location: "//build/bazel/rules/license:license.bzl",
},
CommonAttributes{
Name: m.Name(),
},
attrs)
}
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
}
@ -78,7 +122,7 @@ func LicenseFactory() Module {
module := &licenseModule{}
base := module.base()
module.AddProperties(&base.nameProperties, &module.properties)
module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
@ -86,6 +130,7 @@ func LicenseFactory() Module {
InitSdkAwareModule(module)
initAndroidModuleBase(module)
InitDefaultableModule(module)
InitBazelModule(module)
return module
}

View file

@ -14,6 +14,8 @@
package android
import "android/soong/bazel"
func init() {
RegisterLicenseKindBuildComponents(InitRegistrationContext)
}
@ -32,13 +34,39 @@ type licenseKindProperties struct {
Visibility []string
}
var _ Bazelable = &licenseKindModule{}
type licenseKindModule struct {
ModuleBase
DefaultableModuleBase
BazelModuleBase
properties licenseKindProperties
}
type bazelLicenseKindAttributes struct {
Conditions []string
Url string
Visibility []string
}
func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
attrs := &bazelLicenseKindAttributes{
Conditions: m.properties.Conditions,
Url: m.properties.Url,
Visibility: m.properties.Visibility,
}
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "license_kind",
Bzl_load_location: "@rules_license//rules:license_kind.bzl",
},
CommonAttributes{
Name: m.Name(),
},
attrs)
}
func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
// Nothing to do.
}
@ -51,13 +79,14 @@ func LicenseKindFactory() Module {
module := &licenseKindModule{}
base := module.base()
module.AddProperties(&base.nameProperties, &module.properties)
module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
initAndroidModuleBase(module)
InitDefaultableModule(module)
InitBazelModule(module)
return module
}

View file

@ -1169,7 +1169,9 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator
mod := ctx.Module().base()
// Assert passed-in attributes include Name
if len(attrs.Name) == 0 {
ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
if ctx.ModuleType() != "package" {
ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
}
}
depsToLabelList := func(deps []string) bazel.LabelListAttribute {

View file

@ -15,6 +15,7 @@
package android
import (
"android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@ -37,12 +38,33 @@ type packageProperties struct {
Default_applicable_licenses []string
}
type bazelPackageAttributes struct {
Default_visibility []string
Default_applicable_licenses bazel.LabelListAttribute
}
type packageModule struct {
ModuleBase
BazelModuleBase
properties packageProperties
}
var _ Bazelable = &packageModule{}
func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "package",
},
CommonAttributes{},
&bazelPackageAttributes{
Default_applicable_licenses: bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses)),
// FIXME(asmundak): once b/221436821 is resolved
Default_visibility: []string{"//visibility:public"},
})
}
func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
// Nothing to do.
}
@ -59,7 +81,7 @@ func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModule
func PackageFactory() Module {
module := &packageModule{}
module.AddProperties(&module.properties)
module.AddProperties(&module.properties, &module.commonProperties.BazelConversionStatus)
// The name is the relative path from build root to the directory containing this
// module. Set that name at the earliest possible moment that information is available
@ -76,5 +98,7 @@ func PackageFactory() Module {
// its checking and parsing phases so make it the primary licenses property.
setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
InitBazelModule(module)
return module
}

View file

@ -63,8 +63,11 @@ bootstrap_go_package {
"java_library_host_conversion_test.go",
"java_plugin_conversion_test.go",
"java_proto_conversion_test.go",
"license_conversion_test.go",
"license_kind_conversion_test.go",
"linker_config_conversion_test.go",
"ndk_headers_conversion_test.go",
"package_conversion_test.go",
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",

View file

@ -23,7 +23,7 @@ load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module")
// A macro call in the BUILD file representing a Soong module, with space
// for expanding more attributes.
soongModuleTarget = `soong_module(
soongModuleTargetTemplate = `soong_module(
name = "%s",
soong_module_name = "%s",
soong_module_type = "%s",
@ -31,10 +31,13 @@ load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module")
soong_module_deps = %s,
%s)`
bazelTarget = `%s(
ruleTargetTemplate = `%s(
name = "%s",
%s)`
unnamedRuleTargetTemplate = `%s(
%s)`
// A simple provider to mark and differentiate Soong module rule shims from
// regular Bazel rules. Every Soong module rule shim returns a
// SoongModuleInfo provider, and can only depend on rules returning

View file

@ -64,7 +64,16 @@ func (t BazelTarget) Label() string {
// BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget
// sort a list of BazelTargets in-place by name
func (targets BazelTargets) packageRule() *BazelTarget {
for _, target := range targets {
if target.ruleClass == "package" {
return &target
}
}
return nil
}
// sort a list of BazelTargets in-place, by name, and by generated/handcrafted types.
func (targets BazelTargets) sort() {
sort.Slice(targets, func(i, j int) bool {
return targets[i].name < targets[j].name
@ -77,7 +86,9 @@ func (targets BazelTargets) sort() {
func (targets BazelTargets) String() string {
var res string
for i, target := range targets {
res += target.content
if target.ruleClass != "package" {
res += target.content
}
if i != len(targets)-1 {
res += "\n\n"
}
@ -391,18 +402,19 @@ func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) (BazelTarget, e
// Return the Bazel target with rule class and attributes, ready to be
// code-generated.
attributes := propsToAttributes(props.Attrs)
var content string
targetName := m.TargetName()
if targetName != "" {
content = fmt.Sprintf(ruleTargetTemplate, ruleClass, targetName, attributes)
} else {
content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
}
return BazelTarget{
name: targetName,
packageName: m.TargetPackage(),
ruleClass: ruleClass,
bzlLoadLocation: bzlLoadLocation,
content: fmt.Sprintf(
bazelTarget,
ruleClass,
targetName,
attributes,
),
content: content,
}, nil
}
@ -436,7 +448,7 @@ func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) (BazelT
return BazelTarget{
name: targetName,
content: fmt.Sprintf(
soongModuleTarget,
soongModuleTargetTemplate,
targetName,
ctx.ModuleName(m),
canonicalizeModuleType(ctx.ModuleType(m)),

View file

@ -96,10 +96,14 @@ func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode)
# This file was automatically generated by bp2build for the Bazel migration project.
# Feel free to edit or test it, but do *not* check it into your version control system.
`
// Hardcode the default visibility.
content += "package(default_visibility = [\"//visibility:public\"])\n"
content += targets.LoadStatements()
content += "\n\n"
// Get package rule from the handcrafted BUILD file, otherwise emit the default one.
prText := "package(default_visibility = [\"//visibility:public\"])\n"
if pr := targets.packageRule(); pr != nil {
prText = pr.content
}
content += prText
} else if mode == QueryView {
content = soongModuleLoad
}
@ -160,7 +164,7 @@ func shouldSkipStructField(field reflect.StructField) bool {
// internal to Soong only, and these fields do not have PkgPath.
return true
}
// fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc
// fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc.
// but cannot be set in a .bp file
if proptools.HasTag(field, "blueprint", "mutated") {
return true

View file

@ -0,0 +1,81 @@
// 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 (
"android/soong/android"
"testing"
)
func registerLicenseModuleTypes(_ android.RegistrationContext) {}
func TestLicenseBp2Build(t *testing.T) {
tests := []struct {
description string
module string
expected ExpectedRuleTarget
}{
{
description: "license kind and text notice",
module: `
license {
name: "my_license",
license_kinds: [ "SPDX-license-identifier-Apache-2.0"],
license_text: [ "NOTICE"],
}`,
expected: ExpectedRuleTarget{
"android_license",
"my_license",
AttrNameToString{
"license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
"license_text": `"NOTICE"`,
},
android.HostAndDeviceDefault,
},
},
{
description: "visibility, package_name, copyright_notice",
module: `
license {
name: "my_license",
package_name: "my_package",
visibility: [":__subpackages__"],
copyright_notice: "Copyright © 2022",
}`,
expected: ExpectedRuleTarget{
"android_license",
"my_license",
AttrNameToString{
"copyright_notice": `"Copyright © 2022"`,
"package_name": `"my_package"`,
"visibility": `[":__subpackages__"]`,
},
android.HostAndDeviceDefault,
},
},
}
for _, test := range tests {
RunBp2BuildTestCase(t,
registerLicenseModuleTypes,
Bp2buildTestCase{
Description: test.description,
ModuleTypeUnderTest: "license",
ModuleTypeUnderTestFactory: android.LicenseFactory,
Blueprint: test.module,
ExpectedBazelTargets: []string{test.expected.String()},
})
}
}

View file

@ -0,0 +1,69 @@
// 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 (
"android/soong/android"
"testing"
)
func registerLicenseKindModuleTypes(_ android.RegistrationContext) {}
func TestLicenseKindBp2Build(t *testing.T) {
tests := []struct {
description string
module string
expected ExpectedRuleTarget
}{
{
description: "license_kind",
module: `
license_kind {
name: "my_license",
conditions: [
"by_exception_only",
"not_allowed",
],
url: "https://spdx.org/licenses/0BSD",
visibility: ["//visibility:public"],
}`,
expected: ExpectedRuleTarget{
"license_kind",
"my_license",
AttrNameToString{
"conditions": `[
"by_exception_only",
"not_allowed",
]`,
"url": `"https://spdx.org/licenses/0BSD"`,
"visibility": `["//visibility:public"]`,
},
android.HostAndDeviceDefault,
},
},
}
for _, test := range tests {
RunBp2BuildTestCase(t,
registerLicenseKindModuleTypes,
Bp2buildTestCase{
Description: test.description,
ModuleTypeUnderTest: "license_kind",
ModuleTypeUnderTestFactory: android.LicenseKindFactory,
Blueprint: test.module,
ExpectedBazelTargets: []string{test.expected.String()},
})
}
}

View file

@ -0,0 +1,85 @@
// 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 (
"android/soong/android"
"android/soong/genrule"
"testing"
)
func registerDependentModules(ctx android.RegistrationContext) {
ctx.RegisterModuleType("license", android.LicenseFactory)
ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
}
func TestPackage(t *testing.T) {
tests := []struct {
description string
modules string
expected []ExpectedRuleTarget
}{
{
description: "with default applicable licenses",
modules: `
license {
name: "my_license",
visibility: [":__subpackages__"],
license_kinds: ["SPDX-license-identifier-Apache-2.0"],
license_text: ["NOTICE"],
}
package {
default_applicable_licenses: ["my_license"],
}
`,
expected: []ExpectedRuleTarget{
{
"package",
"",
AttrNameToString{
"default_applicable_licenses": `[":my_license"]`,
"default_visibility": `["//visibility:public"]`,
},
android.HostAndDeviceDefault,
},
{
"android_license",
"my_license",
AttrNameToString{
"license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
"license_text": `"NOTICE"`,
"visibility": `[":__subpackages__"]`,
},
android.HostAndDeviceDefault,
},
},
},
}
for _, test := range tests {
expected := make([]string, 0, len(test.expected))
for _, e := range test.expected {
expected = append(expected, e.String())
}
RunBp2BuildTestCase(t, registerDependentModules,
Bp2buildTestCase{
Description: test.description,
ModuleTypeUnderTest: "package",
ModuleTypeUnderTestFactory: android.PackageFactory,
Blueprint: test.modules,
ExpectedBazelTargets: expected,
})
}
}

View file

@ -141,7 +141,7 @@ func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi
android.FailIfErrored(t, errs)
}
if actualCount, expectedCount := len(bazelTargets), len(tc.ExpectedBazelTargets); actualCount != expectedCount {
t.Errorf("%s: Expected %d bazel target (%s), got `%d`` (%s)",
t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
tc.Description, expectedCount, tc.ExpectedBazelTargets, actualCount, bazelTargets)
} else {
for i, target := range bazelTargets {
@ -429,7 +429,9 @@ func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod a
}
attrStrings := make([]string, 0, len(attrs)+1)
attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
if name != "" {
attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
}
for _, k := range android.SortedStringKeys(attrs) {
attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
}
@ -450,3 +452,14 @@ func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) str
func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
}
type ExpectedRuleTarget struct {
Rule string
Name string
Attrs AttrNameToString
Hod android.HostOrDeviceSupported
}
func (ebr ExpectedRuleTarget) String() string {
return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
}

View file

@ -123,6 +123,7 @@ function create_mock_bazel {
symlink_directory prebuilts/jdk
symlink_directory external/bazel-skylib
symlink_directory external/bazelbuild-rules_android
symlink_directory external/bazelbuild-rules_license
symlink_directory external/bazelbuild-kotlin-rules
symlink_file WORKSPACE