1// Copyright 2023 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 "strings" 19 "testing" 20 21 "android/soong/android" 22) 23 24func TestOrderfileProfileSharedLibrary(t *testing.T) { 25 t.Parallel() 26 bp := ` 27 cc_library_shared { 28 name: "libTest", 29 srcs: ["test.c"], 30 orderfile : { 31 instrumentation: true, 32 load_order_file: false, 33 order_file_path: "", 34 }, 35 } 36 ` 37 38 result := android.GroupFixturePreparers( 39 prepareForCcTest, 40 ).RunTestWithBp(t, bp) 41 42 expectedCFlag := "-forder-file-instrumentation" 43 44 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") 45 46 // Check cFlags of orderfile-enabled module 47 cFlags := libTest.Rule("cc").Args["cFlags"] 48 if !strings.Contains(cFlags, expectedCFlag) { 49 t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 50 } 51 52 // Check ldFlags of orderfile-enabled module 53 ldFlags := libTest.Rule("ld").Args["ldFlags"] 54 if !strings.Contains(ldFlags, expectedCFlag) { 55 t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) 56 } 57} 58 59func TestOrderfileLoadSharedLibrary(t *testing.T) { 60 t.Parallel() 61 bp := ` 62 cc_library_shared { 63 name: "libTest", 64 srcs: ["test.c"], 65 orderfile : { 66 instrumentation: true, 67 load_order_file: true, 68 order_file_path: "libTest.orderfile", 69 }, 70 } 71 ` 72 73 result := android.GroupFixturePreparers( 74 prepareForCcTest, 75 android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"), 76 ).RunTestWithBp(t, bp) 77 78 expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile" 79 80 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") 81 82 // Check ldFlags of orderfile-enabled module 83 ldFlags := libTest.Rule("ld").Args["ldFlags"] 84 if !strings.Contains(ldFlags, expectedCFlag) { 85 t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) 86 } 87} 88 89func TestOrderfileProfileBinary(t *testing.T) { 90 t.Parallel() 91 bp := ` 92 cc_binary { 93 name: "test", 94 srcs: ["test.c"], 95 orderfile : { 96 instrumentation: true, 97 load_order_file: false, 98 order_file_path: "", 99 }, 100 } 101 ` 102 103 result := android.GroupFixturePreparers( 104 prepareForCcTest, 105 ).RunTestWithBp(t, bp) 106 107 expectedCFlag := "-forder-file-instrumentation" 108 109 test := result.ModuleForTests("test", "android_arm64_armv8-a") 110 111 // Check cFlags of orderfile-enabled module 112 cFlags := test.Rule("cc").Args["cFlags"] 113 if !strings.Contains(cFlags, expectedCFlag) { 114 t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 115 } 116 117 // Check ldFlags of orderfile-enabled module 118 ldFlags := test.Rule("ld").Args["ldFlags"] 119 if !strings.Contains(ldFlags, expectedCFlag) { 120 t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) 121 } 122} 123 124func TestOrderfileLoadBinary(t *testing.T) { 125 t.Parallel() 126 bp := ` 127 cc_binary { 128 name: "test", 129 srcs: ["test.c"], 130 orderfile : { 131 instrumentation: true, 132 load_order_file: true, 133 order_file_path: "test.orderfile", 134 }, 135 } 136 ` 137 138 result := android.GroupFixturePreparers( 139 prepareForCcTest, 140 android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), 141 ).RunTestWithBp(t, bp) 142 143 expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" 144 145 test := result.ModuleForTests("test", "android_arm64_armv8-a") 146 147 // Check ldFlags of orderfile-enabled module 148 ldFlags := test.Rule("ld").Args["ldFlags"] 149 if !strings.Contains(ldFlags, expectedCFlag) { 150 t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) 151 } 152} 153 154// Profile flags should propagate through static libraries 155func TestOrderfileProfilePropagateStaticDeps(t *testing.T) { 156 t.Parallel() 157 bp := ` 158 cc_library_shared { 159 name: "libTest", 160 srcs: ["test.c"], 161 static_libs: ["libFoo"], 162 orderfile : { 163 instrumentation: true, 164 load_order_file: false, 165 order_file_path: "", 166 }, 167 } 168 169 cc_library_static { 170 name: "libFoo", 171 srcs: ["foo.c"], 172 static_libs: ["libBar"], 173 } 174 175 cc_library_static { 176 name: "libBar", 177 srcs: ["bar.c"], 178 } 179 ` 180 181 result := android.GroupFixturePreparers( 182 prepareForCcTest, 183 ).RunTestWithBp(t, bp) 184 185 expectedCFlag := "-forder-file-instrumentation" 186 187 // Check cFlags of orderfile-enabled module 188 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") 189 190 cFlags := libTest.Rule("cc").Args["cFlags"] 191 if !strings.Contains(cFlags, expectedCFlag) { 192 t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 193 } 194 195 // Check cFlags of orderfile variant static libraries 196 libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile") 197 libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile") 198 199 cFlags = libFooOfVariant.Rule("cc").Args["cFlags"] 200 if !strings.Contains(cFlags, expectedCFlag) { 201 t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 202 } 203 204 cFlags = libBarOfVariant.Rule("cc").Args["cFlags"] 205 if !strings.Contains(cFlags, expectedCFlag) { 206 t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 207 } 208 209 // Check dependency edge from orderfile-enabled module to orderfile variant static libraries 210 if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) { 211 t.Errorf("libTest missing dependency on orderfile variant of libFoo") 212 } 213 214 if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) { 215 t.Errorf("libTest missing dependency on orderfile variant of libBar") 216 } 217 218 // Check cFlags of the non-orderfile variant static libraries 219 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") 220 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") 221 222 cFlags = libFoo.Rule("cc").Args["cFlags"] 223 if strings.Contains(cFlags, expectedCFlag) { 224 t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 225 } 226 227 cFlags = libBar.Rule("cc").Args["cFlags"] 228 if strings.Contains(cFlags, expectedCFlag) { 229 t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 230 } 231 232 // Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries 233 if hasDirectDep(result, libTest.Module(), libFoo.Module()) { 234 t.Errorf("libTest has dependency on non-orderfile variant of libFoo") 235 } 236 237 if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { 238 t.Errorf("libTest has dependency on non-orderfile variant of libBar") 239 } 240} 241 242// Load flags should never propagate 243func TestOrderfileLoadPropagateStaticDeps(t *testing.T) { 244 t.Parallel() 245 bp := ` 246 cc_library_shared { 247 name: "libTest", 248 srcs: ["test.c"], 249 static_libs: ["libFoo"], 250 orderfile : { 251 instrumentation: true, 252 load_order_file: true, 253 order_file_path: "test.orderfile", 254 }, 255 } 256 257 cc_library_static { 258 name: "libFoo", 259 srcs: ["foo.c"], 260 static_libs: ["libBar"], 261 } 262 263 cc_library_static { 264 name: "libBar", 265 srcs: ["bar.c"], 266 } 267 ` 268 269 result := android.GroupFixturePreparers( 270 prepareForCcTest, 271 android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), 272 ).RunTestWithBp(t, bp) 273 274 expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" 275 276 // Check ldFlags of orderfile-enabled module 277 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") 278 279 ldFlags := libTest.Rule("ld").Args["ldFlags"] 280 if !strings.Contains(ldFlags, expectedCFlag) { 281 t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags) 282 } 283 284 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") 285 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") 286 287 // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries 288 if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { 289 t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") 290 } 291 292 if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { 293 t.Errorf("libTest missing dependency on non-orderfile variant of libBar") 294 } 295 296 // Make sure no orderfile variants are created for static libraries because the flags were not propagated 297 libFooVariants := result.ModuleVariantsForTests("libFoo") 298 for _, v := range libFooVariants { 299 if strings.Contains(v, "orderfile") { 300 t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) 301 } 302 } 303 304 libBarVariants := result.ModuleVariantsForTests("libBar") 305 for _, v := range libBarVariants { 306 if strings.Contains(v, "orderfile") { 307 t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) 308 } 309 } 310} 311 312// Profile flags should not propagate through shared libraries 313func TestOrderfileProfilePropagateSharedDeps(t *testing.T) { 314 t.Parallel() 315 bp := ` 316 cc_library_shared { 317 name: "libTest", 318 srcs: ["test.c"], 319 shared_libs: ["libFoo"], 320 orderfile : { 321 instrumentation: true, 322 load_order_file: false, 323 order_file_path: "", 324 }, 325 } 326 327 cc_library_shared { 328 name: "libFoo", 329 srcs: ["foo.c"], 330 static_libs: ["libBar"], 331 } 332 333 cc_library_static { 334 name: "libBar", 335 srcs: ["bar.c"], 336 } 337 ` 338 339 result := android.GroupFixturePreparers( 340 prepareForCcTest, 341 ).RunTestWithBp(t, bp) 342 343 expectedCFlag := "-forder-file-instrumentation" 344 345 // Check cFlags of orderfile-enabled module 346 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") 347 348 cFlags := libTest.Rule("cc").Args["cFlags"] 349 if !strings.Contains(cFlags, expectedCFlag) { 350 t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) 351 } 352 353 // Check cFlags of the static and shared libraries 354 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared") 355 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") 356 357 cFlags = libFoo.Rule("cc").Args["cFlags"] 358 if strings.Contains(cFlags, expectedCFlag) { 359 t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 360 } 361 362 cFlags = libBar.Rule("cc").Args["cFlags"] 363 if strings.Contains(cFlags, expectedCFlag) { 364 t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 365 } 366 367 // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries 368 if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { 369 t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") 370 } 371 372 if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { 373 t.Errorf("libTest missing dependency on non-orderfile variant of libBar") 374 } 375 376 // Make sure no orderfile variants are created for libraries because the flags were not propagated 377 libFooVariants := result.ModuleVariantsForTests("libFoo") 378 for _, v := range libFooVariants { 379 if strings.Contains(v, "orderfile") { 380 t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) 381 } 382 } 383 384 libBarVariants := result.ModuleVariantsForTests("libBar") 385 for _, v := range libBarVariants { 386 if strings.Contains(v, "orderfile") { 387 t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) 388 } 389 } 390} 391 392// Profile flags should not work or be propagated if orderfile flags start at a static library 393func TestOrderfileProfileStaticLibrary(t *testing.T) { 394 t.Parallel() 395 bp := ` 396 cc_library_static { 397 name: "libTest", 398 srcs: ["test.c"], 399 static_libs: ["libFoo"], 400 orderfile : { 401 instrumentation: true, 402 load_order_file: false, 403 order_file_path: "", 404 }, 405 } 406 407 cc_library_static { 408 name: "libFoo", 409 srcs: ["foo.c"], 410 static_libs: ["libBar"], 411 } 412 413 cc_library_static { 414 name: "libBar", 415 srcs: ["bar.c"], 416 } 417 ` 418 419 result := android.GroupFixturePreparers( 420 prepareForCcTest, 421 ).RunTestWithBp(t, bp) 422 423 expectedCFlag := "-forder-file-instrumentation" 424 425 // Check cFlags of module 426 libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static") 427 428 cFlags := libTest.Rule("cc").Args["cFlags"] 429 if strings.Contains(cFlags, expectedCFlag) { 430 t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 431 } 432 433 // Check cFlags of the static libraries 434 libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") 435 libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") 436 437 cFlags = libFoo.Rule("cc").Args["cFlags"] 438 if strings.Contains(cFlags, expectedCFlag) { 439 t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 440 } 441 442 cFlags = libBar.Rule("cc").Args["cFlags"] 443 if strings.Contains(cFlags, expectedCFlag) { 444 t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) 445 } 446 447 // Check dependency edge from orderfile-enabled module to non-orderfile variant libraries 448 if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { 449 t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") 450 } 451 452 if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { 453 t.Errorf("libTest missing dependency on non-orderfile variant of libBar") 454 } 455 456 // Make sure no orderfile variants are created for static libraries because the flags were not propagated 457 libFooVariants := result.ModuleVariantsForTests("libFoo") 458 for _, v := range libFooVariants { 459 if strings.Contains(v, "orderfile") { 460 t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) 461 } 462 } 463 464 libBarVariants := result.ModuleVariantsForTests("libBar") 465 for _, v := range libBarVariants { 466 if strings.Contains(v, "orderfile") { 467 t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) 468 } 469 } 470} 471