blob: d541c7017a694d2bce625d50f5176ef8e5f67a44 [file] [log] [blame]
Colin Cross29ff8872018-11-12 10:13:39 -08001// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18 "bytes"
19 "flag"
20 "fmt"
21 "os"
22 "path/filepath"
23 "runtime"
24
25 "android/soong/dexpreopt"
26
27 "github.com/google/blueprint/pathtools"
28 "github.com/google/blueprint/proptools"
29)
30
31var (
32 extrasOutputPath = flag.String("extras_zip", "", "path to output zip file of extra files")
33 dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
34 stripScriptPath = flag.String("strip_script", "", "path to output strip script")
35 globalConfigPath = flag.String("global", "", "path to global configuration file")
36 moduleConfigPath = flag.String("module", "", "path to module configuration file")
37)
38
39func main() {
40 flag.Parse()
41
42 usage := func(err string) {
43 if err != "" {
44 fmt.Println(err)
45 flag.Usage()
46 os.Exit(1)
47 }
48 }
49
50 if flag.NArg() > 0 {
51 usage("unrecognized argument " + flag.Arg(0))
52 }
53
54 if *dexpreoptScriptPath == "" {
55 usage("path to output dexpreopt script is required")
56 }
57
58 if *stripScriptPath == "" {
59 usage("path to output strip script is required")
60 }
61
62 if *globalConfigPath == "" {
63 usage("path to global configuration file is required")
64 }
65
66 if *moduleConfigPath == "" {
67 usage("path to module configuration file is required")
68 }
69
70 globalConfig, err := dexpreopt.LoadGlobalConfig(*globalConfigPath)
71 if err != nil {
72 fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
73 os.Exit(2)
74 }
75
76 moduleConfig, err := dexpreopt.LoadModuleConfig(*moduleConfigPath)
77 if err != nil {
78 fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
79 os.Exit(2)
80 }
81
82 defer func() {
83 if r := recover(); r != nil {
84 switch x := r.(type) {
85 case runtime.Error:
86 panic(x)
87 case error:
88 fmt.Fprintln(os.Stderr, "error:", r)
89 os.Exit(3)
90 default:
91 panic(x)
92 }
93 }
94 }()
95
96 writeScripts(globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath, *extrasOutputPath)
97}
98
99func writeScripts(global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
100 dexpreoptScriptPath, stripScriptPath, extrasOutputPath string) {
101 dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(global, module)
102 if err != nil {
103 panic(err)
104 }
105
106 installDir := filepath.Join(filepath.Dir(module.BuildPath), "dexpreopt_install")
107
108 dexpreoptRule.Command().FlagWithArg("rm -rf ", installDir)
109
110 for _, install := range dexpreoptRule.Installs() {
111 installPath := filepath.Join(installDir, install.To)
112 dexpreoptRule.Command().Text("mkdir -p").Flag(filepath.Dir(installPath))
113 dexpreoptRule.Command().Text("cp -f").Input(install.From).Output(installPath)
114 }
115 dexpreoptRule.Command().Tool(global.Tools.SoongZip).
116 FlagWithOutput("-o ", extrasOutputPath).
117 FlagWithArg("-C ", installDir).
118 FlagWithArg("-D ", installDir)
119
120 stripRule, err := dexpreopt.GenerateStripRule(global, module)
121 if err != nil {
122 panic(err)
123 }
124
125 write := func(rule *dexpreopt.Rule, file, output string) {
126 script := &bytes.Buffer{}
127 script.WriteString(scriptHeader)
128 for _, c := range rule.Commands() {
129 script.WriteString(c)
130 script.WriteString("\n\n")
131 }
132
133 depFile := &bytes.Buffer{}
134 fmt.Fprintf(depFile, "%s: \\\n", output)
135 for _, tool := range dexpreoptRule.Tools() {
136 fmt.Fprintf(depFile, " %s \\\n", tool)
137 }
138 for _, input := range dexpreoptRule.Inputs() {
139 fmt.Fprintf(depFile, " %s \\\n", input)
140 }
141 depFile.WriteString("\n")
142
143 fmt.Fprintf(script, `/bin/bash -c 'echo -e $0 > %s' %s\n`,
144 output+".d", proptools.ShellEscape([]string{depFile.String()})[0])
145
146 err := pathtools.WriteFileIfChanged(file, script.Bytes(), 0755)
147 if err != nil {
148 panic(err)
149 }
150 }
151
152 write(dexpreoptRule, dexpreoptScriptPath, extrasOutputPath)
153 write(stripRule, stripScriptPath, module.StripOutputPath)
154}
155
156const scriptHeader = `#!/bin/bash
157
158err() {
159 errno=$?
160 echo "error: $0:$1 exited with status $errno" >&2
161 echo "error in command:" >&2
162 sed -n -e "$1p" $0 >&2
163 if [ "$errno" -ne 0 ]; then
164 exit $errno
165 else
166 exit 1
167 fi
168}
169
170trap 'err $LINENO' ERR
171
172`