diff options
| author | Colin Cross <ccross@android.com> | 2015-01-30 17:27:36 -0800 |
|---|---|---|
| committer | Colin Cross <ccross@android.com> | 2015-03-13 20:28:16 -0700 |
| commit | 3f40fa460d85b10646d383a3b6b01ea6d569b01b (patch) | |
| tree | 542d913a3f0f818042b503948869818a77e99ebc /common/glob.go | |
| parent | e441b9df9a68595d0dd7b8ed184aecb27c86054b (diff) | |
| download | build_soong-3f40fa460d85b10646d383a3b6b01ea6d569b01b.tar.gz build_soong-3f40fa460d85b10646d383a3b6b01ea6d569b01b.tar.bz2 build_soong-3f40fa460d85b10646d383a3b6b01ea6d569b01b.zip | |
Add soong_build primary builder
Initial build logic for building android with soong. It can build
a variety of C and C++ files for arm/arm64 and host.
Change-Id: I10eb37c2c2a50be6af1bb5fd568c0962b9476bf0
Diffstat (limited to 'common/glob.go')
| -rw-r--r-- | common/glob.go | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/common/glob.go b/common/glob.go new file mode 100644 index 00000000..9aada958 --- /dev/null +++ b/common/glob.go @@ -0,0 +1,133 @@ +// 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 ( + "fmt" + "path/filepath" + + "blueprint" + "blueprint/bootstrap" + + "android/soong/glob" +) + +// This file supports globbing source files in Blueprints files. +// +// The build.ninja file needs to be regenerated any time a file matching the glob is added +// or removed. The naive solution is to have the build.ninja file depend on all the +// traversed directories, but this will cause the regeneration step to run every time a +// non-matching file is added to a traversed directory, including backup files created by +// editors. +// +// The solution implemented here optimizes out regenerations when the directory modifications +// don't match the glob by having the build.ninja file depend on an intermedate file that +// is only updated when a file matching the glob is added or removed. The intermediate file +// depends on the traversed directories via a depfile. The depfile is used to avoid build +// errors if a directory is deleted - a direct dependency on the deleted directory would result +// in a build failure with a "missing and no known rule to make it" error. + +var ( + globCmd = filepath.Join(bootstrap.BinDir, "soong_glob") + + // globRule rule traverses directories to produce a list of files that match $glob + // and writes it to $out if it has changed, and writes the directories to $out.d + globRule = pctx.StaticRule("globRule", + blueprint.RuleParams{ + Command: fmt.Sprintf(`%s -o $out "$glob"`, globCmd), + Description: "glob $glob", + + Restat: true, + Generator: true, + Deps: blueprint.DepsGCC, + Depfile: "$out.d", + }, + "glob") +) + +func hasGlob(in []string) bool { + for _, s := range in { + if glob.IsGlob(s) { + return true + } + } + + return false +} + +func ExpandGlobs(ctx AndroidModuleContext, in []string) []string { + if !hasGlob(in) { + return in + } + + out := make([]string, 0, len(in)) + for _, s := range in { + if glob.IsGlob(s) { + out = append(out, Glob(ctx, s)...) + } else { + out = append(out, s) + } + } + + return out +} + +func Glob(ctx AndroidModuleContext, globPattern string) []string { + fileListFile := filepath.Join(ModuleOutDir(ctx), "glob", globToString(globPattern)) + depFile := fileListFile + ".d" + + // Get a globbed file list, and write out fileListFile and depFile + files, err := glob.GlobWithDepFile(globPattern, fileListFile, depFile) + if err != nil { + ctx.ModuleErrorf("glob: %s", err.Error()) + return []string{globPattern} + } + + // Create a rule to rebuild fileListFile if a directory in depFile changes. fileListFile + // will only be rewritten if it has changed, preventing unnecesary build.ninja regenerations. + ctx.Build(pctx, blueprint.BuildParams{ + Rule: globRule, + Outputs: []string{fileListFile}, + Implicits: []string{globCmd}, + Args: map[string]string{ + "glob": globPattern, + }, + }) + + // Phony rule so the cleanup phase doesn't delete the depFile + ctx.Build(pctx, blueprint.BuildParams{ + Rule: blueprint.Phony, + Outputs: []string{depFile}, + }) + + // Make build.ninja depend on the fileListFile + ctx.AddNinjaFileDeps(fileListFile) + + return files +} + +func globToString(glob string) string { + ret := "" + for _, c := range glob { + if c >= 'a' && c <= 'z' || + c >= 'A' && c <= 'Z' || + c >= '0' && c <= '9' || + c == '_' || c == '-' || c == '/' { + ret += string(c) + } + } + + return ret +} |
