1// Copyright 2021 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 bp2build 16 17import ( 18 "fmt" 19 "testing" 20 21 "android/soong/android" 22 "android/soong/cc" 23) 24 25const ( 26 // See cc/testing.go for more context 27 // TODO(alexmarquez): Split out the preamble into common code? 28 soongCcLibrarySharedPreamble = soongCcLibraryStaticPreamble 29) 30 31func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) { 32 cc.RegisterCCBuildComponents(ctx) 33 ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) 34 ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) 35 ctx.RegisterModuleType("cc_library", cc.LibraryFactory) 36} 37 38func runCcLibrarySharedTestCase(t *testing.T, tc bp2buildTestCase) { 39 t.Helper() 40 (&tc).moduleTypeUnderTest = "cc_library_shared" 41 (&tc).moduleTypeUnderTestFactory = cc.LibrarySharedFactory 42 runBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc) 43} 44 45func TestCcLibrarySharedSimple(t *testing.T) { 46 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 47 description: "cc_library_shared simple overall test", 48 filesystem: map[string]string{ 49 // NOTE: include_dir headers *should not* appear in Bazel hdrs later (?) 50 "include_dir_1/include_dir_1_a.h": "", 51 "include_dir_1/include_dir_1_b.h": "", 52 "include_dir_2/include_dir_2_a.h": "", 53 "include_dir_2/include_dir_2_b.h": "", 54 // NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?) 55 "local_include_dir_1/local_include_dir_1_a.h": "", 56 "local_include_dir_1/local_include_dir_1_b.h": "", 57 "local_include_dir_2/local_include_dir_2_a.h": "", 58 "local_include_dir_2/local_include_dir_2_b.h": "", 59 // NOTE: export_include_dir headers *should* appear in Bazel hdrs later 60 "export_include_dir_1/export_include_dir_1_a.h": "", 61 "export_include_dir_1/export_include_dir_1_b.h": "", 62 "export_include_dir_2/export_include_dir_2_a.h": "", 63 "export_include_dir_2/export_include_dir_2_b.h": "", 64 // NOTE: Soong implicitly includes headers in the current directory 65 "implicit_include_1.h": "", 66 "implicit_include_2.h": "", 67 }, 68 blueprint: soongCcLibrarySharedPreamble + ` 69cc_library_headers { 70 name: "header_lib_1", 71 export_include_dirs: ["header_lib_1"], 72 bazel_module: { bp2build_available: false }, 73} 74 75cc_library_headers { 76 name: "header_lib_2", 77 export_include_dirs: ["header_lib_2"], 78 bazel_module: { bp2build_available: false }, 79} 80 81cc_library_shared { 82 name: "shared_lib_1", 83 srcs: ["shared_lib_1.cc"], 84 bazel_module: { bp2build_available: false }, 85} 86 87cc_library_shared { 88 name: "shared_lib_2", 89 srcs: ["shared_lib_2.cc"], 90 bazel_module: { bp2build_available: false }, 91} 92 93cc_library_static { 94 name: "whole_static_lib_1", 95 srcs: ["whole_static_lib_1.cc"], 96 bazel_module: { bp2build_available: false }, 97} 98 99cc_library_static { 100 name: "whole_static_lib_2", 101 srcs: ["whole_static_lib_2.cc"], 102 bazel_module: { bp2build_available: false }, 103} 104 105cc_library_shared { 106 name: "foo_shared", 107 srcs: [ 108 "foo_shared1.cc", 109 "foo_shared2.cc", 110 ], 111 cflags: [ 112 "-Dflag1", 113 "-Dflag2" 114 ], 115 shared_libs: [ 116 "shared_lib_1", 117 "shared_lib_2" 118 ], 119 whole_static_libs: [ 120 "whole_static_lib_1", 121 "whole_static_lib_2" 122 ], 123 include_dirs: [ 124 "include_dir_1", 125 "include_dir_2", 126 ], 127 local_include_dirs: [ 128 "local_include_dir_1", 129 "local_include_dir_2", 130 ], 131 export_include_dirs: [ 132 "export_include_dir_1", 133 "export_include_dir_2" 134 ], 135 header_libs: [ 136 "header_lib_1", 137 "header_lib_2" 138 ], 139 sdk_version: "current", 140 min_sdk_version: "29", 141 142 // TODO: Also support export_header_lib_headers 143}`, 144 expectedBazelTargets: []string{ 145 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 146 "absolute_includes": `[ 147 "include_dir_1", 148 "include_dir_2", 149 ]`, 150 "copts": `[ 151 "-Dflag1", 152 "-Dflag2", 153 ]`, 154 "export_includes": `[ 155 "export_include_dir_1", 156 "export_include_dir_2", 157 ]`, 158 "implementation_deps": `[ 159 ":header_lib_1", 160 ":header_lib_2", 161 ]`, 162 "implementation_dynamic_deps": `[ 163 ":shared_lib_1", 164 ":shared_lib_2", 165 ]`, 166 "local_includes": `[ 167 "local_include_dir_1", 168 "local_include_dir_2", 169 ".", 170 ]`, 171 "srcs": `[ 172 "foo_shared1.cc", 173 "foo_shared2.cc", 174 ]`, 175 "whole_archive_deps": `[ 176 ":whole_static_lib_1", 177 ":whole_static_lib_2", 178 ]`, 179 "sdk_version": `"current"`, 180 "min_sdk_version": `"29"`, 181 }), 182 }, 183 }) 184} 185 186func TestCcLibrarySharedArchSpecificSharedLib(t *testing.T) { 187 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 188 description: "cc_library_shared arch-specific shared_libs with whole_static_libs", 189 filesystem: map[string]string{}, 190 blueprint: soongCcLibrarySharedPreamble + ` 191cc_library_static { 192 name: "static_dep", 193 bazel_module: { bp2build_available: false }, 194} 195cc_library_shared { 196 name: "shared_dep", 197 bazel_module: { bp2build_available: false }, 198} 199cc_library_shared { 200 name: "foo_shared", 201 arch: { arm64: { shared_libs: ["shared_dep"], whole_static_libs: ["static_dep"] } }, 202 include_build_directory: false, 203}`, 204 expectedBazelTargets: []string{ 205 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 206 "implementation_dynamic_deps": `select({ 207 "//build/bazel/platforms/arch:arm64": [":shared_dep"], 208 "//conditions:default": [], 209 })`, 210 "whole_archive_deps": `select({ 211 "//build/bazel/platforms/arch:arm64": [":static_dep"], 212 "//conditions:default": [], 213 })`, 214 }), 215 }, 216 }) 217} 218 219func TestCcLibrarySharedOsSpecificSharedLib(t *testing.T) { 220 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 221 description: "cc_library_shared os-specific shared_libs", 222 filesystem: map[string]string{}, 223 blueprint: soongCcLibrarySharedPreamble + ` 224cc_library_shared { 225 name: "shared_dep", 226 bazel_module: { bp2build_available: false }, 227} 228cc_library_shared { 229 name: "foo_shared", 230 target: { android: { shared_libs: ["shared_dep"], } }, 231 include_build_directory: false, 232}`, 233 expectedBazelTargets: []string{ 234 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 235 "implementation_dynamic_deps": `select({ 236 "//build/bazel/platforms/os:android": [":shared_dep"], 237 "//conditions:default": [], 238 })`, 239 }), 240 }, 241 }) 242} 243 244func TestCcLibrarySharedBaseArchOsSpecificSharedLib(t *testing.T) { 245 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 246 description: "cc_library_shared base, arch, and os-specific shared_libs", 247 filesystem: map[string]string{}, 248 blueprint: soongCcLibrarySharedPreamble + ` 249cc_library_shared { 250 name: "shared_dep", 251 bazel_module: { bp2build_available: false }, 252} 253cc_library_shared { 254 name: "shared_dep2", 255 bazel_module: { bp2build_available: false }, 256} 257cc_library_shared { 258 name: "shared_dep3", 259 bazel_module: { bp2build_available: false }, 260} 261cc_library_shared { 262 name: "foo_shared", 263 shared_libs: ["shared_dep"], 264 target: { android: { shared_libs: ["shared_dep2"] } }, 265 arch: { arm64: { shared_libs: ["shared_dep3"] } }, 266 include_build_directory: false, 267}`, 268 expectedBazelTargets: []string{ 269 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 270 "implementation_dynamic_deps": `[":shared_dep"] + select({ 271 "//build/bazel/platforms/arch:arm64": [":shared_dep3"], 272 "//conditions:default": [], 273 }) + select({ 274 "//build/bazel/platforms/os:android": [":shared_dep2"], 275 "//conditions:default": [], 276 })`, 277 }), 278 }, 279 }) 280} 281 282func TestCcLibrarySharedSimpleExcludeSrcs(t *testing.T) { 283 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 284 description: "cc_library_shared simple exclude_srcs", 285 filesystem: map[string]string{ 286 "common.c": "", 287 "foo-a.c": "", 288 "foo-excluded.c": "", 289 }, 290 blueprint: soongCcLibrarySharedPreamble + ` 291cc_library_shared { 292 name: "foo_shared", 293 srcs: ["common.c", "foo-*.c"], 294 exclude_srcs: ["foo-excluded.c"], 295 include_build_directory: false, 296}`, 297 expectedBazelTargets: []string{ 298 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 299 "srcs_c": `[ 300 "common.c", 301 "foo-a.c", 302 ]`, 303 }), 304 }, 305 }) 306} 307 308func TestCcLibrarySharedStrip(t *testing.T) { 309 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 310 description: "cc_library_shared stripping", 311 filesystem: map[string]string{}, 312 blueprint: soongCcLibrarySharedPreamble + ` 313cc_library_shared { 314 name: "foo_shared", 315 strip: { 316 keep_symbols: false, 317 keep_symbols_and_debug_frame: true, 318 keep_symbols_list: ["sym", "sym2"], 319 all: true, 320 none: false, 321 }, 322 include_build_directory: false, 323}`, 324 expectedBazelTargets: []string{ 325 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 326 "strip": `{ 327 "all": True, 328 "keep_symbols": False, 329 "keep_symbols_and_debug_frame": True, 330 "keep_symbols_list": [ 331 "sym", 332 "sym2", 333 ], 334 "none": False, 335 }`, 336 }), 337 }, 338 }) 339} 340 341func TestCcLibrarySharedVersionScript(t *testing.T) { 342 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 343 description: "cc_library_shared version script", 344 filesystem: map[string]string{ 345 "version_script": "", 346 }, 347 blueprint: soongCcLibrarySharedPreamble + ` 348cc_library_shared { 349 name: "foo_shared", 350 version_script: "version_script", 351 include_build_directory: false, 352}`, 353 expectedBazelTargets: []string{ 354 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 355 "additional_linker_inputs": `["version_script"]`, 356 "linkopts": `["-Wl,--version-script,$(location version_script)"]`, 357 }), 358 }, 359 }) 360} 361 362func TestCcLibrarySharedNoCrtTrue(t *testing.T) { 363 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 364 description: "cc_library_shared - nocrt: true emits attribute", 365 filesystem: map[string]string{ 366 "impl.cpp": "", 367 }, 368 blueprint: soongCcLibraryPreamble + ` 369cc_library_shared { 370 name: "foo_shared", 371 srcs: ["impl.cpp"], 372 nocrt: true, 373 include_build_directory: false, 374} 375`, 376 expectedBazelTargets: []string{ 377 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 378 "link_crt": `False`, 379 "srcs": `["impl.cpp"]`, 380 }), 381 }, 382 }) 383} 384 385func TestCcLibrarySharedNoCrtFalse(t *testing.T) { 386 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 387 description: "cc_library_shared - nocrt: false doesn't emit attribute", 388 filesystem: map[string]string{ 389 "impl.cpp": "", 390 }, 391 blueprint: soongCcLibraryPreamble + ` 392cc_library_shared { 393 name: "foo_shared", 394 srcs: ["impl.cpp"], 395 nocrt: false, 396 include_build_directory: false, 397} 398`, 399 expectedBazelTargets: []string{ 400 makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{ 401 "srcs": `["impl.cpp"]`, 402 }), 403 }, 404 }) 405} 406 407func TestCcLibrarySharedNoCrtArchVariant(t *testing.T) { 408 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 409 description: "cc_library_shared - nocrt in select", 410 filesystem: map[string]string{ 411 "impl.cpp": "", 412 }, 413 blueprint: soongCcLibraryPreamble + ` 414cc_library_shared { 415 name: "foo_shared", 416 srcs: ["impl.cpp"], 417 arch: { 418 arm: { 419 nocrt: true, 420 }, 421 x86: { 422 nocrt: false, 423 }, 424 }, 425 include_build_directory: false, 426} 427`, 428 expectedErr: fmt.Errorf("module \"foo_shared\": nocrt is not supported for arch variants"), 429 }) 430} 431 432func TestCcLibrarySharedProto(t *testing.T) { 433 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 434 blueprint: soongCcProtoPreamble + `cc_library_shared { 435 name: "foo", 436 srcs: ["foo.proto"], 437 proto: { 438 export_proto_headers: true, 439 }, 440 include_build_directory: false, 441}`, 442 expectedBazelTargets: []string{ 443 makeBazelTarget("proto_library", "foo_proto", attrNameToString{ 444 "srcs": `["foo.proto"]`, 445 }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{ 446 "deps": `[":foo_proto"]`, 447 }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{ 448 "dynamic_deps": `[":libprotobuf-cpp-lite"]`, 449 "whole_archive_deps": `[":foo_cc_proto_lite"]`, 450 }), 451 }, 452 }) 453} 454 455func TestCcLibrarySharedUseVersionLib(t *testing.T) { 456 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 457 blueprint: soongCcProtoPreamble + `cc_library_shared { 458 name: "foo", 459 use_version_lib: true, 460 include_build_directory: false, 461}`, 462 expectedBazelTargets: []string{ 463 makeBazelTarget("cc_library_shared", "foo", attrNameToString{ 464 "use_version_lib": "True", 465 }), 466 }, 467 }) 468} 469 470func TestCcLibrarySharedStubs(t *testing.T) { 471 runCcLibrarySharedTestCase(t, bp2buildTestCase{ 472 description: "cc_library_shared stubs", 473 moduleTypeUnderTest: "cc_library_shared", 474 moduleTypeUnderTestFactory: cc.LibrarySharedFactory, 475 dir: "foo/bar", 476 filesystem: map[string]string{ 477 "foo/bar/Android.bp": ` 478cc_library_shared { 479 name: "a", 480 stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, 481 bazel_module: { bp2build_available: true }, 482 include_build_directory: false, 483} 484`, 485 }, 486 blueprint: soongCcLibraryPreamble, 487 expectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "a", attrNameToString{ 488 "stubs_symbol_file": `"a.map.txt"`, 489 "stubs_versions": `[ 490 "28", 491 "29", 492 "current", 493 ]`, 494 }), 495 }, 496 }, 497 ) 498} 499