Support multiple dists per Android.bp module, and dist output selection.

This CL adds "dists" to the base property struct to support multiple
dist file configurations, and generic tag support to dist tagged outputs
of modules.

Fixes: b/152834186
Test: soong tests and `m sdk dist`

Change-Id: I80c86bc9b7b09e671f640a4480c45d438bdd9a2a
Signed-off-by: Jingwen Chen <jingwen@google.com>
This commit is contained in:
Jingwen Chen
2020-06-15 05:24:19 +00:00
parent 670ed3d97d
commit 40fd90ae52
12 changed files with 535 additions and 101 deletions

View File

@@ -46,7 +46,7 @@ type AndroidMkDataProvider interface {
type AndroidMkData struct {
Class string
SubName string
DistFile OptionalPath
DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -72,7 +72,7 @@ type AndroidMkEntriesProvider interface {
type AndroidMkEntries struct {
Class string
SubName string
DistFile OptionalPath
DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -137,6 +137,96 @@ func (a *AndroidMkEntries) AddStrings(name string, value ...string) {
a.EntryMap[name] = append(a.EntryMap[name], value...)
}
// Compute the list of Make strings to declare phone goals and dist-for-goals
// calls from the module's dist and dists properties.
func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
amod := mod.(Module).base()
name := amod.BaseModuleName()
var ret []string
availableTaggedDists := TaggedDistFiles{}
if a.DistFiles != nil && len(a.DistFiles[""]) > 0 {
availableTaggedDists = a.DistFiles
} else if a.OutputFile.Valid() {
availableTaggedDists = MakeDefaultDistFiles(a.OutputFile.Path())
}
// Iterate over this module's dist structs, merged from the dist and dists properties.
for _, dist := range amod.Dists() {
// Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
goals := strings.Join(dist.Targets, " ")
// Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
var tag string
if dist.Tag == nil {
// If the dist struct does not specify a tag, use the default output files tag.
tag = ""
} else {
tag = *dist.Tag
}
// Get the paths of the output files to be dist'd, represented by the tag.
// Can be an empty list.
tagPaths := availableTaggedDists[tag]
if len(tagPaths) == 0 {
// Nothing to dist for this tag, continue to the next dist.
continue
}
if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
errorMessage := "Cannot apply dest/suffix for more than one dist " +
"file for %s goals in module %s. The list of dist files, " +
"which should have a single element, is:\n%s"
panic(fmt.Errorf(errorMessage, goals, name, tagPaths))
}
ret = append(ret, fmt.Sprintf(".PHONY: %s\n", goals))
// Create dist-for-goals calls for each path in the dist'd files.
for _, path := range tagPaths {
// It's possible that the Path is nil from errant modules. Be defensive here.
if path == nil {
tagName := "default" // for error message readability
if dist.Tag != nil {
tagName = *dist.Tag
}
panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
}
dest := filepath.Base(path.String())
if dist.Dest != nil {
var err error
if dest, err = validateSafePath(*dist.Dest); err != nil {
// This was checked in ModuleBase.GenerateBuildActions
panic(err)
}
}
if dist.Suffix != nil {
ext := filepath.Ext(dest)
suffix := *dist.Suffix
dest = strings.TrimSuffix(dest, ext) + suffix + ext
}
if dist.Dir != nil {
var err error
if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
// This was checked in ModuleBase.GenerateBuildActions
panic(err)
}
}
ret = append(
ret,
fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", goals, path.String(), dest))
}
}
return ret
}
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
a.EntryMap = make(map[string][]string)
amod := mod.(Module).base()
@@ -149,42 +239,8 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep
a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...)
a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...)
// Fill in the header part.
if len(amod.commonProperties.Dist.Targets) > 0 {
distFile := a.DistFile
if !distFile.Valid() {
distFile = a.OutputFile
}
if distFile.Valid() {
dest := filepath.Base(distFile.String())
if amod.commonProperties.Dist.Dest != nil {
var err error
if dest, err = validateSafePath(*amod.commonProperties.Dist.Dest); err != nil {
// This was checked in ModuleBase.GenerateBuildActions
panic(err)
}
}
if amod.commonProperties.Dist.Suffix != nil {
ext := filepath.Ext(dest)
suffix := *amod.commonProperties.Dist.Suffix
dest = strings.TrimSuffix(dest, ext) + suffix + ext
}
if amod.commonProperties.Dist.Dir != nil {
var err error
if dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest); err != nil {
// This was checked in ModuleBase.GenerateBuildActions
panic(err)
}
}
goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
fmt.Fprintln(&a.header, ".PHONY:", goals)
fmt.Fprintf(&a.header, "$(call dist-for-goals,%s,%s:%s)\n",
goals, distFile.String(), dest)
}
for _, distString := range a.GetDistForGoals(mod) {
fmt.Fprintf(&a.header, distString)
}
fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
@@ -430,7 +486,7 @@ func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprin
entries := AndroidMkEntries{
Class: data.Class,
SubName: data.SubName,
DistFile: data.DistFile,
DistFiles: data.DistFiles,
OutputFile: data.OutputFile,
Disabled: data.Disabled,
Include: data.Include,

View File

@@ -15,6 +15,7 @@
package android
import (
"fmt"
"io"
"reflect"
"testing"
@@ -22,10 +23,12 @@ import (
type customModule struct {
ModuleBase
data AndroidMkData
data AndroidMkData
distFiles TaggedDistFiles
}
func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) {
m.distFiles = m.GenerateTaggedDistFiles(ctx)
}
func (m *customModule) AndroidMk() AndroidMkData {
@@ -36,6 +39,26 @@ func (m *customModule) AndroidMk() AndroidMkData {
}
}
func (m *customModule) OutputFiles(tag string) (Paths, error) {
switch tag {
case "":
return PathsForTesting("one.out"), nil
case ".multiple":
return PathsForTesting("two.out", "three/four.out"), nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
}
func (m *customModule) AndroidMkEntries() []AndroidMkEntries {
return []AndroidMkEntries{
{
Class: "CUSTOM_MODULE",
DistFiles: m.distFiles,
},
}
}
func customModuleFactory() Module {
module := &customModule{}
InitAndroidModule(module)
@@ -76,3 +99,159 @@ func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testin
assertEqual([]string{"baz"}, m.data.Host_required)
assertEqual([]string{"qux"}, m.data.Target_required)
}
func TestGetDistForGoals(t *testing.T) {
testCases := []struct {
bp string
expectedAndroidMkLines []string
}{
{
bp: `
custom {
name: "foo",
dist: {
targets: ["my_goal"]
}
}
`,
expectedAndroidMkLines: []string{
".PHONY: my_goal\n",
"$(call dist-for-goals,my_goal,one.out:one.out)\n",
},
},
{
bp: `
custom {
name: "foo",
dists: [
{
targets: ["my_goal"],
},
{
targets: ["my_second_goal", "my_third_goal"],
},
],
}
`,
expectedAndroidMkLines: []string{
".PHONY: my_goal\n",
"$(call dist-for-goals,my_goal,one.out:one.out)\n",
".PHONY: my_second_goal my_third_goal\n",
"$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n",
},
},
{
bp: `
custom {
name: "foo",
dist: {
targets: ["my_goal"],
},
dists: [
{
targets: ["my_second_goal", "my_third_goal"],
},
],
}
`,
expectedAndroidMkLines: []string{
".PHONY: my_second_goal my_third_goal\n",
"$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n",
".PHONY: my_goal\n",
"$(call dist-for-goals,my_goal,one.out:one.out)\n",
},
},
{
bp: `
custom {
name: "foo",
dist: {
targets: ["my_goal", "my_other_goal"],
tag: ".multiple",
},
dists: [
{
targets: ["my_second_goal"],
tag: ".multiple",
},
{
targets: ["my_third_goal"],
dir: "test/dir",
},
{
targets: ["my_fourth_goal"],
suffix: ".suffix",
},
{
targets: ["my_fifth_goal"],
dest: "new-name",
},
{
targets: ["my_sixth_goal"],
dest: "new-name",
dir: "some/dir",
suffix: ".suffix",
},
],
}
`,
expectedAndroidMkLines: []string{
".PHONY: my_second_goal\n",
"$(call dist-for-goals,my_second_goal,two.out:two.out)\n",
"$(call dist-for-goals,my_second_goal,three/four.out:four.out)\n",
".PHONY: my_third_goal\n",
"$(call dist-for-goals,my_third_goal,one.out:test/dir/one.out)\n",
".PHONY: my_fourth_goal\n",
"$(call dist-for-goals,my_fourth_goal,one.out:one.suffix.out)\n",
".PHONY: my_fifth_goal\n",
"$(call dist-for-goals,my_fifth_goal,one.out:new-name)\n",
".PHONY: my_sixth_goal\n",
"$(call dist-for-goals,my_sixth_goal,one.out:some/dir/new-name.suffix)\n",
".PHONY: my_goal my_other_goal\n",
"$(call dist-for-goals,my_goal my_other_goal,two.out:two.out)\n",
"$(call dist-for-goals,my_goal my_other_goal,three/four.out:four.out)\n",
},
},
}
for _, testCase := range testCases {
config := TestConfig(buildDir, nil, testCase.bp, nil)
config.inMake = true // Enable androidmk Singleton
ctx := NewTestContext()
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
ctx.RegisterModuleType("custom", customModuleFactory)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
module := ctx.ModuleForTests("foo", "").Module().(*customModule)
entries := AndroidMkEntriesForTest(t, config, "", module)
if len(entries) != 1 {
t.Errorf("Expected a single AndroidMk entry, got %d", len(entries))
}
androidMkLines := entries[0].GetDistForGoals(module)
if len(androidMkLines) != len(testCase.expectedAndroidMkLines) {
t.Errorf(
"Expected %d AndroidMk lines, got %d:\n%v",
len(testCase.expectedAndroidMkLines),
len(androidMkLines),
androidMkLines,
)
}
for idx, line := range androidMkLines {
expectedLine := testCase.expectedAndroidMkLines[idx]
if line != expectedLine {
t.Errorf(
"Expected AndroidMk line to be '%s', got '%s'",
line,
expectedLine,
)
}
}
}
}

View File

@@ -315,6 +315,28 @@ func newPackageId(pkg string) qualifiedModuleName {
return qualifiedModuleName{pkg: pkg, name: ""}
}
type Dist struct {
// Copy the output of this module to the $DIST_DIR when `dist` is specified on the
// command line and any of these targets are also on the command line, or otherwise
// built
Targets []string `android:"arch_variant"`
// The name of the output artifact. This defaults to the basename of the output of
// the module.
Dest *string `android:"arch_variant"`
// The directory within the dist directory to store the artifact. Defaults to the
// top level directory ("").
Dir *string `android:"arch_variant"`
// A suffix to add to the artifact file name (before any extension).
Suffix *string `android:"arch_variant"`
// A string tag to select the OutputFiles associated with the tag. Defaults to the
// the empty "" string.
Tag *string `android:"arch_variant"`
}
type nameProperties struct {
// The name of the module. Must be unique across all modules.
Name *string
@@ -454,23 +476,13 @@ type commonProperties struct {
// relative path to a file to include in the list of notices for the device
Notice *string `android:"path"`
Dist struct {
// copy the output of this module to the $DIST_DIR when `dist` is specified on the
// command line and any of these targets are also on the command line, or otherwise
// built
Targets []string `android:"arch_variant"`
// configuration to distribute output files from this module to the distribution
// directory (default: $OUT/dist, configurable with $DIST_DIR)
Dist Dist `android:"arch_variant"`
// The name of the output artifact. This defaults to the basename of the output of
// the module.
Dest *string `android:"arch_variant"`
// The directory within the dist directory to store the artifact. Defaults to the
// top level directory ("").
Dir *string `android:"arch_variant"`
// A suffix to add to the artifact file name (before any extension).
Suffix *string `android:"arch_variant"`
} `android:"arch_variant"`
// a list of configurations to distribute output files from this module to the
// distribution directory (default: $OUT/dist, configurable with $DIST_DIR)
Dists []Dist `android:"arch_variant"`
// The OsType of artifacts that this module variant is responsible for creating.
//
@@ -537,6 +549,14 @@ type commonProperties struct {
ImageVariation string `blueprint:"mutated"`
}
// A map of OutputFile tag keys to Paths, for disting purposes.
type TaggedDistFiles map[string]Paths
func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles {
// The default OutputFile tag is the empty "" string.
return TaggedDistFiles{"": paths}
}
type hostAndDeviceProperties struct {
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
@@ -815,6 +835,41 @@ func (m *ModuleBase) visibilityProperties() []visibilityProperty {
return m.visibilityPropertyInfo
}
func (m *ModuleBase) Dists() []Dist {
if len(m.commonProperties.Dist.Targets) > 0 {
// Make a copy of the underlying Dists slice to protect against
// backing array modifications with repeated calls to this method.
distsCopy := append([]Dist(nil), m.commonProperties.Dists...)
return append(distsCopy, m.commonProperties.Dist)
} else {
return m.commonProperties.Dists
}
}
func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFiles {
distFiles := make(TaggedDistFiles)
for _, dist := range m.Dists() {
var tag string
var distFilesForTag Paths
if dist.Tag == nil {
tag = ""
} else {
tag = *dist.Tag
}
distFilesForTag, err := m.base().module.(OutputFileProducer).OutputFiles(tag)
if err != nil {
ctx.PropertyErrorf("dist.tag", "%s", err.Error())
}
for _, distFile := range distFilesForTag {
if distFile != nil && !distFiles[tag].containsPath(distFile) {
distFiles[tag] = append(distFiles[tag], distFile)
}
}
}
return distFiles
}
func (m *ModuleBase) Target() Target {
return m.commonProperties.CompileTarget
}

View File

@@ -220,6 +220,15 @@ func (p OptionalPath) String() string {
// Paths is a slice of Path objects, with helpers to operate on the collection.
type Paths []Path
func (paths Paths) containsPath(path Path) bool {
for _, p := range paths {
if p == path {
return true
}
}
return false
}
// PathsForSource returns Paths rooted from SrcDir
func PathsForSource(ctx PathContext, paths []string) Paths {
ret := make(Paths, len(paths))

View File

@@ -249,7 +249,10 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries
entries.Class = "HEADER_LIBRARIES"
}
entries.DistFile = library.distFile
if library.distFile != nil {
entries.DistFiles = android.MakeDefaultDistFiles(library.distFile)
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
library.androidMkWriteExportedFlags(entries)
library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
@@ -318,7 +321,7 @@ func (binary *binaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *a
ctx.subAndroidMk(entries, binary.baseInstaller)
entries.Class = "EXECUTABLES"
entries.DistFile = binary.distFile
entries.DistFiles = binary.distFiles
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String())
if len(binary.symlinks) > 0 {

View File

@@ -98,8 +98,8 @@ type binaryDecorator struct {
// Output archive of gcno coverage information
coverageOutputFile android.OptionalPath
// Location of the file that should be copied to dist dir when requested
distFile android.OptionalPath
// Location of the files that should be copied to dist dir when requested
distFiles android.TaggedDistFiles
post_install_cmds []string
}
@@ -367,11 +367,11 @@ func (binary *binaryDecorator) link(ctx ModuleContext,
binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
binary.distFile = android.OptionalPathForPath(versionedOutputFile)
binary.distFiles = android.MakeDefaultDistFiles(versionedOutputFile)
if binary.stripper.needsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
binary.distFile = android.OptionalPathForPath(out)
binary.distFiles = android.MakeDefaultDistFiles(out)
binary.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
}

View File

@@ -369,7 +369,7 @@ type libraryDecorator struct {
unstrippedOutputFile android.Path
// Location of the file that should be copied to dist dir when requested
distFile android.OptionalPath
distFile android.Path
versionScriptPath android.ModuleGenPath
@@ -894,7 +894,7 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext,
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
library.distFile = android.OptionalPathForPath(versionedOutputFile)
library.distFile = versionedOutputFile
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
}
}
@@ -988,11 +988,11 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
library.distFile = android.OptionalPathForPath(versionedOutputFile)
library.distFile = versionedOutputFile
if library.stripper.needsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
library.distFile = android.OptionalPathForPath(out)
library.distFile = out
library.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
}

View File

@@ -91,7 +91,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
} else {
mainEntries = android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
DistFile: android.OptionalPathForPath(library.distFile),
DistFiles: library.distFiles,
OutputFile: android.OptionalPathForPath(library.outputFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -550,14 +550,14 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
// needed because an invalid output file would prevent the make entries from
// being written.
// TODO(b/146727827): Revert when we do not need to generate stubs and API separately.
distFile := android.OptionalPathForPath(dstubs.apiFile)
distFile := dstubs.apiFile
outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar)
if !outputFile.Valid() {
outputFile = distFile
outputFile = android.OptionalPathForPath(distFile)
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
DistFile: distFile,
DistFiles: android.MakeDefaultDistFiles(distFile),
OutputFile: outputFile,
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{

View File

@@ -156,17 +156,158 @@ func TestDistWithTag(t *testing.T) {
}
`)
without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module())
with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module())
withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module())
withTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module())
if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 {
t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries))
if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 {
t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries))
}
if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") {
t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile)
if len(withTagEntries[0].DistFiles[".jar"]) != 1 ||
!strings.Contains(withTagEntries[0].DistFiles[".jar"][0].String(), "/javac/foo_with_tag.jar") {
t.Errorf("expected DistFiles to contain classes.jar, got %v", withTagEntries[0].DistFiles)
}
if without_tag_entries[0].DistFile.Valid() {
t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile)
if len(withoutTagEntries[0].DistFiles[".jar"]) > 0 {
t.Errorf("did not expect explicit DistFile for .jar tag, got %v", withoutTagEntries[0].DistFiles[".jar"])
}
}
func TestDistWithDest(t *testing.T) {
ctx, config := testJava(t, `
java_library {
name: "foo",
srcs: ["a.java"],
compile_dex: true,
dist: {
targets: ["my_goal"],
dest: "my/custom/dest/dir",
},
}
`)
module := ctx.ModuleForTests("foo", "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, config, "", module)
if len(entries) != 2 {
t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries))
}
distStrings := entries[0].GetDistForGoals(module)
if len(distStrings) != 2 {
t.Errorf("Expected 2 entries for dist: PHONY and dist-for-goals, but got %q", distStrings)
}
if distStrings[0] != ".PHONY: my_goal\n" {
t.Errorf("Expected .PHONY entry to declare my_goal, but got: %s", distStrings[0])
}
if !strings.Contains(distStrings[1], "$(call dist-for-goals,my_goal") ||
!strings.Contains(distStrings[1], ".intermediates/foo/android_common/dex/foo.jar:my/custom/dest/dir") {
t.Errorf(
"Expected dist-for-goals entry to contain my_goal and new dest dir, but got: %s", distStrings[1])
}
}
func TestDistsWithAllProperties(t *testing.T) {
ctx, config := testJava(t, `
java_library {
name: "foo",
srcs: ["a.java"],
compile_dex: true,
dist: {
targets: ["baz"],
},
dists: [
{
targets: ["bar"],
tag: ".jar",
dest: "bar.jar",
dir: "bar/dir",
suffix: ".qux",
},
]
}
`)
module := ctx.ModuleForTests("foo", "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, config, "", module)
if len(entries) != 2 {
t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries))
}
distStrings := entries[0].GetDistForGoals(module)
if len(distStrings) != 4 {
t.Errorf("Expected 4 entries for dist: PHONY and dist-for-goals, but got %d", len(distStrings))
}
if distStrings[0] != ".PHONY: bar\n" {
t.Errorf("Expected .PHONY entry to declare bar, but got: %s", distStrings[0])
}
if !strings.Contains(distStrings[1], "$(call dist-for-goals,bar") ||
!strings.Contains(
distStrings[1],
".intermediates/foo/android_common/javac/foo.jar:bar/dir/bar.qux.jar") {
t.Errorf(
"Expected dist-for-goals entry to contain bar and new dest dir, but got: %s", distStrings[1])
}
if distStrings[2] != ".PHONY: baz\n" {
t.Errorf("Expected .PHONY entry to declare baz, but got: %s", distStrings[2])
}
if !strings.Contains(distStrings[3], "$(call dist-for-goals,baz") ||
!strings.Contains(distStrings[3], ".intermediates/foo/android_common/dex/foo.jar:foo.jar") {
t.Errorf(
"Expected dist-for-goals entry to contain my_other_goal and new dest dir, but got: %s",
distStrings[3])
}
}
func TestDistsWithTag(t *testing.T) {
ctx, config := testJava(t, `
java_library {
name: "foo_without_tag",
srcs: ["a.java"],
compile_dex: true,
dists: [
{
targets: ["hi"],
},
],
}
java_library {
name: "foo_with_tag",
srcs: ["a.java"],
compile_dex: true,
dists: [
{
targets: ["hi"],
tag: ".jar",
},
],
}
`)
moduleWithoutTag := ctx.ModuleForTests("foo_without_tag", "android_common").Module()
moduleWithTag := ctx.ModuleForTests("foo_with_tag", "android_common").Module()
withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithoutTag)
withTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithTag)
if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 {
t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries))
}
distFilesWithoutTag := withoutTagEntries[0].DistFiles
distFilesWithTag := withTagEntries[0].DistFiles
if len(distFilesWithTag[".jar"]) != 1 ||
!strings.Contains(distFilesWithTag[".jar"][0].String(), "/javac/foo_with_tag.jar") {
t.Errorf("expected foo_with_tag's .jar-tagged DistFiles to contain classes.jar, got %v", distFilesWithTag[".jar"])
}
if len(distFilesWithoutTag[".jar"]) > 0 {
t.Errorf("did not expect foo_without_tag's .jar-tagged DistFiles to contain files, but got %v", distFilesWithoutTag[".jar"])
}
}

View File

@@ -479,7 +479,7 @@ type Module struct {
// list of the xref extraction files
kytheFiles android.Paths
distFile android.Path
distFiles android.TaggedDistFiles
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
@@ -1921,18 +1921,9 @@ func (j *Module) IsInstallable() bool {
// Java libraries (.jar file)
//
type LibraryProperties struct {
Dist struct {
// The tag of the output of this module that should be output.
Tag *string `android:"arch_variant"`
} `android:"arch_variant"`
}
type Library struct {
Module
libraryProperties LibraryProperties
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
}
@@ -1994,14 +1985,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
// Verify Dist.Tag is set to a supported output
if j.libraryProperties.Dist.Tag != nil {
distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag)
if err != nil {
ctx.PropertyErrorf("dist.tag", "%s", err.Error())
}
j.distFile = distFiles[0]
}
j.distFiles = j.GenerateTaggedDistFiles(ctx)
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2119,7 +2103,6 @@ func LibraryFactory() android.Module {
module := &Library{}
module.addHostAndDeviceProperties()
module.AddProperties(&module.libraryProperties)
module.initModuleAndImport(&module.ModuleBase)

View File

@@ -86,8 +86,11 @@ func (mod *Module) AndroidMk() android.AndroidMkData {
func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ctx.subAndroidMk(ret, binary.baseCompiler)
if binary.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
}
ret.Class = "EXECUTABLES"
ret.DistFile = binary.distFile
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
if binary.coverageOutputZipFile.Valid() {
@@ -127,7 +130,10 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An
ret.Class = "SHARED_LIBRARIES"
}
ret.DistFile = library.distFile
if library.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
}
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
if !library.rlib() {
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", library.unstrippedOutputFile.String())
@@ -143,7 +149,9 @@ func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *androi
ctx.subAndroidMk(ret, procMacro.baseCompiler)
ret.Class = "PROC_MACRO_LIBRARIES"
ret.DistFile = procMacro.distFile
if procMacro.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(procMacro.distFile.Path())
}
}

View File

@@ -291,7 +291,7 @@ func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "FAKE",
OutputFile: s.snapshotFile,
DistFile: s.snapshotFile,
DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path()),
Include: "$(BUILD_PHONY_PACKAGE)",
ExtraFooters: []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {