1// Copyright 2019 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 "runtime" 19 "testing" 20 21 "android/soong/android" 22 "android/soong/bazel/cquery" 23 24 "github.com/google/blueprint" 25) 26 27var prepareForPrebuiltTest = android.GroupFixturePreparers( 28 prepareForCcTest, 29 android.PrepareForTestWithAndroidMk, 30) 31 32func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext { 33 t.Helper() 34 result := android.GroupFixturePreparers( 35 prepareForPrebuiltTest, 36 fs.AddToFixture(), 37 android.GroupFixturePreparers(handlers...), 38 ).RunTestWithBp(t, bp) 39 40 return result.TestContext 41} 42 43type configCustomizer func(config android.Config) 44 45func TestPrebuilt(t *testing.T) { 46 bp := ` 47 cc_library { 48 name: "liba", 49 } 50 51 cc_prebuilt_library_shared { 52 name: "liba", 53 srcs: ["liba.so"], 54 } 55 56 cc_library { 57 name: "libb", 58 } 59 60 cc_prebuilt_library_static { 61 name: "libb", 62 srcs: ["libb.a"], 63 } 64 65 cc_library_shared { 66 name: "libd", 67 } 68 69 cc_prebuilt_library_shared { 70 name: "libd", 71 srcs: ["libd.so"], 72 } 73 74 cc_library_static { 75 name: "libe", 76 } 77 78 cc_prebuilt_library_static { 79 name: "libe", 80 srcs: ["libe.a"], 81 } 82 83 cc_library { 84 name: "libf", 85 } 86 87 cc_prebuilt_library { 88 name: "libf", 89 static: { 90 srcs: ["libf.a"], 91 }, 92 shared: { 93 srcs: ["libf.so"], 94 }, 95 } 96 97 cc_object { 98 name: "crtx", 99 } 100 101 cc_prebuilt_object { 102 name: "crtx", 103 srcs: ["crtx.o"], 104 } 105 ` 106 107 ctx := testPrebuilt(t, bp, map[string][]byte{ 108 "liba.so": nil, 109 "libb.a": nil, 110 "libd.so": nil, 111 "libe.a": nil, 112 "libf.a": nil, 113 "libf.so": nil, 114 "crtx.o": nil, 115 }) 116 117 // Verify that all the modules exist and that their dependencies were connected correctly 118 liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module() 119 libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module() 120 libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module() 121 libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module() 122 libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module() 123 libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module() 124 crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module() 125 126 prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module() 127 prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module() 128 prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module() 129 prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module() 130 prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module() 131 prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module() 132 prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module() 133 134 hasDep := func(m android.Module, wantDep android.Module) bool { 135 t.Helper() 136 var found bool 137 ctx.VisitDirectDeps(m, func(dep blueprint.Module) { 138 if dep == wantDep { 139 found = true 140 } 141 }) 142 return found 143 } 144 145 if !hasDep(liba, prebuiltLiba) { 146 t.Errorf("liba missing dependency on prebuilt_liba") 147 } 148 149 if !hasDep(libb, prebuiltLibb) { 150 t.Errorf("libb missing dependency on prebuilt_libb") 151 } 152 153 if !hasDep(libd, prebuiltLibd) { 154 t.Errorf("libd missing dependency on prebuilt_libd") 155 } 156 157 if !hasDep(libe, prebuiltLibe) { 158 t.Errorf("libe missing dependency on prebuilt_libe") 159 } 160 161 if !hasDep(libfStatic, prebuiltLibfStatic) { 162 t.Errorf("libf static missing dependency on prebuilt_libf") 163 } 164 165 if !hasDep(libfShared, prebuiltLibfShared) { 166 t.Errorf("libf shared missing dependency on prebuilt_libf") 167 } 168 169 if !hasDep(crtx, prebuiltCrtx) { 170 t.Errorf("crtx missing dependency on prebuilt_crtx") 171 } 172} 173 174func TestPrebuiltLibraryShared(t *testing.T) { 175 ctx := testPrebuilt(t, ` 176 cc_prebuilt_library_shared { 177 name: "libtest", 178 srcs: ["libf.so"], 179 strip: { 180 none: true, 181 }, 182 } 183 `, map[string][]byte{ 184 "libf.so": nil, 185 }) 186 187 shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module) 188 assertString(t, shared.OutputFile().Path().Base(), "libtest.so") 189} 190 191func TestPrebuiltLibraryStatic(t *testing.T) { 192 ctx := testPrebuilt(t, ` 193 cc_prebuilt_library_static { 194 name: "libtest", 195 srcs: ["libf.a"], 196 } 197 `, map[string][]byte{ 198 "libf.a": nil, 199 }) 200 201 static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) 202 assertString(t, static.OutputFile().Path().Base(), "libf.a") 203} 204 205func TestPrebuiltLibrary(t *testing.T) { 206 ctx := testPrebuilt(t, ` 207 cc_prebuilt_library { 208 name: "libtest", 209 static: { 210 srcs: ["libf.a"], 211 }, 212 shared: { 213 srcs: ["libf.so"], 214 }, 215 strip: { 216 none: true, 217 }, 218 } 219 `, map[string][]byte{ 220 "libf.a": nil, 221 "libf.so": nil, 222 }) 223 224 shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module) 225 assertString(t, shared.OutputFile().Path().Base(), "libtest.so") 226 227 static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) 228 assertString(t, static.OutputFile().Path().Base(), "libf.a") 229} 230 231func TestPrebuiltLibraryStem(t *testing.T) { 232 ctx := testPrebuilt(t, ` 233 cc_prebuilt_library { 234 name: "libfoo", 235 stem: "libbar", 236 static: { 237 srcs: ["libfoo.a"], 238 }, 239 shared: { 240 srcs: ["libfoo.so"], 241 }, 242 strip: { 243 none: true, 244 }, 245 } 246 `, map[string][]byte{ 247 "libfoo.a": nil, 248 "libfoo.so": nil, 249 }) 250 251 static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module) 252 assertString(t, static.OutputFile().Path().Base(), "libfoo.a") 253 254 shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module) 255 assertString(t, shared.OutputFile().Path().Base(), "libbar.so") 256} 257 258func TestPrebuiltLibrarySharedStem(t *testing.T) { 259 ctx := testPrebuilt(t, ` 260 cc_prebuilt_library_shared { 261 name: "libfoo", 262 stem: "libbar", 263 srcs: ["libfoo.so"], 264 strip: { 265 none: true, 266 }, 267 } 268 `, map[string][]byte{ 269 "libfoo.so": nil, 270 }) 271 272 shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module) 273 assertString(t, shared.OutputFile().Path().Base(), "libbar.so") 274} 275 276func TestPrebuiltSymlinkedHostBinary(t *testing.T) { 277 if runtime.GOOS != "linux" { 278 t.Skipf("Skipping host prebuilt testing that is only supported on linux not %s", runtime.GOOS) 279 } 280 281 ctx := testPrebuilt(t, ` 282 cc_prebuilt_library_shared { 283 name: "libfoo", 284 device_supported: false, 285 host_supported: true, 286 target: { 287 linux_glibc_x86_64: { 288 srcs: ["linux_glibc_x86_64/lib64/libfoo.so"], 289 }, 290 }, 291 } 292 293 cc_prebuilt_binary { 294 name: "foo", 295 device_supported: false, 296 host_supported: true, 297 shared_libs: ["libfoo"], 298 target: { 299 linux_glibc_x86_64: { 300 srcs: ["linux_glibc_x86_64/bin/foo"], 301 }, 302 }, 303 } 304 `, map[string][]byte{ 305 "libfoo.so": nil, 306 "foo": nil, 307 }) 308 309 fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink") 310 assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo") 311 assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo") 312 313 var libfooDep android.Path 314 for _, dep := range fooRule.Implicits { 315 if dep.Base() == "libfoo.so" { 316 libfooDep = dep 317 break 318 } 319 } 320 assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so") 321} 322 323func TestPrebuiltLibrarySanitized(t *testing.T) { 324 bp := `cc_prebuilt_library { 325 name: "libtest", 326 static: { 327 sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, }, 328 }, 329 shared: { 330 sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, }, 331 }, 332 } 333 cc_prebuilt_library_static { 334 name: "libtest_static", 335 sanitized: { none: { srcs: ["libf.a"], }, hwaddress: { srcs: ["libf.hwasan.a"], }, }, 336 } 337 cc_prebuilt_library_shared { 338 name: "libtest_shared", 339 sanitized: { none: { srcs: ["libf.so"], }, hwaddress: { srcs: ["hwasan/libf.so"], }, }, 340 }` 341 342 fs := map[string][]byte{ 343 "libf.a": nil, 344 "libf.hwasan.a": nil, 345 "libf.so": nil, 346 "hwasan/libf.so": nil, 347 } 348 349 // Without SANITIZE_TARGET. 350 ctx := testPrebuilt(t, bp, fs) 351 352 shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip") 353 assertString(t, shared_rule.Input.String(), "libf.so") 354 355 static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module) 356 assertString(t, static.OutputFile().Path().Base(), "libf.a") 357 358 shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip") 359 assertString(t, shared_rule2.Input.String(), "libf.so") 360 361 static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module) 362 assertString(t, static2.OutputFile().Path().Base(), "libf.a") 363 364 // With SANITIZE_TARGET=hwaddress 365 ctx = testPrebuilt(t, bp, fs, 366 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 367 variables.SanitizeDevice = []string{"hwaddress"} 368 }), 369 ) 370 371 shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip") 372 assertString(t, shared_rule.Input.String(), "hwasan/libf.so") 373 374 static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module) 375 assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a") 376 377 shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip") 378 assertString(t, shared_rule2.Input.String(), "hwasan/libf.so") 379 380 static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module) 381 assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a") 382} 383 384func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) { 385 const bp = ` 386cc_prebuilt_library_shared { 387 name: "foo", 388 srcs: ["foo.so"], 389 bazel_module: { label: "//foo/bar:bar" }, 390}` 391 outBaseDir := "outputbase" 392 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 393 config.BazelContext = android.MockBazelContext{ 394 OutputBaseDir: outBaseDir, 395 LabelToCcInfo: map[string]cquery.CcInfo{ 396 "//foo/bar:bar": cquery.CcInfo{ 397 CcSharedLibraryFiles: []string{"foo.so"}, 398 }, 399 }, 400 } 401 ctx := testCcWithConfig(t, config) 402 sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() 403 pathPrefix := outBaseDir + "/execroot/__main__/" 404 405 info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) 406 android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", 407 pathPrefix+"foo.so", info.SharedLibrary) 408 android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC", 409 pathPrefix+"foo.so", info.TableOfContents.Path()) 410 411 outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") 412 if err != nil { 413 t.Errorf("Unexpected error getting cc_object outputfiles %s", err) 414 } 415 expectedOutputFiles := []string{pathPrefix + "foo.so"} 416 android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) 417} 418 419func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) { 420 const bp = ` 421cc_prebuilt_library_shared { 422 name: "foo", 423 srcs: ["foo.so"], 424 bazel_module: { label: "//foo/bar:bar" }, 425}` 426 outBaseDir := "outputbase" 427 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 428 config.BazelContext = android.MockBazelContext{ 429 OutputBaseDir: outBaseDir, 430 LabelToCcInfo: map[string]cquery.CcInfo{ 431 "//foo/bar:bar": cquery.CcInfo{ 432 CcSharedLibraryFiles: []string{"foo.so"}, 433 TocFile: "toc", 434 }, 435 }, 436 } 437 ctx := testCcWithConfig(t, config) 438 sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() 439 pathPrefix := outBaseDir + "/execroot/__main__/" 440 441 info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo) 442 android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC", 443 pathPrefix+"toc", info.TableOfContents.Path()) 444 android.AssertPathRelativeToTopEquals(t, "prebuilt shared library", 445 pathPrefix+"foo.so", info.SharedLibrary) 446 447 outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("") 448 if err != nil { 449 t.Errorf("Unexpected error getting cc_object outputfiles %s", err) 450 } 451 expectedOutputFiles := []string{pathPrefix + "foo.so"} 452 android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) 453} 454 455func TestPrebuiltStubNoinstall(t *testing.T) { 456 testFunc := func(t *testing.T, bp string) { 457 result := android.GroupFixturePreparers( 458 prepareForPrebuiltTest, 459 android.PrepareForTestWithMakevars, 460 ).RunTestWithBp(t, bp) 461 462 installRules := result.InstallMakeRulesForTesting(t) 463 var installedlibRule *android.InstallMakeRule 464 for i, rule := range installRules { 465 if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" { 466 if installedlibRule != nil { 467 t.Errorf("Duplicate install rules for %s", rule.Target) 468 } 469 installedlibRule = &installRules[i] 470 } 471 } 472 if installedlibRule == nil { 473 t.Errorf("No install rule found for installedlib") 474 return 475 } 476 477 android.AssertStringListDoesNotContain(t, 478 "installedlib has install dependency on stub", 479 installedlibRule.Deps, 480 "out/target/product/test_device/system/lib/stublib.so") 481 android.AssertStringListDoesNotContain(t, 482 "installedlib has order-only install dependency on stub", 483 installedlibRule.OrderOnlyDeps, 484 "out/target/product/test_device/system/lib/stublib.so") 485 } 486 487 const prebuiltStublibBp = ` 488 cc_prebuilt_library { 489 name: "stublib", 490 prefer: true, 491 srcs: ["foo.so"], 492 stubs: { 493 versions: ["1"], 494 }, 495 } 496 ` 497 498 const installedlibBp = ` 499 cc_library { 500 name: "installedlib", 501 shared_libs: ["stublib"], 502 } 503 ` 504 505 t.Run("prebuilt without source", func(t *testing.T) { 506 testFunc(t, prebuiltStublibBp+installedlibBp) 507 }) 508 509 const disabledSourceStublibBp = ` 510 cc_library { 511 name: "stublib", 512 enabled: false, 513 stubs: { 514 versions: ["1"], 515 }, 516 } 517 ` 518 519 t.Run("prebuilt with disabled source", func(t *testing.T) { 520 testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp) 521 }) 522} 523