2015-01-31 02:27:36 +01:00
|
|
|
// Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
package common
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2015-04-02 23:37:16 +02:00
|
|
|
"path/filepath"
|
2015-01-31 02:27:36 +01:00
|
|
|
"runtime"
|
2015-04-15 21:33:28 +02:00
|
|
|
"sync"
|
2015-01-31 02:27:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// The configuration file name
|
2015-07-14 09:39:06 +02:00
|
|
|
const configFileName = "soong.config"
|
|
|
|
const productVariablesFileName = "soong.variables"
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
// A FileConfigurableOptions contains options which can be configured by the
|
|
|
|
// config file. These will be included in the config struct.
|
|
|
|
type FileConfigurableOptions struct {
|
|
|
|
}
|
|
|
|
|
2015-09-18 19:57:10 +02:00
|
|
|
func (f *FileConfigurableOptions) SetDefaultConfig() {
|
|
|
|
*f = FileConfigurableOptions{}
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2015-04-11 00:43:55 +02:00
|
|
|
type Config struct {
|
|
|
|
*config
|
|
|
|
}
|
|
|
|
|
|
|
|
// A config object represents the entire build configuration for Blue.
|
2015-04-08 02:11:30 +02:00
|
|
|
type config struct {
|
2015-01-31 02:27:36 +01:00
|
|
|
FileConfigurableOptions
|
2015-08-27 22:28:01 +02:00
|
|
|
ProductVariables productVariables
|
2015-01-31 02:27:36 +01:00
|
|
|
|
2015-07-14 09:39:06 +02:00
|
|
|
ConfigFileName string
|
|
|
|
ProductVariablesFileName string
|
|
|
|
|
|
|
|
srcDir string // the path of the root source directory
|
|
|
|
buildDir string // the path of the build output directory
|
2015-04-15 21:33:28 +02:00
|
|
|
|
2015-09-12 02:06:19 +02:00
|
|
|
envLock sync.Mutex
|
|
|
|
envDeps map[string]string
|
|
|
|
envFrozen bool
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2015-08-27 22:28:01 +02:00
|
|
|
type jsonConfigurable interface {
|
2015-09-18 19:57:10 +02:00
|
|
|
SetDefaultConfig()
|
2015-08-27 22:28:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func loadConfig(config *config) error {
|
2015-07-14 09:39:06 +02:00
|
|
|
err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName)
|
2015-08-27 22:28:01 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-07-14 09:39:06 +02:00
|
|
|
return loadFromConfigFile(&config.ProductVariables, config.ProductVariablesFileName)
|
2015-08-27 22:28:01 +02:00
|
|
|
}
|
2015-01-31 02:27:36 +01:00
|
|
|
|
2015-08-27 22:28:01 +02:00
|
|
|
// loads configuration options from a JSON file in the cwd.
|
|
|
|
func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
|
2015-01-31 02:27:36 +01:00
|
|
|
// Try to open the file
|
2015-08-27 22:28:01 +02:00
|
|
|
configFileReader, err := os.Open(filename)
|
2015-01-31 02:27:36 +01:00
|
|
|
defer configFileReader.Close()
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
// Need to create a file, so that blueprint & ninja don't get in
|
|
|
|
// a dependency tracking loop.
|
|
|
|
// Make a file-configurable-options with defaults, write it out using
|
|
|
|
// a json writer.
|
2015-09-18 19:57:10 +02:00
|
|
|
configurable.SetDefaultConfig()
|
|
|
|
err = saveToConfigFile(configurable, filename)
|
2015-01-31 02:27:36 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Make a decoder for it
|
|
|
|
jsonDecoder := json.NewDecoder(configFileReader)
|
2015-08-27 22:28:01 +02:00
|
|
|
err = jsonDecoder.Decode(configurable)
|
2015-01-31 02:27:36 +01:00
|
|
|
if err != nil {
|
2015-08-27 22:28:01 +02:00
|
|
|
return fmt.Errorf("config file: %s did not parse correctly: "+err.Error(), filename)
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No error
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-08-27 22:28:01 +02:00
|
|
|
func saveToConfigFile(config jsonConfigurable, filename string) error {
|
2015-01-31 02:27:36 +01:00
|
|
|
data, err := json.MarshalIndent(&config, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot marshal config data: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
2015-08-27 22:28:01 +02:00
|
|
|
configFileWriter, err := os.Create(filename)
|
2015-01-31 02:27:36 +01:00
|
|
|
if err != nil {
|
2015-08-27 22:28:01 +02:00
|
|
|
return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
defer configFileWriter.Close()
|
|
|
|
|
|
|
|
_, err = configFileWriter.Write(data)
|
|
|
|
if err != nil {
|
2015-08-27 22:28:01 +02:00
|
|
|
return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = configFileWriter.WriteString("\n")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates a new Config object. The srcDir argument specifies the path to
|
|
|
|
// the root source directory. It also loads the config file, if found.
|
2015-07-14 09:39:06 +02:00
|
|
|
func NewConfig(srcDir, buildDir string) (Config, error) {
|
2015-01-31 02:27:36 +01:00
|
|
|
// Make a config with default options
|
2015-04-11 00:43:55 +02:00
|
|
|
config := Config{
|
|
|
|
config: &config{
|
2015-07-14 09:39:06 +02:00
|
|
|
ConfigFileName: filepath.Join(buildDir, configFileName),
|
|
|
|
ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
|
|
|
|
|
|
|
|
srcDir: srcDir,
|
|
|
|
buildDir: buildDir,
|
|
|
|
envDeps: make(map[string]string),
|
2015-04-11 00:43:55 +02:00
|
|
|
},
|
2015-03-25 22:43:57 +01:00
|
|
|
}
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
// Load any configurable options from the configuration file
|
2015-08-27 22:28:01 +02:00
|
|
|
err := loadConfig(config.config)
|
2015-01-31 02:27:36 +01:00
|
|
|
if err != nil {
|
2015-04-11 00:43:55 +02:00
|
|
|
return Config{}, err
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return config, nil
|
|
|
|
}
|
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) SrcDir() string {
|
2015-01-31 02:27:36 +01:00
|
|
|
return c.srcDir
|
|
|
|
}
|
|
|
|
|
2015-07-14 09:39:06 +02:00
|
|
|
func (c *config) BuildDir() string {
|
|
|
|
return c.buildDir
|
|
|
|
}
|
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) IntermediatesDir() string {
|
2015-07-14 09:39:06 +02:00
|
|
|
return filepath.Join(c.BuildDir(), ".intermediates")
|
2015-04-08 01:50:10 +02:00
|
|
|
}
|
|
|
|
|
2015-01-31 02:27:36 +01:00
|
|
|
// PrebuiltOS returns the name of the host OS used in prebuilts directories
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) PrebuiltOS() string {
|
2015-01-31 02:27:36 +01:00
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
|
|
|
return "linux-x86"
|
|
|
|
case "darwin":
|
|
|
|
return "darwin-x86"
|
|
|
|
default:
|
|
|
|
panic("Unknown GOOS")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GoRoot returns the path to the root directory of the Go toolchain.
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) GoRoot() string {
|
2015-01-31 02:27:36 +01:00
|
|
|
return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
|
|
|
|
}
|
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) CpPreserveSymlinksFlags() string {
|
2015-08-27 22:28:01 +02:00
|
|
|
switch runtime.GOOS {
|
2015-01-31 02:27:36 +01:00
|
|
|
case "darwin":
|
|
|
|
return "-R"
|
|
|
|
case "linux":
|
|
|
|
return "-d"
|
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
2015-03-25 22:43:57 +01:00
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) Getenv(key string) string {
|
2015-03-25 22:43:57 +01:00
|
|
|
var val string
|
|
|
|
var exists bool
|
2015-04-15 21:33:28 +02:00
|
|
|
c.envLock.Lock()
|
2015-03-25 22:43:57 +01:00
|
|
|
if val, exists = c.envDeps[key]; !exists {
|
2015-09-12 02:06:19 +02:00
|
|
|
if c.envFrozen {
|
|
|
|
panic("Cannot access new environment variables after envdeps are frozen")
|
|
|
|
}
|
2015-03-25 22:43:57 +01:00
|
|
|
val = os.Getenv(key)
|
|
|
|
c.envDeps[key] = val
|
|
|
|
}
|
2015-04-15 21:33:28 +02:00
|
|
|
c.envLock.Unlock()
|
2015-03-25 22:43:57 +01:00
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) EnvDeps() map[string]string {
|
2015-09-12 02:06:19 +02:00
|
|
|
c.envLock.Lock()
|
|
|
|
c.envFrozen = true
|
|
|
|
c.envLock.Unlock()
|
2015-03-25 22:43:57 +01:00
|
|
|
return c.envDeps
|
|
|
|
}
|
2015-04-02 23:37:16 +02:00
|
|
|
|
|
|
|
// DeviceName returns the name of the current device target
|
|
|
|
// TODO: take an AndroidModuleContext to select the device name for multi-device builds
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) DeviceName() string {
|
2015-09-23 01:56:09 +02:00
|
|
|
return *c.ProductVariables.DeviceName
|
2015-04-02 23:37:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeviceOut returns the path to out directory for device targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) DeviceOut() string {
|
2015-07-14 09:39:06 +02:00
|
|
|
return filepath.Join(c.BuildDir(), "target/product", c.DeviceName())
|
2015-04-02 23:37:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// HostOut returns the path to out directory for host targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) HostOut() string {
|
2015-07-14 09:39:06 +02:00
|
|
|
return filepath.Join(c.BuildDir(), "host", c.PrebuiltOS())
|
2015-04-02 23:37:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// HostBin returns the path to bin directory for host targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) HostBin() string {
|
2015-04-02 23:37:16 +02:00
|
|
|
return filepath.Join(c.HostOut(), "bin")
|
|
|
|
}
|
|
|
|
|
|
|
|
// HostBinTool returns the path to a host tool in the bin directory for host targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) HostBinTool(tool string) (string, error) {
|
2015-04-02 23:37:16 +02:00
|
|
|
return filepath.Join(c.HostBin(), tool), nil
|
|
|
|
}
|
2015-04-04 01:54:17 +02:00
|
|
|
|
|
|
|
// HostJavaDir returns the path to framework directory for host targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) HostJavaDir() string {
|
2015-04-04 01:54:17 +02:00
|
|
|
return filepath.Join(c.HostOut(), "framework")
|
|
|
|
}
|
|
|
|
|
|
|
|
// HostJavaTool returns the path to a host tool in the frameworks directory for host targets
|
2015-04-08 02:11:30 +02:00
|
|
|
func (c *config) HostJavaTool(tool string) (string, error) {
|
2015-04-04 01:54:17 +02:00
|
|
|
return filepath.Join(c.HostJavaDir(), tool), nil
|
|
|
|
}
|
2015-04-13 22:58:27 +02:00
|
|
|
|
|
|
|
func (c *config) ResourceOverlays() []string {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) PlatformVersion() string {
|
|
|
|
return "M"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) PlatformSdkVersion() string {
|
|
|
|
return "22"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) BuildNumber() string {
|
|
|
|
return "000000"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) ProductAaptConfig() []string {
|
|
|
|
return []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) ProductAaptPreferredConfig() string {
|
|
|
|
return "xhdpi"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) ProductAaptCharacteristics() string {
|
|
|
|
return "nosdcard"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) DefaultAppCertificateDir() string {
|
|
|
|
return filepath.Join(c.SrcDir(), "build/target/product/security")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *config) DefaultAppCertificate() string {
|
|
|
|
return filepath.Join(c.DefaultAppCertificateDir(), "testkey")
|
|
|
|
}
|