blob: 5d761e66c4418226bde583d2f7b481d01d2e850d [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"
28
29// A FileConfigurableOptions contains options which can be configured by the
30// config file. These will be included in the config struct.
31type FileConfigurableOptions struct {
32}
33
34func NewFileConfigurableOptions() FileConfigurableOptions {
35 f := FileConfigurableOptions{}
36 return f
37}
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
46
Colin Cross68f55102015-03-25 14:43:57 -070047 srcDir string // the path of the root source directory
Colin Crossc1e86a32015-04-15 12:33:28 -070048
49 envLock sync.Mutex
Colin Cross68f55102015-03-25 14:43:57 -070050 envDeps map[string]string
Colin Cross3f40fa42015-01-30 17:27:36 -080051}
52
53// loads configuration options from a JSON file in the cwd.
Colin Cross1332b002015-04-07 17:11:30 -070054func loadFromConfigFile(config *config) error {
Colin Cross3f40fa42015-01-30 17:27:36 -080055 // Make a proxy config
56 var configProxy FileConfigurableOptions
57
58 // Try to open the file
59 configFileReader, err := os.Open(ConfigFileName)
60 defer configFileReader.Close()
61 if os.IsNotExist(err) {
62 // Need to create a file, so that blueprint & ninja don't get in
63 // a dependency tracking loop.
64 // Make a file-configurable-options with defaults, write it out using
65 // a json writer.
66 configProxy = NewFileConfigurableOptions()
67 err = saveToConfigFile(configProxy)
68 if err != nil {
69 return err
70 }
71 } else {
72 // Make a decoder for it
73 jsonDecoder := json.NewDecoder(configFileReader)
74 err = jsonDecoder.Decode(&configProxy)
75 if err != nil {
76 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), ConfigFileName)
77 }
78 }
79
80 // Copy the configurable options out of the config_proxy into the config,
81 // and we're done!
82 config.FileConfigurableOptions = configProxy
83
84 // No error
85 return nil
86}
87
88func saveToConfigFile(config FileConfigurableOptions) error {
89 data, err := json.MarshalIndent(&config, "", " ")
90 if err != nil {
91 return fmt.Errorf("cannot marshal config data: %s", err.Error())
92 }
93
94 configFileWriter, err := os.Create(ConfigFileName)
95 if err != nil {
96 return fmt.Errorf("cannot create empty config file %s: %s\n", ConfigFileName, err.Error())
97 }
98 defer configFileWriter.Close()
99
100 _, err = configFileWriter.Write(data)
101 if err != nil {
102 return fmt.Errorf("default config file: %s could not be written: %s", ConfigFileName, err.Error())
103 }
104
105 return nil
106}
107
108// New creates a new Config object. The srcDir argument specifies the path to
109// the root source directory. It also loads the config file, if found.
Colin Cross1332b002015-04-07 17:11:30 -0700110func NewConfig(srcDir string) (Config, error) {
Colin Cross3f40fa42015-01-30 17:27:36 -0800111 // Make a config with default options
Colin Crossc3c0a492015-04-10 15:43:55 -0700112 config := Config{
113 config: &config{
114 srcDir: srcDir,
115 envDeps: make(map[string]string),
116 },
Colin Cross68f55102015-03-25 14:43:57 -0700117 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800118
119 // Load any configurable options from the configuration file
Colin Crossc3c0a492015-04-10 15:43:55 -0700120 err := loadFromConfigFile(config.config)
Colin Cross3f40fa42015-01-30 17:27:36 -0800121 if err != nil {
Colin Crossc3c0a492015-04-10 15:43:55 -0700122 return Config{}, err
Colin Cross3f40fa42015-01-30 17:27:36 -0800123 }
124
125 return config, nil
126}
127
Colin Cross1332b002015-04-07 17:11:30 -0700128func (c *config) SrcDir() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800129 return c.srcDir
130}
131
Colin Cross1332b002015-04-07 17:11:30 -0700132func (c *config) IntermediatesDir() string {
Colin Cross581c1892015-04-07 16:50:10 -0700133 return ".intermediates"
134}
135
Colin Cross3f40fa42015-01-30 17:27:36 -0800136// HostGoOS returns the OS of the system that the Go toolchain is being run on.
Colin Cross1332b002015-04-07 17:11:30 -0700137func (c *config) HostGoOS() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800138 return runtime.GOOS
139}
140
141// PrebuiltOS returns the name of the host OS used in prebuilts directories
Colin Cross1332b002015-04-07 17:11:30 -0700142func (c *config) PrebuiltOS() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800143 switch runtime.GOOS {
144 case "linux":
145 return "linux-x86"
146 case "darwin":
147 return "darwin-x86"
148 default:
149 panic("Unknown GOOS")
150 }
151}
152
153// GoRoot returns the path to the root directory of the Go toolchain.
Colin Cross1332b002015-04-07 17:11:30 -0700154func (c *config) GoRoot() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800155 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
156}
157
Colin Cross1332b002015-04-07 17:11:30 -0700158func (c *config) CpPreserveSymlinksFlags() string {
Colin Cross3f40fa42015-01-30 17:27:36 -0800159 switch c.HostGoOS() {
160 case "darwin":
161 return "-R"
162 case "linux":
163 return "-d"
164 default:
165 return ""
166 }
167}
Colin Cross68f55102015-03-25 14:43:57 -0700168
Colin Cross1332b002015-04-07 17:11:30 -0700169func (c *config) Getenv(key string) string {
Colin Cross68f55102015-03-25 14:43:57 -0700170 var val string
171 var exists bool
Colin Crossc1e86a32015-04-15 12:33:28 -0700172 c.envLock.Lock()
Colin Cross68f55102015-03-25 14:43:57 -0700173 if val, exists = c.envDeps[key]; !exists {
174 val = os.Getenv(key)
175 c.envDeps[key] = val
176 }
Colin Crossc1e86a32015-04-15 12:33:28 -0700177 c.envLock.Unlock()
Colin Cross68f55102015-03-25 14:43:57 -0700178 return val
179}
180
Colin Cross1332b002015-04-07 17:11:30 -0700181func (c *config) EnvDeps() map[string]string {
Colin Cross68f55102015-03-25 14:43:57 -0700182 return c.envDeps
183}
Colin Cross35cec122015-04-02 14:37:16 -0700184
185// DeviceName returns the name of the current device target
186// TODO: take an AndroidModuleContext to select the device name for multi-device builds
Colin Cross1332b002015-04-07 17:11:30 -0700187func (c *config) DeviceName() string {
Colin Cross35cec122015-04-02 14:37:16 -0700188 return "unset"
189}
190
191// DeviceOut returns the path to out directory for device targets
Colin Cross1332b002015-04-07 17:11:30 -0700192func (c *config) DeviceOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700193 return filepath.Join("target/product", c.DeviceName())
194}
195
196// HostOut returns the path to out directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700197func (c *config) HostOut() string {
Colin Cross35cec122015-04-02 14:37:16 -0700198 return filepath.Join("host", c.PrebuiltOS())
199}
200
201// HostBin returns the path to bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700202func (c *config) HostBin() string {
Colin Cross35cec122015-04-02 14:37:16 -0700203 return filepath.Join(c.HostOut(), "bin")
204}
205
206// HostBinTool returns the path to a host tool in the bin directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700207func (c *config) HostBinTool(tool string) (string, error) {
Colin Cross35cec122015-04-02 14:37:16 -0700208 return filepath.Join(c.HostBin(), tool), nil
209}
Colin Cross65bf4f22015-04-03 16:54:17 -0700210
211// HostJavaDir returns the path to framework directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700212func (c *config) HostJavaDir() string {
Colin Cross65bf4f22015-04-03 16:54:17 -0700213 return filepath.Join(c.HostOut(), "framework")
214}
215
216// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
Colin Cross1332b002015-04-07 17:11:30 -0700217func (c *config) HostJavaTool(tool string) (string, error) {
Colin Cross65bf4f22015-04-03 16:54:17 -0700218 return filepath.Join(c.HostJavaDir(), tool), nil
219}