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 cc 16 17import ( 18 _ "fmt" 19 _ "sort" 20 21 "testing" 22 23 "android/soong/android" 24 25 "github.com/google/blueprint" 26) 27 28func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool { 29 t.Helper() 30 var found bool 31 ctx.VisitDirectDeps(from, func(dep blueprint.Module) { 32 if dep == to { 33 found = true 34 } 35 }) 36 return found 37} 38 39func TestApiLibraryReplacesExistingModule(t *testing.T) { 40 bp := ` 41 cc_library { 42 name: "libfoo", 43 shared_libs: ["libbar"], 44 vendor_available: true, 45 } 46 47 cc_library { 48 name: "libbar", 49 } 50 51 cc_api_library { 52 name: "libbar", 53 vendor_available: true, 54 src: "libbar.so", 55 } 56 57 api_imports { 58 name: "api_imports", 59 shared_libs: [ 60 "libbar", 61 ], 62 } 63 ` 64 65 ctx := prepareForCcTest.RunTestWithBp(t, bp) 66 67 libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module() 68 libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module() 69 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module() 70 71 android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar)) 72 android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport)) 73 74 libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module() 75 libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module() 76 77 android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar)) 78 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor)) 79} 80 81func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) { 82 bp := ` 83 cc_library { 84 name: "libfoo", 85 shared_libs: ["libbar"], 86 vendor: true, 87 } 88 89 cc_api_library { 90 name: "libbar", 91 src: "libbar.so", 92 vendor_available: true, 93 } 94 95 api_imports { 96 name: "api_imports", 97 shared_libs: [ 98 "libbar", 99 ], 100 } 101 ` 102 103 ctx := prepareForCcTest.RunTestWithBp(t, bp) 104 105 libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module() 106 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module() 107 108 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport)) 109} 110 111func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) { 112 bp := ` 113 cc_library { 114 name: "libfoo", 115 shared_libs: ["libbar"], 116 vendor_available: true, 117 } 118 119 cc_library { 120 name: "libbar", 121 vendor_available: true, 122 } 123 124 cc_api_library { 125 name: "libbar", 126 src: "libbar.so", 127 vendor_available: true, 128 } 129 130 api_imports { 131 name: "api_imports", 132 shared_libs: [], 133 } 134 ` 135 136 ctx := prepareForCcTest.RunTestWithBp(t, bp) 137 138 libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module() 139 libbar := ctx.ModuleForTests("libbar", "android_vendor.29_arm64_armv8-a_shared").Module() 140 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module() 141 142 android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar)) 143 android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport)) 144} 145 146func TestExportDirFromStubLibrary(t *testing.T) { 147 bp := ` 148 cc_library { 149 name: "libfoo", 150 export_include_dirs: ["source_include_dir"], 151 export_system_include_dirs: ["source_system_include_dir"], 152 vendor_available: true, 153 } 154 cc_api_library { 155 name: "libfoo", 156 export_include_dirs: ["stub_include_dir"], 157 export_system_include_dirs: ["stub_system_include_dir"], 158 vendor_available: true, 159 src: "libfoo.so", 160 } 161 api_imports { 162 name: "api_imports", 163 shared_libs: [ 164 "libfoo", 165 ], 166 header_libs: [], 167 } 168 // vendor binary 169 cc_binary { 170 name: "vendorbin", 171 vendor: true, 172 srcs: ["vendor.cc"], 173 shared_libs: ["libfoo"], 174 } 175 ` 176 ctx := prepareForCcTest.RunTestWithBp(t, bp) 177 vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"] 178 android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir") 179 android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir") 180 android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir") 181 android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir") 182 183 vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings() 184 // Building the stub.so file first assembles its .h files in multi-tree out. 185 // These header files are required for compiling the other API domain (vendor in this case) 186 android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so") 187} 188 189func TestApiLibraryWithLlndkVariant(t *testing.T) { 190 bp := ` 191 cc_binary { 192 name: "binfoo", 193 vendor: true, 194 srcs: ["binfoo.cc"], 195 shared_libs: ["libbar"], 196 } 197 198 cc_api_library { 199 name: "libbar", 200 // TODO(b/244244438) Remove src property once all variants are implemented. 201 src: "libbar.so", 202 vendor_available: true, 203 variants: [ 204 "llndk", 205 ], 206 } 207 208 cc_api_variant { 209 name: "libbar", 210 variant: "llndk", 211 src: "libbar_llndk.so", 212 export_include_dirs: ["libbar_llndk_include"] 213 } 214 215 api_imports { 216 name: "api_imports", 217 shared_libs: [ 218 "libbar", 219 ], 220 header_libs: [], 221 } 222 ` 223 224 ctx := prepareForCcTest.RunTestWithBp(t, bp) 225 226 binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module() 227 libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module() 228 libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module() 229 230 android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport)) 231 android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant)) 232 233 binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"] 234 android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so") 235 236 binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"] 237 android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include") 238} 239 240func TestApiLibraryWithNdkVariant(t *testing.T) { 241 bp := ` 242 cc_binary { 243 name: "binfoo", 244 sdk_version: "29", 245 srcs: ["binfoo.cc"], 246 shared_libs: ["libbar"], 247 stl: "c++_shared", 248 } 249 250 cc_binary { 251 name: "binbaz", 252 sdk_version: "30", 253 srcs: ["binbaz.cc"], 254 shared_libs: ["libbar"], 255 stl: "c++_shared", 256 } 257 258 cc_binary { 259 name: "binqux", 260 srcs: ["binfoo.cc"], 261 shared_libs: ["libbar"], 262 } 263 264 cc_library { 265 name: "libbar", 266 srcs: ["libbar.cc"], 267 } 268 269 cc_api_library { 270 name: "libbar", 271 // TODO(b/244244438) Remove src property once all variants are implemented. 272 src: "libbar.so", 273 variants: [ 274 "ndk.29", 275 "ndk.30", 276 "ndk.current", 277 ], 278 } 279 280 cc_api_variant { 281 name: "libbar", 282 variant: "ndk", 283 version: "29", 284 src: "libbar_ndk_29.so", 285 export_include_dirs: ["libbar_ndk_29_include"] 286 } 287 288 cc_api_variant { 289 name: "libbar", 290 variant: "ndk", 291 version: "30", 292 src: "libbar_ndk_30.so", 293 export_include_dirs: ["libbar_ndk_30_include"] 294 } 295 296 cc_api_variant { 297 name: "libbar", 298 variant: "ndk", 299 version: "current", 300 src: "libbar_ndk_current.so", 301 export_include_dirs: ["libbar_ndk_current_include"] 302 } 303 304 api_imports { 305 name: "api_imports", 306 shared_libs: [ 307 "libbar", 308 ], 309 header_libs: [], 310 } 311 ` 312 313 ctx := prepareForCcTest.RunTestWithBp(t, bp) 314 315 binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module() 316 libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module() 317 libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module() 318 libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module() 319 libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module() 320 321 android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29)) 322 android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29)) 323 android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30)) 324 android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30)) 325 326 binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module() 327 328 android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30)) 329 android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29)) 330 331 binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"] 332 android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar.ndk.29.apiimport.so") 333 334 binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"] 335 android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include") 336 337 binQux := ctx.ModuleForTests("binqux", "android_arm64_armv8-a").Module() 338 android.AssertBoolEquals(t, "NDK Stub library from API surface should not be linked with nonSdk binary", false, 339 (hasDirectDependency(t, ctx, binQux, libbarApiImportv30) || hasDirectDependency(t, ctx, binQux, libbarApiImportv29))) 340} 341 342func TestApiLibraryWithMultipleVariants(t *testing.T) { 343 bp := ` 344 cc_binary { 345 name: "binfoo", 346 sdk_version: "29", 347 srcs: ["binfoo.cc"], 348 shared_libs: ["libbar"], 349 stl: "c++_shared", 350 } 351 352 cc_binary { 353 name: "binbaz", 354 vendor: true, 355 srcs: ["binbaz.cc"], 356 shared_libs: ["libbar"], 357 } 358 359 cc_library { 360 name: "libbar", 361 srcs: ["libbar.cc"], 362 } 363 364 cc_api_library { 365 name: "libbar", 366 // TODO(b/244244438) Remove src property once all variants are implemented. 367 src: "libbar.so", 368 vendor_available: true, 369 variants: [ 370 "llndk", 371 "ndk.29", 372 "ndk.30", 373 "ndk.current", 374 "apex.29", 375 "apex.30", 376 "apex.current", 377 ], 378 } 379 380 cc_api_variant { 381 name: "libbar", 382 variant: "ndk", 383 version: "29", 384 src: "libbar_ndk_29.so", 385 export_include_dirs: ["libbar_ndk_29_include"] 386 } 387 388 cc_api_variant { 389 name: "libbar", 390 variant: "ndk", 391 version: "30", 392 src: "libbar_ndk_30.so", 393 export_include_dirs: ["libbar_ndk_30_include"] 394 } 395 396 cc_api_variant { 397 name: "libbar", 398 variant: "ndk", 399 version: "current", 400 src: "libbar_ndk_current.so", 401 export_include_dirs: ["libbar_ndk_current_include"] 402 } 403 404 cc_api_variant { 405 name: "libbar", 406 variant: "apex", 407 version: "29", 408 src: "libbar_apex_29.so", 409 export_include_dirs: ["libbar_apex_29_include"] 410 } 411 412 cc_api_variant { 413 name: "libbar", 414 variant: "apex", 415 version: "30", 416 src: "libbar_apex_30.so", 417 export_include_dirs: ["libbar_apex_30_include"] 418 } 419 420 cc_api_variant { 421 name: "libbar", 422 variant: "apex", 423 version: "current", 424 src: "libbar_apex_current.so", 425 export_include_dirs: ["libbar_apex_current_include"] 426 } 427 428 cc_api_variant { 429 name: "libbar", 430 variant: "llndk", 431 src: "libbar_llndk.so", 432 export_include_dirs: ["libbar_llndk_include"] 433 } 434 435 api_imports { 436 name: "api_imports", 437 shared_libs: [ 438 "libbar", 439 ], 440 apex_shared_libs: [ 441 "libbar", 442 ], 443 } 444 ` 445 ctx := prepareForCcTest.RunTestWithBp(t, bp) 446 447 binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module() 448 libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module() 449 libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module() 450 451 android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29)) 452 android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk)) 453 454 binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module() 455 456 android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk)) 457 android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29)) 458 459} 460