123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- // 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 android
- import (
- "fmt"
- "strings"
- "testing"
- "github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/proptools"
- )
- var (
- pctx = NewPackageContext("android/soong/android")
- exportedVars = NewExportedVariables(pctx)
- cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
- Config.CpPreserveSymlinksFlags)
- // A phony rule that is not the built-in Ninja phony rule. The built-in
- // phony rule has special behavior that is sometimes not desired. See the
- // Ninja docs for more details.
- Phony = pctx.AndroidStaticRule("Phony",
- blueprint.RuleParams{
- Command: "# phony $out",
- Description: "phony $out",
- })
- // GeneratedFile is a rule for indicating that a given file was generated
- // while running soong. This allows the file to be cleaned up if it ever
- // stops being generated by soong.
- GeneratedFile = pctx.AndroidStaticRule("GeneratedFile",
- blueprint.RuleParams{
- Command: "# generated $out",
- Description: "generated $out",
- Generator: true,
- })
- // A copy rule.
- Cp = pctx.AndroidStaticRule("Cp",
- blueprint.RuleParams{
- Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out$extraCmds",
- Description: "cp $out",
- },
- "cpFlags", "extraCmds")
- // A copy rule that doesn't preserve symlinks.
- CpNoPreserveSymlink = pctx.AndroidStaticRule("CpNoPreserveSymlink",
- blueprint.RuleParams{
- Command: "rm -f $out && cp $cpFlags $in $out$extraCmds",
- Description: "cp $out",
- },
- "cpFlags", "extraCmds")
- // A copy rule that only updates the output if it changed.
- CpIfChanged = pctx.AndroidStaticRule("CpIfChanged",
- blueprint.RuleParams{
- Command: "if ! cmp -s $in $out; then cp $in $out; fi",
- Description: "cp if changed $out",
- Restat: true,
- },
- "cpFlags")
- CpExecutable = pctx.AndroidStaticRule("CpExecutable",
- blueprint.RuleParams{
- Command: "rm -f $out && cp $cpFlags $in $out && chmod +x $out$extraCmds",
- Description: "cp $out",
- },
- "cpFlags", "extraCmds")
- // A timestamp touch rule.
- Touch = pctx.AndroidStaticRule("Touch",
- blueprint.RuleParams{
- Command: "touch $out",
- Description: "touch $out",
- })
- // A symlink rule.
- Symlink = pctx.AndroidStaticRule("Symlink",
- blueprint.RuleParams{
- Command: "rm -f $out && ln -f -s $fromPath $out",
- Description: "symlink $out",
- SymlinkOutputs: []string{"$out"},
- },
- "fromPath")
- ErrorRule = pctx.AndroidStaticRule("Error",
- blueprint.RuleParams{
- Command: `echo "$error" && false`,
- Description: "error building $out",
- },
- "error")
- Cat = pctx.AndroidStaticRule("Cat",
- blueprint.RuleParams{
- Command: "cat $in > $out",
- Description: "concatenate licenses $out",
- })
- // ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
- // doesn't support -e option. Therefore we force to use /bin/bash when writing out
- // content to file.
- writeFile = pctx.AndroidStaticRule("writeFile",
- blueprint.RuleParams{
- Command: `/bin/bash -c 'echo -e -n "$$0" > $out' $content`,
- Description: "writing file $out",
- },
- "content")
- // Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
- localPool = blueprint.NewBuiltinPool("local_pool")
- // Used only by RuleBuilder to identify remoteable rules. Does not actually get created in ninja.
- remotePool = blueprint.NewBuiltinPool("remote_pool")
- // Used for processes that need significant RAM to ensure there are not too many running in parallel.
- highmemPool = blueprint.NewBuiltinPool("highmem_pool")
- )
- func init() {
- pctx.Import("github.com/google/blueprint/bootstrap")
- pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
- return ctx.Config().RBEWrapper()
- })
- exportedVars.ExportStringList("NeverAllowNotInIncludeDir", neverallowNotInIncludeDir)
- exportedVars.ExportStringList("NeverAllowNoUseIncludeDir", neverallowNoUseIncludeDir)
- }
- func BazelCcToolchainVars(config Config) string {
- return BazelToolchainVars(config, exportedVars)
- }
- var (
- // echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
- echoEscaper = strings.NewReplacer(
- `\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
- "\n", `\n`, // Then replace newlines with \n
- )
- // echoEscaper reverses echoEscaper.
- echoUnescaper = strings.NewReplacer(
- `\n`, "\n",
- `\\`, `\`,
- )
- // shellUnescaper reverses the replacer in proptools.ShellEscape
- shellUnescaper = strings.NewReplacer(`'\''`, `'`)
- )
- func buildWriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- content = echoEscaper.Replace(content)
- content = proptools.NinjaEscape(proptools.ShellEscapeIncludingSpaces(content))
- if content == "" {
- content = "''"
- }
- ctx.Build(pctx, BuildParams{
- Rule: writeFile,
- Output: outputFile,
- Description: "write " + outputFile.Base(),
- Args: map[string]string{
- "content": content,
- },
- })
- }
- // WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
- // so that the file contains exactly the contents passed to the function, plus a trailing newline.
- func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- WriteFileRuleVerbatim(ctx, outputFile, content+"\n")
- }
- // WriteFileRuleVerbatim creates a ninja rule to write contents to a file. The contents will be
- // escaped so that the file contains exactly the contents passed to the function.
- func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- // This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
- const SHARD_SIZE = 131072 - 10000
- if len(content) > SHARD_SIZE {
- var chunks WritablePaths
- for i, c := range ShardString(content, SHARD_SIZE) {
- tempPath := outputFile.ReplaceExtension(ctx, fmt.Sprintf("%s.%d", outputFile.Ext(), i))
- buildWriteFileRule(ctx, tempPath, c)
- chunks = append(chunks, tempPath)
- }
- ctx.Build(pctx, BuildParams{
- Rule: Cat,
- Inputs: chunks.Paths(),
- Output: outputFile,
- Description: "Merging to " + outputFile.Base(),
- })
- return
- }
- buildWriteFileRule(ctx, outputFile, content)
- }
- func CatFileRule(ctx BuilderContext, paths Paths, outputFile WritablePath) {
- ctx.Build(pctx, BuildParams{
- Rule: Cat,
- Inputs: paths,
- Output: outputFile,
- Description: "combine files to " + outputFile.Base(),
- })
- }
- // shellUnescape reverses proptools.ShellEscape
- func shellUnescape(s string) string {
- // Remove leading and trailing quotes if present
- if len(s) >= 2 && s[0] == '\'' {
- s = s[1 : len(s)-1]
- }
- s = shellUnescaper.Replace(s)
- return s
- }
- // ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
- // in tests.
- func ContentFromFileRuleForTests(t *testing.T, params TestingBuildParams) string {
- t.Helper()
- if g, w := params.Rule, writeFile; g != w {
- t.Errorf("expected params.Rule to be %q, was %q", w, g)
- return ""
- }
- content := params.Args["content"]
- content = shellUnescape(content)
- content = echoUnescaper.Replace(content)
- return content
- }
- // GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
- func GlobToListFileRule(ctx ModuleContext, pattern string, excludes []string, file WritablePath) {
- bootstrap.GlobFile(ctx.blueprintModuleContext(), pattern, excludes, file.String())
- }
|