blob: 1cd75d300760083a5f7f3b9f50d886013af9e12b [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
Dan Willemsen87b17d12015-07-14 00:39:06 -070027const configFileName = "soong.config"
28const 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 Cross27385972015-09-18 10:57:10 -070035func (f *FileConfigurableOptions) SetDefaultConfig() {
36 *f = FileConfigurableOptions{}
Colin Cross3f40fa42015-01-30 17:27:36 -080037}
38
Colin Crossc3c0a492015-04-10 15:43:55 -070039type Config struct {
40 *config
41}
42
43// A config object represents the entire build configuration for Blue.
Colin Cross1332b002015-04-07 17:11:30 -070044type config struct {
Colin Cross3f40fa42015-01-30 17:27:36 -080045 FileConfigurableOptions
Colin Cross485e5722015-08-27 13:28:01 -070046 ProductVariables productVariables
Colin Cross3f40fa42015-01-30 17:27:36 -080047
Dan Willemsen87b17d12015-07-14 00:39:06 -070048 ConfigFileName string
49 ProductVariablesFileName string
50
51 srcDir string // the path of the root source directory
52 buildDir string // the path of the build output directory
Colin Crossc1e86a32015-04-15 12:33:28 -070053
Dan Willemsene7680ba2015-09-11 17:06:19 -070054 envLock sync.Mutex
55 envDeps map[string]string
56 envFrozen bool
Colin Cross3f40fa42015-01-30 17:27:36 -080057}
58
Colin Cross485e5722015-08-27 13:28:01 -070059type jsonConfigurable interface {
Colin Cross27385972015-09-18 10:57:10 -070060 SetDefaultConfig()
Colin Cross485e5722015-08-27 13:28:01 -070061}
Colin Cross3f40fa42015-01-30 17:27:36 -080062
Colin Cross485e5722015-08-27 13:28:01 -070063func loadConfig(config *config) error {
Dan Willemsen87b17d12015-07-14 00:39:06 -070064 err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName)
Colin Cross485e5722015-08-27 13:28:01 -070065 if err != nil {
66 return err
67 }
68
Dan Willemsen87b17d12015-07-14 00:39:06 -070069 return loadFromConfigFile(&config.ProductVariables, config.ProductVariablesFileName)
Colin Cross485e5722015-08-27 13:28:01 -070070}
71
72// loads configuration options from a JSON file in the cwd.
73func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080074 // Try to open the file
Colin Cross485e5722015-08-27 13:28:01 -070075 configFileReader, err := os.Open(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080076 defer configFileReader.Close()
77 if os.IsNotExist(err) {
78 // Need to create a file, so that blueprint & ninja don't get in
79 // a dependency tracking loop.
80 // Make a file-configurable-options with defaults, write it out using
81 // a json writer.
Colin Cross27385972015-09-18 10:57:10 -070082 configurable.SetDefaultConfig()
83 err = saveToConfigFile(configurable, filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080084 if err != nil {
85 return err
86 }
87 } else {
88 // Make a decoder for it
89 jsonDecoder := json.NewDecoder(configFileReader)
Colin Cross485e5722015-08-27 13:28:01 -070090 err = jsonDecoder.Decode(configurable)
Colin Cross3f40fa42015-01-30 17:27:36 -080091 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -070092 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), filename)
Colin Cross3f40fa42015-01-30 17:27:36 -080093 }
94 }
95
Colin Cross3f40fa42015-01-30 17:27:36 -080096 // No error
97 return nil
98}
99
Colin Cross485e5722015-08-27 13:28:01 -0700100func saveToConfigFile(config jsonConfigurable, filename string) error {
Colin Cross3f40fa42015-01-30 17:27:36 -0800101 data, err := json.MarshalIndent(&config, "", " ")
102 if err != nil {
103 return fmt.Errorf("cannot marshal config data: %s", err.Error())
104 }
105
Colin Cross485e5722015-08-27 13:28:01 -0700106 configFileWriter, err := os.Create(filename)
Colin Cross3f40fa42015-01-30 17:27:36 -0800107 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700108 return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800109 }
110 defer configFileWriter.Close()
111
112 _, err = configFileWriter.Write(data)
113 if err != nil {
Colin Cross485e5722015-08-27 13:28:01 -0700114 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
115 }
116
117 _, err = configFileWriter.WriteString("\n")
118 if err != nil {
119 return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
Colin Cross3f40fa42015-01-30 17:27:36 -0800120 }
121
122 return nil
123}
124
125// New creates a new Config object. The srcDir argument specifies the path to
126// the root source directory. It also loads the config file, if found.
Dan Willemsen87b17d12015-07-14 00:39:06 -0700127func NewConfig(srcDir, buildDir string) (Config, error) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800128 // Make a config with default options
Colin Crossc3c0a492015-04-10 15:43:55 -0700129 config := Config{
130 config: &config{
Dan Willemsen87b17d12015-07-14 00:39:06 -0700131 ConfigFileName: filepath.Join(buildDir, configFileName),
132 ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
133
134 srcDir: srcDir,
135 buildDir: buildDir,
136 envDeps: make(map[string]string),
Colin Crossc3c0a492015-04-10 15:43:55 -0700137 },
Colin Cross68f55102015-03-25 14:43:57 -0700138 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800139
140 // Load any configurable options from the configuration file
Colin Cross485e5722015-08-27 13:28:01 -0700141 err := loadConfig(config.config)
Colin Cross3f40fa42015-01-30 17:27:36 -0800142 if err != nil {
Colin Crossc3c0a492015-04-10 15:43:55 -0700143 return Config{}, err
Colin Cross3f40fa42015-01-30 17:27:36 -0800144 }
145
146 return config, nil
147}
148
Colin Cross1332b002015-04-07 17:11:30 -0700149func (c *config) SrcDir() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800150 return c.srcDir
151}
152
Dan Willemsen87b17d12015-07-14 00:39:06 -0700153func (c *config) BuildDir() string {
154 return c.buildDir
155}
156
Colin Cross1332b002015-04-07 17:11:30 -0700157func (c *config) IntermediatesDir() string {
Dan Willemsen87b17d12015-07-14 00:39:06 -0700158 return filepath.Join(c.BuildDir(), ".intermediates")
Colin Cross581c1892015-04-07 16:50:10 -0700159}
160
Colin Cross3f40fa42015-01-30 17:27:36 -0800161// PrebuiltOS returns the name of the host OS used in prebuilts directories
Colin Cross1332b002015-04-07 17:11:30 -0700162func (c *config) PrebuiltOS() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800163 switch runtime.GOOS {
164 case "linux":
165 return "linux-x86"
166 case "darwin":
167 return "darwin-x86"
168 default:
169 panic("Unknown GOOS")
170 }
171}
172
173// GoRoot returns the path to the root directory of the Go toolchain.
Colin Cross1332b002015-04-07 17:11:30 -0700174func (c *config) GoRoot() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800175 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
176}
177
Colin Cross1332b002015-04-07 17:11:30 -0700178func (c *config) CpPreserveSymlinksFlags() string {
Colin Cross485e5722015-08-27 13:28:01 -0700179 switch runtime.GOOS {
Colin Cross3f40fa42015-01-30 17:27:36 -0800180 case "darwin":
181 return "-R"
182 case "linux":
183 return "-d"
184 default:
185 return ""
186 }
187}
Colin Cross68f55102015-03-25 14:43:57 -0700188
Colin Cross1332b002015-04-07 17:11:30 -0700189func (c *config) Getenv(key string) string {
Colin Cross68f55102015-03-25 14:43:57 -0700190 var val string
191 var exists bool
Colin Crossc1e86a32015-04-15 12:33:28 -0700192 c.envLock.Lock()
Colin Cross68f55102015-03-25 14:43:57 -0700193 if val, exists = c.envDeps[key]; !exists {
Dan Willemsene7680ba2015-09-11 17:06:19 -0700194 if c.envFrozen {
195 panic("Cannot access new environment variables after envdeps are frozen")
196 }
Colin Cross68f55102015-03-25 14:43:57 -0700197 val = os.Getenv(key)
198 c.envDeps[key] = val
199 }
Colin Crossc1e86a32015-04-15 12:33:28 -0700200 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700201 return val
202}
203
Colin Cross1332b002015-04-07 17:11:30 -0700204func (c *config) EnvDeps() map[string]string {
Dan Willemsene7680ba2015-09-11 17:06:19 -0700205 c.envLock.Lock()
206 c.envFrozen = true
207 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700208 return c.envDeps
209}
Colin Cross35cec122015-04-02 14:37:16 -0700210
211// DeviceName returns the name of the current device target
212// TODO: take an AndroidModuleContext to select the device name for multi-device builds
Colin Cross1332b002015-04-07 17:11:30 -0700213func (c *config) DeviceName() string {
Colin Cross35cec122015-04-02 14:37:16 -0700214 return "unset"
215}
216
217// DeviceOut returns the path to out directory for device targets
Colin Cross1332b002015-04-07 17:11:30 -0700218func (c *config) DeviceOut() string {
Dan Willemsen87b17d12015-07-14 00:39:06 -0700219 return filepath.Join(c.BuildDir(), "target/product", c.DeviceName())
Colin Cross35cec122015-04-02 14:37:16 -0700220}
221
222// HostOut returns the path to out directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700223func (c *config) HostOut() string {
Dan Willemsen87b17d12015-07-14 00:39:06 -0700224 return filepath.Join(c.BuildDir(), "host", c.PrebuiltOS())
Colin Cross35cec122015-04-02 14:37:16 -0700225}
226
227// HostBin returns the path to bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700228func (c *config) HostBin() string {
Colin Cross35cec122015-04-02 14:37:16 -0700229 return filepath.Join(c.HostOut(), "bin")
230}
231
232// HostBinTool returns the path to a host tool in the bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700233func (c *config) HostBinTool(tool string) (string, error) {
Colin Cross35cec122015-04-02 14:37:16 -0700234 return filepath.Join(c.HostBin(), tool), nil
235}
Colin Cross65bf4f22015-04-03 16:54:17 -0700236
237// HostJavaDir returns the path to framework directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700238func (c *config) HostJavaDir() string {
Colin Cross65bf4f22015-04-03 16:54:17 -0700239 return filepath.Join(c.HostOut(), "framework")
240}
241
242// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700243func (c *config) HostJavaTool(tool string) (string, error) {
Colin Cross65bf4f22015-04-03 16:54:17 -0700244 return filepath.Join(c.HostJavaDir(), tool), nil
245}
Colin Cross30e076a2015-04-13 13:58:27 -0700246
247func (c *config) ResourceOverlays() []string {
248 return nil
249}
250
251func (c *config) PlatformVersion() string {
252 return "M"
253}
254
255func (c *config) PlatformSdkVersion() string {
256 return "22"
257}
258
259func (c *config) BuildNumber() string {
260 return "000000"
261}
262
263func (c *config) ProductAaptConfig() []string {
264 return []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}
265}
266
267func (c *config) ProductAaptPreferredConfig() string {
268 return "xhdpi"
269}
270
271func (c *config) ProductAaptCharacteristics() string {
272 return "nosdcard"
273}
274
275func (c *config) DefaultAppCertificateDir() string {
276 return filepath.Join(c.SrcDir(), "build/target/product/security")
277}
278
279func (c *config) DefaultAppCertificate() string {
280 return filepath.Join(c.DefaultAppCertificateDir(), "testkey")
281}