From feec25b08460d1eb1c31296463a9ec61eca9754c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 30 Jan 2019 17:32:39 -0800 Subject: [PATCH] Move dexpreopt.Script to android.RuleBuilder Move dexpreopt.Script to android.RuleBuilder so that the builder style can be used in more places. Also add tests for it. Test: rule_builder_test.go Change-Id: I92a963bd112bf033b08899e930094b908acfcdfd --- Android.bp | 2 + android/rule_builder.go | 230 +++++++++++++++++++++++ android/rule_builder_test.go | 148 +++++++++++++++ dexpreopt/Android.bp | 4 +- dexpreopt/dexpreopt.go | 16 +- dexpreopt/dexpreopt_gen/dexpreopt_gen.go | 3 +- dexpreopt/dexpreopt_test.go | 7 +- dexpreopt/script.go | 178 ------------------ java/dexpreopt.go | 60 +----- java/hiddenapi.go | 16 +- 10 files changed, 413 insertions(+), 251 deletions(-) create mode 100644 android/rule_builder.go create mode 100644 android/rule_builder_test.go delete mode 100644 dexpreopt/script.go diff --git a/Android.bp b/Android.bp index a70f73c92..5e9c600b0 100644 --- a/Android.bp +++ b/Android.bp @@ -61,6 +61,7 @@ bootstrap_go_package { "android/prebuilt_etc.go", "android/proto.go", "android/register.go", + "android/rule_builder.go", "android/sh_binary.go", "android/singleton.go", "android/testing.go", @@ -80,6 +81,7 @@ bootstrap_go_package { "android/paths_test.go", "android/prebuilt_test.go", "android/prebuilt_etc_test.go", + "android/rule_builder_test.go", "android/util_test.go", "android/variable_test.go", ], diff --git a/android/rule_builder.go b/android/rule_builder.go new file mode 100644 index 000000000..b7e84323d --- /dev/null +++ b/android/rule_builder.go @@ -0,0 +1,230 @@ +// Copyright 2018 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "fmt" + "path/filepath" + "sort" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +type RuleBuilderInstall struct { + From, To string +} + +type RuleBuilder struct { + commands []*RuleBuilderCommand + installs []RuleBuilderInstall + restat bool +} + +func (r *RuleBuilder) Restat() *RuleBuilder { + r.restat = true + return r +} + +func (r *RuleBuilder) Install(from, to string) { + r.installs = append(r.installs, RuleBuilderInstall{from, to}) +} + +func (r *RuleBuilder) Command() *RuleBuilderCommand { + command := &RuleBuilderCommand{} + r.commands = append(r.commands, command) + return command +} + +func (r *RuleBuilder) Inputs() []string { + outputs := r.outputSet() + + inputs := make(map[string]bool) + for _, c := range r.commands { + for _, input := range c.inputs { + if !outputs[input] { + inputs[input] = true + } + } + } + + var inputList []string + for input := range inputs { + inputList = append(inputList, input) + } + sort.Strings(inputList) + + return inputList +} + +func (r *RuleBuilder) outputSet() map[string]bool { + outputs := make(map[string]bool) + for _, c := range r.commands { + for _, output := range c.outputs { + outputs[output] = true + } + } + return outputs +} + +func (r *RuleBuilder) Outputs() []string { + outputs := r.outputSet() + + var outputList []string + for output := range outputs { + outputList = append(outputList, output) + } + sort.Strings(outputList) + return outputList +} + +func (r *RuleBuilder) Installs() []RuleBuilderInstall { + return append([]RuleBuilderInstall(nil), r.installs...) +} + +func (r *RuleBuilder) Tools() []string { + var tools []string + for _, c := range r.commands { + tools = append(tools, c.tools...) + } + return tools +} + +func (r *RuleBuilder) Commands() []string { + var commands []string + for _, c := range r.commands { + commands = append(commands, string(c.buf)) + } + return commands +} + +func (r *RuleBuilder) Build(pctx PackageContext, ctx ModuleContext, name string, desc string) { + var inputs Paths + for _, input := range r.Inputs() { + rel, isRel := MaybeRel(ctx, PathForModuleOut(ctx).String(), input) + if isRel { + inputs = append(inputs, PathForModuleOut(ctx, rel)) + } else { + // TODO: use PathForOutput once boot image is moved to where PathForOutput can find it. + inputs = append(inputs, &unknownRulePath{input}) + } + } + + var outputs WritablePaths + for _, output := range r.Outputs() { + rel := Rel(ctx, PathForModuleOut(ctx).String(), output) + outputs = append(outputs, PathForModuleOut(ctx, rel)) + } + + if len(r.Commands()) > 0 { + ctx.Build(pctx, BuildParams{ + Rule: ctx.Rule(pctx, name, blueprint.RuleParams{ + Command: strings.Join(proptools.NinjaEscape(r.Commands()), " && "), + CommandDeps: r.Tools(), + }), + Implicits: inputs, + Outputs: outputs, + Description: desc, + }) + } +} + +type RuleBuilderCommand struct { + buf []byte + inputs []string + outputs []string + tools []string +} + +func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand { + if len(c.buf) > 0 { + c.buf = append(c.buf, ' ') + } + c.buf = append(c.buf, text...) + return c +} + +func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand { + return c.Text(fmt.Sprintf(format, a...)) +} + +func (c *RuleBuilderCommand) Flag(flag string) *RuleBuilderCommand { + return c.Text(flag) +} + +func (c *RuleBuilderCommand) FlagWithArg(flag, arg string) *RuleBuilderCommand { + return c.Text(flag + arg) +} + +func (c *RuleBuilderCommand) FlagWithList(flag string, list []string, sep string) *RuleBuilderCommand { + return c.Text(flag + strings.Join(list, sep)) +} + +func (c *RuleBuilderCommand) Tool(path string) *RuleBuilderCommand { + c.tools = append(c.tools, path) + return c.Text(path) +} + +func (c *RuleBuilderCommand) Input(path string) *RuleBuilderCommand { + c.inputs = append(c.inputs, path) + return c.Text(path) +} + +func (c *RuleBuilderCommand) Implicit(path string) *RuleBuilderCommand { + c.inputs = append(c.inputs, path) + return c +} + +func (c *RuleBuilderCommand) Implicits(paths []string) *RuleBuilderCommand { + c.inputs = append(c.inputs, paths...) + return c +} + +func (c *RuleBuilderCommand) Output(path string) *RuleBuilderCommand { + c.outputs = append(c.outputs, path) + return c.Text(path) +} + +func (c *RuleBuilderCommand) ImplicitOutput(path string) *RuleBuilderCommand { + c.outputs = append(c.outputs, path) + return c +} + +func (c *RuleBuilderCommand) FlagWithInput(flag, path string) *RuleBuilderCommand { + c.inputs = append(c.inputs, path) + return c.Text(flag + path) +} + +func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths []string, sep string) *RuleBuilderCommand { + c.inputs = append(c.inputs, paths...) + return c.FlagWithList(flag, paths, sep) +} + +func (c *RuleBuilderCommand) FlagWithOutput(flag, path string) *RuleBuilderCommand { + c.outputs = append(c.outputs, path) + return c.Text(flag + path) +} + +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 new file mode 100644 index 000000000..b4c9e0eb6 --- /dev/null +++ b/android/rule_builder_test.go @@ -0,0 +1,148 @@ +// Copyright 2019 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "io/ioutil" + "os" + "path/filepath" + "reflect" + "testing" +) + +func TestRuleBuilder(t *testing.T) { + rule := RuleBuilder{} + + cmd := rule.Command(). + Flag("Flag"). + FlagWithArg("FlagWithArg=", "arg"). + FlagWithInput("FlagWithInput=", "input"). + FlagWithOutput("FlagWithOutput=", "output"). + Implicit("Implicit"). + ImplicitOutput("ImplicitOutput"). + Input("Input"). + Output("Output"). + Text("Text"). + Tool("Tool") + + rule.Command(). + Text("command2"). + Input("input2"). + Output("output2"). + Tool("tool2") + + // Test updates to the first command after the second command has been started + cmd.Text("after command2") + // Test updating a command when the previous update did not replace the cmd variable + cmd.Text("old cmd") + + // Test a command that uses the output of a previous command as an input + rule.Command(). + Text("command3"). + Input("input3"). + Input("output2"). + Output("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", + } + wantInputs := []string{"Implicit", "Input", "input", "input2", "input3"} + wantOutputs := []string{"ImplicitOutput", "Output", "output", "output2", "output3"} + wantTools := []string{"Tool", "tool2"} + + if !reflect.DeepEqual(rule.Commands(), wantCommands) { + t.Errorf("\nwant rule.Commands() = %#v\n got %#v", wantCommands, rule.Commands()) + } + if !reflect.DeepEqual(rule.Inputs(), wantInputs) { + t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", wantInputs, rule.Inputs()) + } + if !reflect.DeepEqual(rule.Outputs(), wantOutputs) { + t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", wantOutputs, rule.Outputs()) + } + if !reflect.DeepEqual(rule.Tools(), wantTools) { + t.Errorf("\nwant rule.Tools() = %#v\n got %#v", wantTools, rule.Tools()) + } +} + +func testRuleBuilderFactory() Module { + module := &testRuleBuilderModule{} + module.AddProperties(&module.properties) + InitAndroidModule(module) + return module +} + +type testRuleBuilderModule struct { + ModuleBase + properties struct { + Src string + } +} + +func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) { + rule := RuleBuilder{} + + in := PathForSource(ctx, t.properties.Src) + out := PathForModuleOut(ctx, ctx.ModuleName()) + + rule.Command().Tool("cp").Input(in.String()).Output(out.String()) + + rule.Build(pctx, ctx, "rule", "desc") +} + +func TestRuleBuilder_Build(t *testing.T) { + buildDir, err := ioutil.TempDir("", "soong_test_rule_builder") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(buildDir) + + bp := ` + rule_builder_test { + name: "foo", + src: "bar", + } + ` + + config := TestConfig(buildDir, nil) + ctx := NewTestContext() + ctx.MockFileSystem(map[string][]byte{ + "Android.bp": []byte(bp), + "bar": nil, + "cp": nil, + }) + ctx.RegisterModuleType("rule_builder_test", ModuleFactoryAdaptor(testRuleBuilderFactory)) + ctx.Register() + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + foo := ctx.ModuleForTests("foo", "").Rule("rule") + + // TODO: make RuleParams accessible to tests and verify rule.Command().Tools() ends up in CommandDeps + + if len(foo.Implicits) != 1 || foo.Implicits[0].String() != "bar" { + t.Errorf("want foo.Implicits = [%q], got %q", "bar", foo.Implicits.Strings()) + } + + wantOutput := filepath.Join(buildDir, ".intermediates", "foo", "foo") + if len(foo.Outputs) != 1 || foo.Outputs[0].String() != wantOutput { + t.Errorf("want foo.Outputs = [%q], got %q", wantOutput, foo.Outputs.Strings()) + } + +} diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp index b83252983..c5f24e273 100644 --- a/dexpreopt/Android.bp +++ b/dexpreopt/Android.bp @@ -4,12 +4,12 @@ bootstrap_go_package { srcs: [ "config.go", "dexpreopt.go", - "script.go", ], testSrcs: [ "dexpreopt_test.go", ], deps: [ "blueprint-pathtools", + "soong-android", ], -} \ No newline at end of file +} diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index f316be4b0..b12ca0b6b 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -39,6 +39,8 @@ import ( "path/filepath" "strings" + "android/soong/android" + "github.com/google/blueprint/pathtools" ) @@ -47,7 +49,7 @@ const SystemOtherPartition = "/system_other/" // GenerateStripRule generates a set of commands that will take an APK or JAR as an input and strip the dex files if // they are no longer necessary after preopting. -func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *Rule, err error) { +func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(error); ok { @@ -61,7 +63,7 @@ func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *Rule, er tools := global.Tools - rule = &Rule{} + rule = &android.RuleBuilder{} strip := shouldStripDex(module, global) @@ -81,7 +83,7 @@ func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *Rule, er // 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 *Rule, err error) { +func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) { defer func() { if r := recover(); r != nil { if e, ok := r.(error); ok { @@ -93,7 +95,7 @@ func GenerateDexpreoptRule(global GlobalConfig, module ModuleConfig) (rule *Rule } }() - rule = &Rule{} + rule = &android.RuleBuilder{} generateProfile := module.ProfileClassListing != "" && !global.DisableGenerateProfile @@ -141,7 +143,7 @@ func dexpreoptDisabled(global GlobalConfig, module ModuleConfig) bool { return false } -func profileCommand(global GlobalConfig, module ModuleConfig, rule *Rule) string { +func profileCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder) string { profilePath := filepath.Join(filepath.Dir(module.BuildPath), "profile.prof") profileInstalledPath := module.DexLocation + ".prof" @@ -178,8 +180,8 @@ func profileCommand(global GlobalConfig, module ModuleConfig, rule *Rule) string return profilePath } -func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *Rule, profile, arch, bootImageLocation string, - appImage, generateDM bool) { +func dexpreoptCommand(global GlobalConfig, module ModuleConfig, rule *android.RuleBuilder, + profile, arch, bootImageLocation string, appImage, generateDM bool) { // HACK: make soname in Soong-generated .odex files match Make. base := filepath.Base(module.DexLocation) diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go index 46d8795a8..1467a028a 100644 --- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go +++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go @@ -22,6 +22,7 @@ import ( "path/filepath" "runtime" + "android/soong/android" "android/soong/dexpreopt" "github.com/google/blueprint/pathtools" @@ -121,7 +122,7 @@ func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig, panic(err) } - write := func(rule *dexpreopt.Rule, file string) { + write := func(rule *android.RuleBuilder, file string) { script := &bytes.Buffer{} script.WriteString(scriptHeader) for _, c := range rule.Commands() { diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go index 073d46378..6e520f136 100644 --- a/dexpreopt/dexpreopt_test.go +++ b/dexpreopt/dexpreopt_test.go @@ -15,6 +15,7 @@ package dexpreopt import ( + "android/soong/android" "reflect" "strings" "testing" @@ -100,7 +101,7 @@ func TestDexPreopt(t *testing.T) { t.Error(err) } - wantInstalls := []Install{ + wantInstalls := []android.RuleBuilderInstall{ {"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"}, } @@ -126,7 +127,7 @@ func TestDexPreoptSystemOther(t *testing.T) { t.Error(err) } - wantInstalls := []Install{ + wantInstalls := []android.RuleBuilderInstall{ {"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"}, } @@ -150,7 +151,7 @@ func TestDexPreoptProfile(t *testing.T) { t.Error(err) } - wantInstalls := []Install{ + wantInstalls := []android.RuleBuilderInstall{ {"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"}, diff --git a/dexpreopt/script.go b/dexpreopt/script.go deleted file mode 100644 index 9d4329c5b..000000000 --- a/dexpreopt/script.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package dexpreopt - -import ( - "fmt" - "sort" - "strings" -) - -type Install struct { - From, To string -} - -type Rule struct { - commands []*Command - installs []Install -} - -func (r *Rule) Install(from, to string) { - r.installs = append(r.installs, Install{from, to}) -} - -func (r *Rule) Command() *Command { - command := &Command{} - r.commands = append(r.commands, command) - return command -} - -func (r *Rule) Inputs() []string { - outputs := r.outputSet() - - inputs := make(map[string]bool) - for _, c := range r.commands { - for _, input := range c.inputs { - if !outputs[input] { - inputs[input] = true - } - } - } - - var inputList []string - for input := range inputs { - inputList = append(inputList, input) - } - sort.Strings(inputList) - - return inputList -} - -func (r *Rule) outputSet() map[string]bool { - outputs := make(map[string]bool) - for _, c := range r.commands { - for _, output := range c.outputs { - outputs[output] = true - } - } - return outputs -} - -func (r *Rule) Outputs() []string { - outputs := r.outputSet() - - var outputList []string - for output := range outputs { - outputList = append(outputList, output) - } - sort.Strings(outputList) - return outputList -} - -func (r *Rule) Installs() []Install { - return append([]Install(nil), r.installs...) -} - -func (r *Rule) Tools() []string { - var tools []string - for _, c := range r.commands { - tools = append(tools, c.tools...) - } - return tools -} - -func (r *Rule) Commands() []string { - var commands []string - for _, c := range r.commands { - commands = append(commands, string(c.buf)) - } - return commands -} - -type Command struct { - buf []byte - inputs []string - outputs []string - tools []string -} - -func (c *Command) Text(text string) *Command { - if len(c.buf) > 0 { - c.buf = append(c.buf, ' ') - } - c.buf = append(c.buf, text...) - return c -} - -func (c *Command) Textf(format string, a ...interface{}) *Command { - return c.Text(fmt.Sprintf(format, a...)) -} - -func (c *Command) Flag(flag string) *Command { - return c.Text(flag) -} - -func (c *Command) FlagWithArg(flag, arg string) *Command { - return c.Text(flag + arg) -} - -func (c *Command) FlagWithList(flag string, list []string, sep string) *Command { - return c.Text(flag + strings.Join(list, sep)) -} - -func (c *Command) Tool(path string) *Command { - c.tools = append(c.tools, path) - return c.Text(path) -} - -func (c *Command) Input(path string) *Command { - c.inputs = append(c.inputs, path) - return c.Text(path) -} - -func (c *Command) Implicit(path string) *Command { - c.inputs = append(c.inputs, path) - return c -} - -func (c *Command) Implicits(paths []string) *Command { - c.inputs = append(c.inputs, paths...) - return c -} - -func (c *Command) Output(path string) *Command { - c.outputs = append(c.outputs, path) - return c.Text(path) -} - -func (c *Command) ImplicitOutput(path string) *Command { - c.outputs = append(c.outputs, path) - return c -} - -func (c *Command) FlagWithInput(flag, path string) *Command { - c.inputs = append(c.inputs, path) - return c.Text(flag + path) -} - -func (c *Command) FlagWithInputList(flag string, paths []string, sep string) *Command { - c.inputs = append(c.inputs, paths...) - return c.FlagWithList(flag, paths, sep) -} - -func (c *Command) FlagWithOutput(flag, path string) *Command { - c.outputs = append(c.outputs, path) - return c.Text(flag + path) -} diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 6e46bc91a..bb72b7dec 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -15,12 +15,6 @@ package java import ( - "path/filepath" - "strings" - - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" - "android/soong/android" "android/soong/dexpreopt" ) @@ -185,69 +179,19 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo return dexJarFile } - var inputs android.Paths - for _, input := range dexpreoptRule.Inputs() { - if input == "" { - // Tests sometimes have empty configuration values that lead to empty inputs - continue - } - rel, isRel := android.MaybeRel(ctx, android.PathForModuleOut(ctx).String(), input) - if isRel { - inputs = append(inputs, android.PathForModuleOut(ctx, rel)) - } else { - // TODO: use PathForOutput once boot image is moved to where PathForOutput can find it. - inputs = append(inputs, &bootImagePath{input}) - } - } - - var outputs android.WritablePaths - for _, output := range dexpreoptRule.Outputs() { - rel := android.Rel(ctx, android.PathForModuleOut(ctx).String(), output) - outputs = append(outputs, android.PathForModuleOut(ctx, rel)) - } + dexpreoptRule.Build(pctx, ctx, "dexpreopt", "dexpreopt") for _, install := range dexpreoptRule.Installs() { d.builtInstalled = append(d.builtInstalled, install.From+":"+install.To) } - if len(dexpreoptRule.Commands()) > 0 { - ctx.Build(pctx, android.BuildParams{ - Rule: ctx.Rule(pctx, "dexpreopt", blueprint.RuleParams{ - Command: strings.Join(proptools.NinjaEscape(dexpreoptRule.Commands()), " && "), - CommandDeps: dexpreoptRule.Tools(), - }), - Implicits: inputs, - Outputs: outputs, - Description: "dexpreopt", - }) - } - stripRule, err := dexpreopt.GenerateStripRule(globalConfig, dexpreoptConfig) if err != nil { ctx.ModuleErrorf("error generating dexpreopt strip rule: %s", err.Error()) return dexJarFile } - ctx.Build(pctx, android.BuildParams{ - Rule: ctx.Rule(pctx, "dexpreopt_strip", blueprint.RuleParams{ - Command: strings.Join(proptools.NinjaEscape(stripRule.Commands()), " && "), - CommandDeps: stripRule.Tools(), - }), - Input: dexJarFile, - Output: strippedDexJarFile, - Description: "dexpreopt strip", - }) + stripRule.Build(pctx, ctx, "dexpreopt_strip", "dexpreopt strip") return strippedDexJarFile } - -type bootImagePath struct { - path string -} - -var _ android.Path = (*bootImagePath)(nil) - -func (p *bootImagePath) String() string { return p.path } -func (p *bootImagePath) Ext() string { return filepath.Ext(p.path) } -func (p *bootImagePath) Base() string { return filepath.Base(p.path) } -func (p *bootImagePath) Rel() string { return p.path } diff --git a/java/hiddenapi.go b/java/hiddenapi.go index 67df57552..983daa79c 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -15,6 +15,7 @@ package java import ( + "path/filepath" "sort" "strings" "sync" @@ -32,7 +33,7 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl func hiddenAPIGenerateCSV(ctx android.ModuleContext, classesJar android.Path) { flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv") metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv") - stubFlagsCSV := &bootImagePath{ctx.Config().HiddenAPIStubFlags()} + stubFlagsCSV := &hiddenAPIPath{ctx.Config().HiddenAPIStubFlags()} ctx.Build(pctx, android.BuildParams{ Rule: hiddenAPIGenerateCSVRule, @@ -80,7 +81,7 @@ var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", bluepr func hiddenAPIEncodeDex(ctx android.ModuleContext, output android.WritablePath, dexInput android.WritablePath, uncompressDex bool) { - flagsCsv := &bootImagePath{ctx.Config().HiddenAPIFlags()} + flagsCsv := &hiddenAPIPath{ctx.Config().HiddenAPIFlags()} // The encode dex rule requires unzipping and rezipping the classes.dex files, ensure that if it was uncompressed // in the input it stays uncompressed in the output. @@ -168,3 +169,14 @@ func hiddenAPIMakeVars(ctx android.MakeVarsContext) { export("SOONG_HIDDENAPI_GREYLIST_METADATA", metadataCSVList) export("SOONG_HIDDENAPI_DEX_INPUTS", dexInputList) } + +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 }