blob: e324e42d79d72f5bed0d6113df71592f211a1ad4 [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"
Colin Cross35cec122015-04-02 14:37:16 -070022 "path/filepath"
Colin Cross3f40fa42015-01-30 17:27:36 -080023 "runtime"
24)
25
26var _ common.Config = (*Config)(nil)
27
28// The configuration file name
29const ConfigFileName = "soong.config"
30
31// A FileConfigurableOptions contains options which can be configured by the
32// config file. These will be included in the config struct.
33type FileConfigurableOptions struct {
34}
35
36func NewFileConfigurableOptions() FileConfigurableOptions {
37 f := FileConfigurableOptions{}
38 return f
39}
40
41// A Config object represents the entire build configuration for Blue.
42type Config struct {
43 FileConfigurableOptions
44
Colin Cross68f55102015-03-25 14:43:57 -070045 srcDir string // the path of the root source directory
46 envDeps map[string]string
Colin Cross3f40fa42015-01-30 17:27:36 -080047}
48
49// loads configuration options from a JSON file in the cwd.
50func loadFromConfigFile(config *Config) error {
51 // Make a proxy config
52 var configProxy FileConfigurableOptions
53
54 // Try to open the file
55 configFileReader, err := os.Open(ConfigFileName)
56 defer configFileReader.Close()
57 if os.IsNotExist(err) {
58 // Need to create a file, so that blueprint & ninja don't get in
59 // a dependency tracking loop.
60 // Make a file-configurable-options with defaults, write it out using
61 // a json writer.
62 configProxy = NewFileConfigurableOptions()
63 err = saveToConfigFile(configProxy)
64 if err != nil {
65 return err
66 }
67 } else {
68 // Make a decoder for it
69 jsonDecoder := json.NewDecoder(configFileReader)
70 err = jsonDecoder.Decode(&configProxy)
71 if err != nil {
72 return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), ConfigFileName)
73 }
74 }
75
76 // Copy the configurable options out of the config_proxy into the config,
77 // and we're done!
78 config.FileConfigurableOptions = configProxy
79
80 // No error
81 return nil
82}
83
84func saveToConfigFile(config FileConfigurableOptions) error {
85 data, err := json.MarshalIndent(&config, "", " ")
86 if err != nil {
87 return fmt.Errorf("cannot marshal config data: %s", err.Error())
88 }
89
90 configFileWriter, err := os.Create(ConfigFileName)
91 if err != nil {
92 return fmt.Errorf("cannot create empty config file %s: %s\n", ConfigFileName, err.Error())
93 }
94 defer configFileWriter.Close()
95
96 _, err = configFileWriter.Write(data)
97 if err != nil {
98 return fmt.Errorf("default config file: %s could not be written: %s", ConfigFileName, err.Error())
99 }
100
101 return nil
102}
103
104// New creates a new Config object. The srcDir argument specifies the path to
105// the root source directory. It also loads the config file, if found.
106func New(srcDir string) (*Config, error) {
107 // Make a config with default options
Colin Cross68f55102015-03-25 14:43:57 -0700108 config := &Config{
109 srcDir: srcDir,
110 envDeps: make(map[string]string),
111 }
Colin Cross3f40fa42015-01-30 17:27:36 -0800112
113 // Load any configurable options from the configuration file
114 err := loadFromConfigFile(config)
115 if err != nil {
116 return nil, err
117 }
118
119 return config, nil
120}
121
122func (c *Config) SrcDir() string {
123 return c.srcDir
124}
125
Colin Cross581c1892015-04-07 16:50:10 -0700126func (c *Config) IntermediatesDir() string {
127 return ".intermediates"
128}
129
Colin Cross3f40fa42015-01-30 17:27:36 -0800130// HostGoOS returns the OS of the system that the Go toolchain is being run on.
131func (c *Config) HostGoOS() string {
132 return runtime.GOOS
133}
134
135// PrebuiltOS returns the name of the host OS used in prebuilts directories
136func (c *Config) PrebuiltOS() string {
137 switch runtime.GOOS {
138 case "linux":
139 return "linux-x86"
140 case "darwin":
141 return "darwin-x86"
142 default:
143 panic("Unknown GOOS")
144 }
145}
146
147// GoRoot returns the path to the root directory of the Go toolchain.
148func (c *Config) GoRoot() string {
149 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
150}
151
152func (c *Config) CpPreserveSymlinksFlags() string {
153 switch c.HostGoOS() {
154 case "darwin":
155 return "-R"
156 case "linux":
157 return "-d"
158 default:
159 return ""
160 }
161}
Colin Cross68f55102015-03-25 14:43:57 -0700162
163func (c *Config) Getenv(key string) string {
164 var val string
165 var exists bool
166 if val, exists = c.envDeps[key]; !exists {
167 val = os.Getenv(key)
168 c.envDeps[key] = val
169 }
170 return val
171}
172
173func (c *Config) EnvDeps() map[string]string {
174 return c.envDeps
175}
Colin Cross35cec122015-04-02 14:37:16 -0700176
177// DeviceName returns the name of the current device target
178// TODO: take an AndroidModuleContext to select the device name for multi-device builds
179func (c *Config) DeviceName() string {
180 return "unset"
181}
182
183// DeviceOut returns the path to out directory for device targets
184func (c *Config) DeviceOut() string {
185 return filepath.Join("target/product", c.DeviceName())
186}
187
188// HostOut returns the path to out directory for host targets
189func (c *Config) HostOut() string {
190 return filepath.Join("host", c.PrebuiltOS())
191}
192
193// HostBin returns the path to bin directory for host targets
194func (c *Config) HostBin() string {
195 return filepath.Join(c.HostOut(), "bin")
196}
197
198// HostBinTool returns the path to a host tool in the bin directory for host targets
199func (c *Config) HostBinTool(tool string) (string, error) {
200 return filepath.Join(c.HostBin(), tool), nil
201}
Colin Cross65bf4f22015-04-03 16:54:17 -0700202
203// HostJavaDir returns the path to framework directory for host targets
204func (c *Config) HostJavaDir() string {
205 return filepath.Join(c.HostOut(), "framework")
206}
207
208// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
209func (c *Config) HostJavaTool(tool string) (string, error) {
210 return filepath.Join(c.HostJavaDir(), tool), nil
211}