Read product variables from soong.variables

Refactor the soong.config loading code to support reading in
product variables from soong.variables.

Change-Id: I389e6bb5c501b53167267d5f5d0d25557811cf72
This commit is contained in:
Colin Cross 2015-08-27 13:28:01 -07:00
parent 7f64b6de31
commit 485e572aeb
4 changed files with 53 additions and 36 deletions

View file

@ -173,7 +173,7 @@ var targetToHostModuleRule = map[string]string{
"BUILD_JAVA_LIBRARY": "BUILD_HOST_JAVA_LIBRARY", "BUILD_JAVA_LIBRARY": "BUILD_HOST_JAVA_LIBRARY",
} }
var productVariableConditionals = map[string]struct{conditional, value string}{ var productVariableConditionals = map[string]struct{ conditional, value string }{
"device_uses_jemalloc": {"ifneq ($(MALLOC_IMPL),dlmalloc)", ""}, "device_uses_jemalloc": {"ifneq ($(MALLOC_IMPL),dlmalloc)", ""},
"device_uses_dlmalloc": {"ifeq ($(MALLOC_IMPL),dlmalloc)", ""}, "device_uses_dlmalloc": {"ifeq ($(MALLOC_IMPL),dlmalloc)", ""},
"device_uses_logd": {"ifneq ($(TARGET_USES_LOGD),false)", ""}, "device_uses_logd": {"ifneq ($(TARGET_USES_LOGD),false)", ""},

View file

@ -49,5 +49,5 @@ func main() {
// Temporary hack // Temporary hack
//ctx.SetIgnoreUnknownModuleTypes(true) //ctx.SetIgnoreUnknownModuleTypes(true)
bootstrap.Main(ctx, configuration, common.ConfigFileName) bootstrap.Main(ctx, configuration, common.ConfigFileName, common.ProductVariablesFileName)
} }

View file

@ -25,13 +25,14 @@ import (
// The configuration file name // The configuration file name
const ConfigFileName = "soong.config" const ConfigFileName = "soong.config"
const ProductVariablesFileName = "soong.variables"
// A FileConfigurableOptions contains options which can be configured by the // A FileConfigurableOptions contains options which can be configured by the
// config file. These will be included in the config struct. // config file. These will be included in the config struct.
type FileConfigurableOptions struct { type FileConfigurableOptions struct {
} }
func NewFileConfigurableOptions() FileConfigurableOptions { func (FileConfigurableOptions) DefaultConfig() jsonConfigurable {
f := FileConfigurableOptions{} f := FileConfigurableOptions{}
return f return f
} }
@ -43,6 +44,7 @@ type Config struct {
// A config object represents the entire build configuration for Blue. // A config object represents the entire build configuration for Blue.
type config struct { type config struct {
FileConfigurableOptions FileConfigurableOptions
ProductVariables productVariables
srcDir string // the path of the root source directory srcDir string // the path of the root source directory
@ -50,56 +52,66 @@ type config struct {
envDeps map[string]string envDeps map[string]string
} }
// loads configuration options from a JSON file in the cwd. type jsonConfigurable interface {
func loadFromConfigFile(config *config) error { DefaultConfig() jsonConfigurable
// Make a proxy config }
var configProxy FileConfigurableOptions
func loadConfig(config *config) error {
err := loadFromConfigFile(&config.FileConfigurableOptions, ConfigFileName)
if err != nil {
return err
}
return loadFromConfigFile(&config.ProductVariables, ProductVariablesFileName)
}
// loads configuration options from a JSON file in the cwd.
func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
// Try to open the file // Try to open the file
configFileReader, err := os.Open(ConfigFileName) configFileReader, err := os.Open(filename)
defer configFileReader.Close() defer configFileReader.Close()
if os.IsNotExist(err) { if os.IsNotExist(err) {
// Need to create a file, so that blueprint & ninja don't get in // Need to create a file, so that blueprint & ninja don't get in
// a dependency tracking loop. // a dependency tracking loop.
// Make a file-configurable-options with defaults, write it out using // Make a file-configurable-options with defaults, write it out using
// a json writer. // a json writer.
configProxy = NewFileConfigurableOptions() err = saveToConfigFile(configurable.DefaultConfig(), filename)
err = saveToConfigFile(configProxy)
if err != nil { if err != nil {
return err return err
} }
} else { } else {
// Make a decoder for it // Make a decoder for it
jsonDecoder := json.NewDecoder(configFileReader) jsonDecoder := json.NewDecoder(configFileReader)
err = jsonDecoder.Decode(&configProxy) err = jsonDecoder.Decode(configurable)
if err != nil { if err != nil {
return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), ConfigFileName) return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), filename)
} }
} }
// Copy the configurable options out of the config_proxy into the config,
// and we're done!
config.FileConfigurableOptions = configProxy
// No error // No error
return nil return nil
} }
func saveToConfigFile(config FileConfigurableOptions) error { func saveToConfigFile(config jsonConfigurable, filename string) error {
data, err := json.MarshalIndent(&config, "", " ") data, err := json.MarshalIndent(&config, "", " ")
if err != nil { if err != nil {
return fmt.Errorf("cannot marshal config data: %s", err.Error()) return fmt.Errorf("cannot marshal config data: %s", err.Error())
} }
configFileWriter, err := os.Create(ConfigFileName) configFileWriter, err := os.Create(filename)
if err != nil { if err != nil {
return fmt.Errorf("cannot create empty config file %s: %s\n", ConfigFileName, err.Error()) return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
} }
defer configFileWriter.Close() defer configFileWriter.Close()
_, err = configFileWriter.Write(data) _, err = configFileWriter.Write(data)
if err != nil { if err != nil {
return fmt.Errorf("default config file: %s could not be written: %s", ConfigFileName, err.Error()) return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
}
_, err = configFileWriter.WriteString("\n")
if err != nil {
return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
} }
return nil return nil
@ -117,7 +129,7 @@ func NewConfig(srcDir string) (Config, error) {
} }
// Load any configurable options from the configuration file // Load any configurable options from the configuration file
err := loadFromConfigFile(config.config) err := loadConfig(config.config)
if err != nil { if err != nil {
return Config{}, err return Config{}, err
} }
@ -133,11 +145,6 @@ func (c *config) IntermediatesDir() string {
return ".intermediates" return ".intermediates"
} }
// HostGoOS returns the OS of the system that the Go toolchain is being run on.
func (c *config) HostGoOS() string {
return runtime.GOOS
}
// PrebuiltOS returns the name of the host OS used in prebuilts directories // PrebuiltOS returns the name of the host OS used in prebuilts directories
func (c *config) PrebuiltOS() string { func (c *config) PrebuiltOS() string {
switch runtime.GOOS { switch runtime.GOOS {
@ -156,7 +163,7 @@ func (c *config) GoRoot() string {
} }
func (c *config) CpPreserveSymlinksFlags() string { func (c *config) CpPreserveSymlinksFlags() string {
switch c.HostGoOS() { switch runtime.GOOS {
case "darwin": case "darwin":
return "-R" return "-R"
case "linux": case "linux":

View file

@ -53,10 +53,19 @@ type variableProperties struct {
var zeroProductVariables variableProperties var zeroProductVariables variableProperties
// TODO: replace hardcoded test values with per-product values type productVariables struct {
var productVariables = map[string]interface{}{ Device_uses_logd bool
"device_uses_logd": true, Device_uses_jemalloc bool
"device_uses_jemalloc": true, Device_uses_dlmalloc bool
Dlmalloc_alignment int
}
func (productVariables) DefaultConfig() jsonConfigurable {
v := productVariables{
Device_uses_logd: true,
Device_uses_jemalloc: true,
}
return v
} }
func VariableMutator(mctx blueprint.EarlyMutatorContext) { func VariableMutator(mctx blueprint.EarlyMutatorContext) {
@ -78,12 +87,13 @@ func VariableMutator(mctx blueprint.EarlyMutatorContext) {
continue continue
} }
name := proptools.PropertyNameForField(variableValues.Type().Field(i).Name) name := variableValues.Type().Field(i).Name
property := "product_variables." + name property := "product_variables." + proptools.PropertyNameForField(name)
val := productVariables[name]
if mctx.ContainsProperty(property) && val != nil { val := reflect.ValueOf(mctx.Config().(Config).ProductVariables).FieldByName(name)
a.setVariableProperties(mctx, property, variableValue, val)
if mctx.ContainsProperty(property) && val.IsValid() {
a.setVariableProperties(mctx, property, variableValue, val.Interface())
} }
} }
} }