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 "testing" 19 20 "android/soong/android" 21 "android/soong/cc" 22) 23 24const ( 25 // See cc/testing.go for more context 26 soongCcLibraryHeadersPreamble = ` 27cc_defaults { 28 name: "linux_bionic_supported", 29}` 30) 31 32func TestCcLibraryHeadersLoadStatement(t *testing.T) { 33 testCases := []struct { 34 bazelTargets BazelTargets 35 expectedLoadStatements string 36 }{ 37 { 38 bazelTargets: BazelTargets{ 39 BazelTarget{ 40 name: "cc_library_headers_target", 41 ruleClass: "cc_library_headers", 42 // Note: no bzlLoadLocation for native rules 43 }, 44 }, 45 expectedLoadStatements: ``, 46 }, 47 } 48 49 for _, testCase := range testCases { 50 actual := testCase.bazelTargets.LoadStatements() 51 expected := testCase.expectedLoadStatements 52 if actual != expected { 53 t.Fatalf("Expected load statements to be %s, got %s", expected, actual) 54 } 55 } 56} 57 58func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) { 59 cc.RegisterCCBuildComponents(ctx) 60} 61 62func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) { 63 t.Helper() 64 RunBp2BuildTestCase(t, registerCcLibraryHeadersModuleTypes, tc) 65} 66 67func TestCcLibraryHeadersSimple(t *testing.T) { 68 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 69 Description: "cc_library_headers test", 70 ModuleTypeUnderTest: "cc_library_headers", 71 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 72 Filesystem: map[string]string{ 73 "lib-1/lib1a.h": "", 74 "lib-1/lib1b.h": "", 75 "lib-2/lib2a.h": "", 76 "lib-2/lib2b.h": "", 77 "dir-1/dir1a.h": "", 78 "dir-1/dir1b.h": "", 79 "dir-2/dir2a.h": "", 80 "dir-2/dir2b.h": "", 81 "arch_arm64_exported_include_dir/a.h": "", 82 "arch_x86_exported_include_dir/b.h": "", 83 "arch_x86_64_exported_include_dir/c.h": "", 84 }, 85 Blueprint: soongCcLibraryHeadersPreamble + ` 86cc_library_headers { 87 name: "foo_headers", 88 export_include_dirs: ["dir-1", "dir-2"], 89 header_libs: ["lib-1", "lib-2"], 90 91 arch: { 92 arm64: { 93 // We expect dir-1 headers to be dropped, because dir-1 is already in export_include_dirs 94 export_include_dirs: ["arch_arm64_exported_include_dir", "dir-1"], 95 }, 96 x86: { 97 export_include_dirs: ["arch_x86_exported_include_dir"], 98 }, 99 x86_64: { 100 export_include_dirs: ["arch_x86_64_exported_include_dir"], 101 }, 102 }, 103 sdk_version: "current", 104 min_sdk_version: "29", 105 106 // TODO: Also support export_header_lib_headers 107}`, 108 ExpectedBazelTargets: []string{ 109 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 110 "export_includes": `select({ 111 "//build/bazel/platforms/arch:arm64": ["arch_arm64_exported_include_dir"], 112 "//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir"], 113 "//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir"], 114 "//conditions:default": [], 115 }) + [ 116 "dir-1", 117 "dir-2", 118 ]`, 119 "sdk_version": `"current"`, 120 "min_sdk_version": `"29"`, 121 }), 122 }, 123 }) 124} 125 126func TestCcApiHeaders(t *testing.T) { 127 fs := map[string]string{ 128 "bar/Android.bp": `cc_library_headers { name: "bar_headers", }`, 129 } 130 bp := ` 131 cc_library_headers { 132 name: "foo_headers", 133 export_include_dirs: ["dir1", "dir2"], 134 export_header_lib_headers: ["bar_headers"], 135 136 arch: { 137 arm: { 138 export_include_dirs: ["dir_arm"], 139 }, 140 x86: { 141 export_include_dirs: ["dir_x86"], 142 }, 143 }, 144 145 target: { 146 android: { 147 export_include_dirs: ["dir1", "dir_android"], 148 }, 149 windows: { 150 export_include_dirs: ["dir_windows"], 151 }, 152 } 153 } 154 ` 155 expectedBazelTargets := []string{ 156 MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{ 157 "export_includes": `["dir_arm"]`, 158 "arch": `"arm"`, 159 }), 160 MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{ 161 "export_includes": `["dir_x86"]`, 162 "arch": `"x86"`, 163 }), 164 MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{ 165 "export_includes": `["dir_android"]`, // common includes are deduped 166 }), 167 // Windows headers are not exported 168 MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{ 169 "export_includes": `[ 170 "dir1", 171 "dir2", 172 ]`, 173 "deps": `[ 174 "//bar:bar_headers.contribution", 175 ":foo_headers.contribution.arm", 176 ":foo_headers.contribution.x86", 177 ":foo_headers.contribution.androidos", 178 ]`, 179 }), 180 } 181 RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{ 182 Blueprint: bp, 183 Description: "Header library contributions to API surfaces", 184 ExpectedBazelTargets: expectedBazelTargets, 185 Filesystem: fs, 186 }) 187} 188 189// header_libs has "variant_prepend" tag. In bp2build output, 190// variant info(select) should go before general info. 191func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) { 192 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 193 Description: "cc_library_headers test with os-specific header_libs props", 194 ModuleTypeUnderTest: "cc_library_headers", 195 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 196 Filesystem: map[string]string{}, 197 Blueprint: soongCcLibraryPreamble + ` 198cc_library_headers { 199 name: "android-lib", 200 bazel_module: { bp2build_available: false }, 201} 202cc_library_headers { 203 name: "base-lib", 204 bazel_module: { bp2build_available: false }, 205} 206cc_library_headers { 207 name: "darwin-lib", 208 bazel_module: { bp2build_available: false }, 209} 210cc_library_headers { 211 name: "linux-lib", 212 bazel_module: { bp2build_available: false }, 213} 214cc_library_headers { 215 name: "linux_bionic-lib", 216 bazel_module: { bp2build_available: false }, 217} 218cc_library_headers { 219 name: "windows-lib", 220 bazel_module: { bp2build_available: false }, 221} 222cc_library_headers { 223 name: "foo_headers", 224 header_libs: ["base-lib"], 225 export_header_lib_headers: ["base-lib"], 226 target: { 227 android: { 228 header_libs: ["android-lib"], 229 export_header_lib_headers: ["android-lib"], 230 }, 231 darwin: { 232 header_libs: ["darwin-lib"], 233 export_header_lib_headers: ["darwin-lib"], 234 }, 235 linux_bionic: { 236 header_libs: ["linux_bionic-lib"], 237 export_header_lib_headers: ["linux_bionic-lib"], 238 }, 239 linux_glibc: { 240 header_libs: ["linux-lib"], 241 export_header_lib_headers: ["linux-lib"], 242 }, 243 windows: { 244 header_libs: ["windows-lib"], 245 export_header_lib_headers: ["windows-lib"], 246 }, 247 }, 248 include_build_directory: false, 249}`, 250 ExpectedBazelTargets: []string{ 251 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 252 "deps": `select({ 253 "//build/bazel/platforms/os:android": [":android-lib"], 254 "//build/bazel/platforms/os:darwin": [":darwin-lib"], 255 "//build/bazel/platforms/os:linux_bionic": [":linux_bionic-lib"], 256 "//build/bazel/platforms/os:linux_glibc": [":linux-lib"], 257 "//build/bazel/platforms/os:windows": [":windows-lib"], 258 "//conditions:default": [], 259 }) + [":base-lib"]`, 260 }), 261 }, 262 }) 263} 264 265func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) { 266 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 267 Description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props", 268 ModuleTypeUnderTest: "cc_library_headers", 269 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 270 Filesystem: map[string]string{}, 271 Blueprint: soongCcLibraryPreamble + ` 272cc_library_headers { 273 name: "android-lib", 274 bazel_module: { bp2build_available: false }, 275 } 276cc_library_headers { 277 name: "exported-lib", 278 bazel_module: { bp2build_available: false }, 279} 280cc_library_headers { 281 name: "foo_headers", 282 target: { 283 android: { 284 header_libs: ["android-lib", "exported-lib"], 285 export_header_lib_headers: ["exported-lib"] 286 }, 287 }, 288 include_build_directory: false, 289}`, 290 ExpectedBazelTargets: []string{ 291 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 292 "deps": `select({ 293 "//build/bazel/platforms/os:android": [":exported-lib"], 294 "//conditions:default": [], 295 })`, 296 }), 297 }, 298 }) 299} 300 301func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { 302 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 303 Description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props", 304 ModuleTypeUnderTest: "cc_library_headers", 305 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 306 Filesystem: map[string]string{}, 307 Blueprint: soongCcLibraryPreamble + `cc_library_headers { 308 name: "foo_headers", 309 export_system_include_dirs: [ 310 "shared_include_dir", 311 ], 312 target: { 313 android: { 314 export_system_include_dirs: [ 315 "android_include_dir", 316 ], 317 }, 318 linux_glibc: { 319 export_system_include_dirs: [ 320 "linux_include_dir", 321 ], 322 }, 323 darwin: { 324 export_system_include_dirs: [ 325 "darwin_include_dir", 326 ], 327 }, 328 }, 329 arch: { 330 arm: { 331 export_system_include_dirs: [ 332 "arm_include_dir", 333 ], 334 }, 335 x86_64: { 336 export_system_include_dirs: [ 337 "x86_64_include_dir", 338 ], 339 }, 340 }, 341 include_build_directory: false, 342}`, 343 ExpectedBazelTargets: []string{ 344 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 345 "export_system_includes": `select({ 346 "//build/bazel/platforms/os:android": ["android_include_dir"], 347 "//build/bazel/platforms/os:darwin": ["darwin_include_dir"], 348 "//build/bazel/platforms/os:linux_glibc": ["linux_include_dir"], 349 "//conditions:default": [], 350 }) + select({ 351 "//build/bazel/platforms/arch:arm": ["arm_include_dir"], 352 "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"], 353 "//conditions:default": [], 354 }) + ["shared_include_dir"]`, 355 }), 356 }, 357 }) 358} 359 360func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) { 361 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 362 Description: "cc_library_headers test", 363 ModuleTypeUnderTest: "cc_library_headers", 364 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 365 Filesystem: map[string]string{ 366 "lib-1/lib1a.h": "", 367 "lib-1/lib1b.h": "", 368 "lib-2/lib2a.h": "", 369 "lib-2/lib2b.h": "", 370 "dir-1/dir1a.h": "", 371 "dir-1/dir1b.h": "", 372 "dir-2/dir2a.h": "", 373 "dir-2/dir2b.h": "", 374 "arch_arm64_exported_include_dir/a.h": "", 375 "arch_x86_exported_include_dir/b.h": "", 376 "arch_x86_64_exported_include_dir/c.h": "", 377 }, 378 Blueprint: soongCcLibraryHeadersPreamble + ` 379cc_library_headers { 380 name: "lib-1", 381 export_include_dirs: ["lib-1"], 382 no_libcrt: true, 383 include_build_directory: false, 384}`, 385 ExpectedBazelTargets: []string{ 386 MakeBazelTarget("cc_library_headers", "lib-1", AttrNameToString{ 387 "export_includes": `["lib-1"]`, 388 }), 389 }, 390 }) 391} 392 393func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) { 394 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 395 Description: "cc_library_headers exported_static_lib_headers is reexported", 396 ModuleTypeUnderTest: "cc_library_headers", 397 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 398 Filesystem: map[string]string{}, 399 Blueprint: soongCcLibraryHeadersPreamble + ` 400cc_library_headers { 401 name: "foo_headers", 402 export_static_lib_headers: ["foo_export"], 403 static_libs: ["foo_export", "foo_no_reexport"], 404 bazel_module: { bp2build_available: true }, 405} 406` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), 407 ExpectedBazelTargets: []string{ 408 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 409 "deps": `[":foo_export"]`, 410 }), 411 }, 412 }) 413} 414 415func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) { 416 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 417 Description: "cc_library_headers exported_shared_lib_headers is reexported", 418 ModuleTypeUnderTest: "cc_library_headers", 419 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 420 Filesystem: map[string]string{}, 421 Blueprint: soongCcLibraryHeadersPreamble + ` 422cc_library_headers { 423 name: "foo_headers", 424 export_shared_lib_headers: ["foo_export"], 425 shared_libs: ["foo_export", "foo_no_reexport"], 426 bazel_module: { bp2build_available: true }, 427} 428` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), 429 ExpectedBazelTargets: []string{ 430 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 431 "deps": `[":foo_export"]`, 432 }), 433 }, 434 }) 435} 436 437func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) { 438 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 439 Description: "cc_library_headers exported_header_lib_headers is reexported", 440 ModuleTypeUnderTest: "cc_library_headers", 441 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 442 Filesystem: map[string]string{}, 443 Blueprint: soongCcLibraryHeadersPreamble + ` 444cc_library_headers { 445 name: "foo_headers", 446 export_header_lib_headers: ["foo_export"], 447 header_libs: ["foo_export", "foo_no_reexport"], 448 bazel_module: { bp2build_available: true }, 449} 450` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), 451 ExpectedBazelTargets: []string{ 452 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 453 "deps": `[":foo_export"]`, 454 }), 455 }, 456 }) 457} 458 459func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) { 460 runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ 461 Description: "cc_library_headers whole_static_libs is reexported", 462 ModuleTypeUnderTest: "cc_library_headers", 463 ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, 464 Filesystem: map[string]string{}, 465 Blueprint: soongCcLibraryHeadersPreamble + ` 466cc_library_headers { 467 name: "foo_headers", 468 whole_static_libs: ["foo_export"], 469 bazel_module: { bp2build_available: true }, 470} 471` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), 472 ExpectedBazelTargets: []string{ 473 MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ 474 "deps": `[":foo_export"]`, 475 }), 476 }, 477 }) 478} 479