• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"fmt"
19	"reflect"
20	"runtime"
21	"strings"
22
23	"github.com/google/blueprint/proptools"
24)
25
26func init() {
27	registerVariableBuildComponents(InitRegistrationContext)
28}
29
30func registerVariableBuildComponents(ctx RegistrationContext) {
31	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
32		ctx.BottomUp("variable", VariableMutator).Parallel()
33	})
34}
35
36var PrepareForTestWithVariables = FixtureRegisterWithContext(registerVariableBuildComponents)
37
38type variableProperties struct {
39	Product_variables struct {
40		Platform_sdk_version struct {
41			Asflags []string
42			Cflags  []string
43			Cmd     *string
44		}
45
46		Platform_sdk_version_or_codename struct {
47			Java_resource_dirs []string
48		}
49
50		Platform_sdk_extension_version struct {
51			Cmd *string
52		}
53
54		Platform_version_name struct {
55			Base_dir *string
56		}
57
58		Shipping_api_level struct {
59			Cflags []string
60		}
61
62		// unbundled_build is a catch-all property to annotate modules that don't build in one or
63		// more unbundled branches, usually due to dependencies missing from the manifest.
64		Unbundled_build struct {
65			Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
66		} `android:"arch_variant"`
67
68		// similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt
69		// sdk specifically.
70		Always_use_prebuilt_sdks struct {
71			Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
72		} `android:"arch_variant"`
73
74		Malloc_low_memory struct {
75			Cflags              []string `android:"arch_variant"`
76			Shared_libs         []string `android:"arch_variant"`
77			Whole_static_libs   []string `android:"arch_variant"`
78			Static_libs         []string `android:"arch_variant"`
79			Exclude_static_libs []string `android:"arch_variant"`
80			Srcs                []string `android:"arch_variant"`
81			Header_libs         []string `android:"arch_variant"`
82		} `android:"arch_variant"`
83
84		Malloc_zero_contents struct {
85			Cflags []string `android:"arch_variant"`
86		} `android:"arch_variant"`
87
88		Malloc_pattern_fill_contents struct {
89			Cflags []string `android:"arch_variant"`
90		} `android:"arch_variant"`
91
92		Safestack struct {
93			Cflags []string `android:"arch_variant"`
94		} `android:"arch_variant"`
95
96		Binder32bit struct {
97			Cflags []string
98		}
99
100		Override_rs_driver struct {
101			Cflags []string
102		}
103
104		// treble_linker_namespaces is true when the system/vendor linker namespace separation is
105		// enabled.
106		Treble_linker_namespaces struct {
107			Cflags []string
108		}
109		// enforce_vintf_manifest is true when a device is required to have a vintf manifest.
110		Enforce_vintf_manifest struct {
111			Cflags []string
112		}
113
114		Build_from_text_stub struct {
115			Static_libs         []string
116			Exclude_static_libs []string
117		}
118
119		// debuggable is true for eng and userdebug builds, and can be used to turn on additional
120		// debugging features that don't significantly impact runtime behavior.  userdebug builds
121		// are used for dogfooding and performance testing, and should be as similar to user builds
122		// as possible.
123		Debuggable struct {
124			Cflags          []string
125			Cppflags        []string
126			Init_rc         []string
127			Required        []string
128			Host_required   []string
129			Target_required []string
130			Strip           struct {
131				All                          *bool
132				Keep_symbols                 *bool
133				Keep_symbols_and_debug_frame *bool
134			}
135			Static_libs       []string
136			Whole_static_libs []string
137			Shared_libs       []string
138
139			Cmdline []string
140
141			Srcs         []string
142			Exclude_srcs []string
143			Cmd          *string
144
145			Deps []string
146		}
147
148		// eng is true for -eng builds, and can be used to turn on additional heavyweight debugging
149		// features.
150		Eng struct {
151			Cflags   []string
152			Cppflags []string
153			Lto      struct {
154				Never *bool
155			}
156			Sanitize struct {
157				Address *bool
158			}
159			Optimize struct {
160				Enabled *bool
161			}
162		}
163
164		Uml struct {
165			Cppflags []string
166		}
167
168		Arc struct {
169			Cflags            []string `android:"arch_variant"`
170			Exclude_srcs      []string `android:"arch_variant"`
171			Header_libs       []string `android:"arch_variant"`
172			Include_dirs      []string `android:"arch_variant"`
173			Shared_libs       []string `android:"arch_variant"`
174			Static_libs       []string `android:"arch_variant"`
175			Srcs              []string `android:"arch_variant"`
176			Whole_static_libs []string `android:"arch_variant"`
177		} `android:"arch_variant"`
178
179		Native_coverage struct {
180			Src          *string  `android:"arch_variant"`
181			Srcs         []string `android:"arch_variant"`
182			Exclude_srcs []string `android:"arch_variant"`
183		} `android:"arch_variant"`
184
185		// release_aidl_use_unfrozen is "true" when a device can
186		// use the unfrozen versions of AIDL interfaces.
187		Release_aidl_use_unfrozen struct {
188			Cflags          []string
189			Cmd             *string
190			Required        []string
191			Vintf_fragments []string
192		}
193	} `android:"arch_variant"`
194}
195
196var defaultProductVariables interface{} = variableProperties{}
197
198type ProductVariables struct {
199	// Suffix to add to generated Makefiles
200	Make_suffix *string `json:",omitempty"`
201
202	BuildId             *string `json:",omitempty"`
203	BuildNumberFile     *string `json:",omitempty"`
204	BuildHostnameFile   *string `json:",omitempty"`
205	BuildThumbprintFile *string `json:",omitempty"`
206	DisplayBuildNumber  *bool   `json:",omitempty"`
207
208	Platform_display_version_name          *string  `json:",omitempty"`
209	Platform_version_name                  *string  `json:",omitempty"`
210	Platform_sdk_version                   *int     `json:",omitempty"`
211	Platform_sdk_codename                  *string  `json:",omitempty"`
212	Platform_sdk_version_or_codename       *string  `json:",omitempty"`
213	Platform_sdk_final                     *bool    `json:",omitempty"`
214	Platform_sdk_extension_version         *int     `json:",omitempty"`
215	Platform_base_sdk_extension_version    *int     `json:",omitempty"`
216	Platform_version_active_codenames      []string `json:",omitempty"`
217	Platform_version_all_preview_codenames []string `json:",omitempty"`
218	Platform_systemsdk_versions            []string `json:",omitempty"`
219	Platform_security_patch                *string  `json:",omitempty"`
220	Platform_preview_sdk_version           *string  `json:",omitempty"`
221	Platform_base_os                       *string  `json:",omitempty"`
222	Platform_version_last_stable           *string  `json:",omitempty"`
223	Platform_version_known_codenames       *string  `json:",omitempty"`
224
225	DeviceName                            *string  `json:",omitempty"`
226	DeviceProduct                         *string  `json:",omitempty"`
227	DeviceArch                            *string  `json:",omitempty"`
228	DeviceArchVariant                     *string  `json:",omitempty"`
229	DeviceCpuVariant                      *string  `json:",omitempty"`
230	DeviceAbi                             []string `json:",omitempty"`
231	DeviceVndkVersion                     *string  `json:",omitempty"`
232	DeviceCurrentApiLevelForVendorModules *string  `json:",omitempty"`
233	DeviceSystemSdkVersions               []string `json:",omitempty"`
234	DeviceMaxPageSizeSupported            *string  `json:",omitempty"`
235	DeviceNoBionicPageSizeMacro           *bool    `json:",omitempty"`
236
237	VendorApiLevel *string `json:",omitempty"`
238
239	RecoverySnapshotVersion *string `json:",omitempty"`
240
241	DeviceSecondaryArch        *string  `json:",omitempty"`
242	DeviceSecondaryArchVariant *string  `json:",omitempty"`
243	DeviceSecondaryCpuVariant  *string  `json:",omitempty"`
244	DeviceSecondaryAbi         []string `json:",omitempty"`
245
246	NativeBridgeArch         *string  `json:",omitempty"`
247	NativeBridgeArchVariant  *string  `json:",omitempty"`
248	NativeBridgeCpuVariant   *string  `json:",omitempty"`
249	NativeBridgeAbi          []string `json:",omitempty"`
250	NativeBridgeRelativePath *string  `json:",omitempty"`
251
252	NativeBridgeSecondaryArch         *string  `json:",omitempty"`
253	NativeBridgeSecondaryArchVariant  *string  `json:",omitempty"`
254	NativeBridgeSecondaryCpuVariant   *string  `json:",omitempty"`
255	NativeBridgeSecondaryAbi          []string `json:",omitempty"`
256	NativeBridgeSecondaryRelativePath *string  `json:",omitempty"`
257
258	HostArch          *string `json:",omitempty"`
259	HostSecondaryArch *string `json:",omitempty"`
260	HostMusl          *bool   `json:",omitempty"`
261
262	CrossHost              *string `json:",omitempty"`
263	CrossHostArch          *string `json:",omitempty"`
264	CrossHostSecondaryArch *string `json:",omitempty"`
265
266	DeviceResourceOverlays     []string `json:",omitempty"`
267	ProductResourceOverlays    []string `json:",omitempty"`
268	EnforceRROTargets          []string `json:",omitempty"`
269	EnforceRROExcludedOverlays []string `json:",omitempty"`
270
271	AAPTCharacteristics *string  `json:",omitempty"`
272	AAPTConfig          []string `json:",omitempty"`
273	AAPTPreferredConfig *string  `json:",omitempty"`
274	AAPTPrebuiltDPI     []string `json:",omitempty"`
275
276	DefaultAppCertificate           *string `json:",omitempty"`
277	MainlineSepolicyDevCertificates *string `json:",omitempty"`
278
279	AppsDefaultVersionName *string `json:",omitempty"`
280
281	Allow_missing_dependencies   *bool    `json:",omitempty"`
282	Unbundled_build              *bool    `json:",omitempty"`
283	Unbundled_build_apps         []string `json:",omitempty"`
284	Unbundled_build_image        *bool    `json:",omitempty"`
285	Always_use_prebuilt_sdks     *bool    `json:",omitempty"`
286	Skip_boot_jars_check         *bool    `json:",omitempty"`
287	Malloc_low_memory            *bool    `json:",omitempty"`
288	Malloc_zero_contents         *bool    `json:",omitempty"`
289	Malloc_pattern_fill_contents *bool    `json:",omitempty"`
290	Safestack                    *bool    `json:",omitempty"`
291	HostStaticBinaries           *bool    `json:",omitempty"`
292	Binder32bit                  *bool    `json:",omitempty"`
293	UseGoma                      *bool    `json:",omitempty"`
294	UseRBE                       *bool    `json:",omitempty"`
295	UseRBEJAVAC                  *bool    `json:",omitempty"`
296	UseRBER8                     *bool    `json:",omitempty"`
297	UseRBED8                     *bool    `json:",omitempty"`
298	Debuggable                   *bool    `json:",omitempty"`
299	Eng                          *bool    `json:",omitempty"`
300	Treble_linker_namespaces     *bool    `json:",omitempty"`
301	Enforce_vintf_manifest       *bool    `json:",omitempty"`
302	Uml                          *bool    `json:",omitempty"`
303	Arc                          *bool    `json:",omitempty"`
304	MinimizeJavaDebugInfo        *bool    `json:",omitempty"`
305	Build_from_text_stub         *bool    `json:",omitempty"`
306
307	BuildType *string `json:",omitempty"`
308
309	Check_elf_files *bool `json:",omitempty"`
310
311	UncompressPrivAppDex             *bool    `json:",omitempty"`
312	ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
313
314	BootJars     ConfiguredJarList `json:",omitempty"`
315	ApexBootJars ConfiguredJarList `json:",omitempty"`
316
317	IntegerOverflowExcludePaths []string `json:",omitempty"`
318
319	EnableCFI       *bool    `json:",omitempty"`
320	CFIExcludePaths []string `json:",omitempty"`
321	CFIIncludePaths []string `json:",omitempty"`
322
323	DisableScudo *bool `json:",omitempty"`
324
325	MemtagHeapExcludePaths      []string `json:",omitempty"`
326	MemtagHeapAsyncIncludePaths []string `json:",omitempty"`
327	MemtagHeapSyncIncludePaths  []string `json:",omitempty"`
328
329	HWASanIncludePaths []string `json:",omitempty"`
330	HWASanExcludePaths []string `json:",omitempty"`
331
332	VendorPath    *string `json:",omitempty"`
333	OdmPath       *string `json:",omitempty"`
334	ProductPath   *string `json:",omitempty"`
335	SystemExtPath *string `json:",omitempty"`
336
337	ClangTidy  *bool   `json:",omitempty"`
338	TidyChecks *string `json:",omitempty"`
339
340	JavaCoveragePaths        []string `json:",omitempty"`
341	JavaCoverageExcludePaths []string `json:",omitempty"`
342
343	GcovCoverage                *bool    `json:",omitempty"`
344	ClangCoverage               *bool    `json:",omitempty"`
345	NativeCoveragePaths         []string `json:",omitempty"`
346	NativeCoverageExcludePaths  []string `json:",omitempty"`
347	ClangCoverageContinuousMode *bool    `json:",omitempty"`
348
349	// Set by NewConfig
350	Native_coverage *bool `json:",omitempty"`
351
352	SanitizeHost       []string `json:",omitempty"`
353	SanitizeDevice     []string `json:",omitempty"`
354	SanitizeDeviceDiag []string `json:",omitempty"`
355	SanitizeDeviceArch []string `json:",omitempty"`
356
357	ArtUseReadBarrier *bool `json:",omitempty"`
358
359	BtConfigIncludeDir *string `json:",omitempty"`
360
361	Override_rs_driver *string `json:",omitempty"`
362
363	DeviceKernelHeaders []string `json:",omitempty"`
364
365	ExtraVndkVersions []string `json:",omitempty"`
366
367	NamespacesToExport []string `json:",omitempty"`
368
369	PgoAdditionalProfileDirs []string `json:",omitempty"`
370
371	VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
372
373	DirectedVendorSnapshot bool            `json:",omitempty"`
374	VendorSnapshotModules  map[string]bool `json:",omitempty"`
375
376	DirectedRecoverySnapshot bool            `json:",omitempty"`
377	RecoverySnapshotModules  map[string]bool `json:",omitempty"`
378
379	VendorSnapshotDirsIncluded   []string `json:",omitempty"`
380	VendorSnapshotDirsExcluded   []string `json:",omitempty"`
381	RecoverySnapshotDirsExcluded []string `json:",omitempty"`
382	RecoverySnapshotDirsIncluded []string `json:",omitempty"`
383	HostFakeSnapshotEnabled      bool     `json:",omitempty"`
384
385	MultitreeUpdateMeta bool `json:",omitempty"`
386
387	BoardVendorSepolicyDirs      []string `json:",omitempty"`
388	BoardOdmSepolicyDirs         []string `json:",omitempty"`
389	SystemExtPublicSepolicyDirs  []string `json:",omitempty"`
390	SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
391	BoardSepolicyM4Defs          []string `json:",omitempty"`
392
393	BoardSepolicyVers       *string `json:",omitempty"`
394	PlatformSepolicyVersion *string `json:",omitempty"`
395
396	SystemExtSepolicyPrebuiltApiDir *string `json:",omitempty"`
397	ProductSepolicyPrebuiltApiDir   *string `json:",omitempty"`
398
399	PlatformSepolicyCompatVersions []string `json:",omitempty"`
400
401	VendorVars map[string]map[string]string `json:",omitempty"`
402
403	Ndk_abis *bool `json:",omitempty"`
404
405	TrimmedApex                  *bool `json:",omitempty"`
406	ForceApexSymlinkOptimization *bool `json:",omitempty"`
407	CompressedApex               *bool `json:",omitempty"`
408	Aml_abis                     *bool `json:",omitempty"`
409
410	DexpreoptGlobalConfig *string `json:",omitempty"`
411
412	WithDexpreopt bool `json:",omitempty"`
413
414	ManifestPackageNameOverrides   []string `json:",omitempty"`
415	CertificateOverrides           []string `json:",omitempty"`
416	PackageNameOverrides           []string `json:",omitempty"`
417	ConfiguredJarLocationOverrides []string `json:",omitempty"`
418
419	ApexGlobalMinSdkVersionOverride *string `json:",omitempty"`
420
421	EnforceSystemCertificate          *bool    `json:",omitempty"`
422	EnforceSystemCertificateAllowList []string `json:",omitempty"`
423
424	ProductHiddenAPIStubs       []string `json:",omitempty"`
425	ProductHiddenAPIStubsSystem []string `json:",omitempty"`
426	ProductHiddenAPIStubsTest   []string `json:",omitempty"`
427
428	ProductPublicSepolicyDirs  []string `json:",omitempty"`
429	ProductPrivateSepolicyDirs []string `json:",omitempty"`
430
431	TargetFSConfigGen []string `json:",omitempty"`
432
433	EnforceProductPartitionInterface *bool `json:",omitempty"`
434
435	EnforceInterPartitionJavaSdkLibrary *bool    `json:",omitempty"`
436	InterPartitionJavaLibraryAllowList  []string `json:",omitempty"`
437
438	BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
439
440	BoardKernelBinaries                []string `json:",omitempty"`
441	BoardKernelModuleInterfaceVersions []string `json:",omitempty"`
442
443	BoardMoveRecoveryResourcesToVendorBoot *bool `json:",omitempty"`
444
445	PrebuiltHiddenApiDir *string `json:",omitempty"`
446
447	Shipping_api_level *string `json:",omitempty"`
448
449	BuildBrokenPluginValidation         []string `json:",omitempty"`
450	BuildBrokenClangAsFlags             bool     `json:",omitempty"`
451	BuildBrokenClangCFlags              bool     `json:",omitempty"`
452	BuildBrokenClangProperty            bool     `json:",omitempty"`
453	GenruleSandboxing                   *bool    `json:",omitempty"`
454	BuildBrokenEnforceSyspropOwner      bool     `json:",omitempty"`
455	BuildBrokenTrebleSyspropNeverallow  bool     `json:",omitempty"`
456	BuildBrokenUsesSoongPython2Modules  bool     `json:",omitempty"`
457	BuildBrokenVendorPropertyNamespace  bool     `json:",omitempty"`
458	BuildBrokenIncorrectPartitionImages bool     `json:",omitempty"`
459	BuildBrokenInputDirModules          []string `json:",omitempty"`
460	BuildBrokenDontCheckSystemSdk       bool     `json:",omitempty"`
461
462	BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
463
464	BuildDebugfsRestrictionsEnabled bool `json:",omitempty"`
465
466	RequiresInsecureExecmemForSwiftshader bool `json:",omitempty"`
467
468	SelinuxIgnoreNeverallows bool `json:",omitempty"`
469
470	Release_aidl_use_unfrozen *bool `json:",omitempty"`
471
472	SepolicyFreezeTestExtraDirs         []string `json:",omitempty"`
473	SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
474
475	GenerateAidlNdkPlatformBackend bool `json:",omitempty"`
476
477	IgnorePrefer32OnDevice bool `json:",omitempty"`
478
479	SourceRootDirs []string `json:",omitempty"`
480
481	AfdoProfiles []string `json:",omitempty"`
482
483	ProductManufacturer string `json:",omitempty"`
484	ProductBrand        string `json:",omitempty"`
485
486	ReleaseVersion          string   `json:",omitempty"`
487	ReleaseAconfigValueSets []string `json:",omitempty"`
488
489	ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
490
491	ReleaseDefaultModuleBuildFromSource *bool `json:",omitempty"`
492
493	CheckVendorSeappViolations *bool `json:",omitempty"`
494
495	BuildFlags map[string]string `json:",omitempty"`
496
497	BuildFlagTypes map[string]string `json:",omitempty"`
498
499	BuildFromSourceStub *bool `json:",omitempty"`
500
501	BuildIgnoreApexContributionContents *bool `json:",omitempty"`
502
503	HiddenapiExportableStubs *bool `json:",omitempty"`
504
505	ExportRuntimeApis *bool `json:",omitempty"`
506
507	AconfigContainerValidation string `json:",omitempty"`
508
509	ProductLocales []string `json:",omitempty"`
510
511	ProductDefaultWifiChannels []string `json:",omitempty"`
512
513	BoardUseVbmetaDigestInFingerprint *bool `json:",omitempty"`
514
515	OemProperties []string `json:",omitempty"`
516}
517
518type PartitionQualifiedVariablesType struct {
519	BuildingImage               bool   `json:",omitempty"`
520	BoardErofsCompressor        string `json:",omitempty"`
521	BoardErofsCompressHints     string `json:",omitempty"`
522	BoardErofsPclusterSize      string `json:",omitempty"`
523	BoardExtfsInodeCount        string `json:",omitempty"`
524	BoardExtfsRsvPct            string `json:",omitempty"`
525	BoardF2fsSloadCompressFlags string `json:",omitempty"`
526	BoardFileSystemCompress     string `json:",omitempty"`
527	BoardFileSystemType         string `json:",omitempty"`
528	BoardJournalSize            string `json:",omitempty"`
529	BoardPartitionReservedSize  string `json:",omitempty"`
530	BoardPartitionSize          string `json:",omitempty"`
531	BoardSquashfsBlockSize      string `json:",omitempty"`
532	BoardSquashfsCompressor     string `json:",omitempty"`
533	BoardSquashfsCompressorOpt  string `json:",omitempty"`
534	BoardSquashfsDisable4kAlign string `json:",omitempty"`
535	ProductBaseFsPath           string `json:",omitempty"`
536	ProductHeadroom             string `json:",omitempty"`
537	ProductVerityPartition      string `json:",omitempty"`
538
539	BoardAvbAddHashtreeFooterArgs string `json:",omitempty"`
540	BoardAvbKeyPath               string `json:",omitempty"`
541	BoardAvbAlgorithm             string `json:",omitempty"`
542	BoardAvbRollbackIndex         string `json:",omitempty"`
543	BoardAvbRollbackIndexLocation string `json:",omitempty"`
544}
545
546type PartitionVariables struct {
547	ProductDirectory            string `json:",omitempty"`
548	PartitionQualifiedVariables map[string]PartitionQualifiedVariablesType
549	TargetUserimagesUseExt2     bool `json:",omitempty"`
550	TargetUserimagesUseExt3     bool `json:",omitempty"`
551	TargetUserimagesUseExt4     bool `json:",omitempty"`
552
553	TargetUserimagesSparseExtDisabled      bool `json:",omitempty"`
554	TargetUserimagesSparseErofsDisabled    bool `json:",omitempty"`
555	TargetUserimagesSparseSquashfsDisabled bool `json:",omitempty"`
556	TargetUserimagesSparseF2fsDisabled     bool `json:",omitempty"`
557
558	BoardErofsCompressor           string `json:",omitempty"`
559	BoardErofsCompressorHints      string `json:",omitempty"`
560	BoardErofsPclusterSize         string `json:",omitempty"`
561	BoardErofsShareDupBlocks       string `json:",omitempty"`
562	BoardErofsUseLegacyCompression string `json:",omitempty"`
563	BoardExt4ShareDupBlocks        string `json:",omitempty"`
564	BoardFlashLogicalBlockSize     string `json:",omitempty"`
565	BoardFlashEraseBlockSize       string `json:",omitempty"`
566	BoardUsesRecoveryAsBoot        bool   `json:",omitempty"`
567	ProductUseDynamicPartitionSize bool   `json:",omitempty"`
568	CopyImagesForTargetFilesZip    bool   `json:",omitempty"`
569
570	BoardAvbEnable bool `json:",omitempty"`
571
572	ProductPackages []string `json:",omitempty"`
573}
574
575func boolPtr(v bool) *bool {
576	return &v
577}
578
579func intPtr(v int) *int {
580	return &v
581}
582
583func stringPtr(v string) *string {
584	return &v
585}
586
587func (v *ProductVariables) SetDefaultConfig() {
588	*v = ProductVariables{
589		BuildNumberFile: stringPtr("build_number.txt"),
590
591		Platform_version_name:                  stringPtr("S"),
592		Platform_base_sdk_extension_version:    intPtr(30),
593		Platform_sdk_version:                   intPtr(30),
594		Platform_sdk_codename:                  stringPtr("S"),
595		Platform_sdk_final:                     boolPtr(false),
596		Platform_version_active_codenames:      []string{"S"},
597		Platform_version_all_preview_codenames: []string{"S"},
598
599		HostArch:                    stringPtr("x86_64"),
600		HostSecondaryArch:           stringPtr("x86"),
601		DeviceName:                  stringPtr("generic_arm64"),
602		DeviceProduct:               stringPtr("aosp_arm-eng"),
603		DeviceArch:                  stringPtr("arm64"),
604		DeviceArchVariant:           stringPtr("armv8-a"),
605		DeviceCpuVariant:            stringPtr("generic"),
606		DeviceAbi:                   []string{"arm64-v8a"},
607		DeviceSecondaryArch:         stringPtr("arm"),
608		DeviceSecondaryArchVariant:  stringPtr("armv8-a"),
609		DeviceSecondaryCpuVariant:   stringPtr("generic"),
610		DeviceSecondaryAbi:          []string{"armeabi-v7a", "armeabi"},
611		DeviceMaxPageSizeSupported:  stringPtr("4096"),
612		DeviceNoBionicPageSizeMacro: boolPtr(false),
613
614		AAPTConfig:          []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
615		AAPTPreferredConfig: stringPtr("xhdpi"),
616		AAPTCharacteristics: stringPtr("nosdcard"),
617		AAPTPrebuiltDPI:     []string{"xhdpi", "xxhdpi"},
618
619		Malloc_low_memory:            boolPtr(false),
620		Malloc_zero_contents:         boolPtr(true),
621		Malloc_pattern_fill_contents: boolPtr(false),
622		Safestack:                    boolPtr(false),
623		TrimmedApex:                  boolPtr(false),
624		Build_from_text_stub:         boolPtr(false),
625
626		BootJars:     ConfiguredJarList{apexes: []string{}, jars: []string{}},
627		ApexBootJars: ConfiguredJarList{apexes: []string{}, jars: []string{}},
628	}
629
630	if runtime.GOOS == "linux" {
631		v.CrossHost = stringPtr("windows")
632		v.CrossHostArch = stringPtr("x86")
633		v.CrossHostSecondaryArch = stringPtr("x86_64")
634	}
635}
636
637func (this *ProductVariables) GetBuildFlagBool(flag string) bool {
638	val, ok := this.BuildFlags[flag]
639	if !ok {
640		return false
641	}
642	return val == "true"
643}
644
645func VariableMutator(mctx BottomUpMutatorContext) {
646	var module Module
647	var ok bool
648	if module, ok = mctx.Module().(Module); !ok {
649		return
650	}
651
652	// TODO: depend on config variable, create variants, propagate variants up tree
653	a := module.base()
654
655	if a.variableProperties == nil {
656		return
657	}
658
659	variableValues := reflect.ValueOf(a.variableProperties).Elem().FieldByName("Product_variables")
660
661	productVariables := reflect.ValueOf(mctx.Config().productVariables)
662
663	for i := 0; i < variableValues.NumField(); i++ {
664		variableValue := variableValues.Field(i)
665		name := variableValues.Type().Field(i).Name
666		property := "product_variables." + proptools.PropertyNameForField(name)
667
668		// Check that the variable was set for the product
669		val := productVariables.FieldByName(name)
670		if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
671			continue
672		}
673
674		val = val.Elem()
675
676		// For bools, check that the value is true
677		if val.Kind() == reflect.Bool && val.Bool() == false {
678			continue
679		}
680
681		// Check if any properties were set for the module
682		if variableValue.IsZero() {
683			continue
684		}
685		a.setVariableProperties(mctx, property, variableValue, val.Interface())
686	}
687}
688
689func (m *ModuleBase) setVariableProperties(ctx BottomUpMutatorContext,
690	prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
691
692	printfIntoProperties(ctx, prefix, productVariablePropertyValue, variableValue)
693
694	err := proptools.AppendMatchingProperties(m.GetProperties(),
695		productVariablePropertyValue.Addr().Interface(), nil)
696	if err != nil {
697		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
698			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
699		} else {
700			panic(err)
701		}
702	}
703}
704
705func printfIntoPropertiesError(ctx BottomUpMutatorContext, prefix string,
706	productVariablePropertyValue reflect.Value, i int, err error) {
707
708	field := productVariablePropertyValue.Type().Field(i).Name
709	property := prefix + "." + proptools.PropertyNameForField(field)
710	ctx.PropertyErrorf(property, "%s", err)
711}
712
713func printfIntoProperties(ctx BottomUpMutatorContext, prefix string,
714	productVariablePropertyValue reflect.Value, variableValue interface{}) {
715
716	for i := 0; i < productVariablePropertyValue.NumField(); i++ {
717		propertyValue := productVariablePropertyValue.Field(i)
718		kind := propertyValue.Kind()
719		if kind == reflect.Ptr {
720			if propertyValue.IsNil() {
721				continue
722			}
723			propertyValue = propertyValue.Elem()
724		}
725		switch propertyValue.Kind() {
726		case reflect.String:
727			err := printfIntoProperty(propertyValue, variableValue)
728			if err != nil {
729				printfIntoPropertiesError(ctx, prefix, productVariablePropertyValue, i, err)
730			}
731		case reflect.Slice:
732			for j := 0; j < propertyValue.Len(); j++ {
733				err := printfIntoProperty(propertyValue.Index(j), variableValue)
734				if err != nil {
735					printfIntoPropertiesError(ctx, prefix, productVariablePropertyValue, i, err)
736				}
737			}
738		case reflect.Bool:
739			// Nothing
740		case reflect.Struct:
741			printfIntoProperties(ctx, prefix, propertyValue, variableValue)
742		default:
743			panic(fmt.Errorf("unsupported field kind %q", propertyValue.Kind()))
744		}
745	}
746}
747
748func printfIntoProperty(propertyValue reflect.Value, variableValue interface{}) error {
749	s := propertyValue.String()
750
751	count := strings.Count(s, "%")
752	if count == 0 {
753		return nil
754	}
755
756	if count > 1 {
757		return fmt.Errorf("product variable properties only support a single '%%'")
758	}
759
760	if strings.Contains(s, "%d") {
761		switch v := variableValue.(type) {
762		case int:
763			// Nothing
764		case bool:
765			if v {
766				variableValue = 1
767			} else {
768				variableValue = 0
769			}
770		default:
771			return fmt.Errorf("unsupported type %T for %%d", variableValue)
772		}
773	} else if strings.Contains(s, "%s") {
774		switch variableValue.(type) {
775		case string:
776			// Nothing
777		default:
778			return fmt.Errorf("unsupported type %T for %%s", variableValue)
779		}
780	} else {
781		return fmt.Errorf("unsupported %% in product variable property")
782	}
783
784	propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, variableValue)))
785
786	return nil
787}
788
789var variablePropTypeMap OncePer
790
791// sliceToTypeArray takes a slice of property structs and returns a reflection created array containing the
792// reflect.Types of each property struct.  The result can be used as a key in a map.
793func sliceToTypeArray(s []interface{}) interface{} {
794	// Create an array using reflection whose length is the length of the input slice
795	ret := reflect.New(reflect.ArrayOf(len(s), reflect.TypeOf(reflect.TypeOf(0)))).Elem()
796	for i, e := range s {
797		ret.Index(i).Set(reflect.ValueOf(reflect.TypeOf(e)))
798	}
799	return ret.Interface()
800}
801
802func initProductVariableModule(m Module) {
803	base := m.base()
804
805	// Allow tests to override the default product variables
806	if base.variableProperties == nil {
807		base.variableProperties = defaultProductVariables
808	}
809	// Filter the product variables properties to the ones that exist on this module
810	base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
811	if base.variableProperties != nil {
812		m.AddProperties(base.variableProperties)
813	}
814}
815
816// createVariableProperties takes the list of property structs for a module and returns a property struct that
817// contains the product variable properties that exist in the property structs, or nil if there are none.  It
818// caches the result.
819func createVariableProperties(moduleTypeProps []interface{}, productVariables interface{}) interface{} {
820	// Convert the moduleTypeProps to an array of reflect.Types that can be used as a key in the OncePer.
821	key := sliceToTypeArray(moduleTypeProps)
822
823	// Use the variablePropTypeMap OncePer to cache the result for each set of property struct types.
824	typ, _ := variablePropTypeMap.Once(NewCustomOnceKey(key), func() interface{} {
825		// Compute the filtered property struct type.
826		return createVariablePropertiesType(moduleTypeProps, productVariables)
827	}).(reflect.Type)
828
829	if typ == nil {
830		return nil
831	}
832
833	// Create a new pointer to a filtered property struct.
834	return reflect.New(typ).Interface()
835}
836
837// createVariablePropertiesType creates a new type that contains only the product variable properties that exist in
838// a list of property structs.
839func createVariablePropertiesType(moduleTypeProps []interface{}, productVariables interface{}) reflect.Type {
840	typ, _ := proptools.FilterPropertyStruct(reflect.TypeOf(productVariables),
841		func(field reflect.StructField, prefix string) (bool, reflect.StructField) {
842			// Filter function, returns true if the field should be in the resulting struct
843			if prefix == "" {
844				// Keep the top level Product_variables field
845				return true, field
846			}
847			_, rest := splitPrefix(prefix)
848			if rest == "" {
849				// Keep the 2nd level field (i.e. Product_variables.Eng)
850				return true, field
851			}
852
853			// Strip off the first 2 levels of the prefix
854			_, prefix = splitPrefix(rest)
855
856			for _, p := range moduleTypeProps {
857				if fieldExistsByNameRecursive(reflect.TypeOf(p).Elem(), prefix, field.Name) {
858					// Keep any fields that exist in one of the property structs
859					return true, field
860				}
861			}
862
863			return false, field
864		})
865	return typ
866}
867
868func splitPrefix(prefix string) (first, rest string) {
869	index := strings.IndexByte(prefix, '.')
870	if index == -1 {
871		return prefix, ""
872	}
873	return prefix[:index], prefix[index+1:]
874}
875
876func fieldExistsByNameRecursive(t reflect.Type, prefix, name string) bool {
877	if t.Kind() != reflect.Struct {
878		panic(fmt.Errorf("fieldExistsByNameRecursive can only be called on a reflect.Struct"))
879	}
880
881	if prefix != "" {
882		split := strings.SplitN(prefix, ".", 2)
883		firstPrefix := split[0]
884		rest := ""
885		if len(split) > 1 {
886			rest = split[1]
887		}
888		f, exists := t.FieldByName(firstPrefix)
889		if !exists {
890			return false
891		}
892		ft := f.Type
893		if ft.Kind() == reflect.Ptr {
894			ft = ft.Elem()
895		}
896		if ft.Kind() != reflect.Struct {
897			panic(fmt.Errorf("field %q in %q is not a struct", firstPrefix, t))
898		}
899		return fieldExistsByNameRecursive(ft, rest, name)
900	} else {
901		_, exists := t.FieldByName(name)
902		return exists
903	}
904}
905