Home | History | Annotate | Download | only in android
      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 
     15 package android
     16 
     17 import (
     18 	"fmt"
     19 	"reflect"
     20 	"runtime"
     21 	"strings"
     22 
     23 	"github.com/google/blueprint/proptools"
     24 )
     25 
     26 func init() {
     27 	PreDepsMutators(func(ctx RegisterMutatorsContext) {
     28 		ctx.BottomUp("variable", variableMutator).Parallel()
     29 	})
     30 }
     31 
     32 type 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 
    130 var zeroProductVariables variableProperties
    131 
    132 type 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 
    292 func boolPtr(v bool) *bool {
    293 	return &v
    294 }
    295 
    296 func intPtr(v int) *int {
    297 	return &v
    298 }
    299 
    300 func stringPtr(v string) *string {
    301 	return &v
    302 }
    303 
    304 func (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 
    338 func 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 
    378 func (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 
    394 func 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 
    402 func 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 
    437 func 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