| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 1 | // 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 |  | 
|  | 15 | package dexpreopt | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 18 | "encoding/json" | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 19 | "fmt" | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 20 | "reflect" | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 21 | "strings" | 
| Colin Cross | 74ba962 | 2019-02-11 15:11:14 -0800 | [diff] [blame] | 22 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 23 | "github.com/google/blueprint" | 
|  | 24 |  | 
| Colin Cross | 74ba962 | 2019-02-11 15:11:14 -0800 | [diff] [blame] | 25 | "android/soong/android" | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 26 | ) | 
|  | 27 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 28 | // GlobalConfig stores the configuration for dex preopting. The fields are set | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 29 | // from product variables via dex_preopt_config.mk. | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 30 | type GlobalConfig struct { | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 31 | DisablePreopt           bool     // disable preopt for all modules (excluding boot images) | 
|  | 32 | DisablePreoptBootImages bool     // disable prepot for boot images | 
|  | 33 | DisablePreoptModules    []string // modules with preopt disabled by product-specific config | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 34 |  | 
|  | 35 | OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server | 
|  | 36 |  | 
| Ulya Trafimovich | 9023b02 | 2021-03-22 16:02:28 +0000 | [diff] [blame] | 37 | PreoptWithUpdatableBcp bool // If updatable boot jars are included in dexpreopt or not. | 
|  | 38 |  | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 39 | HasSystemOther        bool     // store odex files that match PatternsOnSystemOther on the system_other partition | 
|  | 40 | PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition | 
|  | 41 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 42 | DisableGenerateProfile bool   // don't generate profiles | 
|  | 43 | ProfileDir             string // directory to find profiles in | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 44 |  | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 45 | BootJars     android.ConfiguredJarList // modules for jars that form the boot class path | 
|  | 46 | ApexBootJars android.ConfiguredJarList // jars within apex that form the boot class path | 
| Vladimir Marko | d2ee532 | 2018-12-19 17:57:57 +0000 | [diff] [blame] | 47 |  | 
| Jiakai Zhang | 556bdf8 | 2023-07-12 16:51:57 +0100 | [diff] [blame] | 48 | ArtApexJars              android.ConfiguredJarList // modules for jars that are in the ART APEX | 
|  | 49 | TestOnlyArtBootImageJars android.ConfiguredJarList // modules for jars to be included in the ART boot image for testing | 
| Colin Cross | 800fe13 | 2019-02-11 14:21:24 -0800 | [diff] [blame] | 50 |  | 
| Jiakai Zhang | cee9e19 | 2021-10-29 19:46:45 +0000 | [diff] [blame] | 51 | SystemServerJars               android.ConfiguredJarList // system_server classpath jars on the platform | 
|  | 52 | SystemServerApps               []string                  // apps that are loaded into system server | 
|  | 53 | ApexSystemServerJars           android.ConfiguredJarList // system_server classpath jars delivered via apex | 
|  | 54 | StandaloneSystemServerJars     android.ConfiguredJarList // jars on the platform that system_server loads dynamically using separate classloaders | 
|  | 55 | ApexStandaloneSystemServerJars android.ConfiguredJarList // jars delivered via apex that system_server loads dynamically using separate classloaders | 
|  | 56 | SpeedApps                      []string                  // apps that should be speed optimized | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 57 |  | 
| Ulya Trafimovich | cd3203f | 2020-03-27 11:30:00 +0000 | [diff] [blame] | 58 | BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error | 
|  | 59 |  | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 60 | PreoptFlags []string // global dex2oat flags that should be used if no module-specific dex2oat flags are specified | 
|  | 61 |  | 
|  | 62 | DefaultCompilerFilter      string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags | 
|  | 63 | SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars | 
|  | 64 |  | 
| Nicolas Geoffray | c1bf724 | 2019-10-18 14:51:38 +0100 | [diff] [blame] | 65 | GenerateDMFiles bool // generate Dex Metadata files | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 66 |  | 
|  | 67 | NoDebugInfo                 bool // don't generate debug info by default | 
| Mathieu Chartier | 3f7ddbb | 2019-04-29 09:33:50 -0700 | [diff] [blame] | 68 | DontResolveStartupStrings   bool // don't resolve string literals loaded during application startup. | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 69 | AlwaysSystemServerDebugInfo bool // always generate mini debug info for system server modules (overrides NoDebugInfo=true) | 
|  | 70 | NeverSystemServerDebugInfo  bool // never generate mini debug info for system server modules (overrides NoDebugInfo=false) | 
|  | 71 | AlwaysOtherDebugInfo        bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true) | 
|  | 72 | NeverOtherDebugInfo         bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true) | 
|  | 73 |  | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 74 | IsEng        bool // build is a eng variant | 
|  | 75 | SanitizeLite bool // build is the second phase of a SANITIZE_LITE build | 
|  | 76 |  | 
|  | 77 | DefaultAppImages bool // build app images (TODO: .art files?) by default | 
|  | 78 |  | 
| Colin Cross | 800fe13 | 2019-02-11 14:21:24 -0800 | [diff] [blame] | 79 | Dex2oatXmx string // max heap size for dex2oat | 
|  | 80 | Dex2oatXms string // initial heap size for dex2oat | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 81 |  | 
|  | 82 | EmptyDirectory string // path to an empty directory | 
|  | 83 |  | 
| Colin Cross | 74ba962 | 2019-02-11 15:11:14 -0800 | [diff] [blame] | 84 | CpuVariant             map[android.ArchType]string // cpu variant for each architecture | 
|  | 85 | InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 86 |  | 
| Nicolas Geoffray | 1086e60 | 2021-01-20 14:30:40 +0000 | [diff] [blame] | 87 | BootImageProfiles android.Paths // path to a boot-image-profile.txt file | 
|  | 88 | BootFlags         string        // extra flags to pass to dex2oat for the boot image | 
|  | 89 | Dex2oatImageXmx   string        // max heap size for dex2oat for the boot image | 
|  | 90 | Dex2oatImageXms   string        // initial heap size for dex2oat for the boot image | 
| Ulya Trafimovich | 8c35fcf | 2021-02-17 16:23:28 +0000 | [diff] [blame] | 91 |  | 
| Ulya Trafimovich | 4a13acb | 2021-03-02 12:25:02 +0000 | [diff] [blame] | 92 | // If true, downgrade the compiler filter of dexpreopt to "verify" when verify_uses_libraries | 
| Ulya Trafimovich | 8c35fcf | 2021-02-17 16:23:28 +0000 | [diff] [blame] | 93 | // check fails, instead of failing the build. This will disable any AOT-compilation. | 
|  | 94 | // | 
|  | 95 | // The intended use case for this flag is to have a smoother migration path for the Java | 
|  | 96 | // modules that need to add <uses-library> information in their build files. The flag allows to | 
|  | 97 | // quickly silence build errors. This flag should be used with caution and only as a temporary | 
|  | 98 | // measure, as it masks real errors and affects performance. | 
|  | 99 | RelaxUsesLibraryCheck bool | 
| Jiakai Zhang | 616be06 | 2022-11-16 11:50:59 +0000 | [diff] [blame] | 100 |  | 
|  | 101 | EnableUffdGc bool // preopt with the assumption that userfaultfd GC will be used on device. | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 102 | } | 
|  | 103 |  | 
| Jiakai Zhang | 389a647 | 2021-12-14 18:54:06 +0000 | [diff] [blame] | 104 | var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars") | 
|  | 105 |  | 
|  | 106 | // Returns all jars on the platform that system_server loads, including those on classpath and those | 
|  | 107 | // loaded dynamically. | 
|  | 108 | func (g *GlobalConfig) AllPlatformSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList { | 
|  | 109 | return ctx.Config().Once(allPlatformSystemServerJarsKey, func() interface{} { | 
|  | 110 | res := g.SystemServerJars.AppendList(&g.StandaloneSystemServerJars) | 
|  | 111 | return &res | 
|  | 112 | }).(*android.ConfiguredJarList) | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | var allApexSystemServerJarsKey = android.NewOnceKey("allApexSystemServerJars") | 
|  | 116 |  | 
|  | 117 | // Returns all jars delivered via apex that system_server loads, including those on classpath and | 
|  | 118 | // those loaded dynamically. | 
|  | 119 | func (g *GlobalConfig) AllApexSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList { | 
|  | 120 | return ctx.Config().Once(allApexSystemServerJarsKey, func() interface{} { | 
|  | 121 | res := g.ApexSystemServerJars.AppendList(&g.ApexStandaloneSystemServerJars) | 
|  | 122 | return &res | 
|  | 123 | }).(*android.ConfiguredJarList) | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | var allSystemServerClasspathJarsKey = android.NewOnceKey("allSystemServerClasspathJars") | 
|  | 127 |  | 
|  | 128 | // Returns all system_server classpath jars. | 
|  | 129 | func (g *GlobalConfig) AllSystemServerClasspathJars(ctx android.PathContext) *android.ConfiguredJarList { | 
|  | 130 | return ctx.Config().Once(allSystemServerClasspathJarsKey, func() interface{} { | 
|  | 131 | res := g.SystemServerJars.AppendList(&g.ApexSystemServerJars) | 
|  | 132 | return &res | 
|  | 133 | }).(*android.ConfiguredJarList) | 
|  | 134 | } | 
|  | 135 |  | 
|  | 136 | var allSystemServerJarsKey = android.NewOnceKey("allSystemServerJars") | 
|  | 137 |  | 
|  | 138 | // Returns all jars that system_server loads. | 
|  | 139 | func (g *GlobalConfig) AllSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList { | 
|  | 140 | return ctx.Config().Once(allSystemServerJarsKey, func() interface{} { | 
|  | 141 | res := g.AllPlatformSystemServerJars(ctx).AppendList(g.AllApexSystemServerJars(ctx)) | 
|  | 142 | return &res | 
|  | 143 | }).(*android.ConfiguredJarList) | 
|  | 144 | } | 
|  | 145 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 146 | // GlobalSoongConfig contains the global config that is generated from Soong, | 
|  | 147 | // stored in dexpreopt_soong.config. | 
|  | 148 | type GlobalSoongConfig struct { | 
|  | 149 | // Paths to tools possibly used by the generated commands. | 
|  | 150 | Profman          android.Path | 
|  | 151 | Dex2oat          android.Path | 
|  | 152 | Aapt             android.Path | 
|  | 153 | SoongZip         android.Path | 
|  | 154 | Zip2zip          android.Path | 
|  | 155 | ManifestCheck    android.Path | 
| Colin Cross | 38b9685 | 2019-05-22 10:21:09 -0700 | [diff] [blame] | 156 | ConstructContext android.Path | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 157 | } | 
|  | 158 |  | 
|  | 159 | type ModuleConfig struct { | 
| Victor Hsieh | d181c8b | 2019-01-29 13:00:33 -0800 | [diff] [blame] | 160 | Name            string | 
|  | 161 | DexLocation     string // dex location on device | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 162 | BuildPath       android.OutputPath | 
|  | 163 | DexPath         android.Path | 
| Jeongik Cha | 33a3a81 | 2021-04-15 09:12:49 +0900 | [diff] [blame] | 164 | ManifestPath    android.OptionalPath | 
| Victor Hsieh | d181c8b | 2019-01-29 13:00:33 -0800 | [diff] [blame] | 165 | UncompressedDex bool | 
|  | 166 | HasApkLibraries bool | 
|  | 167 | PreoptFlags     []string | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 168 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 169 | ProfileClassListing  android.OptionalPath | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 170 | ProfileIsTextListing bool | 
| Nicolas Geoffray | e710242 | 2019-07-24 13:19:29 +0100 | [diff] [blame] | 171 | ProfileBootListing   android.OptionalPath | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 172 |  | 
| Ulya Trafimovich | 8c35fcf | 2021-02-17 16:23:28 +0000 | [diff] [blame] | 173 | EnforceUsesLibraries           bool         // turn on build-time verify_uses_libraries check | 
|  | 174 | EnforceUsesLibrariesStatusFile android.Path // a file with verify_uses_libraries errors (if any) | 
|  | 175 | ProvidesUsesLibrary            string       // library name (usually the same as module name) | 
|  | 176 | ClassLoaderContexts            ClassLoaderContextMap | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 177 |  | 
| Jeongik Cha | 4dda75e | 2021-04-27 23:56:44 +0900 | [diff] [blame] | 178 | Archs               []android.ArchType | 
|  | 179 | DexPreoptImagesDeps []android.OutputPaths | 
|  | 180 |  | 
|  | 181 | DexPreoptImageLocationsOnHost   []string // boot image location on host (file path without the arch subdirectory) | 
|  | 182 | DexPreoptImageLocationsOnDevice []string // boot image location on device (file path without the arch subdirectory) | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 183 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 184 | PreoptBootClassPathDexFiles     android.Paths // file paths of boot class path files | 
|  | 185 | PreoptBootClassPathDexLocations []string      // virtual locations of boot class path files | 
| Colin Cross | 800fe13 | 2019-02-11 14:21:24 -0800 | [diff] [blame] | 186 |  | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 187 | PreoptExtractedApk bool // Overrides OnlyPreoptModules | 
|  | 188 |  | 
|  | 189 | NoCreateAppImage    bool | 
|  | 190 | ForceCreateAppImage bool | 
|  | 191 |  | 
|  | 192 | PresignedPrebuilt bool | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 193 | } | 
|  | 194 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 195 | type globalSoongConfigSingleton struct{} | 
|  | 196 |  | 
|  | 197 | var pctx = android.NewPackageContext("android/soong/dexpreopt") | 
|  | 198 |  | 
|  | 199 | func init() { | 
|  | 200 | pctx.Import("android/soong/android") | 
| LaMont Jones | 0c10e4d | 2023-05-16 00:58:37 +0000 | [diff] [blame] | 201 | android.RegisterParallelSingletonType("dexpreopt-soong-config", func() android.Singleton { | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 202 | return &globalSoongConfigSingleton{} | 
|  | 203 | }) | 
|  | 204 | } | 
|  | 205 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 206 | func constructPath(ctx android.PathContext, path string) android.Path { | 
| Lukacs T. Berki | 9f6c24a | 2021-08-26 15:07:24 +0200 | [diff] [blame] | 207 | buildDirPrefix := ctx.Config().SoongOutDir() + "/" | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 208 | if path == "" { | 
|  | 209 | return nil | 
|  | 210 | } else if strings.HasPrefix(path, buildDirPrefix) { | 
|  | 211 | return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix)) | 
|  | 212 | } else { | 
|  | 213 | return android.PathForSource(ctx, path) | 
|  | 214 | } | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 215 | } | 
|  | 216 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 217 | func constructPaths(ctx android.PathContext, paths []string) android.Paths { | 
|  | 218 | var ret android.Paths | 
|  | 219 | for _, path := range paths { | 
|  | 220 | ret = append(ret, constructPath(ctx, path)) | 
|  | 221 | } | 
|  | 222 | return ret | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 225 | func constructWritablePath(ctx android.PathContext, path string) android.WritablePath { | 
|  | 226 | if path == "" { | 
|  | 227 | return nil | 
|  | 228 | } | 
|  | 229 | return constructPath(ctx, path).(android.WritablePath) | 
|  | 230 | } | 
|  | 231 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 232 | // ParseGlobalConfig parses the given data assumed to be read from the global | 
|  | 233 | // dexpreopt.config file into a GlobalConfig struct. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 234 | func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, error) { | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 235 | type GlobalJSONConfig struct { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 236 | *GlobalConfig | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 237 |  | 
|  | 238 | // Copies of entries in GlobalConfig that are not constructable without extra parameters.  They will be | 
|  | 239 | // used to construct the real value manually below. | 
| Paul Duffin | 7ccacae | 2020-10-23 21:14:20 +0100 | [diff] [blame] | 240 | BootImageProfiles []string | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 241 | } | 
|  | 242 |  | 
|  | 243 | config := GlobalJSONConfig{} | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 244 | err := json.Unmarshal(data, &config) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 245 | if err != nil { | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 246 | return config.GlobalConfig, err | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 247 | } | 
|  | 248 |  | 
|  | 249 | // Construct paths that require a PathContext. | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 250 | config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) | 
|  | 251 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 252 | return config.GlobalConfig, nil | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 253 | } | 
|  | 254 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 255 | type globalConfigAndRaw struct { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 256 | global     *GlobalConfig | 
|  | 257 | data       []byte | 
|  | 258 | pathErrors []error | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 259 | } | 
|  | 260 |  | 
|  | 261 | // GetGlobalConfig returns the global dexpreopt.config that's created in the | 
|  | 262 | // make config phase. It is loaded once the first time it is called for any | 
|  | 263 | // ctx.Config(), and returns the same data for all future calls with the same | 
|  | 264 | // ctx.Config(). A value can be inserted for tests using | 
|  | 265 | // setDexpreoptTestGlobalConfig. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 266 | func GetGlobalConfig(ctx android.PathContext) *GlobalConfig { | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 267 | return getGlobalConfigRaw(ctx).global | 
|  | 268 | } | 
|  | 269 |  | 
|  | 270 | // GetGlobalConfigRawData is the same as GetGlobalConfig, except that it returns | 
|  | 271 | // the literal content of dexpreopt.config. | 
|  | 272 | func GetGlobalConfigRawData(ctx android.PathContext) []byte { | 
|  | 273 | return getGlobalConfigRaw(ctx).data | 
|  | 274 | } | 
|  | 275 |  | 
|  | 276 | var globalConfigOnceKey = android.NewOnceKey("DexpreoptGlobalConfig") | 
|  | 277 | var testGlobalConfigOnceKey = android.NewOnceKey("TestDexpreoptGlobalConfig") | 
|  | 278 |  | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 279 | type pathContextErrorCollector struct { | 
|  | 280 | android.PathContext | 
|  | 281 | errors []error | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | func (p *pathContextErrorCollector) Errorf(format string, args ...interface{}) { | 
|  | 285 | p.errors = append(p.errors, fmt.Errorf(format, args...)) | 
|  | 286 | } | 
|  | 287 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 288 | func getGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 289 | config := ctx.Config().Once(globalConfigOnceKey, func() interface{} { | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 290 | if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil { | 
|  | 291 | panic(err) | 
|  | 292 | } else if data != nil { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 293 | pathErrorCollectorCtx := &pathContextErrorCollector{PathContext: ctx} | 
|  | 294 | globalConfig, err := ParseGlobalConfig(pathErrorCollectorCtx, data) | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 295 | if err != nil { | 
|  | 296 | panic(err) | 
|  | 297 | } | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 298 | return globalConfigAndRaw{globalConfig, data, pathErrorCollectorCtx.errors} | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 299 | } | 
|  | 300 |  | 
|  | 301 | // No global config filename set, see if there is a test config set | 
|  | 302 | return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} { | 
|  | 303 | // Nope, return a config with preopting disabled | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 304 | return globalConfigAndRaw{&GlobalConfig{ | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 305 | DisablePreopt:           true, | 
|  | 306 | DisablePreoptBootImages: true, | 
|  | 307 | DisableGenerateProfile:  true, | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 308 | }, nil, nil} | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 309 | }) | 
|  | 310 | }).(globalConfigAndRaw) | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 311 |  | 
|  | 312 | // Avoid non-deterministic errors by reporting cached path errors on all callers. | 
|  | 313 | for _, err := range config.pathErrors { | 
|  | 314 | if ctx.Config().AllowMissingDependencies() { | 
|  | 315 | // When AllowMissingDependencies it set, report errors through AddMissingDependencies. | 
|  | 316 | // If AddMissingDependencies doesn't exist on the current context (for example when | 
|  | 317 | // called with a SingletonContext), just swallow the errors since there is no way to | 
|  | 318 | // report them. | 
|  | 319 | if missingDepsCtx, ok := ctx.(interface { | 
|  | 320 | AddMissingDependencies(missingDeps []string) | 
|  | 321 | }); ok { | 
|  | 322 | missingDepsCtx.AddMissingDependencies([]string{err.Error()}) | 
|  | 323 | } | 
|  | 324 | } else { | 
| Colin Cross | c85750b | 2022-04-21 12:50:51 -0700 | [diff] [blame] | 325 | android.ReportPathErrorf(ctx, "%s", err) | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 326 | } | 
|  | 327 | } | 
|  | 328 |  | 
|  | 329 | return config | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 330 | } | 
|  | 331 |  | 
|  | 332 | // SetTestGlobalConfig sets a GlobalConfig that future calls to GetGlobalConfig | 
|  | 333 | // will return. It must be called before the first call to GetGlobalConfig for | 
|  | 334 | // the config. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 335 | func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 336 | config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil, nil} }) | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 337 | } | 
|  | 338 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 339 | // This struct is required to convert ModuleConfig from/to JSON. | 
|  | 340 | // The types of fields in ModuleConfig are not convertible, | 
|  | 341 | // so moduleJSONConfig has those fields as a convertible type. | 
|  | 342 | type moduleJSONConfig struct { | 
|  | 343 | *ModuleConfig | 
|  | 344 |  | 
|  | 345 | BuildPath    string | 
|  | 346 | DexPath      string | 
|  | 347 | ManifestPath string | 
|  | 348 |  | 
|  | 349 | ProfileClassListing string | 
|  | 350 | ProfileBootListing  string | 
|  | 351 |  | 
|  | 352 | EnforceUsesLibrariesStatusFile string | 
|  | 353 | ClassLoaderContexts            jsonClassLoaderContextMap | 
|  | 354 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 355 | DexPreoptImagesDeps [][]string | 
|  | 356 |  | 
|  | 357 | PreoptBootClassPathDexFiles []string | 
|  | 358 | } | 
|  | 359 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 360 | // ParseModuleConfig parses a per-module dexpreopt.config file into a | 
|  | 361 | // ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig | 
|  | 362 | // struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called | 
|  | 363 | // from Make to read the module dexpreopt.config written in the Make config | 
|  | 364 | // stage. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 365 | func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) { | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 366 | config := moduleJSONConfig{} | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 367 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 368 | err := json.Unmarshal(data, &config) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 369 | if err != nil { | 
|  | 370 | return config.ModuleConfig, err | 
|  | 371 | } | 
|  | 372 |  | 
|  | 373 | // Construct paths that require a PathContext. | 
|  | 374 | config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath) | 
|  | 375 | config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath) | 
| Jeongik Cha | 33a3a81 | 2021-04-15 09:12:49 +0900 | [diff] [blame] | 376 | config.ModuleConfig.ManifestPath = android.OptionalPathForPath(constructPath(ctx, config.ManifestPath)) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 377 | config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing)) | 
| Ulya Trafimovich | 8c35fcf | 2021-02-17 16:23:28 +0000 | [diff] [blame] | 378 | config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile) | 
| Ulya Trafimovich | 8cbc5d2 | 2020-11-03 15:15:46 +0000 | [diff] [blame] | 379 | config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 380 | config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 381 |  | 
| Dan Willemsen | 0f41678 | 2019-06-13 21:44:53 +0000 | [diff] [blame] | 382 | // This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON. | 
| Jeongik Cha | b19b58a | 2021-04-26 22:57:27 +0900 | [diff] [blame] | 383 | config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.Archs)) | 
| Dan Willemsen | 0f41678 | 2019-06-13 21:44:53 +0000 | [diff] [blame] | 384 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 385 | return config.ModuleConfig, nil | 
|  | 386 | } | 
|  | 387 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 388 | func pathsListToStringLists(pathsList []android.OutputPaths) [][]string { | 
|  | 389 | ret := make([][]string, 0, len(pathsList)) | 
|  | 390 | for _, paths := range pathsList { | 
|  | 391 | ret = append(ret, paths.Strings()) | 
|  | 392 | } | 
|  | 393 | return ret | 
|  | 394 | } | 
|  | 395 |  | 
|  | 396 | func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) { | 
|  | 397 | return json.MarshalIndent(&moduleJSONConfig{ | 
|  | 398 | BuildPath:                      config.BuildPath.String(), | 
|  | 399 | DexPath:                        config.DexPath.String(), | 
|  | 400 | ManifestPath:                   config.ManifestPath.String(), | 
|  | 401 | ProfileClassListing:            config.ProfileClassListing.String(), | 
|  | 402 | ProfileBootListing:             config.ProfileBootListing.String(), | 
|  | 403 | EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(), | 
|  | 404 | ClassLoaderContexts:            toJsonClassLoaderContext(config.ClassLoaderContexts), | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 405 | DexPreoptImagesDeps:            pathsListToStringLists(config.DexPreoptImagesDeps), | 
|  | 406 | PreoptBootClassPathDexFiles:    config.PreoptBootClassPathDexFiles.Strings(), | 
|  | 407 | ModuleConfig:                   config, | 
|  | 408 | }, "", "    ") | 
|  | 409 | } | 
|  | 410 |  | 
|  | 411 | // WriteModuleConfig serializes a ModuleConfig into a per-module dexpreopt.config JSON file. | 
|  | 412 | // These config files are used for post-processing. | 
|  | 413 | func WriteModuleConfig(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) { | 
| Ulya Trafimovich | 76b0852 | 2021-01-14 17:52:43 +0000 | [diff] [blame] | 414 | if path == nil { | 
|  | 415 | return | 
|  | 416 | } | 
|  | 417 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 418 | data, err := moduleConfigToJSON(config) | 
| Ulya Trafimovich | 76b0852 | 2021-01-14 17:52:43 +0000 | [diff] [blame] | 419 | if err != nil { | 
|  | 420 | ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err) | 
|  | 421 | return | 
|  | 422 | } | 
|  | 423 |  | 
|  | 424 | android.WriteFileRule(ctx, path, string(data)) | 
|  | 425 | } | 
|  | 426 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 427 | // dex2oatModuleName returns the name of the module to use for the dex2oat host | 
|  | 428 | // tool. It should be a binary module with public visibility that is compiled | 
|  | 429 | // and installed for host. | 
|  | 430 | func dex2oatModuleName(config android.Config) string { | 
|  | 431 | // Default to the debug variant of dex2oat to help find bugs. | 
|  | 432 | // Set USE_DEX2OAT_DEBUG to false for only building non-debug versions. | 
|  | 433 | if config.Getenv("USE_DEX2OAT_DEBUG") == "false" { | 
|  | 434 | return "dex2oat" | 
|  | 435 | } else { | 
|  | 436 | return "dex2oatd" | 
|  | 437 | } | 
|  | 438 | } | 
|  | 439 |  | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 440 | type dex2oatDependencyTag struct { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 441 | blueprint.BaseDependencyTag | 
| Colin Cross | ce56425 | 2022-01-12 11:13:32 -0800 | [diff] [blame] | 442 | android.LicenseAnnotationToolchainDependencyTag | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 443 | } | 
|  | 444 |  | 
|  | 445 | func (d dex2oatDependencyTag) ExcludeFromVisibilityEnforcement() { | 
|  | 446 | } | 
|  | 447 |  | 
|  | 448 | func (d dex2oatDependencyTag) ExcludeFromApexContents() { | 
|  | 449 | } | 
|  | 450 |  | 
| Martin Stjernholm | 0e4cceb | 2021-05-13 02:38:35 +0100 | [diff] [blame] | 451 | func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Module) bool { | 
|  | 452 | // RegisterToolDeps may run after the prebuilt mutators and hence register a | 
|  | 453 | // dependency on the source module even when the prebuilt is to be used. | 
|  | 454 | // dex2oatPathFromDep takes that into account when it retrieves the path to | 
|  | 455 | // the binary, but we also need to disable the check for dependencies on | 
|  | 456 | // disabled modules. | 
|  | 457 | return target.IsReplacedByPrebuilt() | 
|  | 458 | } | 
|  | 459 |  | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 460 | // Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that | 
|  | 461 | // needs dexpreopting and so it makes no sense for it to be checked for visibility or included in | 
|  | 462 | // the apex. | 
|  | 463 | var Dex2oatDepTag = dex2oatDependencyTag{} | 
|  | 464 |  | 
|  | 465 | var _ android.ExcludeFromVisibilityEnforcementTag = Dex2oatDepTag | 
|  | 466 | var _ android.ExcludeFromApexContentsTag = Dex2oatDepTag | 
| Martin Stjernholm | 0e4cceb | 2021-05-13 02:38:35 +0100 | [diff] [blame] | 467 | var _ android.AllowDisabledModuleDependency = Dex2oatDepTag | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 468 |  | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 469 | // RegisterToolDeps adds the necessary dependencies to binary modules for tools | 
|  | 470 | // that are required later when Get(Cached)GlobalSoongConfig is called. It | 
|  | 471 | // should be called from a mutator that's registered with | 
|  | 472 | // android.RegistrationContext.FinalDepsMutators. | 
|  | 473 | func RegisterToolDeps(ctx android.BottomUpMutatorContext) { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 474 | dex2oatBin := dex2oatModuleName(ctx.Config()) | 
|  | 475 | v := ctx.Config().BuildOSTarget.Variations() | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 476 | ctx.AddFarVariationDependencies(v, Dex2oatDepTag, dex2oatBin) | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 477 | } | 
|  | 478 |  | 
| Jiakai Zhang | bc698cd | 2023-05-08 16:28:38 +0000 | [diff] [blame] | 479 | func IsDex2oatNeeded(ctx android.PathContext) bool { | 
|  | 480 | global := GetGlobalConfig(ctx) | 
|  | 481 | return !global.DisablePreopt || !global.DisablePreoptBootImages | 
|  | 482 | } | 
|  | 483 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 484 | func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { | 
| Jiakai Zhang | bc698cd | 2023-05-08 16:28:38 +0000 | [diff] [blame] | 485 | if !IsDex2oatNeeded(ctx) { | 
|  | 486 | return nil | 
|  | 487 | } | 
|  | 488 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 489 | dex2oatBin := dex2oatModuleName(ctx.Config()) | 
|  | 490 |  | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 491 | // Find the right dex2oat module, trying to follow PrebuiltDepTag from source | 
|  | 492 | // to prebuilt if there is one. We wouldn't have to do this if the | 
|  | 493 | // prebuilt_postdeps mutator that replaces source deps with prebuilt deps was | 
|  | 494 | // run after RegisterToolDeps above, but changing that leads to ordering | 
|  | 495 | // problems between mutators (RegisterToolDeps needs to run late to act on | 
|  | 496 | // final variants, while prebuilt_postdeps needs to run before many of the | 
|  | 497 | // PostDeps mutators, like the APEX mutators). Hence we need to dig out the | 
|  | 498 | // prebuilt explicitly here instead. | 
|  | 499 | var dex2oatModule android.Module | 
|  | 500 | ctx.WalkDeps(func(child, parent android.Module) bool { | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 501 | if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 502 | // Found the source module, or prebuilt module that has replaced the source. | 
|  | 503 | dex2oatModule = child | 
| Paul Duffin | f7c99f5 | 2021-04-28 10:41:21 +0100 | [diff] [blame] | 504 | if android.IsModulePrebuilt(child) { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 505 | return false // If it's the prebuilt we're done. | 
|  | 506 | } else { | 
|  | 507 | return true // Recurse to check if the source has a prebuilt dependency. | 
|  | 508 | } | 
|  | 509 | } | 
|  | 510 | if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag { | 
| Paul Duffin | f7c99f5 | 2021-04-28 10:41:21 +0100 | [diff] [blame] | 511 | if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 512 | dex2oatModule = child // Found a prebuilt that should be used. | 
|  | 513 | } | 
|  | 514 | } | 
|  | 515 | return false | 
|  | 516 | }) | 
|  | 517 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 518 | if dex2oatModule == nil { | 
|  | 519 | // If this happens there's probably a missing call to AddToolDeps in DepsMutator. | 
|  | 520 | panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin)) | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath() | 
|  | 524 | if !dex2oatPath.Valid() { | 
|  | 525 | panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule)) | 
|  | 526 | } | 
|  | 527 |  | 
|  | 528 | return dex2oatPath.Path() | 
|  | 529 | } | 
|  | 530 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 531 | // createGlobalSoongConfig creates a GlobalSoongConfig from the current context. | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 532 | // Should not be used in dexpreopt_gen. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 533 | func createGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 534 | return &GlobalSoongConfig{ | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 535 | Profman:          ctx.Config().HostToolPath(ctx, "profman"), | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 536 | Dex2oat:          dex2oatPathFromDep(ctx), | 
| Saeid Farivar Asanjan | fd27c7c | 2022-08-08 20:21:26 +0000 | [diff] [blame] | 537 | Aapt:             ctx.Config().HostToolPath(ctx, "aapt2"), | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 538 | SoongZip:         ctx.Config().HostToolPath(ctx, "soong_zip"), | 
|  | 539 | Zip2zip:          ctx.Config().HostToolPath(ctx, "zip2zip"), | 
|  | 540 | ManifestCheck:    ctx.Config().HostToolPath(ctx, "manifest_check"), | 
| Ulya Trafimovich | 5f364b6 | 2020-06-30 12:39:01 +0100 | [diff] [blame] | 541 | ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"), | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 542 | } | 
|  | 543 | } | 
|  | 544 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 545 | // The main reason for this Once cache for GlobalSoongConfig is to make the | 
|  | 546 | // dex2oat path available to singletons. In ordinary modules we get it through a | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 547 | // Dex2oatDepTag dependency, but in singletons there's no simple way to do the | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 548 | // same thing and ensure the right variant is selected, hence this cache to make | 
|  | 549 | // the resolved path available to singletons. This means we depend on there | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 550 | // being at least one ordinary module with a Dex2oatDepTag dependency. | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 551 | // | 
|  | 552 | // TODO(b/147613152): Implement a way to deal with dependencies from singletons, | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 553 | // and then possibly remove this cache altogether. | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 554 | var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig") | 
|  | 555 |  | 
|  | 556 | // GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called, | 
|  | 557 | // and later returns the same cached instance. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 558 | func GetGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 559 | globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { | 
|  | 560 | return createGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 561 | }).(*GlobalSoongConfig) | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 562 |  | 
|  | 563 | // Always resolve the tool path from the dependency, to ensure that every | 
|  | 564 | // module has the dependency added properly. | 
|  | 565 | myDex2oat := dex2oatPathFromDep(ctx) | 
|  | 566 | if myDex2oat != globalSoong.Dex2oat { | 
|  | 567 | panic(fmt.Sprintf("Inconsistent dex2oat path in cached config: expected %s, got %s", globalSoong.Dex2oat, myDex2oat)) | 
|  | 568 | } | 
|  | 569 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 570 | return globalSoong | 
|  | 571 | } | 
|  | 572 |  | 
|  | 573 | // GetCachedGlobalSoongConfig returns a cached GlobalSoongConfig created by an | 
|  | 574 | // earlier GetGlobalSoongConfig call. This function works with any context | 
|  | 575 | // compatible with a basic PathContext, since it doesn't try to create a | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 576 | // GlobalSoongConfig with the proper paths (which requires a full | 
|  | 577 | // ModuleContext). If there has been no prior call to GetGlobalSoongConfig, nil | 
|  | 578 | // is returned. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 579 | func GetCachedGlobalSoongConfig(ctx android.PathContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 580 | return ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { | 
|  | 581 | return (*GlobalSoongConfig)(nil) | 
|  | 582 | }).(*GlobalSoongConfig) | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 583 | } | 
|  | 584 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 585 | type globalJsonSoongConfig struct { | 
|  | 586 | Profman          string | 
|  | 587 | Dex2oat          string | 
|  | 588 | Aapt             string | 
|  | 589 | SoongZip         string | 
|  | 590 | Zip2zip          string | 
|  | 591 | ManifestCheck    string | 
|  | 592 | ConstructContext string | 
|  | 593 | } | 
|  | 594 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 595 | // ParseGlobalSoongConfig parses the given data assumed to be read from the | 
|  | 596 | // global dexpreopt_soong.config file into a GlobalSoongConfig struct. It is | 
|  | 597 | // only used in dexpreopt_gen. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 598 | func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongConfig, error) { | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 599 | var jc globalJsonSoongConfig | 
|  | 600 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 601 | err := json.Unmarshal(data, &jc) | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 602 | if err != nil { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 603 | return &GlobalSoongConfig{}, err | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 604 | } | 
|  | 605 |  | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 606 | config := &GlobalSoongConfig{ | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 607 | Profman:          constructPath(ctx, jc.Profman), | 
|  | 608 | Dex2oat:          constructPath(ctx, jc.Dex2oat), | 
|  | 609 | Aapt:             constructPath(ctx, jc.Aapt), | 
|  | 610 | SoongZip:         constructPath(ctx, jc.SoongZip), | 
|  | 611 | Zip2zip:          constructPath(ctx, jc.Zip2zip), | 
|  | 612 | ManifestCheck:    constructPath(ctx, jc.ManifestCheck), | 
|  | 613 | ConstructContext: constructPath(ctx, jc.ConstructContext), | 
|  | 614 | } | 
|  | 615 |  | 
|  | 616 | return config, nil | 
|  | 617 | } | 
|  | 618 |  | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 619 | // checkBootJarsConfigConsistency checks the consistency of BootJars and ApexBootJars fields in | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 620 | // DexpreoptGlobalConfig and Config.productVariables. | 
|  | 621 | func checkBootJarsConfigConsistency(ctx android.SingletonContext, dexpreoptConfig *GlobalConfig, config android.Config) { | 
|  | 622 | compareBootJars := func(property string, dexpreoptJars, variableJars android.ConfiguredJarList) { | 
|  | 623 | dexpreoptPairs := dexpreoptJars.CopyOfApexJarPairs() | 
|  | 624 | variablePairs := variableJars.CopyOfApexJarPairs() | 
|  | 625 | if !reflect.DeepEqual(dexpreoptPairs, variablePairs) { | 
|  | 626 | ctx.Errorf("Inconsistent configuration of %[1]s\n"+ | 
|  | 627 | "    dexpreopt.GlobalConfig.%[1]s = %[2]s\n"+ | 
|  | 628 | "    productVariables.%[1]s       = %[3]s", | 
|  | 629 | property, dexpreoptPairs, variablePairs) | 
|  | 630 | } | 
|  | 631 | } | 
|  | 632 |  | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 633 | compareBootJars("BootJars", dexpreoptConfig.BootJars, config.NonApexBootJars()) | 
|  | 634 | compareBootJars("ApexBootJars", dexpreoptConfig.ApexBootJars, config.ApexBootJars()) | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 635 | } | 
|  | 636 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 637 | func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 638 | checkBootJarsConfigConsistency(ctx, GetGlobalConfig(ctx), ctx.Config()) | 
|  | 639 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 640 | if GetGlobalConfig(ctx).DisablePreopt { | 
|  | 641 | return | 
|  | 642 | } | 
|  | 643 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 644 | config := GetCachedGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 645 | if config == nil { | 
|  | 646 | // No module has enabled dexpreopting, so we assume there will be no calls | 
|  | 647 | // to dexpreopt_gen. | 
|  | 648 | return | 
|  | 649 | } | 
|  | 650 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 651 | jc := globalJsonSoongConfig{ | 
|  | 652 | Profman:          config.Profman.String(), | 
|  | 653 | Dex2oat:          config.Dex2oat.String(), | 
|  | 654 | Aapt:             config.Aapt.String(), | 
|  | 655 | SoongZip:         config.SoongZip.String(), | 
|  | 656 | Zip2zip:          config.Zip2zip.String(), | 
|  | 657 | ManifestCheck:    config.ManifestCheck.String(), | 
|  | 658 | ConstructContext: config.ConstructContext.String(), | 
|  | 659 | } | 
|  | 660 |  | 
|  | 661 | data, err := json.Marshal(jc) | 
|  | 662 | if err != nil { | 
|  | 663 | ctx.Errorf("failed to JSON marshal GlobalSoongConfig: %v", err) | 
|  | 664 | return | 
|  | 665 | } | 
|  | 666 |  | 
| Colin Cross | cf371cc | 2020-11-13 11:48:42 -0800 | [diff] [blame] | 667 | android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data)) | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 668 | } | 
|  | 669 |  | 
|  | 670 | func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 671 | if GetGlobalConfig(ctx).DisablePreopt { | 
|  | 672 | return | 
|  | 673 | } | 
|  | 674 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 675 | config := GetCachedGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 676 | if config == nil { | 
|  | 677 | return | 
|  | 678 | } | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 679 |  | 
|  | 680 | ctx.Strict("DEX2OAT", config.Dex2oat.String()) | 
|  | 681 | ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{ | 
|  | 682 | config.Profman.String(), | 
|  | 683 | config.Dex2oat.String(), | 
|  | 684 | config.Aapt.String(), | 
|  | 685 | config.SoongZip.String(), | 
|  | 686 | config.Zip2zip.String(), | 
|  | 687 | config.ManifestCheck.String(), | 
|  | 688 | config.ConstructContext.String(), | 
|  | 689 | }, " ")) | 
|  | 690 | } | 
|  | 691 |  | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 692 | func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { | 
|  | 693 | return &GlobalConfig{ | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 694 | DisablePreopt:                      false, | 
|  | 695 | DisablePreoptModules:               nil, | 
|  | 696 | OnlyPreoptBootImageAndSystemServer: false, | 
|  | 697 | HasSystemOther:                     false, | 
|  | 698 | PatternsOnSystemOther:              nil, | 
|  | 699 | DisableGenerateProfile:             false, | 
|  | 700 | ProfileDir:                         "", | 
| Ulya Trafimovich | 249386a | 2020-07-01 14:31:13 +0100 | [diff] [blame] | 701 | BootJars:                           android.EmptyConfiguredJarList(), | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 702 | ApexBootJars:                       android.EmptyConfiguredJarList(), | 
| Ulya Trafimovich | 249386a | 2020-07-01 14:31:13 +0100 | [diff] [blame] | 703 | ArtApexJars:                        android.EmptyConfiguredJarList(), | 
| Jiakai Zhang | 556bdf8 | 2023-07-12 16:51:57 +0100 | [diff] [blame] | 704 | TestOnlyArtBootImageJars:           android.EmptyConfiguredJarList(), | 
| satayev | 9a6f87e | 2021-05-04 16:14:48 +0100 | [diff] [blame] | 705 | SystemServerJars:                   android.EmptyConfiguredJarList(), | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 706 | SystemServerApps:                   nil, | 
| satayev | 492b17d | 2021-07-28 14:04:49 +0100 | [diff] [blame] | 707 | ApexSystemServerJars:               android.EmptyConfiguredJarList(), | 
| Jiakai Zhang | cee9e19 | 2021-10-29 19:46:45 +0000 | [diff] [blame] | 708 | StandaloneSystemServerJars:         android.EmptyConfiguredJarList(), | 
|  | 709 | ApexStandaloneSystemServerJars:     android.EmptyConfiguredJarList(), | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 710 | SpeedApps:                          nil, | 
|  | 711 | PreoptFlags:                        nil, | 
|  | 712 | DefaultCompilerFilter:              "", | 
|  | 713 | SystemServerCompilerFilter:         "", | 
|  | 714 | GenerateDMFiles:                    false, | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 715 | NoDebugInfo:                        false, | 
| Mathieu Chartier | 3f7ddbb | 2019-04-29 09:33:50 -0700 | [diff] [blame] | 716 | DontResolveStartupStrings:          false, | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 717 | AlwaysSystemServerDebugInfo:        false, | 
|  | 718 | NeverSystemServerDebugInfo:         false, | 
|  | 719 | AlwaysOtherDebugInfo:               false, | 
|  | 720 | NeverOtherDebugInfo:                false, | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 721 | IsEng:                              false, | 
|  | 722 | SanitizeLite:                       false, | 
|  | 723 | DefaultAppImages:                   false, | 
|  | 724 | Dex2oatXmx:                         "", | 
|  | 725 | Dex2oatXms:                         "", | 
|  | 726 | EmptyDirectory:                     "empty_dir", | 
|  | 727 | CpuVariant:                         nil, | 
|  | 728 | InstructionSetFeatures:             nil, | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 729 | BootImageProfiles:                  nil, | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 730 | BootFlags:                          "", | 
|  | 731 | Dex2oatImageXmx:                    "", | 
|  | 732 | Dex2oatImageXms:                    "", | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 733 | } | 
|  | 734 | } | 
|  | 735 |  | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 736 | func globalSoongConfigForTests() *GlobalSoongConfig { | 
|  | 737 | return &GlobalSoongConfig{ | 
|  | 738 | Profman:          android.PathForTesting("profman"), | 
|  | 739 | Dex2oat:          android.PathForTesting("dex2oat"), | 
| Saeid Farivar Asanjan | fd27c7c | 2022-08-08 20:21:26 +0000 | [diff] [blame] | 740 | Aapt:             android.PathForTesting("aapt2"), | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 741 | SoongZip:         android.PathForTesting("soong_zip"), | 
|  | 742 | Zip2zip:          android.PathForTesting("zip2zip"), | 
|  | 743 | ManifestCheck:    android.PathForTesting("manifest_check"), | 
|  | 744 | ConstructContext: android.PathForTesting("construct_context"), | 
|  | 745 | } | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 746 | } |