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",
}
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_dlmalloc": {"ifeq ($(MALLOC_IMPL),dlmalloc)", ""},
"device_uses_logd": {"ifneq ($(TARGET_USES_LOGD),false)", ""},

View file

@ -49,5 +49,5 @@ func main() {
// Temporary hack
//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
const ConfigFileName = "soong.config"
const ProductVariablesFileName = "soong.variables"
// A FileConfigurableOptions contains options which can be configured by the
// config file. These will be included in the config struct.
type FileConfigurableOptions struct {
}
func NewFileConfigurableOptions() FileConfigurableOptions {
func (FileConfigurableOptions) DefaultConfig() jsonConfigurable {
f := FileConfigurableOptions{}
return f
}
@ -43,6 +44,7 @@ type Config struct {
// A config object represents the entire build configuration for Blue.
type config struct {
FileConfigurableOptions
ProductVariables productVariables
srcDir string // the path of the root source directory
@ -50,56 +52,66 @@ type config struct {
envDeps map[string]string
}
// loads configuration options from a JSON file in the cwd.
func loadFromConfigFile(config *config) error {
// Make a proxy config
var configProxy FileConfigurableOptions
type jsonConfigurable interface {
DefaultConfig() jsonConfigurable
}
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
configFileReader, err := os.Open(ConfigFileName)
configFileReader, err := os.Open(filename)
defer configFileReader.Close()
if os.IsNotExist(err) {
// Need to create a file, so that blueprint & ninja don't get in
// a dependency tracking loop.
// Make a file-configurable-options with defaults, write it out using
// a json writer.
configProxy = NewFileConfigurableOptions()
err = saveToConfigFile(configProxy)
err = saveToConfigFile(configurable.DefaultConfig(), filename)
if err != nil {
return err
}
} else {
// Make a decoder for it
jsonDecoder := json.NewDecoder(configFileReader)
err = jsonDecoder.Decode(&configProxy)
err = jsonDecoder.Decode(configurable)
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
return nil
}
func saveToConfigFile(config FileConfigurableOptions) error {
func saveToConfigFile(config jsonConfigurable, filename string) error {
data, err := json.MarshalIndent(&config, "", " ")
if err != nil {
return fmt.Errorf("cannot marshal config data: %s", err.Error())
}
configFileWriter, err := os.Create(ConfigFileName)
configFileWriter, err := os.Create(filename)
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()
_, err = configFileWriter.Write(data)
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
@ -117,7 +129,7 @@ func NewConfig(srcDir string) (Config, error) {
}
// Load any configurable options from the configuration file
err := loadFromConfigFile(config.config)
err := loadConfig(config.config)
if err != nil {
return Config{}, err
}
@ -133,11 +145,6 @@ func (c *config) IntermediatesDir() string {
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
func (c *config) PrebuiltOS() string {
switch runtime.GOOS {
@ -156,7 +163,7 @@ func (c *config) GoRoot() string {
}
func (c *config) CpPreserveSymlinksFlags() string {
switch c.HostGoOS() {
switch runtime.GOOS {
case "darwin":
return "-R"
case "linux":

View file

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