blob: 4e700a2cd221e0f3d45acb661e20f2258c1b836b [file] [log] [blame]
Colin Crossef354482018-10-23 11:27:50 -07001// Copyright 2018 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
15package cc
16
17import (
18 "reflect"
Kiyoung Kim853e3912024-01-09 09:51:00 +090019 "slices"
Cole Faust7d345122025-03-06 12:45:53 -080020 "strings"
Colin Crossef354482018-10-23 11:27:50 -070021 "testing"
22
23 "android/soong/android"
24)
25
Colin Cross98be1bb2019-12-13 20:41:13 -080026func testGenruleContext(config android.Config) *android.TestContext {
Colin Crossae8600b2020-10-29 17:09:13 -070027 ctx := android.NewTestArchContext(config)
Wei Libcd39942021-09-16 23:57:28 +000028 ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
Colin Crossae8600b2020-10-29 17:09:13 -070029 ctx.Register()
Colin Crossef354482018-10-23 11:27:50 -070030
31 return ctx
32}
33
34func TestArchGenruleCmd(t *testing.T) {
Colin Cross98be1bb2019-12-13 20:41:13 -080035 fs := map[string][]byte{
36 "tool": nil,
37 "foo": nil,
38 "bar": nil,
39 }
Colin Crossef354482018-10-23 11:27:50 -070040 bp := `
41 cc_genrule {
42 name: "gen",
43 tool_files: ["tool"],
44 cmd: "$(location tool) $(in) $(out)",
Yu Liud6201012022-10-17 12:29:15 -070045 out: ["out_arm"],
Colin Crossef354482018-10-23 11:27:50 -070046 arch: {
47 arm: {
48 srcs: ["foo"],
Colin Crossef354482018-10-23 11:27:50 -070049 },
50 arm64: {
51 srcs: ["bar"],
Colin Crossef354482018-10-23 11:27:50 -070052 },
53 },
54 }
55 `
Paul Duffinc3e6ce02021-03-22 23:21:32 +000056 config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
Colin Crossef354482018-10-23 11:27:50 -070057
Colin Cross98be1bb2019-12-13 20:41:13 -080058 ctx := testGenruleContext(config)
Colin Crossef354482018-10-23 11:27:50 -070059
60 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
61 if errs == nil {
62 _, errs = ctx.PrepareBuildActions(config)
63 }
64 if errs != nil {
65 t.Fatal(errs)
66 }
67
Colin Cross90607e92025-02-11 14:58:07 -080068 gen := ctx.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").Output("out_arm")
Colin Crossef354482018-10-23 11:27:50 -070069 expected := []string{"foo"}
Colin Cross3d680512020-11-13 16:23:53 -080070 if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
71 t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
Colin Crossef354482018-10-23 11:27:50 -070072 }
73
Colin Cross90607e92025-02-11 14:58:07 -080074 gen = ctx.ModuleForTests(t, "gen", "android_arm64_armv8-a").Output("out_arm")
Colin Crossef354482018-10-23 11:27:50 -070075 expected = []string{"bar"}
Colin Cross3d680512020-11-13 16:23:53 -080076 if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
77 t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Implicits.Strings())
Colin Crossef354482018-10-23 11:27:50 -070078 }
79}
Colin Cross81ca6cd2020-08-06 17:46:48 -070080
81func TestLibraryGenruleCmd(t *testing.T) {
82 bp := `
83 cc_library {
84 name: "libboth",
85 }
86
87 cc_library_shared {
88 name: "libshared",
89 }
90
91 cc_library_static {
92 name: "libstatic",
93 }
94
95 cc_genrule {
96 name: "gen",
97 tool_files: ["tool"],
98 srcs: [
99 ":libboth",
100 ":libshared",
101 ":libstatic",
102 ],
103 cmd: "$(location tool) $(in) $(out)",
104 out: ["out"],
105 }
106 `
107 ctx := testCc(t, bp)
108
Colin Cross90607e92025-02-11 14:58:07 -0800109 gen := ctx.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").Output("out")
Colin Cross81ca6cd2020-08-06 17:46:48 -0700110 expected := []string{"libboth.so", "libshared.so", "libstatic.a"}
111 var got []string
Colin Cross3d680512020-11-13 16:23:53 -0800112 for _, input := range gen.Implicits {
Colin Cross81ca6cd2020-08-06 17:46:48 -0700113 got = append(got, input.Base())
114 }
Colin Cross3d680512020-11-13 16:23:53 -0800115 if !reflect.DeepEqual(expected, got[:len(expected)]) {
Colin Cross81ca6cd2020-08-06 17:46:48 -0700116 t.Errorf(`want inputs %v, got %v`, expected, got)
117 }
118}
Colin Crossf3bfd022021-09-27 15:15:06 -0700119
120func TestCmdPrefix(t *testing.T) {
121 bp := `
122 cc_genrule {
123 name: "gen",
124 cmd: "echo foo",
125 out: ["out"],
126 native_bridge_supported: true,
127 }
128 `
129
130 testCases := []struct {
131 name string
132 variant string
133 preparer android.FixturePreparer
134
135 arch string
136 nativeBridge string
137 multilib string
138 }{
139 {
140 name: "arm",
141 variant: "android_arm_armv7-a-neon",
142 arch: "arm",
143 multilib: "lib32",
144 },
145 {
146 name: "arm64",
147 variant: "android_arm64_armv8-a",
148 arch: "arm64",
149 multilib: "lib64",
150 },
151 {
152 name: "nativebridge",
153 variant: "android_native_bridge_arm_armv7-a-neon",
154 preparer: android.FixtureModifyConfig(func(config android.Config) {
155 config.Targets[android.Android] = []android.Target{
156 {
157 Os: android.Android,
158 Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
159 NativeBridge: android.NativeBridgeDisabled,
160 },
161 {
162 Os: android.Android,
163 Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
164 NativeBridge: android.NativeBridgeEnabled,
165 NativeBridgeHostArchName: "x86",
166 NativeBridgeRelativePath: "arm",
167 },
168 }
169 }),
170 arch: "arm",
171 multilib: "lib32",
172 nativeBridge: "arm",
173 },
174 }
175
176 for _, tt := range testCases {
177 t.Run(tt.name, func(t *testing.T) {
178 result := android.GroupFixturePreparers(
179 PrepareForIntegrationTestWithCc,
180 android.OptionalFixturePreparer(tt.preparer),
181 ).RunTestWithBp(t, bp)
Colin Cross90607e92025-02-11 14:58:07 -0800182 gen := result.ModuleForTests(t, "gen", tt.variant)
Colin Crossf61d03d2023-11-02 16:56:39 -0700183 sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
Colin Crossf3bfd022021-09-27 15:15:06 -0700184 cmd := *sboxProto.Commands[0].Command
185 android.AssertStringDoesContain(t, "incorrect CC_ARCH", cmd, "CC_ARCH="+tt.arch+" ")
186 android.AssertStringDoesContain(t, "incorrect CC_NATIVE_BRIDGE", cmd, "CC_NATIVE_BRIDGE="+tt.nativeBridge+" ")
187 android.AssertStringDoesContain(t, "incorrect CC_MULTILIB", cmd, "CC_MULTILIB="+tt.multilib+" ")
188 })
189 }
190}
Kiyoung Kim853e3912024-01-09 09:51:00 +0900191
192func TestVendorProductVariantGenrule(t *testing.T) {
193 bp := `
194 cc_genrule {
195 name: "gen",
196 tool_files: ["tool"],
197 cmd: "$(location tool) $(in) $(out)",
198 out: ["out"],
199 vendor_available: true,
200 product_available: true,
201 }
202 `
203 t.Helper()
Kiyoung Kim0d1c1e62024-03-26 16:33:58 +0900204 ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
Kiyoung Kim853e3912024-01-09 09:51:00 +0900205
206 variants := ctx.ModuleVariantsForTests("gen")
207 if !slices.Contains(variants, "android_vendor_arm64_armv8-a") {
208 t.Errorf(`expected vendor variant, but does not exist in %v`, variants)
209 }
210 if !slices.Contains(variants, "android_product_arm64_armv8-a") {
211 t.Errorf(`expected product variant, but does not exist in %v`, variants)
212 }
213}
kellyhung750334a2024-03-14 01:03:49 +0800214
215// cc_genrule is initialized to android.InitAndroidArchModule
216// that is an architecture-specific Android module.
217// So testing properties tagged with `android:"arch_variant"`
218// for cc_genrule.
219func TestMultilibGenruleOut(t *testing.T) {
220 bp := `
221 cc_genrule {
222 name: "gen",
223 cmd: "cp $(in) $(out)",
224 srcs: ["foo"],
225 multilib: {
226 lib32: {
227 out: [
228 "subdir32/external-module32",
229 ],
230 },
231 lib64: {
232 out: [
233 "subdir64/external-module64",
234 ],
235 },
236 },
237 }
238 `
239 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
Colin Cross90607e92025-02-11 14:58:07 -0800240 gen_32bit := result.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").OutputFiles(result.TestContext, t, "")
kellyhung750334a2024-03-14 01:03:49 +0800241 android.AssertPathsEndWith(t,
242 "genrule_out",
243 []string{
244 "subdir32/external-module32",
245 },
246 gen_32bit,
247 )
248
Colin Cross90607e92025-02-11 14:58:07 -0800249 gen_64bit := result.ModuleForTests(t, "gen", "android_arm64_armv8-a").OutputFiles(result.TestContext, t, "")
kellyhung750334a2024-03-14 01:03:49 +0800250 android.AssertPathsEndWith(t,
251 "genrule_out",
252 []string{
253 "subdir64/external-module64",
254 },
255 gen_64bit,
256 )
257}
Cole Faust7d345122025-03-06 12:45:53 -0800258
259// Test that a genrule can depend on a tool with symlinks. The symlinks are ignored, but
260// at least it doesn't cause errors.
261func TestGenruleToolWithSymlinks(t *testing.T) {
262 bp := `
263 genrule {
264 name: "gen",
265 tools: ["tool_with_symlinks"],
266 cmd: "$(location tool_with_symlinks) $(in) $(out)",
267 out: ["out"],
268 }
269
270 cc_binary_host {
271 name: "tool_with_symlinks",
272 symlinks: ["symlink1", "symlink2"],
273 }
274 `
275 ctx := PrepareForIntegrationTestWithCc.
276 ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
277 RunTestWithBp(t, bp)
278 gen := ctx.ModuleForTests(t, "gen", "").Output("out")
279 toolFound := false
280 symlinkFound := false
281 for _, dep := range gen.RuleParams.CommandDeps {
282 if strings.HasSuffix(dep, "/tool_with_symlinks") {
283 toolFound = true
284 }
285 if strings.HasSuffix(dep, "/symlink1") || strings.HasSuffix(dep, "/symlink2") {
286 symlinkFound = true
287 }
288 }
289 if !toolFound {
290 t.Errorf("Tool not found")
291 }
292 // We may want to change genrules to include symlinks later
293 if symlinkFound {
294 t.Errorf("Symlinks found")
295 }
296}