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 24func registerCcObjectModuleTypes(ctx android.RegistrationContext) { 25 // Always register cc_defaults module factory 26 ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() }) 27 ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) 28} 29 30func runCcObjectTestCase(t *testing.T, tc Bp2buildTestCase) { 31 t.Helper() 32 (&tc).ModuleTypeUnderTest = "cc_object" 33 (&tc).ModuleTypeUnderTestFactory = cc.ObjectFactory 34 RunBp2BuildTestCase(t, registerCcObjectModuleTypes, tc) 35} 36 37func TestCcObjectSimple(t *testing.T) { 38 runCcObjectTestCase(t, Bp2buildTestCase{ 39 Description: "simple cc_object generates cc_object with include header dep", 40 Filesystem: map[string]string{ 41 "a/b/foo.h": "", 42 "a/b/bar.h": "", 43 "a/b/exclude.c": "", 44 "a/b/c.c": "", 45 }, 46 Blueprint: `cc_object { 47 name: "foo", 48 local_include_dirs: ["include"], 49 system_shared_libs: [], 50 cflags: [ 51 "-Wno-gcc-compat", 52 "-Wall", 53 "-Werror", 54 ], 55 srcs: [ 56 "a/b/*.c" 57 ], 58 exclude_srcs: ["a/b/exclude.c"], 59 sdk_version: "current", 60 min_sdk_version: "29", 61 crt: true, 62} 63`, 64 ExpectedBazelTargets: []string{ 65 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 66 "copts": `[ 67 "-fno-addrsig", 68 "-Wno-gcc-compat", 69 "-Wall", 70 "-Werror", 71 ]`, 72 "local_includes": `[ 73 "include", 74 ".", 75 ]`, 76 "srcs": `["a/b/c.c"]`, 77 "system_dynamic_deps": `[]`, 78 "sdk_version": `"current"`, 79 "min_sdk_version": `"29"`, 80 "crt": "True", 81 }), 82 }, 83 }) 84} 85 86func TestCcObjectDefaults(t *testing.T) { 87 runCcObjectTestCase(t, Bp2buildTestCase{ 88 Blueprint: `cc_object { 89 name: "foo", 90 system_shared_libs: [], 91 srcs: [ 92 "a/b/*.h", 93 "a/b/c.c" 94 ], 95 96 defaults: ["foo_defaults"], 97} 98 99cc_defaults { 100 name: "foo_defaults", 101 defaults: ["foo_bar_defaults"], 102} 103 104cc_defaults { 105 name: "foo_bar_defaults", 106 cflags: [ 107 "-Werror", 108 ], 109} 110`, 111 ExpectedBazelTargets: []string{ 112 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 113 "copts": `[ 114 "-Werror", 115 "-fno-addrsig", 116 ]`, 117 "local_includes": `["."]`, 118 "srcs": `["a/b/c.c"]`, 119 "system_dynamic_deps": `[]`, 120 }), 121 }}) 122} 123 124func TestCcObjectCcObjetDepsInObjs(t *testing.T) { 125 runCcObjectTestCase(t, Bp2buildTestCase{ 126 Description: "cc_object with cc_object deps in objs props", 127 Filesystem: map[string]string{ 128 "a/b/c.c": "", 129 "x/y/z.c": "", 130 }, 131 Blueprint: `cc_object { 132 name: "foo", 133 system_shared_libs: [], 134 srcs: ["a/b/c.c"], 135 objs: ["bar"], 136 include_build_directory: false, 137} 138 139cc_object { 140 name: "bar", 141 system_shared_libs: [], 142 srcs: ["x/y/z.c"], 143 include_build_directory: false, 144} 145`, 146 ExpectedBazelTargets: []string{ 147 MakeBazelTarget("cc_object", "bar", AttrNameToString{ 148 "copts": `["-fno-addrsig"]`, 149 "srcs": `["x/y/z.c"]`, 150 "system_dynamic_deps": `[]`, 151 }), MakeBazelTarget("cc_object", "foo", AttrNameToString{ 152 "copts": `["-fno-addrsig"]`, 153 "objs": `[":bar"]`, 154 "srcs": `["a/b/c.c"]`, 155 "system_dynamic_deps": `[]`, 156 }), 157 }, 158 }) 159} 160 161func TestCcObjectIncludeBuildDirFalse(t *testing.T) { 162 runCcObjectTestCase(t, Bp2buildTestCase{ 163 Description: "cc_object with include_build_dir: false", 164 Filesystem: map[string]string{ 165 "a/b/c.c": "", 166 "x/y/z.c": "", 167 }, 168 Blueprint: `cc_object { 169 name: "foo", 170 system_shared_libs: [], 171 srcs: ["a/b/c.c"], 172 include_build_directory: false, 173} 174`, 175 ExpectedBazelTargets: []string{ 176 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 177 "copts": `["-fno-addrsig"]`, 178 "srcs": `["a/b/c.c"]`, 179 "system_dynamic_deps": `[]`, 180 }), 181 }, 182 }) 183} 184 185func TestCcObjectProductVariable(t *testing.T) { 186 runCcObjectTestCase(t, Bp2buildTestCase{ 187 Description: "cc_object with product variable", 188 Blueprint: `cc_object { 189 name: "foo", 190 system_shared_libs: [], 191 include_build_directory: false, 192 product_variables: { 193 platform_sdk_version: { 194 asflags: ["-DPLATFORM_SDK_VERSION=%d"], 195 }, 196 }, 197 srcs: ["src.S"], 198} 199`, 200 ExpectedBazelTargets: []string{ 201 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 202 "asflags": `select({ 203 "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"], 204 "//conditions:default": [], 205 })`, 206 "copts": `["-fno-addrsig"]`, 207 "srcs_as": `["src.S"]`, 208 "system_dynamic_deps": `[]`, 209 }), 210 }, 211 }) 212} 213 214func TestCcObjectCflagsOneArch(t *testing.T) { 215 runCcObjectTestCase(t, Bp2buildTestCase{ 216 Description: "cc_object setting cflags for one arch", 217 Blueprint: `cc_object { 218 name: "foo", 219 system_shared_libs: [], 220 srcs: ["a.cpp"], 221 arch: { 222 x86: { 223 cflags: ["-fPIC"], // string list 224 }, 225 arm: { 226 srcs: ["arch/arm/file.cpp"], // label list 227 }, 228 }, 229 include_build_directory: false, 230} 231`, 232 ExpectedBazelTargets: []string{ 233 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 234 "copts": `["-fno-addrsig"] + select({ 235 "//build/bazel/platforms/arch:x86": ["-fPIC"], 236 "//conditions:default": [], 237 })`, 238 "srcs": `["a.cpp"] + select({ 239 "//build/bazel/platforms/arch:arm": ["arch/arm/file.cpp"], 240 "//conditions:default": [], 241 })`, 242 "system_dynamic_deps": `[]`, 243 }), 244 }, 245 }) 246} 247 248func TestCcObjectCflagsFourArch(t *testing.T) { 249 runCcObjectTestCase(t, Bp2buildTestCase{ 250 Description: "cc_object setting cflags for 4 architectures", 251 Blueprint: `cc_object { 252 name: "foo", 253 system_shared_libs: [], 254 srcs: ["base.cpp"], 255 arch: { 256 x86: { 257 srcs: ["x86.cpp"], 258 cflags: ["-fPIC"], 259 }, 260 x86_64: { 261 srcs: ["x86_64.cpp"], 262 cflags: ["-fPIC"], 263 }, 264 arm: { 265 srcs: ["arm.cpp"], 266 cflags: ["-Wall"], 267 }, 268 arm64: { 269 srcs: ["arm64.cpp"], 270 cflags: ["-Wall"], 271 }, 272 }, 273 include_build_directory: false, 274} 275`, 276 ExpectedBazelTargets: []string{ 277 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 278 "copts": `["-fno-addrsig"] + select({ 279 "//build/bazel/platforms/arch:arm": ["-Wall"], 280 "//build/bazel/platforms/arch:arm64": ["-Wall"], 281 "//build/bazel/platforms/arch:x86": ["-fPIC"], 282 "//build/bazel/platforms/arch:x86_64": ["-fPIC"], 283 "//conditions:default": [], 284 })`, 285 "srcs": `["base.cpp"] + select({ 286 "//build/bazel/platforms/arch:arm": ["arm.cpp"], 287 "//build/bazel/platforms/arch:arm64": ["arm64.cpp"], 288 "//build/bazel/platforms/arch:x86": ["x86.cpp"], 289 "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"], 290 "//conditions:default": [], 291 })`, 292 "system_dynamic_deps": `[]`, 293 }), 294 }, 295 }) 296} 297 298func TestCcObjectLinkerScript(t *testing.T) { 299 runCcObjectTestCase(t, Bp2buildTestCase{ 300 Description: "cc_object setting linker_script", 301 Blueprint: `cc_object { 302 name: "foo", 303 srcs: ["base.cpp"], 304 linker_script: "bunny.lds", 305 include_build_directory: false, 306} 307`, 308 ExpectedBazelTargets: []string{ 309 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 310 "copts": `["-fno-addrsig"]`, 311 "linker_script": `"bunny.lds"`, 312 "srcs": `["base.cpp"]`, 313 }), 314 }, 315 }) 316} 317 318func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) { 319 runCcObjectTestCase(t, Bp2buildTestCase{ 320 Description: "cc_object setting deps and linker_script across archs", 321 Blueprint: `cc_object { 322 name: "foo", 323 srcs: ["base.cpp"], 324 arch: { 325 x86: { 326 objs: ["x86_obj"], 327 linker_script: "x86.lds", 328 }, 329 x86_64: { 330 objs: ["x86_64_obj"], 331 linker_script: "x86_64.lds", 332 }, 333 arm: { 334 objs: ["arm_obj"], 335 linker_script: "arm.lds", 336 }, 337 }, 338 include_build_directory: false, 339} 340 341cc_object { 342 name: "x86_obj", 343 system_shared_libs: [], 344 srcs: ["x86.cpp"], 345 include_build_directory: false, 346 bazel_module: { bp2build_available: false }, 347} 348 349cc_object { 350 name: "x86_64_obj", 351 system_shared_libs: [], 352 srcs: ["x86_64.cpp"], 353 include_build_directory: false, 354 bazel_module: { bp2build_available: false }, 355} 356 357cc_object { 358 name: "arm_obj", 359 system_shared_libs: [], 360 srcs: ["arm.cpp"], 361 include_build_directory: false, 362 bazel_module: { bp2build_available: false }, 363} 364`, 365 ExpectedBazelTargets: []string{ 366 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 367 "copts": `["-fno-addrsig"]`, 368 "objs": `select({ 369 "//build/bazel/platforms/arch:arm": [":arm_obj"], 370 "//build/bazel/platforms/arch:x86": [":x86_obj"], 371 "//build/bazel/platforms/arch:x86_64": [":x86_64_obj"], 372 "//conditions:default": [], 373 })`, 374 "linker_script": `select({ 375 "//build/bazel/platforms/arch:arm": "arm.lds", 376 "//build/bazel/platforms/arch:x86": "x86.lds", 377 "//build/bazel/platforms/arch:x86_64": "x86_64.lds", 378 "//conditions:default": None, 379 })`, 380 "srcs": `["base.cpp"]`, 381 }), 382 }, 383 }) 384} 385 386func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) { 387 runCcObjectTestCase(t, Bp2buildTestCase{ 388 Description: "cc_object setting srcs based on linux and bionic archs", 389 Blueprint: `cc_object { 390 name: "foo", 391 srcs: ["base.cpp"], 392 target: { 393 linux_arm64: { 394 srcs: ["linux_arm64.cpp",] 395 }, 396 linux_x86: { 397 srcs: ["linux_x86.cpp",] 398 }, 399 bionic_arm64: { 400 srcs: ["bionic_arm64.cpp",] 401 }, 402 }, 403 include_build_directory: false, 404} 405`, 406 ExpectedBazelTargets: []string{ 407 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 408 "copts": `["-fno-addrsig"]`, 409 "srcs": `["base.cpp"] + select({ 410 "//build/bazel/platforms/os_arch:android_arm64": [ 411 "linux_arm64.cpp", 412 "bionic_arm64.cpp", 413 ], 414 "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"], 415 "//build/bazel/platforms/os_arch:linux_bionic_arm64": [ 416 "linux_arm64.cpp", 417 "bionic_arm64.cpp", 418 ], 419 "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"], 420 "//build/bazel/platforms/os_arch:linux_musl_arm64": ["linux_arm64.cpp"], 421 "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"], 422 "//conditions:default": [], 423 })`, 424 }), 425 }, 426 }) 427} 428 429func TestCcObjectHeaderLib(t *testing.T) { 430 runCcObjectTestCase(t, Bp2buildTestCase{ 431 Description: "simple cc_object generates cc_object with include header dep", 432 Filesystem: map[string]string{ 433 "a/b/foo.h": "", 434 "a/b/bar.h": "", 435 "a/b/exclude.c": "", 436 "a/b/c.c": "", 437 }, 438 Blueprint: `cc_object { 439 name: "foo", 440 header_libs: ["libheaders"], 441 system_shared_libs: [], 442 cflags: [ 443 "-Wno-gcc-compat", 444 "-Wall", 445 "-Werror", 446 ], 447 srcs: [ 448 "a/b/*.c" 449 ], 450 exclude_srcs: ["a/b/exclude.c"], 451 sdk_version: "current", 452 min_sdk_version: "29", 453} 454 455cc_library_headers { 456 name: "libheaders", 457 export_include_dirs: ["include"], 458} 459`, 460 ExpectedBazelTargets: []string{ 461 MakeBazelTarget("cc_object", "foo", AttrNameToString{ 462 "copts": `[ 463 "-fno-addrsig", 464 "-Wno-gcc-compat", 465 "-Wall", 466 "-Werror", 467 ]`, 468 "deps": `[":libheaders"]`, 469 "local_includes": `["."]`, 470 "srcs": `["a/b/c.c"]`, 471 "system_dynamic_deps": `[]`, 472 "sdk_version": `"current"`, 473 "min_sdk_version": `"29"`, 474 }), 475 MakeBazelTarget("cc_library_headers", "libheaders", AttrNameToString{ 476 "export_includes": `["include"]`, 477 }), 478 }, 479 }) 480} 481