huangcm
2025-04-22 c8cf547b11f2c03565d8fb8b8bcdc69860d0ed08
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// 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 (
   "encoding/json"
   "io/ioutil"
   "strings"
 
   "android/soong/android"
)
 
// GlobalConfig stores the configuration for dex preopting set by the product
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
 
   GenerateApexImage bool // generate an extra boot image only containing jars from the runtime apex
   UseApexImage      bool // use the apex image by default
 
   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
   ProfileDir             string // directory to find profiles in
 
   BootJars []string // modules for jars that form the boot class path
 
   RuntimeApexJars               []string // modules for jars that are in the runtime apex
   ProductUpdatableBootModules   []string
   ProductUpdatableBootLocations []string
 
   SystemServerJars []string // jars that form the system server
   SystemServerApps []string // apps that are loaded into system server
   SpeedApps        []string // apps that should be speed optimized
 
   PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified
 
   DefaultCompilerFilter      string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags
   SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars
 
   GenerateDMFiles     bool // generate Dex Metadata files
   NeverAllowStripping bool // whether stripping should not be done - used as build time check to make sure dex files are always available
 
   NoDebugInfo                 bool // don't generate debug info by default
   DontResolveStartupStrings   bool // don't resolve string literals loaded during application startup.
   AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true)
   NeverSystemServerDebugInfo  bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false)
   AlwaysOtherDebugInfo        bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
   NeverOtherDebugInfo         bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
 
   MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product
 
   IsEng        bool // build is a eng variant
   SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
 
   DefaultAppImages bool // build app images (TODO: .art files?) by default
 
   Dex2oatXmx string // max heap size for dex2oat
   Dex2oatXms string // initial heap size for dex2oat
 
   EmptyDirectory string // path to an empty directory
 
   CpuVariant             map[android.ArchType]string // cpu variant for each architecture
   InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
 
   // Only used for 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
}
 
// 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  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       android.OutputPath
   DexPath         android.Path
   UncompressedDex bool
   HasApkLibraries bool
   PreoptFlags     []string
 
   ProfileClassListing  android.OptionalPath
   ProfileIsTextListing bool
 
   EnforceUsesLibraries  bool
   OptionalUsesLibraries []string
   UsesLibraries         []string
   LibraryPaths          map[string]android.Path
 
   Archs           []android.ArchType
   DexPreoptImages []android.Path
 
   PreoptBootClassPathDexFiles     android.Paths // file paths of boot class path files
   PreoptBootClassPathDexLocations []string      // virtual locations of boot class path files
 
   PreoptExtractedApk bool // Overrides OnlyPreoptModules
 
   NoCreateAppImage    bool
   ForceCreateAppImage bool
 
   PresignedPrebuilt bool
 
   NoStripping     bool
   StripInputPath  android.Path
   StripOutputPath android.WritablePath
}
 
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
}
 
// 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(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
   }
 
   err = json.Unmarshal(data, config)
   if err != nil {
       return err
   }
 
   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,
       DontResolveStartupStrings:          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"),
       },
   }
}