blob: 4e9cbf1d495380ed13d5dcd0ea9e64ef21d090c4 [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
126// HostGoOS returns the OS of the system that the Go toolchain is being run on.
127func (c *Config) HostGoOS() string {
128 return runtime.GOOS
129}
130
131// PrebuiltOS returns the name of the host OS used in prebuilts directories
132func (c *Config) PrebuiltOS() string {
133 switch runtime.GOOS {
134 case "linux":
135 return "linux-x86"
136 case "darwin":
137 return "darwin-x86"
138 default:
139 panic("Unknown GOOS")
140 }
141}
142
143// GoRoot returns the path to the root directory of the Go toolchain.
144func (c *Config) GoRoot() string {
145 return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
146}
147
148func (c *Config) CpPreserveSymlinksFlags() string {
149 switch c.HostGoOS() {
150 case "darwin":
151 return "-R"
152 case "linux":
153 return "-d"
154 default:
155 return ""
156 }
157}
Colin Cross68f55102015-03-25 14:43:57 -0700158
159func (c *Config) Getenv(key string) string {
160 var val string
161 var exists bool
162 if val, exists = c.envDeps[key]; !exists {
163 val = os.Getenv(key)
164 c.envDeps[key] = val
165 }
166 return val
167}
168
169func (c *Config) EnvDeps() map[string]string {
170 return c.envDeps
171}
Colin Cross35cec122015-04-02 14:37:16 -0700172
173// DeviceName returns the name of the current device target
174// TODO: take an AndroidModuleContext to select the device name for multi-device builds
175func (c *Config) DeviceName() string {
176 return "unset"
177}
178
179// DeviceOut returns the path to out directory for device targets
180func (c *Config) DeviceOut() string {
181 return filepath.Join("target/product", c.DeviceName())
182}
183
184// HostOut returns the path to out directory for host targets
185func (c *Config) HostOut() string {
186 return filepath.Join("host", c.PrebuiltOS())
187}
188
189// HostBin returns the path to bin directory for host targets
190func (c *Config) HostBin() string {
191 return filepath.Join(c.HostOut(), "bin")
192}
193
194// HostBinTool returns the path to a host tool in the bin directory for host targets
195func (c *Config) HostBinTool(tool string) (string, error) {
196 return filepath.Join(c.HostBin(), tool), nil
197}