blob: 75aa2906a31e841d82aba2bd7bdba233fbe3e070 [file] [log] [blame]
Colin Crossd00350c2017-11-17 10:55:38 -08001// Copyright 2017 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
Colin Cross74d1ec02015-04-28 13:30:13 -070015package cc
16
17import (
Colin Cross5b529592017-05-09 13:34:34 -070018 "android/soong/android"
Colin Crossf18e1102017-11-16 14:33:08 -080019 "android/soong/genrule"
20
Jeff Gaston294356f2017-09-27 17:05:30 -070021 "fmt"
Jiyong Park6a43f042017-10-12 23:05:00 +090022 "io/ioutil"
23 "os"
Colin Cross74d1ec02015-04-28 13:30:13 -070024 "reflect"
Jeff Gaston294356f2017-09-27 17:05:30 -070025 "sort"
26 "strings"
Colin Cross74d1ec02015-04-28 13:30:13 -070027 "testing"
28)
29
Jiyong Park6a43f042017-10-12 23:05:00 +090030var buildDir string
31
32func setUp() {
33 var err error
34 buildDir, err = ioutil.TempDir("", "soong_cc_test")
35 if err != nil {
36 panic(err)
37 }
38}
39
40func tearDown() {
41 os.RemoveAll(buildDir)
42}
43
44func TestMain(m *testing.M) {
45 run := func() int {
46 setUp()
47 defer tearDown()
48
49 return m.Run()
50 }
51
52 os.Exit(run())
53}
54
Logan Chienf3511742017-10-31 18:04:35 +080055func createTestContext(t *testing.T, config android.Config, bp string) *android.TestContext {
Jiyong Park6a43f042017-10-12 23:05:00 +090056 ctx := android.NewTestArchContext()
Steven Morelandf9e62162017-11-02 17:00:50 -070057 ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
Colin Crossf18e1102017-11-16 14:33:08 -080058 ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
Jiyong Park374510b2018-03-19 18:23:01 +090059 ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090060 ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
61 ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
Jiyong Parka46a4d52017-12-14 19:54:34 +090062 ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
Jiyong Park374510b2018-03-19 18:23:01 +090063 ctx.RegisterModuleType("vendor_public_library", android.ModuleFactoryAdaptor(vendorPublicLibraryFactory))
Jeff Gaston294356f2017-09-27 17:05:30 -070064 ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
Colin Crossf18e1102017-11-16 14:33:08 -080065 ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
Jiyong Park6a43f042017-10-12 23:05:00 +090066 ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
67 ctx.BottomUp("image", vendorMutator).Parallel()
68 ctx.BottomUp("link", linkageMutator).Parallel()
69 ctx.BottomUp("vndk", vndkMutator).Parallel()
Jiyong Park374510b2018-03-19 18:23:01 +090070 ctx.BottomUp("begin", beginMutator).Parallel()
Jiyong Park6a43f042017-10-12 23:05:00 +090071 })
72 ctx.Register()
73
Jeff Gaston294356f2017-09-27 17:05:30 -070074 // add some modules that are required by the compiler and/or linker
75 bp = bp + `
76 toolchain_library {
77 name: "libatomic",
78 vendor_available: true,
79 }
80
81 toolchain_library {
82 name: "libcompiler_rt-extras",
83 vendor_available: true,
84 }
85
86 toolchain_library {
87 name: "libgcc",
88 vendor_available: true,
89 }
90
91 cc_library {
92 name: "libc",
Logan Chienf3511742017-10-31 18:04:35 +080093 no_libgcc: true,
94 nocrt: true,
Jeff Gaston294356f2017-09-27 17:05:30 -070095 system_shared_libs: [],
96 }
97 llndk_library {
98 name: "libc",
99 symbol_file: "",
100 }
101 cc_library {
102 name: "libm",
Logan Chienf3511742017-10-31 18:04:35 +0800103 no_libgcc: true,
104 nocrt: true,
Jeff Gaston294356f2017-09-27 17:05:30 -0700105 system_shared_libs: [],
106 }
107 llndk_library {
108 name: "libm",
109 symbol_file: "",
110 }
111 cc_library {
112 name: "libdl",
Logan Chienf3511742017-10-31 18:04:35 +0800113 no_libgcc: true,
114 nocrt: true,
Jeff Gaston294356f2017-09-27 17:05:30 -0700115 system_shared_libs: [],
116 }
117 llndk_library {
118 name: "libdl",
119 symbol_file: "",
120 }
Jiyong Park374510b2018-03-19 18:23:01 +0900121 cc_library {
122 name: "libc++_static",
123 no_libgcc: true,
124 nocrt: true,
125 system_shared_libs: [],
126 stl: "none",
127 vendor_available: true,
128 }
129 cc_library {
130 name: "libc++",
131 no_libgcc: true,
132 nocrt: true,
133 system_shared_libs: [],
134 stl: "none",
135 vendor_available: true,
136 vndk: {
137 enabled: true,
138 support_system_process: true,
139 },
140 }
141 cc_library {
142 name: "libunwind_llvm",
143 no_libgcc: true,
144 nocrt: true,
145 system_shared_libs: [],
146 stl: "none",
147 vendor_available: true,
148 }
Jeff Gaston294356f2017-09-27 17:05:30 -0700149
150 cc_object {
151 name: "crtbegin_so",
152 }
153
154 cc_object {
155 name: "crtend_so",
156 }
157
Colin Crossad59e752017-11-16 14:29:11 -0800158 cc_library {
159 name: "libprotobuf-cpp-lite",
160 }
161
Jeff Gaston294356f2017-09-27 17:05:30 -0700162`
163
Jiyong Park6a43f042017-10-12 23:05:00 +0900164 ctx.MockFileSystem(map[string][]byte{
165 "Android.bp": []byte(bp),
166 "foo.c": nil,
167 "bar.c": nil,
Colin Crossad59e752017-11-16 14:29:11 -0800168 "a.proto": nil,
Colin Crossf18e1102017-11-16 14:33:08 -0800169 "b.aidl": nil,
Jiyong Parka46a4d52017-12-14 19:54:34 +0900170 "my_include": nil,
Jiyong Park6a43f042017-10-12 23:05:00 +0900171 })
172
Logan Chienf3511742017-10-31 18:04:35 +0800173 return ctx
174}
175
176func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.TestContext {
177 ctx := createTestContext(t, config, bp)
178
Jeff Gastond3e141d2017-08-08 17:46:01 -0700179 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
Logan Chien42039712018-03-12 16:29:17 +0800180 android.FailIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900181 _, errs = ctx.PrepareBuildActions(config)
Logan Chien42039712018-03-12 16:29:17 +0800182 android.FailIfErrored(t, errs)
Jiyong Park6a43f042017-10-12 23:05:00 +0900183
184 return ctx
185}
186
Logan Chienf3511742017-10-31 18:04:35 +0800187func testCc(t *testing.T, bp string) *android.TestContext {
188 config := android.TestArchConfig(buildDir, nil)
189 config.ProductVariables.DeviceVndkVersion = StringPtr("current")
190 config.ProductVariables.Platform_vndk_version = StringPtr("VER")
191
192 return testCcWithConfig(t, bp, config)
193}
194
195func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
196 config := android.TestArchConfig(buildDir, nil)
197 config.ProductVariables.Platform_vndk_version = StringPtr("VER")
198
199 return testCcWithConfig(t, bp, config)
200}
201
202func testCcError(t *testing.T, pattern string, bp string) {
203 config := android.TestArchConfig(buildDir, nil)
204 config.ProductVariables.DeviceVndkVersion = StringPtr("current")
205 config.ProductVariables.Platform_vndk_version = StringPtr("VER")
206
207 ctx := createTestContext(t, config, bp)
208
209 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
210 if len(errs) > 0 {
Logan Chienee97c3e2018-03-12 16:34:26 +0800211 android.FailIfNoMatchingErrors(t, pattern, errs)
Logan Chienf3511742017-10-31 18:04:35 +0800212 return
213 }
214
215 _, errs = ctx.PrepareBuildActions(config)
216 if len(errs) > 0 {
Logan Chienee97c3e2018-03-12 16:34:26 +0800217 android.FailIfNoMatchingErrors(t, pattern, errs)
Logan Chienf3511742017-10-31 18:04:35 +0800218 return
219 }
220
221 t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
222}
223
224const (
225 coreVariant = "android_arm64_armv8-a_core_shared"
226 vendorVariant = "android_arm64_armv8-a_vendor_shared"
227)
228
Jiyong Park6a43f042017-10-12 23:05:00 +0900229func TestVendorSrc(t *testing.T) {
230 ctx := testCc(t, `
231 cc_library {
232 name: "libTest",
233 srcs: ["foo.c"],
Logan Chienf3511742017-10-31 18:04:35 +0800234 no_libgcc: true,
235 nocrt: true,
236 system_shared_libs: [],
Jiyong Park6a43f042017-10-12 23:05:00 +0900237 vendor_available: true,
238 target: {
239 vendor: {
240 srcs: ["bar.c"],
241 },
242 },
243 }
Jiyong Park6a43f042017-10-12 23:05:00 +0900244 `)
245
Logan Chienf3511742017-10-31 18:04:35 +0800246 ld := ctx.ModuleForTests("libTest", vendorVariant).Rule("ld")
Jiyong Park6a43f042017-10-12 23:05:00 +0900247 var objs []string
248 for _, o := range ld.Inputs {
249 objs = append(objs, o.Base())
250 }
Colin Cross95d33fe2018-01-03 13:40:46 -0800251 if len(objs) != 2 || objs[0] != "foo.o" || objs[1] != "bar.o" {
Jiyong Park6a43f042017-10-12 23:05:00 +0900252 t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
253 }
254}
255
Logan Chienf3511742017-10-31 18:04:35 +0800256func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
257 isVndkSp bool, extends string) {
258
259 mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
260 if !mod.hasVendorVariant() {
Colin Crossf46e37f2018-03-21 16:25:58 -0700261 t.Errorf("%q must have vendor variant", name)
Logan Chienf3511742017-10-31 18:04:35 +0800262 }
263
264 // Check library properties.
265 lib, ok := mod.compiler.(*libraryDecorator)
266 if !ok {
267 t.Errorf("%q must have libraryDecorator", name)
268 } else if lib.baseInstaller.subDir != subDir {
269 t.Errorf("%q must use %q as subdir but it is using %q", name, subDir,
270 lib.baseInstaller.subDir)
271 }
272
273 // Check VNDK properties.
274 if mod.vndkdep == nil {
275 t.Fatalf("%q must have `vndkdep`", name)
276 }
277 if !mod.isVndk() {
278 t.Errorf("%q isVndk() must equal to true", name)
279 }
280 if mod.isVndkSp() != isVndkSp {
281 t.Errorf("%q isVndkSp() must equal to %t", name, isVndkSp)
282 }
283
284 // Check VNDK extension properties.
285 isVndkExt := extends != ""
286 if mod.isVndkExt() != isVndkExt {
287 t.Errorf("%q isVndkExt() must equal to %t", name, isVndkExt)
288 }
289
290 if actualExtends := mod.getVndkExtendsModuleName(); actualExtends != extends {
291 t.Errorf("%q must extend from %q but get %q", name, extends, actualExtends)
292 }
293}
294
295func TestVndk(t *testing.T) {
296 ctx := testCc(t, `
297 cc_library {
298 name: "libvndk",
299 vendor_available: true,
300 vndk: {
301 enabled: true,
302 },
303 nocrt: true,
304 }
305
306 cc_library {
307 name: "libvndk_private",
308 vendor_available: false,
309 vndk: {
310 enabled: true,
311 },
312 nocrt: true,
313 }
314
315 cc_library {
316 name: "libvndk_sp",
317 vendor_available: true,
318 vndk: {
319 enabled: true,
320 support_system_process: true,
321 },
322 nocrt: true,
323 }
324
325 cc_library {
326 name: "libvndk_sp_private",
327 vendor_available: false,
328 vndk: {
329 enabled: true,
330 support_system_process: true,
331 },
332 nocrt: true,
333 }
334 `)
335
336 checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
337 checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
338 checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
339 checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
340}
341
342func TestVndkExt(t *testing.T) {
343 // This test checks the VNDK-Ext properties.
344 ctx := testCc(t, `
345 cc_library {
346 name: "libvndk",
347 vendor_available: true,
348 vndk: {
349 enabled: true,
350 },
351 nocrt: true,
352 }
353
354 cc_library {
355 name: "libvndk_ext",
356 vendor: true,
357 vndk: {
358 enabled: true,
359 extends: "libvndk",
360 },
361 nocrt: true,
362 }
363 `)
364
365 checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
366}
367
368func TestVndkExtNoVndk(t *testing.T) {
369 // This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
370 ctx := testCcNoVndk(t, `
371 cc_library {
372 name: "libvndk",
373 vendor_available: true,
374 vndk: {
375 enabled: true,
376 },
377 nocrt: true,
378 }
379
380 cc_library {
381 name: "libvndk_ext",
382 vendor: true,
383 vndk: {
384 enabled: true,
385 extends: "libvndk",
386 },
387 nocrt: true,
388 }
389 `)
390
391 // Ensures that the core variant of "libvndk_ext" can be found.
392 mod := ctx.ModuleForTests("libvndk_ext", coreVariant).Module().(*Module)
393 if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
394 t.Errorf("\"libvndk_ext\" must extend from \"libvndk\" but get %q", extends)
395 }
396}
397
398func TestVndkExtError(t *testing.T) {
399 // This test ensures an error is emitted in ill-formed vndk-ext definition.
400 testCcError(t, "must set `vendor: true` to set `extends: \".*\"`", `
401 cc_library {
402 name: "libvndk",
403 vendor_available: true,
404 vndk: {
405 enabled: true,
406 },
407 nocrt: true,
408 }
409
410 cc_library {
411 name: "libvndk_ext",
412 vndk: {
413 enabled: true,
414 extends: "libvndk",
415 },
416 nocrt: true,
417 }
418 `)
419
420 testCcError(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
421 cc_library {
422 name: "libvndk",
423 vendor_available: true,
424 vndk: {
425 enabled: true,
426 },
427 nocrt: true,
428 }
429
430 cc_library {
431 name: "libvndk_ext",
432 vendor: true,
433 vndk: {
434 enabled: true,
435 },
436 nocrt: true,
437 }
438 `)
439}
440
441func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
442 // This test ensures an error is emitted for inconsistent support_system_process.
443 testCcError(t, "module \".*\" with mismatched support_system_process", `
444 cc_library {
445 name: "libvndk",
446 vendor_available: true,
447 vndk: {
448 enabled: true,
449 },
450 nocrt: true,
451 }
452
453 cc_library {
454 name: "libvndk_sp_ext",
455 vendor: true,
456 vndk: {
457 enabled: true,
458 extends: "libvndk",
459 support_system_process: true,
460 },
461 nocrt: true,
462 }
463 `)
464
465 testCcError(t, "module \".*\" with mismatched support_system_process", `
466 cc_library {
467 name: "libvndk_sp",
468 vendor_available: true,
469 vndk: {
470 enabled: true,
471 support_system_process: true,
472 },
473 nocrt: true,
474 }
475
476 cc_library {
477 name: "libvndk_ext",
478 vendor: true,
479 vndk: {
480 enabled: true,
481 extends: "libvndk_sp",
482 },
483 nocrt: true,
484 }
485 `)
486}
487
488func TestVndkExtVendorAvailableFalseError(t *testing.T) {
489 // This test ensures an error is emitted when a vndk-ext library extends a vndk library
490 // with `vendor_available: false`.
491 testCcError(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
492 cc_library {
493 name: "libvndk",
494 vendor_available: false,
495 vndk: {
496 enabled: true,
497 },
498 nocrt: true,
499 }
500
501 cc_library {
502 name: "libvndk_ext",
503 vendor: true,
504 vndk: {
505 enabled: true,
506 extends: "libvndk",
507 },
508 nocrt: true,
509 }
510 `)
511}
512
513func TestVendorModuleUsesVndkExt(t *testing.T) {
514 // This test ensures a vendor module can depend on a vndk-ext library.
515 testCc(t, `
516 cc_library {
517 name: "libvndk",
518 vendor_available: true,
519 vndk: {
520 enabled: true,
521 },
522 nocrt: true,
523 }
524
525 cc_library {
526 name: "libvndk_ext",
527 vendor: true,
528 vndk: {
529 enabled: true,
530 extends: "libvndk",
531 },
532 nocrt: true,
533 }
534
535 cc_library {
536
537 name: "libvndk_sp",
538 vendor_available: true,
539 vndk: {
540 enabled: true,
541 support_system_process: true,
542 },
543 nocrt: true,
544 }
545
546 cc_library {
547 name: "libvndk_sp_ext",
548 vendor: true,
549 vndk: {
550 enabled: true,
551 extends: "libvndk_sp",
552 support_system_process: true,
553 },
554 nocrt: true,
555 }
556
557 cc_library {
558 name: "libvendor",
559 vendor: true,
560 shared_libs: ["libvndk_ext", "libvndk_sp_ext"],
561 nocrt: true,
562 }
563 `)
564}
565
566func TestVndkExtUsesVendorLib(t *testing.T) {
567 // This test ensures a vndk-ext library can depend on a vendor library.
568 testCc(t, `
569 cc_library {
570 name: "libvndk",
571 vendor_available: true,
572 vndk: {
573 enabled: true,
574 },
575 nocrt: true,
576 }
577
578 cc_library {
579 name: "libvndk_ext",
580 vendor: true,
581 vndk: {
582 enabled: true,
583 extends: "libvndk",
584 },
585 shared_libs: ["libvendor"],
586 nocrt: true,
587 }
588
589 cc_library {
590 name: "libvendor",
591 vendor: true,
592 nocrt: true,
593 }
594 `)
595}
596
597func TestVndkSpExtUsesVendorLibError(t *testing.T) {
598 // This test ensures an error is emitted if a vndk-sp-ext library depends on a vendor
599 // library.
600 testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
601 cc_library {
602 name: "libvndk_sp",
603 vendor_available: true,
604 vndk: {
605 enabled: true,
606 support_system_process: true,
607 },
608 nocrt: true,
609 }
610
611 cc_library {
612 name: "libvndk_sp_ext",
613 vendor: true,
614 vndk: {
615 enabled: true,
616 extends: "libvndk_sp",
617 support_system_process: true,
618 },
619 shared_libs: ["libvendor"], // Cause an error
620 nocrt: true,
621 }
622
623 cc_library {
624 name: "libvendor",
625 vendor: true,
626 nocrt: true,
627 }
628 `)
629}
630
631func TestVndkUsesVndkExtError(t *testing.T) {
632 // This test ensures an error is emitted if a vndk/vndk-sp library depends on a
633 // vndk-ext/vndk-sp-ext library.
634 testCcError(t, "dependency \".*\" of \".*\" missing variant", `
635 cc_library {
636 name: "libvndk",
637 vendor_available: true,
638 vndk: {
639 enabled: true,
640 },
641 nocrt: true,
642 }
643
644 cc_library {
645 name: "libvndk_ext",
646 vendor: true,
647 vndk: {
648 enabled: true,
649 extends: "libvndk",
650 },
651 nocrt: true,
652 }
653
654 cc_library {
655 name: "libvndk2",
656 vendor_available: true,
657 vndk: {
658 enabled: true,
659 },
660 shared_libs: ["libvndk_ext"],
661 nocrt: true,
662 }
663 `)
664
665 // The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
666 // but target.vendor.shared_libs has not been supported yet.
667 testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
668 cc_library {
669 name: "libvndk",
670 vendor_available: true,
671 vndk: {
672 enabled: true,
673 },
674 nocrt: true,
675 }
676
677 cc_library {
678 name: "libvndk_ext",
679 vendor: true,
680 vndk: {
681 enabled: true,
682 extends: "libvndk",
683 },
684 nocrt: true,
685 }
686
687 cc_library {
688 name: "libvndk2",
689 vendor_available: true,
690 vndk: {
691 enabled: true,
692 },
693 target: {
694 vendor: {
695 shared_libs: ["libvndk_ext"],
696 },
697 },
698 nocrt: true,
699 }
700 `)
701
702 testCcError(t, "dependency \".*\" of \".*\" missing variant", `
703 cc_library {
704 name: "libvndk_sp",
705 vendor_available: true,
706 vndk: {
707 enabled: true,
708 support_system_process: true,
709 },
710 nocrt: true,
711 }
712
713 cc_library {
714 name: "libvndk_sp_ext",
715 vendor: true,
716 vndk: {
717 enabled: true,
718 extends: "libvndk_sp",
719 support_system_process: true,
720 },
721 nocrt: true,
722 }
723
724 cc_library {
725 name: "libvndk_sp_2",
726 vendor_available: true,
727 vndk: {
728 enabled: true,
729 support_system_process: true,
730 },
731 shared_libs: ["libvndk_sp_ext"],
732 nocrt: true,
733 }
734 `)
735
736 // The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
737 // but target.vendor.shared_libs has not been supported yet.
738 testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
739 cc_library {
740 name: "libvndk_sp",
741 vendor_available: true,
742 vndk: {
743 enabled: true,
744 },
745 nocrt: true,
746 }
747
748 cc_library {
749 name: "libvndk_sp_ext",
750 vendor: true,
751 vndk: {
752 enabled: true,
753 extends: "libvndk_sp",
754 },
755 nocrt: true,
756 }
757
758 cc_library {
759 name: "libvndk_sp2",
760 vendor_available: true,
761 vndk: {
762 enabled: true,
763 },
764 target: {
765 vendor: {
766 shared_libs: ["libvndk_sp_ext"],
767 },
768 },
769 nocrt: true,
770 }
771 `)
772}
773
Colin Cross0af4b842015-04-30 16:36:18 -0700774var (
775 str11 = "01234567891"
776 str10 = str11[:10]
777 str9 = str11[:9]
778 str5 = str11[:5]
779 str4 = str11[:4]
780)
781
782var splitListForSizeTestCases = []struct {
783 in []string
784 out [][]string
785 size int
786}{
787 {
788 in: []string{str10},
789 out: [][]string{{str10}},
790 size: 10,
791 },
792 {
793 in: []string{str9},
794 out: [][]string{{str9}},
795 size: 10,
796 },
797 {
798 in: []string{str5},
799 out: [][]string{{str5}},
800 size: 10,
801 },
802 {
803 in: []string{str11},
804 out: nil,
805 size: 10,
806 },
807 {
808 in: []string{str10, str10},
809 out: [][]string{{str10}, {str10}},
810 size: 10,
811 },
812 {
813 in: []string{str9, str10},
814 out: [][]string{{str9}, {str10}},
815 size: 10,
816 },
817 {
818 in: []string{str10, str9},
819 out: [][]string{{str10}, {str9}},
820 size: 10,
821 },
822 {
823 in: []string{str5, str4},
824 out: [][]string{{str5, str4}},
825 size: 10,
826 },
827 {
828 in: []string{str5, str4, str5},
829 out: [][]string{{str5, str4}, {str5}},
830 size: 10,
831 },
832 {
833 in: []string{str5, str4, str5, str4},
834 out: [][]string{{str5, str4}, {str5, str4}},
835 size: 10,
836 },
837 {
838 in: []string{str5, str4, str5, str5},
839 out: [][]string{{str5, str4}, {str5}, {str5}},
840 size: 10,
841 },
842 {
843 in: []string{str5, str5, str5, str4},
844 out: [][]string{{str5}, {str5}, {str5, str4}},
845 size: 10,
846 },
847 {
848 in: []string{str9, str11},
849 out: nil,
850 size: 10,
851 },
852 {
853 in: []string{str11, str9},
854 out: nil,
855 size: 10,
856 },
857}
858
859func TestSplitListForSize(t *testing.T) {
860 for _, testCase := range splitListForSizeTestCases {
Colin Cross5b529592017-05-09 13:34:34 -0700861 out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
862
863 var outStrings [][]string
864
865 if len(out) > 0 {
866 outStrings = make([][]string, len(out))
867 for i, o := range out {
868 outStrings[i] = o.Strings()
869 }
870 }
871
872 if !reflect.DeepEqual(outStrings, testCase.out) {
Colin Cross0af4b842015-04-30 16:36:18 -0700873 t.Errorf("incorrect output:")
874 t.Errorf(" input: %#v", testCase.in)
875 t.Errorf(" size: %d", testCase.size)
876 t.Errorf(" expected: %#v", testCase.out)
Colin Cross5b529592017-05-09 13:34:34 -0700877 t.Errorf(" got: %#v", outStrings)
Colin Cross0af4b842015-04-30 16:36:18 -0700878 }
879 }
880}
Jeff Gaston294356f2017-09-27 17:05:30 -0700881
882var staticLinkDepOrderTestCases = []struct {
883 // This is a string representation of a map[moduleName][]moduleDependency .
884 // It models the dependencies declared in an Android.bp file.
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800885 inStatic string
886
887 // This is a string representation of a map[moduleName][]moduleDependency .
888 // It models the dependencies declared in an Android.bp file.
889 inShared string
Jeff Gaston294356f2017-09-27 17:05:30 -0700890
891 // allOrdered is a string representation of a map[moduleName][]moduleDependency .
892 // The keys of allOrdered specify which modules we would like to check.
893 // The values of allOrdered specify the expected result (of the transitive closure of all
894 // dependencies) for each module to test
895 allOrdered string
896
897 // outOrdered is a string representation of a map[moduleName][]moduleDependency .
898 // The keys of outOrdered specify which modules we would like to check.
899 // The values of outOrdered specify the expected result (of the ordered linker command line)
900 // for each module to test.
901 outOrdered string
902}{
903 // Simple tests
904 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800905 inStatic: "",
Jeff Gaston294356f2017-09-27 17:05:30 -0700906 outOrdered: "",
907 },
908 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800909 inStatic: "a:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700910 outOrdered: "a:",
911 },
912 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800913 inStatic: "a:b; b:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700914 outOrdered: "a:b; b:",
915 },
916 // Tests of reordering
917 {
918 // diamond example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800919 inStatic: "a:d,b,c; b:d; c:d; d:",
Jeff Gaston294356f2017-09-27 17:05:30 -0700920 outOrdered: "a:b,c,d; b:d; c:d; d:",
921 },
922 {
923 // somewhat real example
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800924 inStatic: "bsdiff_unittest:b,c,d,e,f,g,h,i; e:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700925 outOrdered: "bsdiff_unittest:c,d,e,b,f,g,h,i; e:b",
926 },
927 {
928 // multiple reorderings
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800929 inStatic: "a:b,c,d,e; d:b; e:c",
Jeff Gaston294356f2017-09-27 17:05:30 -0700930 outOrdered: "a:d,b,e,c; d:b; e:c",
931 },
932 {
933 // should reorder without adding new transitive dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800934 inStatic: "bin:lib2,lib1; lib1:lib2,liboptional",
Jeff Gaston294356f2017-09-27 17:05:30 -0700935 allOrdered: "bin:lib1,lib2,liboptional; lib1:lib2,liboptional",
936 outOrdered: "bin:lib1,lib2; lib1:lib2,liboptional",
937 },
938 {
939 // multiple levels of dependencies
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800940 inStatic: "a:b,c,d,e,f,g,h; f:b,c,d; b:c,d; c:d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700941 allOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
942 outOrdered: "a:e,f,b,c,d,g,h; f:b,c,d; b:c,d; c:d",
943 },
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800944 // shared dependencies
945 {
946 // Note that this test doesn't recurse, to minimize the amount of logic it tests.
947 // So, we don't actually have to check that a shared dependency of c will change the order
948 // of a library that depends statically on b and on c. We only need to check that if c has
949 // a shared dependency on b, that that shows up in allOrdered.
950 inShared: "c:b",
951 allOrdered: "c:b",
952 outOrdered: "c:",
953 },
954 {
955 // This test doesn't actually include any shared dependencies but it's a reminder of what
956 // the second phase of the above test would look like
957 inStatic: "a:b,c; c:b",
958 allOrdered: "a:c,b; c:b",
959 outOrdered: "a:c,b; c:b",
960 },
Jeff Gaston294356f2017-09-27 17:05:30 -0700961 // tiebreakers for when two modules specifying different orderings and there is no dependency
962 // to dictate an order
963 {
964 // if the tie is between two modules at the end of a's deps, then a's order wins
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800965 inStatic: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
Jeff Gaston294356f2017-09-27 17:05:30 -0700966 outOrdered: "a1:b,c,d,e; a2:b,c,e,d; b:d,e; c:e,d",
967 },
968 {
969 // if the tie is between two modules at the start of a's deps, then c's order is used
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800970 inStatic: "a1:d,e,b1,c1; b1:d,e; c1:e,d; a2:d,e,b2,c2; b2:d,e; c2:d,e",
Jeff Gaston294356f2017-09-27 17:05:30 -0700971 outOrdered: "a1:b1,c1,e,d; b1:d,e; c1:e,d; a2:b2,c2,d,e; b2:d,e; c2:d,e",
972 },
973 // Tests involving duplicate dependencies
974 {
975 // simple duplicate
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800976 inStatic: "a:b,c,c,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700977 outOrdered: "a:c,b",
978 },
979 {
980 // duplicates with reordering
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800981 inStatic: "a:b,c,d,c; c:b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700982 outOrdered: "a:d,c,b",
983 },
984 // Tests to confirm the nonexistence of infinite loops.
985 // These cases should never happen, so as long as the test terminates and the
986 // result is deterministic then that should be fine.
987 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800988 inStatic: "a:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700989 outOrdered: "a:a",
990 },
991 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800992 inStatic: "a:b; b:c; c:a",
Jeff Gaston294356f2017-09-27 17:05:30 -0700993 allOrdered: "a:b,c; b:c,a; c:a,b",
994 outOrdered: "a:b; b:c; c:a",
995 },
996 {
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -0800997 inStatic: "a:b,c; b:c,a; c:a,b",
Jeff Gaston294356f2017-09-27 17:05:30 -0700998 allOrdered: "a:c,a,b; b:a,b,c; c:b,c,a",
999 outOrdered: "a:c,b; b:a,c; c:b,a",
1000 },
1001}
1002
1003// converts from a string like "a:b,c; d:e" to (["a","b"], {"a":["b","c"], "d":["e"]}, [{"a", "a.o"}, {"b", "b.o"}])
1004func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[android.Path][]android.Path) {
1005 // convert from "a:b,c; d:e" to "a:b,c;d:e"
1006 strippedText := strings.Replace(text, " ", "", -1)
1007 if len(strippedText) < 1 {
1008 return []android.Path{}, make(map[android.Path][]android.Path, 0)
1009 }
1010 allDeps = make(map[android.Path][]android.Path, 0)
1011
1012 // convert from "a:b,c;d:e" to ["a:b,c", "d:e"]
1013 moduleTexts := strings.Split(strippedText, ";")
1014
1015 outputForModuleName := func(moduleName string) android.Path {
1016 return android.PathForTesting(moduleName)
1017 }
1018
1019 for _, moduleText := range moduleTexts {
1020 // convert from "a:b,c" to ["a", "b,c"]
1021 components := strings.Split(moduleText, ":")
1022 if len(components) != 2 {
1023 panic(fmt.Sprintf("illegal module dep string %q from larger string %q; must contain one ':', not %v", moduleText, text, len(components)-1))
1024 }
1025 moduleName := components[0]
1026 moduleOutput := outputForModuleName(moduleName)
1027 modulesInOrder = append(modulesInOrder, moduleOutput)
1028
1029 depString := components[1]
1030 // convert from "b,c" to ["b", "c"]
1031 depNames := strings.Split(depString, ",")
1032 if len(depString) < 1 {
1033 depNames = []string{}
1034 }
1035 var deps []android.Path
1036 for _, depName := range depNames {
1037 deps = append(deps, outputForModuleName(depName))
1038 }
1039 allDeps[moduleOutput] = deps
1040 }
1041 return modulesInOrder, allDeps
1042}
1043
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001044func TestLinkReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -07001045 for _, testCase := range staticLinkDepOrderTestCases {
1046 errs := []string{}
1047
1048 // parse testcase
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001049 _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic)
Jeff Gaston294356f2017-09-27 17:05:30 -07001050 expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered)
1051 if testCase.allOrdered == "" {
1052 // allow the test case to skip specifying allOrdered
1053 testCase.allOrdered = testCase.outOrdered
1054 }
1055 _, expectedAllDeps := parseModuleDeps(testCase.allOrdered)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001056 _, givenAllSharedDeps := parseModuleDeps(testCase.inShared)
Jeff Gaston294356f2017-09-27 17:05:30 -07001057
1058 // For each module whose post-reordered dependencies were specified, validate that
1059 // reordering the inputs produces the expected outputs.
1060 for _, moduleName := range expectedModuleNames {
1061 moduleDeps := givenTransitiveDeps[moduleName]
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001062 givenSharedDeps := givenAllSharedDeps[moduleName]
1063 orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps)
Jeff Gaston294356f2017-09-27 17:05:30 -07001064
1065 correctAllOrdered := expectedAllDeps[moduleName]
1066 if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) {
1067 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001068 "\nin static:%q"+
1069 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -07001070 "\nmodule: %v"+
1071 "\nexpected: %s"+
1072 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001073 testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -07001074 }
1075
1076 correctOutputDeps := expectedTransitiveDeps[moduleName]
1077 if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) {
1078 errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001079 "\nin static:%q"+
1080 "\nin shared:%q"+
Jeff Gaston294356f2017-09-27 17:05:30 -07001081 "\nmodule: %v"+
1082 "\nexpected: %s"+
1083 "\nactual: %s",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001084 testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps))
Jeff Gaston294356f2017-09-27 17:05:30 -07001085 }
1086 }
1087
1088 if len(errs) > 0 {
1089 sort.Strings(errs)
1090 for _, err := range errs {
1091 t.Error(err)
1092 }
1093 }
1094 }
1095}
Logan Chienf3511742017-10-31 18:04:35 +08001096
Jeff Gaston294356f2017-09-27 17:05:30 -07001097func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
1098 for _, moduleName := range moduleNames {
1099 module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
1100 output := module.outputFile.Path()
1101 paths = append(paths, output)
1102 }
1103 return paths
1104}
1105
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001106func TestStaticLibDepReordering(t *testing.T) {
Jeff Gaston294356f2017-09-27 17:05:30 -07001107 ctx := testCc(t, `
1108 cc_library {
1109 name: "a",
1110 static_libs: ["b", "c", "d"],
Jiyong Park374510b2018-03-19 18:23:01 +09001111 stl: "none",
Jeff Gaston294356f2017-09-27 17:05:30 -07001112 }
1113 cc_library {
1114 name: "b",
Jiyong Park374510b2018-03-19 18:23:01 +09001115 stl: "none",
Jeff Gaston294356f2017-09-27 17:05:30 -07001116 }
1117 cc_library {
1118 name: "c",
1119 static_libs: ["b"],
Jiyong Park374510b2018-03-19 18:23:01 +09001120 stl: "none",
Jeff Gaston294356f2017-09-27 17:05:30 -07001121 }
1122 cc_library {
1123 name: "d",
Jiyong Park374510b2018-03-19 18:23:01 +09001124 stl: "none",
Jeff Gaston294356f2017-09-27 17:05:30 -07001125 }
1126
1127 `)
1128
1129 variant := "android_arm64_armv8-a_core_static"
1130 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001131 actual := moduleA.depsInLinkOrder
Jeff Gaston294356f2017-09-27 17:05:30 -07001132 expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"})
1133
1134 if !reflect.DeepEqual(actual, expected) {
1135 t.Errorf("staticDeps orderings were not propagated correctly"+
1136 "\nactual: %v"+
1137 "\nexpected: %v",
1138 actual,
1139 expected,
1140 )
1141 }
Jiyong Parkd08b6972017-09-26 10:50:54 +09001142}
Jeff Gaston294356f2017-09-27 17:05:30 -07001143
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001144func TestStaticLibDepReorderingWithShared(t *testing.T) {
1145 ctx := testCc(t, `
1146 cc_library {
1147 name: "a",
1148 static_libs: ["b", "c"],
Jiyong Park374510b2018-03-19 18:23:01 +09001149 stl: "none",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001150 }
1151 cc_library {
1152 name: "b",
Jiyong Park374510b2018-03-19 18:23:01 +09001153 stl: "none",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001154 }
1155 cc_library {
1156 name: "c",
1157 shared_libs: ["b"],
Jiyong Park374510b2018-03-19 18:23:01 +09001158 stl: "none",
Jeff Gastonf5b6e8f2017-11-27 15:48:57 -08001159 }
1160
1161 `)
1162
1163 variant := "android_arm64_armv8-a_core_static"
1164 moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
1165 actual := moduleA.depsInLinkOrder
1166 expected := getOutputPaths(ctx, variant, []string{"c", "b"})
1167
1168 if !reflect.DeepEqual(actual, expected) {
1169 t.Errorf("staticDeps orderings did not account for shared libs"+
1170 "\nactual: %v"+
1171 "\nexpected: %v",
1172 actual,
1173 expected,
1174 )
1175 }
1176}
1177
Jiyong Parka46a4d52017-12-14 19:54:34 +09001178func TestLlndkHeaders(t *testing.T) {
1179 ctx := testCc(t, `
1180 llndk_headers {
1181 name: "libllndk_headers",
1182 export_include_dirs: ["my_include"],
1183 }
1184 llndk_library {
1185 name: "libllndk",
1186 export_llndk_headers: ["libllndk_headers"],
1187 }
1188 cc_library {
1189 name: "libvendor",
1190 shared_libs: ["libllndk"],
1191 vendor: true,
1192 srcs: ["foo.c"],
Logan Chienf3511742017-10-31 18:04:35 +08001193 no_libgcc: true,
1194 nocrt: true,
Jiyong Parka46a4d52017-12-14 19:54:34 +09001195 }
1196 `)
1197
1198 // _static variant is used since _shared reuses *.o from the static variant
1199 cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
1200 cflags := cc.Args["cFlags"]
1201 if !strings.Contains(cflags, "-Imy_include") {
1202 t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
1203 }
1204}
1205
Jiyong Parkd08b6972017-09-26 10:50:54 +09001206var compilerFlagsTestCases = []struct {
1207 in string
1208 out bool
1209}{
1210 {
1211 in: "a",
1212 out: false,
1213 },
1214 {
1215 in: "-a",
1216 out: true,
1217 },
1218 {
1219 in: "-Ipath/to/something",
1220 out: false,
1221 },
1222 {
1223 in: "-isystempath/to/something",
1224 out: false,
1225 },
1226 {
1227 in: "--coverage",
1228 out: false,
1229 },
1230 {
1231 in: "-include a/b",
1232 out: true,
1233 },
1234 {
1235 in: "-include a/b c/d",
1236 out: false,
1237 },
1238 {
1239 in: "-DMACRO",
1240 out: true,
1241 },
1242 {
1243 in: "-DMAC RO",
1244 out: false,
1245 },
1246 {
1247 in: "-a -b",
1248 out: false,
1249 },
1250 {
1251 in: "-DMACRO=definition",
1252 out: true,
1253 },
1254 {
1255 in: "-DMACRO=defi nition",
1256 out: true, // TODO(jiyong): this should be false
1257 },
1258 {
1259 in: "-DMACRO(x)=x + 1",
1260 out: true,
1261 },
1262 {
1263 in: "-DMACRO=\"defi nition\"",
1264 out: true,
1265 },
1266}
1267
1268type mockContext struct {
1269 BaseModuleContext
1270 result bool
1271}
1272
1273func (ctx *mockContext) PropertyErrorf(property, format string, args ...interface{}) {
1274 // CheckBadCompilerFlags calls this function when the flag should be rejected
1275 ctx.result = false
1276}
1277
1278func TestCompilerFlags(t *testing.T) {
1279 for _, testCase := range compilerFlagsTestCases {
1280 ctx := &mockContext{result: true}
1281 CheckBadCompilerFlags(ctx, "", []string{testCase.in})
1282 if ctx.result != testCase.out {
1283 t.Errorf("incorrect output:")
1284 t.Errorf(" input: %#v", testCase.in)
1285 t.Errorf(" expected: %#v", testCase.out)
1286 t.Errorf(" got: %#v", ctx.result)
1287 }
1288 }
Jeff Gaston294356f2017-09-27 17:05:30 -07001289}
Jiyong Park374510b2018-03-19 18:23:01 +09001290
1291func TestVendorPublicLibraries(t *testing.T) {
1292 ctx := testCc(t, `
1293 cc_library_headers {
1294 name: "libvendorpublic_headers",
1295 export_include_dirs: ["my_include"],
1296 }
1297 vendor_public_library {
1298 name: "libvendorpublic",
1299 symbol_file: "",
1300 export_public_headers: ["libvendorpublic_headers"],
1301 }
1302 cc_library {
1303 name: "libvendorpublic",
1304 srcs: ["foo.c"],
1305 vendor: true,
1306 no_libgcc: true,
1307 nocrt: true,
1308 }
1309
1310 cc_library {
1311 name: "libsystem",
1312 shared_libs: ["libvendorpublic"],
1313 vendor: false,
1314 srcs: ["foo.c"],
1315 no_libgcc: true,
1316 nocrt: true,
1317 }
1318 cc_library {
1319 name: "libvendor",
1320 shared_libs: ["libvendorpublic"],
1321 vendor: true,
1322 srcs: ["foo.c"],
1323 no_libgcc: true,
1324 nocrt: true,
1325 }
1326 `)
1327
1328 variant := "android_arm64_armv8-a_core_shared"
1329
1330 // test if header search paths are correctly added
1331 // _static variant is used since _shared reuses *.o from the static variant
1332 cc := ctx.ModuleForTests("libsystem", strings.Replace(variant, "_shared", "_static", 1)).Rule("cc")
1333 cflags := cc.Args["cFlags"]
1334 if !strings.Contains(cflags, "-Imy_include") {
1335 t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
1336 }
1337
1338 // test if libsystem is linked to the stub
1339 ld := ctx.ModuleForTests("libsystem", variant).Rule("ld")
1340 libflags := ld.Args["libFlags"]
1341 stubPaths := getOutputPaths(ctx, variant, []string{"libvendorpublic" + vendorPublicLibrarySuffix})
1342 if !strings.Contains(libflags, stubPaths[0].String()) {
1343 t.Errorf("libflags for libsystem must contain %#v, but was %#v", stubPaths[0], libflags)
1344 }
1345
1346 // test if libvendor is linked to the real shared lib
1347 ld = ctx.ModuleForTests("libvendor", strings.Replace(variant, "_core", "_vendor", 1)).Rule("ld")
1348 libflags = ld.Args["libFlags"]
1349 stubPaths = getOutputPaths(ctx, strings.Replace(variant, "_core", "_vendor", 1), []string{"libvendorpublic"})
1350 if !strings.Contains(libflags, stubPaths[0].String()) {
1351 t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
1352 }
1353
1354}