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 15package rust 16 17import ( 18 "strings" 19 "testing" 20 21 "android/soong/android" 22) 23 24// Test that variants are being generated correctly, and that crate-types are correct. 25func TestLibraryVariants(t *testing.T) { 26 27 ctx := testRust(t, ` 28 rust_library_host { 29 name: "libfoo", 30 srcs: ["foo.rs"], 31 crate_name: "foo", 32 } 33 rust_ffi_host { 34 name: "libfoo.ffi", 35 srcs: ["foo.rs"], 36 crate_name: "foo" 37 } 38 rust_ffi_host_static { 39 name: "libfoo.ffi_static", 40 srcs: ["foo.rs"], 41 crate_name: "foo" 42 }`) 43 44 // Test all variants are being built. 45 libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc") 46 libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") 47 libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc") 48 libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc") 49 50 rlibCrateType := "rlib" 51 dylibCrateType := "dylib" 52 sharedCrateType := "cdylib" 53 54 // Test crate type for rlib is correct. 55 if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) { 56 t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.Args["rustcFlags"]) 57 } 58 59 // Test crate type for dylib is correct. 60 if !strings.Contains(libfooDylib.Args["rustcFlags"], "crate-type="+dylibCrateType) { 61 t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.Args["rustcFlags"]) 62 } 63 64 // Test crate type for FFI rlibs is correct 65 if !strings.Contains(libfooFFIRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) { 66 t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooFFIRlib.Args["rustcFlags"]) 67 } 68 69 // Test crate type for C shared libraries is correct. 70 if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) { 71 t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"]) 72 } 73 74} 75 76// Test that dylibs are not statically linking the standard library. 77func TestDylibPreferDynamic(t *testing.T) { 78 ctx := testRust(t, ` 79 rust_library_host_dylib { 80 name: "libfoo", 81 srcs: ["foo.rs"], 82 crate_name: "foo", 83 }`) 84 85 libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc") 86 87 if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") { 88 t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) 89 } 90} 91 92func TestValidateLibraryStem(t *testing.T) { 93 testRustError(t, "crate_name must be defined.", ` 94 rust_library_host { 95 name: "libfoo", 96 srcs: ["foo.rs"], 97 }`) 98 99 testRustError(t, "library crate_names must be alphanumeric with underscores allowed", ` 100 rust_library_host { 101 name: "libfoo-bar", 102 srcs: ["foo.rs"], 103 crate_name: "foo-bar" 104 }`) 105 106 testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", ` 107 rust_library_host { 108 name: "foobar", 109 srcs: ["foo.rs"], 110 crate_name: "foo_bar" 111 }`) 112 testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", ` 113 rust_library_host { 114 name: "foobar", 115 stem: "libfoo", 116 srcs: ["foo.rs"], 117 crate_name: "foo_bar" 118 }`) 119 testRustError(t, "Invalid name or stem property; library filenames must start with lib<crate_name>", ` 120 rust_library_host { 121 name: "foobar", 122 stem: "foo_bar", 123 srcs: ["foo.rs"], 124 crate_name: "foo_bar" 125 }`) 126 127} 128 129func TestSharedLibrary(t *testing.T) { 130 ctx := testRust(t, ` 131 rust_ffi_shared { 132 name: "libfoo", 133 srcs: ["foo.rs"], 134 crate_name: "foo", 135 }`) 136 137 libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared") 138 139 libfooOutput := libfoo.Rule("rustc") 140 if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") { 141 t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", 142 libfooOutput.Args["linkFlags"]) 143 } 144 145 if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkDylibs) { 146 t.Errorf("Non-static libstd dylib expected to be a dependency of Rust shared libraries. Dylib deps are: %#v", 147 libfoo.Module().(*Module).Properties.AndroidMkDylibs) 148 } 149} 150 151func TestSharedLibraryToc(t *testing.T) { 152 ctx := testRust(t, ` 153 rust_ffi_shared { 154 name: "libfoo", 155 srcs: ["foo.rs"], 156 crate_name: "foo", 157 } 158 cc_binary { 159 name: "fizzbuzz", 160 shared_libs: ["libfoo"], 161 }`) 162 163 fizzbuzz := ctx.ModuleForTests(t, "fizzbuzz", "android_arm64_armv8-a").Rule("ld") 164 165 if !android.SuffixInList(fizzbuzz.Implicits.Strings(), "libfoo.so.toc") { 166 t.Errorf("missing expected libfoo.so.toc implicit dependency, instead found: %#v", 167 fizzbuzz.Implicits.Strings()) 168 } 169} 170 171func TestStaticLibraryLinkage(t *testing.T) { 172 ctx := testRust(t, ` 173 rust_ffi_static { 174 name: "libfoo", 175 srcs: ["foo.rs"], 176 crate_name: "foo", 177 }`) 178 179 libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std") 180 181 if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) { 182 t.Errorf("Static libstd rlib expected to be a dependency of Rust rlib libraries. Rlib deps are: %#v", 183 libfoo.Module().(*Module).Properties.AndroidMkDylibs) 184 } 185} 186 187func TestNativeDependencyOfRlib(t *testing.T) { 188 ctx := testRust(t, ` 189 rust_ffi_static { 190 name: "libffi_static", 191 crate_name: "ffi_static", 192 rlibs: ["librust_rlib"], 193 srcs: ["foo.rs"], 194 } 195 rust_library_rlib { 196 name: "librust_rlib", 197 crate_name: "rust_rlib", 198 srcs: ["foo.rs"], 199 shared_libs: ["libshared_cc_dep"], 200 static_libs: ["libstatic_cc_dep"], 201 } 202 cc_library_shared { 203 name: "libshared_cc_dep", 204 srcs: ["foo.cpp"], 205 } 206 cc_library_static { 207 name: "libstatic_cc_dep", 208 srcs: ["foo.cpp"], 209 } 210 `) 211 212 rustRlibRlibStd := ctx.ModuleForTests(t, "librust_rlib", "android_arm64_armv8-a_rlib_rlib-std") 213 rustRlibDylibStd := ctx.ModuleForTests(t, "librust_rlib", "android_arm64_armv8-a_rlib_dylib-std") 214 ffiRlib := ctx.ModuleForTests(t, "libffi_static", "android_arm64_armv8-a_rlib_rlib-std") 215 216 modules := []android.TestingModule{ 217 rustRlibRlibStd, 218 rustRlibDylibStd, 219 ffiRlib, 220 } 221 222 // librust_rlib specifies -L flag to cc deps output directory on rustc command 223 // and re-export the cc deps to rdep libffi_static 224 // When building rlib crate, rustc doesn't link the native libraries 225 // The build system assumes the cc deps will be at the final linkage (either a shared library or binary) 226 // Hence, these flags are no-op 227 // TODO: We could consider removing these flags 228 for _, module := range modules { 229 if !strings.Contains(module.Rule("rustc").Args["libFlags"], 230 "-L out/soong/.intermediates/libshared_cc_dep/android_arm64_armv8-a_shared/") { 231 t.Errorf( 232 "missing -L flag for libshared_cc_dep of %s, rustcFlags: %#v", 233 module.Module().Name(), rustRlibRlibStd.Rule("rustc").Args["libFlags"], 234 ) 235 } 236 if !strings.Contains(module.Rule("rustc").Args["libFlags"], 237 "-L out/soong/.intermediates/libstatic_cc_dep/android_arm64_armv8-a_static/") { 238 t.Errorf( 239 "missing -L flag for libstatic_cc_dep of %s, rustcFlags: %#v", 240 module.Module().Name(), rustRlibRlibStd.Rule("rustc").Args["libFlags"], 241 ) 242 } 243 } 244} 245 246// Test that variants pull in the right type of rustlib autodep 247func TestAutoDeps(t *testing.T) { 248 249 ctx := testRust(t, ` 250 rust_library_host { 251 name: "libbar", 252 srcs: ["bar.rs"], 253 crate_name: "bar", 254 } 255 rust_library_host_rlib { 256 name: "librlib_only", 257 srcs: ["bar.rs"], 258 crate_name: "rlib_only", 259 } 260 rust_library_host { 261 name: "libfoo", 262 srcs: ["foo.rs"], 263 crate_name: "foo", 264 rustlibs: [ 265 "libbar", 266 "librlib_only", 267 ], 268 } 269 rust_ffi_host { 270 name: "libfoo.ffi", 271 srcs: ["foo.rs"], 272 crate_name: "foo", 273 rustlibs: [ 274 "libbar", 275 "librlib_only", 276 ], 277 } 278 rust_ffi_host_static { 279 name: "libfoo.ffi.static", 280 srcs: ["foo.rs"], 281 crate_name: "foo", 282 rustlibs: [ 283 "libbar", 284 "librlib_only", 285 ], 286 }`) 287 288 libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std") 289 libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib") 290 libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std") 291 libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared") 292 293 for _, static := range []android.TestingModule{libfooRlib, libfooFFIRlib} { 294 if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) { 295 t.Errorf("libbar not present as rlib dependency in static lib: %s", static.Module().Name()) 296 } 297 if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) { 298 t.Errorf("libbar present as dynamic dependency in static lib: %s", static.Module().Name()) 299 } 300 } 301 302 for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} { 303 if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) { 304 t.Errorf("libbar not present as dynamic dependency in dynamic lib: %s", dyn.Module().Name()) 305 } 306 if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) { 307 t.Errorf("libbar present as rlib dependency in dynamic lib: %s", dyn.Module().Name()) 308 } 309 if !android.InList("librlib_only", dyn.Module().(*Module).Properties.AndroidMkRlibs) { 310 t.Errorf("librlib_only should be selected by rustlibs as an rlib: %s.", dyn.Module().Name()) 311 } 312 } 313} 314 315// Test that stripped versions are correctly generated and used. 316func TestStrippedLibrary(t *testing.T) { 317 ctx := testRust(t, ` 318 rust_library_dylib { 319 name: "libfoo", 320 crate_name: "foo", 321 srcs: ["foo.rs"], 322 } 323 rust_library_dylib { 324 name: "libbar", 325 crate_name: "bar", 326 srcs: ["foo.rs"], 327 strip: { 328 none: true 329 } 330 } 331 `) 332 333 foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib") 334 foo.Output("libfoo.dylib.so") 335 foo.Output("unstripped/libfoo.dylib.so") 336 // Check that the `cp` rule is using the stripped version as input. 337 cp := foo.Rule("android.Cp") 338 if strings.HasSuffix(cp.Input.String(), "unstripped/libfoo.dylib.so") { 339 t.Errorf("installed library not based on stripped version: %v", cp.Input) 340 } 341 342 fizzBar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_dylib").MaybeOutput("unstripped/libbar.dylib.so") 343 if fizzBar.Rule != nil { 344 t.Errorf("unstripped library exists, so stripped library has incorrectly been generated") 345 } 346} 347 348func TestLibstdLinkage(t *testing.T) { 349 ctx := testRust(t, ` 350 rust_library { 351 name: "libfoo", 352 srcs: ["foo.rs"], 353 crate_name: "foo", 354 } 355 rust_ffi { 356 name: "libbar", 357 srcs: ["foo.rs"], 358 crate_name: "bar", 359 rustlibs: ["libfoo"], 360 } 361 rust_ffi_static { 362 name: "libbar_static", 363 srcs: ["foo.rs"], 364 crate_name: "bar", 365 rustlibs: ["libfoo"], 366 } 367 rust_ffi { 368 name: "libbar.prefer_rlib", 369 srcs: ["foo.rs"], 370 crate_name: "bar", 371 rustlibs: ["libfoo"], 372 prefer_rlib: true, 373 }`) 374 375 libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) 376 libfooRlibStatic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module) 377 libfooRlibDynamic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module) 378 379 libbarShared := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_shared").Module().(*Module) 380 libbarFFIRlib := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module) 381 382 // prefer_rlib works the same for both rust_library and rust_ffi, so a single check is sufficient here. 383 libbarRlibStd := ctx.ModuleForTests(t, "libbar.prefer_rlib", "android_arm64_armv8-a_shared").Module().(*Module) 384 385 if !android.InList("libstd", libfooRlibStatic.Properties.AndroidMkRlibs) { 386 t.Errorf("rlib-std variant for device rust_library_rlib does not link libstd as an rlib") 387 } 388 if !android.InList("libstd", libfooRlibDynamic.Properties.AndroidMkDylibs) { 389 t.Errorf("dylib-std variant for device rust_library_rlib does not link libstd as an dylib") 390 } 391 if !android.InList("libstd", libfooDylib.Properties.AndroidMkDylibs) { 392 t.Errorf("Device rust_library_dylib does not link libstd as an dylib") 393 } 394 395 if !android.InList("libstd", libbarShared.Properties.AndroidMkDylibs) { 396 t.Errorf("Device rust_ffi_shared does not link libstd as an dylib") 397 } 398 if !android.InList("libstd", libbarFFIRlib.Properties.AndroidMkRlibs) { 399 t.Errorf("Device rust_ffi_static does not link libstd as an rlib") 400 } 401 if !android.InList("libfoo.rlib-std", libbarFFIRlib.Properties.AndroidMkRlibs) { 402 t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant") 403 } 404 if !android.InList("libstd", libbarRlibStd.Properties.AndroidMkRlibs) { 405 t.Errorf("rust_ffi with prefer_rlib does not link libstd as an rlib") 406 } 407 408} 409 410func TestRustFFIExportedIncludes(t *testing.T) { 411 ctx := testRust(t, ` 412 rust_ffi { 413 name: "libbar", 414 srcs: ["foo.rs"], 415 crate_name: "bar", 416 export_include_dirs: ["rust_includes"], 417 host_supported: true, 418 } 419 cc_library_static { 420 name: "libfoo", 421 srcs: ["foo.cpp"], 422 shared_libs: ["libbar"], 423 host_supported: true, 424 }`) 425 libfooStatic := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_static").Rule("cc") 426 android.AssertStringDoesContain(t, "cFlags for lib module", libfooStatic.Args["cFlags"], " -Irust_includes ") 427} 428 429// Make sure cc_rustlibs_for_make has the expected behavior, and that 430// cc_library_static does as well. 431// This is here instead of cc/library_test.go because the test needs to 432// define a rust_ffi module which can't be done in soong-cc to avoid the 433// circular dependency. 434func TestCCRustlibsForMake(t *testing.T) { 435 t.Parallel() 436 result := testRust(t, ` 437 rust_ffi_static { 438 name: "libbar", 439 srcs: ["foo.rs"], 440 crate_name: "bar", 441 export_include_dirs: ["rust_includes"], 442 host_supported: true, 443 } 444 445 cc_rustlibs_for_make { 446 name: "libmakerustlibs", 447 whole_static_libs: ["libbar"], 448 } 449 450 cc_library_static { 451 name: "libccstatic", 452 whole_static_libs: ["libbar"], 453 } 454 `) 455 456 libmakerustlibs := result.ModuleForTests(t, "libmakerustlibs", "android_arm64_armv8-a_static").MaybeRule("rustc") 457 libccstatic := result.ModuleForTests(t, "libccstatic", "android_arm64_armv8-a_static").MaybeRule("rustc") 458 459 if libmakerustlibs.Output == nil { 460 t.Errorf("cc_rustlibs_for_make is not generating a Rust staticlib when it should") 461 } 462 463 if libccstatic.Output != nil { 464 t.Errorf("cc_library_static is generating a Rust staticlib when it should not") 465 } 466} 467 468func TestRustVersionScript(t *testing.T) { 469 ctx := testRust(t, ` 470 rust_library { 471 name: "librs", 472 srcs: ["bar.rs"], 473 crate_name: "rs", 474 extra_exported_symbols: "librs.map.txt", 475 } 476 rust_ffi { 477 name: "libffi", 478 srcs: ["foo.rs"], 479 crate_name: "ffi", 480 version_script: "libffi.map.txt", 481 } 482 `) 483 484 //linkFlags 485 librs := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_dylib").Rule("rustc") 486 libffi := ctx.ModuleForTests(t, "libffi", "android_arm64_armv8-a_shared").Rule("rustc") 487 488 if !strings.Contains(librs.Args["linkFlags"], "-Wl,--version-script=librs.map.txt") { 489 t.Errorf("missing expected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v", 490 librs.Args["linkFlags"]) 491 } 492 if strings.Contains(librs.Args["linkFlags"], "-Wl,--android-version-script=librs.map.txt") { 493 t.Errorf("unexpected -Wl,--android-version-script= linker flag for libextended shared lib, linkFlags: %#v", 494 librs.Args["linkFlags"]) 495 } 496 497 if !strings.Contains(libffi.Args["linkFlags"], "-Wl,--android-version-script=libffi.map.txt") { 498 t.Errorf("missing -Wl,--android-version-script= linker flag for libreplaced shared lib, linkFlags: %#v", 499 libffi.Args["linkFlags"]) 500 } 501 if strings.Contains(libffi.Args["linkFlags"], "-Wl,--version-script=libffi.map.txt") { 502 t.Errorf("unexpected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v", 503 libffi.Args["linkFlags"]) 504 } 505} 506 507func TestRustVersionScriptPropertyErrors(t *testing.T) { 508 testRustError(t, "version_script: can only be set for rust_ffi modules", ` 509 rust_library { 510 name: "librs", 511 srcs: ["bar.rs"], 512 crate_name: "rs", 513 version_script: "libbar.map.txt", 514 }`) 515 testRustError(t, "version_script and extra_exported_symbols", ` 516 rust_ffi { 517 name: "librs", 518 srcs: ["bar.rs"], 519 crate_name: "rs", 520 version_script: "libbar.map.txt", 521 extra_exported_symbols: "libbar.map.txt", 522 }`) 523} 524 525func TestStubsVersions(t *testing.T) { 526 t.Parallel() 527 bp := ` 528 rust_ffi { 529 name: "libfoo", 530 crate_name: "foo", 531 srcs: ["foo.rs"], 532 stubs: { 533 versions: ["29", "R", "current"], 534 }, 535 } 536 ` 537 ctx := android.GroupFixturePreparers( 538 prepareForRustTest, 539 android.PrepareForTestWithVisibility, 540 rustMockedFiles.AddToFixture(), 541 android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { 542 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 543 })).RunTestWithBp(t, bp) 544 545 variants := ctx.ModuleVariantsForTests("libfoo") 546 for _, expectedVer := range []string{"29", "R", "current"} { 547 expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer 548 if !android.InList(expectedVariant, variants) { 549 t.Errorf("missing expected variant: %q", expectedVariant) 550 } 551 } 552} 553 554func TestStubsVersions_NotSorted(t *testing.T) { 555 t.Parallel() 556 bp := ` 557 rust_ffi_shared { 558 name: "libfoo", 559 crate_name: "foo", 560 srcs: ["foo.rs"], 561 stubs: { 562 versions: ["29", "current", "R"], 563 }, 564 } 565 ` 566 fixture := android.GroupFixturePreparers( 567 prepareForRustTest, 568 android.PrepareForTestWithVisibility, 569 rustMockedFiles.AddToFixture(), 570 571 android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { 572 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 573 })) 574 575 fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: not sorted`)).RunTestWithBp(t, bp) 576} 577 578func TestStubsVersions_ParseError(t *testing.T) { 579 t.Parallel() 580 bp := ` 581 rust_ffi_shared { 582 name: "libfoo", 583 crate_name: "foo", 584 srcs: ["foo.rs"], 585 stubs: { 586 versions: ["29", "current", "X"], 587 }, 588 } 589 ` 590 fixture := android.GroupFixturePreparers( 591 prepareForRustTest, 592 android.PrepareForTestWithVisibility, 593 rustMockedFiles.AddToFixture(), 594 595 android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { 596 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 597 })) 598 599 fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`)).RunTestWithBp(t, bp) 600} 601 602func TestVersionedStubs(t *testing.T) { 603 t.Parallel() 604 bp := ` 605 rust_ffi_shared { 606 name: "libFoo", 607 crate_name: "Foo", 608 srcs: ["foo.rs"], 609 stubs: { 610 symbol_file: "foo.map.txt", 611 versions: ["1", "2", "3"], 612 }, 613 } 614 615 cc_library_shared { 616 name: "libBar", 617 srcs: ["bar.c"], 618 shared_libs: ["libFoo#1"], 619 } 620 621 rust_library { 622 name: "libbar_rs", 623 crate_name: "bar_rs", 624 srcs: ["bar.rs"], 625 shared_libs: ["libFoo#1"], 626 } 627 rust_ffi { 628 name: "libbar_ffi_rs", 629 crate_name: "bar_ffi_rs", 630 srcs: ["bar.rs"], 631 shared_libs: ["libFoo#1"], 632 } 633 ` 634 635 ctx := android.GroupFixturePreparers( 636 prepareForRustTest, 637 android.PrepareForTestWithVisibility, 638 rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp) 639 640 variants := ctx.ModuleVariantsForTests("libFoo") 641 expectedVariants := []string{ 642 "android_arm64_armv8-a_shared", 643 "android_arm64_armv8-a_shared_1", 644 "android_arm64_armv8-a_shared_2", 645 "android_arm64_armv8-a_shared_3", 646 "android_arm64_armv8-a_shared_current", 647 "android_arm_armv7-a-neon_shared", 648 "android_arm_armv7-a-neon_shared_1", 649 "android_arm_armv7-a-neon_shared_2", 650 "android_arm_armv7-a-neon_shared_3", 651 "android_arm_armv7-a-neon_shared_current", 652 } 653 variantsMismatch := false 654 if len(variants) != len(expectedVariants) { 655 variantsMismatch = true 656 } else { 657 for _, v := range expectedVariants { 658 if !android.InList(v, variants) { 659 variantsMismatch = false 660 } 661 } 662 } 663 if variantsMismatch { 664 t.Errorf("variants of libFoo expected:\n") 665 for _, v := range expectedVariants { 666 t.Errorf("%q\n", v) 667 } 668 t.Errorf(", but got:\n") 669 for _, v := range variants { 670 t.Errorf("%q\n", v) 671 } 672 } 673 674 libBarLinkRule := ctx.ModuleForTests(t, "libBar", "android_arm64_armv8-a_shared").Rule("ld") 675 libBarFlags := libBarLinkRule.Args["libFlags"] 676 677 libBarRsRustcRule := ctx.ModuleForTests(t, "libbar_rs", "android_arm64_armv8-a_dylib").Rule("rustc") 678 libBarRsFlags := libBarRsRustcRule.Args["linkFlags"] 679 680 libBarFfiRsRustcRule := ctx.ModuleForTests(t, "libbar_ffi_rs", "android_arm64_armv8-a_shared").Rule("rustc") 681 libBarFfiRsFlags := libBarFfiRsRustcRule.Args["linkFlags"] 682 683 libFoo1StubPath := "libFoo/android_arm64_armv8-a_shared_1/unstripped/libFoo.so" 684 if !strings.Contains(libBarFlags, libFoo1StubPath) { 685 t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFlags) 686 } 687 if !strings.Contains(libBarRsFlags, libFoo1StubPath) { 688 t.Errorf("%q is not found in %q", libFoo1StubPath, libBarRsFlags) 689 } 690 if !strings.Contains(libBarFfiRsFlags, libFoo1StubPath) { 691 t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFfiRsFlags) 692 } 693} 694 695func TestCheckConflictingExplicitVersions(t *testing.T) { 696 t.Parallel() 697 bp := ` 698 cc_library_shared { 699 name: "libbar", 700 srcs: ["bar.c"], 701 shared_libs: ["libfoo", "libfoo#impl"], 702 } 703 704 rust_ffi_shared { 705 name: "libfoo", 706 crate_name: "foo", 707 srcs: ["foo.rs"], 708 stubs: { 709 versions: ["29", "current"], 710 }, 711 } 712 ` 713 fixture := android.GroupFixturePreparers( 714 prepareForRustTest, 715 android.PrepareForTestWithVisibility, 716 rustMockedFiles.AddToFixture()) 717 718 fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`duplicate shared libraries with different explicit versions`)).RunTestWithBp(t, bp) 719} 720 721func TestAddnoOverride64GlobalCflags(t *testing.T) { 722 t.Parallel() 723 bp := ` 724 cc_library_shared { 725 name: "libclient", 726 srcs: ["foo.c"], 727 shared_libs: ["libfoo#1"], 728 } 729 730 rust_ffi_shared { 731 name: "libfoo", 732 crate_name: "foo", 733 srcs: ["foo.c"], 734 shared_libs: ["libbar"], 735 stubs: { 736 symbol_file: "foo.map.txt", 737 versions: ["1", "2", "3"], 738 }, 739 } 740 741 cc_library_shared { 742 name: "libbar", 743 export_include_dirs: ["include/libbar"], 744 srcs: ["foo.c"], 745 }` 746 ctx := android.GroupFixturePreparers( 747 prepareForRustTest, 748 android.PrepareForTestWithVisibility, 749 rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp) 750 751 cFlags := ctx.ModuleForTests(t, "libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"] 752 753 if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") { 754 t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags) 755 } 756} 757 758// Make sure the stubs properties can only be used in modules producing shared libs 759func TestRustStubsFFIOnly(t *testing.T) { 760 testRustError(t, "stubs properties", ` 761 rust_library { 762 name: "libfoo", 763 crate_name: "foo", 764 srcs: ["foo.c"], 765 shared_libs: ["libbar"], 766 stubs: { 767 symbol_file: "foo.map.txt", 768 }, 769 } 770 `) 771 772 testRustError(t, "stubs properties", ` 773 rust_library { 774 name: "libfoo", 775 crate_name: "foo", 776 srcs: ["foo.c"], 777 shared_libs: ["libbar"], 778 stubs: { 779 versions: ["1"], 780 }, 781 } 782 `) 783 784 testRustError(t, "stubs properties", ` 785 rust_ffi_static { 786 name: "libfoo", 787 crate_name: "foo", 788 srcs: ["foo.c"], 789 shared_libs: ["libbar"], 790 stubs: { 791 symbol_file: "foo.map.txt", 792 }, 793 } 794 `) 795 testRustError(t, "stubs properties", ` 796 rust_ffi_static { 797 name: "libfoo", 798 crate_name: "foo", 799 srcs: ["foo.c"], 800 shared_libs: ["libbar"], 801 stubs: { 802 versions: ["1"], 803 }, 804 } 805 `) 806} 807 808// TODO: When rust_ffi libraries support export_*_lib_headers, 809// add a test similar to cc.TestStubsLibReexportsHeaders 810