github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/android/variable.go (about)

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