blob: 348d0dbb7d2a75b65550b5045780c957e5f33864 [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
Colin Cross1332b002015-04-07 17:11:30 -070015package common
Colin Cross3f40fa42015-01-30 17:27:36 -080016
17import (
Colin Cross3f40fa42015-01-30 17:27:36 -080018 "encoding/json"
19 "fmt"
20 "os"
Colin Cross35cec122015-04-02 14:37:16 -070021 "path/filepath"
Colin Cross3f40fa42015-01-30 17:27:36 -080022 "runtime"
Colin Crossc1e86a32015-04-15 12:33:28 -070023 "sync"
Colin Cross3f40fa42015-01-30 17:27:36 -080024)
25
Colin Cross3f40fa42015-01-30 17:27:36 -080026// The configuration file name
27const ConfigFileName = "soong.config"
Colin Cross485e5722015-08-27 13:28:01 -070028const ProductVariablesFileName = "soong.variables"
Colin Cross3f40fa42015-01-30 17:27:36 -080029
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
Colin Cross485e5722015-08-27 13:28:01 -070035func (FileConfigurableOptions) DefaultConfig() jsonConfigurable {
Colin Cross3f40fa42015-01-30 17:27:36 -080036 f := FileConfigurableOptions{}
37 return f
38}
39
Colin Crossc3c0a492015-04-10 15:43:55 -070040type Config struct {
41 *config
42}
43
44// A config object represents the entire build configuration for Blue.
Colin Cross1332b002015-04-07 17:11:30 -070045type config struct {
Colin Cross3f40fa42015-01-30 17:27:36 -080046 FileConfigurableOptions
Colin Cross485e5722015-08-27 13:28:01 -070047 ProductVariables productVariables
Colin Cross3f40fa42015-01-30 17:27:36 -080048
Colin Cross30e076a2015-04-13 13:58:27 -070049 srcDir string // the path of the root source directory
Colin Crossc1e86a32015-04-15 12:33:28 -070050
51 envLock sync.Mutex
Colin Cross68f55102015-03-25 14:43:57 -070052 envDeps map[string]string
Colin Cross3f40fa42015-01-30 17:27:36 -080053}
54
Colin Cross485e5722015-08-27 13:28:01 -070055type jsonConfigurable interface {
56 DefaultConfig() jsonConfigurable
57}
Colin Cross3f40fa42015-01-30 17:27:36 -080058
Colin Cross485e5722015-08-27 13:28:01 -070059func loadConfig(config *config) error {
60 err := loadFromConfigFile(&config.FileConfigurableOptions, ConfigFileName)
61 if err != nil {
62 return err
63 }
64
65 return loadFromConfigFile(&config.ProductVariables, ProductVariablesFileName)
66}
67
68// loads configuration options from a JSON file in the cwd.
69func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080070 // Try to open the file
Colin Cross485e5722015-08-27 13:28:01 -070071 configFileReader, err := os.Open(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080072 defer configFileReader.Close()
73 if os.IsNotExist(err) {
74 // Need to create a file, so that blueprint & ninja don't get in
75 // a dependency tracking loop.
76 // Make a file-configurable-options with defaults, write it out using
77 // a json writer.
Colin Cross485e5722015-08-27 13:28:01 -070078 err = saveToConfigFile(configurable.DefaultConfig(), filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080079 if err != nil {
80 return err
81 }
82 } else {
83 // Make a decoder for it
84 jsonDecoder := json.NewDecoder(configFileReader)
Colin Cross485e5722015-08-27 13:28:01 -070085 err = jsonDecoder.Decode(configurable)
Colin Cross3f40fa42015-01-30 17:27:36 -080086 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -070087 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080088 }
89 }
90
Colin Cross3f40fa42015-01-30 17:27:36 -080091 // No error
92 return nil
93}
94
Colin Cross485e5722015-08-27 13:28:01 -070095func saveToConfigFile(config jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080096 data, err := json.MarshalIndent(&config, "", " ")
97 if err != nil {
98 return fmt.Errorf("cannot marshal config data: %s", err.Error())
99 }
100
Colin Cross485e5722015-08-27 13:28:01 -0700101 configFileWriter, err := os.Create(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -0800102 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700103 return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800104 }
105 defer configFileWriter.Close()
106
107 _, err = configFileWriter.Write(data)
108 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700109 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
110 }
111
112 _, err = configFileWriter.WriteString("\n")
113 if err != nil {
114 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800115 }
116
117 return nil
118}
119
120// New creates a new Config object. The srcDir argument specifies the path to
121// the root source directory. It also loads the config file, if found.
Colin Cross1332b002015-04-07 17:11:30 -0700122func NewConfig(srcDir string) (Config, error) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800123 // Make a config with default options
Colin Crossc3c0a492015-04-10 15:43:55 -0700124 config := Config{
125 config: &config{
126 srcDir: srcDir,
127 envDeps: make(map[string]string),
128 },
Colin Cross68f55102015-03-25 14:43:57 -0700129 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800130
131 // Load any configurable options from the configuration file
Colin Cross485e5722015-08-27 13:28:01 -0700132 err := loadConfig(config.config)
Colin Cross3f40fa42015-01-30 17:27:36 -0800133 if err != nil {
Colin Crossc3c0a492015-04-10 15:43:55 -0700134 return Config{}, err
Colin Cross3f40fa42015-01-30 17:27:36 -0800135 }
136
137 return config, nil
138}
139
Colin Cross1332b002015-04-07 17:11:30 -0700140func (c *config) SrcDir() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800141 return c.srcDir
142}
143
Colin Cross1332b002015-04-07 17:11:30 -0700144func (c *config) IntermediatesDir() string {
Colin Cross581c1892015-04-07 16:50:10 -0700145 return ".intermediates"
146}
147
Colin Cross3f40fa42015-01-30 17:27:36 -0800148// PrebuiltOS returns the name of the host OS used in prebuilts directories
Colin Cross1332b002015-04-07 17:11:30 -0700149func (c *config) PrebuiltOS() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800150 switch runtime.GOOS {
151 case "linux":
152 return "linux-x86"
153 case "darwin":
154 return "darwin-x86"
155 default:
156 panic("Unknown GOOS")
157 }
158}
159
160// GoRoot returns the path to the root directory of the Go toolchain.
Colin Cross1332b002015-04-07 17:11:30 -0700161func (c *config) GoRoot() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800162 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
163}
164
Colin Cross1332b002015-04-07 17:11:30 -0700165func (c *config) CpPreserveSymlinksFlags() string {
Colin Cross485e5722015-08-27 13:28:01 -0700166 switch runtime.GOOS {
Colin Cross3f40fa42015-01-30 17:27:36 -0800167 case "darwin":
168 return "-R"
169 case "linux":
170 return "-d"
171 default:
172 return ""
173 }
174}
Colin Cross68f55102015-03-25 14:43:57 -0700175
Colin Cross1332b002015-04-07 17:11:30 -0700176func (c *config) Getenv(key string) string {
Colin Cross68f55102015-03-25 14:43:57 -0700177 var val string
178 var exists bool
Colin Crossc1e86a32015-04-15 12:33:28 -0700179 c.envLock.Lock()
Colin Cross68f55102015-03-25 14:43:57 -0700180 if val, exists = c.envDeps[key]; !exists {
181 val = os.Getenv(key)
182 c.envDeps[key] = val
183 }
Colin Crossc1e86a32015-04-15 12:33:28 -0700184 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700185 return val
186}
187
Colin Cross1332b002015-04-07 17:11:30 -0700188func (c *config) EnvDeps() map[string]string {
Colin Cross68f55102015-03-25 14:43:57 -0700189 return c.envDeps
190}
Colin Cross35cec122015-04-02 14:37:16 -0700191
192// DeviceName returns the name of the current device target
193// TODO: take an AndroidModuleContext to select the device name for multi-device builds
Colin Cross1332b002015-04-07 17:11:30 -0700194func (c *config) DeviceName() string {
Colin Cross35cec122015-04-02 14:37:16 -0700195 return "unset"
196}
197
198// DeviceOut returns the path to out directory for device targets
Colin Cross1332b002015-04-07 17:11:30 -0700199func (c *config) DeviceOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700200 return filepath.Join("target/product", c.DeviceName())
201}
202
203// HostOut returns the path to out directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700204func (c *config) HostOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700205 return filepath.Join("host", c.PrebuiltOS())
206}
207
208// HostBin returns the path to bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700209func (c *config) HostBin() string {
Colin Cross35cec122015-04-02 14:37:16 -0700210 return filepath.Join(c.HostOut(), "bin")
211}
212
213// HostBinTool returns the path to a host tool in the bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700214func (c *config) HostBinTool(tool string) (string, error) {
Colin Cross35cec122015-04-02 14:37:16 -0700215 return filepath.Join(c.HostBin(), tool), nil
216}
Colin Cross65bf4f22015-04-03 16:54:17 -0700217
218// HostJavaDir returns the path to framework directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700219func (c *config) HostJavaDir() string {
Colin Cross65bf4f22015-04-03 16:54:17 -0700220 return filepath.Join(c.HostOut(), "framework")
221}
222
223// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700224func (c *config) HostJavaTool(tool string) (string, error) {
Colin Cross65bf4f22015-04-03 16:54:17 -0700225 return filepath.Join(c.HostJavaDir(), tool), nil
226}
Colin Cross30e076a2015-04-13 13:58:27 -0700227
228func (c *config) ResourceOverlays() []string {
229 return nil
230}
231
232func (c *config) PlatformVersion() string {
233 return "M"
234}
235
236func (c *config) PlatformSdkVersion() string {
237 return "22"
238}
239
240func (c *config) BuildNumber() string {
241 return "000000"
242}
243
244func (c *config) ProductAaptConfig() []string {
245 return []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}
246}
247
248func (c *config) ProductAaptPreferredConfig() string {
249 return "xhdpi"
250}
251
252func (c *config) ProductAaptCharacteristics() string {
253 return "nosdcard"
254}
255
256func (c *config) DefaultAppCertificateDir() string {
257 return filepath.Join(c.SrcDir(), "build/target/product/security")
258}
259
260func (c *config) DefaultAppCertificate() string {
261 return filepath.Join(c.DefaultAppCertificateDir(), "testkey")
262}