blob: 631dfe8f82c620596afe9189ad8fc7873198eac8 [file] [log] [blame]
Colin Cross3f40fa42015-01-30 17:27:36 -08001// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Colin Cross3f40fa42015-01-30 17:27:36 -080016
17import (
Colin Crosscf371cc2020-11-13 11:48:42 -080018 "strings"
19 "testing"
20
Colin Cross70b40592015-03-23 12:57:34 -070021 "github.com/google/blueprint"
Dan Willemsen24f2f8d2015-07-15 14:34:02 -070022 _ "github.com/google/blueprint/bootstrap"
Colin Crosscf371cc2020-11-13 11:48:42 -080023 "github.com/google/blueprint/proptools"
Colin Cross3f40fa42015-01-30 17:27:36 -080024)
25
26var (
Colin Crosscc0ce802019-04-02 16:14:11 -070027 pctx = NewPackageContext("android/soong/android")
Colin Cross3f40fa42015-01-30 17:27:36 -080028
29 cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
30 Config.CpPreserveSymlinksFlags)
31
Colin Cross3f40fa42015-01-30 17:27:36 -080032 // A phony rule that is not the built-in Ninja phony rule. The built-in
33 // phony rule has special behavior that is sometimes not desired. See the
34 // Ninja docs for more details.
Colin Cross9d45bb72016-08-29 16:14:13 -070035 Phony = pctx.AndroidStaticRule("Phony",
Colin Cross3f40fa42015-01-30 17:27:36 -080036 blueprint.RuleParams{
37 Command: "# phony $out",
38 Description: "phony $out",
39 })
40
41 // GeneratedFile is a rule for indicating that a given file was generated
42 // while running soong. This allows the file to be cleaned up if it ever
43 // stops being generated by soong.
Colin Cross9d45bb72016-08-29 16:14:13 -070044 GeneratedFile = pctx.AndroidStaticRule("GeneratedFile",
Colin Cross3f40fa42015-01-30 17:27:36 -080045 blueprint.RuleParams{
46 Command: "# generated $out",
47 Description: "generated $out",
48 Generator: true,
49 })
50
51 // A copy rule.
Colin Cross9d45bb72016-08-29 16:14:13 -070052 Cp = pctx.AndroidStaticRule("Cp",
Colin Cross3f40fa42015-01-30 17:27:36 -080053 blueprint.RuleParams{
Josh Gaoae152712017-07-26 14:09:50 -070054 Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out",
Colin Cross3f40fa42015-01-30 17:27:36 -080055 Description: "cp $out",
56 },
57 "cpFlags")
58
Colin Cross5c517922017-08-31 12:29:17 -070059 CpExecutable = pctx.AndroidStaticRule("CpExecutable",
60 blueprint.RuleParams{
61 Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out && chmod +x $out",
62 Description: "cp $out",
63 },
64 "cpFlags")
65
Dan Albert5d723ab2016-07-18 22:29:52 -070066 // A timestamp touch rule.
Colin Cross9d45bb72016-08-29 16:14:13 -070067 Touch = pctx.AndroidStaticRule("Touch",
Dan Albert5d723ab2016-07-18 22:29:52 -070068 blueprint.RuleParams{
69 Command: "touch $out",
70 Description: "touch $out",
71 })
72
Colin Cross3f40fa42015-01-30 17:27:36 -080073 // A symlink rule.
Colin Cross9d45bb72016-08-29 16:14:13 -070074 Symlink = pctx.AndroidStaticRule("Symlink",
Colin Cross3f40fa42015-01-30 17:27:36 -080075 blueprint.RuleParams{
Jingwen Chence679d22020-09-23 04:30:02 +000076 Command: "rm -f $out && ln -f -s $fromPath $out",
77 Description: "symlink $out",
78 SymlinkOutputs: []string{"$out"},
Colin Cross3f40fa42015-01-30 17:27:36 -080079 },
80 "fromPath")
Colin Cross6ff51382015-12-17 16:39:19 -080081
Colin Cross9d45bb72016-08-29 16:14:13 -070082 ErrorRule = pctx.AndroidStaticRule("Error",
Colin Cross6ff51382015-12-17 16:39:19 -080083 blueprint.RuleParams{
84 Command: `echo "$error" && false`,
85 Description: "error building $out",
86 },
87 "error")
Colin Cross9d45bb72016-08-29 16:14:13 -070088
Dan Albertc6345fb2016-10-20 01:36:11 -070089 Cat = pctx.AndroidStaticRule("Cat",
90 blueprint.RuleParams{
91 Command: "cat $in > $out",
92 Description: "concatenate licenses $out",
93 })
94
Nan Zhang27005112017-05-12 14:02:13 -070095 // ubuntu 14.04 offcially use dash for /bin/sh, and its builtin echo command
96 // doesn't support -e option. Therefore we force to use /bin/bash when writing out
97 // content to file.
Colin Crosscf371cc2020-11-13 11:48:42 -080098 writeFile = pctx.AndroidStaticRule("writeFile",
Dan Albert30c9d6e2017-03-28 14:54:55 -070099 blueprint.RuleParams{
Colin Crosscf371cc2020-11-13 11:48:42 -0800100 Command: `/bin/bash -c 'echo -e "$$0" > $out' $content`,
Dan Albert30c9d6e2017-03-28 14:54:55 -0700101 Description: "writing file $out",
102 },
103 "content")
104
Colin Cross9d45bb72016-08-29 16:14:13 -0700105 // Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
106 localPool = blueprint.NewBuiltinPool("local_pool")
Colin Cross8b8bec32019-11-15 13:18:43 -0800107
Ramy Medhat944839a2020-03-31 22:14:52 -0400108 // Used only by RuleBuilder to identify remoteable rules. Does not actually get created in ninja.
109 remotePool = blueprint.NewBuiltinPool("remote_pool")
110
Colin Cross8b8bec32019-11-15 13:18:43 -0800111 // Used for processes that need significant RAM to ensure there are not too many running in parallel.
112 highmemPool = blueprint.NewBuiltinPool("highmem_pool")
Colin Cross3f40fa42015-01-30 17:27:36 -0800113)
Dan Willemsen24f2f8d2015-07-15 14:34:02 -0700114
115func init() {
116 pctx.Import("github.com/google/blueprint/bootstrap")
117}
Colin Crosscf371cc2020-11-13 11:48:42 -0800118
119var (
120 // echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
121 echoEscaper = strings.NewReplacer(
122 `\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
123 "\n", `\n`, // Then replace newlines with \n
124 )
125
126 // echoEscaper reverses echoEscaper.
127 echoUnescaper = strings.NewReplacer(
128 `\n`, "\n",
129 `\\`, `\`,
130 )
131
132 // shellUnescaper reverses the replacer in proptools.ShellEscape
133 shellUnescaper = strings.NewReplacer(`'\''`, `'`)
134)
135
136// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
137// so that the file contains exactly the contents passed to the function, plus a trailing newline.
138func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
139 content = echoEscaper.Replace(content)
140 content = proptools.ShellEscape(content)
141 if content == "" {
142 content = "''"
143 }
144 ctx.Build(pctx, BuildParams{
145 Rule: writeFile,
146 Output: outputFile,
147 Description: "write " + outputFile.Base(),
148 Args: map[string]string{
149 "content": content,
150 },
151 })
152}
153
154// shellUnescape reverses proptools.ShellEscape
155func shellUnescape(s string) string {
156 // Remove leading and trailing quotes if present
157 if len(s) >= 2 && s[0] == '\'' {
158 s = s[1 : len(s)-1]
159 }
160 s = shellUnescaper.Replace(s)
161 return s
162}
163
164// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
165// in tests.
166func ContentFromFileRuleForTests(t *testing.T, params TestingBuildParams) string {
167 t.Helper()
168 if g, w := params.Rule, writeFile; g != w {
169 t.Errorf("expected params.Rule to be %q, was %q", w, g)
170 return ""
171 }
172
173 content := params.Args["content"]
174 content = shellUnescape(content)
175 content = echoUnescaper.Replace(content)
176
177 return content
178}