blob: f8231f07361b47c0c1ee5a2ed7e3d018be3c09dd [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
Dan Willemsene7680ba2015-09-11 17:06:19 -070051 envLock sync.Mutex
52 envDeps map[string]string
53 envFrozen bool
Colin Cross3f40fa42015-01-30 17:27:36 -080054}
55
Colin Cross485e5722015-08-27 13:28:01 -070056type jsonConfigurable interface {
57 DefaultConfig() jsonConfigurable
58}
Colin Cross3f40fa42015-01-30 17:27:36 -080059
Colin Cross485e5722015-08-27 13:28:01 -070060func loadConfig(config *config) error {
61 err := loadFromConfigFile(&config.FileConfigurableOptions, ConfigFileName)
62 if err != nil {
63 return err
64 }
65
66 return loadFromConfigFile(&config.ProductVariables, ProductVariablesFileName)
67}
68
69// loads configuration options from a JSON file in the cwd.
70func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080071 // Try to open the file
Colin Cross485e5722015-08-27 13:28:01 -070072 configFileReader, err := os.Open(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080073 defer configFileReader.Close()
74 if os.IsNotExist(err) {
75 // Need to create a file, so that blueprint & ninja don't get in
76 // a dependency tracking loop.
77 // Make a file-configurable-options with defaults, write it out using
78 // a json writer.
Colin Cross485e5722015-08-27 13:28:01 -070079 err = saveToConfigFile(configurable.DefaultConfig(), filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080080 if err != nil {
81 return err
82 }
83 } else {
84 // Make a decoder for it
85 jsonDecoder := json.NewDecoder(configFileReader)
Colin Cross485e5722015-08-27 13:28:01 -070086 err = jsonDecoder.Decode(configurable)
Colin Cross3f40fa42015-01-30 17:27:36 -080087 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -070088 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080089 }
90 }
91
Colin Cross3f40fa42015-01-30 17:27:36 -080092 // No error
93 return nil
94}
95
Colin Cross485e5722015-08-27 13:28:01 -070096func saveToConfigFile(config jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080097 data, err := json.MarshalIndent(&config, "", " ")
98 if err != nil {
99 return fmt.Errorf("cannot marshal config data: %s", err.Error())
100 }
101
Colin Cross485e5722015-08-27 13:28:01 -0700102 configFileWriter, err := os.Create(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -0800103 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700104 return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800105 }
106 defer configFileWriter.Close()
107
108 _, err = configFileWriter.Write(data)
109 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700110 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
111 }
112
113 _, err = configFileWriter.WriteString("\n")
114 if err != nil {
115 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800116 }
117
118 return nil
119}
120
121// New creates a new Config object. The srcDir argument specifies the path to
122// the root source directory. It also loads the config file, if found.
Colin Cross1332b002015-04-07 17:11:30 -0700123func NewConfig(srcDir string) (Config, error) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800124 // Make a config with default options
Colin Crossc3c0a492015-04-10 15:43:55 -0700125 config := Config{
126 config: &config{
127 srcDir: srcDir,
128 envDeps: make(map[string]string),
129 },
Colin Cross68f55102015-03-25 14:43:57 -0700130 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800131
132 // Load any configurable options from the configuration file
Colin Cross485e5722015-08-27 13:28:01 -0700133 err := loadConfig(config.config)
Colin Cross3f40fa42015-01-30 17:27:36 -0800134 if err != nil {
Colin Crossc3c0a492015-04-10 15:43:55 -0700135 return Config{}, err
Colin Cross3f40fa42015-01-30 17:27:36 -0800136 }
137
138 return config, nil
139}
140
Colin Cross1332b002015-04-07 17:11:30 -0700141func (c *config) SrcDir() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800142 return c.srcDir
143}
144
Colin Cross1332b002015-04-07 17:11:30 -0700145func (c *config) IntermediatesDir() string {
Colin Cross581c1892015-04-07 16:50:10 -0700146 return ".intermediates"
147}
148
Colin Cross3f40fa42015-01-30 17:27:36 -0800149// PrebuiltOS returns the name of the host OS used in prebuilts directories
Colin Cross1332b002015-04-07 17:11:30 -0700150func (c *config) PrebuiltOS() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800151 switch runtime.GOOS {
152 case "linux":
153 return "linux-x86"
154 case "darwin":
155 return "darwin-x86"
156 default:
157 panic("Unknown GOOS")
158 }
159}
160
161// GoRoot returns the path to the root directory of the Go toolchain.
Colin Cross1332b002015-04-07 17:11:30 -0700162func (c *config) GoRoot() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800163 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
164}
165
Colin Cross1332b002015-04-07 17:11:30 -0700166func (c *config) CpPreserveSymlinksFlags() string {
Colin Cross485e5722015-08-27 13:28:01 -0700167 switch runtime.GOOS {
Colin Cross3f40fa42015-01-30 17:27:36 -0800168 case "darwin":
169 return "-R"
170 case "linux":
171 return "-d"
172 default:
173 return ""
174 }
175}
Colin Cross68f55102015-03-25 14:43:57 -0700176
Colin Cross1332b002015-04-07 17:11:30 -0700177func (c *config) Getenv(key string) string {
Colin Cross68f55102015-03-25 14:43:57 -0700178 var val string
179 var exists bool
Colin Crossc1e86a32015-04-15 12:33:28 -0700180 c.envLock.Lock()
Colin Cross68f55102015-03-25 14:43:57 -0700181 if val, exists = c.envDeps[key]; !exists {
Dan Willemsene7680ba2015-09-11 17:06:19 -0700182 if c.envFrozen {
183 panic("Cannot access new environment variables after envdeps are frozen")
184 }
Colin Cross68f55102015-03-25 14:43:57 -0700185 val = os.Getenv(key)
186 c.envDeps[key] = val
187 }
Colin Crossc1e86a32015-04-15 12:33:28 -0700188 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700189 return val
190}
191
Colin Cross1332b002015-04-07 17:11:30 -0700192func (c *config) EnvDeps() map[string]string {
Dan Willemsene7680ba2015-09-11 17:06:19 -0700193 c.envLock.Lock()
194 c.envFrozen = true
195 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700196 return c.envDeps
197}
Colin Cross35cec122015-04-02 14:37:16 -0700198
199// DeviceName returns the name of the current device target
200// TODO: take an AndroidModuleContext to select the device name for multi-device builds
Colin Cross1332b002015-04-07 17:11:30 -0700201func (c *config) DeviceName() string {
Colin Cross35cec122015-04-02 14:37:16 -0700202 return "unset"
203}
204
205// DeviceOut returns the path to out directory for device targets
Colin Cross1332b002015-04-07 17:11:30 -0700206func (c *config) DeviceOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700207 return filepath.Join("target/product", c.DeviceName())
208}
209
210// HostOut returns the path to out directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700211func (c *config) HostOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700212 return filepath.Join("host", c.PrebuiltOS())
213}
214
215// HostBin returns the path to bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700216func (c *config) HostBin() string {
Colin Cross35cec122015-04-02 14:37:16 -0700217 return filepath.Join(c.HostOut(), "bin")
218}
219
220// HostBinTool returns the path to a host tool in the bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700221func (c *config) HostBinTool(tool string) (string, error) {
Colin Cross35cec122015-04-02 14:37:16 -0700222 return filepath.Join(c.HostBin(), tool), nil
223}
Colin Cross65bf4f22015-04-03 16:54:17 -0700224
225// HostJavaDir returns the path to framework directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700226func (c *config) HostJavaDir() string {
Colin Cross65bf4f22015-04-03 16:54:17 -0700227 return filepath.Join(c.HostOut(), "framework")
228}
229
230// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700231func (c *config) HostJavaTool(tool string) (string, error) {
Colin Cross65bf4f22015-04-03 16:54:17 -0700232 return filepath.Join(c.HostJavaDir(), tool), nil
233}
Colin Cross30e076a2015-04-13 13:58:27 -0700234
235func (c *config) ResourceOverlays() []string {
236 return nil
237}
238
239func (c *config) PlatformVersion() string {
240 return "M"
241}
242
243func (c *config) PlatformSdkVersion() string {
244 return "22"
245}
246
247func (c *config) BuildNumber() string {
248 return "000000"
249}
250
251func (c *config) ProductAaptConfig() []string {
252 return []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}
253}
254
255func (c *config) ProductAaptPreferredConfig() string {
256 return "xhdpi"
257}
258
259func (c *config) ProductAaptCharacteristics() string {
260 return "nosdcard"
261}
262
263func (c *config) DefaultAppCertificateDir() string {
264 return filepath.Join(c.SrcDir(), "build/target/product/security")
265}
266
267func (c *config) DefaultAppCertificate() string {
268 return filepath.Join(c.DefaultAppCertificateDir(), "testkey")
269}