compiler_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. // 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. package rust
  15. import (
  16. "strings"
  17. "testing"
  18. "android/soong/android"
  19. )
  20. // Test that feature flags are being correctly generated.
  21. func TestFeaturesToFlags(t *testing.T) {
  22. ctx := testRust(t, `
  23. rust_library_host_dylib {
  24. name: "libfoo",
  25. srcs: ["foo.rs"],
  26. crate_name: "foo",
  27. features: [
  28. "fizz",
  29. "buzz"
  30. ],
  31. }`)
  32. libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
  33. if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") ||
  34. !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") {
  35. t.Fatalf("missing fizz and buzz feature flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
  36. }
  37. }
  38. // Test that cfgs flags are being correctly generated.
  39. func TestCfgsToFlags(t *testing.T) {
  40. ctx := testRust(t, `
  41. rust_library_host {
  42. name: "libfoo",
  43. srcs: ["foo.rs"],
  44. crate_name: "foo",
  45. cfgs: [
  46. "std",
  47. "cfg1=\"one\""
  48. ],
  49. }`)
  50. libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
  51. if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") ||
  52. !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") {
  53. t.Fatalf("missing std and cfg1 flags for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
  54. }
  55. }
  56. // Test that we reject multiple source files.
  57. func TestEnforceSingleSourceFile(t *testing.T) {
  58. singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
  59. // Test libraries
  60. testRustError(t, singleSrcError, `
  61. rust_library_host {
  62. name: "foo-bar-library",
  63. srcs: ["foo.rs", "src/bar.rs"],
  64. }`)
  65. // Test binaries
  66. testRustError(t, singleSrcError, `
  67. rust_binary_host {
  68. name: "foo-bar-binary",
  69. srcs: ["foo.rs", "src/bar.rs"],
  70. }`)
  71. // Test proc_macros
  72. testRustError(t, singleSrcError, `
  73. rust_proc_macro {
  74. name: "foo-bar-proc-macro",
  75. srcs: ["foo.rs", "src/bar.rs"],
  76. }`)
  77. // Test prebuilts
  78. testRustError(t, singleSrcError, `
  79. rust_prebuilt_dylib {
  80. name: "foo-bar-prebuilt",
  81. srcs: ["liby.so", "libz.so"],
  82. host_supported: true,
  83. }`)
  84. }
  85. // Test that we reject _no_ source files.
  86. func TestEnforceMissingSourceFiles(t *testing.T) {
  87. singleSrcError := "srcs must not be empty"
  88. // Test libraries
  89. testRustError(t, singleSrcError, `
  90. rust_library_host {
  91. name: "foo-bar-library",
  92. crate_name: "foo",
  93. }`)
  94. // Test binaries
  95. testRustError(t, singleSrcError, `
  96. rust_binary_host {
  97. name: "foo-bar-binary",
  98. crate_name: "foo",
  99. }`)
  100. // Test proc_macros
  101. testRustError(t, singleSrcError, `
  102. rust_proc_macro {
  103. name: "foo-bar-proc-macro",
  104. crate_name: "foo",
  105. }`)
  106. // Test prebuilts
  107. testRustError(t, singleSrcError, `
  108. rust_prebuilt_dylib {
  109. name: "foo-bar-prebuilt",
  110. crate_name: "foo",
  111. host_supported: true,
  112. }`)
  113. }
  114. // Test environment vars for Cargo compat are set.
  115. func TestCargoCompat(t *testing.T) {
  116. ctx := testRust(t, `
  117. rust_binary {
  118. name: "fizz",
  119. srcs: ["foo.rs"],
  120. crate_name: "foo",
  121. cargo_env_compat: true,
  122. cargo_pkg_version: "1.0.0"
  123. }`)
  124. fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
  125. if !strings.Contains(fizz.Args["envVars"], "CARGO_BIN_NAME=fizz") {
  126. t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual envVars: %#v", fizz.Args["envVars"])
  127. }
  128. if !strings.Contains(fizz.Args["envVars"], "CARGO_CRATE_NAME=foo") {
  129. t.Fatalf("expected 'CARGO_CRATE_NAME=foo' in envVars, actual envVars: %#v", fizz.Args["envVars"])
  130. }
  131. if !strings.Contains(fizz.Args["envVars"], "CARGO_PKG_VERSION=1.0.0") {
  132. t.Fatalf("expected 'CARGO_PKG_VERSION=1.0.0' in envVars, actual envVars: %#v", fizz.Args["envVars"])
  133. }
  134. }
  135. func TestInstallDir(t *testing.T) {
  136. ctx := testRust(t, `
  137. rust_library_dylib {
  138. name: "libfoo",
  139. srcs: ["foo.rs"],
  140. crate_name: "foo",
  141. }
  142. rust_binary {
  143. name: "fizzbuzz",
  144. srcs: ["foo.rs"],
  145. }`)
  146. install_path_lib64 := ctx.ModuleForTests("libfoo",
  147. "android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
  148. install_path_lib32 := ctx.ModuleForTests("libfoo",
  149. "android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
  150. install_path_bin := ctx.ModuleForTests("fizzbuzz",
  151. "android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String()
  152. if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") {
  153. t.Fatalf("unexpected install path for 64-bit library: %#v", install_path_lib64)
  154. }
  155. if !strings.HasSuffix(install_path_lib32, "system/lib/libfoo.dylib.so") {
  156. t.Fatalf("unexpected install path for 32-bit library: %#v", install_path_lib32)
  157. }
  158. if !strings.HasSuffix(install_path_bin, "system/bin/fizzbuzz") {
  159. t.Fatalf("unexpected install path for binary: %#v", install_path_bin)
  160. }
  161. }
  162. func TestLints(t *testing.T) {
  163. bp := `
  164. // foo uses the default value of lints
  165. rust_library {
  166. name: "libfoo",
  167. srcs: ["foo.rs"],
  168. crate_name: "foo",
  169. }
  170. // bar forces the use of the "android" lint set
  171. rust_library {
  172. name: "libbar",
  173. srcs: ["foo.rs"],
  174. crate_name: "bar",
  175. lints: "android",
  176. }
  177. // foobar explicitly disable all lints
  178. rust_library {
  179. name: "libfoobar",
  180. srcs: ["foo.rs"],
  181. crate_name: "foobar",
  182. lints: "none",
  183. }`
  184. var lintTests = []struct {
  185. modulePath string
  186. fooFlags string
  187. }{
  188. {"", "${config.RustDefaultLints}"},
  189. {"external/", "${config.RustAllowAllLints}"},
  190. {"hardware/", "${config.RustVendorLints}"},
  191. }
  192. for _, tc := range lintTests {
  193. t.Run("path="+tc.modulePath, func(t *testing.T) {
  194. result := android.GroupFixturePreparers(
  195. prepareForRustTest,
  196. // Test with the blueprint file in different directories.
  197. android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
  198. ).RunTest(t)
  199. r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
  200. android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags)
  201. r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
  202. android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}")
  203. r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
  204. android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
  205. })
  206. }
  207. }
  208. // Test that devices are linking the stdlib dynamically
  209. func TestStdDeviceLinkage(t *testing.T) {
  210. ctx := testRust(t, `
  211. rust_binary {
  212. name: "fizz",
  213. srcs: ["foo.rs"],
  214. }
  215. rust_library {
  216. name: "libfoo",
  217. srcs: ["foo.rs"],
  218. crate_name: "foo",
  219. }`)
  220. fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
  221. fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
  222. fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
  223. if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) {
  224. t.Errorf("libstd is not linked dynamically for device binaries")
  225. }
  226. if !android.InList("libstd", fooRlib.Properties.AndroidMkDylibs) {
  227. t.Errorf("libstd is not linked dynamically for rlibs")
  228. }
  229. if !android.InList("libstd", fooDylib.Properties.AndroidMkDylibs) {
  230. t.Errorf("libstd is not linked dynamically for dylibs")
  231. }
  232. }
  233. // Ensure that manual link flags are disallowed.
  234. func TestManualLinkageRejection(t *testing.T) {
  235. // rustc flags
  236. testRustError(t, ".* cannot be manually specified", `
  237. rust_binary {
  238. name: "foo",
  239. srcs: [
  240. "foo.rs",
  241. ],
  242. flags: ["-lbar"],
  243. }
  244. `)
  245. testRustError(t, ".* cannot be manually specified", `
  246. rust_binary {
  247. name: "foo",
  248. srcs: [
  249. "foo.rs",
  250. ],
  251. flags: ["--extern=foo"],
  252. }
  253. `)
  254. testRustError(t, ".* cannot be manually specified", `
  255. rust_binary {
  256. name: "foo",
  257. srcs: [
  258. "foo.rs",
  259. ],
  260. flags: ["-Clink-args=foo"],
  261. }
  262. `)
  263. testRustError(t, ".* cannot be manually specified", `
  264. rust_binary {
  265. name: "foo",
  266. srcs: [
  267. "foo.rs",
  268. ],
  269. flags: ["-C link-args=foo"],
  270. }
  271. `)
  272. testRustError(t, ".* cannot be manually specified", `
  273. rust_binary {
  274. name: "foo",
  275. srcs: [
  276. "foo.rs",
  277. ],
  278. flags: ["-L foo/"],
  279. }
  280. `)
  281. // lld flags
  282. testRustError(t, ".* cannot be manually specified", `
  283. rust_binary {
  284. name: "foo",
  285. srcs: [
  286. "foo.rs",
  287. ],
  288. ld_flags: ["-Wl,-L bar/"],
  289. }
  290. `)
  291. testRustError(t, ".* cannot be manually specified", `
  292. rust_binary {
  293. name: "foo",
  294. srcs: [
  295. "foo.rs",
  296. ],
  297. ld_flags: ["-Wl,-lbar"],
  298. }
  299. `)
  300. }