Minimal license feature. am: 58d85b87bc
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/13929165 Change-Id: I49453a723ea46a2bda5d21655e569c212564c076
This commit is contained in:
commit
6b4ddeb66c
|
@ -50,6 +50,7 @@ bootstrap_go_package {
|
||||||
"android/expand.go",
|
"android/expand.go",
|
||||||
"android/filegroup.go",
|
"android/filegroup.go",
|
||||||
"android/hooks.go",
|
"android/hooks.go",
|
||||||
|
"android/license.go",
|
||||||
"android/makevars.go",
|
"android/makevars.go",
|
||||||
"android/module.go",
|
"android/module.go",
|
||||||
"android/mutator.go",
|
"android/mutator.go",
|
||||||
|
@ -58,6 +59,7 @@ bootstrap_go_package {
|
||||||
"android/notices.go",
|
"android/notices.go",
|
||||||
"android/onceper.go",
|
"android/onceper.go",
|
||||||
"android/override_module.go",
|
"android/override_module.go",
|
||||||
|
"android/package.go",
|
||||||
"android/package_ctx.go",
|
"android/package_ctx.go",
|
||||||
"android/path_properties.go",
|
"android/path_properties.go",
|
||||||
"android/paths.go",
|
"android/paths.go",
|
||||||
|
@ -81,10 +83,12 @@ bootstrap_go_package {
|
||||||
"android/arch_test.go",
|
"android/arch_test.go",
|
||||||
"android/config_test.go",
|
"android/config_test.go",
|
||||||
"android/expand_test.go",
|
"android/expand_test.go",
|
||||||
|
"android/license_test.go",
|
||||||
"android/namespace_test.go",
|
"android/namespace_test.go",
|
||||||
"android/neverallow_test.go",
|
"android/neverallow_test.go",
|
||||||
"android/onceper_test.go",
|
"android/onceper_test.go",
|
||||||
"android/path_properties_test.go",
|
"android/path_properties_test.go",
|
||||||
|
"android/package_test.go",
|
||||||
"android/paths_test.go",
|
"android/paths_test.go",
|
||||||
"android/prebuilt_test.go",
|
"android/prebuilt_test.go",
|
||||||
"android/prebuilt_etc_test.go",
|
"android/prebuilt_etc_test.go",
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
// 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 android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterModuleType("license", LicenseFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
type licenseProperties struct {
|
||||||
|
// Specifies the kinds of license that apply.
|
||||||
|
License_kinds []string
|
||||||
|
// Specifies a short copyright notice to use for the license.
|
||||||
|
Copyright_notice *string
|
||||||
|
// Specifies the path or label for the text of the license.
|
||||||
|
License_text []string `android:"path"`
|
||||||
|
// Specifies the package name to which the license applies.
|
||||||
|
Package_name *string
|
||||||
|
// Specifies where this license can be used
|
||||||
|
Visibility []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type licenseModule struct {
|
||||||
|
ModuleBase
|
||||||
|
DefaultableModuleBase
|
||||||
|
|
||||||
|
properties licenseProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *licenseModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func LicenseFactory() Module {
|
||||||
|
module := &licenseModule{}
|
||||||
|
|
||||||
|
base := module.base()
|
||||||
|
module.AddProperties(
|
||||||
|
&base.nameProperties,
|
||||||
|
&module.properties)
|
||||||
|
|
||||||
|
base.generalProperties = module.GetProperties()
|
||||||
|
base.customizableProperties = module.GetProperties()
|
||||||
|
|
||||||
|
return module
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
package android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var licenseTests = []struct {
|
||||||
|
name string
|
||||||
|
fs map[string][]byte
|
||||||
|
expectedErrors []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "license must not accept licenses property",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
license {
|
||||||
|
name: "top_license",
|
||||||
|
visibility: ["//visibility:private"],
|
||||||
|
licenses: ["other_license"],
|
||||||
|
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
expectedErrors: []string{
|
||||||
|
`top/Blueprints:5:14: unrecognized property "licenses"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "public license",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
license {
|
||||||
|
name: "top_proprietary",
|
||||||
|
license_kinds: ["top_by_exception_only"],
|
||||||
|
visibility: ["//visibility:public"],
|
||||||
|
}`),
|
||||||
|
"other/Blueprints": []byte(`
|
||||||
|
rule {
|
||||||
|
name: "arule",
|
||||||
|
licenses: ["top_proprietary"],
|
||||||
|
|
||||||
|
}`),
|
||||||
|
"yetmore/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
default_applicable_licenses: ["top_proprietary"],
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple licenses",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
default_applicable_licenses: ["top_proprietary"],
|
||||||
|
}
|
||||||
|
license {
|
||||||
|
name: "top_allowed_as_notice",
|
||||||
|
license_kinds: ["top_notice"],
|
||||||
|
}
|
||||||
|
license {
|
||||||
|
name: "top_proprietary",
|
||||||
|
license_kinds: ["top_by_exception_only"],
|
||||||
|
visibility: ["//visibility:public"],
|
||||||
|
}
|
||||||
|
rule {
|
||||||
|
name: "myrule",
|
||||||
|
licenses: ["top_allowed_as_notice", "top_proprietary"]
|
||||||
|
}`),
|
||||||
|
"other/Blueprints": []byte(`
|
||||||
|
rule {
|
||||||
|
name: "arule",
|
||||||
|
licenses: ["top_proprietary"],
|
||||||
|
|
||||||
|
}`),
|
||||||
|
"yetmore/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
default_applicable_licenses: ["top_proprietary"],
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLicense(t *testing.T) {
|
||||||
|
for _, test := range licenseTests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
_, errs := testLicense(test.fs)
|
||||||
|
expectedErrors := test.expectedErrors
|
||||||
|
if expectedErrors == nil {
|
||||||
|
FailIfErrored(t, errs)
|
||||||
|
} else {
|
||||||
|
for _, expectedError := range expectedErrors {
|
||||||
|
FailIfNoMatchingErrors(t, expectedError, errs)
|
||||||
|
}
|
||||||
|
if len(errs) > len(expectedErrors) {
|
||||||
|
t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
|
||||||
|
for i, expectedError := range expectedErrors {
|
||||||
|
t.Errorf("expectedErrors[%d] = %s", i, expectedError)
|
||||||
|
}
|
||||||
|
for i, err := range errs {
|
||||||
|
t.Errorf("errs[%d] = %s", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testLicense(fs map[string][]byte) (*TestContext, []error) {
|
||||||
|
buildDir, err := ioutil.TempDir("", "license_test")
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{err}
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(buildDir)
|
||||||
|
|
||||||
|
// Create a new config per test as visibility information is stored in the config.
|
||||||
|
env := make(map[string]string)
|
||||||
|
env["ANDROID_REQUIRE_LICENSES"] = "1"
|
||||||
|
config := TestArchConfig(buildDir, env)
|
||||||
|
ctx := NewTestArchContext()
|
||||||
|
ctx.MockFileSystem(fs)
|
||||||
|
ctx.RegisterModuleType("package", ModuleFactoryAdaptor(PackageFactory))
|
||||||
|
ctx.RegisterModuleType("license", ModuleFactoryAdaptor(LicenseFactory))
|
||||||
|
ctx.RegisterModuleType("rule", ModuleFactoryAdaptor(newMockRuleModule))
|
||||||
|
ctx.PreArchMutators(registerPackageRenamer)
|
||||||
|
ctx.Register()
|
||||||
|
_, errs := ctx.ParseBlueprintsFiles(".")
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return ctx, errs
|
||||||
|
}
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
return ctx, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockRuleModule struct {
|
||||||
|
ModuleBase
|
||||||
|
DefaultableModuleBase
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockRuleModule() Module {
|
||||||
|
m := &mockRuleModule{}
|
||||||
|
InitAndroidModule(m)
|
||||||
|
InitDefaultableModule(m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *mockRuleModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *mockRuleModule) DepsMutator(BottomUpMutatorContext) {
|
||||||
|
}
|
|
@ -208,6 +208,9 @@ type commonProperties struct {
|
||||||
// emit build rules for this module
|
// emit build rules for this module
|
||||||
Enabled *bool `android:"arch_variant"`
|
Enabled *bool `android:"arch_variant"`
|
||||||
|
|
||||||
|
// Names of the licenses that apply to this module.
|
||||||
|
Licenses []string
|
||||||
|
|
||||||
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
|
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
|
||||||
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
|
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
|
||||||
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
|
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
|
||||||
|
|
|
@ -77,6 +77,7 @@ var preArch = []RegisterMutatorFunc{
|
||||||
ctx.TopDown("load_hooks", LoadHookMutator).Parallel()
|
ctx.TopDown("load_hooks", LoadHookMutator).Parallel()
|
||||||
},
|
},
|
||||||
RegisterNamespaceMutator,
|
RegisterNamespaceMutator,
|
||||||
|
registerPackageRenamer,
|
||||||
RegisterPrebuiltsPreArchMutators,
|
RegisterPrebuiltsPreArchMutators,
|
||||||
RegisterDefaultsPreArchMutators,
|
RegisterDefaultsPreArchMutators,
|
||||||
RegisterOverridePreArchMutators,
|
RegisterOverridePreArchMutators,
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2019 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 android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterModuleType("package", PackageFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
type packageProperties struct {
|
||||||
|
// Specifies the default visibility for all modules defined in this package.
|
||||||
|
Default_visibility []string
|
||||||
|
// Specifies the names of the default licenses for all modules defined in this package.
|
||||||
|
Default_applicable_licenses []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type packageModule struct {
|
||||||
|
ModuleBase
|
||||||
|
|
||||||
|
properties packageProperties
|
||||||
|
// The module dir
|
||||||
|
name string `blueprint:"mutated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packageModule) Name() string {
|
||||||
|
return p.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerPackageRenamer(ctx RegisterMutatorsContext) {
|
||||||
|
ctx.BottomUp("packages", packageRenamer).Parallel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// packageRenamer ensures that every package gets named
|
||||||
|
func packageRenamer(ctx BottomUpMutatorContext) {
|
||||||
|
if p, ok := ctx.Module().(*packageModule); ok {
|
||||||
|
p.name = "//" + ctx.ModuleDir()
|
||||||
|
ctx.Rename("//" + ctx.ModuleDir())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Counter to ensure package modules are created with a unique name within whatever namespace they
|
||||||
|
// belong.
|
||||||
|
var packageCount uint32 = 0
|
||||||
|
|
||||||
|
func PackageFactory() Module {
|
||||||
|
module := &packageModule{}
|
||||||
|
|
||||||
|
// Get a unique if for the package. Has to be done atomically as the creation of the modules are
|
||||||
|
// done in parallel.
|
||||||
|
id := atomic.AddUint32(&packageCount, 1)
|
||||||
|
module.name = fmt.Sprintf("soong_package_%d", id)
|
||||||
|
|
||||||
|
module.AddProperties(&module.properties)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// which is in a LoadHook.
|
||||||
|
AddLoadHook(module, func(ctx LoadHookContext) {
|
||||||
|
module.name = "//" + ctx.ModuleDir()
|
||||||
|
})
|
||||||
|
|
||||||
|
return module
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
package android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var packageTests = []struct {
|
||||||
|
name string
|
||||||
|
fs map[string][]byte
|
||||||
|
expectedErrors []string
|
||||||
|
}{
|
||||||
|
// Package default_visibility handling is tested in visibility_test.go
|
||||||
|
{
|
||||||
|
name: "package must not accept visibility and name properties",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
name: "package",
|
||||||
|
visibility: ["//visibility:private"],
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
expectedErrors: []string{
|
||||||
|
`top/Blueprints:3:10: unrecognized property "name"`,
|
||||||
|
`top/Blueprints:4:16: unrecognized property "visibility"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple packages in separate directories",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
}`),
|
||||||
|
"other/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
}`),
|
||||||
|
"other/nested/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "package must not be specified more than once per package",
|
||||||
|
fs: map[string][]byte{
|
||||||
|
"top/Blueprints": []byte(`
|
||||||
|
package {
|
||||||
|
default_visibility: ["//visibility:private"],
|
||||||
|
default_applicable_licenses: ["license"],
|
||||||
|
}
|
||||||
|
|
||||||
|
package {
|
||||||
|
}`),
|
||||||
|
},
|
||||||
|
expectedErrors: []string{
|
||||||
|
`"//top" conflicts with existing module`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPackage(t *testing.T) {
|
||||||
|
for _, test := range packageTests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
_, errs := testPackage(test.fs)
|
||||||
|
|
||||||
|
expectedErrors := test.expectedErrors
|
||||||
|
if expectedErrors == nil {
|
||||||
|
FailIfErrored(t, errs)
|
||||||
|
} else {
|
||||||
|
for _, expectedError := range expectedErrors {
|
||||||
|
FailIfNoMatchingErrors(t, expectedError, errs)
|
||||||
|
}
|
||||||
|
if len(errs) > len(expectedErrors) {
|
||||||
|
t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
|
||||||
|
for i, expectedError := range expectedErrors {
|
||||||
|
t.Errorf("expectedErrors[%d] = %s", i, expectedError)
|
||||||
|
}
|
||||||
|
for i, err := range errs {
|
||||||
|
t.Errorf("errs[%d] = %s", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPackage(fs map[string][]byte) (*TestContext, []error) {
|
||||||
|
buildDir, err := ioutil.TempDir("", "package_test")
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{err}
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(buildDir)
|
||||||
|
|
||||||
|
// Create a new config per test as visibility information is stored in the config.
|
||||||
|
config := TestArchConfig(buildDir, nil)
|
||||||
|
|
||||||
|
ctx := NewTestArchContext()
|
||||||
|
ctx.MockFileSystem(fs)
|
||||||
|
ctx.RegisterModuleType("package", ModuleFactoryAdaptor(PackageFactory))
|
||||||
|
ctx.PreArchMutators(registerPackageRenamer)
|
||||||
|
ctx.Register()
|
||||||
|
|
||||||
|
_, errs := ctx.ParseBlueprintsFiles(".")
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return ctx, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
return ctx, errs
|
||||||
|
}
|
Loading…
Reference in New Issue