aboutsummaryrefslogtreecommitdiffstats
path: root/dexpreopt/dexpreopt_gen
diff options
context:
space:
mode:
Diffstat (limited to 'dexpreopt/dexpreopt_gen')
-rw-r--r--dexpreopt/dexpreopt_gen/Android.bp11
-rw-r--r--dexpreopt/dexpreopt_gen/dexpreopt_gen.go190
2 files changed, 201 insertions, 0 deletions
diff --git a/dexpreopt/dexpreopt_gen/Android.bp b/dexpreopt/dexpreopt_gen/Android.bp
new file mode 100644
index 00000000..07903910
--- /dev/null
+++ b/dexpreopt/dexpreopt_gen/Android.bp
@@ -0,0 +1,11 @@
+blueprint_go_binary {
+ name: "dexpreopt_gen",
+ srcs: [
+ "dexpreopt_gen.go",
+ ],
+ deps: [
+ "soong-dexpreopt",
+ "blueprint-pathtools",
+ "blueprint-proptools",
+ ],
+} \ No newline at end of file
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
new file mode 100644
index 00000000..c010056a
--- /dev/null
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -0,0 +1,190 @@
+// 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 main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "android/soong/dexpreopt"
+
+ "github.com/google/blueprint/pathtools"
+)
+
+var (
+ dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
+ 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")
+)
+
+func main() {
+ flag.Parse()
+
+ usage := func(err string) {
+ if err != "" {
+ fmt.Println(err)
+ flag.Usage()
+ os.Exit(1)
+ }
+ }
+
+ if flag.NArg() > 0 {
+ usage("unrecognized argument " + flag.Arg(0))
+ }
+
+ if *dexpreoptScriptPath == "" {
+ usage("path to output dexpreopt script is required")
+ }
+
+ if *stripScriptPath == "" {
+ usage("path to output strip script is required")
+ }
+
+ if *globalConfigPath == "" {
+ usage("path to global configuration file is required")
+ }
+
+ if *moduleConfigPath == "" {
+ usage("path to module configuration file is required")
+ }
+
+ globalConfig, err := dexpreopt.LoadGlobalConfig(*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)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
+ os.Exit(2)
+ }
+
+ defer func() {
+ if r := recover(); r != nil {
+ switch x := r.(type) {
+ case runtime.Error:
+ panic(x)
+ case error:
+ fmt.Fprintln(os.Stderr, "error:", r)
+ os.Exit(3)
+ default:
+ panic(x)
+ }
+ }
+ }()
+
+ writeScripts(globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
+}
+
+func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
+ dexpreoptScriptPath, stripScriptPath string) {
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(global, module)
+ if err != nil {
+ panic(err)
+ }
+
+ installDir := filepath.Join(filepath.Dir(module.BuildPath), "dexpreopt_install")
+
+ dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir)
+
+ for _, install := range dexpreoptRule.Installs() {
+ installPath := filepath.Join(installDir, install.To)
+ dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath))
+ 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)
+
+ stripRule, err := dexpreopt.GenerateStripRule(global, module)
+ if err != nil {
+ panic(err)
+ }
+
+ write := func(rule *dexpreopt.Rule, file string) {
+ script := &bytes.Buffer{}
+ script.WriteString(scriptHeader)
+ for _, c := range rule.Commands() {
+ script.WriteString(c)
+ script.WriteString("\n\n")
+ }
+
+ depFile := &bytes.Buffer{}
+
+ fmt.Fprint(depFile, `: \`+"\n")
+ for _, tool := range dexpreoptRule.Tools() {
+ fmt.Fprintf(depFile, ` %s \`+"\n", tool)
+ }
+ for _, input := range dexpreoptRule.Inputs() {
+ // Assume the rule that ran the script already has a dependency on the input file passed on the
+ // command line.
+ if input != "$1" {
+ fmt.Fprintf(depFile, ` %s \`+"\n", input)
+ }
+ }
+ depFile.WriteString("\n")
+
+ fmt.Fprintln(script, "rm -f $2.d")
+ // Write the output path unescaped so the $2 gets expanded
+ fmt.Fprintln(script, `echo -n $2 > $2.d`)
+ // Write the rest of the depsfile using cat <<'EOF', which will not do any shell expansion on
+ // the contents to preserve backslashes and special characters in filenames.
+ fmt.Fprintf(script, "cat >> $2.d <<'EOF'\n%sEOF\n", depFile.String())
+
+ err := pathtools.WriteFileIfChanged(file, script.Bytes(), 0755)
+ if err != nil {
+ panic(err)
+ }
+ }
+
+ // The written scripts will assume the input is $1 and the output is $2
+ if module.DexPath != "$1" {
+ panic(fmt.Errorf("module.DexPath must be '$1', was %q", module.DexPath))
+ }
+ if module.StripInputPath != "$1" {
+ panic(fmt.Errorf("module.StripInputPath must be '$1', was %q", module.StripInputPath))
+ }
+ if module.StripOutputPath != "$2" {
+ panic(fmt.Errorf("module.StripOutputPath must be '$2', was %q", module.StripOutputPath))
+ }
+
+ write(dexpreoptRule, dexpreoptScriptPath)
+ write(stripRule, stripScriptPath)
+}
+
+const scriptHeader = `#!/bin/bash
+
+err() {
+ errno=$?
+ echo "error: $0:$1 exited with status $errno" >&2
+ echo "error in command:" >&2
+ sed -n -e "$1p" $0 >&2
+ if [ "$errno" -ne 0 ]; then
+ exit $errno
+ else
+ exit 1
+ fi
+}
+
+trap 'err $LINENO' ERR
+
+`