Add license modules to the sdk

Adds initial support for adding license modules to the sdk, along with
any referenced license text files. There is a number of minor
improvements to be made but the core of the support is there and it
works for ART sdks.

Basically, this change will automatically add license modules
referenced from any sdk member module as an internal sdk member. An
internal module has an sdk snapshot specific name that will not
conflict with the source module and which cannot be referenced from
outside the sdk snapshot.

Bug: 181569894
Test: m art-module-sdk art-module-host-exports art-module-test-exports
      - diff output before and after this change
        made sure that every prebuilt had a licenses field
        and that the license modules were added
Change-Id: I0c5ccabf58f4ef487e42ef8e61a5b2a74c0e81af
This commit is contained in:
Paul Duffin 2021-05-06 16:48:05 +01:00
parent ec0836af3a
commit b0bb376efa
5 changed files with 197 additions and 3 deletions

View File

@ -42,6 +42,7 @@ bootstrap_go_package {
"image.go",
"license.go",
"license_kind.go",
"license_sdk_member.go",
"licenses.go",
"makefile_goal.go",
"makevars.go",

View File

@ -0,0 +1,118 @@
// Copyright 2021 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
"path/filepath"
"github.com/google/blueprint"
)
// Contains support for adding license modules to an sdk.
func init() {
RegisterSdkMemberType(LicenseModuleSdkMemberType)
}
// licenseSdkMemberType determines how a license module is added to the sdk.
type licenseSdkMemberType struct {
SdkMemberTypeBase
}
func (l *licenseSdkMemberType) AddDependencies(mctx BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
// Add dependencies onto the license module from the sdk module.
mctx.AddDependency(mctx.Module(), dependencyTag, names...)
}
func (l *licenseSdkMemberType) IsInstance(module Module) bool {
// Verify that the module being added is compatible with this module type.
_, ok := module.(*licenseModule)
return ok
}
func (l *licenseSdkMemberType) AddPrebuiltModule(ctx SdkMemberContext, member SdkMember) BpModule {
// Add the basics of a prebuilt module.
return ctx.SnapshotBuilder().AddPrebuiltModule(member, "license")
}
func (l *licenseSdkMemberType) CreateVariantPropertiesStruct() SdkMemberProperties {
// Create the structure into which the properties of the license module that need to be output to
// the snapshot will be placed. The structure may be populated with information from a variant or
// may be used as the destination for properties that are common to a set of variants.
return &licenseSdkMemberProperties{}
}
// LicenseModuleSdkMemberType is the instance of licenseSdkMemberType
var LicenseModuleSdkMemberType = &licenseSdkMemberType{
SdkMemberTypeBase{
PropertyName: "licenses",
// This should never be added directly to an sdk/module_exports, all license modules should be
// added indirectly as transitive dependencies of other sdk members.
BpPropertyNotRequired: true,
SupportsSdk: true,
// The snapshot of the license module is just another license module (not a prebuilt). They are
// internal modules only so will have an sdk specific name that will not clash with the
// originating source module.
UseSourceModuleTypeInSnapshot: true,
},
}
var _ SdkMemberType = (*licenseSdkMemberType)(nil)
// licenseSdkMemberProperties is the set of properties that need to be added to the license module
// in the snapshot.
type licenseSdkMemberProperties struct {
SdkMemberPropertiesBase
// The kinds of licenses provided by the module.
License_kinds []string
// The source paths to the files containing license text.
License_text Paths
}
func (p *licenseSdkMemberProperties) PopulateFromVariant(_ SdkMemberContext, variant Module) {
// Populate the properties from the variant.
l := variant.(*licenseModule)
p.License_kinds = l.properties.License_kinds
p.License_text = l.base().commonProperties.Effective_license_text
}
func (p *licenseSdkMemberProperties) AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet) {
// Just pass any specified license_kinds straight through.
if len(p.License_kinds) > 0 {
propertySet.AddProperty("license_kinds", p.License_kinds)
}
// Copy any license test files to the snapshot into a module specific location.
if len(p.License_text) > 0 {
dests := []string{}
for _, path := range p.License_text {
// The destination path only uses the path of the license file in the source not the license
// module name. That ensures that if the same license file is used by multiple license modules
// that it only gets copied once as the snapshot builder will dedup copies where the source
// and destination match.
dest := filepath.Join("licenses", path.String())
dests = append(dests, dest)
ctx.SnapshotBuilder().CopyToSnapshot(path, dest)
}
propertySet.AddProperty("license_text", dests)
}
}
var _ SdkMemberProperties = (*licenseSdkMemberProperties)(nil)

