Merge changes from topic "metalics"
* changes: Define the standard license_kind rules. Export soong license data to make. Add ability to declare licenses in soong.
This commit is contained in:
commit
659f11fcfc
|
@ -30,6 +30,9 @@ bootstrap_go_package {
|
|||
"filegroup.go",
|
||||
"hooks.go",
|
||||
"image.go",
|
||||
"license.go",
|
||||
"license_kind.go",
|
||||
"licenses.go",
|
||||
"makefile_goal.go",
|
||||
"makevars.go",
|
||||
"metrics.go",
|
||||
|
@ -77,6 +80,9 @@ bootstrap_go_package {
|
|||
"depset_test.go",
|
||||
"deptag_test.go",
|
||||
"expand_test.go",
|
||||
"license_kind_test.go",
|
||||
"license_test.go",
|
||||
"licenses_test.go",
|
||||
"module_test.go",
|
||||
"mutator_test.go",
|
||||
"namespace_test.go",
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
@ -434,6 +435,17 @@ func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
|
|||
return generateDistContributionsForMake(distContributions)
|
||||
}
|
||||
|
||||
// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..)
|
||||
// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make.
|
||||
func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) {
|
||||
fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " "))
|
||||
fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " "))
|
||||
fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " "))
|
||||
if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok {
|
||||
fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " "))
|
||||
}
|
||||
}
|
||||
|
||||
// fillInEntries goes through the common variable processing and calls the extra data funcs to
|
||||
// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
|
||||
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
|
||||
|
@ -460,6 +472,13 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep
|
|||
// Collect make variable assignment entries.
|
||||
a.SetString("LOCAL_PATH", filepath.Dir(bpPath))
|
||||
a.SetString("LOCAL_MODULE", name+a.SubName)
|
||||
a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...)
|
||||
a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...)
|
||||
a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text...)
|
||||
// TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
|
||||
if amod.commonProperties.Effective_package_name != nil {
|
||||
a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name)
|
||||
}
|
||||
a.SetString("LOCAL_MODULE_CLASS", a.Class)
|
||||
a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
|
||||
a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
|
||||
|
@ -682,6 +701,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M
|
|||
}
|
||||
}()
|
||||
|
||||
// Additional cases here require review for correct license propagation to make.
|
||||
switch x := mod.(type) {
|
||||
case AndroidMkDataProvider:
|
||||
return translateAndroidModule(ctx, w, mod, x)
|
||||
|
@ -690,6 +710,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M
|
|||
case AndroidMkEntriesProvider:
|
||||
return translateAndroidMkEntriesModule(ctx, w, mod, x)
|
||||
default:
|
||||
// Not exported to make so no make variables to set.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -703,6 +724,10 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo
|
|||
fmt.Fprintln(w, ".PHONY:", name)
|
||||
fmt.Fprintln(w, name+":", goBinary.InstallPath())
|
||||
fmt.Fprintln(w, "")
|
||||
// Assuming no rules in make include go binaries in distributables.
|
||||
// If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files.
|
||||
// In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for
|
||||
// `goBinary.InstallPath()` pointing to the `name`.meta_lic file.
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -768,6 +793,25 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod
|
|||
blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
|
||||
|
||||
if data.Custom != nil {
|
||||
// List of module types allowed to use .Custom(...)
|
||||
// Additions to the list require careful review for proper license handling.
|
||||
switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
|
||||
case "*aidl.aidlApi": // writes non-custom before adding .phony
|
||||
case "*aidl.aidlMapping": // writes non-custom before adding .phony
|
||||
case "*android.customModule": // appears in tests only
|
||||
case "*apex.apexBundle": // license properties written
|
||||
case "*bpf.bpf": // license properties written (both for module and objs)
|
||||
case "*genrule.Module": // writes non-custom before adding .phony
|
||||
case "*java.SystemModules": // doesn't go through base_rules
|
||||
case "*java.systemModulesImport": // doesn't go through base_rules
|
||||
case "*phony.phony": // license properties written
|
||||
case "*selinux.selinuxContextsModule": // license properties written
|
||||
case "*sysprop.syspropLibrary": // license properties written
|
||||
default:
|
||||
if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
|
||||
return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
|
||||
}
|
||||
}
|
||||
data.Custom(w, name, prefix, blueprintDir, data)
|
||||
} else {
|
||||
WriteAndroidMkData(w, data)
|
||||
|
@ -804,6 +848,7 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blue
|
|||
return nil
|
||||
}
|
||||
|
||||
// Any new or special cases here need review to verify correct propagation of license information.
|
||||
for _, entries := range provider.AndroidMkEntries() {
|
||||
entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
|
||||
entries.write(w)
|
||||
|
|
|
@ -204,6 +204,9 @@ func InitDefaultsModule(module DefaultsModule) {
|
|||
// its checking phase and parsing phase so add it to the list as a normal property.
|
||||
AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
|
||||
|
||||
// The applicable licenses property for defaults is 'licenses'.
|
||||
setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
|
||||
|
||||
base.module = module
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
// 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"
|
||||
)
|
||||
|
||||
type licenseKindDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}
|
||||
|
||||
var (
|
||||
licenseKindTag = licenseKindDependencyTag{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterLicenseBuildComponents(InitRegistrationContext)
|
||||
}
|
||||
|
||||
// Register the license module type.
|
||||
func RegisterLicenseBuildComponents(ctx RegistrationContext) {
|
||||
ctx.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) {
|
||||
ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
|
||||
}
|
||||
|
||||
func (m *licenseModule) GenerateAndroidBuildActions(ctx 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()
|
||||
|
||||
// The visibility property needs to be checked and parsed by the visibility module.
|
||||
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
|
||||
|
||||
initAndroidModuleBase(module)
|
||||
InitDefaultableModule(module)
|
||||
|
||||
return module
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// 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
|
||||
|
||||
func init() {
|
||||
RegisterLicenseKindBuildComponents(InitRegistrationContext)
|
||||
}
|
||||
|
||||
// Register the license_kind module type.
|
||||
func RegisterLicenseKindBuildComponents(ctx RegistrationContext) {
|
||||
ctx.RegisterModuleType("license_kind", LicenseKindFactory)
|
||||
}
|
||||
|
||||
type licenseKindProperties struct {
|
||||
// Specifies the conditions for all licenses of the kind.
|
||||
Conditions []string
|
||||
// Specifies the url to the canonical license definition.
|
||||
Url string
|
||||
// Specifies where this license can be used
|
||||
Visibility []string
|
||||
}
|
||||
|
||||
type licenseKindModule struct {
|
||||
ModuleBase
|
||||
DefaultableModuleBase
|
||||
|
||||
properties licenseKindProperties
|
||||
}
|
||||
|
||||
func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
func (m *licenseKindModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
func LicenseKindFactory() Module {
|
||||
module := &licenseKindModule{}
|
||||
|
||||
base := module.base()
|
||||
module.AddProperties(&base.nameProperties, &module.properties)
|
||||
|
||||
base.generalProperties = module.GetProperties()
|
||||
base.customizableProperties = module.GetProperties()
|
||||
|
||||
// The visibility property needs to be checked and parsed by the visibility module.
|
||||
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
|
||||
|
||||
initAndroidModuleBase(module)
|
||||
InitDefaultableModule(module)
|
||||
|
||||
return module
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var licenseKindTests = []struct {
|
||||
name string
|
||||
fs map[string][]byte
|
||||
expectedErrors []string
|
||||
}{
|
||||
{
|
||||
name: "license_kind must not accept licenses property",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_license",
|
||||
licenses: ["other_license"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`top/Blueprints:4:14: unrecognized property "licenses"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad license_kind",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_notice",
|
||||
conditions: ["notice"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
mock_license {
|
||||
name: "other_notice",
|
||||
license_kinds: ["notice"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`other/Blueprints:2:5: "other_notice" depends on undefined module "notice"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "good license kind",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_by_exception_only",
|
||||
conditions: ["by_exception_only"],
|
||||
}
|
||||
|
||||
mock_license {
|
||||
name: "top_proprietary",
|
||||
license_kinds: ["top_by_exception_only"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
mock_license {
|
||||
name: "other_proprietary",
|
||||
license_kinds: ["top_proprietary"],
|
||||
}`),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple license kinds",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_notice",
|
||||
conditions: ["notice"],
|
||||
}
|
||||
|
||||
license_kind {
|
||||
name: "top_by_exception_only",
|
||||
conditions: ["by_exception_only"],
|
||||
}
|
||||
|
||||
mock_license {
|
||||
name: "top_allowed_as_notice",
|
||||
license_kinds: ["top_notice"],
|
||||
}
|
||||
|
||||
mock_license {
|
||||
name: "top_proprietary",
|
||||
license_kinds: ["top_by_exception_only"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
mock_license {
|
||||
name: "other_rule",
|
||||
license_kinds: ["top_by_exception_only"],
|
||||
}`),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestLicenseKind(t *testing.T) {
|
||||
for _, test := range licenseKindTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, errs := testLicenseKind(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 testLicenseKind(fs map[string][]byte) (*TestContext, []error) {
|
||||
|
||||
// Create a new config per test as license_kind information is stored in the config.
|
||||
config := TestArchConfig(buildDir, nil, "", fs)
|
||||
|
||||
ctx := NewTestArchContext(config)
|
||||
RegisterLicenseKindBuildComponents(ctx)
|
||||
ctx.RegisterModuleType("mock_license", newMockLicenseModule)
|
||||
ctx.Register()
|
||||
|
||||
_, errs := ctx.ParseBlueprintsFiles(".")
|
||||
if len(errs) > 0 {
|
||||
return ctx, errs
|
||||
}
|
||||
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
return ctx, errs
|
||||
}
|
||||
|
||||
type mockLicenseProperties struct {
|
||||
License_kinds []string
|
||||
}
|
||||
|
||||
type mockLicenseModule struct {
|
||||
ModuleBase
|
||||
DefaultableModuleBase
|
||||
|
||||
properties mockLicenseProperties
|
||||
}
|
||||
|
||||
func newMockLicenseModule() Module {
|
||||
m := &mockLicenseModule{}
|
||||
m.AddProperties(&m.properties)
|
||||
InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
|
||||
InitDefaultableModule(m)
|
||||
return m
|
||||
}
|
||||
|
||||
type licensekindTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}
|
||||
|
||||
func (j *mockLicenseModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||
m, ok := ctx.Module().(Module)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ctx.AddDependency(m, licensekindTag{}, j.properties.License_kinds...)
|
||||
}
|
||||
|
||||
func (p *mockLicenseModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"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: "private license",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_notice",
|
||||
conditions: ["notice"],
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
license {
|
||||
name: "top_allowed_as_notice",
|
||||
license_kinds: ["top_notice"],
|
||||
visibility: ["//visibility:private"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
rule {
|
||||
name: "arule",
|
||||
licenses: ["top_allowed_as_notice"],
|
||||
}`),
|
||||
"yetmore/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["top_allowed_as_notice"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+
|
||||
`which is not visible to this module`,
|
||||
`yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+
|
||||
`which is not visible to this module`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "must reference license_kind module",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
rule {
|
||||
name: "top_by_exception_only",
|
||||
}
|
||||
|
||||
license {
|
||||
name: "top_proprietary",
|
||||
license_kinds: ["top_by_exception_only"],
|
||||
visibility: ["//visibility:public"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`top/Blueprints:6:5: module "top_proprietary": license_kinds property `+
|
||||
`"top_by_exception_only" is not a license_kind module`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "license_kind module must exist",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license {
|
||||
name: "top_notice_allowed",
|
||||
license_kinds: ["top_notice"],
|
||||
visibility: ["//visibility:public"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`top/Blueprints:2:5: "top_notice_allowed" depends on undefined module "top_notice"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "public license",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_by_exception_only",
|
||||
conditions: ["by_exception_only"],
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
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_kind {
|
||||
name: "top_notice",
|
||||
conditions: ["notice"],
|
||||
}
|
||||
|
||||
license_kind {
|
||||
name: "top_by_exception_only",
|
||||
conditions: ["by_exception_only"],
|
||||
visibility: ["//visibility:public"],
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// 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, "", fs)
|
||||
|
||||
ctx := NewTestArchContext(config)
|
||||
RegisterPackageBuildComponents(ctx)
|
||||
registerTestPrebuiltBuildComponents(ctx)
|
||||
RegisterLicenseKindBuildComponents(ctx)
|
||||
RegisterLicenseBuildComponents(ctx)
|
||||
ctx.RegisterModuleType("rule", newMockRuleModule)
|
||||
ctx.PreArchMutators(RegisterVisibilityRuleChecker)
|
||||
ctx.PreArchMutators(RegisterLicensesPackageMapper)
|
||||
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
|
||||
ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
|
||||
ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
|
||||
ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
|
||||
ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
|
||||
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) {
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
// 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 (
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
|
||||
//
|
||||
// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
|
||||
// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies.
|
||||
// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency.
|
||||
// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts.
|
||||
|
||||
type licensesDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}
|
||||
|
||||
var (
|
||||
licensesTag = licensesDependencyTag{}
|
||||
)
|
||||
|
||||
// Describes the property provided by a module to reference applicable licenses.
|
||||
type applicableLicensesProperty interface {
|
||||
// The name of the property. e.g. default_applicable_licenses or licenses
|
||||
getName() string
|
||||
// The values assigned to the property. (Must reference license modules.)
|
||||
getStrings() []string
|
||||
}
|
||||
|
||||
type applicableLicensesPropertyImpl struct {
|
||||
name string
|
||||
licensesProperty *[]string
|
||||
}
|
||||
|
||||
func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
|
||||
return applicableLicensesPropertyImpl{
|
||||
name: name,
|
||||
licensesProperty: licensesProperty,
|
||||
}
|
||||
}
|
||||
|
||||
func (p applicableLicensesPropertyImpl) getName() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
func (p applicableLicensesPropertyImpl) getStrings() []string {
|
||||
return *p.licensesProperty
|
||||
}
|
||||
|
||||
// Set the primary applicable licenses property for a module.
|
||||
func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) {
|
||||
module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty)
|
||||
}
|
||||
|
||||
// Storage blob for a package's default_applicable_licenses mapped by package directory.
|
||||
type licensesContainer struct {
|
||||
licenses []string
|
||||
}
|
||||
|
||||
func (r licensesContainer) getLicenses() []string {
|
||||
return r.licenses
|
||||
}
|
||||
|
||||
var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap")
|
||||
|
||||
// The map from package dir name to default applicable licenses as a licensesContainer.
|
||||
func moduleToPackageDefaultLicensesMap(config Config) *sync.Map {
|
||||
return config.Once(packageDefaultLicensesMap, func() interface{} {
|
||||
return &sync.Map{}
|
||||
}).(*sync.Map)
|
||||
}
|
||||
|
||||
// Registers the function that maps each package to its default_applicable_licenses.
|
||||
//
|
||||
// This goes before defaults expansion so the defaults can pick up the package default.
|
||||
func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
|
||||
}
|
||||
|
||||
// Registers the function that gathers the license dependencies for each module.
|
||||
//
|
||||
// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
|
||||
func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
|
||||
}
|
||||
|
||||
// Registers the function that verifies the licenses and license_kinds dependency types for each module.
|
||||
func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
|
||||
ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
|
||||
}
|
||||
|
||||
// Maps each package to its default applicable licenses.
|
||||
func licensesPackageMapper(ctx BottomUpMutatorContext) {
|
||||
p, ok := ctx.Module().(*packageModule)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
licenses := getLicenses(ctx, p)
|
||||
|
||||
dir := ctx.ModuleDir()
|
||||
c := makeLicensesContainer(licenses)
|
||||
moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c)
|
||||
}
|
||||
|
||||
// Copies the default_applicable_licenses property values for mapping by package directory.
|
||||
func makeLicensesContainer(propVals []string) licensesContainer {
|
||||
licenses := make([]string, 0, len(propVals))
|
||||
licenses = append(licenses, propVals...)
|
||||
|
||||
return licensesContainer{licenses}
|
||||
}
|
||||
|
||||
// Gathers the applicable licenses into dependency references after defaults expansion.
|
||||
func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
|
||||
m, ok := ctx.Module().(Module)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if exemptFromRequiredApplicableLicensesProperty(m) {
|
||||
return
|
||||
}
|
||||
|
||||
licenses := getLicenses(ctx, m)
|
||||
|
||||
ctx.AddVariationDependencies(nil, licensesTag, licenses...)
|
||||
}
|
||||
|
||||
// Verifies the license and license_kind dependencies are each the correct kind of module.
|
||||
func licensesDependencyChecker(ctx BottomUpMutatorContext) {
|
||||
m, ok := ctx.Module().(Module)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// license modules have no licenses, but license_kinds must refer to license_kind modules
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
|
||||
if _, ok := module.(*licenseKindModule); !ok {
|
||||
ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if exemptFromRequiredApplicableLicensesProperty(m) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
|
||||
if _, ok := module.(*licenseModule); !ok {
|
||||
propertyName := "licenses"
|
||||
primaryProperty := m.base().primaryLicensesProperty
|
||||
if primaryProperty != nil {
|
||||
propertyName = primaryProperty.getName()
|
||||
}
|
||||
ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flattens license and license_kind dependencies into calculated properties.
|
||||
//
|
||||
// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer
|
||||
// only to license_kind modules.
|
||||
func licensesPropertyFlattener(ctx ModuleContext) {
|
||||
m, ok := ctx.Module().(Module)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// license modules have no licenses, but license_kinds must refer to license_kind modules
|
||||
if l, ok := m.(*licenseModule); ok {
|
||||
mergeProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName())
|
||||
mergeProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, l.properties.License_text).Strings()...)
|
||||
for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
|
||||
if lk, ok := module.(*licenseKindModule); ok {
|
||||
mergeProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...)
|
||||
mergeProps(&m.base().commonProperties.Effective_license_kinds, ctx.OtherModuleName(module))
|
||||
} else {
|
||||
ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if exemptFromRequiredApplicableLicensesProperty(m) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
|
||||
if l, ok := module.(*licenseModule); ok {
|
||||
if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
|
||||
m.base().commonProperties.Effective_package_name = l.properties.Package_name
|
||||
}
|
||||
mergeProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
|
||||
mergeProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
|
||||
mergeProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
|
||||
mergeProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
|
||||
} else {
|
||||
propertyName := "licenses"
|
||||
primaryProperty := m.base().primaryLicensesProperty
|
||||
if primaryProperty != nil {
|
||||
propertyName = primaryProperty.getName()
|
||||
}
|
||||
ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update a property string array with a distinct union of its values and a list of new values.
|
||||
func mergeProps(prop *[]string, values ...string) {
|
||||
s := make(map[string]bool)
|
||||
for _, v := range *prop {
|
||||
s[v] = true
|
||||
}
|
||||
for _, v := range values {
|
||||
s[v] = true
|
||||
}
|
||||
*prop = []string{}
|
||||
*prop = append(*prop, SortedStringKeys(s)...)
|
||||
}
|
||||
|
||||
// Get the licenses property falling back to the package default.
|
||||
func getLicenses(ctx BaseModuleContext, module Module) []string {
|
||||
if exemptFromRequiredApplicableLicensesProperty(module) {
|
||||
return nil
|
||||
}
|
||||
|
||||
primaryProperty := module.base().primaryLicensesProperty
|
||||
if primaryProperty == nil {
|
||||
if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
|
||||
ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
licenses := primaryProperty.getStrings()
|
||||
if len(licenses) > 0 {
|
||||
s := make(map[string]bool)
|
||||
for _, l := range licenses {
|
||||
if _, ok := s[l]; ok {
|
||||
ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName())
|
||||
}
|
||||
s[l] = true
|
||||
}
|
||||
return licenses
|
||||
}
|
||||
|
||||
dir := ctx.OtherModuleDir(module)
|
||||
|
||||
moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config())
|
||||
value, ok := moduleToApplicableLicenses.Load(dir)
|
||||
var c licensesContainer
|
||||
if ok {
|
||||
c = value.(licensesContainer)
|
||||
} else {
|
||||
c = licensesContainer{}
|
||||
}
|
||||
return c.getLicenses()
|
||||
}
|
||||
|
||||
// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
|
||||
func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
|
||||
switch reflect.TypeOf(module).String() {
|
||||
case "*android.licenseModule": // is a license, doesn't need one
|
||||
case "*android.licenseKindModule": // is a license, doesn't need one
|
||||
case "*android.NamespaceModule": // just partitions things, doesn't add anything
|
||||
case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses
|
||||
case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses
|
||||
case "*android.soongConfigStringVariableDummyModule": // used for creating aliases
|
||||
case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,863 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var licensesTests = []struct {
|
||||
name string
|
||||
fs map[string][]byte
|
||||
expectedErrors []string
|
||||
effectiveLicenses map[string][]string
|
||||
effectiveInheritedLicenses map[string][]string
|
||||
effectivePackage map[string]string
|
||||
effectiveNotices map[string][]string
|
||||
effectiveKinds map[string][]string
|
||||
effectiveConditions map[string][]string
|
||||
}{
|
||||
{
|
||||
name: "invalid module type without licenses property",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
mock_bad_module {
|
||||
name: "libexample",
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{`module type "mock_bad_module" must have an applicable licenses property`},
|
||||
},
|
||||
{
|
||||
name: "license must exist",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
licenses: ["notice"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{`"libexample" depends on undefined module "notice"`},
|
||||
},
|
||||
{
|
||||
name: "all good",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "notice",
|
||||
conditions: ["shownotice"],
|
||||
}
|
||||
|
||||
license {
|
||||
name: "top_Apache2",
|
||||
license_kinds: ["notice"],
|
||||
package_name: "topDog",
|
||||
license_text: ["LICENSE", "NOTICE"],
|
||||
}
|
||||
|
||||
mock_library {
|
||||
name: "libexample1",
|
||||
licenses: ["top_Apache2"],
|
||||
}`),
|
||||
"top/nested/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "libnested",
|
||||
licenses: ["top_Apache2"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "libother",
|
||||
licenses: ["top_Apache2"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample1": []string{"top_Apache2"},
|
||||
"libnested": []string{"top_Apache2"},
|
||||
"libother": []string{"top_Apache2"},
|
||||
},
|
||||
effectiveKinds: map[string][]string{
|
||||
"libexample1": []string{"notice"},
|
||||
"libnested": []string{"notice"},
|
||||
"libother": []string{"notice"},
|
||||
},
|
||||
effectivePackage: map[string]string{
|
||||
"libexample1": "topDog",
|
||||
"libnested": "topDog",
|
||||
"libother": "topDog",
|
||||
},
|
||||
effectiveConditions: map[string][]string{
|
||||
"libexample1": []string{"shownotice"},
|
||||
"libnested": []string{"shownotice"},
|
||||
"libother": []string{"shownotice"},
|
||||
},
|
||||
effectiveNotices: map[string][]string{
|
||||
"libexample1": []string{"top/LICENSE", "top/NOTICE"},
|
||||
"libnested": []string{"top/LICENSE", "top/NOTICE"},
|
||||
"libother": []string{"top/LICENSE", "top/NOTICE"},
|
||||
},
|
||||
},
|
||||
|
||||
// Defaults propagation tests
|
||||
{
|
||||
// Check that licenses is the union of the defaults modules.
|
||||
name: "defaults union, basic",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "top_notice",
|
||||
conditions: ["notice"],
|
||||
}
|
||||
|
||||
license {
|
||||
name: "top_other",
|
||||
license_kinds: ["top_notice"],
|
||||
}
|
||||
|
||||
mock_defaults {
|
||||
name: "libexample_defaults",
|
||||
licenses: ["top_other"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
licenses: ["nested_other"],
|
||||
defaults: ["libexample_defaults"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libsamepackage",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
"top/nested/Blueprints": []byte(`
|
||||
license_kind {
|
||||
name: "nested_notice",
|
||||
conditions: ["notice"],
|
||||
}
|
||||
|
||||
license {
|
||||
name: "nested_other",
|
||||
license_kinds: ["nested_notice"],
|
||||
}
|
||||
|
||||
mock_library {
|
||||
name: "libnested",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "libother",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample": []string{"nested_other", "top_other"},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"libexample": []string{"nested_other", "top_other"},
|
||||
"libsamepackage": []string{"nested_other", "top_other"},
|
||||
"libnested": []string{"nested_other", "top_other"},
|
||||
"libother": []string{"nested_other", "top_other"},
|
||||
},
|
||||
effectiveKinds: map[string][]string{
|
||||
"libexample": []string{"nested_notice", "top_notice"},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
},
|
||||
effectiveConditions: map[string][]string{
|
||||
"libexample": []string{"notice"},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "defaults union, multiple defaults",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
license {
|
||||
name: "top",
|
||||
}
|
||||
mock_defaults {
|
||||
name: "libexample_defaults_1",
|
||||
licenses: ["other"],
|
||||
}
|
||||
mock_defaults {
|
||||
name: "libexample_defaults_2",
|
||||
licenses: ["top_nested"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
defaults: ["libexample_defaults_1", "libexample_defaults_2"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libsamepackage",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
"top/nested/Blueprints": []byte(`
|
||||
license {
|
||||
name: "top_nested",
|
||||
license_text: ["LICENSE.txt"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libnested",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
"other/Blueprints": []byte(`
|
||||
license {
|
||||
name: "other",
|
||||
}
|
||||
mock_library {
|
||||
name: "libother",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
"outsider/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "liboutsider",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample": []string{"other", "top_nested"},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
"liboutsider": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"libexample": []string{"other", "top_nested"},
|
||||
"libsamepackage": []string{"other", "top_nested"},
|
||||
"libnested": []string{"other", "top_nested"},
|
||||
"libother": []string{"other", "top_nested"},
|
||||
"liboutsider": []string{"other", "top_nested"},
|
||||
},
|
||||
effectiveKinds: map[string][]string{
|
||||
"libexample": []string{},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
"liboutsider": []string{},
|
||||
},
|
||||
effectiveNotices: map[string][]string{
|
||||
"libexample": []string{"top/nested/LICENSE.txt"},
|
||||
"libsamepackage": []string{},
|
||||
"libnested": []string{},
|
||||
"libother": []string{},
|
||||
"liboutsider": []string{},
|
||||
},
|
||||
},
|
||||
|
||||
// Defaults module's defaults_licenses tests
|
||||
{
|
||||
name: "defaults_licenses invalid",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
mock_defaults {
|
||||
name: "top_defaults",
|
||||
licenses: ["notice"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{`"top_defaults" depends on undefined module "notice"`},
|
||||
},
|
||||
{
|
||||
name: "defaults_licenses overrides package default",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["by_exception_only"],
|
||||
}
|
||||
license {
|
||||
name: "by_exception_only",
|
||||
}
|
||||
license {
|
||||
name: "notice",
|
||||
}
|
||||
mock_defaults {
|
||||
name: "top_defaults",
|
||||
licenses: ["notice"],
|
||||
}
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
}
|
||||
mock_library {
|
||||
name: "libdefaults",
|
||||
defaults: ["top_defaults"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample": []string{"by_exception_only"},
|
||||
"libdefaults": []string{"notice"},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"libexample": []string{"by_exception_only"},
|
||||
"libdefaults": []string{"notice"},
|
||||
},
|
||||
},
|
||||
|
||||
// Package default_applicable_licenses tests
|
||||
{
|
||||
name: "package default_applicable_licenses must exist",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["notice"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{`"//top" depends on undefined module "notice"`},
|
||||
},
|
||||
{
|
||||
// This test relies on the default licenses being legacy_public.
|
||||
name: "package default_applicable_licenses property used when no licenses specified",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["top_notice"],
|
||||
}
|
||||
|
||||
license {
|
||||
name: "top_notice",
|
||||
}
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
}`),
|
||||
"outsider/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "liboutsider",
|
||||
deps: ["libexample"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample": []string{"top_notice"},
|
||||
"liboutsider": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"libexample": []string{"top_notice"},
|
||||
"liboutsider": []string{"top_notice"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "package default_applicable_licenses not inherited to subpackages",
|
||||
fs: map[string][]byte{
|
||||
"top/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["top_notice"],
|
||||
}
|
||||
license {
|
||||
name: "top_notice",
|
||||
}
|
||||
mock_library {
|
||||
name: "libexample",
|
||||
}`),
|
||||
"top/nested/Blueprints": []byte(`
|
||||
package {
|
||||
default_applicable_licenses: ["outsider"],
|
||||
}
|
||||
|
||||
mock_library {
|
||||
name: "libnested",
|
||||
}`),
|
||||
"top/other/Blueprints": []byte(`
|
||||
mock_library {
|
||||
name: "libother",
|
||||
}`),
|
||||
"outsider/Blueprints": []byte(`
|
||||
license {
|
||||
name: "outsider",
|
||||
}
|
||||
mock_library {
|
||||
name: "liboutsider",
|
||||
deps: ["libexample", "libother", "libnested"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"libexample": []string{"top_notice"},
|
||||
"libnested": []string{"outsider"},
|
||||
"libother": []string{},
|
||||
"liboutsider": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"libexample": []string{"top_notice"},
|
||||
"libnested": []string{"outsider"},
|
||||
"libother": []string{},
|
||||
"liboutsider": []string{"top_notice", "outsider"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "verify that prebuilt dependencies are included",
|
||||
fs: map[string][]byte{
|
||||
"prebuilts/Blueprints": []byte(`
|
||||
license {
|
||||
name: "prebuilt"
|
||||
}
|
||||
prebuilt {
|
||||
name: "module",
|
||||
licenses: ["prebuilt"],
|
||||
}`),
|
||||
"top/sources/source_file": nil,
|
||||
"top/sources/Blueprints": []byte(`
|
||||
license {
|
||||
name: "top_sources"
|
||||
}
|
||||
source {
|
||||
name: "module",
|
||||
licenses: ["top_sources"],
|
||||
}`),
|
||||
"top/other/source_file": nil,
|
||||
"top/other/Blueprints": []byte(`
|
||||
source {
|
||||
name: "other",
|
||||
deps: [":module"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"other": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"other": []string{"prebuilt", "top_sources"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)",
|
||||
fs: map[string][]byte{
|
||||
"prebuilts/Blueprints": []byte(`
|
||||
license {
|
||||
name: "prebuilt"
|
||||
}
|
||||
prebuilt {
|
||||
name: "module",
|
||||
licenses: ["prebuilt"],
|
||||
prefer: true,
|
||||
}`),
|
||||
"top/sources/source_file": nil,
|
||||
"top/sources/Blueprints": []byte(`
|
||||
license {
|
||||
name: "top_sources"
|
||||
}
|
||||
source {
|
||||
name: "module",
|
||||
licenses: ["top_sources"],
|
||||
}`),
|
||||
"top/other/source_file": nil,
|
||||
"top/other/Blueprints": []byte(`
|
||||
source {
|
||||
name: "other",
|
||||
deps: [":module"],
|
||||
}`),
|
||||
},
|
||||
effectiveLicenses: map[string][]string{
|
||||
"other": []string{},
|
||||
},
|
||||
effectiveInheritedLicenses: map[string][]string{
|
||||
"module": []string{"prebuilt", "top_sources"},
|
||||
"other": []string{"prebuilt", "top_sources"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestLicenses(t *testing.T) {
|
||||
for _, test := range licensesTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx, errs := testLicenses(buildDir, test.fs)
|
||||
|
||||
CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
|
||||
|
||||
if test.effectiveLicenses != nil {
|
||||
checkEffectiveLicenses(t, ctx, test.effectiveLicenses)
|
||||
}
|
||||
|
||||
if test.effectivePackage != nil {
|
||||
checkEffectivePackage(t, ctx, test.effectivePackage)
|
||||
}
|
||||
|
||||
if test.effectiveNotices != nil {
|
||||
checkEffectiveNotices(t, ctx, test.effectiveNotices)
|
||||
}
|
||||
|
||||
if test.effectiveKinds != nil {
|
||||
checkEffectiveKinds(t, ctx, test.effectiveKinds)
|
||||
}
|
||||
|
||||
if test.effectiveConditions != nil {
|
||||
checkEffectiveConditions(t, ctx, test.effectiveConditions)
|
||||
}
|
||||
|
||||
if test.effectiveInheritedLicenses != nil {
|
||||
checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) {
|
||||
actualLicenses := make(map[string][]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
actualLicenses[m.Name()] = base.commonProperties.Effective_licenses
|
||||
})
|
||||
|
||||
for moduleName, expectedLicenses := range effectiveLicenses {
|
||||
licenses, ok := actualLicenses[moduleName]
|
||||
if !ok {
|
||||
licenses = []string{}
|
||||
}
|
||||
if !compareUnorderedStringArrays(expectedLicenses, licenses) {
|
||||
t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) {
|
||||
actualLicenses := make(map[string][]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
inherited := make(map[string]bool)
|
||||
for _, l := range base.commonProperties.Effective_licenses {
|
||||
inherited[l] = true
|
||||
}
|
||||
ctx.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
|
||||
if _, ok := c.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := c.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := c.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
cmodule, ok := c.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", c.Name())
|
||||
return
|
||||
}
|
||||
cbase := cmodule.base()
|
||||
if cbase == nil {
|
||||
return
|
||||
}
|
||||
for _, l := range cbase.commonProperties.Effective_licenses {
|
||||
inherited[l] = true
|
||||
}
|
||||
})
|
||||
actualLicenses[m.Name()] = []string{}
|
||||
for l := range inherited {
|
||||
actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l)
|
||||
}
|
||||
})
|
||||
|
||||
for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses {
|
||||
licenses, ok := actualLicenses[moduleName]
|
||||
if !ok {
|
||||
licenses = []string{}
|
||||
}
|
||||
if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) {
|
||||
t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) {
|
||||
actualPackage := make(map[string]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if base.commonProperties.Effective_package_name == nil {
|
||||
actualPackage[m.Name()] = ""
|
||||
} else {
|
||||
actualPackage[m.Name()] = *base.commonProperties.Effective_package_name
|
||||
}
|
||||
})
|
||||
|
||||
for moduleName, expectedPackage := range effectivePackage {
|
||||
packageName, ok := actualPackage[moduleName]
|
||||
if !ok {
|
||||
packageName = ""
|
||||
}
|
||||
if expectedPackage != packageName {
|
||||
t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) {
|
||||
actualNotices := make(map[string][]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
actualNotices[m.Name()] = base.commonProperties.Effective_license_text
|
||||
})
|
||||
|
||||
for moduleName, expectedNotices := range effectiveNotices {
|
||||
notices, ok := actualNotices[moduleName]
|
||||
if !ok {
|
||||
notices = []string{}
|
||||
}
|
||||
if !compareUnorderedStringArrays(expectedNotices, notices) {
|
||||
t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) {
|
||||
actualKinds := make(map[string][]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
actualKinds[m.Name()] = base.commonProperties.Effective_license_kinds
|
||||
})
|
||||
|
||||
for moduleName, expectedKinds := range effectiveKinds {
|
||||
kinds, ok := actualKinds[moduleName]
|
||||
if !ok {
|
||||
kinds = []string{}
|
||||
}
|
||||
if !compareUnorderedStringArrays(expectedKinds, kinds) {
|
||||
t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) {
|
||||
actualConditions := make(map[string][]string)
|
||||
ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
|
||||
if _, ok := m.(*licenseModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*licenseKindModule); ok {
|
||||
return
|
||||
}
|
||||
if _, ok := m.(*packageModule); ok {
|
||||
return
|
||||
}
|
||||
module, ok := m.(Module)
|
||||
if !ok {
|
||||
t.Errorf("%q not a module", m.Name())
|
||||
return
|
||||
}
|
||||
base := module.base()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
actualConditions[m.Name()] = base.commonProperties.Effective_license_conditions
|
||||
})
|
||||
|
||||
for moduleName, expectedConditions := range effectiveConditions {
|
||||
conditions, ok := actualConditions[moduleName]
|
||||
if !ok {
|
||||
conditions = []string{}
|
||||
}
|
||||
if !compareUnorderedStringArrays(expectedConditions, conditions) {
|
||||
t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func compareUnorderedStringArrays(expected, actual []string) bool {
|
||||
if len(expected) != len(actual) {
|
||||
return false
|
||||
}
|
||||
s := make(map[string]int)
|
||||
for _, v := range expected {
|
||||
s[v] += 1
|
||||
}
|
||||
for _, v := range actual {
|
||||
c, ok := s[v]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if c < 1 {
|
||||
return false
|
||||
}
|
||||
s[v] -= 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func testLicenses(buildDir string, fs map[string][]byte) (*TestContext, []error) {
|
||||
|
||||
// Create a new config per test as licenses information is stored in the config.
|
||||
env := make(map[string]string)
|
||||
env["ANDROID_REQUIRE_LICENSES"] = "1"
|
||||
config := TestArchConfig(buildDir, env, "", fs)
|
||||
|
||||
ctx := NewTestArchContext(config)
|
||||
ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
|
||||
ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
|
||||
ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
|
||||
|
||||
// Order of the following method calls is significant.
|
||||
RegisterPackageBuildComponents(ctx)
|
||||
registerTestPrebuiltBuildComponents(ctx)
|
||||
RegisterLicenseKindBuildComponents(ctx)
|
||||
RegisterLicenseBuildComponents(ctx)
|
||||
ctx.PreArchMutators(RegisterVisibilityRuleChecker)
|
||||
ctx.PreArchMutators(RegisterLicensesPackageMapper)
|
||||
ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
|
||||
ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
|
||||
ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
|
||||
ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
|
||||
ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
|
||||
ctx.Register()
|
||||
|
||||
_, errs := ctx.ParseBlueprintsFiles(".")
|
||||
if len(errs) > 0 {
|
||||
return ctx, errs
|
||||
}
|
||||
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
return ctx, errs
|
||||
}
|
||||
|
||||
type mockLicensesBadProperties struct {
|
||||
Visibility []string
|
||||
}
|
||||
|
||||
type mockLicensesBadModule struct {
|
||||
ModuleBase
|
||||
DefaultableModuleBase
|
||||
properties mockLicensesBadProperties
|
||||
}
|
||||
|
||||
func newMockLicensesBadModule() Module {
|
||||
m := &mockLicensesBadModule{}
|
||||
|
||||
base := m.base()
|
||||
m.AddProperties(&base.nameProperties, &m.properties)
|
||||
|
||||
base.generalProperties = m.GetProperties()
|
||||
base.customizableProperties = m.GetProperties()
|
||||
|
||||
// The default_visibility property needs to be checked and parsed by the visibility module during
|
||||
// its checking and parsing phases so make it the primary visibility property.
|
||||
setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility)
|
||||
|
||||
initAndroidModuleBase(m)
|
||||
InitDefaultableModule(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mockLicensesBadModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||
}
|
||||
|
||||
type mockLicensesLibraryProperties struct {
|
||||
Deps []string
|
||||
}
|
||||
|
||||
type mockLicensesLibraryModule struct {
|
||||
ModuleBase
|
||||
DefaultableModuleBase
|
||||
properties mockLicensesLibraryProperties
|
||||
}
|
||||
|
||||
func newMockLicensesLibraryModule() Module {
|
||||
m := &mockLicensesLibraryModule{}
|
||||
m.AddProperties(&m.properties)
|
||||
InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
|
||||
InitDefaultableModule(m)
|
||||
return m
|
||||
}
|
||||
|
||||
type dependencyLicensesTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
name string
|
||||
}
|
||||
|
||||
func (j *mockLicensesLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||
ctx.AddVariationDependencies(nil, dependencyLicensesTag{name: "mockdeps"}, j.properties.Deps...)
|
||||
}
|
||||
|
||||
func (p *mockLicensesLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||
}
|
||||
|
||||
type mockLicensesDefaults struct {
|
||||
ModuleBase
|
||||
DefaultsModuleBase
|
||||
}
|
||||
|
||||
func defaultsLicensesFactory() Module {
|
||||
m := &mockLicensesDefaults{}
|
||||
InitDefaultsModule(m)
|
||||
return m
|
||||
}
|
|
@ -619,6 +619,20 @@ type commonProperties struct {
|
|||
// more details.
|
||||
Visibility []string
|
||||
|
||||
// Describes the licenses applicable to this module. Must reference license modules.
|
||||
Licenses []string
|
||||
|
||||
// Flattened from direct license dependencies. Equal to Licenses unless particular module adds more.
|
||||
Effective_licenses []string `blueprint:"mutated"`
|
||||
// Override of module name when reporting licenses
|
||||
Effective_package_name *string `blueprint:"mutated"`
|
||||
// Notice files
|
||||
Effective_license_text []string `blueprint:"mutated"`
|
||||
// License names
|
||||
Effective_license_kinds []string `blueprint:"mutated"`
|
||||
// License conditions
|
||||
Effective_license_conditions []string `blueprint:"mutated"`
|
||||
|
||||
// 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
|
||||
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
|
||||
|
@ -940,6 +954,10 @@ func InitAndroidModule(m Module) {
|
|||
// The default_visibility property needs to be checked and parsed by the visibility module during
|
||||
// its checking and parsing phases so make it the primary visibility property.
|
||||
setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
|
||||
|
||||
// The default_applicable_licenses property needs to be checked and parsed by the licenses module during
|
||||
// its checking and parsing phases so make it the primary licenses property.
|
||||
setPrimaryLicensesProperty(m, "licenses", &base.commonProperties.Licenses)
|
||||
}
|
||||
|
||||
// InitAndroidArchModule initializes the Module as an Android module that is architecture-specific.
|
||||
|
@ -1057,6 +1075,9 @@ type ModuleBase struct {
|
|||
// The primary visibility property, may be nil, that controls access to the module.
|
||||
primaryVisibilityProperty visibilityProperty
|
||||
|
||||
// The primary licenses property, may be nil, records license metadata for the module.
|
||||
primaryLicensesProperty applicableLicensesProperty
|
||||
|
||||
noAddressSanitizer bool
|
||||
installFiles InstallPaths
|
||||
installFilesDepSet *installPathsDepSet
|
||||
|
@ -1732,6 +1753,11 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
|
|||
}
|
||||
}
|
||||
|
||||
licensesPropertyFlattener(ctx)
|
||||
if ctx.Failed() {
|
||||
return
|
||||
}
|
||||
|
||||
m.module.GenerateAndroidBuildActions(ctx)
|
||||
if ctx.Failed() {
|
||||
return
|
||||
|
|
|
@ -115,6 +115,11 @@ var preArch = []RegisterMutatorFunc{
|
|||
//
|
||||
RegisterVisibilityRuleChecker,
|
||||
|
||||
// Record the default_applicable_licenses for each package.
|
||||
//
|
||||
// This must run before the defaults so that defaults modules can pick up the package default.
|
||||
RegisterLicensesPackageMapper,
|
||||
|
||||
// Apply properties from defaults modules to the referencing modules.
|
||||
//
|
||||
// Any mutators that are added before this will not see any modules created by
|
||||
|
@ -141,6 +146,12 @@ var preArch = []RegisterMutatorFunc{
|
|||
// prebuilt.
|
||||
RegisterPrebuiltsPreArchMutators,
|
||||
|
||||
// Gather the licenses properties for all modules for use during expansion and enforcement.
|
||||
//
|
||||
// This must come after the defaults mutators to ensure that any licenses supplied
|
||||
// in a defaults module has been successfully applied before the rules are gathered.
|
||||
RegisterLicensesPropertyGatherer,
|
||||
|
||||
// Gather the visibility rules for all modules for us during visibility enforcement.
|
||||
//
|
||||
// This must come after the defaults mutators to ensure that any visibility supplied
|
||||
|
@ -162,6 +173,7 @@ var postDeps = []RegisterMutatorFunc{
|
|||
registerPathDepsMutator,
|
||||
RegisterPrebuiltsPostDepsMutators,
|
||||
RegisterVisibilityRuleEnforcer,
|
||||
RegisterLicensesDependencyChecker,
|
||||
RegisterNeverallowMutator,
|
||||
RegisterOverridePostDepsMutators,
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ func RegisterPackageBuildComponents(ctx RegistrationContext) {
|
|||
type packageProperties struct {
|
||||
// Specifies the default visibility for all modules defined in this package.
|
||||
Default_visibility []string
|
||||
// Specifies the default license terms for all modules defined in this package.
|
||||
Default_applicable_licenses []string
|
||||
}
|
||||
|
||||
type packageModule struct {
|
||||
|
@ -68,5 +70,9 @@ func PackageFactory() Module {
|
|||
// its checking and parsing phases so make it the primary visibility property.
|
||||
setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility)
|
||||
|
||||
// The default_applicable_licenses property needs to be checked and parsed by the licenses module during
|
||||
// its checking and parsing phases so make it the primary licenses property.
|
||||
setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
|
||||
|
||||
return module
|
||||
}
|
||||
|
|
|
@ -17,9 +17,11 @@ var packageTests = []struct {
|
|||
package {
|
||||
name: "package",
|
||||
visibility: ["//visibility:private"],
|
||||
licenses: ["license"],
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
`top/Blueprints:5:14: unrecognized property "licenses"`,
|
||||
`top/Blueprints:3:10: unrecognized property "name"`,
|
||||
`top/Blueprints:4:16: unrecognized property "visibility"`,
|
||||
},
|
||||
|
@ -44,9 +46,10 @@ var packageTests = []struct {
|
|||
"top/Blueprints": []byte(`
|
||||
package {
|
||||
default_visibility: ["//visibility:private"],
|
||||
default_applicable_licenses: ["license"],
|
||||
}
|
||||
|
||||
package {
|
||||
package {
|
||||
}`),
|
||||
},
|
||||
expectedErrors: []string{
|
||||
|
|
|
@ -63,6 +63,16 @@ func (class apexFileClass) nameInMake() string {
|
|||
}
|
||||
}
|
||||
|
||||
// Return the full module name for a dependency module, which appends the apex module name unless re-using a system lib.
|
||||
func (a *apexBundle) fullModuleName(apexBundleName string, fi *apexFile) string {
|
||||
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
|
||||
|
||||
if linkToSystemLib {
|
||||
return fi.androidMkModuleName
|
||||
}
|
||||
return fi.androidMkModuleName + "." + apexBundleName + a.suffix
|
||||
}
|
||||
|
||||
func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string,
|
||||
apexAndroidMkData android.AndroidMkData) []string {
|
||||
|
||||
|
@ -114,12 +124,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
|
|||
|
||||
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
|
||||
|
||||
var moduleName string
|
||||
if linkToSystemLib {
|
||||
moduleName = fi.androidMkModuleName
|
||||
} else {
|
||||
moduleName = fi.androidMkModuleName + "." + apexBundleName + a.suffix
|
||||
}
|
||||
moduleName := a.fullModuleName(apexBundleName, &fi)
|
||||
|
||||
if !android.InList(moduleName, moduleNames) {
|
||||
moduleNames = append(moduleNames, moduleName)
|
||||
|
@ -311,14 +316,16 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo
|
|||
return moduleNames
|
||||
}
|
||||
|
||||
func (a *apexBundle) writeRequiredModules(w io.Writer) {
|
||||
func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) {
|
||||
var required []string
|
||||
var targetRequired []string
|
||||
var hostRequired []string
|
||||
installMapSet := make(map[string]bool) // set of dependency module:location mappings
|
||||
for _, fi := range a.filesInfo {
|
||||
required = append(required, fi.requiredModuleNames...)
|
||||
targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
|
||||
hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
|
||||
installMapSet[a.fullModuleName(apexBundleName, &fi)+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
|
||||
}
|
||||
|
||||
if len(required) > 0 {
|
||||
|
@ -330,6 +337,11 @@ func (a *apexBundle) writeRequiredModules(w io.Writer) {
|
|||
if len(hostRequired) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES +=", strings.Join(hostRequired, " "))
|
||||
}
|
||||
if len(installMapSet) > 0 {
|
||||
var installs []string
|
||||
installs = append(installs, android.SortedStringKeys(installMapSet)...)
|
||||
fmt.Fprintln(w, "LOCAL_LICENSE_INSTALL_MAP +=", strings.Join(installs, " "))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *apexBundle) androidMkForType() android.AndroidMkData {
|
||||
|
@ -347,16 +359,18 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
|
|||
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
||||
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
||||
fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
if len(moduleNames) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
|
||||
}
|
||||
a.writeRequiredModules(w)
|
||||
a.writeRequiredModules(w, name)
|
||||
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
|
||||
|
||||
} else {
|
||||
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
||||
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
||||
fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
|
||||
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
|
||||
|
@ -389,7 +403,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
|
|||
if len(a.requiredDeps) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
|
||||
}
|
||||
a.writeRequiredModules(w)
|
||||
a.writeRequiredModules(w, name)
|
||||
var postInstallCommands []string
|
||||
if a.prebuiltFileToDelete != "" {
|
||||
postInstallCommands = append(postInstallCommands, "rm -rf "+
|
||||
|
|
|
@ -120,6 +120,7 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData {
|
|||
names = append(names, objName)
|
||||
fmt.Fprintln(w, "include $(CLEAR_VARS)")
|
||||
fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
|
||||
|
@ -129,6 +130,7 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData {
|
|||
}
|
||||
fmt.Fprintln(w, "include $(CLEAR_VARS)")
|
||||
fmt.Fprintln(w, "LOCAL_MODULE := ", name)
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " "))
|
||||
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
|
||||
},
|
||||
|
|
|
@ -192,6 +192,7 @@ func (system *SystemModules) AndroidMk() android.AndroidMkData {
|
|||
|
||||
fmt.Fprintln(w, name+":", "$("+makevar+")")
|
||||
fmt.Fprintln(w, ".PHONY:", name)
|
||||
// TODO(b/151177513): Licenses: Doesn't go through base_rules. May have to generate meta_lic and meta_module here.
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,214 @@
|
|||
|
||||
Copyright (c) The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
|
@ -52,6 +52,7 @@ func (p *phony) AndroidMk() android.AndroidMkData {
|
|||
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
||||
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
||||
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
if p.Host() {
|
||||
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
|
||||
}
|
||||
|
|
|
@ -307,6 +307,7 @@ func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
|
|||
// Actual implementation libraries are created on LoadHookMutator
|
||||
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
||||
fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name())
|
||||
data.Entries.WriteLicenseVariables(w)
|
||||
fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
|
||||
fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
|
||||
fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
|
||||
|
|
Loading…
Reference in New Issue