Revert^2 "Build license metadata files in Soong"
b3264f20905792e553561e9e0076eaf95d80a25d
Change-Id: I5ea5f7e29eb1dbc72b8b30f010006a25f5f72fac
diff --git a/android/Android.bp b/android/Android.bp
index a20aedc..da36959 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -47,6 +47,7 @@
"image.go",
"license.go",
"license_kind.go",
+ "license_metadata.go",
"license_sdk_member.go",
"licenses.go",
"makefile_goal.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 0adc2a6..85f9ded 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -474,6 +474,7 @@
ModuleDir(module blueprint.Module) string
Config() Config
ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
+ ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
}
func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
@@ -609,6 +610,11 @@
}
}
+ if ctx.ModuleHasProvider(mod, LicenseMetadataProvider) {
+ licenseMetadata := ctx.ModuleProvider(mod, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
+ }
+
extraCtx := &androidMkExtraEntriesContext{
ctx: ctx,
mod: mod,
diff --git a/android/license_metadata.go b/android/license_metadata.go
new file mode 100644
index 0000000..3bc53d6
--- /dev/null
+++ b/android/license_metadata.go
@@ -0,0 +1,231 @@
+// 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 (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ _ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
+
+ licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
+ Command: "${licenseMetadataCmd} -o $out @${out}.rsp",
+ CommandDeps: []string{"${licenseMetadataCmd}"},
+ Rspfile: "${out}.rsp",
+ RspfileContent: "${args}",
+ }, "args")
+)
+
+func buildLicenseMetadata(ctx ModuleContext) {
+ base := ctx.Module().base()
+
+ if !base.Enabled() {
+ return
+ }
+
+ if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
+ return
+ }
+
+ var allDepMetadataFiles Paths
+ var allDepMetadataArgs []string
+ var allDepOutputFiles Paths
+
+ ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
+ dep, _ := bpdep.(Module)
+ if dep == nil {
+ return
+ }
+ if !dep.Enabled() {
+ return
+ }
+
+ if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
+ info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
+
+ depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
+
+ allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
+
+ if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
+ allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
+ } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
+ depOutputFiles = PathsIfNonNil(depOutputFiles...)
+ allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
+ }
+ }
+ })
+
+ allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
+ sort.Strings(allDepMetadataArgs)
+ allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
+
+ var orderOnlyDeps Paths
+ var args []string
+
+ if t := ctx.ModuleType(); t != "" {
+ args = append(args,
+ "-mt "+proptools.NinjaAndShellEscape(t))
+ }
+
+ args = append(args,
+ "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
+ "-mc UNKNOWN")
+
+ if p := base.commonProperties.Effective_package_name; p != nil {
+ args = append(args,
+ "-p "+proptools.NinjaAndShellEscape(*p))
+ }
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
+ orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
+
+ // Install map
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
+
+ // Built files
+ var outputFiles Paths
+ if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
+ outputFiles, _ = outputFileProducer.OutputFiles("")
+ outputFiles = PathsIfNonNil(outputFiles...)
+ }
+
+ if len(outputFiles) > 0 {
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
+ } else {
+ args = append(args, fmt.Sprintf("-t //%s:%s", ctx.ModuleDir(), ctx.ModuleName()))
+ }
+
+ // Installed files
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
+
+ isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
+ if isContainer {
+ args = append(args, "--is_container")
+ }
+
+ licenseMetadataFile := PathForModuleOut(ctx, "meta_lic")
+
+ ctx.Build(pctx, BuildParams{
+ Rule: licenseMetadataRule,
+ Output: licenseMetadataFile,
+ OrderOnly: orderOnlyDeps,
+ Description: "license metadata",
+ Args: map[string]string{
+ "args": strings.Join(args, " "),
+ },
+ })
+
+ ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
+ LicenseMetadataPath: licenseMetadataFile,
+ })
+}
+
+func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
+ var paths Paths
+ if len(installPaths) > 0 {
+ paths = installPaths.Paths()
+ } else {
+ paths = builtPaths
+ }
+
+ for _, path := range paths {
+ switch path.Ext() {
+ case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
+ return true
+ }
+ }
+
+ return false
+}
+
+// LicenseMetadataProvider is used to propagate license metadata paths between modules.
+var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
+
+// LicenseMetadataInfo stores the license metadata path for a module.
+type LicenseMetadataInfo struct {
+ LicenseMetadataPath Path
+}
+
+// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
+// a string, or an empty string if there are none.
+func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
+ if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
+ annos := annoTag.LicenseAnnotations()
+ if len(annos) > 0 {
+ annoStrings := make([]string, len(annos))
+ for i, s := range annos {
+ annoStrings[i] = string(s)
+ }
+ return ":" + strings.Join(annoStrings, ",")
+ }
+ }
+ return ""
+}
+
+// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
+// list of license dependency annotations.
+type LicenseAnnotationsDependencyTag interface {
+ LicenseAnnotations() []LicenseAnnotation
+}
+
+// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
+// license information.
+type LicenseAnnotation string
+
+const (
+ // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
+ // of dependency tags when the usage of the dependency is dynamic, for example a shared library
+ // linkage for native modules or as a classpath library for java modules.
+ LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
+
+ // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
+ // dependency tags when the dependency is used as a toolchain.
+ //
+ // Dependency tags that need to always return LicenseAnnotationToolchain
+ // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
+ LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
+)
+
+// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
+// LicenseAnnotations that always returns LicenseAnnotationToolchain.
+type LicenseAnnotationToolchainDependencyTag struct{}
+
+func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
+ return []LicenseAnnotation{LicenseAnnotationToolchain}
+}
diff --git a/android/module.go b/android/module.go
index 767f9f4..df01dc5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1230,6 +1230,10 @@
initRcPaths Paths
vintfFragmentsPaths Paths
+
+ // set of dependency module:location mappings used to populate the license metadata for
+ // apex containers.
+ licenseInstallMap []string
}
// A struct containing all relevant information about a Bazel target converted via bp2build.
@@ -1774,6 +1778,12 @@
return append(Paths{}, m.vintfFragmentsPaths...)
}
+// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
+// apex container for use when generation the license metadata file.
+func (m *ModuleBase) SetLicenseInstallMap(installMap []string) {
+ m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
+}
+
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
var allInstalledFiles InstallPaths
var allCheckbuildFiles Paths
@@ -2049,6 +2059,8 @@
m.installFilesDepSet = newInstallPathsDepSet(m.installFiles, dependencyInstallFiles)
m.packagingSpecsDepSet = newPackagingSpecsDepSet(m.packagingSpecs, dependencyPackagingSpecs)
+ buildLicenseMetadata(ctx)
+
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7764b6b..f001fa2 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -309,19 +309,17 @@
return moduleNames
}
-func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) {
+func (a *apexBundle) writeRequiredModules(w io.Writer) {
var required []string
var targetRequired []string
var hostRequired []string
required = append(required, a.RequiredModuleNames()...)
targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
- 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 {
@@ -333,11 +331,6 @@
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 {
@@ -359,7 +352,7 @@
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
}
- a.writeRequiredModules(w, name)
+ a.writeRequiredModules(w)
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
} else {
@@ -401,7 +394,7 @@
if len(a.requiredDeps) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
}
- a.writeRequiredModules(w, name)
+ a.writeRequiredModules(w)
if a.mergedNotices.Merged.Valid() {
fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", a.mergedNotices.Merged.Path().String())
diff --git a/apex/builder.go b/apex/builder.go
index 0880e2b..5910784 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -434,7 +434,10 @@
// Avoid creating duplicate build rules for multi-installed APEXes.
if proptools.BoolDefault(a.properties.Multi_install_skip_symbol_files, false) {
installSymbolFiles = false
+
}
+ // set of dependency module:location mappings
+ installMapSet := make(map[string]bool)
// TODO(jiyong): use the RuleBuilder
var copyCommands []string
@@ -442,7 +445,6 @@
pathWhenActivated := android.PathForModuleInPartitionInstall(ctx, "apex", apexName)
for _, fi := range a.filesInfo {
destPath := imageDir.Join(ctx, fi.path()).String()
- var installedPath android.InstallPath
// Prepare the destination path
destPathDir := filepath.Dir(destPath)
if fi.class == appSet {
@@ -450,6 +452,8 @@
}
copyCommands = append(copyCommands, "mkdir -p "+destPathDir)
+ installMapPath := fi.builtFile
+
// Copy the built file to the directory. But if the symlink optimization is turned
// on, place a symlink to the corresponding file in /system partition instead.
if a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() {
@@ -457,6 +461,7 @@
pathOnDevice := filepath.Join("/system", fi.path())
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
+ var installedPath android.InstallPath
if fi.class == appSet {
copyCommands = append(copyCommands,
fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
@@ -475,17 +480,19 @@
if installSymbolFiles {
implicitInputs = append(implicitInputs, installedPath)
}
- }
- // Create additional symlinks pointing the file inside the APEX (if any). Note that
- // this is independent from the symlink optimization.
- for _, symlinkPath := range fi.symlinkPaths() {
- symlinkDest := imageDir.Join(ctx, symlinkPath).String()
- copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
- if installSymbolFiles {
- installedSymlink := ctx.InstallSymlink(pathWhenActivated.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
- implicitInputs = append(implicitInputs, installedSymlink)
+ // Create additional symlinks pointing the file inside the APEX (if any). Note that
+ // this is independent from the symlink optimization.
+ for _, symlinkPath := range fi.symlinkPaths() {
+ symlinkDest := imageDir.Join(ctx, symlinkPath).String()
+ copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
+ if installSymbolFiles {
+ installedSymlink := ctx.InstallSymlink(pathWhenActivated.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
+ implicitInputs = append(implicitInputs, installedSymlink)
+ }
}
+
+ installMapPath = installedPath
}
// Copy the test files (if any)
@@ -502,6 +509,8 @@
copyCommands = append(copyCommands, "cp -f "+d.SrcPath.String()+" "+dataDest)
implicitInputs = append(implicitInputs, d.SrcPath)
}
+
+ installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
implicitInputs = append(implicitInputs, a.manifestPbOut)
if installSymbolFiles {
@@ -510,6 +519,12 @@
implicitInputs = append(implicitInputs, installedManifest, installedKey)
}
+ if len(installMapSet) > 0 {
+ var installs []string
+ installs = append(installs, android.SortedStringKeys(installMapSet)...)
+ a.SetLicenseInstallMap(installs)
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////
// Step 1.a: Write the list of files in this APEX to a txt file and compare it against
// the allowed list given via the allowed_files property. Build fails when the two lists
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 3065d57..daf932e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1206,11 +1206,16 @@
func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
paths, err := module.commonOutputFiles(tag)
- if paths == nil && err == nil {
- return module.Library.OutputFiles(tag)
- } else {
+ if paths != nil || err != nil {
return paths, err
}
+ if module.requiresRuntimeImplementationLibrary() {
+ return module.Library.OutputFiles(tag)
+ }
+ if tag == "" {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {