| 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 |  | 
| Jiakai Zhang | 2398442 | 2023-11-09 16:47:04 +0000 | [diff] [blame] | 35 | 	OnlyPreoptArtBootImage bool // only preopt jars in the ART boot image | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 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 | 	NoCreateAppImage    bool | 
 | 188 | 	ForceCreateAppImage bool | 
 | 189 |  | 
 | 190 | 	PresignedPrebuilt bool | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 191 | } | 
 | 192 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 193 | type globalSoongConfigSingleton struct{} | 
 | 194 |  | 
 | 195 | var pctx = android.NewPackageContext("android/soong/dexpreopt") | 
 | 196 |  | 
 | 197 | func init() { | 
 | 198 | 	pctx.Import("android/soong/android") | 
| LaMont Jones | 0c10e4d | 2023-05-16 00:58:37 +0000 | [diff] [blame] | 199 | 	android.RegisterParallelSingletonType("dexpreopt-soong-config", func() android.Singleton { | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 200 | 		return &globalSoongConfigSingleton{} | 
 | 201 | 	}) | 
 | 202 | } | 
 | 203 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 204 | func constructPath(ctx android.PathContext, path string) android.Path { | 
| Lukacs T. Berki | 9f6c24a | 2021-08-26 15:07:24 +0200 | [diff] [blame] | 205 | 	buildDirPrefix := ctx.Config().SoongOutDir() + "/" | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 206 | 	if path == "" { | 
 | 207 | 		return nil | 
 | 208 | 	} else if strings.HasPrefix(path, buildDirPrefix) { | 
 | 209 | 		return android.PathForOutput(ctx, strings.TrimPrefix(path, buildDirPrefix)) | 
 | 210 | 	} else { | 
 | 211 | 		return android.PathForSource(ctx, path) | 
 | 212 | 	} | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 213 | } | 
 | 214 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 215 | func constructPaths(ctx android.PathContext, paths []string) android.Paths { | 
 | 216 | 	var ret android.Paths | 
 | 217 | 	for _, path := range paths { | 
 | 218 | 		ret = append(ret, constructPath(ctx, path)) | 
 | 219 | 	} | 
 | 220 | 	return ret | 
| Colin Cross | 43f08db | 2018-11-12 10:13:39 -0800 | [diff] [blame] | 221 | } | 
 | 222 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 223 | func constructWritablePath(ctx android.PathContext, path string) android.WritablePath { | 
 | 224 | 	if path == "" { | 
 | 225 | 		return nil | 
 | 226 | 	} | 
 | 227 | 	return constructPath(ctx, path).(android.WritablePath) | 
 | 228 | } | 
 | 229 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 230 | // ParseGlobalConfig parses the given data assumed to be read from the global | 
 | 231 | // dexpreopt.config file into a GlobalConfig struct. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 232 | func ParseGlobalConfig(ctx android.PathContext, data []byte) (*GlobalConfig, error) { | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 233 | 	type GlobalJSONConfig struct { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 234 | 		*GlobalConfig | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 235 |  | 
 | 236 | 		// Copies of entries in GlobalConfig that are not constructable without extra parameters.  They will be | 
 | 237 | 		// used to construct the real value manually below. | 
| Paul Duffin | 7ccacae | 2020-10-23 21:14:20 +0100 | [diff] [blame] | 238 | 		BootImageProfiles []string | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 239 | 	} | 
 | 240 |  | 
 | 241 | 	config := GlobalJSONConfig{} | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 242 | 	err := json.Unmarshal(data, &config) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 243 | 	if err != nil { | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 244 | 		return config.GlobalConfig, err | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 245 | 	} | 
 | 246 |  | 
 | 247 | 	// Construct paths that require a PathContext. | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 248 | 	config.GlobalConfig.BootImageProfiles = constructPaths(ctx, config.BootImageProfiles) | 
 | 249 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 250 | 	return config.GlobalConfig, nil | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 251 | } | 
 | 252 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 253 | type globalConfigAndRaw struct { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 254 | 	global     *GlobalConfig | 
 | 255 | 	data       []byte | 
 | 256 | 	pathErrors []error | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 257 | } | 
 | 258 |  | 
 | 259 | // GetGlobalConfig returns the global dexpreopt.config that's created in the | 
 | 260 | // make config phase. It is loaded once the first time it is called for any | 
 | 261 | // ctx.Config(), and returns the same data for all future calls with the same | 
 | 262 | // ctx.Config(). A value can be inserted for tests using | 
 | 263 | // setDexpreoptTestGlobalConfig. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 264 | func GetGlobalConfig(ctx android.PathContext) *GlobalConfig { | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 265 | 	return getGlobalConfigRaw(ctx).global | 
 | 266 | } | 
 | 267 |  | 
 | 268 | // GetGlobalConfigRawData is the same as GetGlobalConfig, except that it returns | 
 | 269 | // the literal content of dexpreopt.config. | 
 | 270 | func GetGlobalConfigRawData(ctx android.PathContext) []byte { | 
 | 271 | 	return getGlobalConfigRaw(ctx).data | 
 | 272 | } | 
 | 273 |  | 
 | 274 | var globalConfigOnceKey = android.NewOnceKey("DexpreoptGlobalConfig") | 
 | 275 | var testGlobalConfigOnceKey = android.NewOnceKey("TestDexpreoptGlobalConfig") | 
 | 276 |  | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 277 | type pathContextErrorCollector struct { | 
 | 278 | 	android.PathContext | 
 | 279 | 	errors []error | 
 | 280 | } | 
 | 281 |  | 
 | 282 | func (p *pathContextErrorCollector) Errorf(format string, args ...interface{}) { | 
 | 283 | 	p.errors = append(p.errors, fmt.Errorf(format, args...)) | 
 | 284 | } | 
 | 285 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 286 | func getGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 287 | 	config := ctx.Config().Once(globalConfigOnceKey, func() interface{} { | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 288 | 		if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil { | 
 | 289 | 			panic(err) | 
 | 290 | 		} else if data != nil { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 291 | 			pathErrorCollectorCtx := &pathContextErrorCollector{PathContext: ctx} | 
 | 292 | 			globalConfig, err := ParseGlobalConfig(pathErrorCollectorCtx, data) | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 293 | 			if err != nil { | 
 | 294 | 				panic(err) | 
 | 295 | 			} | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 296 | 			return globalConfigAndRaw{globalConfig, data, pathErrorCollectorCtx.errors} | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 297 | 		} | 
 | 298 |  | 
 | 299 | 		// No global config filename set, see if there is a test config set | 
 | 300 | 		return ctx.Config().Once(testGlobalConfigOnceKey, func() interface{} { | 
 | 301 | 			// Nope, return a config with preopting disabled | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 302 | 			return globalConfigAndRaw{&GlobalConfig{ | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 303 | 				DisablePreopt:           true, | 
 | 304 | 				DisablePreoptBootImages: true, | 
 | 305 | 				DisableGenerateProfile:  true, | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 306 | 			}, nil, nil} | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 307 | 		}) | 
 | 308 | 	}).(globalConfigAndRaw) | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 309 |  | 
 | 310 | 	// Avoid non-deterministic errors by reporting cached path errors on all callers. | 
 | 311 | 	for _, err := range config.pathErrors { | 
 | 312 | 		if ctx.Config().AllowMissingDependencies() { | 
 | 313 | 			// When AllowMissingDependencies it set, report errors through AddMissingDependencies. | 
 | 314 | 			// If AddMissingDependencies doesn't exist on the current context (for example when | 
 | 315 | 			// called with a SingletonContext), just swallow the errors since there is no way to | 
 | 316 | 			// report them. | 
 | 317 | 			if missingDepsCtx, ok := ctx.(interface { | 
 | 318 | 				AddMissingDependencies(missingDeps []string) | 
 | 319 | 			}); ok { | 
 | 320 | 				missingDepsCtx.AddMissingDependencies([]string{err.Error()}) | 
 | 321 | 			} | 
 | 322 | 		} else { | 
| Colin Cross | c85750b | 2022-04-21 12:50:51 -0700 | [diff] [blame] | 323 | 			android.ReportPathErrorf(ctx, "%s", err) | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 324 | 		} | 
 | 325 | 	} | 
 | 326 |  | 
 | 327 | 	return config | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 328 | } | 
 | 329 |  | 
 | 330 | // SetTestGlobalConfig sets a GlobalConfig that future calls to GetGlobalConfig | 
 | 331 | // will return. It must be called before the first call to GetGlobalConfig for | 
 | 332 | // the config. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 333 | func SetTestGlobalConfig(config android.Config, globalConfig *GlobalConfig) { | 
| Colin Cross | 7134e28 | 2021-12-01 12:16:55 -0800 | [diff] [blame] | 334 | 	config.Once(testGlobalConfigOnceKey, func() interface{} { return globalConfigAndRaw{globalConfig, nil, nil} }) | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 335 | } | 
 | 336 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 337 | // This struct is required to convert ModuleConfig from/to JSON. | 
 | 338 | // The types of fields in ModuleConfig are not convertible, | 
 | 339 | // so moduleJSONConfig has those fields as a convertible type. | 
 | 340 | type moduleJSONConfig struct { | 
 | 341 | 	*ModuleConfig | 
 | 342 |  | 
 | 343 | 	BuildPath    string | 
 | 344 | 	DexPath      string | 
 | 345 | 	ManifestPath string | 
 | 346 |  | 
 | 347 | 	ProfileClassListing string | 
 | 348 | 	ProfileBootListing  string | 
 | 349 |  | 
 | 350 | 	EnforceUsesLibrariesStatusFile string | 
 | 351 | 	ClassLoaderContexts            jsonClassLoaderContextMap | 
 | 352 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 353 | 	DexPreoptImagesDeps [][]string | 
 | 354 |  | 
 | 355 | 	PreoptBootClassPathDexFiles []string | 
 | 356 | } | 
 | 357 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 358 | // ParseModuleConfig parses a per-module dexpreopt.config file into a | 
 | 359 | // ModuleConfig struct. It is not used in Soong, which receives a ModuleConfig | 
 | 360 | // struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called | 
 | 361 | // from Make to read the module dexpreopt.config written in the Make config | 
 | 362 | // stage. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 363 | func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, error) { | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 364 | 	config := moduleJSONConfig{} | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 365 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 366 | 	err := json.Unmarshal(data, &config) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 367 | 	if err != nil { | 
 | 368 | 		return config.ModuleConfig, err | 
 | 369 | 	} | 
 | 370 |  | 
 | 371 | 	// Construct paths that require a PathContext. | 
 | 372 | 	config.ModuleConfig.BuildPath = constructPath(ctx, config.BuildPath).(android.OutputPath) | 
 | 373 | 	config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath) | 
| Jeongik Cha | 33a3a81 | 2021-04-15 09:12:49 +0900 | [diff] [blame] | 374 | 	config.ModuleConfig.ManifestPath = android.OptionalPathForPath(constructPath(ctx, config.ManifestPath)) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 375 | 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing)) | 
| Ulya Trafimovich | 8c35fcf | 2021-02-17 16:23:28 +0000 | [diff] [blame] | 376 | 	config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile) | 
| Ulya Trafimovich | 8cbc5d2 | 2020-11-03 15:15:46 +0000 | [diff] [blame] | 377 | 	config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 378 | 	config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles) | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 379 |  | 
| Dan Willemsen | 0f41678 | 2019-06-13 21:44:53 +0000 | [diff] [blame] | 380 | 	// 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] | 381 | 	config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.Archs)) | 
| Dan Willemsen | 0f41678 | 2019-06-13 21:44:53 +0000 | [diff] [blame] | 382 |  | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 383 | 	return config.ModuleConfig, nil | 
 | 384 | } | 
 | 385 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 386 | func pathsListToStringLists(pathsList []android.OutputPaths) [][]string { | 
 | 387 | 	ret := make([][]string, 0, len(pathsList)) | 
 | 388 | 	for _, paths := range pathsList { | 
 | 389 | 		ret = append(ret, paths.Strings()) | 
 | 390 | 	} | 
 | 391 | 	return ret | 
 | 392 | } | 
 | 393 |  | 
 | 394 | func moduleConfigToJSON(config *ModuleConfig) ([]byte, error) { | 
 | 395 | 	return json.MarshalIndent(&moduleJSONConfig{ | 
 | 396 | 		BuildPath:                      config.BuildPath.String(), | 
 | 397 | 		DexPath:                        config.DexPath.String(), | 
 | 398 | 		ManifestPath:                   config.ManifestPath.String(), | 
 | 399 | 		ProfileClassListing:            config.ProfileClassListing.String(), | 
 | 400 | 		ProfileBootListing:             config.ProfileBootListing.String(), | 
 | 401 | 		EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(), | 
 | 402 | 		ClassLoaderContexts:            toJsonClassLoaderContext(config.ClassLoaderContexts), | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 403 | 		DexPreoptImagesDeps:            pathsListToStringLists(config.DexPreoptImagesDeps), | 
 | 404 | 		PreoptBootClassPathDexFiles:    config.PreoptBootClassPathDexFiles.Strings(), | 
 | 405 | 		ModuleConfig:                   config, | 
 | 406 | 	}, "", "    ") | 
 | 407 | } | 
 | 408 |  | 
 | 409 | // WriteModuleConfig serializes a ModuleConfig into a per-module dexpreopt.config JSON file. | 
 | 410 | // These config files are used for post-processing. | 
 | 411 | func WriteModuleConfig(ctx android.ModuleContext, config *ModuleConfig, path android.WritablePath) { | 
| Ulya Trafimovich | 76b0852 | 2021-01-14 17:52:43 +0000 | [diff] [blame] | 412 | 	if path == nil { | 
 | 413 | 		return | 
 | 414 | 	} | 
 | 415 |  | 
| Jeongik Cha | c624667 | 2021-04-08 00:00:19 +0900 | [diff] [blame] | 416 | 	data, err := moduleConfigToJSON(config) | 
| Ulya Trafimovich | 76b0852 | 2021-01-14 17:52:43 +0000 | [diff] [blame] | 417 | 	if err != nil { | 
 | 418 | 		ctx.ModuleErrorf("failed to JSON marshal module dexpreopt.config: %v", err) | 
 | 419 | 		return | 
 | 420 | 	} | 
 | 421 |  | 
 | 422 | 	android.WriteFileRule(ctx, path, string(data)) | 
 | 423 | } | 
 | 424 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 425 | // dex2oatModuleName returns the name of the module to use for the dex2oat host | 
 | 426 | // tool. It should be a binary module with public visibility that is compiled | 
 | 427 | // and installed for host. | 
 | 428 | func dex2oatModuleName(config android.Config) string { | 
 | 429 | 	// Default to the debug variant of dex2oat to help find bugs. | 
 | 430 | 	// Set USE_DEX2OAT_DEBUG to false for only building non-debug versions. | 
 | 431 | 	if config.Getenv("USE_DEX2OAT_DEBUG") == "false" { | 
 | 432 | 		return "dex2oat" | 
 | 433 | 	} else { | 
 | 434 | 		return "dex2oatd" | 
 | 435 | 	} | 
 | 436 | } | 
 | 437 |  | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 438 | type dex2oatDependencyTag struct { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 439 | 	blueprint.BaseDependencyTag | 
| Colin Cross | ce56425 | 2022-01-12 11:13:32 -0800 | [diff] [blame] | 440 | 	android.LicenseAnnotationToolchainDependencyTag | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 441 | } | 
 | 442 |  | 
 | 443 | func (d dex2oatDependencyTag) ExcludeFromVisibilityEnforcement() { | 
 | 444 | } | 
 | 445 |  | 
 | 446 | func (d dex2oatDependencyTag) ExcludeFromApexContents() { | 
 | 447 | } | 
 | 448 |  | 
| Martin Stjernholm | 0e4cceb | 2021-05-13 02:38:35 +0100 | [diff] [blame] | 449 | func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Module) bool { | 
 | 450 | 	// RegisterToolDeps may run after the prebuilt mutators and hence register a | 
 | 451 | 	// dependency on the source module even when the prebuilt is to be used. | 
 | 452 | 	// dex2oatPathFromDep takes that into account when it retrieves the path to | 
 | 453 | 	// the binary, but we also need to disable the check for dependencies on | 
 | 454 | 	// disabled modules. | 
 | 455 | 	return target.IsReplacedByPrebuilt() | 
 | 456 | } | 
 | 457 |  | 
| Paul Duffin | b506c9d | 2021-03-24 14:34:40 +0000 | [diff] [blame] | 458 | // Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that | 
 | 459 | // needs dexpreopting and so it makes no sense for it to be checked for visibility or included in | 
 | 460 | // the apex. | 
 | 461 | var Dex2oatDepTag = dex2oatDependencyTag{} | 
 | 462 |  | 
 | 463 | var _ android.ExcludeFromVisibilityEnforcementTag = Dex2oatDepTag | 
 | 464 | var _ android.ExcludeFromApexContentsTag = Dex2oatDepTag | 
| Martin Stjernholm | 0e4cceb | 2021-05-13 02:38:35 +0100 | [diff] [blame] | 465 | var _ android.AllowDisabledModuleDependency = Dex2oatDepTag | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 466 |  | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 467 | // RegisterToolDeps adds the necessary dependencies to binary modules for tools | 
 | 468 | // that are required later when Get(Cached)GlobalSoongConfig is called. It | 
 | 469 | // should be called from a mutator that's registered with | 
 | 470 | // android.RegistrationContext.FinalDepsMutators. | 
 | 471 | func RegisterToolDeps(ctx android.BottomUpMutatorContext) { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 472 | 	dex2oatBin := dex2oatModuleName(ctx.Config()) | 
 | 473 | 	v := ctx.Config().BuildOSTarget.Variations() | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 474 | 	ctx.AddFarVariationDependencies(v, Dex2oatDepTag, dex2oatBin) | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 475 | } | 
 | 476 |  | 
| Jiakai Zhang | bc698cd | 2023-05-08 16:28:38 +0000 | [diff] [blame] | 477 | func IsDex2oatNeeded(ctx android.PathContext) bool { | 
 | 478 | 	global := GetGlobalConfig(ctx) | 
 | 479 | 	return !global.DisablePreopt || !global.DisablePreoptBootImages | 
 | 480 | } | 
 | 481 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 482 | func dex2oatPathFromDep(ctx android.ModuleContext) android.Path { | 
| Jiakai Zhang | bc698cd | 2023-05-08 16:28:38 +0000 | [diff] [blame] | 483 | 	if !IsDex2oatNeeded(ctx) { | 
 | 484 | 		return nil | 
 | 485 | 	} | 
 | 486 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 487 | 	dex2oatBin := dex2oatModuleName(ctx.Config()) | 
 | 488 |  | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 489 | 	// Find the right dex2oat module, trying to follow PrebuiltDepTag from source | 
 | 490 | 	// to prebuilt if there is one. We wouldn't have to do this if the | 
 | 491 | 	// prebuilt_postdeps mutator that replaces source deps with prebuilt deps was | 
 | 492 | 	// run after RegisterToolDeps above, but changing that leads to ordering | 
 | 493 | 	// problems between mutators (RegisterToolDeps needs to run late to act on | 
 | 494 | 	// final variants, while prebuilt_postdeps needs to run before many of the | 
 | 495 | 	// PostDeps mutators, like the APEX mutators). Hence we need to dig out the | 
 | 496 | 	// prebuilt explicitly here instead. | 
 | 497 | 	var dex2oatModule android.Module | 
 | 498 | 	ctx.WalkDeps(func(child, parent android.Module) bool { | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 499 | 		if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 500 | 			// Found the source module, or prebuilt module that has replaced the source. | 
 | 501 | 			dex2oatModule = child | 
| Paul Duffin | f7c99f5 | 2021-04-28 10:41:21 +0100 | [diff] [blame] | 502 | 			if android.IsModulePrebuilt(child) { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 503 | 				return false // If it's the prebuilt we're done. | 
 | 504 | 			} else { | 
 | 505 | 				return true // Recurse to check if the source has a prebuilt dependency. | 
 | 506 | 			} | 
 | 507 | 		} | 
 | 508 | 		if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag { | 
| Paul Duffin | f7c99f5 | 2021-04-28 10:41:21 +0100 | [diff] [blame] | 509 | 			if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() { | 
| Martin Stjernholm | c004862 | 2020-08-18 17:37:41 +0100 | [diff] [blame] | 510 | 				dex2oatModule = child // Found a prebuilt that should be used. | 
 | 511 | 			} | 
 | 512 | 		} | 
 | 513 | 		return false | 
 | 514 | 	}) | 
 | 515 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 516 | 	if dex2oatModule == nil { | 
 | 517 | 		// If this happens there's probably a missing call to AddToolDeps in DepsMutator. | 
 | 518 | 		panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin)) | 
 | 519 | 	} | 
 | 520 |  | 
 | 521 | 	dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath() | 
 | 522 | 	if !dex2oatPath.Valid() { | 
 | 523 | 		panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule)) | 
 | 524 | 	} | 
 | 525 |  | 
 | 526 | 	return dex2oatPath.Path() | 
 | 527 | } | 
 | 528 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 529 | // createGlobalSoongConfig creates a GlobalSoongConfig from the current context. | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 530 | // Should not be used in dexpreopt_gen. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 531 | func createGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 532 | 	return &GlobalSoongConfig{ | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 533 | 		Profman:          ctx.Config().HostToolPath(ctx, "profman"), | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 534 | 		Dex2oat:          dex2oatPathFromDep(ctx), | 
| Saeid Farivar Asanjan | fd27c7c | 2022-08-08 20:21:26 +0000 | [diff] [blame] | 535 | 		Aapt:             ctx.Config().HostToolPath(ctx, "aapt2"), | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 536 | 		SoongZip:         ctx.Config().HostToolPath(ctx, "soong_zip"), | 
 | 537 | 		Zip2zip:          ctx.Config().HostToolPath(ctx, "zip2zip"), | 
 | 538 | 		ManifestCheck:    ctx.Config().HostToolPath(ctx, "manifest_check"), | 
| Ulya Trafimovich | 5f364b6 | 2020-06-30 12:39:01 +0100 | [diff] [blame] | 539 | 		ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"), | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 540 | 	} | 
 | 541 | } | 
 | 542 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 543 | // The main reason for this Once cache for GlobalSoongConfig is to make the | 
 | 544 | // 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] | 545 | // 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] | 546 | // same thing and ensure the right variant is selected, hence this cache to make | 
 | 547 | // the resolved path available to singletons. This means we depend on there | 
| Ulya Trafimovich | a4a1c4e | 2021-01-15 18:40:04 +0000 | [diff] [blame] | 548 | // being at least one ordinary module with a Dex2oatDepTag dependency. | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 549 | // | 
 | 550 | // TODO(b/147613152): Implement a way to deal with dependencies from singletons, | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 551 | // and then possibly remove this cache altogether. | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 552 | var globalSoongConfigOnceKey = android.NewOnceKey("DexpreoptGlobalSoongConfig") | 
 | 553 |  | 
 | 554 | // GetGlobalSoongConfig creates a GlobalSoongConfig the first time it's called, | 
 | 555 | // and later returns the same cached instance. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 556 | func GetGlobalSoongConfig(ctx android.ModuleContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 557 | 	globalSoong := ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { | 
 | 558 | 		return createGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 559 | 	}).(*GlobalSoongConfig) | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 560 |  | 
 | 561 | 	// Always resolve the tool path from the dependency, to ensure that every | 
 | 562 | 	// module has the dependency added properly. | 
 | 563 | 	myDex2oat := dex2oatPathFromDep(ctx) | 
 | 564 | 	if myDex2oat != globalSoong.Dex2oat { | 
 | 565 | 		panic(fmt.Sprintf("Inconsistent dex2oat path in cached config: expected %s, got %s", globalSoong.Dex2oat, myDex2oat)) | 
 | 566 | 	} | 
 | 567 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 568 | 	return globalSoong | 
 | 569 | } | 
 | 570 |  | 
 | 571 | // GetCachedGlobalSoongConfig returns a cached GlobalSoongConfig created by an | 
 | 572 | // earlier GetGlobalSoongConfig call. This function works with any context | 
 | 573 | // 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] | 574 | // GlobalSoongConfig with the proper paths (which requires a full | 
 | 575 | // ModuleContext). If there has been no prior call to GetGlobalSoongConfig, nil | 
 | 576 | // is returned. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 577 | func GetCachedGlobalSoongConfig(ctx android.PathContext) *GlobalSoongConfig { | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 578 | 	return ctx.Config().Once(globalSoongConfigOnceKey, func() interface{} { | 
 | 579 | 		return (*GlobalSoongConfig)(nil) | 
 | 580 | 	}).(*GlobalSoongConfig) | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 581 | } | 
 | 582 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 583 | type globalJsonSoongConfig struct { | 
 | 584 | 	Profman          string | 
 | 585 | 	Dex2oat          string | 
 | 586 | 	Aapt             string | 
 | 587 | 	SoongZip         string | 
 | 588 | 	Zip2zip          string | 
 | 589 | 	ManifestCheck    string | 
 | 590 | 	ConstructContext string | 
 | 591 | } | 
 | 592 |  | 
| Martin Stjernholm | 40f9f3c | 2020-01-20 18:12:23 +0000 | [diff] [blame] | 593 | // ParseGlobalSoongConfig parses the given data assumed to be read from the | 
 | 594 | // global dexpreopt_soong.config file into a GlobalSoongConfig struct. It is | 
 | 595 | // only used in dexpreopt_gen. | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 596 | func ParseGlobalSoongConfig(ctx android.PathContext, data []byte) (*GlobalSoongConfig, error) { | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 597 | 	var jc globalJsonSoongConfig | 
 | 598 |  | 
| Colin Cross | 988414c | 2020-01-11 01:11:46 +0000 | [diff] [blame] | 599 | 	err := json.Unmarshal(data, &jc) | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 600 | 	if err != nil { | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 601 | 		return &GlobalSoongConfig{}, err | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 602 | 	} | 
 | 603 |  | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 604 | 	config := &GlobalSoongConfig{ | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 605 | 		Profman:          constructPath(ctx, jc.Profman), | 
 | 606 | 		Dex2oat:          constructPath(ctx, jc.Dex2oat), | 
 | 607 | 		Aapt:             constructPath(ctx, jc.Aapt), | 
 | 608 | 		SoongZip:         constructPath(ctx, jc.SoongZip), | 
 | 609 | 		Zip2zip:          constructPath(ctx, jc.Zip2zip), | 
 | 610 | 		ManifestCheck:    constructPath(ctx, jc.ManifestCheck), | 
 | 611 | 		ConstructContext: constructPath(ctx, jc.ConstructContext), | 
 | 612 | 	} | 
 | 613 |  | 
 | 614 | 	return config, nil | 
 | 615 | } | 
 | 616 |  | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 617 | // checkBootJarsConfigConsistency checks the consistency of BootJars and ApexBootJars fields in | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 618 | // DexpreoptGlobalConfig and Config.productVariables. | 
 | 619 | func checkBootJarsConfigConsistency(ctx android.SingletonContext, dexpreoptConfig *GlobalConfig, config android.Config) { | 
 | 620 | 	compareBootJars := func(property string, dexpreoptJars, variableJars android.ConfiguredJarList) { | 
 | 621 | 		dexpreoptPairs := dexpreoptJars.CopyOfApexJarPairs() | 
 | 622 | 		variablePairs := variableJars.CopyOfApexJarPairs() | 
 | 623 | 		if !reflect.DeepEqual(dexpreoptPairs, variablePairs) { | 
 | 624 | 			ctx.Errorf("Inconsistent configuration of %[1]s\n"+ | 
 | 625 | 				"    dexpreopt.GlobalConfig.%[1]s = %[2]s\n"+ | 
 | 626 | 				"    productVariables.%[1]s       = %[3]s", | 
 | 627 | 				property, dexpreoptPairs, variablePairs) | 
 | 628 | 		} | 
 | 629 | 	} | 
 | 630 |  | 
| satayev | d604b21 | 2021-07-21 14:23:52 +0100 | [diff] [blame] | 631 | 	compareBootJars("BootJars", dexpreoptConfig.BootJars, config.NonApexBootJars()) | 
 | 632 | 	compareBootJars("ApexBootJars", dexpreoptConfig.ApexBootJars, config.ApexBootJars()) | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 633 | } | 
 | 634 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 635 | func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) { | 
| Paul Duffin | 7d1d083 | 2021-04-23 11:39:41 +0100 | [diff] [blame] | 636 | 	checkBootJarsConfigConsistency(ctx, GetGlobalConfig(ctx), ctx.Config()) | 
 | 637 |  | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 638 | 	if GetGlobalConfig(ctx).DisablePreopt { | 
 | 639 | 		return | 
 | 640 | 	} | 
 | 641 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 642 | 	config := GetCachedGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 643 | 	if config == nil { | 
 | 644 | 		// No module has enabled dexpreopting, so we assume there will be no calls | 
 | 645 | 		// to dexpreopt_gen. | 
 | 646 | 		return | 
 | 647 | 	} | 
 | 648 |  | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 649 | 	jc := globalJsonSoongConfig{ | 
 | 650 | 		Profman:          config.Profman.String(), | 
 | 651 | 		Dex2oat:          config.Dex2oat.String(), | 
 | 652 | 		Aapt:             config.Aapt.String(), | 
 | 653 | 		SoongZip:         config.SoongZip.String(), | 
 | 654 | 		Zip2zip:          config.Zip2zip.String(), | 
 | 655 | 		ManifestCheck:    config.ManifestCheck.String(), | 
 | 656 | 		ConstructContext: config.ConstructContext.String(), | 
 | 657 | 	} | 
 | 658 |  | 
 | 659 | 	data, err := json.Marshal(jc) | 
 | 660 | 	if err != nil { | 
 | 661 | 		ctx.Errorf("failed to JSON marshal GlobalSoongConfig: %v", err) | 
 | 662 | 		return | 
 | 663 | 	} | 
 | 664 |  | 
| Colin Cross | cf371cc | 2020-11-13 11:48:42 -0800 | [diff] [blame] | 665 | 	android.WriteFileRule(ctx, android.PathForOutput(ctx, "dexpreopt_soong.config"), string(data)) | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 666 | } | 
 | 667 |  | 
 | 668 | func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { | 
| Martin Stjernholm | d90676f | 2020-01-11 00:37:30 +0000 | [diff] [blame] | 669 | 	if GetGlobalConfig(ctx).DisablePreopt { | 
 | 670 | 		return | 
 | 671 | 	} | 
 | 672 |  | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 673 | 	config := GetCachedGlobalSoongConfig(ctx) | 
| Martin Stjernholm | 6d41527 | 2020-01-31 17:10:36 +0000 | [diff] [blame] | 674 | 	if config == nil { | 
 | 675 | 		return | 
 | 676 | 	} | 
| Martin Stjernholm | c52aaf1 | 2020-01-06 23:11:37 +0000 | [diff] [blame] | 677 |  | 
 | 678 | 	ctx.Strict("DEX2OAT", config.Dex2oat.String()) | 
 | 679 | 	ctx.Strict("DEXPREOPT_GEN_DEPS", strings.Join([]string{ | 
 | 680 | 		config.Profman.String(), | 
 | 681 | 		config.Dex2oat.String(), | 
 | 682 | 		config.Aapt.String(), | 
 | 683 | 		config.SoongZip.String(), | 
 | 684 | 		config.Zip2zip.String(), | 
 | 685 | 		config.ManifestCheck.String(), | 
 | 686 | 		config.ConstructContext.String(), | 
 | 687 | 	}, " ")) | 
 | 688 | } | 
 | 689 |  | 
| Martin Stjernholm | 8d80cee | 2020-01-31 17:44:54 +0000 | [diff] [blame] | 690 | func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { | 
 | 691 | 	return &GlobalConfig{ | 
| Jiakai Zhang | 2398442 | 2023-11-09 16:47:04 +0000 | [diff] [blame] | 692 | 		DisablePreopt:                  false, | 
 | 693 | 		DisablePreoptModules:           nil, | 
 | 694 | 		OnlyPreoptArtBootImage:         false, | 
 | 695 | 		HasSystemOther:                 false, | 
 | 696 | 		PatternsOnSystemOther:          nil, | 
 | 697 | 		DisableGenerateProfile:         false, | 
 | 698 | 		ProfileDir:                     "", | 
 | 699 | 		BootJars:                       android.EmptyConfiguredJarList(), | 
 | 700 | 		ApexBootJars:                   android.EmptyConfiguredJarList(), | 
 | 701 | 		ArtApexJars:                    android.EmptyConfiguredJarList(), | 
 | 702 | 		TestOnlyArtBootImageJars:       android.EmptyConfiguredJarList(), | 
 | 703 | 		SystemServerJars:               android.EmptyConfiguredJarList(), | 
 | 704 | 		SystemServerApps:               nil, | 
 | 705 | 		ApexSystemServerJars:           android.EmptyConfiguredJarList(), | 
 | 706 | 		StandaloneSystemServerJars:     android.EmptyConfiguredJarList(), | 
 | 707 | 		ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(), | 
 | 708 | 		SpeedApps:                      nil, | 
 | 709 | 		PreoptFlags:                    nil, | 
 | 710 | 		DefaultCompilerFilter:          "", | 
 | 711 | 		SystemServerCompilerFilter:     "", | 
 | 712 | 		GenerateDMFiles:                false, | 
 | 713 | 		NoDebugInfo:                    false, | 
 | 714 | 		DontResolveStartupStrings:      false, | 
 | 715 | 		AlwaysSystemServerDebugInfo:    false, | 
 | 716 | 		NeverSystemServerDebugInfo:     false, | 
 | 717 | 		AlwaysOtherDebugInfo:           false, | 
 | 718 | 		NeverOtherDebugInfo:            false, | 
 | 719 | 		IsEng:                          false, | 
 | 720 | 		SanitizeLite:                   false, | 
 | 721 | 		DefaultAppImages:               false, | 
 | 722 | 		Dex2oatXmx:                     "", | 
 | 723 | 		Dex2oatXms:                     "", | 
 | 724 | 		EmptyDirectory:                 "empty_dir", | 
 | 725 | 		CpuVariant:                     nil, | 
 | 726 | 		InstructionSetFeatures:         nil, | 
 | 727 | 		BootImageProfiles:              nil, | 
 | 728 | 		BootFlags:                      "", | 
 | 729 | 		Dex2oatImageXmx:                "", | 
 | 730 | 		Dex2oatImageXms:                "", | 
| Martin Stjernholm | 75a48d8 | 2020-01-10 20:32:59 +0000 | [diff] [blame] | 731 | 	} | 
 | 732 | } | 
 | 733 |  | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 734 | func globalSoongConfigForTests() *GlobalSoongConfig { | 
 | 735 | 	return &GlobalSoongConfig{ | 
 | 736 | 		Profman:          android.PathForTesting("profman"), | 
 | 737 | 		Dex2oat:          android.PathForTesting("dex2oat"), | 
| Saeid Farivar Asanjan | fd27c7c | 2022-08-08 20:21:26 +0000 | [diff] [blame] | 738 | 		Aapt:             android.PathForTesting("aapt2"), | 
| Paul Duffin | 9f04524 | 2021-01-21 15:05:11 +0000 | [diff] [blame] | 739 | 		SoongZip:         android.PathForTesting("soong_zip"), | 
 | 740 | 		Zip2zip:          android.PathForTesting("zip2zip"), | 
 | 741 | 		ManifestCheck:    android.PathForTesting("manifest_check"), | 
 | 742 | 		ConstructContext: android.PathForTesting("construct_context"), | 
 | 743 | 	} | 
| Colin Cross | 69f59a3 | 2019-02-15 10:39:37 -0800 | [diff] [blame] | 744 | } |