diff --git a/Blueprints b/Blueprints index c8442e7c4..8a2d85f85 100644 --- a/Blueprints +++ b/Blueprints @@ -19,6 +19,7 @@ bootstrap_go_binary { "soong-cc", "soong-common", "soong-config", + "soong-env", "soong-genrule", ], srcs: [ @@ -27,6 +28,25 @@ bootstrap_go_binary { primaryBuilder: true, } +bootstrap_go_binary { + name: "soong_env", + deps: [ + "soong-env", + ], + srcs: [ + "cmd/soong_env/soong_env.go", + ], +} + +bootstrap_go_package { + name: "soong-env", + pkgPath: "android/soong/env", + srcs: [ + "env/env.go", + ], +} + + bootstrap_go_binary { name: "soong_glob", deps: [ @@ -54,12 +74,14 @@ bootstrap_go_package { deps: [ "blueprint", "blueprint-bootstrap", + "soong-env", "soong-glob", ], srcs: [ "common/arch.go", "common/checkbuild.go", "common/defs.go", + "common/env.go", "common/glob.go", "common/module.go", "common/paths.go", diff --git a/build.ninja.in b/build.ninja.in index 2b802d43f..4fb63250e 100644 --- a/build.ninja.in +++ b/build.ninja.in @@ -53,7 +53,7 @@ rule g.bootstrap.link # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:123:1 +# Defined: build/soong/Blueprints:145:1 build .bootstrap/androidmk/obj/androidmk.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/androidmk/cmd/androidmk/android.go $ @@ -79,7 +79,7 @@ default .bootstrap/bin/androidmk # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:136:1 +# Defined: build/soong/Blueprints:158:1 build .bootstrap/androidmk-parser/pkg/android/soong/androidmk/parser.a: $ g.bootstrap.gc $ @@ -295,12 +295,13 @@ build .bootstrap/soong-art/pkg/android/soong/art.a: g.bootstrap.gc $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a $ .bootstrap/soong-common/pkg/android/soong/common.a $ .bootstrap/soong-config/pkg/android/soong/config.a $ .bootstrap/soong-genrule/pkg/android/soong/genrule.a $ .bootstrap/soong-cc/pkg/android/soong/cc.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg pkgPath = android/soong/art default .bootstrap/soong-art/pkg/android/soong/art.a @@ -309,7 +310,7 @@ default .bootstrap/soong-art/pkg/android/soong/art.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:82:1 +# Defined: build/soong/Blueprints:104:1 build .bootstrap/soong-cc/pkg/android/soong/cc.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cc/builder.go $ @@ -327,11 +328,12 @@ build .bootstrap/soong-cc/pkg/android/soong/cc.a: g.bootstrap.gc $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a $ .bootstrap/soong-common/pkg/android/soong/common.a $ .bootstrap/soong-config/pkg/android/soong/config.a $ .bootstrap/soong-genrule/pkg/android/soong/genrule.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg pkgPath = android/soong/cc default .bootstrap/soong-cc/pkg/android/soong/cc.a @@ -340,12 +342,13 @@ default .bootstrap/soong-cc/pkg/android/soong/cc.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:51:1 +# Defined: build/soong/Blueprints:71:1 build .bootstrap/soong-common/pkg/android/soong/common.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/common/arch.go $ ${g.bootstrap.srcDir}/build/soong/common/checkbuild.go $ ${g.bootstrap.srcDir}/build/soong/common/defs.go $ + ${g.bootstrap.srcDir}/build/soong/common/env.go $ ${g.bootstrap.srcDir}/build/soong/common/glob.go $ ${g.bootstrap.srcDir}/build/soong/common/module.go $ ${g.bootstrap.srcDir}/build/soong/common/paths.go | $ @@ -356,8 +359,9 @@ build .bootstrap/soong-common/pkg/android/soong/common.a: g.bootstrap.gc $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg pkgPath = android/soong/common default .bootstrap/soong-common/pkg/android/soong/common.a @@ -366,7 +370,7 @@ default .bootstrap/soong-common/pkg/android/soong/common.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:69:1 +# Defined: build/soong/Blueprints:91:1 build .bootstrap/soong-config/pkg/android/soong/config.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/config/config.go | $ @@ -377,18 +381,31 @@ build .bootstrap/soong-config/pkg/android/soong/config.a: g.bootstrap.gc $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a $ .bootstrap/soong-common/pkg/android/soong/common.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg pkgPath = android/soong/config default .bootstrap/soong-config/pkg/android/soong/config.a +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Module: soong-env +# Variant: +# Type: bootstrap_go_package +# Factory: github.com/google/blueprint/bootstrap.newGoPackageModule +# Defined: build/soong/Blueprints:41:1 + +build .bootstrap/soong-env/pkg/android/soong/env.a: g.bootstrap.gc $ + ${g.bootstrap.srcDir}/build/soong/env/env.go | ${g.bootstrap.gcCmd} + pkgPath = android/soong/env +default .bootstrap/soong-env/pkg/android/soong/env.a + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Module: soong-genrule # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:106:1 +# Defined: build/soong/Blueprints:128:1 build .bootstrap/soong-genrule/pkg/android/soong/genrule.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/genrule/genrule.go | $ @@ -399,10 +416,11 @@ build .bootstrap/soong-genrule/pkg/android/soong/genrule.a: g.bootstrap.gc $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a $ .bootstrap/soong-common/pkg/android/soong/common.a $ .bootstrap/soong-config/pkg/android/soong/config.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg pkgPath = android/soong/genrule default .bootstrap/soong-genrule/pkg/android/soong/genrule.a @@ -411,7 +429,7 @@ default .bootstrap/soong-genrule/pkg/android/soong/genrule.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:40:1 +# Defined: build/soong/Blueprints:60:1 build .bootstrap/soong-glob/pkg/android/soong/glob.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/glob/glob.go | ${g.bootstrap.gcCmd} $ @@ -436,31 +454,54 @@ build .bootstrap/soong_build/obj/soong_build.a: g.bootstrap.gc $ .bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $ .bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $ .bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $ + .bootstrap/soong-env/pkg/android/soong/env.a $ .bootstrap/soong-glob/pkg/android/soong/glob.a $ .bootstrap/soong-common/pkg/android/soong/common.a $ .bootstrap/soong-config/pkg/android/soong/config.a $ .bootstrap/soong-genrule/pkg/android/soong/genrule.a $ .bootstrap/soong-cc/pkg/android/soong/cc.a $ .bootstrap/soong-art/pkg/android/soong/art.a - incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg -I .bootstrap/soong-art/pkg + incFlags = -I .bootstrap/blueprint-parser/pkg -I .bootstrap/blueprint-proptools/pkg -I .bootstrap/blueprint/pkg -I .bootstrap/blueprint-deptools/pkg -I .bootstrap/blueprint-pathtools/pkg -I .bootstrap/blueprint-bootstrap/pkg -I .bootstrap/soong-env/pkg -I .bootstrap/soong-glob/pkg -I .bootstrap/soong-common/pkg -I .bootstrap/soong-config/pkg -I .bootstrap/soong-genrule/pkg -I .bootstrap/soong-cc/pkg -I .bootstrap/soong-art/pkg pkgPath = soong_build default .bootstrap/soong_build/obj/soong_build.a build .bootstrap/soong_build/obj/a.out: g.bootstrap.link $ .bootstrap/soong_build/obj/soong_build.a | ${g.bootstrap.linkCmd} - libDirFlags = -L .bootstrap/blueprint-parser/pkg -L .bootstrap/blueprint-proptools/pkg -L .bootstrap/blueprint/pkg -L .bootstrap/blueprint-deptools/pkg -L .bootstrap/blueprint-pathtools/pkg -L .bootstrap/blueprint-bootstrap/pkg -L .bootstrap/soong-glob/pkg -L .bootstrap/soong-common/pkg -L .bootstrap/soong-config/pkg -L .bootstrap/soong-genrule/pkg -L .bootstrap/soong-cc/pkg -L .bootstrap/soong-art/pkg + libDirFlags = -L .bootstrap/blueprint-parser/pkg -L .bootstrap/blueprint-proptools/pkg -L .bootstrap/blueprint/pkg -L .bootstrap/blueprint-deptools/pkg -L .bootstrap/blueprint-pathtools/pkg -L .bootstrap/blueprint-bootstrap/pkg -L .bootstrap/soong-env/pkg -L .bootstrap/soong-glob/pkg -L .bootstrap/soong-common/pkg -L .bootstrap/soong-config/pkg -L .bootstrap/soong-genrule/pkg -L .bootstrap/soong-cc/pkg -L .bootstrap/soong-art/pkg default .bootstrap/soong_build/obj/a.out build .bootstrap/bin/soong_build: g.bootstrap.cp $ .bootstrap/soong_build/obj/a.out default .bootstrap/bin/soong_build +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Module: soong_env +# Variant: +# Type: bootstrap_go_binary +# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule +# Defined: build/soong/Blueprints:31:1 + +build .bootstrap/soong_env/obj/soong_env.a: g.bootstrap.gc $ + ${g.bootstrap.srcDir}/build/soong/cmd/soong_env/soong_env.go | $ + ${g.bootstrap.gcCmd} .bootstrap/soong-env/pkg/android/soong/env.a + incFlags = -I .bootstrap/soong-env/pkg + pkgPath = soong_env +default .bootstrap/soong_env/obj/soong_env.a + +build .bootstrap/soong_env/obj/a.out: g.bootstrap.link $ + .bootstrap/soong_env/obj/soong_env.a | ${g.bootstrap.linkCmd} + libDirFlags = -L .bootstrap/soong-env/pkg +default .bootstrap/soong_env/obj/a.out + +build .bootstrap/bin/soong_env: g.bootstrap.cp .bootstrap/soong_env/obj/a.out +default .bootstrap/bin/soong_env + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Module: soong_glob # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:30:1 +# Defined: build/soong/Blueprints:50:1 build .bootstrap/soong_glob/obj/soong_glob.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cmd/soong_glob/soong_glob.go | $ @@ -498,7 +539,8 @@ rule s.bootstrap.minibp build .bootstrap/main.ninja.in: s.bootstrap.bigbp $ ${g.bootstrap.srcDir}/Blueprints | .bootstrap/bin/androidmk $ .bootstrap/bin/bpfmt .bootstrap/bin/bpmodify .bootstrap/bin/minibp $ - .bootstrap/bin/soong_build .bootstrap/bin/soong_glob + .bootstrap/bin/soong_build .bootstrap/bin/soong_env $ + .bootstrap/bin/soong_glob default .bootstrap/main.ninja.in build .bootstrap/notAFile: phony default .bootstrap/notAFile diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index b84b804c1..cb579e9c9 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -64,6 +64,7 @@ func main() { // Singletons ctx.RegisterSingletonType("checkbuild", common.CheckbuildSingleton) + ctx.RegisterSingletonType("env", common.EnvSingleton) configuration, err := config.New(srcDir) if err != nil { diff --git a/cmd/soong_env/soong_env.go b/cmd/soong_env/soong_env.go new file mode 100644 index 000000000..933e525ae --- /dev/null +++ b/cmd/soong_env/soong_env.go @@ -0,0 +1,55 @@ +// 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. + +// soong_glob is the command line tool that checks if the list of files matching a glob has +// changed, and only updates the output file list if it has changed. It is used to optimize +// out build.ninja regenerations when non-matching files are added. See +// android/soong/common/glob.go for a longer description. +package main + +import ( + "flag" + "fmt" + "os" + + "android/soong/env" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: soong_env env_file\n") + fmt.Fprintf(os.Stderr, "exits with success if the environment varibles in env_file match\n") + fmt.Fprintf(os.Stderr, "the current environment\n") + flag.PrintDefaults() + os.Exit(2) +} + +func main() { + flag.Parse() + + if flag.NArg() != 1 { + usage() + } + + stale, err := env.StaleEnvFile(flag.Arg(0)) + if err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err.Error()) + os.Exit(1) + } + + if stale { + os.Exit(1) + } + + os.Exit(0) +} diff --git a/common/env.go b/common/env.go new file mode 100644 index 000000000..e33a0258b --- /dev/null +++ b/common/env.go @@ -0,0 +1,47 @@ +// 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. + +package common + +import ( + "android/soong/env" + + "github.com/google/blueprint" +) + +// This file supports dependencies on environment variables. During build manifest generation, +// any dependency on an environment variable is added to a list. During the singleton phase +// a JSON file is written containing the current value of all used environment variables. +// The next time the top-level build script is run, it uses the soong_env executable to +// compare the contents of the environment variables, rewriting the file if necessary to cause +// a manifest regeneration. + +func EnvSingleton() blueprint.Singleton { + return &envSingleton{} +} + +type envSingleton struct{} + +func (c *envSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) { + envDeps := ctx.Config().(Config).EnvDeps() + + envFile := ".soong.environment" + + err := env.WriteEnvFile(envFile, envDeps) + if err != nil { + ctx.Errorf(err.Error()) + } + + ctx.AddNinjaFileDeps(envFile) +} diff --git a/common/module.go b/common/module.go index 4b1200d3c..3cb4c09d5 100644 --- a/common/module.go +++ b/common/module.go @@ -20,6 +20,13 @@ import ( "github.com/google/blueprint" ) +type Config interface { + CpPreserveSymlinksFlags() string + SrcDir() string + Getenv(string) string + EnvDeps() map[string]string +} + var ( DeviceSharedLibrary = "shared_library" DeviceStaticLibrary = "static_library" diff --git a/common/paths.go b/common/paths.go index bc75ea59b..abe67bf52 100644 --- a/common/paths.go +++ b/common/paths.go @@ -20,11 +20,6 @@ import ( "github.com/google/blueprint" ) -type Config interface { - CpPreserveSymlinksFlags() string - SrcDir() string -} - // ModuleOutDir returns the path to the module-specific output directory. func ModuleOutDir(ctx AndroidModuleContext) string { return filepath.Join(".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) diff --git a/config/config.go b/config/config.go index 6cdc211e7..6cb61e4be 100644 --- a/config/config.go +++ b/config/config.go @@ -41,7 +41,8 @@ func NewFileConfigurableOptions() FileConfigurableOptions { type Config struct { FileConfigurableOptions - srcDir string // the path of the root source directory + srcDir string // the path of the root source directory + envDeps map[string]string } // loads configuration options from a JSON file in the cwd. @@ -103,7 +104,10 @@ func saveToConfigFile(config FileConfigurableOptions) error { // the root source directory. It also loads the config file, if found. func New(srcDir string) (*Config, error) { // Make a config with default options - config := &Config{srcDir: srcDir} + config := &Config{ + srcDir: srcDir, + envDeps: make(map[string]string), + } // Load any configurable options from the configuration file err := loadFromConfigFile(config) @@ -150,3 +154,17 @@ func (c *Config) CpPreserveSymlinksFlags() string { return "" } } + +func (c *Config) Getenv(key string) string { + var val string + var exists bool + if val, exists = c.envDeps[key]; !exists { + val = os.Getenv(key) + c.envDeps[key] = val + } + return val +} + +func (c *Config) EnvDeps() map[string]string { + return c.envDeps +} diff --git a/env/env.go b/env/env.go new file mode 100644 index 000000000..bf58a9914 --- /dev/null +++ b/env/env.go @@ -0,0 +1,97 @@ +// 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. + +// env implements the environment JSON file handling for the soong_env command line tool run before +// the builder and for the env writer in the builder. +package env + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "sort" +) + +type envFileEntry struct{ Key, Value string } +type envFileData []envFileEntry + +func WriteEnvFile(filename string, envDeps map[string]string) error { + contents := make(envFileData, 0, len(envDeps)) + for key, value := range envDeps { + contents = append(contents, envFileEntry{key, value}) + } + + sort.Sort(contents) + + data, err := json.MarshalIndent(contents, "", " ") + if err != nil { + return err + } + + data = append(data, '\n') + + err = ioutil.WriteFile(filename, data, 0664) + if err != nil { + return err + } + + return nil +} + +func StaleEnvFile(filename string) (bool, error) { + data, err := ioutil.ReadFile(filename) + if err != nil { + return true, err + } + + var contents envFileData + + err = json.Unmarshal(data, &contents) + if err != nil { + return true, err + } + + var changed []string + for _, entry := range contents { + key := entry.Key + old := entry.Value + cur := os.Getenv(key) + if old != cur { + changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur)) + } + } + + if len(changed) > 0 { + fmt.Printf("environment variables changed value:\n") + for _, s := range changed { + fmt.Printf(" %s\n", s) + } + return true, nil + } + + return false, nil +} + +func (e envFileData) Len() int { + return len(e) +} + +func (e envFileData) Less(i, j int) bool { + return e[i].Key < e[j].Key +} + +func (e envFileData) Swap(i, j int) { + e[i], e[j] = e[j], e[i] +} diff --git a/soong.bash b/soong.bash index fc330d0b1..fab15de5f 100755 --- a/soong.bash +++ b/soong.bash @@ -27,4 +27,21 @@ fi # can regenerate the build manifest. export BLUEPRINT_NINJA_HAS_MULTIPASS=1 +# Ninja can't depend on environment variables, so do a manual comparison +# of the relevant environment variables from the last build using the +# soong_env tool and trigger a build manifest regeneration if necessary +ENVFILE=${BUILDDIR}/.soong.environment +ENVTOOL=${BUILDDIR}/.bootstrap/bin/soong_env +if [ -f ${ENVFILE} ]; then + if [ -x ${ENVTOOL} ]; then + if ! ${ENVTOOL} ${ENVFILE}; then + echo "forcing build manifest regeneration" + rm -f ${ENVFILE} + fi + else + echo "Missing soong_env tool, forcing build manifest regeneration" + rm -f ${ENVFILE} + fi +fi + ${SRCDIR}/prebuilts/ninja/${PREBUILTOS}/ninja -C ${BUILDDIR} "$@"