aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2019-02-15 10:39:37 -0800
committerColin Cross <ccross@android.com>2019-02-20 22:06:09 -0800
commit69f59a33271bc0646282f698754384f6bfe90624 (patch)
treeabee22cf22276b0a14eb5133239596d34d7e9f10
parent501d7e594ab483932c7785ff9f7e3c46f985ee6f (diff)
downloadandroid_build_soong-69f59a33271bc0646282f698754384f6bfe90624.tar.gz
android_build_soong-69f59a33271bc0646282f698754384f6bfe90624.tar.bz2
android_build_soong-69f59a33271bc0646282f698754384f6bfe90624.zip
Make RuleBuilder methods take Paths
There are no more Make paths being used in Soong now that dexpreopting and hiddenapi are in Soong. Use the Path types in the inputs to RuleBuilder, and fix all users of RuleBuilder. This reapplies I886f803d9a3419a43b2cae412537645f94c5dfbf with fixes to disable preopt for Soong-only builds when the global dexpreopt.config doesn't exist. Test: all soong tests Test: m checkbuild Change-Id: I4dae9ecd5de22f062f9478ec8f0747f099cf8190
-rw-r--r--android/config.go12
-rw-r--r--android/rule_builder.go172
-rw-r--r--android/rule_builder_test.go175
-rw-r--r--android/variable.go4
-rw-r--r--dexpreopt/config.go240
-rw-r--r--dexpreopt/dexpreopt.go105
-rw-r--r--dexpreopt/dexpreopt_gen/dexpreopt_gen.go52
-rw-r--r--dexpreopt/dexpreopt_test.go173
-rw-r--r--java/dexpreopt.go48
-rw-r--r--java/dexpreopt_bootjars.go76
-rw-r--r--java/hiddenapi.go13
-rw-r--r--java/hiddenapi_singleton.go50
-rw-r--r--java/testing.go4
13 files changed, 646 insertions, 478 deletions
diff --git a/android/config.go b/android/config.go
index 7d2e8299..cfa2c0f7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -779,22 +779,10 @@ func (c *config) PreoptBootJars() []string {
return c.productVariables.PreoptBootJars
}
-func (c *config) DisableDexPreopt() bool {
- return Bool(c.productVariables.DisableDexPreopt)
-}
-
-func (c *config) DisableDexPreoptForModule(name string) bool {
- return Bool(c.productVariables.DisableDexPreopt) || InList(name, c.productVariables.DisableDexPreoptModules)
-}
-
func (c *config) DexpreoptGlobalConfig() string {
return String(c.productVariables.DexpreoptGlobalConfig)
}
-func (c *config) DexPreoptProfileDir() string {
- return String(c.productVariables.DexPreoptProfileDir)
-}
-
func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
return ExistentPathForSource(ctx, "frameworks", "base").Valid()
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 3b869470..5edd7b65 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -16,7 +16,6 @@ package android
import (
"fmt"
- "path/filepath"
"sort"
"strings"
@@ -29,7 +28,7 @@ import (
type RuleBuilder struct {
commands []*RuleBuilderCommand
installs RuleBuilderInstalls
- temporariesSet map[string]bool
+ temporariesSet map[WritablePath]bool
restat bool
missingDeps []string
}
@@ -37,13 +36,14 @@ type RuleBuilder struct {
// NewRuleBuilder returns a newly created RuleBuilder.
func NewRuleBuilder() *RuleBuilder {
return &RuleBuilder{
- temporariesSet: make(map[string]bool),
+ temporariesSet: make(map[WritablePath]bool),
}
}
// RuleBuilderInstall is a tuple of install from and to locations.
type RuleBuilderInstall struct {
- From, To string
+ From Path
+ To string
}
type RuleBuilderInstalls []RuleBuilderInstall
@@ -56,7 +56,7 @@ func (installs RuleBuilderInstalls) String() string {
if i != 0 {
sb.WriteRune(' ')
}
- sb.WriteString(install.From)
+ sb.WriteString(install.From.String())
sb.WriteRune(':')
sb.WriteString(install.To)
}
@@ -80,7 +80,7 @@ func (r *RuleBuilder) Restat() *RuleBuilder {
// Install associates an output of the rule with an install location, which can be retrieved later using
// RuleBuilder.Installs.
-func (r *RuleBuilder) Install(from, to string) {
+func (r *RuleBuilder) Install(from Path, to string) {
r.installs = append(r.installs, RuleBuilderInstall{from, to})
}
@@ -95,19 +95,22 @@ func (r *RuleBuilder) Command() *RuleBuilderCommand {
// Temporary marks an output of a command as an intermediate file that will be used as an input to another command
// in the same rule, and should not be listed in Outputs.
-func (r *RuleBuilder) Temporary(path string) {
+func (r *RuleBuilder) Temporary(path WritablePath) {
r.temporariesSet[path] = true
}
// DeleteTemporaryFiles adds a command to the rule that deletes any outputs that have been marked using Temporary
// when the rule runs. DeleteTemporaryFiles should be called after all calls to Temporary.
func (r *RuleBuilder) DeleteTemporaryFiles() {
- var temporariesList []string
+ var temporariesList WritablePaths
for intermediate := range r.temporariesSet {
temporariesList = append(temporariesList, intermediate)
}
- sort.Strings(temporariesList)
+
+ sort.Slice(temporariesList, func(i, j int) bool {
+ return temporariesList[i].String() < temporariesList[j].String()
+ })
r.Command().Text("rm").Flag("-f").Outputs(temporariesList)
}
@@ -115,32 +118,35 @@ func (r *RuleBuilder) DeleteTemporaryFiles() {
// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take input paths, such
// as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or RuleBuilderCommand.FlagWithInput. Inputs to a command
// that are also outputs of another command in the same RuleBuilder are filtered out.
-func (r *RuleBuilder) Inputs() []string {
+func (r *RuleBuilder) Inputs() Paths {
outputs := r.outputSet()
- inputs := make(map[string]bool)
+ inputs := make(map[string]Path)
for _, c := range r.commands {
for _, input := range c.inputs {
- if !outputs[input] {
- inputs[input] = true
+ if _, isOutput := outputs[input.String()]; !isOutput {
+ inputs[input.String()] = input
}
}
}
- var inputList []string
- for input := range inputs {
+ var inputList Paths
+ for _, input := range inputs {
inputList = append(inputList, input)
}
- sort.Strings(inputList)
+
+ sort.Slice(inputList, func(i, j int) bool {
+ return inputList[i].String() < inputList[j].String()
+ })
return inputList
}
-func (r *RuleBuilder) outputSet() map[string]bool {
- outputs := make(map[string]bool)
+func (r *RuleBuilder) outputSet() map[string]WritablePath {
+ outputs := make(map[string]WritablePath)
for _, c := range r.commands {
for _, output := range c.outputs {
- outputs[output] = true
+ outputs[output.String()] = output
}
}
return outputs
@@ -148,16 +154,20 @@ func (r *RuleBuilder) outputSet() map[string]bool {
// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take output paths, such
// as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or RuleBuilderCommand.FlagWithInput.
-func (r *RuleBuilder) Outputs() []string {
+func (r *RuleBuilder) Outputs() WritablePaths {
outputs := r.outputSet()
- var outputList []string
- for output := range outputs {
+ var outputList WritablePaths
+ for _, output := range outputs {
if !r.temporariesSet[output] {
outputList = append(outputList, output)
}
}
- sort.Strings(outputList)
+
+ sort.Slice(outputList, func(i, j int) bool {
+ return outputList[i].String() < outputList[j].String()
+ })
+
return outputList
}
@@ -166,11 +176,11 @@ func (r *RuleBuilder) Installs() RuleBuilderInstalls {
return append(RuleBuilderInstalls(nil), r.installs...)
}
-func (r *RuleBuilder) toolsSet() map[string]bool {
- tools := make(map[string]bool)
+func (r *RuleBuilder) toolsSet() map[string]Path {
+ tools := make(map[string]Path)
for _, c := range r.commands {
for _, tool := range c.tools {
- tools[tool] = true
+ tools[tool.String()] = tool
}
}
@@ -178,14 +188,18 @@ func (r *RuleBuilder) toolsSet() map[string]bool {
}
// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method.
-func (r *RuleBuilder) Tools() []string {
+func (r *RuleBuilder) Tools() Paths {
toolsSet := r.toolsSet()
- var toolsList []string
- for tool := range toolsSet {
+ var toolsList Paths
+ for _, tool := range toolsSet {
toolsList = append(toolsList, tool)
}
- sort.Strings(toolsList)
+
+ sort.Slice(toolsList, func(i, j int) bool {
+ return toolsList[i].String() < toolsList[j].String()
+ })
+
return toolsList
}
@@ -211,45 +225,10 @@ var _ BuilderContext = SingletonContext(nil)
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs.
func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string, desc string) {
- // TODO: convert RuleBuilder arguments and storage to Paths
- mctx, _ := ctx.(ModuleContext)
- var inputs Paths
- for _, input := range r.Inputs() {
- // Module output paths
- if mctx != nil {
- rel, isRel := MaybeRel(ctx, PathForModuleOut(mctx).String(), input)
- if isRel {
- inputs = append(inputs, PathForModuleOut(mctx, rel))
- continue
- }
- }
-
- // Other output paths
- rel, isRel := MaybeRel(ctx, PathForOutput(ctx).String(), input)
- if isRel {
- inputs = append(inputs, PathForOutput(ctx, rel))
- continue
- }
-
- // TODO: remove this once boot image is moved to where PathForOutput can find it.
- inputs = append(inputs, &unknownRulePath{input})
- }
-
- var outputs WritablePaths
- for _, output := range r.Outputs() {
- if mctx != nil {
- rel := Rel(ctx, PathForModuleOut(mctx).String(), output)
- outputs = append(outputs, PathForModuleOut(mctx, rel))
- } else {
- rel := Rel(ctx, PathForOutput(ctx).String(), output)
- outputs = append(outputs, PathForOutput(ctx, rel))
- }
- }
-
if len(r.missingDeps) > 0 {
ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
- Outputs: outputs,
+ Outputs: r.Outputs(),
Description: desc,
Args: map[string]string{
"error": "missing dependencies: " + strings.Join(r.missingDeps, ", "),
@@ -262,10 +241,10 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
ctx.Build(pctx, BuildParams{
Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
Command: strings.Join(proptools.NinjaEscape(r.Commands()), " && "),
- CommandDeps: r.Tools(),
+ CommandDeps: r.Tools().Strings(),
}),
- Implicits: inputs,
- Outputs: outputs,
+ Implicits: r.Inputs(),
+ Outputs: r.Outputs(),
Description: desc,
})
}
@@ -277,9 +256,9 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
// space as a separator from the previous method.
type RuleBuilderCommand struct {
buf []byte
- inputs []string
- outputs []string
- tools []string
+ inputs Paths
+ outputs WritablePaths
+ tools Paths
}
// Text adds the specified raw text to the command line. The text should not contain input or output paths or the
@@ -329,21 +308,21 @@ func (c *RuleBuilderCommand) FlagWithList(flag string, list []string, sep string
// Tool adds the specified tool path to the command line. The path will be also added to the dependencies returned by
// RuleBuilder.Tools.
-func (c *RuleBuilderCommand) Tool(path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand {
c.tools = append(c.tools, path)
- return c.Text(path)
+ return c.Text(path.String())
}
// Input adds the specified input path to the command line. The path will also be added to the dependencies returned by
// RuleBuilder.Inputs.
-func (c *RuleBuilderCommand) Input(path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand {
c.inputs = append(c.inputs, path)
- return c.Text(path)
+ return c.Text(path.String())
}
// Inputs adds the specified input paths to the command line, separated by spaces. The paths will also be added to the
// dependencies returned by RuleBuilder.Inputs.
-func (c *RuleBuilderCommand) Inputs(paths []string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Inputs(paths Paths) *RuleBuilderCommand {
for _, path := range paths {
c.Input(path)
}
@@ -352,28 +331,28 @@ func (c *RuleBuilderCommand) Inputs(paths []string) *RuleBuilderCommand {
// Implicit adds the specified input path to the dependencies returned by RuleBuilder.Inputs without modifying the
// command line.
-func (c *RuleBuilderCommand) Implicit(path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Implicit(path Path) *RuleBuilderCommand {
c.inputs = append(c.inputs, path)
return c
}
// Implicits adds the specified input paths to the dependencies returned by RuleBuilder.Inputs without modifying the
// command line.
-func (c *RuleBuilderCommand) Implicits(paths []string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand {
c.inputs = append(c.inputs, paths...)
return c
}
// Output adds the specified output path to the command line. The path will also be added to the outputs returned by
// RuleBuilder.Outputs.
-func (c *RuleBuilderCommand) Output(path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(path)
+ return c.Text(path.String())
}
// Outputs adds the specified output paths to the command line, separated by spaces. The paths will also be added to
// the outputs returned by RuleBuilder.Outputs.
-func (c *RuleBuilderCommand) Outputs(paths []string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) Outputs(paths WritablePaths) *RuleBuilderCommand {
for _, path := range paths {
c.Output(path)
}
@@ -382,37 +361,37 @@ func (c *RuleBuilderCommand) Outputs(paths []string) *RuleBuilderCommand {
// ImplicitOutput adds the specified output path to the dependencies returned by RuleBuilder.Outputs without modifying
// the command line.
-func (c *RuleBuilderCommand) ImplicitOutput(path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) ImplicitOutput(path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
return c
}
// ImplicitOutputs adds the specified output paths to the dependencies returned by RuleBuilder.Outputs without modifying
// the command line.
-func (c *RuleBuilderCommand) ImplicitOutputs(paths []string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) ImplicitOutputs(paths WritablePaths) *RuleBuilderCommand {
c.outputs = append(c.outputs, paths...)
return c
}
// FlagWithInput adds the specified flag and input path to the command line, with no separator between them. The path
// will also be added to the dependencies returned by RuleBuilder.Inputs.
-func (c *RuleBuilderCommand) FlagWithInput(flag, path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) FlagWithInput(flag string, path Path) *RuleBuilderCommand {
c.inputs = append(c.inputs, path)
- return c.Text(flag + path)
+ return c.Text(flag + path.String())
}
// FlagWithInputList adds the specified flag and input paths to the command line, with the inputs joined by sep
// and no separator between the flag and inputs. The input paths will also be added to the dependencies returned by
// RuleBuilder.Inputs.
-func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths []string, sep string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths Paths, sep string) *RuleBuilderCommand {
c.inputs = append(c.inputs, paths...)
- return c.FlagWithList(flag, paths, sep)
+ return c.FlagWithList(flag, paths.Strings(), sep)
}
// FlagForEachInput adds the specified flag joined with each input path to the command line. The input paths will also
// be added to the dependencies returned by RuleBuilder.Inputs. The result is identical to calling FlagWithInput for
// each input path.
-func (c *RuleBuilderCommand) FlagForEachInput(flag string, paths []string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) FlagForEachInput(flag string, paths Paths) *RuleBuilderCommand {
for _, path := range paths {
c.FlagWithInput(flag, path)
}
@@ -421,23 +400,12 @@ func (c *RuleBuilderCommand) FlagForEachInput(flag string, paths []string) *Rule
// FlagWithOutput adds the specified flag and output path to the command line, with no separator between them. The path
// will also be added to the outputs returned by RuleBuilder.Outputs.
-func (c *RuleBuilderCommand) FlagWithOutput(flag, path string) *RuleBuilderCommand {
+func (c *RuleBuilderCommand) FlagWithOutput(flag string, path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(flag + path)
+ return c.Text(flag + path.String())
}
// String returns the command line.
func (c *RuleBuilderCommand) String() string {
return string(c.buf)
}
-
-type unknownRulePath struct {
- path string
-}
-
-var _ Path = (*unknownRulePath)(nil)
-
-func (p *unknownRulePath) String() string { return p.path }
-func (p *unknownRulePath) Ext() string { return filepath.Ext(p.path) }
-func (p *unknownRulePath) Base() string { return filepath.Base(p.path) }
-func (p *unknownRulePath) Rel() string { return p.path }
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index f9473489..f738fafc 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -24,10 +24,30 @@ import (
"testing"
)
+func pathContext() PathContext {
+ return PathContextForTesting(TestConfig("out", nil),
+ map[string][]byte{
+ "ld": nil,
+ "a.o": nil,
+ "b.o": nil,
+ "cp": nil,
+ "a": nil,
+ "b": nil,
+ "ls": nil,
+ "turbine": nil,
+ "java": nil,
+ })
+}
+
func ExampleRuleBuilder() {
rule := NewRuleBuilder()
- rule.Command().Tool("ld").Inputs([]string{"a.o", "b.o"}).FlagWithOutput("-o ", "linked")
+ ctx := pathContext()
+
+ rule.Command().
+ Tool(PathForSource(ctx, "ld")).
+ Inputs(PathsForTesting("a.o", "b.o")).
+ FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
rule.Command().Text("echo success")
// To add the command to the build graph:
@@ -39,18 +59,26 @@ func ExampleRuleBuilder() {
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "ld a.o b.o -o linked && echo success"
+ // commands: "ld a.o b.o -o out/linked && echo success"
// tools: ["ld"]
// inputs: ["a.o" "b.o"]
- // outputs: ["linked"]
+ // outputs: ["out/linked"]
}
func ExampleRuleBuilder_Temporary() {
rule := NewRuleBuilder()
- rule.Command().Tool("cp").Input("a").Output("b")
- rule.Command().Tool("cp").Input("b").Output("c")
- rule.Temporary("b")
+ ctx := pathContext()
+
+ rule.Command().
+ Tool(PathForSource(ctx, "cp")).
+ Input(PathForSource(ctx, "a")).
+ Output(PathForOutput(ctx, "b"))
+ rule.Command().
+ Tool(PathForSource(ctx, "cp")).
+ Input(PathForOutput(ctx, "b")).
+ Output(PathForOutput(ctx, "c"))
+ rule.Temporary(PathForOutput(ctx, "b"))
fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
fmt.Printf("tools: %q\n", rule.Tools())
@@ -58,18 +86,26 @@ func ExampleRuleBuilder_Temporary() {
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "cp a b && cp b c"
+ // commands: "cp a out/b && cp out/b out/c"
// tools: ["cp"]
// inputs: ["a"]
- // outputs: ["c"]
+ // outputs: ["out/c"]
}
func ExampleRuleBuilder_DeleteTemporaryFiles() {
rule := NewRuleBuilder()
- rule.Command().Tool("cp").Input("a").Output("b")
- rule.Command().Tool("cp").Input("b").Output("c")
- rule.Temporary("b")
+ ctx := pathContext()
+
+ rule.Command().
+ Tool(PathForSource(ctx, "cp")).
+ Input(PathForSource(ctx, "a")).
+ Output(PathForOutput(ctx, "b"))
+ rule.Command().
+ Tool(PathForSource(ctx, "cp")).
+ Input(PathForOutput(ctx, "b")).
+ Output(PathForOutput(ctx, "c"))
+ rule.Temporary(PathForOutput(ctx, "b"))
rule.DeleteTemporaryFiles()
fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
@@ -78,93 +114,112 @@ func ExampleRuleBuilder_DeleteTemporaryFiles() {
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "cp a b && cp b c && rm -f b"
+ // commands: "cp a out/b && cp out/b out/c && rm -f out/b"
// tools: ["cp"]
// inputs: ["a"]
- // outputs: ["c"]
+ // outputs: ["out/c"]
}
func ExampleRuleBuilder_Installs() {
rule := NewRuleBuilder()
- rule.Command().Tool("ld").Inputs([]string{"a.o", "b.o"}).FlagWithOutput("-o ", "linked")
- rule.Install("linked", "/bin/linked")
- rule.Install("linked", "/sbin/linked")
+ ctx := pathContext()
+
+ out := PathForOutput(ctx, "linked")
+
+ rule.Command().
+ Tool(PathForSource(ctx, "ld")).
+ Inputs(PathsForTesting("a.o", "b.o")).
+ FlagWithOutput("-o ", out)
+ rule.Install(out, "/bin/linked")
+ rule.Install(out, "/sbin/linked")
fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
// Output:
- // rule.Installs().String() = "linked:/bin/linked linked:/sbin/linked"
+ // rule.Installs().String() = "out/linked:/bin/linked out/linked:/sbin/linked"
}
func ExampleRuleBuilderCommand() {
rule := NewRuleBuilder()
+ ctx := pathContext()
+
// chained
- rule.Command().Tool("ld").Inputs([]string{"a.o", "b.o"}).FlagWithOutput("-o ", "linked")
+ rule.Command().
+ Tool(PathForSource(ctx, "ld")).
+ Inputs(PathsForTesting("a.o", "b.o")).
+ FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
// unchained
cmd := rule.Command()
- cmd.Tool("ld")
- cmd.Inputs([]string{"a.o", "b.o"})
- cmd.FlagWithOutput("-o ", "linked")
+ cmd.Tool(PathForSource(ctx, "ld"))
+ cmd.Inputs(PathsForTesting("a.o", "b.o"))
+ cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
// mixed:
- cmd = rule.Command().Tool("ld")
- cmd.Inputs([]string{"a.o", "b.o"})
- cmd.FlagWithOutput("-o ", "linked")
+ cmd = rule.Command().Tool(PathForSource(ctx, "ld"))
+ cmd.Inputs(PathsForTesting("a.o", "b.o"))
+ cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
}
func ExampleRuleBuilderCommand_Flag() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("ls").Flag("-l"))
+ Tool(PathForSource(ctx, "ls")).Flag("-l"))
// Output:
// ls -l
}
func ExampleRuleBuilderCommand_FlagWithArg() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("ls").
+ Tool(PathForSource(ctx, "ls")).
FlagWithArg("--sort=", "time"))
// Output:
// ls --sort=time
}
func ExampleRuleBuilderCommand_FlagForEachArg() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("ls").
+ Tool(PathForSource(ctx, "ls")).
FlagForEachArg("--sort=", []string{"time", "size"}))
// Output:
// ls --sort=time --sort=size
}
func ExampleRuleBuilderCommand_FlagForEachInput() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("turbine").
- FlagForEachInput("--classpath ", []string{"a.jar", "b.jar"}))
+ Tool(PathForSource(ctx, "turbine")).
+ FlagForEachInput("--classpath ", PathsForTesting("a.jar", "b.jar")))
// Output:
// turbine --classpath a.jar --classpath b.jar
}
func ExampleRuleBuilderCommand_FlagWithInputList() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("java").
- FlagWithInputList("-classpath=", []string{"a.jar", "b.jar"}, ":"))
+ Tool(PathForSource(ctx, "java")).
+ FlagWithInputList("-classpath=", PathsForTesting("a.jar", "b.jar"), ":"))
// Output:
// java -classpath=a.jar:b.jar
}
func ExampleRuleBuilderCommand_FlagWithInput() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("java").
- FlagWithInput("-classpath=", "a"))
+ Tool(PathForSource(ctx, "java")).
+ FlagWithInput("-classpath=", PathForSource(ctx, "a")))
// Output:
// java -classpath=a
}
func ExampleRuleBuilderCommand_FlagWithList() {
+ ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
- Tool("ls").
+ Tool(PathForSource(ctx, "ls")).
FlagWithList("--sort=", []string{"time", "size"}, ","))
// Output:
// ls --sort=time,size
@@ -173,23 +228,35 @@ func ExampleRuleBuilderCommand_FlagWithList() {
func TestRuleBuilder(t *testing.T) {
rule := NewRuleBuilder()
+ fs := map[string][]byte{
+ "input": nil,
+ "Implicit": nil,
+ "Input": nil,
+ "Tool": nil,
+ "input2": nil,
+ "tool2": nil,
+ "input3": nil,
+ }
+
+ ctx := PathContextForTesting(TestConfig("out", nil), fs)
+
cmd := rule.Command().
Flag("Flag").
FlagWithArg("FlagWithArg=", "arg").
- FlagWithInput("FlagWithInput=", "input").
- FlagWithOutput("FlagWithOutput=", "output").
- Implicit("Implicit").
- ImplicitOutput("ImplicitOutput").
- Input("Input").
- Output("Output").
+ FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
+ FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
+ Implicit(PathForSource(ctx, "Implicit")).
+ ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
+ Input(PathForSource(ctx, "Input")).
+ Output(PathForOutput(ctx, "Output")).
Text("Text").
- Tool("Tool")
+ Tool(PathForSource(ctx, "Tool"))
rule.Command().
Text("command2").
- Input("input2").
- Output("output2").
- Tool("tool2")
+ Input(PathForSource(ctx, "input2")).
+ Output(PathForOutput(ctx, "output2")).
+ Tool(PathForSource(ctx, "tool2"))
// Test updates to the first command after the second command has been started
cmd.Text("after command2")
@@ -199,18 +266,18 @@ func TestRuleBuilder(t *testing.T) {
// Test a command that uses the output of a previous command as an input
rule.Command().
Text("command3").
- Input("input3").
- Input("output2").
- Output("output3")
+ Input(PathForSource(ctx, "input3")).
+ Input(PathForOutput(ctx, "output2")).
+ Output(PathForOutput(ctx, "output3"))
wantCommands := []string{
- "Flag FlagWithArg=arg FlagWithInput=input FlagWithOutput=output Input Output Text Tool after command2 old cmd",
- "command2 input2 output2 tool2",
- "command3 input3 output2 output3",
+ "Flag FlagWithArg=arg FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
+ "command2 input2 out/output2 tool2",
+ "command3 input3 out/output2 out/output3",
}
- wantInputs := []string{"Implicit", "Input", "input", "input2", "input3"}
- wantOutputs := []string{"ImplicitOutput", "Output", "output", "output2", "output3"}
- wantTools := []string{"Tool", "tool2"}
+ wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
+ wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
+ wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
if !reflect.DeepEqual(rule.Commands(), wantCommands) {
t.Errorf("\nwant rule.Commands() = %#v\n got %#v", wantCommands, rule.Commands())
@@ -262,7 +329,7 @@ func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
func testRuleBuilder_Build(ctx BuilderContext, in Path, out WritablePath) {
rule := NewRuleBuilder()
- rule.Command().Tool("cp").Input(in.String()).Output(out.String())
+ rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out)
rule.Build(pctx, ctx, "rule", "desc")
}
diff --git a/android/variable.go b/android/variable.go
index dc880b84..700d9174 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -203,10 +203,6 @@ type productVariables struct {
BootJars []string `json:",omitempty"`
PreoptBootJars []string `json:",omitempty"`
- DisableDexPreopt *bool `json:",omitempty"`
- DisableDexPreoptModules []string `json:",omitempty"`
- DexPreoptProfileDir *string `json:",omitempty"`
-
IntegerOverflowExcludePaths []string `json:",omitempty"`
EnableCFI *bool `json:",omitempty"`
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index ee3cc8db..99814019 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -17,6 +17,7 @@ package dexpreopt
import (
"encoding/json"
"io/ioutil"
+ "strings"
"android/soong/android"
)
@@ -25,6 +26,7 @@ import (
type GlobalConfig struct {
DefaultNoStripping bool // don't strip dex files by default
+ DisablePreopt bool // disable preopt for all modules
DisablePreoptModules []string // modules with preopt disabled by product-specific config
OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
@@ -32,7 +34,8 @@ type GlobalConfig struct {
HasSystemOther bool // store odex files that match PatternsOnSystemOther on the system_other partition
PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition
- DisableGenerateProfile bool // don't generate profiles
+ DisableGenerateProfile bool // don't generate profiles
+ ProfileDir string // directory to find profiles in
BootJars []string // modules for jars that form the boot class path
@@ -74,12 +77,13 @@ type GlobalConfig struct {
InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
// Only used for boot image
- DirtyImageObjects string // path to a dirty-image-objects file
- PreloadedClasses string // path to a preloaded-classes file
- BootImageProfiles []string // path to a boot-image-profile.txt file
- BootFlags string // extra flags to pass to dex2oat for the boot image
- Dex2oatImageXmx string // max heap size for dex2oat for the boot image
- Dex2oatImageXms string // initial heap size for dex2oat for the boot image
+ DirtyImageObjects android.OptionalPath // path to a dirty-image-objects file
+ PreloadedClasses android.OptionalPath // path to a preloaded-classes file
+ BootImageProfiles android.Paths // path to a boot-image-profile.txt file
+ UseProfileForBootImage bool // whether a profile should be used to compile the boot image
+ BootFlags string // extra flags to pass to dex2oat for the boot image
+ Dex2oatImageXmx string // max heap size for dex2oat for the boot image
+ Dex2oatImageXms string // initial heap size for dex2oat for the boot image
Tools Tools // paths to tools possibly used by the generated commands
}
@@ -87,38 +91,38 @@ type GlobalConfig struct {
// Tools contains paths to tools possibly used by the generated commands. If you add a new tool here you MUST add it
// to the order-only dependency list in DEXPREOPT_GEN_DEPS.
type Tools struct {
- Profman string
- Dex2oat string
- Aapt string
- SoongZip string
- Zip2zip string
-
- VerifyUsesLibraries string
- ConstructContext string
+ Profman android.Path
+ Dex2oat android.Path
+ Aapt android.Path
+ SoongZip android.Path
+ Zip2zip android.Path
+
+ VerifyUsesLibraries android.Path
+ ConstructContext android.Path
}
type ModuleConfig struct {
Name string
DexLocation string // dex location on device
- BuildPath string
- DexPath string
+ BuildPath android.OutputPath
+ DexPath android.Path
UncompressedDex bool
HasApkLibraries bool
PreoptFlags []string
- ProfileClassListing string
+ ProfileClassListing android.OptionalPath
ProfileIsTextListing bool
EnforceUsesLibraries bool
OptionalUsesLibraries []string
UsesLibraries []string
- LibraryPaths map[string]string
+ LibraryPaths map[string]android.Path
Archs []android.ArchType
- DexPreoptImages []string
+ DexPreoptImages []android.Path
- PreoptBootClassPathDexFiles []string // file paths of boot class path files
- PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
+ PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files
+ PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
PreoptExtractedApk bool // Overrides OnlyPreoptModules
@@ -128,24 +132,137 @@ type ModuleConfig struct {
PresignedPrebuilt bool
NoStripping bool
- StripInputPath string
- StripOutputPath string
+ StripInputPath android.Path
+ StripOutputPath android.WritablePath
}
-func LoadGlobalConfig(path string) (GlobalConfig, error) {
- config := GlobalConfig{}
- err := loadConfig(path, &config)
- return config, err
+func constructPath(ctx android.PathContext, path string) android.Path {
+ buildDirPrefix := ctx.Config().BuildDir() + "/"
+ if path == "" {
+ return nil
+ } else if strings.HasPrefix(path, buildDirPrefix) {
+ return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix))
+ } else {
+ return android.PathForSource(ctx, path)
+ }
+}
+
+func constructPaths(ctx android.PathContext, paths []string) android.Paths {
+ var ret android.Paths
+ for _, path := range paths {
+ ret = append(ret, constructPath(ctx, path))
+ }
+ return ret
+}
+
+func constructPathMap(ctx android.PathContext, paths map[string]string) map[string]android.Path {
+ ret := map[string]android.Path{}
+ for key, path := range paths {
+ ret[key] = constructPath(ctx, path)
+ }
+ return ret
+}
+
+func constructWritablePath(ctx android.PathContext, path string) android.WritablePath {
+ if path == "" {
+ return nil
+ }
+ return constructPath(ctx, path).(android.WritablePath)
+}
+
+// LoadGlobalConfig reads the global dexpreopt.config file into a GlobalConfig struct. It is used directly in Soong
+// and in dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by Make.
+func LoadGlobalConfig(ctx android.PathContext, path string) (GlobalConfig, error) {
+ type GlobalJSONConfig struct {
+ GlobalConfig
+
+ // Copies of entries in GlobalConfig that are not constructable without extra parameters. They will be
+ // used to construct the real value manually below.
+ DirtyImageObjects string
+ PreloadedClasses string
+ BootImageProfiles []string
+
+ Tools struct {
+ Profman string
+ Dex2oat string
+ Aapt string
+ SoongZip string
+ Zip2zip string
+
+ VerifyUsesLibraries string
+ ConstructContext string
+ }
+ }
+
+ config := GlobalJSONConfig{}
+ err := loadConfig(ctx, path, &config)
+ if err != nil {
+ return config.GlobalConfig, err
+ }
+
+ // Construct paths that require a PathContext.
+ config.GlobalConfig.DirtyImageObjects = android.OptionalPathForPath(constructPath(ctx, config.DirtyImageObjects))
+ config.GlobalConfig.PreloadedClasses = android.OptionalPathForPath(constructPath(ctx, config.PreloadedClasses))
+ config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles)
+
+ config.GlobalConfig.Tools.Profman = constructPath(ctx, config.Tools.Profman)
+ config.GlobalConfig.Tools.Dex2oat = constructPath(ctx, config.Tools.Dex2oat)
+ config.GlobalConfig.Tools.Aapt = constructPath(ctx, config.Tools.Aapt)
+ config.GlobalConfig.Tools.SoongZip = constructPath(ctx, config.Tools.SoongZip)
+ config.GlobalConfig.Tools.Zip2zip = constructPath(ctx, config.Tools.Zip2zip)
+ config.GlobalConfig.Tools.VerifyUsesLibraries = constructPath(ctx, config.Tools.VerifyUsesLibraries)
+ config.GlobalConfig.Tools.ConstructContext = constructPath(ctx, config.Tools.ConstructContext)
+
+ return config.GlobalConfig, nil
}
-func LoadModuleConfig(path string) (ModuleConfig, error) {
- config := ModuleConfig{}
- err := loadConfig(path, &config)
- return config, err
+// LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which
+// receives a ModuleConfig struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called from oMake to
+// read the module dexpreopt.config written by Make.
+func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) {
+ type ModuleJSONConfig struct {
+ ModuleConfig
+
+ // Copies of entries in ModuleConfig that are not constructable without extra parameters. They will be
+ // used to construct the real value manually below.
+ BuildPath string
+ DexPath string
+ ProfileClassListing string
+ LibraryPaths map[string]string
+ DexPreoptImages []string
+ PreoptBootClassPathDexFiles []string
+ StripInputPath string
+ StripOutputPath string
+ }
+
+ config := ModuleJSONConfig{}
+
+ err := loadConfig(ctx, path, &config)
+ if err != nil {
+ return config.ModuleConfig, err
+ }
+
+ // Construct paths that require a PathContext.
+ config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath)
+ config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
+ config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
+ config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
+ config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
+ config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
+ config.ModuleConfig.StripInputPath = constructPath(ctx, config.StripInputPath)
+ config.ModuleConfig.StripOutputPath = constructWritablePath(ctx, config.StripOutputPath)
+
+ return config.ModuleConfig, nil
}
-func loadConfig(path string, config interface{}) error {
- data, err := ioutil.ReadFile(path)
+func loadConfig(ctx android.PathContext, path string, config interface{}) error {
+ r, err := ctx.Fs().Open(path)
+ if err != nil {
+ return err
+ }
+ defer r.Close()
+
+ data, err := ioutil.ReadAll(r)
if err != nil {
return err
}
@@ -157,3 +274,58 @@ func loadConfig(path string, config interface{}) error {
return nil
}
+
+func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
+ return GlobalConfig{
+ DefaultNoStripping: false,
+ DisablePreopt: false,
+ DisablePreoptModules: nil,
+ OnlyPreoptBootImageAndSystemServer: false,
+ HasSystemOther: false,
+ PatternsOnSystemOther: nil,
+ DisableGenerateProfile: false,
+ ProfileDir: "",
+ BootJars: nil,
+ RuntimeApexJars: nil,
+ ProductUpdatableBootModules: nil,
+ ProductUpdatableBootLocations: nil,
+ SystemServerJars: nil,
+ SystemServerApps: nil,
+ SpeedApps: nil,
+ PreoptFlags: nil,
+ DefaultCompilerFilter: "",
+ SystemServerCompilerFilter: "",
+ GenerateDMFiles: false,
+ NeverAllowStripping: false,
+ NoDebugInfo: false,
+ AlwaysSystemServerDebugInfo: false,
+ NeverSystemServerDebugInfo: false,
+ AlwaysOtherDebugInfo: false,
+ NeverOtherDebugInfo: false,
+ MissingUsesLibraries: nil,
+ IsEng: false,
+ SanitizeLite: false,
+ DefaultAppImages: false,
+ Dex2oatXmx: "",
+ Dex2oatXms: "",
+ EmptyDirectory: "empty_dir",
+ CpuVariant: nil,
+ InstructionSetFeatures: nil,
+ DirtyImageObjects: android.OptionalPath{},
+ PreloadedClasses: android.OptionalPath{},
+ BootImageProfiles: nil,
+ UseProfileForBootImage: false,
+ BootFlags: "",
+ Dex2oatImageXmx: "",
+ Dex2oatImageXms: "",
+ Tools: Tools{
+ Profman: android.PathForTesting("profman"),
+ Dex2oat: android.PathForTesting("dex2oat"),
+ Aapt: android.PathForTesting("aapt"),
+ SoongZip: android.PathForTesting("soong_zip"),
+ Zip2zip: android.PathForTesting("zip2zip"),
+ VerifyUsesLibraries: android.PathForTesting("verify_uses_libraries.sh"),
+ ConstructContext: android.PathForTesting("construct_context.sh"),
+ },
+ }
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 7fdfb496..9e333c10 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -37,6 +37,7 @@ package dexpreopt
import (
"fmt"
"path/filepath"
+ "runtime"
"strings"
"android/soong/android"
@@ -52,7 +53,9 @@ const SystemOtherPartition = "/system_other/"
func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
defer func() {
if r := recover(); r != nil {
- if e, ok := r.(error); ok {
+ if _, ok := r.(runtime.Error); ok {
+ panic(r)
+ } else if e, ok := r.(error); ok {
err = e
rule = nil
} else {
@@ -86,10 +89,14 @@ func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *android.
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
-func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
+func GenerateDexpreoptRule(ctx android.PathContext,
+ global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
+
defer func() {
if r := recover(); r != nil {
- if e, ok := r.(error); ok {
+ if _, ok := r.(runtime.Error); ok {
+ panic(r)
+ } else if e, ok := r.(error); ok {
err = e
rule = nil
} else {
@@ -100,11 +107,11 @@ func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *andr
rule = android.NewRuleBuilder()
- generateProfile := module.ProfileClassListing != "" && !global.DisableGenerateProfile
+ generateProfile := module.ProfileClassListing.Valid() && !global.DisableGenerateProfile
- var profile string
+ var profile android.WritablePath
if generateProfile {
- profile = profileCommand(global, module, rule)
+ profile = profileCommand(ctx, global, module, rule)
}
if !dexpreoptDisabled(global, module) {
@@ -118,7 +125,7 @@ func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *andr
for i, arch := range module.Archs {
image := module.DexPreoptImages[i]
- dexpreoptCommand(global, module, rule, arch, profile, image, appImage, generateDM)
+ dexpreoptCommand(ctx, global, module, rule, arch, profile, image, appImage, generateDM)
}
}
}
@@ -143,8 +150,10 @@ func dexpreoptDisabled(global GlobalConfig, module ModuleConfig) bool {
return false
}
-func profileCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder) string {
- profilePath := filepath.Join(filepath.Dir(module.BuildPath), "profile.prof")
+func profileCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig,
+ rule *android.RuleBuilder) android.WritablePath {
+
+ profilePath := module.BuildPath.InSameDir(ctx, "profile.prof")
profileInstalledPath := module.DexLocation + ".prof"
if !module.ProfileIsTextListing {
@@ -158,13 +167,13 @@ func profileCommand(global GlobalConfig, module ModuleConfig, rule *android.Rule
if module.ProfileIsTextListing {
// The profile is a test listing of classes (used for framework jars).
// We need to generate the actual binary profile before being able to compile.
- cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing)
+ cmd.FlagWithInput("--create-profile-from=", module.ProfileClassListing.Path())
} else {
// The profile is binary profile (used for apps). Run it through profman to
// ensure the profile keys match the apk.
cmd.
Flag("--copy-and-update-profile-key").
- FlagWithInput("--profile-file=", module.ProfileClassListing)
+ FlagWithInput("--profile-file=", module.ProfileClassListing.Path())
}
cmd.
@@ -180,8 +189,8 @@ func profileCommand(global GlobalConfig, module ModuleConfig, rule *android.Rule
return profilePath
}
-func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
- arch android.ArchType, profile, bootImage string, appImage, generateDM bool) {
+func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder,
+ arch android.ArchType, profile, bootImage android.Path, appImage, generateDM bool) {
// HACK: make soname in Soong-generated .odex files match Make.
base := filepath.Base(module.DexLocation)
@@ -199,21 +208,21 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
pathtools.ReplaceExtension(filepath.Base(path), "odex"))
}
- odexPath := toOdexPath(filepath.Join(filepath.Dir(module.BuildPath), base))
+ odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
odexInstallPath := toOdexPath(module.DexLocation)
if odexOnSystemOther(module, global) {
odexInstallPath = strings.Replace(odexInstallPath, SystemPartition, SystemOtherPartition, 1)
}
- vdexPath := pathtools.ReplaceExtension(odexPath, "vdex")
+ vdexPath := odexPath.ReplaceExtension(ctx, "vdex")
vdexInstallPath := pathtools.ReplaceExtension(odexInstallPath, "vdex")
- invocationPath := pathtools.ReplaceExtension(odexPath, "invocation")
+ invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
// 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 != "" {
+ if bootImage != nil {
bootImageLocation = PathToLocation(bootImage, arch)
}
@@ -227,19 +236,21 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
var filteredOptionalUsesLibs []string
// The class loader context using paths in the build
- var classLoaderContextHost []string
+ var classLoaderContextHost android.Paths
// The class loader context using paths as they will be on the device
var classLoaderContextTarget []string
// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 28
- var conditionalClassLoaderContextHost28 []string
+ var conditionalClassLoaderContextHost28 android.Paths
var conditionalClassLoaderContextTarget28 []string
// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 29
- var conditionalClassLoaderContextHost29 []string
+ var conditionalClassLoaderContextHost29 android.Paths
var conditionalClassLoaderContextTarget29 []string
+ var classLoaderContextHostString string
+
if module.EnforceUsesLibraries {
verifyUsesLibs = copyOf(module.UsesLibraries)
verifyOptionalUsesLibs = copyOf(module.OptionalUsesLibraries)
@@ -281,31 +292,41 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
pathForLibrary(module, hidlBase))
conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
filepath.Join("/system/framework", hidlBase+".jar"))
+
+ classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":")
} else {
// Pass special class loader context to skip the classpath and collision check.
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
// to the &.
- classLoaderContextHost = []string{`\&`}
+ classLoaderContextHostString = `\&`
}
- rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath))
+ rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
rule.Command().FlagWithOutput("rm -f ", odexPath)
// Set values in the environment of the rule. These may be modified by construct_context.sh.
- rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=",
- strings.Join(classLoaderContextHost, ":"))
+ rule.Command().FlagWithArg("class_loader_context_arg=--class-loader-context=", classLoaderContextHostString)
rule.Command().Text(`stored_class_loader_context_arg=""`)
if module.EnforceUsesLibraries {
rule.Command().Textf(`uses_library_names="%s"`, strings.Join(verifyUsesLibs, " "))
rule.Command().Textf(`optional_uses_library_names="%s"`, strings.Join(verifyOptionalUsesLibs, " "))
rule.Command().Textf(`aapt_binary="%s"`, global.Tools.Aapt)
- rule.Command().Textf(`dex_preopt_host_libraries="%s"`, strings.Join(classLoaderContextHost, " "))
- rule.Command().Textf(`dex_preopt_target_libraries="%s"`, strings.Join(classLoaderContextTarget, " "))
- rule.Command().Textf(`conditional_host_libs_28="%s"`, strings.Join(conditionalClassLoaderContextHost28, " "))
- rule.Command().Textf(`conditional_target_libs_28="%s"`, strings.Join(conditionalClassLoaderContextTarget28, " "))
- rule.Command().Textf(`conditional_host_libs_29="%s"`, strings.Join(conditionalClassLoaderContextHost29, " "))
- rule.Command().Textf(`conditional_target_libs_29="%s"`, strings.Join(conditionalClassLoaderContextTarget29, " "))
+ rule.Command().Textf(`dex_preopt_host_libraries="%s"`,
+ strings.Join(classLoaderContextHost.Strings(), " ")).
+ Implicits(classLoaderContextHost)
+ rule.Command().Textf(`dex_preopt_target_libraries="%s"`,
+ strings.Join(classLoaderContextTarget, " "))
+ rule.Command().Textf(`conditional_host_libs_28="%s"`,
+ strings.Join(conditionalClassLoaderContextHost28.Strings(), " ")).
+ Implicits(conditionalClassLoaderContextHost28)
+ rule.Command().Textf(`conditional_target_libs_28="%s"`,
+ strings.Join(conditionalClassLoaderContextTarget28, " "))
+ rule.Command().Textf(`conditional_host_libs_29="%s"`,
+ strings.Join(conditionalClassLoaderContextHost29.Strings(), " ")).
+ Implicits(conditionalClassLoaderContextHost29)
+ rule.Command().Textf(`conditional_target_libs_29="%s"`,
+ strings.Join(conditionalClassLoaderContextTarget29, " "))
rule.Command().Text("source").Tool(global.Tools.VerifyUsesLibraries).Input(module.DexPath)
rule.Command().Text("source").Tool(global.Tools.ConstructContext)
}
@@ -364,7 +385,7 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
// Apps loaded into system server, and apps the product default to being compiled with the
// 'speed' compiler filter.
compilerFilter = "speed"
- } else if profile != "" {
+ } else if profile != nil {
// For non system server jars, use speed-profile when we have a profile.
compilerFilter = "speed-profile"
} else if global.DefaultCompilerFilter != "" {
@@ -377,9 +398,9 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
if generateDM {
cmd.FlagWithArg("--copy-dex-files=", "false")
- dmPath := filepath.Join(filepath.Dir(module.BuildPath), "generated.dm")
+ dmPath := module.BuildPath.InSameDir(ctx, "generated.dm")
dmInstalledPath := pathtools.ReplaceExtension(module.DexLocation, "dm")
- tmpPath := filepath.Join(filepath.Dir(module.BuildPath), "primary.vdex")
+ tmpPath := module.BuildPath.InSameDir(ctx, "primary.vdex")
rule.Command().Text("cp -f").Input(vdexPath).Output(tmpPath)
rule.Command().Tool(global.Tools.SoongZip).
FlagWithArg("-L", "9").
@@ -428,15 +449,15 @@ func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.Ru
cmd.FlagWithArg("--compilation-reason=", "prebuilt")
if appImage {
- appImagePath := pathtools.ReplaceExtension(odexPath, "art")
+ appImagePath := odexPath.ReplaceExtension(ctx, "art")
appImageInstallPath := pathtools.ReplaceExtension(odexInstallPath, "art")
cmd.FlagWithOutput("--app-image-file=", appImagePath).
FlagWithArg("--image-format=", "lz4")
rule.Install(appImagePath, appImageInstallPath)
}
- if profile != "" {
- cmd.FlagWithArg("--profile-file=", profile)
+ if profile != nil {
+ cmd.FlagWithInput("--profile-file=", profile)
}
rule.Install(odexPath, odexInstallPath)
@@ -522,17 +543,17 @@ func odexOnSystemOther(module ModuleConfig, global GlobalConfig) bool {
}
// 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))
+func PathToLocation(path android.Path, arch android.ArchType) string {
+ pathArch := filepath.Base(filepath.Dir(path.String()))
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))
+ return filepath.Join(filepath.Dir(filepath.Dir(path.String())), filepath.Base(path.String()))
}
-func pathForLibrary(module ModuleConfig, lib string) string {
- path := module.LibraryPaths[lib]
- if path == "" {
+func pathForLibrary(module ModuleConfig, lib string) android.Path {
+ path, ok := module.LibraryPaths[lib]
+ if !ok {
panic(fmt.Errorf("unknown library path for %q", lib))
}
return path
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index cc3c1f10..c72f6842 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -21,6 +21,7 @@ import (
"os"
"path/filepath"
"runtime"
+ "strings"
"android/soong/android"
"android/soong/dexpreopt"
@@ -33,8 +34,17 @@ var (
stripScriptPath = flag.String("strip_script", "", "path to output strip script")
globalConfigPath = flag.String("global", "", "path to global configuration file")
moduleConfigPath = flag.String("module", "", "path to module configuration file")
+ outDir = flag.String("out_dir", "", "path to output directory")
)
+type pathContext struct {
+ config android.Config
+}
+
+func (x *pathContext) Fs() pathtools.FileSystem { return pathtools.OsFs }
+func (x *pathContext) Config() android.Config { return x.config }
+func (x *pathContext) AddNinjaFileDeps(...string) {}
+
func main() {
flag.Parse()
@@ -66,18 +76,26 @@ func main() {
usage("path to module configuration file is required")
}
- globalConfig, err := dexpreopt.LoadGlobalConfig(*globalConfigPath)
+ ctx := &pathContext{android.TestConfig(*outDir, nil)}
+
+ globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
os.Exit(2)
}
- moduleConfig, err := dexpreopt.LoadModuleConfig(*moduleConfigPath)
+ moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, *moduleConfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
os.Exit(2)
}
+ // This shouldn't be using *PathForTesting, but it's outside of soong_build so its OK for now.
+ moduleConfig.StripInputPath = android.PathForTesting("$1")
+ moduleConfig.StripOutputPath = android.WritablePathForTesting("$2")
+
+ moduleConfig.DexPath = android.PathForTesting("$1")
+
defer func() {
if r := recover(); r != nil {
switch x := r.(type) {
@@ -92,30 +110,30 @@ func main() {
}
}()
- writeScripts(globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
+ writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
}
-func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
+func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
dexpreoptScriptPath, stripScriptPath string) {
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(global, module)
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, module)
if err != nil {
panic(err)
}
- installDir := filepath.Join(filepath.Dir(module.BuildPath), "dexpreopt_install")
+ installDir := module.BuildPath.InSameDir(ctx, "dexpreopt_install")
- dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir)
- dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir)
+ dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir.String())
+ dexpreoptRule.Command().FlagWithArg("mkdir -p ", installDir.String())
for _, install := range dexpreoptRule.Installs() {
- installPath := filepath.Join(installDir, install.To)
- dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath))
+ installPath := installDir.Join(ctx, strings.TrimPrefix(install.To, "/"))
+ dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath.String()))
dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
}
dexpreoptRule.Command().Tool(global.Tools.SoongZip).
- FlagWithOutput("-o ", "$2").
- FlagWithArg("-C ", installDir).
- FlagWithArg("-D ", installDir)
+ FlagWithArg("-o ", "$2").
+ FlagWithArg("-C ", installDir.String()).
+ FlagWithArg("-D ", installDir.String())
stripRule, err := dexpreopt.GenerateStripRule(global, module)
if err != nil {
@@ -139,7 +157,7 @@ func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
for _, input := range rule.Inputs() {
// Assume the rule that ran the script already has a dependency on the input file passed on the
// command line.
- if input != "$1" {
+ if input.String() != "$1" {
fmt.Fprintf(depFile, ` %s \`+"\n", input)
}
}
@@ -159,13 +177,13 @@ func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
}
// The written scripts will assume the input is $1 and the output is $2
- if module.DexPath != "$1" {
+ if module.DexPath.String() != "$1" {
panic(fmt.Errorf("module.DexPath must be '$1', was %q", module.DexPath))
}
- if module.StripInputPath != "$1" {
+ if module.StripInputPath.String() != "$1" {
panic(fmt.Errorf("module.StripInputPath must be '$1', was %q", module.StripInputPath))
}
- if module.StripOutputPath != "$2" {
+ if module.StripOutputPath.String() != "$2" {
panic(fmt.Errorf("module.StripOutputPath must be '$2', was %q", module.StripOutputPath))
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 949f91f3..2a58ab9c 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -21,98 +21,47 @@ import (
"testing"
)
-var testGlobalConfig = GlobalConfig{
- DefaultNoStripping: false,
- DisablePreoptModules: nil,
- OnlyPreoptBootImageAndSystemServer: false,
- HasSystemOther: false,
- PatternsOnSystemOther: nil,
- DisableGenerateProfile: false,
- BootJars: nil,
- RuntimeApexJars: nil,
- ProductUpdatableBootModules: nil,
- ProductUpdatableBootLocations: nil,
- SystemServerJars: nil,
- SystemServerApps: nil,
- SpeedApps: nil,
- PreoptFlags: nil,
- DefaultCompilerFilter: "",
- SystemServerCompilerFilter: "",
- GenerateDMFiles: false,
- NeverAllowStripping: false,
- NoDebugInfo: false,
- AlwaysSystemServerDebugInfo: false,
- NeverSystemServerDebugInfo: false,
- AlwaysOtherDebugInfo: false,
- NeverOtherDebugInfo: false,
- MissingUsesLibraries: nil,
- IsEng: false,
- SanitizeLite: false,
- DefaultAppImages: false,
- Dex2oatXmx: "",
- Dex2oatXms: "",
- EmptyDirectory: "",
- CpuVariant: nil,
- InstructionSetFeatures: nil,
- DirtyImageObjects: "",
- PreloadedClasses: "",
- BootImageProfiles: nil,
- BootFlags: "",
- Dex2oatImageXmx: "",
- Dex2oatImageXms: "",
- Tools: Tools{
- Profman: "profman",
- Dex2oat: "dex2oat",
- Aapt: "aapt",
- SoongZip: "soong_zip",
- Zip2zip: "zip2zip",
- VerifyUsesLibraries: "verify_uses_libraries.sh",
- ConstructContext: "construct_context.sh",
- },
-}
-
-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: []android.ArchType{android.Arm},
- DexPreoptImages: []string{"system/framework/arm/boot.art"},
- PreoptBootClassPathDexFiles: nil,
- PreoptBootClassPathDexLocations: nil,
- PreoptExtractedApk: false,
- NoCreateAppImage: false,
- ForceCreateAppImage: false,
- PresignedPrebuilt: false,
- NoStripping: false,
- StripInputPath: "",
- StripOutputPath: "",
+func testModuleConfig(ctx android.PathContext) ModuleConfig {
+ return ModuleConfig{
+ Name: "test",
+ DexLocation: "/system/app/test/test.apk",
+ BuildPath: android.PathForOutput(ctx, "test/test.apk"),
+ DexPath: android.PathForOutput(ctx, "test/dex/test.jar"),
+ UncompressedDex: false,
+ HasApkLibraries: false,
+ PreoptFlags: nil,
+ ProfileClassListing: android.OptionalPath{},
+ ProfileIsTextListing: false,
+ EnforceUsesLibraries: false,
+ OptionalUsesLibraries: nil,
+ UsesLibraries: nil,
+ LibraryPaths: nil,
+ Archs: []android.ArchType{android.Arm},
+ DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
+ PreoptBootClassPathDexFiles: nil,
+ PreoptBootClassPathDexLocations: nil,
+ PreoptExtractedApk: false,
+ NoCreateAppImage: false,
+ ForceCreateAppImage: false,
+ PresignedPrebuilt: false,
+ NoStripping: false,
+ StripInputPath: android.PathForOutput(ctx, "unstripped/test.apk"),
+ StripOutputPath: android.PathForOutput(ctx, "stripped/test.apk"),
+ }
}
func TestDexPreopt(t *testing.T) {
- global, module := testGlobalConfig, testModuleConfig
+ ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
+ global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
- module.Name = "test"
- module.DexLocation = "/system/app/test/test.apk"
- module.BuildPath = "out/test/test.apk"
-
- rule, err := GenerateDexpreoptRule(global, module)
+ rule, err := GenerateDexpreoptRule(ctx, global, module)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
wantInstalls := android.RuleBuilderInstalls{
- {"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"},
- {"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
}
if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -122,13 +71,11 @@ func TestDexPreopt(t *testing.T) {
func TestDexPreoptStrip(t *testing.T) {
// Test that we panic if we strip in a configuration where stripping is not allowed.
- global, module := testGlobalConfig, testModuleConfig
+ ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
+ global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
global.NeverAllowStripping = true
module.NoStripping = false
- module.Name = "test"
- module.DexLocation = "/system/app/test/test.apk"
- module.BuildPath = "out/test/test.apk"
_, err := GenerateStripRule(global, module)
if err == nil {
@@ -137,23 +84,20 @@ func TestDexPreoptStrip(t *testing.T) {
}
func TestDexPreoptSystemOther(t *testing.T) {
- global, module := testGlobalConfig, testModuleConfig
+ ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
+ global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
global.HasSystemOther = true
global.PatternsOnSystemOther = []string{"app/%"}
- module.Name = "test"
- module.DexLocation = "/system/app/test/test.apk"
- module.BuildPath = "out/test/test.apk"
-
- rule, err := GenerateDexpreoptRule(global, module)
+ rule, err := GenerateDexpreoptRule(ctx, global, module)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
wantInstalls := android.RuleBuilderInstalls{
- {"out/test/oat/arm/package.odex", "/system_other/app/test/oat/arm/test.odex"},
- {"out/test/oat/arm/package.vdex", "/system_other/app/test/oat/arm/test.vdex"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system_other/app/test/oat/arm/test.odex"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system_other/app/test/oat/arm/test.vdex"},
}
if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -162,23 +106,21 @@ func TestDexPreoptSystemOther(t *testing.T) {
}
func TestDexPreoptProfile(t *testing.T) {
- global, module := testGlobalConfig, testModuleConfig
+ ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
+ global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
- module.Name = "test"
- module.DexLocation = "/system/app/test/test.apk"
- module.BuildPath = "out/test/test.apk"
- module.ProfileClassListing = "profile"
+ module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
- rule, err := GenerateDexpreoptRule(global, module)
+ rule, err := GenerateDexpreoptRule(ctx, global, module)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
wantInstalls := android.RuleBuilderInstalls{
- {"out/test/profile.prof", "/system/app/test/test.apk.prof"},
- {"out/test/oat/arm/package.art", "/system/app/test/oat/arm/test.art"},
- {"out/test/oat/arm/package.odex", "/system/app/test/oat/arm/test.odex"},
- {"out/test/oat/arm/package.vdex", "/system/app/test/oat/arm/test.vdex"},
+ {android.PathForOutput(ctx, "test/profile.prof"), "/system/app/test/test.apk.prof"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.art"), "/system/app/test/oat/arm/test.art"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.odex"), "/system/app/test/oat/arm/test.odex"},
+ {android.PathForOutput(ctx, "test/oat/arm/package.vdex"), "/system/app/test/oat/arm/test.vdex"},
}
if !reflect.DeepEqual(rule.Installs(), wantInstalls) {
@@ -212,29 +154,24 @@ func TestStripDex(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- global, module := testGlobalConfig, testModuleConfig
-
- module.Name = "test"
- module.DexLocation = "/system/app/test/test.apk"
- module.BuildPath = "out/test/test.apk"
- module.StripInputPath = "$1"
- module.StripOutputPath = "$2"
+ ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
+ global, module := GlobalConfigForTests(ctx), testModuleConfig(ctx)
test.setup(&global, &module)
rule, err := GenerateStripRule(global, module)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
if test.strip {
- want := `zip2zip -i $1 -o $2 -x "classes*.dex"`
+ want := `zip2zip -i out/unstripped/test.apk -o out/stripped/test.apk -x "classes*.dex"`
if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
t.Errorf("\nwant commands[0] to have:\n %v\ngot:\n %v", want, rule.Commands()[0])
}
} else {
wantCommands := []string{
- "cp -f $1 $2",
+ "cp -f out/unstripped/test.apk out/stripped/test.apk",
}
if !reflect.DeepEqual(rule.Commands(), wantCommands) {
t.Errorf("\nwant commands:\n %v\ngot:\n %v", wantCommands, rule.Commands())
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 0a565297..ceed9cb8 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -56,11 +56,13 @@ type DexpreoptProperties struct {
}
func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
- if ctx.Config().DisableDexPreopt() {
+ global := dexpreoptGlobalConfig(ctx)
+
+ if global.DisablePreopt {
return true
}
- if ctx.Config().DisableDexPreoptForModule(ctx.ModuleName()) {
+ if inList(ctx.ModuleName(), global.DisablePreoptModules) {
return true
}
@@ -86,18 +88,30 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
}
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
+var dexpreoptTestGlobalConfigKey = android.NewOnceKey("TestDexpreoptGlobalConfig")
+
+func setDexpreoptGlobalConfig(config android.Config, globalConfig dexpreopt.GlobalConfig) {
+ config.Once(dexpreoptTestGlobalConfigKey, func() interface{} { return globalConfig })
+}
func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
ctx.AddNinjaFileDeps(f)
- globalConfig, err := dexpreopt.LoadGlobalConfig(f)
+ globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, f)
if err != nil {
panic(err)
}
return globalConfig
}
- return dexpreopt.GlobalConfig{}
+
+ // No global config filename set, see if there is a test config set
+ return ctx.Config().Once(dexpreoptTestGlobalConfigKey, func() interface{} {
+ // Nope, return a config with preopting disabled
+ return dexpreopt.GlobalConfig{
+ DisablePreopt: true,
+ }
+ })
}).(dexpreopt.GlobalConfig)
}
@@ -131,17 +145,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
archs = archs[:1]
}
- var images []string
+ var images android.Paths
for _, arch := range archs {
- images = append(images, info.images[arch].String())
+ images = append(images, info.images[arch])
}
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base())
- deps := android.Paths{dexJarFile}
-
var profileClassListing android.OptionalPath
profileIsTextListing := false
if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) {
@@ -153,24 +165,20 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
profileIsTextListing = true
} else {
profileClassListing = android.ExistentPathForSource(ctx,
- ctx.Config().DexPreoptProfileDir(), ctx.ModuleName()+".prof")
+ info.global.ProfileDir, ctx.ModuleName()+".prof")
}
}
- if profileClassListing.Valid() {
- deps = append(deps, profileClassListing.Path())
- }
-
dexpreoptConfig := dexpreopt.ModuleConfig{
Name: ctx.ModuleName(),
DexLocation: dexLocation,
- BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").String(),
- DexPath: dexJarFile.String(),
+ BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
+ DexPath: dexJarFile,
UncompressedDex: d.uncompressedDex,
HasApkLibraries: false,
PreoptFlags: nil,
- ProfileClassListing: profileClassListing.String(),
+ ProfileClassListing: profileClassListing,
ProfileIsTextListing: profileIsTextListing,
EnforceUsesLibraries: false,
@@ -181,7 +189,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
Archs: archs,
DexPreoptImages: images,
- PreoptBootClassPathDexFiles: info.preoptBootDex.Strings(),
+ PreoptBootClassPathDexFiles: info.preoptBootDex.Paths(),
PreoptBootClassPathDexLocations: info.preoptBootLocations,
PreoptExtractedApk: false,
@@ -190,11 +198,11 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
NoStripping: Bool(d.dexpreoptProperties.Dex_preopt.No_stripping),
- StripInputPath: dexJarFile.String(),
- StripOutputPath: strippedDexJarFile.String(),
+ StripInputPath: dexJarFile,
+ StripOutputPath: strippedDexJarFile.OutputPath,
}
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(info.global, dexpreoptConfig)
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, info.global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return dexJarFile
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 88534283..fe425b1f 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -240,7 +240,7 @@ func (dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
profile := bootImageProfileRule(ctx, info, missingDeps)
- if !ctx.Config().DisableDexPreopt() {
+ if !info.global.DisablePreopt {
targets := ctx.Config().Targets[android.Android]
if ctx.Config().SecondArchIsTranslated() {
targets = targets[:1]
@@ -259,7 +259,7 @@ func dexPreoptBootImageRule(ctx android.SingletonContext, info *bootJarsInfo,
symbolsFile := symbolsDir.Join(ctx, "boot.oat")
outputDir := info.dir.Join(ctx, "system/framework", arch.String())
outputPath := info.images[arch]
- oatLocation := pathtools.ReplaceExtension(dexpreopt.PathToLocation(outputPath.String(), arch), "oat")
+ oatLocation := pathtools.ReplaceExtension(dexpreopt.PathToLocation(outputPath, arch), "oat")
rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps)
@@ -289,31 +289,31 @@ func dexPreoptBootImageRule(ctx android.SingletonContext, info *bootJarsInfo,
cmd.Tool(info.global.Tools.Dex2oat).
Flag("--avoid-storing-invocation").
- FlagWithOutput("--write-invocation-to=", invocationPath.String()).ImplicitOutput(invocationPath.String()).
+ FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", info.global.Dex2oatImageXms).
Flag("--runtime-arg").FlagWithArg("-Xmx", info.global.Dex2oatImageXmx)
- if profile == nil {
- cmd.FlagWithArg("--image-classes=", info.global.PreloadedClasses)
- } else {
+ if profile != nil {
cmd.FlagWithArg("--compiler-filter=", "speed-profile")
- cmd.FlagWithInput("--profile-file=", profile.String())
+ cmd.FlagWithInput("--profile-file=", profile)
+ } else if info.global.PreloadedClasses.Valid() {
+ cmd.FlagWithInput("--image-classes=", info.global.PreloadedClasses.Path())
}
- if info.global.DirtyImageObjects != "" {
- cmd.FlagWithArg("--dirty-image-objects=", info.global.DirtyImageObjects)
+ if info.global.DirtyImageObjects.Valid() {
+ cmd.FlagWithInput("--dirty-image-objects=", info.global.DirtyImageObjects.Path())
}
cmd.
- FlagForEachInput("--dex-file=", info.preoptBootDex.Strings()).
+ FlagForEachInput("--dex-file=", info.preoptBootDex.Paths()).
FlagForEachArg("--dex-location=", info.preoptBootLocations).
Flag("--generate-debug-info").
Flag("--generate-build-id").
- FlagWithArg("--oat-symbols=", symbolsFile.String()).
+ FlagWithOutput("--oat-symbols=", symbolsFile).
Flag("--strip").
- FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat").String()).
+ FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat")).
FlagWithArg("--oat-location=", oatLocation).
- FlagWithOutput("--image=", outputPath.String()).
+ FlagWithOutput("--image=", outputPath).
FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress()).
FlagWithArg("--instruction-set=", arch.String()).
FlagWithArg("--instruction-set-variant=", info.global.CpuVariant[arch]).
@@ -358,21 +358,21 @@ func dexPreoptBootImageRule(ctx android.SingletonContext, info *bootJarsInfo,
extraFiles = append(extraFiles, art, oat, vdex, unstrippedOat)
// Install the .oat and .art files.
- rule.Install(art.String(), filepath.Join(installDir, art.Base()))
- rule.Install(oat.String(), filepath.Join(installDir, oat.Base()))
+ rule.Install(art, filepath.Join(installDir, art.Base()))
+ rule.Install(oat, filepath.Join(installDir, oat.Base()))
// The vdex files are identical between architectures, install them to a shared location. The Make rules will
// only use the install rules for one architecture, and will create symlinks into the architecture-specific
// directories.
vdexInstalls = append(vdexInstalls,
- android.RuleBuilderInstall{vdex.String(), filepath.Join(vdexInstallDir, vdex.Base())})
+ android.RuleBuilderInstall{vdex, filepath.Join(vdexInstallDir, vdex.Base())})
// Install the unstripped oat files. The Make rules will put these in $(TARGET_OUT_UNSTRIPPED)
unstrippedInstalls = append(unstrippedInstalls,
- android.RuleBuilderInstall{unstrippedOat.String(), filepath.Join(installDir, unstrippedOat.Base())})
+ android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
}
- cmd.ImplicitOutputs(extraFiles.Strings())
+ cmd.ImplicitOutputs(extraFiles)
rule.Build(pctx, ctx, "bootJarsDexpreopt_"+arch.String(), "dexpreopt boot jars "+arch.String())
@@ -387,7 +387,7 @@ It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
func bootImageProfileRule(ctx android.SingletonContext, info *bootJarsInfo, missingDeps []string) android.WritablePath {
- if len(info.global.BootImageProfiles) == 0 {
+ if !info.global.UseProfileForBootImage || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() {
return nil
}
@@ -396,13 +396,25 @@ func bootImageProfileRule(ctx android.SingletonContext, info *bootJarsInfo, miss
rule := android.NewRuleBuilder()
rule.MissingDeps(missingDeps)
- var bootImageProfile string
+ var bootImageProfile android.Path
if len(info.global.BootImageProfiles) > 1 {
combinedBootImageProfile := info.dir.Join(ctx, "boot-image-profile.txt")
- rule.Command().Text("cat").Inputs(info.global.BootImageProfiles).Text(">").Output(combinedBootImageProfile.String())
- bootImageProfile = combinedBootImageProfile.String()
- } else {
+ rule.Command().Text("cat").Inputs(info.global.BootImageProfiles).Text(">").Output(combinedBootImageProfile)
+ bootImageProfile = combinedBootImageProfile
+ } else if len(info.global.BootImageProfiles) == 1 {
bootImageProfile = info.global.BootImageProfiles[0]
+ } else {
+ // If not set, use the default. Some branches like master-art-host don't have frameworks/base, so manually
+ // handle the case that the default is missing. Those branches won't attempt to build the profile rule,
+ // and if they do they'll get a missing deps error.
+ defaultProfile := "frameworks/base/config/boot-image-profile.txt"
+ path := android.ExistentPathForSource(ctx, defaultProfile)
+ if path.Valid() {
+ bootImageProfile = path.Path()
+ } else {
+ missingDeps = append(missingDeps, defaultProfile)
+ bootImageProfile = android.PathForOutput(ctx, "missing")
+ }
}
profile := info.dir.Join(ctx, "boot.prof")
@@ -410,12 +422,12 @@ func bootImageProfileRule(ctx android.SingletonContext, info *bootJarsInfo, miss
rule.Command().
Text(`ANDROID_LOG_TAGS="*:e"`).
Tool(tools.Profman).
- FlagWithArg("--create-profile-from=", bootImageProfile).
- FlagForEachInput("--apk=", info.preoptBootDex.Strings()).
+ FlagWithInput("--create-profile-from=", bootImageProfile).
+ FlagForEachInput("--apk=", info.preoptBootDex.Paths()).
FlagForEachArg("--dex-location=", info.preoptBootLocations).
- FlagWithOutput("--reference-profile-file=", profile.String())
+ FlagWithOutput("--reference-profile-file=", profile)
- rule.Install(profile.String(), "/system/etc/boot-image.prof")
+ rule.Install(profile, "/system/etc/boot-image.prof")
rule.Build(pctx, ctx, "bootJarsProfile", "profile boot jars")
@@ -439,16 +451,6 @@ func bootImageMakeVars(ctx android.MakeVarsContext) {
for arch, _ := range info.images {
ctx.Strict("DEXPREOPT_IMAGE_"+arch.String(), info.images[arch].String())
- var builtInstalled []string
- for _, install := range info.installs[arch] {
- builtInstalled = append(builtInstalled, install.From+":"+install.To)
- }
-
- var unstrippedBuiltInstalled []string
- for _, install := range info.unstrippedInstalls[arch] {
- unstrippedBuiltInstalled = append(unstrippedBuiltInstalled, install.From+":"+install.To)
- }
-
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+arch.String(), info.installs[arch].String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+arch.String(), info.unstrippedInstalls[arch].String())
ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+arch.String(), info.vdexInstalls[arch].String())
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 01e2c5ec..104cd767 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -15,8 +15,6 @@
package java
import (
- "path/filepath"
-
"github.com/google/blueprint"
"android/soong/android"
@@ -175,14 +173,3 @@ func hiddenAPIEncodeDex(ctx android.ModuleContext, output android.WritablePath,
TransformZipAlign(ctx, output, tmpOutput)
}
}
-
-type hiddenAPIPath struct {
- path string
-}
-
-var _ android.Path = (*hiddenAPIPath)(nil)
-
-func (p *hiddenAPIPath) String() string { return p.path }
-func (p *hiddenAPIPath) Ext() string { return filepath.Ext(p.path) }
-func (p *hiddenAPIPath) Base() string { return filepath.Base(p.path) }
-func (p *hiddenAPIPath) Rel() string { return p.path }
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index adbd3567..ba8b3e1f 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -170,14 +170,14 @@ func stubFlagsRule(ctx android.SingletonContext) {
rule.MissingDeps(missingDeps)
rule.Command().
- Tool(pctx.HostBinToolPath(ctx, "hiddenapi").String()).
+ Tool(pctx.HostBinToolPath(ctx, "hiddenapi")).
Text("list").
- FlagForEachInput("--boot-dex=", bootDexJars.Strings()).
- FlagWithInputList("--public-stub-classpath=", publicStubPaths.Strings(), ":").
- FlagWithInputList("--public-stub-classpath=", systemStubPaths.Strings(), ":").
- FlagWithInputList("--public-stub-classpath=", testStubPaths.Strings(), ":").
- FlagWithInputList("--core-platform-stub-classpath=", corePlatformStubPaths.Strings(), ":").
- FlagWithOutput("--out-api-flags=", tempPath.String())
+ FlagForEachInput("--boot-dex=", bootDexJars).
+ FlagWithInputList("--public-stub-classpath=", publicStubPaths, ":").
+ FlagWithInputList("--public-stub-classpath=", systemStubPaths, ":").
+ FlagWithInputList("--public-stub-classpath=", testStubPaths, ":").
+ FlagWithInputList("--core-platform-stub-classpath=", corePlatformStubPaths, ":").
+ FlagWithOutput("--out-api-flags=", tempPath)
commitChangeForRestat(rule, tempPath, outputPath)
@@ -214,20 +214,20 @@ func flagsRule(ctx android.SingletonContext) android.Path {
stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
rule.Command().
- Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py").String()).
- FlagWithInput("--csv ", stubFlags.String()).
- Inputs(flagsCSV.Strings()).
+ Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py")).
+ FlagWithInput("--csv ", stubFlags).
+ Inputs(flagsCSV).
FlagWithInput("--greylist ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt").String()).
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt")).
FlagWithInput("--greylist-ignore-conflicts ",
- greylistIgnoreConflicts.String()).
+ greylistIgnoreConflicts).
FlagWithInput("--greylist-max-p ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-p.txt").String()).
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-p.txt")).
FlagWithInput("--greylist-max-o-ignore-conflicts ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-o.txt").String()).
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-o.txt")).
FlagWithInput("--blacklist ",
- android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blacklist.txt").String()).
- FlagWithOutput("--output ", tempPath.String())
+ android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blacklist.txt")).
+ FlagWithOutput("--output ", tempPath)
commitChangeForRestat(rule, tempPath, outputPath)
@@ -243,8 +243,8 @@ func emptyFlagsRule(ctx android.SingletonContext) android.Path {
outputPath := hiddenAPISingletonPaths(ctx).flags
- rule.Command().Text("rm").Flag("-f").Output(outputPath.String())
- rule.Command().Text("touch").Output(outputPath.String())
+ rule.Command().Text("rm").Flag("-f").Output(outputPath)
+ rule.Command().Text("touch").Output(outputPath)
rule.Build(pctx, ctx, "emptyHiddenAPIFlagsFile", "empty hiddenapi flags")
@@ -269,10 +269,10 @@ func metadataRule(ctx android.SingletonContext) android.Path {
outputPath := hiddenAPISingletonPaths(ctx).metadata
rule.Command().
- Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/merge_csv.py").String()).
- Inputs(metadataCSV.Strings()).
+ Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/merge_csv.py")).
+ Inputs(metadataCSV).
Text(">").
- Output(outputPath.String())
+ Output(outputPath)
rule.Build(pctx, ctx, "hiddenAPIGreylistMetadataFile", "hiddenapi greylist metadata")
@@ -284,15 +284,15 @@ func metadataRule(ctx android.SingletonContext) android.Path {
// the rule.
func commitChangeForRestat(rule *android.RuleBuilder, tempPath, outputPath android.WritablePath) {
rule.Restat()
- rule.Temporary(tempPath.String())
+ rule.Temporary(tempPath)
rule.Command().
Text("(").
Text("if").
- Text("cmp -s").Input(tempPath.String()).Output(outputPath.String()).Text(";").
+ Text("cmp -s").Input(tempPath).Output(outputPath).Text(";").
Text("then").
- Text("rm").Input(tempPath.String()).Text(";").
+ Text("rm").Input(tempPath).Text(";").
Text("else").
- Text("mv").Input(tempPath.String()).Output(outputPath.String()).Text(";").
+ Text("mv").Input(tempPath).Output(outputPath).Text(";").
Text("fi").
Text(")")
}
diff --git a/java/testing.go b/java/testing.go
index 6febfa1d..bec3c0b2 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -18,6 +18,7 @@ import (
"fmt"
"android/soong/android"
+ "android/soong/dexpreopt"
)
func TestConfig(buildDir string, env map[string]string) android.Config {
@@ -30,6 +31,9 @@ func TestConfig(buildDir string, env map[string]string) android.Config {
config := android.TestArchConfig(buildDir, env)
config.TestProductVariables.DeviceSystemSdkVersions = []string{"14", "15"}
+ pathCtx := android.PathContextForTesting(config, nil)
+ setDexpreoptGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+
return config
}