• 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	PreDepsMutators(func(ctx RegisterMutatorsContext) {
28		ctx.BottomUp("variable", variableMutator).Parallel()
29	})
30}
31
32type variableProperties struct {
33	Product_variables struct {
34		Platform_sdk_version struct {
35			Asflags []string
36			Cflags  []string
37		}
38
39		// unbundled_build is a catch-all property to annotate modules that don't build in one or
40		// more unbundled branches, usually due to dependencies missing from the manifest.
41		Unbundled_build struct {
42			Enabled *bool `android:"arch_variant"`
43		} `android:"arch_variant"`
44
45		Malloc_not_svelte struct {
46			Cflags      []string `android:"arch_variant"`
47			Shared_libs []string `android:"arch_variant"`
48		} `android:"arch_variant"`
49
50		Safestack struct {
51			Cflags []string `android:"arch_variant"`
52		} `android:"arch_variant"`
53
54		Binder32bit struct {
55			Cflags []string
56		}
57
58		Override_rs_driver struct {
59			Cflags []string
60		}
61
62		// Product_is_iot is true for Android Things devices.
63		Product_is_iot struct {
64			Cflags       []string
65			Enabled      bool
66			Exclude_srcs []string
67			Init_rc      []string
68			Shared_libs  []string
69			Srcs         []string
70			Static_libs  []string
71		}
72
73		// treble_linker_namespaces is true when the system/vendor linker namespace separation is
74		// enabled.
75		Treble_linker_namespaces struct {
76			Cflags []string
77		}
78		// enforce_vintf_manifest is true when a device is required to have a vintf manifest.
79		Enforce_vintf_manifest struct {
80			Cflags []string
81		}
82
83		// debuggable is true for eng and userdebug builds, and can be used to turn on additional
84		// debugging features that don't significantly impact runtime behavior.  userdebug builds
85		// are used for dogfooding and performance testing, and should be as similar to user builds
86		// as possible.
87		Debuggable struct {
88			Cflags   []string
89			Cppflags []string
90			Init_rc  []string
91			Required []string
92		}
93
94		// eng is true for -eng builds, and can be used to turn on additionaly heavyweight debugging
95		// features.
96		Eng struct {
97			Cflags   []string
98			Cppflags []string
99			Lto      struct {
100				Never *bool
101			}
102			Sanitize struct {
103				Address *bool
104			}
105		}
106
107		Pdk struct {
108			Enabled *bool `android:"arch_variant"`
109		} `android:"arch_variant"`
110
111		Uml struct {
112			Cppflags []string
113		}
114
115		Use_lmkd_stats_log struct {
116			Cflags []string
117		}
118
119		Arc struct {
120			Cflags       []string
121			Exclude_srcs []string
122			Include_dirs []string
123			Shared_libs  []string
124			Static_libs  []string
125			Srcs         []string
126		}
127	} `android:"arch_variant"`
128}
129
130var zeroProductVariables variableProperties
131
132type productVariables struct {
133	// Suffix to add to generated Makefiles
134	Make_suffix *string `json:",omitempty"`
135
136	BuildId             *string `json:",omitempty"`
137	BuildNumberFromFile *string `json:",omitempty"`
138	DateFromFile        *string `json:",omitempty"`
139
140	Platform_version_name                     *string  `json:",omitempty"`
141	Platform_sdk_version                      *int     `json:",omitempty"`
142	Platform_sdk_codename                     *string  `json:",omitempty"`
143	Platform_sdk_final                        *bool    `json:",omitempty"`
144	Platform_version_active_codenames         []string `json:",omitempty"`
145	Platform_version_future_codenames         []string `json:",omitempty"`
146	Platform_vndk_version                     *string  `json:",omitempty"`
147	Platform_systemsdk_versions               []string `json:",omitempty"`
148	Platform_security_patch                   *string  `json:",omitempty"`
149	Platform_preview_sdk_version              *string  `json:",omitempty"`
150	Platform_min_supported_target_sdk_version *string  `json:",omitempty"`
151	Platform_base_os                          *string  `json:",omitempty"`
152
153	DeviceName              *string  `json:",omitempty"`
154	DeviceArch              *string  `json:",omitempty"`
155	DeviceArchVariant       *string  `json:",omitempty"`
156	DeviceCpuVariant        *string  `json:",omitempty"`
157	DeviceAbi               []string `json:",omitempty"`
158	DeviceVndkVersion       *string  `json:",omitempty"`
159	DeviceSystemSdkVersions []string `json:",omitempty"`
160
161	DeviceSecondaryArch        *string  `json:",omitempty"`
162	DeviceSecondaryArchVariant *string  `json:",omitempty"`
163	DeviceSecondaryCpuVariant  *string  `json:",omitempty"`
164	DeviceSecondaryAbi         []string `json:",omitempty"`
165
166	HostArch          *string `json:",omitempty"`
167	HostSecondaryArch *string `json:",omitempty"`
168
169	CrossHost              *string `json:",omitempty"`
170	CrossHostArch          *string `json:",omitempty"`
171	CrossHostSecondaryArch *string `json:",omitempty"`
172
173	DeviceResourceOverlays     []string `json:",omitempty"`
174	ProductResourceOverlays    []string `json:",omitempty"`
175	EnforceRROTargets          []string `json:",omitempty"`
176	EnforceRROExcludedOverlays []string `json:",omitempty"`
177
178	AAPTCharacteristics *string  `json:",omitempty"`
179	AAPTConfig          []string `json:",omitempty"`
180	AAPTPreferredConfig *string  `json:",omitempty"`
181	AAPTPrebuiltDPI     []string `json:",omitempty"`
182
183	DefaultAppCertificate *string `json:",omitempty"`
184
185	AppsDefaultVersionName *string `json:",omitempty"`
186
187	Allow_missing_dependencies       *bool `json:",omitempty"`
188	Unbundled_build                  *bool `json:",omitempty"`
189	Unbundled_build_sdks_from_source *bool `json:",omitempty"`
190	Malloc_not_svelte                *bool `json:",omitempty"`
191	Safestack                        *bool `json:",omitempty"`
192	HostStaticBinaries               *bool `json:",omitempty"`
193	Binder32bit                      *bool `json:",omitempty"`
194	UseGoma                          *bool `json:",omitempty"`
195	Debuggable                       *bool `json:",omitempty"`
196	Eng                              *bool `json:",omitempty"`
197	Treble_linker_namespaces         *bool `json:",omitempty"`
198	Enforce_vintf_manifest           *bool `json:",omitempty"`
199	Pdk                              *bool `json:",omitempty"`
200	Uml                              *bool `json:",omitempty"`
201	Use_lmkd_stats_log               *bool `json:",omitempty"`
202	Arc                              *bool `json:",omitempty"`
203	MinimizeJavaDebugInfo            *bool `json:",omitempty"`
204
205	Check_elf_files *bool `json:",omitempty"`
206
207	UncompressPrivAppDex             *bool    `json:",omitempty"`
208	ModulesLoadedByPrivilegedModules []string `json:",omitempty"`
209
210	BootJars []string `json:",omitempty"`
211
212	IntegerOverflowExcludePaths []string `json:",omitempty"`
213
214	EnableCFI       *bool    `json:",omitempty"`
215	CFIExcludePaths []string `json:",omitempty"`
216	CFIIncludePaths []string `json:",omitempty"`
217
218	DisableScudo *bool `json:",omitempty"`
219
220	EnableXOM       *bool    `json:",omitempty"`
221	XOMExcludePaths []string `json:",omitempty"`
222
223	VendorPath          *string `json:",omitempty"`
224	OdmPath             *string `json:",omitempty"`
225	ProductPath         *string `json:",omitempty"`
226	ProductServicesPath *string `json:",omitempty"`
227
228	ClangTidy  *bool   `json:",omitempty"`
229	TidyChecks *string `json:",omitempty"`
230
231	NativeCoverage       *bool    `json:",omitempty"`
232	CoveragePaths        []string `json:",omitempty"`
233	CoverageExcludePaths []string `json:",omitempty"`
234
235	DevicePrefer32BitApps        *bool `json:",omitempty"`
236	DevicePrefer32BitExecutables *bool `json:",omitempty"`
237	HostPrefer32BitExecutables   *bool `json:",omitempty"`
238
239	SanitizeHost       []string `json:",omitempty"`
240	SanitizeDevice     []string `json:",omitempty"`
241	SanitizeDeviceDiag []string `json:",omitempty"`
242	SanitizeDeviceArch []string `json:",omitempty"`
243
244	ArtUseReadBarrier *bool `json:",omitempty"`
245
246	BtConfigIncludeDir *string `json:",omitempty"`
247
248	Override_rs_driver *string `json:",omitempty"`
249
250	Product_is_iot *bool `json:",omitempty"`
251
252	Fuchsia *bool `json:",omitempty"`
253
254	DeviceKernelHeaders []string `json:",omitempty"`
255
256	ExtraVndkVersions []string `json:",omitempty"`
257
258	NamespacesToExport []string `json:",omitempty"`
259
260	PgoAdditionalProfileDirs []string `json:",omitempty"`
261
262	VndkUseCoreVariant *bool `json:",omitempty"`
263
264	BoardVendorSepolicyDirs      []string `json:",omitempty"`
265	BoardOdmSepolicyDirs         []string `json:",omitempty"`
266	BoardPlatPublicSepolicyDirs  []string `json:",omitempty"`
267	BoardPlatPrivateSepolicyDirs []string `json:",omitempty"`
268
269	VendorVars map[string]map[string]string `json:",omitempty"`
270
271	Ndk_abis               *bool `json:",omitempty"`
272	Exclude_draft_ndk_apis *bool `json:",omitempty"`
273
274	FlattenApex *bool `json:",omitempty"`
275
276	DexpreoptGlobalConfig *string `json:",omitempty"`
277
278	ManifestPackageNameOverrides []string `json:",omitempty"`
279	CertificateOverrides         []string `json:",omitempty"`
280	PackageNameOverrides         []string `json:",omitempty"`
281
282	EnforceSystemCertificate          *bool    `json:",omitempty"`
283	EnforceSystemCertificateWhitelist []string `json:",omitempty"`
284
285	ProductHiddenAPIStubs       []string `json:",omitempty"`
286	ProductHiddenAPIStubsSystem []string `json:",omitempty"`
287	ProductHiddenAPIStubsTest   []string `json:",omitempty"`
288
289	TargetFSConfigGen []string `json:",omitempty"`
290}
291
292func boolPtr(v bool) *bool {
293	return &v
294}
295
296func intPtr(v int) *int {
297	return &v
298}
299
300func stringPtr(v string) *string {
301	return &v
302}
303
304func (v *productVariables) SetDefaultConfig() {
305	*v = productVariables{
306		Platform_sdk_version:              intPtr(26),
307		Platform_version_active_codenames: []string{"P"},
308		Platform_version_future_codenames: []string{"P"},
309
310		HostArch:                   stringPtr("x86_64"),
311		HostSecondaryArch:          stringPtr("x86"),
312		DeviceName:                 stringPtr("generic_arm64"),
313		DeviceArch:                 stringPtr("arm64"),
314		DeviceArchVariant:          stringPtr("armv8-a"),
315		DeviceCpuVariant:           stringPtr("generic"),
316		DeviceAbi:                  []string{"arm64-v8a"},
317		DeviceSecondaryArch:        stringPtr("arm"),
318		DeviceSecondaryArchVariant: stringPtr("armv8-a"),
319		DeviceSecondaryCpuVariant:  stringPtr("generic"),
320		DeviceSecondaryAbi:         []string{"armeabi-v7a", "armeabi"},
321
322		AAPTConfig:          []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
323		AAPTPreferredConfig: stringPtr("xhdpi"),
324		AAPTCharacteristics: stringPtr("nosdcard"),
325		AAPTPrebuiltDPI:     []string{"xhdpi", "xxhdpi"},
326
327		Malloc_not_svelte: boolPtr(true),
328		Safestack:         boolPtr(false),
329	}
330
331	if runtime.GOOS == "linux" {
332		v.CrossHost = stringPtr("windows")
333		v.CrossHostArch = stringPtr("x86")
334		v.CrossHostSecondaryArch = stringPtr("x86_64")
335	}
336}
337
338func variableMutator(mctx BottomUpMutatorContext) {
339	var module Module
340	var ok bool
341	if module, ok = mctx.Module().(Module); !ok {
342		return
343	}
344
345	// TODO: depend on config variable, create variants, propagate variants up tree
346	a := module.base()
347	variableValues := reflect.ValueOf(&a.variableProperties.Product_variables).Elem()
348	zeroValues := reflect.ValueOf(zeroProductVariables.Product_variables)
349
350	for i := 0; i < variableValues.NumField(); i++ {
351		variableValue := variableValues.Field(i)
352		zeroValue := zeroValues.Field(i)
353		name := variableValues.Type().Field(i).Name
354		property := "product_variables." + proptools.PropertyNameForField(name)
355
356		// Check that the variable was set for the product
357		val := reflect.ValueOf(mctx.Config().productVariables).FieldByName(name)
358		if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
359			continue
360		}
361
362		val = val.Elem()
363
364		// For bools, check that the value is true
365		if val.Kind() == reflect.Bool && val.Bool() == false {
366			continue
367		}
368
369		// Check if any properties were set for the module
370		if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
371			continue
372		}
373
374		a.setVariableProperties(mctx, property, variableValue, val.Interface())
375	}
376}
377
378func (a *ModuleBase) setVariableProperties(ctx BottomUpMutatorContext,
379	prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
380
381	printfIntoProperties(ctx, prefix, productVariablePropertyValue, variableValue)
382
383	err := proptools.AppendMatchingProperties(a.generalProperties,
384		productVariablePropertyValue.Addr().Interface(), nil)
385	if err != nil {
386		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
387			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
388		} else {
389			panic(err)
390		}
391	}
392}
393
394func printfIntoPropertiesError(ctx BottomUpMutatorContext, prefix string,
395	productVariablePropertyValue reflect.Value, i int, err error) {
396
397	field := productVariablePropertyValue.Type().Field(i).Name
398	property := prefix + "." + proptools.PropertyNameForField(field)
399	ctx.PropertyErrorf(property, "%s", err)
400}
401
402func printfIntoProperties(ctx BottomUpMutatorContext, prefix string,
403	productVariablePropertyValue reflect.Value, variableValue interface{}) {
404
405	for i := 0; i < productVariablePropertyValue.NumField(); i++ {
406		propertyValue := productVariablePropertyValue.Field(i)
407		kind := propertyValue.Kind()
408		if kind == reflect.Ptr {
409			if propertyValue.IsNil() {
410				continue
411			}
412			propertyValue = propertyValue.Elem()
413		}
414		switch propertyValue.Kind() {
415		case reflect.String:
416			err := printfIntoProperty(propertyValue, variableValue)
417			if err != nil {
418				printfIntoPropertiesError(ctx, prefix, productVariablePropertyValue, i, err)
419			}
420		case reflect.Slice:
421			for j := 0; j < propertyValue.Len(); j++ {
422				err := printfIntoProperty(propertyValue.Index(j), variableValue)
423				if err != nil {
424					printfIntoPropertiesError(ctx, prefix, productVariablePropertyValue, i, err)
425				}
426			}
427		case reflect.Bool:
428			// Nothing
429		case reflect.Struct:
430			printfIntoProperties(ctx, prefix, propertyValue, variableValue)
431		default:
432			panic(fmt.Errorf("unsupported field kind %q", propertyValue.Kind()))
433		}
434	}
435}
436
437func printfIntoProperty(propertyValue reflect.Value, variableValue interface{}) error {
438	s := propertyValue.String()
439
440	count := strings.Count(s, "%")
441	if count == 0 {
442		return nil
443	}
444
445	if count > 1 {
446		return fmt.Errorf("product variable properties only support a single '%%'")
447	}
448
449	if strings.Contains(s, "%d") {
450		switch v := variableValue.(type) {
451		case int:
452			// Nothing
453		case bool:
454			if v {
455				variableValue = 1
456			} else {
457				variableValue = 0
458			}
459		default:
460			return fmt.Errorf("unsupported type %T for %%d", variableValue)
461		}
462	} else if strings.Contains(s, "%s") {
463		switch variableValue.(type) {
464		case string:
465			// Nothing
466		default:
467			return fmt.Errorf("unsupported type %T for %%s", variableValue)
468		}
469	} else {
470		return fmt.Errorf("unsupported %% in product variable property")
471	}
472
473	propertyValue.Set(reflect.ValueOf(fmt.Sprintf(s, variableValue)))
474
475	return nil
476}
477