blob: 6cb61e4beea6a861f176d4a3211fef1221da4a7c [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// 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 config
16
17import (
18 "android/soong/common"
19 "encoding/json"
20 "fmt"
21 "os"
22 "runtime"
23)
24
25var _ common.Config = (*Config)(nil)
26
27// The configuration file name
28const ConfigFileName = "soong.config"
29
30// A FileConfigurableOptions contains options which can be configured by the
31// config file. These will be included in the config struct.
32type FileConfigurableOptions struct {
33}
34
35func NewFileConfigurableOptions() FileConfigurableOptions {
36 f := FileConfigurableOptions{}
37 return f
38}
39
40// A Config object represents the entire build configuration for Blue.
41type Config struct {
42 FileConfigurableOptions
43
Colin Cross68f55102015-03-25 14:43:57 -070044 srcDir string // the path of the root source directory
45 envDeps map[string]string
Colin Cross3f40fa42015-01-30 17:27:36 -080046}
47
48// loads configuration options from a JSON file in the cwd.
49func loadFromConfigFile(config *Config) error {
50 // Make a proxy config
51 var configProxy FileConfigurableOptions
52
53 // Try to open the file
54 configFileReader, err := os.Open(ConfigFileName)
55 defer configFileReader.Close()
56 if os.IsNotExist(err) {
57 // Need to create a file, so that blueprint & ninja don't get in
58 // a dependency tracking loop.
59 // Make a file-configurable-options with defaults, write it out using
60 // a json writer.
61 configProxy = NewFileConfigurableOptions()
62 err = saveToConfigFile(configProxy)
63 if err != nil {
64 return err
65 }
66 } else {
67 // Make a decoder for it
68 jsonDecoder := json.NewDecoder(configFileReader)
69 err = jsonDecoder.Decode(&configProxy)
70 if err != nil {
71 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), ConfigFileName)
72 }
73 }
74
75 // Copy the configurable options out of the config_proxy into the config,
76 // and we're done!
77 config.FileConfigurableOptions = configProxy
78
79 // No error
80 return nil
81}
82
83func saveToConfigFile(config FileConfigurableOptions) error {
84 data, err := json.MarshalIndent(&config, "", " ")
85 if err != nil {
86 return fmt.Errorf("cannot marshal config data: %s", err.Error())
87 }
88
89 configFileWriter, err := os.Create(ConfigFileName)
90 if err != nil {
91 return fmt.Errorf("cannot create empty config file %s: %s\n", ConfigFileName, err.Error())
92 }
93 defer configFileWriter.Close()
94
95 _, err = configFileWriter.Write(data)
96 if err != nil {
97 return fmt.Errorf("default config file: %s could not be written: %s", ConfigFileName, err.Error())
98 }
99
100 return nil
101}
102
103// New creates a new Config object. The srcDir argument specifies the path to
104// the root source directory. It also loads the config file, if found.
105func New(srcDir string) (*Config, error) {
106 // Make a config with default options
Colin Cross68f55102015-03-25 14:43:57 -0700107 config := &Config{
108 srcDir: srcDir,
109 envDeps: make(map[string]string),
110 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800111
112 // Load any configurable options from the configuration file
113 err := loadFromConfigFile(config)
114 if err != nil {
115 return nil, err
116 }
117
118 return config, nil
119}
120
121func (c *Config) SrcDir() string {
122 return c.srcDir
123}
124
125// HostGoOS returns the OS of the system that the Go toolchain is being run on.
126func (c *Config) HostGoOS() string {
127 return runtime.GOOS
128}
129
130// PrebuiltOS returns the name of the host OS used in prebuilts directories
131func (c *Config) PrebuiltOS() string {
132 switch runtime.GOOS {
133 case "linux":
134 return "linux-x86"
135 case "darwin":
136 return "darwin-x86"
137 default:
138 panic("Unknown GOOS")
139 }
140}
141
142// GoRoot returns the path to the root directory of the Go toolchain.
143func (c *Config) GoRoot() string {
144 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
145}
146
147func (c *Config) CpPreserveSymlinksFlags() string {
148 switch c.HostGoOS() {
149 case "darwin":
150 return "-R"
151 case "linux":
152 return "-d"
153 default:
154 return ""
155 }
156}
Colin Cross68f55102015-03-25 14:43:57 -0700157
158func (c *Config) Getenv(key string) string {
159 var val string
160 var exists bool
161 if val, exists = c.envDeps[key]; !exists {
162 val = os.Getenv(key)
163 c.envDeps[key] = val
164 }
165 return val
166}
167
168func (c *Config) EnvDeps() map[string]string {
169 return c.envDeps
170}