Merge "Always build zipapex's unflattened."
diff --git a/android/arch.go b/android/arch.go
index ad812a4..b88b275 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -15,9 +15,11 @@
package android
import (
+ "encoding"
"fmt"
"reflect"
"runtime"
+ "strconv"
"strings"
"github.com/google/blueprint/proptools"
@@ -369,6 +371,23 @@
return a.Name
}
+var _ encoding.TextMarshaler = ArchType{}
+
+func (a ArchType) MarshalText() ([]byte, error) {
+ return []byte(strconv.Quote(a.String())), nil
+}
+
+var _ encoding.TextUnmarshaler = &ArchType{}
+
+func (a *ArchType) UnmarshalText(text []byte) error {
+ if u, ok := archTypeMap[string(text)]; ok {
+ *a = u
+ return nil
+ }
+
+ return fmt.Errorf("unknown ArchType %q", text)
+}
+
var BuildOs = func() OsType {
switch runtime.GOOS {
case "linux":
diff --git a/android/makevars.go b/android/makevars.go
index 366bb6b..2c2fb6f 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -92,10 +92,6 @@
///////////////////////////////////////////////////////////////////////////////
-func init() {
- RegisterSingletonType("makevars", makeVarsSingletonFunc)
-}
-
func makeVarsSingletonFunc() Singleton {
return &makeVarsSingleton{}
}
diff --git a/android/paths.go b/android/paths.go
index 0c65b83..31500ab 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -697,6 +697,16 @@
return p.withRel(path)
}
+// ReplaceExtension creates a new OutputPath with the extension replaced with ext.
+func (p OutputPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
+ if strings.Contains(ext, "/") {
+ reportPathErrorf(ctx, "extension %q cannot contain /", ext)
+ }
+ ret := PathForOutput(ctx, pathtools.ReplaceExtension(p.path, ext))
+ ret.rel = p.rel
+ return ret
+}
+
// PathForIntermediates returns an OutputPath representing the top-level
// intermediates directory.
func PathForIntermediates(ctx PathContext, paths ...string) OutputPath {
diff --git a/android/paths_test.go b/android/paths_test.go
index 1ed0734..1972591 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -691,3 +691,15 @@
})
}
}
+
+func ExampleOutputPath_ReplaceExtension() {
+ ctx := &configErrorWrapper{
+ config: TestConfig("out", nil),
+ }
+ p := PathForOutput(ctx, "system/framework/boot.art")
+ p2 := p.ReplaceExtension(ctx, "oat")
+ fmt.Println(p, p2)
+
+ // Output:
+ // out/system/framework/boot.art out/system/framework/boot.oat
+}
diff --git a/android/register.go b/android/register.go
index 6c88af1..10e14fe 100644
--- a/android/register.go
+++ b/android/register.go
@@ -99,5 +99,9 @@
registerMutators(ctx.Context, preArch, preDeps, postDeps)
+ // Register makevars after other singletons so they can export values through makevars
+ ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
+
+ // Register env last so that it can track all used environment variables
ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(EnvSingleton))
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 38018be..468b617 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -294,6 +294,15 @@
return c.Text(flag + arg)
}
+// FlagForEachArg adds the specified flag joined with each argument to the command line. The result is identical to
+// calling FlagWithArg for argument.
+func (c *RuleBuilderCommand) FlagForEachArg(flag string, args []string) *RuleBuilderCommand {
+ for _, arg := range args {
+ c.FlagWithArg(flag, arg)
+ }
+ return c
+}
+
// FlagWithArg adds the specified flag and list of arguments to the command line, with the arguments joined by sep
// and no separator between the flag and arguments. The flag and arguments should not contain input or output paths or
// the rule will not have them listed in its dependencies or outputs.
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index f7577a6..53a5b48 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -117,6 +117,14 @@
// ls --sort=time
}
+func ExampleRuleBuilderCommand_FlagForEachArg() {
+ fmt.Println(NewRuleBuilder().Command().
+ Tool("ls").
+ FlagForEachArg("--sort=", []string{"time", "size"}))
+ // Output:
+ // ls --sort=time --sort=size
+}
+
func ExampleRuleBuilderCommand_FlagForEachInput() {
fmt.Println(NewRuleBuilder().Command().
Tool("turbine").
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 319e36e..8fef010 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -17,6 +17,8 @@
import (
"encoding/json"
"io/ioutil"
+
+ "android/soong/android"
)
// GlobalConfig stores the configuration for dex preopting set by the product
@@ -66,9 +68,9 @@
EmptyDirectory string // path to an empty directory
- DefaultDexPreoptImageLocation map[string]string // default boot image location for each architecture
- CpuVariant map[string]string // cpu variant for each architecture
- InstructionSetFeatures map[string]string // instruction set for each architecture
+ DefaultDexPreoptImage map[android.ArchType]string // default boot image location for each architecture
+ CpuVariant map[android.ArchType]string // cpu variant for each architecture
+ InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
Tools Tools // paths to tools possibly used by the generated commands
}
@@ -103,8 +105,8 @@
UsesLibraries []string
LibraryPaths map[string]string
- Archs []string
- DexPreoptImageLocation string
+ Archs []android.ArchType
+ DexPreoptImages []string
PreoptExtractedApk bool // Overrides OnlyPreoptModules
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index c38fbff..cd931df 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -113,12 +113,9 @@
generateDM := shouldGenerateDM(module, global)
- for _, arch := range module.Archs {
- imageLocation := module.DexPreoptImageLocation
- if imageLocation == "" {
- imageLocation = global.DefaultDexPreoptImageLocation[arch]
- }
- dexpreoptCommand(global, module, rule, profile, arch, imageLocation, appImage, generateDM)
+ for i, arch := range module.Archs {
+ image := module.DexPreoptImages[i]
+ dexpreoptCommand(global, module, rule, arch, profile, image, appImage, generateDM)
}
}
}
@@ -181,7 +178,7 @@
}
func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
- profile, arch, bootImageLocation string, appImage, generateDM bool) {
+ arch android.ArchType, profile, bootImage string, appImage, generateDM bool) {
// HACK: make soname in Soong-generated .odex files match Make.
base := filepath.Base(module.DexLocation)
@@ -195,7 +192,7 @@
return filepath.Join(
filepath.Dir(path),
"oat",
- arch,
+ arch.String(),
pathtools.ReplaceExtension(filepath.Base(path), "odex"))
}
@@ -213,11 +210,11 @@
invocationPath := pathtools.ReplaceExtension(odexPath, "invocation")
- // bootImageLocation is $OUT/dex_bootjars/system/framework/boot.art, but dex2oat actually reads
- // $OUT/dex_bootjars/system/framework/arm64/boot.art
- var bootImagePath string
- if bootImageLocation != "" {
- bootImagePath = filepath.Join(filepath.Dir(bootImageLocation), arch, filepath.Base(bootImageLocation))
+ // bootImage is .../dex_bootjars/system/framework/arm64/boot.art, but dex2oat wants
+ // .../dex_bootjars/system/framework/boot.art on the command line
+ var bootImageLocation string
+ if bootImage != "" {
+ bootImageLocation = PathToLocation(bootImage, arch)
}
// Lists of used and optional libraries from the build config to be verified against the manifest in the APK
@@ -325,13 +322,13 @@
Flag("--runtime-arg").FlagWithArg("-Xbootclasspath-locations:", bcp_locations).
Flag("${class_loader_context_arg}").
Flag("${stored_class_loader_context_arg}").
- FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImagePath).
+ FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImage).
FlagWithInput("--dex-file=", module.DexPath).
FlagWithArg("--dex-location=", module.DexLocation).
FlagWithOutput("--oat-file=", odexPath).ImplicitOutput(vdexPath).
// Pass an empty directory, dex2oat shouldn't be reading arbitrary files
FlagWithArg("--android-root=", global.EmptyDirectory).
- FlagWithArg("--instruction-set=", arch).
+ FlagWithArg("--instruction-set=", arch.String()).
FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch]).
FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
Flag("--no-generate-debug-info").
@@ -521,6 +518,15 @@
return false
}
+// PathToLocation converts .../system/framework/arm64/boot.art to .../system/framework/boot.art
+func PathToLocation(path string, arch android.ArchType) string {
+ pathArch := filepath.Base(filepath.Dir(path))
+ if pathArch != arch.String() {
+ panic(fmt.Errorf("last directory in %q must be %q", path, arch.String()))
+ }
+ return filepath.Join(filepath.Dir(filepath.Dir(path)), filepath.Base(path))
+}
+
func pathForLibrary(module ModuleConfig, lib string) string {
path := module.LibraryPaths[lib]
if path == "" {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index d949852..be86190 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -48,7 +48,7 @@
Dex2oatXmx: "",
Dex2oatXms: "",
EmptyDirectory: "",
- DefaultDexPreoptImageLocation: nil,
+ DefaultDexPreoptImage: nil,
CpuVariant: nil,
InstructionSetFeatures: nil,
Tools: Tools{
@@ -63,28 +63,28 @@
}
var testModuleConfig = ModuleConfig{
- Name: "",
- DexLocation: "",
- BuildPath: "",
- DexPath: "",
- UncompressedDex: false,
- HasApkLibraries: false,
- PreoptFlags: nil,
- ProfileClassListing: "",
- ProfileIsTextListing: false,
- EnforceUsesLibraries: false,
- OptionalUsesLibraries: nil,
- UsesLibraries: nil,
- LibraryPaths: nil,
- Archs: nil,
- DexPreoptImageLocation: "",
- PreoptExtractedApk: false,
- NoCreateAppImage: false,
- ForceCreateAppImage: false,
- PresignedPrebuilt: false,
- NoStripping: false,
- StripInputPath: "",
- StripOutputPath: "",
+ Name: "",
+ DexLocation: "",
+ BuildPath: "",
+ DexPath: "",
+ UncompressedDex: false,
+ HasApkLibraries: false,
+ PreoptFlags: nil,
+ ProfileClassListing: "",
+ ProfileIsTextListing: false,
+ EnforceUsesLibraries: false,
+ OptionalUsesLibraries: nil,
+ UsesLibraries: nil,
+ LibraryPaths: nil,
+ Archs: []android.ArchType{android.Arm},
+ DexPreoptImages: []string{"system/framework/arm/boot.art"},
+ PreoptExtractedApk: false,
+ NoCreateAppImage: false,
+ ForceCreateAppImage: false,
+ PresignedPrebuilt: false,
+ NoStripping: false,
+ StripInputPath: "",
+ StripOutputPath: "",
}
func TestDexPreopt(t *testing.T) {
@@ -93,7 +93,6 @@
module.Name = "test"
module.DexLocation = "/system/app/test/test.apk"
module.BuildPath = "out/test/test.apk"
- module.Archs = []string{"arm"}
rule, err := GenerateDexpreoptRule(global, module)
if err != nil {
@@ -119,7 +118,6 @@
module.Name = "test"
module.DexLocation = "/system/app/test/test.apk"
module.BuildPath = "out/test/test.apk"
- module.Archs = []string{"arm"}
rule, err := GenerateDexpreoptRule(global, module)
if err != nil {
@@ -143,7 +141,6 @@
module.DexLocation = "/system/app/test/test.apk"
module.BuildPath = "out/test/test.apk"
module.ProfileClassListing = "profile"
- module.Archs = []string{"arm"}
rule, err := GenerateDexpreoptRule(global, module)
if err != nil {
@@ -193,7 +190,6 @@
module.Name = "test"
module.DexLocation = "/system/app/test/test.apk"
module.BuildPath = "out/test/test.apk"
- module.Archs = []string{"arm"}
module.StripInputPath = "$1"
module.StripOutputPath = "$2"
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 55662cf..cb6427b 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -100,14 +100,14 @@
return dexpreopt.GlobalConfig{}
}).(dexpreopt.GlobalConfig)
- var archs []string
+ var archs []android.ArchType
for _, a := range ctx.MultiTargets() {
- archs = append(archs, a.Arch.ArchType.String())
+ archs = append(archs, a.Arch.ArchType)
}
if len(archs) == 0 {
// assume this is a java library, dexpreopt for all arches for now
for _, target := range ctx.Config().Targets[android.Android] {
- archs = append(archs, target.Arch.ArchType.String())
+ archs = append(archs, target.Arch.ArchType)
}
if inList(ctx.ModuleName(), globalConfig.SystemServerJars) && !d.isSDKLibrary {
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
@@ -119,6 +119,11 @@
archs = archs[:1]
}
+ var images []string
+ for _, arch := range archs {
+ images = append(images, globalConfig.DefaultDexPreoptImage[arch])
+ }
+
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base())
@@ -161,8 +166,8 @@
UsesLibraries: nil,
LibraryPaths: nil,
- Archs: archs,
- DexPreoptImageLocation: "",
+ Archs: archs,
+ DexPreoptImages: images,
PreoptExtractedApk: false,
diff --git a/java/droiddoc.go b/java/droiddoc.go
index d893c09..cbe6be6 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -630,10 +630,10 @@
}
case libTag:
switch dep := module.(type) {
+ case SdkLibraryDependency:
+ deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...)
case Dependency:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
- case SdkLibraryDependency:
- deps.classpath = append(deps.classpath, dep.ImplementationJars(ctx, j.sdkVersion())...)
case android.SourceFileProducer:
checkProducesJars(ctx, dep)
deps.classpath = append(deps.classpath, dep.Srcs()...)
diff --git a/java/java.go b/java/java.go
index 3d7d6ad..2c7c1f6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -338,8 +338,8 @@
}
type SdkLibraryDependency interface {
- HeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths
- ImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths
+ SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths
+ SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths
}
type SrcDependency interface {
@@ -698,6 +698,15 @@
}
}
switch dep := module.(type) {
+ case SdkLibraryDependency:
+ switch tag {
+ case libTag:
+ deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ // names of sdk libs that are directly depended are exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+ default:
+ ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+ }
case Dependency:
switch tag {
case bootClasspathTag:
@@ -748,15 +757,6 @@
}
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
- case SdkLibraryDependency:
- switch tag {
- case libTag:
- deps.classpath = append(deps.classpath, dep.HeaderJars(ctx, j.sdkVersion())...)
- // names of sdk libs that are directly depended are exported
- j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
- default:
- ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
- }
case android.SourceFileProducer:
switch tag {
case libTag:
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 1b0fe75..85ce533 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -145,6 +145,9 @@
testApiFilePath android.Path
}
+var _ Dependency = (*sdkLibrary)(nil)
+var _ SdkLibraryDependency = (*sdkLibrary)(nil)
+
func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies to the stubs library
ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
@@ -596,7 +599,7 @@
}
// to satisfy SdkLibraryDependency interface
-func (module *sdkLibrary) HeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *sdkLibrary) SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths {
// This module is just a wrapper for the stubs.
if ctx.Config().UnbundledBuildPrebuiltSdks() {
return module.PrebuiltJars(ctx, sdkVersion)
@@ -612,7 +615,7 @@
}
// to satisfy SdkLibraryDependency interface
-func (module *sdkLibrary) ImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths {
+func (module *sdkLibrary) SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths {
// This module is just a wrapper for the stubs.
if ctx.Config().UnbundledBuildPrebuiltSdks() {
return module.PrebuiltJars(ctx, sdkVersion)
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 17decd0..b9713fe 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -74,7 +74,6 @@
}
var Configuration = map[string]PathConfig{
- "awk": Allowed,
"bash": Allowed,
"bc": Allowed,
"bzip2": Allowed,
@@ -127,6 +126,7 @@
"pkg-config": Forbidden,
// On Linux we'll use the toybox versions of these instead.
+ "awk": Toybox, // Strictly one-true-awk, but...
"basename": Toybox,
"cat": Toybox,
"chmod": Toybox,