blob: 4caa12b3ea345ba0bab4877106820e56c3fca8cf [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// Copyright 2019 The Android Open Source Project
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 rust
16
17import (
18 "strings"
19 "testing"
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +020020
21 "android/soong/android"
Ivan Lozanoffee3342019-08-27 12:03:00 -070022)
23
24// Test that feature flags are being correctly generated.
25func TestFeaturesToFlags(t *testing.T) {
26 ctx := testRust(t, `
27 rust_library_host_dylib {
28 name: "libfoo",
29 srcs: ["foo.rs"],
30 crate_name: "foo",
31 features: [
32 "fizz",
33 "buzz"
34 ],
35 }`)
36
37 libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
38
Wen-yi Chu41326c12023-09-22 03:58:59 +000039 if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") ||
40 !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") {
41 t.Fatalf("missing fizz and buzz feature flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
Ivan Lozanoffee3342019-08-27 12:03:00 -070042 }
43}
44
Thiébaud Weksteenc44e7372021-04-07 14:53:06 +020045// Test that cfgs flags are being correctly generated.
46func TestCfgsToFlags(t *testing.T) {
47 ctx := testRust(t, `
48 rust_library_host {
49 name: "libfoo",
50 srcs: ["foo.rs"],
51 crate_name: "foo",
52 cfgs: [
53 "std",
54 "cfg1=\"one\""
55 ],
56 }`)
57
58 libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
59
Wen-yi Chu41326c12023-09-22 03:58:59 +000060 if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") ||
61 !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") {
62 t.Fatalf("missing std and cfg1 flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
Thiébaud Weksteenc44e7372021-04-07 14:53:06 +020063 }
64}
65
Ivan Lozanoab586472024-05-15 10:59:47 -040066func TestLtoFlag(t *testing.T) {
67 ctx := testRust(t, `
68 rust_library_host {
69 name: "libfoo",
70 srcs: ["foo.rs"],
71 crate_name: "foo",
72 lto: {
73 thin: false,
74 }
75 }
76
77 rust_library_host {
78 name: "libfoo_lto",
79 srcs: ["foo.rs"],
80 crate_name: "foo",
81 }
82 `)
83
84 libfoo := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
85 libfooLto := ctx.ModuleForTests("libfoo_lto", "linux_glibc_x86_64_dylib").Rule("rustc")
86
87 if strings.Contains(libfoo.Args["rustcFlags"], "-C lto=thin") {
88 t.Fatalf("libfoo expected to disable lto -- rustcFlags: %#v", libfoo.Args["rustcFlags"])
89 }
90 if !strings.Contains(libfooLto.Args["rustcFlags"], "-C lto=thin") {
91 t.Fatalf("libfoo expected to enable lto by default -- rustcFlags: %#v", libfooLto.Args["rustcFlags"])
92 }
93}
94
Ivan Lozanoffee3342019-08-27 12:03:00 -070095// Test that we reject multiple source files.
96func TestEnforceSingleSourceFile(t *testing.T) {
97
Ivan Lozano43845682020-07-09 21:03:28 -040098 singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
Matthew Maurer1d8e20d2023-11-20 21:18:12 +000099 prebuiltSingleSrcError := "prebuilt libraries can only have one entry in srcs"
Ivan Lozanoffee3342019-08-27 12:03:00 -0700100
101 // Test libraries
102 testRustError(t, singleSrcError, `
103 rust_library_host {
104 name: "foo-bar-library",
105 srcs: ["foo.rs", "src/bar.rs"],
106 }`)
107
108 // Test binaries
109 testRustError(t, singleSrcError, `
110 rust_binary_host {
111 name: "foo-bar-binary",
112 srcs: ["foo.rs", "src/bar.rs"],
113 }`)
114
115 // Test proc_macros
116 testRustError(t, singleSrcError, `
117 rust_proc_macro {
118 name: "foo-bar-proc-macro",
119 srcs: ["foo.rs", "src/bar.rs"],
Ivan Lozanoffee3342019-08-27 12:03:00 -0700120 }`)
121
122 // Test prebuilts
Matthew Maurer1d8e20d2023-11-20 21:18:12 +0000123 testRustError(t, prebuiltSingleSrcError, `
Ivan Lozanoffee3342019-08-27 12:03:00 -0700124 rust_prebuilt_dylib {
125 name: "foo-bar-prebuilt",
126 srcs: ["liby.so", "libz.so"],
127 host_supported: true,
128 }`)
129}
Ivan Lozanof900f4b2020-04-28 13:58:45 -0400130
Seth Moore3afac0b2021-10-13 15:32:18 -0700131// Test that we reject _no_ source files.
132func TestEnforceMissingSourceFiles(t *testing.T) {
133
134 singleSrcError := "srcs must not be empty"
135
136 // Test libraries
137 testRustError(t, singleSrcError, `
138 rust_library_host {
139 name: "foo-bar-library",
140 crate_name: "foo",
141 }`)
142
143 // Test binaries
144 testRustError(t, singleSrcError, `
145 rust_binary_host {
146 name: "foo-bar-binary",
147 crate_name: "foo",
148 }`)
149
150 // Test proc_macros
151 testRustError(t, singleSrcError, `
152 rust_proc_macro {
153 name: "foo-bar-proc-macro",
154 crate_name: "foo",
155 }`)
156
157 // Test prebuilts
158 testRustError(t, singleSrcError, `
159 rust_prebuilt_dylib {
160 name: "foo-bar-prebuilt",
161 crate_name: "foo",
162 host_supported: true,
163 }`)
164}
165
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400166// Test environment vars for Cargo compat are set.
167func TestCargoCompat(t *testing.T) {
168 ctx := testRust(t, `
169 rust_binary {
170 name: "fizz",
171 srcs: ["foo.rs"],
172 crate_name: "foo",
173 cargo_env_compat: true,
174 cargo_pkg_version: "1.0.0"
175 }`)
176
177 fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
178
Wen-yi Chu41326c12023-09-22 03:58:59 +0000179 if !strings.Contains(fizz.Args["envVars"], "CARGO_BIN_NAME=fizz") {
180 t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400181 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000182 if !strings.Contains(fizz.Args["envVars"], "CARGO_CRATE_NAME=foo") {
183 t.Fatalf("expected 'CARGO_CRATE_NAME=foo' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400184 }
Wen-yi Chu41326c12023-09-22 03:58:59 +0000185 if !strings.Contains(fizz.Args["envVars"], "CARGO_PKG_VERSION=1.0.0") {
186 t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' in envVars, actual envVars: %#v", fizz.Args["envVars"])
Ivan Lozanoa9a1fc02021-08-11 15:13:43 -0400187 }
188}
189
Ivan Lozanof900f4b2020-04-28 13:58:45 -0400190func TestInstallDir(t *testing.T) {
191 ctx := testRust(t, `
192 rust_library_dylib {
193 name: "libfoo",
194 srcs: ["foo.rs"],
195 crate_name: "foo",
196 }
197 rust_binary {
198 name: "fizzbuzz",
199 srcs: ["foo.rs"],
200 }`)
201
202 install_path_lib64 := ctx.ModuleForTests("libfoo",
203 "android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
204 install_path_lib32 := ctx.ModuleForTests("libfoo",
205 "android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
206 install_path_bin := ctx.ModuleForTests("fizzbuzz",
207 "android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String()
208
209 if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") {
210 t.Fatalf("unexpected install path for 64-bit library: %#v", install_path_lib64)
211 }
212 if !strings.HasSuffix(install_path_lib32, "system/lib/libfoo.dylib.so") {
213 t.Fatalf("unexpected install path for 32-bit library: %#v", install_path_lib32)
214 }
215 if !strings.HasSuffix(install_path_bin, "system/bin/fizzbuzz") {
216 t.Fatalf("unexpected install path for binary: %#v", install_path_bin)
217 }
218}
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200219
220func TestLints(t *testing.T) {
221
222 bp := `
223 // foo uses the default value of lints
224 rust_library {
225 name: "libfoo",
226 srcs: ["foo.rs"],
227 crate_name: "foo",
228 }
229 // bar forces the use of the "android" lint set
230 rust_library {
231 name: "libbar",
232 srcs: ["foo.rs"],
233 crate_name: "bar",
234 lints: "android",
235 }
236 // foobar explicitly disable all lints
237 rust_library {
238 name: "libfoobar",
239 srcs: ["foo.rs"],
240 crate_name: "foobar",
241 lints: "none",
242 }`
243
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200244 var lintTests = []struct {
245 modulePath string
246 fooFlags string
247 }{
248 {"", "${config.RustDefaultLints}"},
249 {"external/", "${config.RustAllowAllLints}"},
250 {"hardware/", "${config.RustVendorLints}"},
251 }
252
253 for _, tc := range lintTests {
254 t.Run("path="+tc.modulePath, func(t *testing.T) {
255
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100256 result := android.GroupFixturePreparers(
257 prepareForRustTest,
258 // Test with the blueprint file in different directories.
259 android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
260 ).RunTest(t)
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200261
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100262 r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000263 android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags)
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200264
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100265 r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000266 android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}")
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200267
Paul Duffin9e0c3f92021-03-30 22:45:21 +0100268 r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
Wen-yi Chu41326c12023-09-22 03:58:59 +0000269 android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
Thiébaud Weksteen9e8451e2020-08-13 12:55:59 +0200270 })
271 }
272}
Ivan Lozano042504f2020-08-18 14:31:23 -0400273
274// Test that devices are linking the stdlib dynamically
275func TestStdDeviceLinkage(t *testing.T) {
276 ctx := testRust(t, `
277 rust_binary {
278 name: "fizz",
279 srcs: ["foo.rs"],
280 }
281 rust_library {
282 name: "libfoo",
283 srcs: ["foo.rs"],
284 crate_name: "foo",
285 }`)
286 fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
Ivan Lozano2b081132020-09-08 12:46:52 -0400287 fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
Ivan Lozano042504f2020-08-18 14:31:23 -0400288 fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
289
290 if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) {
291 t.Errorf("libstd is not linked dynamically for device binaries")
292 }
293 if !android.InList("libstd", fooRlib.Properties.AndroidMkDylibs) {
294 t.Errorf("libstd is not linked dynamically for rlibs")
295 }
296 if !android.InList("libstd", fooDylib.Properties.AndroidMkDylibs) {
297 t.Errorf("libstd is not linked dynamically for dylibs")
298 }
299}
Ivan Lozano45a9e312021-07-27 12:29:12 -0400300
301// Ensure that manual link flags are disallowed.
302func TestManualLinkageRejection(t *testing.T) {
303 // rustc flags
304 testRustError(t, ".* cannot be manually specified", `
305 rust_binary {
306 name: "foo",
307 srcs: [
308 "foo.rs",
309 ],
310 flags: ["-lbar"],
311 }
312 `)
313 testRustError(t, ".* cannot be manually specified", `
314 rust_binary {
315 name: "foo",
316 srcs: [
317 "foo.rs",
318 ],
319 flags: ["--extern=foo"],
320 }
321 `)
322 testRustError(t, ".* cannot be manually specified", `
323 rust_binary {
324 name: "foo",
325 srcs: [
326 "foo.rs",
327 ],
328 flags: ["-Clink-args=foo"],
329 }
330 `)
331 testRustError(t, ".* cannot be manually specified", `
332 rust_binary {
333 name: "foo",
334 srcs: [
335 "foo.rs",
336 ],
337 flags: ["-C link-args=foo"],
338 }
339 `)
340 testRustError(t, ".* cannot be manually specified", `
341 rust_binary {
342 name: "foo",
343 srcs: [
344 "foo.rs",
345 ],
346 flags: ["-L foo/"],
347 }
348 `)
349
350 // lld flags
351 testRustError(t, ".* cannot be manually specified", `
352 rust_binary {
353 name: "foo",
354 srcs: [
355 "foo.rs",
356 ],
357 ld_flags: ["-Wl,-L bar/"],
358 }
359 `)
360 testRustError(t, ".* cannot be manually specified", `
361 rust_binary {
362 name: "foo",
363 srcs: [
364 "foo.rs",
365 ],
366 ld_flags: ["-Wl,-lbar"],
367 }
368 `)
369}