View File

@ -32,8 +32,23 @@ type licensesDependencyTag struct {
blueprint.BaseDependencyTag
}
func (l licensesDependencyTag) SdkMemberType(Module) SdkMemberType {
// Add the supplied module to the sdk as a license module.
return LicenseModuleSdkMemberType
}
func (l licensesDependencyTag) ExportMember() bool {
// The license module will only every be referenced from within the sdk. This will ensure that it
// gets a unique name and so avoid clashing with the original license module.
return false
}
var (
licensesTag = licensesDependencyTag{}
// License modules, i.e. modules depended upon via a licensesTag, must be automatically added to
// any sdk/module_exports to which their referencing module is a member.
_ SdkMemberTypeDependencyTag = licensesTag
)
// Describes the property provided by a module to reference applicable licenses.
@ -140,7 +155,6 @@ func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
}
licenses := getLicenses(ctx, m)
ctx.AddVariationDependencies(nil, licensesTag, licenses...)
}
@ -191,8 +205,10 @@ func licensesPropertyFlattener(ctx ModuleContext) {
return
}
var licenses []string
for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
if l, ok := module.(*licenseModule); ok {
licenses = append(licenses, ctx.OtherModuleName(module))
if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
m.base().commonProperties.Effective_package_name = l.properties.Package_name
}
@ -209,6 +225,12 @@ func licensesPropertyFlattener(ctx ModuleContext) {
ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
}
}
// Make the license information available for other modules.
licenseInfo := LicenseInfo{
Licenses: licenses,
}
ctx.SetProvider(LicenseInfoProvider, licenseInfo)
}
// Update a property string array with a distinct union of its values and a list of new values.
@ -277,3 +299,12 @@ func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
}
return true
}
// LicenseInfo contains information about licenses for a specific module.
type LicenseInfo struct {
// The list of license modules this depends upon, either explicitly or through default package
// configuration.
Licenses []string
}
var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})

View File

@ -68,9 +68,23 @@ java_import {
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
licenses: ["mysdk_mylicense"],
jars: ["java/myjavalib.jar"],
}
`),
license {
name: "mysdk_mylicense",
visibility: ["//visibility:private"],
license_kinds: [
"SPDX-license-identifier-Apache-2.0",
"legacy_unencumbered",
],
license_text: [
"licenses/NOTICE1",
"licenses/NOTICE2",
],
}
`),
checkVersionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@ -79,17 +93,34 @@ java_import {
sdk_member_name: "myjavalib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
licenses: ["mysdk_mylicense@current"],
jars: ["java/myjavalib.jar"],
}
license {
name: "mysdk_mylicense@current",
sdk_member_name: "mylicense",
visibility: ["//visibility:private"],
license_kinds: [
"SPDX-license-identifier-Apache-2.0",
"legacy_unencumbered",
],
license_text: [
"licenses/NOTICE1",
"licenses/NOTICE2",
],
}
sdk_snapshot {
name: "mysdk@current",
visibility: ["//visibility:public"],
java_header_libs: ["mysdk_myjavalib@current"],
}
`),
`),
checkAllCopyRules(`
.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/myjavalib.jar
NOTICE1 -> licenses/NOTICE1
NOTICE2 -> licenses/NOTICE2
`),
)
}

View File

@ -893,6 +893,13 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType
m.AddProperty("apex_available", apexAvailable)
}
// The licenses are the same for all variants.
mctx := s.ctx
licenseInfo := mctx.OtherModuleProvider(variant, android.LicenseInfoProvider).(android.LicenseInfo)
if len(licenseInfo.Licenses) > 0 {
m.AddPropertyWithTag("licenses", licenseInfo.Licenses, s.OptionalSdkMemberReferencePropertyTag())
}
deviceSupported := false
hostSupported := false
@ -920,6 +927,12 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType
}
func addHostDeviceSupportedProperties(deviceSupported bool, hostSupported bool, bpModule *bpModule) {
// If neither device or host is supported then this module does not support either so will not
// recognize the properties.
if !deviceSupported && !hostSupported {
return
}
if !deviceSupported {
bpModule.AddProperty("device_supported", false)
}