Sandbox soong_build by changing to root directory

Store the current working directory and then change to the root
directory so that all file accesses must go through helpers in
the android package that properly track dependencies.

Fixes: 146437378
Test: m checkbuild
Change-Id: I12a0f907753fefd1997ab8b4ea2ac331234093cf
This commit is contained in:
Colin Cross 2019-12-12 10:23:57 -08:00
parent 62c085d7fe
commit 05c25ccb4a
23 changed files with 208 additions and 130 deletions

View File

@ -69,6 +69,7 @@ bootstrap_go_package {
"android/proto.go",
"android/register.go",
"android/rule_builder.go",
"android/sandbox.go",
"android/sdk.go",
"android/sh_binary.go",
"android/singleton.go",

View File

@ -323,7 +323,7 @@ func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
return
}
err := translateAndroidMk(ctx, transMk.String(), androidMkModulesList)
err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
if err != nil {
ctx.Errorf(err.Error())
}
@ -364,8 +364,8 @@ func translateAndroidMk(ctx SingletonContext, mkFile string, mods []blueprint.Mo
}
// Don't write to the file if it hasn't changed
if _, err := os.Stat(mkFile); !os.IsNotExist(err) {
if data, err := ioutil.ReadFile(mkFile); err == nil {
if _, err := os.Stat(absolutePath(mkFile)); !os.IsNotExist(err) {
if data, err := ioutil.ReadFile(absolutePath(mkFile)); err == nil {
matches := buf.Len() == len(data)
if matches {
@ -383,7 +383,7 @@ func translateAndroidMk(ctx SingletonContext, mkFile string, mods []blueprint.Mo
}
}
return ioutil.WriteFile(mkFile, buf.Bytes(), 0666)
return ioutil.WriteFile(absolutePath(mkFile), buf.Bytes(), 0666)
}
func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {

View File

@ -135,12 +135,12 @@ type jsonConfigurable interface {
}
func loadConfig(config *config) error {
err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName)
err := loadFromConfigFile(&config.FileConfigurableOptions, absolutePath(config.ConfigFileName))
if err != nil {
return err
}
return loadFromConfigFile(&config.productVariables, config.ProductVariablesFileName)
return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
}
// loads configuration options from a JSON file in the cwd.
@ -204,6 +204,17 @@ func saveToConfigFile(config jsonConfigurable, filename string) error {
return nil
}
// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
// use the android package.
func NullConfig(buildDir string) Config {
return Config{
config: &config{
buildDir: buildDir,
fs: pathtools.OsFs,
},
}
}
// TestConfig returns a Config object suitable for using for tests
func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
envCopy := make(map[string]string)
@ -320,7 +331,7 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
buildDir: buildDir,
multilibConflicts: make(map[ArchType]bool),
fs: pathtools.OsFs,
fs: pathtools.NewOsFs(absSrcDir),
}
config.deviceConfig = &deviceConfig{
@ -350,7 +361,7 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
}
inMakeFile := filepath.Join(buildDir, ".soong.in_make")
if _, err := os.Stat(inMakeFile); err == nil {
if _, err := os.Stat(absolutePath(inMakeFile)); err == nil {
config.inMake = true
}
@ -398,6 +409,8 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
return Config{config}, nil
}
var TestConfigOsFs = map[string][]byte{}
// mockFileSystem replaces all reads with accesses to the provided map of
// filenames to contents stored as a byte slice.
func (c *config) mockFileSystem(bp string, fs map[string][]byte) {
@ -901,8 +914,13 @@ func (c *config) BootJars() []string {
return c.productVariables.BootJars
}
func (c *config) DexpreoptGlobalConfig() string {
return String(c.productVariables.DexpreoptGlobalConfig)
func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
if c.productVariables.DexpreoptGlobalConfig == nil {
return nil, nil
}
path := absolutePath(*c.productVariables.DexpreoptGlobalConfig)
ctx.AddNinjaFileDeps(path)
return ioutil.ReadFile(path)
}
func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {

View File

@ -52,6 +52,17 @@ func init() {
os.Clearenv()
}
// getenv checks either os.Getenv or originalEnv so that it works before or after the init()
// function above. It doesn't add any dependencies on the environment variable, so it should
// only be used for values that won't change. For values that might change use ctx.Config().Getenv.
func getenv(key string) string {
if originalEnv == nil {
return os.Getenv(key)
} else {
return originalEnv[key]
}
}
func EnvSingleton() Singleton {
return &envSingleton{}
}
@ -66,7 +77,12 @@ func (c *envSingleton) GenerateBuildActions(ctx SingletonContext) {
return
}
err := env.WriteEnvFile(envFile.String(), envDeps)
data, err := env.EnvFileContents(envDeps)
if err != nil {
ctx.Errorf(err.Error())
}
err = WriteFileToOutputDir(envFile, data, 0666)
if err != nil {
ctx.Errorf(err.Error())
}

View File

@ -23,7 +23,6 @@ import (
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
@ -41,7 +40,6 @@ type MakeVarsContext interface {
Config() Config
DeviceConfig() DeviceConfig
AddNinjaFileDeps(deps ...string)
Fs() pathtools.FileSystem
ModuleName(module blueprint.Module) string
ModuleDir(module blueprint.Module) string
@ -151,7 +149,8 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
return
}
outFile := PathForOutput(ctx, "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()
outFile := absolutePath(PathForOutput(ctx,
"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
if ctx.Failed() {
return
@ -175,15 +174,15 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
outBytes := s.writeVars(vars)
if _, err := os.Stat(outFile); err == nil {
if data, err := ioutil.ReadFile(outFile); err == nil {
if _, err := os.Stat(absolutePath(outFile)); err == nil {
if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
if bytes.Equal(data, outBytes) {
return
}
}
}
if err := ioutil.WriteFile(outFile, outBytes, 0666); err != nil {
if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
ctx.Errorf(err.Error())
}
}

View File

@ -16,13 +16,13 @@ package android
import (
"fmt"
"os"
"path"
"path/filepath"
"strings"
"text/scanner"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
@ -91,7 +91,8 @@ type EarlyModuleContext interface {
Glob(globPattern string, excludes []string) Paths
GlobFiles(globPattern string, excludes []string) Paths
Fs() pathtools.FileSystem
IsSymlink(path Path) bool
Readlink(path Path) string
}
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@ -1172,6 +1173,22 @@ func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Pa
return pathsForModuleSrcFromFullPath(e, ret, false)
}
func (b *earlyModuleContext) IsSymlink(path Path) bool {
fileInfo, err := b.config.fs.Lstat(path.String())
if err != nil {
b.ModuleErrorf("os.Lstat(%q) failed: %s", path.String(), err)
}
return fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink
}
func (b *earlyModuleContext) Readlink(path Path) string {
dest, err := b.config.fs.Readlink(path.String())
if err != nil {
b.ModuleErrorf("os.Readlink(%q) failed: %s", path.String(), err)
}
return dest
}
func (e *earlyModuleContext) Module() Module {
module, _ := e.EarlyModuleContext.Module().(Module)
return module

View File

@ -19,7 +19,6 @@ import (
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
)
// PackageContext is a wrapper for blueprint.PackageContext that adds
@ -60,10 +59,6 @@ func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
e.pctx.AddNinjaFileDeps(deps...)
}
func (e *configErrorWrapper) Fs() pathtools.FileSystem {
return nil
}
type PackageVarContext interface {
PathContext
errorfContext

View File

@ -16,6 +16,8 @@ package android
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
@ -25,10 +27,11 @@ import (
"github.com/google/blueprint/pathtools"
)
var absSrcDir string
// PathContext is the subset of a (Module|Singleton)Context required by the
// Path methods.
type PathContext interface {
Fs() pathtools.FileSystem
Config() Config
AddNinjaFileDeps(deps ...string)
}
@ -390,7 +393,7 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P
return PathsWithModuleSrcSubDir(ctx, paths, ""), nil
} else {
p := pathForModuleSrc(ctx, s)
if exists, _, err := ctx.Fs().Exists(p.String()); err != nil {
if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
reportPathErrorf(ctx, "%s: %s", p, err.Error())
} else if !exists {
reportPathErrorf(ctx, "module source path %q does not exist", p)
@ -720,7 +723,7 @@ func existsWithDependencies(ctx PathContext, path SourcePath) (exists bool, err
var deps []string
// We cannot add build statements in this context, so we fall back to
// AddNinjaFileDeps
files, deps, err = pathtools.Glob(path.String(), nil, pathtools.FollowSymlinks)
files, deps, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
ctx.AddNinjaFileDeps(deps...)
}
@ -752,7 +755,7 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
if !exists {
modCtx.AddMissingDependencies([]string{path.String()})
}
} else if exists, _, err := ctx.Fs().Exists(path.String()); err != nil {
} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
reportPathErrorf(ctx, "%s: %s", path, err.Error())
} else if !exists {
reportPathErrorf(ctx, "source path %q does not exist", path)
@ -1356,7 +1359,6 @@ type testPathContext struct {
config Config
}
func (x *testPathContext) Fs() pathtools.FileSystem { return x.config.fs }
func (x *testPathContext) Config() Config { return x.config }
func (x *testPathContext) AddNinjaFileDeps(...string) {}
@ -1402,3 +1404,16 @@ func maybeRelErr(basePath string, targetPath string) (string, bool, error) {
}
return rel, true, nil
}
// Writes a file to the output directory. Attempting to write directly to the output directory
// will fail due to the sandbox of the soong_build process.
func WriteFileToOutputDir(path WritablePath, data []byte, perm os.FileMode) error {
return ioutil.WriteFile(absolutePath(path.String()), data, perm)
}
func absolutePath(path string) string {
if filepath.IsAbs(path) {
return path
}
return filepath.Join(absSrcDir, path)
}

View File

@ -21,7 +21,6 @@ import (
"strings"
"testing"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
@ -207,10 +206,6 @@ type moduleInstallPathContextImpl struct {
inRoot bool
}
func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
return pathtools.MockFs(nil)
}
func (m moduleInstallPathContextImpl) Config() Config {
return m.baseModuleContext.config
}

View File

@ -84,7 +84,9 @@ type Context struct {
}
func NewContext() *Context {
return &Context{blueprint.NewContext()}
ctx := &Context{blueprint.NewContext()}
ctx.SetSrcDir(absSrcDir)
return ctx
}
func (ctx *Context) Register() {

47
android/sandbox.go Normal file
View File

@ -0,0 +1,47 @@
// Copyright 2020 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.
package android
import (
"fmt"
"os"
)
func init() {
// Stash the working directory in a private variable and then change the working directory
// to "/", which will prevent untracked accesses to files by Go Soong plugins. The
// SOONG_SANDBOX_SOONG_BUILD environment variable is set by soong_ui, and is not
// overrideable on the command line.
orig, err := os.Getwd()
if err != nil {
panic(fmt.Errorf("failed to get working directory: %s", err))
}
absSrcDir = orig
if getenv("SOONG_SANDBOX_SOONG_BUILD") == "true" {
err = os.Chdir("/")
if err != nil {
panic(fmt.Errorf("failed to change working directory to '/': %s", err))
}
}
}
// DO NOT USE THIS FUNCTION IN NEW CODE.
// Deprecated: This function will be removed as soon as the existing use cases that use it have been
// replaced.
func AbsSrcDirForExistingUseCases() string {
return absSrcDir
}

View File

@ -16,7 +16,6 @@ package android
import (
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
)
// SingletonContext
@ -74,8 +73,6 @@ type SingletonContext interface {
// builder whenever a file matching the pattern as added or removed, without rerunning if a
// file that does not match the pattern is added to a searched directory.
GlobWithDeps(pattern string, excludes []string) ([]string, error)
Fs() pathtools.FileSystem
}
type singletonAdaptor struct {

View File

@ -41,7 +41,6 @@ bootstrap_go_package {
"androidmk-parser",
"blueprint-parser",
"bpfix-lib",
"soong-android",
],
}

View File

@ -15,9 +15,9 @@
package androidmk
import (
"android/soong/android"
mkparser "android/soong/androidmk/parser"
"fmt"
"sort"
"strings"
bpparser "github.com/google/blueprint/parser"
@ -350,7 +350,13 @@ func splitAndAssign(ctx variableAssignmentContext, splitFunc listSplitFunc, name
return err
}
for _, nameClassification := range android.SortedStringKeys(namesByClassification) {
var classifications []string
for classification := range namesByClassification {
classifications = append(classifications, classification)
}
sort.Strings(classifications)
for _, nameClassification := range classifications {
name := namesByClassification[nameClassification]
if component, ok := lists[nameClassification]; ok && !emptyList(component) {
err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true)

View File

@ -76,7 +76,7 @@ func (c *cmakelistsGeneratorSingleton) GenerateBuildActions(ctx android.Singleto
// Link all handmade CMakeLists.txt aggregate from
// BASE/development/ide/clion to
// BASE/out/development/ide/clion.
dir := filepath.Join(getAndroidSrcRootDirectory(ctx), cLionAggregateProjectsDirectory)
dir := filepath.Join(android.AbsSrcDirForExistingUseCases(), cLionAggregateProjectsDirectory)
filepath.Walk(dir, linkAggregateCMakeListsFiles)
return
@ -147,7 +147,7 @@ func generateCLionProject(compiledModule CompiledInterface, ctx android.Singleto
f.WriteString("# Tools > CMake > Change Project Root \n\n")
f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported))
f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", getAndroidSrcRootDirectory(ctx)))
f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", android.AbsSrcDirForExistingUseCases()))
pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
@ -465,7 +465,7 @@ func evalVariable(ctx android.SingletonContext, str string) (string, error) {
}
func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string {
return filepath.Join(getAndroidSrcRootDirectory(ctx),
return filepath.Join(android.AbsSrcDirForExistingUseCases(),
cLionOutputProjectsDirectory,
path.Dir(ctx.BlueprintFile(module)),
module.ModuleBase.Name()+"-"+
@ -473,8 +473,3 @@ func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string
module.ModuleBase.Os().Name,
cMakeListsFilename)
}
func getAndroidSrcRootDirectory(ctx android.SingletonContext) string {
srcPath, _ := filepath.Abs(android.PathForSource(ctx).String())
return srcPath
}

View File

@ -79,9 +79,9 @@ func (c *compdbGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon
// Create the output file.
dir := android.PathForOutput(ctx, compdbOutputProjectsDirectory)
os.MkdirAll(dir.String(), 0777)
os.MkdirAll(filepath.Join(android.AbsSrcDirForExistingUseCases(), dir.String()), 0777)
compDBFile := dir.Join(ctx, compdbFilename)
f, err := os.Create(compDBFile.String())
f, err := os.Create(filepath.Join(android.AbsSrcDirForExistingUseCases(), compDBFile.String()))
if err != nil {
log.Fatalf("Could not create file %s: %s", compDBFile, err)
}
@ -103,8 +103,8 @@ func (c *compdbGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCon
}
f.Write(dat)
finalLinkPath := filepath.Join(ctx.Config().Getenv(envVariableCompdbLink), compdbFilename)
if finalLinkPath != "" {
if finalLinkDir := ctx.Config().Getenv(envVariableCompdbLink); finalLinkDir != "" {
finalLinkPath := filepath.Join(finalLinkDir, compdbFilename)
os.Remove(finalLinkPath)
if err := os.Symlink(compDBFile.String(), finalLinkPath); err != nil {
log.Fatalf("Unable to symlink %s to %s: %s", compDBFile, finalLinkPath, err)
@ -174,18 +174,17 @@ func generateCompdbProject(compiledModule CompiledInterface, ctx android.Singlet
return
}
rootDir := getCompdbAndroidSrcRootDirectory(ctx)
pathToCC, err := ctx.Eval(pctx, rootDir+"/${config.ClangBin}/")
pathToCC, err := ctx.Eval(pctx, "${config.ClangBin}")
ccPath := "/bin/false"
cxxPath := "/bin/false"
if err == nil {
ccPath = pathToCC + "clang"
cxxPath = pathToCC + "clang++"
ccPath = filepath.Join(pathToCC, "clang")
cxxPath = filepath.Join(pathToCC, "clang++")
}
for _, src := range srcs {
if _, ok := builds[src.String()]; !ok {
builds[src.String()] = compDbEntry{
Directory: rootDir,
Directory: android.AbsSrcDirForExistingUseCases(),
Arguments: getArguments(src, ctx, ccModule, ccPath, cxxPath),
File: src.String(),
}
@ -200,8 +199,3 @@ func evalAndSplitVariable(ctx android.SingletonContext, str string) ([]string, e
}
return []string{""}, err
}
func getCompdbAndroidSrcRootDirectory(ctx android.SingletonContext) string {
srcPath, _ := filepath.Abs(android.PathForSource(ctx).String())
return srcPath
}

View File

@ -16,7 +16,6 @@ package cc
import (
"fmt"
"os"
"path/filepath"
"strings"
@ -255,16 +254,8 @@ func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir andro
depsPath := android.PathForSource(ctx, "bionic/libc/versioner-dependencies")
depsGlob := ctx.Glob(filepath.Join(depsPath.String(), "**/*"), nil)
for i, path := range depsGlob {
fileInfo, err := os.Lstat(path.String())
if err != nil {
ctx.ModuleErrorf("os.Lstat(%q) failed: %s", path.String, err)
}
if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
dest, err := os.Readlink(path.String())
if err != nil {
ctx.ModuleErrorf("os.Readlink(%q) failed: %s",
path.String, err)
}
if ctx.IsSymlink(path) {
dest := ctx.Readlink(path)
// Additional .. to account for the symlink itself.
depsGlob[i] = android.PathForSource(
ctx, filepath.Clean(filepath.Join(path.String(), "..", dest)))

View File

@ -16,7 +16,6 @@ package dexpreopt
import (
"encoding/json"
"io/ioutil"
"strings"
"android/soong/android"
@ -185,7 +184,7 @@ func constructWritablePath(ctx android.PathContext, path string) android.Writabl
// soongConfig argument. LoadGlobalConfig is used directly in Soong and in
// dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by
// Make.
func LoadGlobalConfig(ctx android.PathContext, path string, soongConfig GlobalSoongConfig) (GlobalConfig, []byte, error) {
func LoadGlobalConfig(ctx android.PathContext, data []byte, soongConfig GlobalSoongConfig) (GlobalConfig, error) {
type GlobalJSONConfig struct {
GlobalConfig
@ -196,9 +195,9 @@ func LoadGlobalConfig(ctx android.PathContext, path string, soongConfig GlobalSo
}
config := GlobalJSONConfig{}
data, err := loadConfig(ctx, path, &config)
err := json.Unmarshal(data, &config)
if err != nil {
return config.GlobalConfig, nil, err
return config.GlobalConfig, err
}
// Construct paths that require a PathContext.
@ -209,13 +208,13 @@ func LoadGlobalConfig(ctx android.PathContext, path string, soongConfig GlobalSo
// either CreateGlobalSoongConfig or LoadGlobalSoongConfig).
config.GlobalConfig.SoongConfig = soongConfig
return config.GlobalConfig, data, nil
return config.GlobalConfig, nil
}
// LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct. It is not used in Soong, which
// receives a ModuleConfig struct directly from java/dexpreopt.go. It is used in dexpreopt_gen called from oMake to
// read the module dexpreopt.config written by Make.
func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) {
func LoadModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, error) {
type ModuleJSONConfig struct {
ModuleConfig
@ -233,7 +232,7 @@ func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error
config := ModuleJSONConfig{}
_, err := loadConfig(ctx, path, &config)
err := json.Unmarshal(data, &config)
if err != nil {
return config.ModuleConfig, err
}
@ -289,10 +288,10 @@ type globalJsonSoongConfig struct {
// LoadGlobalSoongConfig reads the dexpreopt_soong.config file into a
// GlobalSoongConfig struct. It is only used in dexpreopt_gen.
func LoadGlobalSoongConfig(ctx android.PathContext, path string) (GlobalSoongConfig, error) {
func LoadGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongConfig, error) {
var jc globalJsonSoongConfig
_, err := loadConfig(ctx, path, &jc)
err := json.Unmarshal(data, &jc)
if err != nil {
return GlobalSoongConfig{}, err
}
@ -352,26 +351,6 @@ func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
}, " "))
}
func loadConfig(ctx android.PathContext, path string, config interface{}) ([]byte, error) {
r, err := ctx.Fs().Open(path)
if err != nil {
return nil, err
}
defer r.Close()
data, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, config)
if err != nil {
return nil, err
}
return data, nil
}
func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
return GlobalConfig{
DisablePreopt: false,

View File

@ -18,6 +18,7 @@ import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@ -41,7 +42,6 @@ type pathContext struct {
config android.Config
}
func (x *pathContext) Fs() pathtools.FileSystem { return pathtools.OsFs }
func (x *pathContext) Config() android.Config { return x.config }
func (x *pathContext) AddNinjaFileDeps(...string) {}
@ -76,21 +76,39 @@ func main() {
usage("--module configuration file is required")
}
ctx := &pathContext{android.TestConfig(*outDir, nil, "", nil)}
ctx := &pathContext{android.NullConfig(*outDir)}
globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, *globalSoongConfigPath)
globalSoongConfigData, err := ioutil.ReadFile(*globalSoongConfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalSoongConfigPath, err)
os.Exit(2)
}
globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, globalSoongConfigData)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
os.Exit(2)
}
globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath, globalSoongConfig)
globalConfigData, err := ioutil.ReadFile(*globalConfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalConfigPath, err)
os.Exit(2)
}
moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, *moduleConfigPath)
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, globalConfigData, globalSoongConfig)
if err != nil {
fmt.Fprintf(os.Stderr, "error parse global config %q: %s\n", *globalConfigPath, err)
os.Exit(2)
}
moduleConfigData, err := ioutil.ReadFile(*moduleConfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error reading module config %q: %s\n", *moduleConfigPath, err)
os.Exit(2)
}
moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, moduleConfigData)
if err != nil {
fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
os.Exit(2)

11
env/env.go vendored
View File

@ -27,7 +27,7 @@ import (
type envFileEntry struct{ Key, Value string }
type envFileData []envFileEntry
func WriteEnvFile(filename string, envDeps map[string]string) error {
func EnvFileContents(envDeps map[string]string) ([]byte, error) {
contents := make(envFileData, 0, len(envDeps))
for key, value := range envDeps {
contents = append(contents, envFileEntry{key, value})
@ -37,17 +37,12 @@ func WriteEnvFile(filename string, envDeps map[string]string) error {
data, err := json.MarshalIndent(contents, "", " ")
if err != nil {
return err
return nil, err
}
data = append(data, '\n')
err = ioutil.WriteFile(filename, data, 0664)
if err != nil {
return err
}
return nil
return data, nil
}
func StaleEnvFile(filename string) (bool, error) {

View File

@ -36,10 +36,11 @@ type globalConfigAndRaw struct {
func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
panic(err)
} else if data != nil {
soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
ctx.AddNinjaFileDeps(f)
globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f, soongConfig)
globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, data, soongConfig)
if err != nil {
panic(err)
}

View File

@ -17,7 +17,6 @@ package java
import (
"encoding/json"
"fmt"
"os"
"android/soong/android"
)
@ -92,23 +91,21 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont
moduleInfos[name] = dpInfo
})
jfpath := android.PathForOutput(ctx, jdepsJsonFileName).String()
jfpath := android.PathForOutput(ctx, jdepsJsonFileName)
err := createJsonFile(moduleInfos, jfpath)
if err != nil {
ctx.Errorf(err.Error())
}
}
func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath string) error {
file, err := os.Create(jfpath)
if err != nil {
return fmt.Errorf("Failed to create file: %s, relative: %v", jdepsJsonFileName, err)
}
defer file.Close()
func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error {
buf, err := json.MarshalIndent(moduleInfos, "", "\t")
if err != nil {
return fmt.Errorf("Write file failed: %s, relative: %v", jdepsJsonFileName, err)
return fmt.Errorf("JSON marshal of java deps failed: %s", err)
}
err = android.WriteFileToOutputDir(jfpath, buf, 0666)
if err != nil {
return fmt.Errorf("Writing java deps to %s failed: %s", jfpath.String(), err)
}
fmt.Fprintf(file, string(buf))
return nil
}

View File

@ -119,6 +119,7 @@ func runSoong(ctx Context, config Config) {
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
cmd.Sandbox = soongSandbox
cmd.RunAndStreamOrFatal()
}