library_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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 variants are being generated correctly, and that crate-types are correct.
  21. func TestLibraryVariants(t *testing.T) {
  22. ctx := testRust(t, `
  23. rust_library_host {
  24. name: "libfoo",
  25. srcs: ["foo.rs"],
  26. crate_name: "foo",
  27. }
  28. rust_ffi_host {
  29. name: "libfoo.ffi",
  30. srcs: ["foo.rs"],
  31. crate_name: "foo"
  32. }`)
  33. // Test all variants are being built.
  34. libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Output("libfoo.rlib")
  35. libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so")
  36. libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Output("libfoo.ffi.a")
  37. libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Output("libfoo.ffi.so")
  38. rlibCrateType := "rlib"
  39. dylibCrateType := "dylib"
  40. sharedCrateType := "cdylib"
  41. staticCrateType := "static"
  42. // Test crate type for rlib is correct.
  43. if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
  44. t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.Args["rustcFlags"])
  45. }
  46. // Test crate type for dylib is correct.
  47. if !strings.Contains(libfooDylib.Args["rustcFlags"], "crate-type="+dylibCrateType) {
  48. t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.Args["rustcFlags"])
  49. }
  50. // Test crate type for C static libraries is correct.
  51. if !strings.Contains(libfooStatic.Args["rustcFlags"], "crate-type="+staticCrateType) {
  52. t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"])
  53. }
  54. // Test crate type for C shared libraries is correct.
  55. if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) {
  56. t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"])
  57. }
  58. }
  59. // Test that dylibs are not statically linking the standard library.
  60. func TestDylibPreferDynamic(t *testing.T) {
  61. ctx := testRust(t, `
  62. rust_library_host_dylib {
  63. name: "libfoo",
  64. srcs: ["foo.rs"],
  65. crate_name: "foo",
  66. }`)
  67. libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so")
  68. if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") {
  69. t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
  70. }
  71. }
  72. func TestValidateLibraryStem(t *testing.T) {
  73. testRustError(t, "crate_name must be defined.", `
  74. rust_library_host {
  75. name: "libfoo",
  76. srcs: ["foo.rs"],
  77. }`)
  78. testRustError(t, "library crate_names must be alphanumeric with underscores allowed", `
  79. rust_library_host {
  80. name: "libfoo-bar",
  81. srcs: ["foo.rs"],
  82. crate_name: "foo-bar"
  83. }`)
  84. testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", `
  85. rust_library_host {
  86. name: "foobar",
  87. srcs: ["foo.rs"],
  88. crate_name: "foo_bar"
  89. }`)
  90. testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", `
  91. rust_library_host {
  92. name: "foobar",
  93. stem: "libfoo",
  94. srcs: ["foo.rs"],
  95. crate_name: "foo_bar"
  96. }`)
  97. testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", `
  98. rust_library_host {
  99. name: "foobar",
  100. stem: "foo_bar",
  101. srcs: ["foo.rs"],
  102. crate_name: "foo_bar"
  103. }`)
  104. }
  105. func TestSharedLibrary(t *testing.T) {
  106. ctx := testRust(t, `
  107. rust_ffi_shared {
  108. name: "libfoo",
  109. srcs: ["foo.rs"],
  110. crate_name: "foo",
  111. }`)
  112. libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared")
  113. libfooOutput := libfoo.Output("libfoo.so")
  114. if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
  115. t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v",
  116. libfooOutput.Args["linkFlags"])
  117. }
  118. if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkDylibs) {
  119. t.Errorf("Non-static libstd dylib expected to be a dependency of Rust shared libraries. Dylib deps are: %#v",
  120. libfoo.Module().(*Module).Properties.AndroidMkDylibs)
  121. }
  122. }
  123. func TestStaticLibraryLinkage(t *testing.T) {
  124. ctx := testRust(t, `
  125. rust_ffi_static {
  126. name: "libfoo",
  127. srcs: ["foo.rs"],
  128. crate_name: "foo",
  129. }`)
  130. libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
  131. if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
  132. t.Errorf("Static libstd rlib expected to be a dependency of Rust static libraries. Rlib deps are: %#v",
  133. libfoo.Module().(*Module).Properties.AndroidMkDylibs)
  134. }
  135. }
  136. // Test that variants pull in the right type of rustlib autodep
  137. func TestAutoDeps(t *testing.T) {
  138. ctx := testRust(t, `
  139. rust_library_host {
  140. name: "libbar",
  141. srcs: ["bar.rs"],
  142. crate_name: "bar",
  143. }
  144. rust_library_host {
  145. name: "libfoo",
  146. srcs: ["foo.rs"],
  147. crate_name: "foo",
  148. rustlibs: ["libbar"],
  149. }
  150. rust_ffi_host {
  151. name: "libfoo.ffi",
  152. srcs: ["foo.rs"],
  153. crate_name: "foo",
  154. rustlibs: ["libbar"],
  155. }`)
  156. libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std")
  157. libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
  158. libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
  159. libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
  160. for _, static := range []android.TestingModule{libfooRlib, libfooStatic} {
  161. if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
  162. t.Errorf("libbar not present as rlib dependency in static lib")
  163. }
  164. if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) {
  165. t.Errorf("libbar present as dynamic dependency in static lib")
  166. }
  167. }
  168. for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} {
  169. if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) {
  170. t.Errorf("libbar not present as dynamic dependency in dynamic lib")
  171. }
  172. if android.InList("libbar.dylib-std", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
  173. t.Errorf("libbar present as rlib dependency in dynamic lib")
  174. }
  175. }
  176. }
  177. // Test that stripped versions are correctly generated and used.
  178. func TestStrippedLibrary(t *testing.T) {
  179. ctx := testRust(t, `
  180. rust_library_dylib {
  181. name: "libfoo",
  182. crate_name: "foo",
  183. srcs: ["foo.rs"],
  184. }
  185. rust_library_dylib {
  186. name: "libbar",
  187. crate_name: "bar",
  188. srcs: ["foo.rs"],
  189. strip: {
  190. none: true
  191. }
  192. }
  193. `)
  194. foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib")
  195. foo.Output("stripped/libfoo.dylib.so")
  196. // Check that the `cp` rule is using the stripped version as input.
  197. cp := foo.Rule("android.Cp")
  198. if !strings.HasSuffix(cp.Input.String(), "stripped/libfoo.dylib.so") {
  199. t.Errorf("installed binary not based on stripped version: %v", cp.Input)
  200. }
  201. fizzBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeOutput("stripped/libbar.dylib.so")
  202. if fizzBar.Rule != nil {
  203. t.Errorf("stripped version of bar has been generated")
  204. }
  205. }
  206. func TestLibstdLinkage(t *testing.T) {
  207. ctx := testRust(t, `
  208. rust_library {
  209. name: "libfoo",
  210. srcs: ["foo.rs"],
  211. crate_name: "foo",
  212. }
  213. rust_ffi {
  214. name: "libbar",
  215. srcs: ["foo.rs"],
  216. crate_name: "bar",
  217. rustlibs: ["libfoo"],
  218. }`)
  219. libfooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
  220. libfooRlibStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
  221. libfooRlibDynamic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
  222. libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module)
  223. libbarStatic := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module().(*Module)
  224. if !android.InList("libstd", libfooRlibStatic.Properties.AndroidMkRlibs) {
  225. t.Errorf("rlib-std variant for device rust_library_rlib does not link libstd as an rlib")
  226. }
  227. if !android.InList("libstd", libfooRlibDynamic.Properties.AndroidMkDylibs) {
  228. t.Errorf("dylib-std variant for device rust_library_rlib does not link libstd as an dylib")
  229. }
  230. if !android.InList("libstd", libfooDylib.Properties.AndroidMkDylibs) {
  231. t.Errorf("Device rust_library_dylib does not link libstd as an dylib")
  232. }
  233. if !android.InList("libstd", libbarShared.Properties.AndroidMkDylibs) {
  234. t.Errorf("Device rust_ffi_shared does not link libstd as an dylib")
  235. }
  236. if !android.InList("libstd", libbarStatic.Properties.AndroidMkRlibs) {
  237. t.Errorf("Device rust_ffi_static does not link libstd as an rlib")
  238. }
  239. if !android.InList("libfoo.rlib-std", libbarStatic.Properties.AndroidMkRlibs) {
  240. t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant")
  241. }
  242. }