Merge "Support multiple dists per Android.bp module, and dist output selection." am: d06f11ee71 am: 3779799731

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1335521

Change-Id: I2ca43562972b4d50f1e9fd4a801026aa9abb6816
This commit is contained in:
Jingwen Chen 2020-06-26 08:25:04 +00:00 committed by Automerger Merge Worker
commit ce00ee318f
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

@ -483,7 +483,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
@ -1925,18 +1925,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)
}
@ -1998,14 +1989,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) {
@ -2123,7 +2107,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) {