• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"fmt"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/cc"
23)
24
25const (
26	// See cc/testing.go for more context
27	soongCcLibraryPreamble = `
28cc_defaults {
29    name: "linux_bionic_supported",
30}`
31
32	soongCcProtoLibraries = `
33cc_library {
34	name: "libprotobuf-cpp-lite",
35	bazel_module: { bp2build_available: false },
36}
37
38cc_library {
39	name: "libprotobuf-cpp-full",
40	bazel_module: { bp2build_available: false },
41}`
42
43	soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries
44)
45
46func runCcLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
47	t.Helper()
48	runBp2BuildTestCase(t, registerCcLibraryModuleTypes, tc)
49}
50
51func registerCcLibraryModuleTypes(ctx android.RegistrationContext) {
52	cc.RegisterCCBuildComponents(ctx)
53	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
54	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
55	ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
56	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
57}
58
59func TestCcLibrarySimple(t *testing.T) {
60	runCcLibraryTestCase(t, bp2buildTestCase{
61		description:                "cc_library - simple example",
62		moduleTypeUnderTest:        "cc_library",
63		moduleTypeUnderTestFactory: cc.LibraryFactory,
64		filesystem: map[string]string{
65			"android.cpp": "",
66			"bionic.cpp":  "",
67			"darwin.cpp":  "",
68			// Refer to cc.headerExts for the supported header extensions in Soong.
69			"header.h":         "",
70			"header.hh":        "",
71			"header.hpp":       "",
72			"header.hxx":       "",
73			"header.h++":       "",
74			"header.inl":       "",
75			"header.inc":       "",
76			"header.ipp":       "",
77			"header.h.generic": "",
78			"impl.cpp":         "",
79			"linux.cpp":        "",
80			"x86.cpp":          "",
81			"x86_64.cpp":       "",
82			"foo-dir/a.h":      "",
83		},
84		blueprint: soongCcLibraryPreamble +
85			simpleModuleDoNotConvertBp2build("cc_library_headers", "some-headers") + `
86cc_library {
87    name: "foo-lib",
88    srcs: ["impl.cpp"],
89    cflags: ["-Wall"],
90    header_libs: ["some-headers"],
91    export_include_dirs: ["foo-dir"],
92    ldflags: ["-Wl,--exclude-libs=bar.a"],
93    arch: {
94        x86: {
95            ldflags: ["-Wl,--exclude-libs=baz.a"],
96            srcs: ["x86.cpp"],
97        },
98        x86_64: {
99            ldflags: ["-Wl,--exclude-libs=qux.a"],
100            srcs: ["x86_64.cpp"],
101        },
102    },
103    target: {
104        android: {
105            srcs: ["android.cpp"],
106        },
107        linux_glibc: {
108            srcs: ["linux.cpp"],
109        },
110        darwin: {
111            srcs: ["darwin.cpp"],
112        },
113        bionic: {
114          srcs: ["bionic.cpp"]
115        },
116    },
117    include_build_directory: false,
118    sdk_version: "current",
119    min_sdk_version: "29",
120    use_version_lib: true,
121}
122`,
123		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
124			"copts":               `["-Wall"]`,
125			"export_includes":     `["foo-dir"]`,
126			"implementation_deps": `[":some-headers"]`,
127			"linkopts": `["-Wl,--exclude-libs=bar.a"] + select({
128        "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
129        "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
130        "//conditions:default": [],
131    })`,
132			"srcs": `["impl.cpp"] + select({
133        "//build/bazel/platforms/arch:x86": ["x86.cpp"],
134        "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
135        "//conditions:default": [],
136    }) + select({
137        "//build/bazel/platforms/os:android": [
138            "bionic.cpp",
139            "android.cpp",
140        ],
141        "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
142        "//build/bazel/platforms/os:linux": ["linux.cpp"],
143        "//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
144        "//conditions:default": [],
145    })`,
146			"sdk_version":     `"current"`,
147			"min_sdk_version": `"29"`,
148			"use_version_lib": `True`,
149		}),
150	})
151}
152
153func TestCcLibraryTrimmedLdAndroid(t *testing.T) {
154	runCcLibraryTestCase(t, bp2buildTestCase{
155		description:                "cc_library - trimmed example of //bionic/linker:ld-android",
156		moduleTypeUnderTest:        "cc_library",
157		moduleTypeUnderTestFactory: cc.LibraryFactory,
158		filesystem: map[string]string{
159			"ld-android.cpp":           "",
160			"linked_list.h":            "",
161			"linker.h":                 "",
162			"linker_block_allocator.h": "",
163			"linker_cfi.h":             "",
164		},
165		blueprint: soongCcLibraryPreamble +
166			simpleModuleDoNotConvertBp2build("cc_library_headers", "libc_headers") + `
167cc_library {
168    name: "fake-ld-android",
169    srcs: ["ld_android.cpp"],
170    cflags: [
171        "-Wall",
172        "-Wextra",
173        "-Wunused",
174        "-Werror",
175    ],
176    header_libs: ["libc_headers"],
177    ldflags: [
178        "-Wl,--exclude-libs=libgcc.a",
179        "-Wl,--exclude-libs=libgcc_stripped.a",
180        "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
181        "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
182        "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
183        "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
184    ],
185    arch: {
186        x86: {
187            ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
188        },
189        x86_64: {
190            ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
191        },
192    },
193    include_build_directory: false,
194}
195`,
196		expectedBazelTargets: makeCcLibraryTargets("fake-ld-android", attrNameToString{
197			"srcs": `["ld_android.cpp"]`,
198			"copts": `[
199        "-Wall",
200        "-Wextra",
201        "-Wunused",
202        "-Werror",
203    ]`,
204			"implementation_deps": `[":libc_headers"]`,
205			"linkopts": `[
206        "-Wl,--exclude-libs=libgcc.a",
207        "-Wl,--exclude-libs=libgcc_stripped.a",
208        "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
209        "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
210        "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
211        "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
212    ] + select({
213        "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=libgcc_eh.a"],
214        "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
215        "//conditions:default": [],
216    })`,
217		}),
218	})
219}
220
221func TestCcLibraryExcludeSrcs(t *testing.T) {
222	runCcLibraryTestCase(t, bp2buildTestCase{
223		description:                "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
224		moduleTypeUnderTest:        "cc_library",
225		moduleTypeUnderTestFactory: cc.LibraryFactory,
226		dir:                        "external",
227		filesystem: map[string]string{
228			"external/math/cosf.c":      "",
229			"external/math/erf.c":       "",
230			"external/math/erf_data.c":  "",
231			"external/math/erff.c":      "",
232			"external/math/erff_data.c": "",
233			"external/Android.bp": `
234cc_library {
235    name: "fake-libarm-optimized-routines-math",
236    exclude_srcs: [
237        // Provided by:
238        // bionic/libm/upstream-freebsd/lib/msun/src/s_erf.c
239        // bionic/libm/upstream-freebsd/lib/msun/src/s_erff.c
240        "math/erf.c",
241        "math/erf_data.c",
242        "math/erff.c",
243        "math/erff_data.c",
244    ],
245    srcs: [
246        "math/*.c",
247    ],
248    // arch-specific settings
249    arch: {
250        arm64: {
251            cflags: [
252                "-DHAVE_FAST_FMA=1",
253            ],
254        },
255    },
256    bazel_module: { bp2build_available: true },
257}
258`,
259		},
260		blueprint: soongCcLibraryPreamble,
261		expectedBazelTargets: makeCcLibraryTargets("fake-libarm-optimized-routines-math", attrNameToString{
262			"copts": `select({
263        "//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
264        "//conditions:default": [],
265    })`,
266			"local_includes": `["."]`,
267			"srcs_c":         `["math/cosf.c"]`,
268		}),
269	})
270}
271
272func TestCcLibrarySharedStaticProps(t *testing.T) {
273	runCcLibraryTestCase(t, bp2buildTestCase{
274		description:                "cc_library shared/static props",
275		moduleTypeUnderTest:        "cc_library",
276		moduleTypeUnderTestFactory: cc.LibraryFactory,
277		filesystem: map[string]string{
278			"both.cpp":       "",
279			"sharedonly.cpp": "",
280			"staticonly.cpp": "",
281		},
282		blueprint: soongCcLibraryPreamble + `
283cc_library {
284    name: "a",
285    srcs: ["both.cpp"],
286    cflags: ["bothflag"],
287    shared_libs: ["shared_dep_for_both"],
288    static_libs: ["static_dep_for_both", "whole_and_static_lib_for_both"],
289    whole_static_libs: ["whole_static_lib_for_both", "whole_and_static_lib_for_both"],
290    static: {
291        srcs: ["staticonly.cpp"],
292        cflags: ["staticflag"],
293        shared_libs: ["shared_dep_for_static"],
294        static_libs: ["static_dep_for_static"],
295        whole_static_libs: ["whole_static_lib_for_static"],
296    },
297    shared: {
298        srcs: ["sharedonly.cpp"],
299        cflags: ["sharedflag"],
300        shared_libs: ["shared_dep_for_shared"],
301        static_libs: ["static_dep_for_shared"],
302        whole_static_libs: ["whole_static_lib_for_shared"],
303    },
304    include_build_directory: false,
305}
306
307cc_library_static {
308    name: "static_dep_for_shared",
309    bazel_module: { bp2build_available: false },
310}
311
312cc_library_static {
313    name: "static_dep_for_static",
314    bazel_module: { bp2build_available: false },
315}
316
317cc_library_static {
318    name: "static_dep_for_both",
319    bazel_module: { bp2build_available: false },
320}
321
322cc_library_static {
323    name: "whole_static_lib_for_shared",
324    bazel_module: { bp2build_available: false },
325}
326
327cc_library_static {
328    name: "whole_static_lib_for_static",
329    bazel_module: { bp2build_available: false },
330}
331
332cc_library_static {
333    name: "whole_static_lib_for_both",
334    bazel_module: { bp2build_available: false },
335}
336
337cc_library_static {
338    name: "whole_and_static_lib_for_both",
339    bazel_module: { bp2build_available: false },
340}
341
342cc_library {
343    name: "shared_dep_for_shared",
344    bazel_module: { bp2build_available: false },
345}
346
347cc_library {
348    name: "shared_dep_for_static",
349    bazel_module: { bp2build_available: false },
350}
351
352cc_library {
353    name: "shared_dep_for_both",
354    bazel_module: { bp2build_available: false },
355}
356`,
357		expectedBazelTargets: []string{
358			makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
359				"copts": `[
360        "bothflag",
361        "staticflag",
362    ]`,
363				"implementation_deps": `[
364        ":static_dep_for_both",
365        ":static_dep_for_static",
366    ]`,
367				"implementation_dynamic_deps": `[
368        ":shared_dep_for_both",
369        ":shared_dep_for_static",
370    ]`,
371				"srcs": `[
372        "both.cpp",
373        "staticonly.cpp",
374    ]`,
375				"whole_archive_deps": `[
376        ":whole_static_lib_for_both",
377        ":whole_and_static_lib_for_both",
378        ":whole_static_lib_for_static",
379    ]`}),
380			makeBazelTarget("cc_library_shared", "a", attrNameToString{
381				"copts": `[
382        "bothflag",
383        "sharedflag",
384    ]`,
385				"implementation_deps": `[
386        ":static_dep_for_both",
387        ":static_dep_for_shared",
388    ]`,
389				"implementation_dynamic_deps": `[
390        ":shared_dep_for_both",
391        ":shared_dep_for_shared",
392    ]`,
393				"srcs": `[
394        "both.cpp",
395        "sharedonly.cpp",
396    ]`,
397				"whole_archive_deps": `[
398        ":whole_static_lib_for_both",
399        ":whole_and_static_lib_for_both",
400        ":whole_static_lib_for_shared",
401    ]`,
402			}),
403		},
404	})
405}
406
407func TestCcLibraryDeps(t *testing.T) {
408	runCcLibraryTestCase(t, bp2buildTestCase{
409		description:                "cc_library shared/static props",
410		moduleTypeUnderTest:        "cc_library",
411		moduleTypeUnderTestFactory: cc.LibraryFactory,
412		filesystem: map[string]string{
413			"both.cpp":       "",
414			"sharedonly.cpp": "",
415			"staticonly.cpp": "",
416		},
417		blueprint: soongCcLibraryPreamble + `
418cc_library {
419    name: "a",
420    srcs: ["both.cpp"],
421    cflags: ["bothflag"],
422    shared_libs: ["implementation_shared_dep_for_both", "shared_dep_for_both"],
423    export_shared_lib_headers: ["shared_dep_for_both"],
424    static_libs: ["implementation_static_dep_for_both", "static_dep_for_both"],
425    export_static_lib_headers: ["static_dep_for_both", "whole_static_dep_for_both"],
426    whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_both", "whole_static_dep_for_both"],
427    static: {
428        srcs: ["staticonly.cpp"],
429        cflags: ["staticflag"],
430        shared_libs: ["implementation_shared_dep_for_static", "shared_dep_for_static"],
431        export_shared_lib_headers: ["shared_dep_for_static"],
432        static_libs: ["implementation_static_dep_for_static", "static_dep_for_static"],
433        export_static_lib_headers: ["static_dep_for_static", "whole_static_dep_for_static"],
434        whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_static", "whole_static_dep_for_static"],
435    },
436    shared: {
437        srcs: ["sharedonly.cpp"],
438        cflags: ["sharedflag"],
439        shared_libs: ["implementation_shared_dep_for_shared", "shared_dep_for_shared"],
440        export_shared_lib_headers: ["shared_dep_for_shared"],
441        static_libs: ["implementation_static_dep_for_shared", "static_dep_for_shared"],
442        export_static_lib_headers: ["static_dep_for_shared", "whole_static_dep_for_shared"],
443        whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_shared", "whole_static_dep_for_shared"],
444    },
445    include_build_directory: false,
446}
447` + simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_shared") +
448			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_shared") +
449			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_static") +
450			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_static") +
451			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_both") +
452			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_both") +
453			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_shared") +
454			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") +
455			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_static") +
456			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") +
457			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_both") +
458			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") +
459			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_shared") +
460			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_shared") +
461			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_static") +
462			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") +
463			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
464			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
465		expectedBazelTargets: []string{
466			makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
467				"copts": `[
468        "bothflag",
469        "staticflag",
470    ]`,
471				"deps": `[
472        ":static_dep_for_both",
473        ":static_dep_for_static",
474    ]`,
475				"dynamic_deps": `[
476        ":shared_dep_for_both",
477        ":shared_dep_for_static",
478    ]`,
479				"implementation_deps": `[
480        ":implementation_static_dep_for_both",
481        ":implementation_static_dep_for_static",
482    ]`,
483				"implementation_dynamic_deps": `[
484        ":implementation_shared_dep_for_both",
485        ":implementation_shared_dep_for_static",
486    ]`,
487				"srcs": `[
488        "both.cpp",
489        "staticonly.cpp",
490    ]`,
491				"whole_archive_deps": `[
492        ":not_explicitly_exported_whole_static_dep_for_both",
493        ":whole_static_dep_for_both",
494        ":not_explicitly_exported_whole_static_dep_for_static",
495        ":whole_static_dep_for_static",
496    ]`,
497			}),
498			makeBazelTarget("cc_library_shared", "a", attrNameToString{
499				"copts": `[
500        "bothflag",
501        "sharedflag",
502    ]`,
503				"deps": `[
504        ":static_dep_for_both",
505        ":static_dep_for_shared",
506    ]`,
507				"dynamic_deps": `[
508        ":shared_dep_for_both",
509        ":shared_dep_for_shared",
510    ]`,
511				"implementation_deps": `[
512        ":implementation_static_dep_for_both",
513        ":implementation_static_dep_for_shared",
514    ]`,
515				"implementation_dynamic_deps": `[
516        ":implementation_shared_dep_for_both",
517        ":implementation_shared_dep_for_shared",
518    ]`,
519				"srcs": `[
520        "both.cpp",
521        "sharedonly.cpp",
522    ]`,
523				"whole_archive_deps": `[
524        ":not_explicitly_exported_whole_static_dep_for_both",
525        ":whole_static_dep_for_both",
526        ":not_explicitly_exported_whole_static_dep_for_shared",
527        ":whole_static_dep_for_shared",
528    ]`,
529			})},
530	},
531	)
532}
533
534func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) {
535	runCcLibraryTestCase(t, bp2buildTestCase{
536		moduleTypeUnderTest:        "cc_library",
537		moduleTypeUnderTestFactory: cc.LibraryFactory,
538		dir:                        "foo/bar",
539		filesystem: map[string]string{
540			"foo/bar/Android.bp": `
541cc_library {
542    name: "a",
543    whole_static_libs: ["whole_static_lib_for_both"],
544    static: {
545        whole_static_libs: ["whole_static_lib_for_static"],
546    },
547    shared: {
548        whole_static_libs: ["whole_static_lib_for_shared"],
549    },
550    bazel_module: { bp2build_available: true },
551    include_build_directory: false,
552}
553
554cc_prebuilt_library_static { name: "whole_static_lib_for_shared" }
555
556cc_prebuilt_library_static { name: "whole_static_lib_for_static" }
557
558cc_prebuilt_library_static { name: "whole_static_lib_for_both" }
559`,
560		},
561		blueprint: soongCcLibraryPreamble,
562		expectedBazelTargets: []string{
563			makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
564				"whole_archive_deps": `[
565        ":whole_static_lib_for_both_alwayslink",
566        ":whole_static_lib_for_static_alwayslink",
567    ]`,
568			}),
569			makeBazelTarget("cc_library_shared", "a", attrNameToString{
570				"whole_archive_deps": `[
571        ":whole_static_lib_for_both_alwayslink",
572        ":whole_static_lib_for_shared_alwayslink",
573    ]`,
574			}),
575		},
576	},
577	)
578}
579
580func TestCcLibrarySharedStaticPropsInArch(t *testing.T) {
581	runCcLibraryTestCase(t, bp2buildTestCase{
582		description:                "cc_library shared/static props in arch",
583		moduleTypeUnderTest:        "cc_library",
584		moduleTypeUnderTestFactory: cc.LibraryFactory,
585		dir:                        "foo/bar",
586		filesystem: map[string]string{
587			"foo/bar/arm.cpp":        "",
588			"foo/bar/x86.cpp":        "",
589			"foo/bar/sharedonly.cpp": "",
590			"foo/bar/staticonly.cpp": "",
591			"foo/bar/Android.bp": `
592cc_library {
593    name: "a",
594    arch: {
595        arm: {
596            shared: {
597                srcs: ["arm_shared.cpp"],
598                cflags: ["-DARM_SHARED"],
599                static_libs: ["arm_static_dep_for_shared"],
600                whole_static_libs: ["arm_whole_static_dep_for_shared"],
601                shared_libs: ["arm_shared_dep_for_shared"],
602            },
603        },
604        x86: {
605            static: {
606                srcs: ["x86_static.cpp"],
607                cflags: ["-DX86_STATIC"],
608                static_libs: ["x86_dep_for_static"],
609            },
610        },
611    },
612    target: {
613        android: {
614            shared: {
615                srcs: ["android_shared.cpp"],
616                cflags: ["-DANDROID_SHARED"],
617                static_libs: ["android_dep_for_shared"],
618            },
619        },
620        android_arm: {
621            shared: {
622                cflags: ["-DANDROID_ARM_SHARED"],
623            },
624        },
625    },
626    srcs: ["both.cpp"],
627    cflags: ["bothflag"],
628    static_libs: ["static_dep_for_both"],
629    static: {
630        srcs: ["staticonly.cpp"],
631        cflags: ["staticflag"],
632        static_libs: ["static_dep_for_static"],
633    },
634    shared: {
635        srcs: ["sharedonly.cpp"],
636        cflags: ["sharedflag"],
637        static_libs: ["static_dep_for_shared"],
638    },
639    bazel_module: { bp2build_available: true },
640}
641
642cc_library_static { name: "static_dep_for_shared" }
643cc_library_static { name: "static_dep_for_static" }
644cc_library_static { name: "static_dep_for_both" }
645
646cc_library_static { name: "arm_static_dep_for_shared" }
647cc_library_static { name: "arm_whole_static_dep_for_shared" }
648cc_library_static { name: "arm_shared_dep_for_shared" }
649
650cc_library_static { name: "x86_dep_for_static" }
651
652cc_library_static { name: "android_dep_for_shared" }
653`,
654		},
655		blueprint: soongCcLibraryPreamble,
656		expectedBazelTargets: []string{
657			makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
658				"copts": `[
659        "bothflag",
660        "staticflag",
661    ] + select({
662        "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
663        "//conditions:default": [],
664    })`,
665				"implementation_deps": `[
666        ":static_dep_for_both",
667        ":static_dep_for_static",
668    ] + select({
669        "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
670        "//conditions:default": [],
671    })`,
672				"local_includes": `["."]`,
673				"srcs": `[
674        "both.cpp",
675        "staticonly.cpp",
676    ] + select({
677        "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
678        "//conditions:default": [],
679    })`,
680			}),
681			makeBazelTarget("cc_library_shared", "a", attrNameToString{
682				"copts": `[
683        "bothflag",
684        "sharedflag",
685    ] + select({
686        "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"],
687        "//conditions:default": [],
688    }) + select({
689        "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"],
690        "//conditions:default": [],
691    }) + select({
692        "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"],
693        "//conditions:default": [],
694    })`,
695				"implementation_deps": `[
696        ":static_dep_for_both",
697        ":static_dep_for_shared",
698    ] + select({
699        "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
700        "//conditions:default": [],
701    }) + select({
702        "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
703        "//conditions:default": [],
704    })`,
705				"implementation_dynamic_deps": `select({
706        "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"],
707        "//conditions:default": [],
708    })`,
709				"local_includes": `["."]`,
710				"srcs": `[
711        "both.cpp",
712        "sharedonly.cpp",
713    ] + select({
714        "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"],
715        "//conditions:default": [],
716    }) + select({
717        "//build/bazel/platforms/os:android": ["android_shared.cpp"],
718        "//conditions:default": [],
719    })`,
720				"whole_archive_deps": `select({
721        "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
722        "//conditions:default": [],
723    })`,
724			}),
725		},
726	},
727	)
728}
729
730func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) {
731	runCcLibraryTestCase(t, bp2buildTestCase{
732		description:                "cc_library shared/static props with c/cpp/s mixed sources",
733		moduleTypeUnderTest:        "cc_library",
734		moduleTypeUnderTestFactory: cc.LibraryFactory,
735		dir:                        "foo/bar",
736		filesystem: map[string]string{
737			"foo/bar/both_source.cpp":   "",
738			"foo/bar/both_source.cc":    "",
739			"foo/bar/both_source.c":     "",
740			"foo/bar/both_source.s":     "",
741			"foo/bar/both_source.S":     "",
742			"foo/bar/shared_source.cpp": "",
743			"foo/bar/shared_source.cc":  "",
744			"foo/bar/shared_source.c":   "",
745			"foo/bar/shared_source.s":   "",
746			"foo/bar/shared_source.S":   "",
747			"foo/bar/static_source.cpp": "",
748			"foo/bar/static_source.cc":  "",
749			"foo/bar/static_source.c":   "",
750			"foo/bar/static_source.s":   "",
751			"foo/bar/static_source.S":   "",
752			"foo/bar/Android.bp": `
753cc_library {
754    name: "a",
755    srcs: [
756    "both_source.cpp",
757    "both_source.cc",
758    "both_source.c",
759    "both_source.s",
760    "both_source.S",
761    ":both_filegroup",
762  ],
763    static: {
764        srcs: [
765          "static_source.cpp",
766          "static_source.cc",
767          "static_source.c",
768          "static_source.s",
769          "static_source.S",
770          ":static_filegroup",
771        ],
772    },
773    shared: {
774        srcs: [
775          "shared_source.cpp",
776          "shared_source.cc",
777          "shared_source.c",
778          "shared_source.s",
779          "shared_source.S",
780          ":shared_filegroup",
781        ],
782    },
783    bazel_module: { bp2build_available: true },
784}
785
786filegroup {
787    name: "both_filegroup",
788    srcs: [
789        // Not relevant, handled by filegroup macro
790  ],
791}
792
793filegroup {
794    name: "shared_filegroup",
795    srcs: [
796        // Not relevant, handled by filegroup macro
797  ],
798}
799
800filegroup {
801    name: "static_filegroup",
802    srcs: [
803        // Not relevant, handled by filegroup macro
804  ],
805}
806`,
807		},
808		blueprint: soongCcLibraryPreamble,
809		expectedBazelTargets: []string{
810			makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
811				"local_includes": `["."]`,
812				"srcs": `[
813        "both_source.cpp",
814        "both_source.cc",
815        ":both_filegroup_cpp_srcs",
816        "static_source.cpp",
817        "static_source.cc",
818        ":static_filegroup_cpp_srcs",
819    ]`,
820				"srcs_as": `[
821        "both_source.s",
822        "both_source.S",
823        ":both_filegroup_as_srcs",
824        "static_source.s",
825        "static_source.S",
826        ":static_filegroup_as_srcs",
827    ]`,
828				"srcs_c": `[
829        "both_source.c",
830        ":both_filegroup_c_srcs",
831        "static_source.c",
832        ":static_filegroup_c_srcs",
833    ]`,
834			}),
835			makeBazelTarget("cc_library_shared", "a", attrNameToString{
836				"local_includes": `["."]`,
837				"srcs": `[
838        "both_source.cpp",
839        "both_source.cc",
840        ":both_filegroup_cpp_srcs",
841        "shared_source.cpp",
842        "shared_source.cc",
843        ":shared_filegroup_cpp_srcs",
844    ]`,
845				"srcs_as": `[
846        "both_source.s",
847        "both_source.S",
848        ":both_filegroup_as_srcs",
849        "shared_source.s",
850        "shared_source.S",
851        ":shared_filegroup_as_srcs",
852    ]`,
853				"srcs_c": `[
854        "both_source.c",
855        ":both_filegroup_c_srcs",
856        "shared_source.c",
857        ":shared_filegroup_c_srcs",
858    ]`,
859			})}})
860}
861
862func TestCcLibraryNonConfiguredVersionScript(t *testing.T) {
863	runCcLibraryTestCase(t, bp2buildTestCase{
864		description:                "cc_library non-configured version script",
865		moduleTypeUnderTest:        "cc_library",
866		moduleTypeUnderTestFactory: cc.LibraryFactory,
867		dir:                        "foo/bar",
868		filesystem: map[string]string{
869			"foo/bar/Android.bp": `
870cc_library {
871    name: "a",
872    srcs: ["a.cpp"],
873    version_script: "v.map",
874    bazel_module: { bp2build_available: true },
875    include_build_directory: false,
876}
877`,
878		},
879		blueprint: soongCcLibraryPreamble,
880		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
881			"additional_linker_inputs": `["v.map"]`,
882			"linkopts":                 `["-Wl,--version-script,$(location v.map)"]`,
883			"srcs":                     `["a.cpp"]`,
884		}),
885	},
886	)
887}
888
889func TestCcLibraryConfiguredVersionScript(t *testing.T) {
890	runCcLibraryTestCase(t, bp2buildTestCase{
891		description:                "cc_library configured version script",
892		moduleTypeUnderTest:        "cc_library",
893		moduleTypeUnderTestFactory: cc.LibraryFactory,
894		dir:                        "foo/bar",
895		filesystem: map[string]string{
896			"foo/bar/Android.bp": `
897cc_library {
898   name: "a",
899   srcs: ["a.cpp"],
900   arch: {
901     arm: {
902       version_script: "arm.map",
903     },
904     arm64: {
905       version_script: "arm64.map",
906     },
907   },
908
909   bazel_module: { bp2build_available: true },
910    include_build_directory: false,
911}
912    `,
913		},
914		blueprint: soongCcLibraryPreamble,
915		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
916			"additional_linker_inputs": `select({
917        "//build/bazel/platforms/arch:arm": ["arm.map"],
918        "//build/bazel/platforms/arch:arm64": ["arm64.map"],
919        "//conditions:default": [],
920    })`,
921			"linkopts": `select({
922        "//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"],
923        "//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"],
924        "//conditions:default": [],
925    })`,
926			"srcs": `["a.cpp"]`,
927		}),
928	},
929	)
930}
931
932func TestCcLibrarySharedLibs(t *testing.T) {
933	runCcLibraryTestCase(t, bp2buildTestCase{
934		description:                "cc_library shared_libs",
935		moduleTypeUnderTest:        "cc_library",
936		moduleTypeUnderTestFactory: cc.LibraryFactory,
937		blueprint: soongCcLibraryPreamble + `
938cc_library {
939    name: "mylib",
940    bazel_module: { bp2build_available: false },
941}
942
943cc_library {
944    name: "a",
945    shared_libs: ["mylib",],
946    include_build_directory: false,
947}
948`,
949		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
950			"implementation_dynamic_deps": `[":mylib"]`,
951		}),
952	},
953	)
954}
955
956func TestCcLibraryFeatures(t *testing.T) {
957	expected_targets := []string{}
958	expected_targets = append(expected_targets, makeCcLibraryTargets("a", attrNameToString{
959		"features": `[
960        "disable_pack_relocations",
961        "-no_undefined_symbols",
962    ]`,
963		"srcs": `["a.cpp"]`,
964	})...)
965	expected_targets = append(expected_targets, makeCcLibraryTargets("b", attrNameToString{
966		"features": `select({
967        "//build/bazel/platforms/arch:x86_64": [
968            "disable_pack_relocations",
969            "-no_undefined_symbols",
970        ],
971        "//conditions:default": [],
972    })`,
973		"srcs": `["b.cpp"]`,
974	})...)
975	expected_targets = append(expected_targets, makeCcLibraryTargets("c", attrNameToString{
976		"features": `select({
977        "//build/bazel/platforms/os:darwin": [
978            "disable_pack_relocations",
979            "-no_undefined_symbols",
980        ],
981        "//conditions:default": [],
982    })`,
983		"srcs": `["c.cpp"]`,
984	})...)
985
986	runCcLibraryTestCase(t, bp2buildTestCase{
987		description:                "cc_library pack_relocations test",
988		moduleTypeUnderTest:        "cc_library",
989		moduleTypeUnderTestFactory: cc.LibraryFactory,
990		blueprint: soongCcLibraryPreamble + `
991cc_library {
992    name: "a",
993    srcs: ["a.cpp"],
994    pack_relocations: false,
995    allow_undefined_symbols: true,
996    include_build_directory: false,
997}
998
999cc_library {
1000    name: "b",
1001    srcs: ["b.cpp"],
1002    arch: {
1003        x86_64: {
1004            pack_relocations: false,
1005            allow_undefined_symbols: true,
1006        },
1007    },
1008    include_build_directory: false,
1009}
1010
1011cc_library {
1012    name: "c",
1013    srcs: ["c.cpp"],
1014    target: {
1015        darwin: {
1016            pack_relocations: false,
1017            allow_undefined_symbols: true,
1018        },
1019    },
1020    include_build_directory: false,
1021}`,
1022		expectedBazelTargets: expected_targets,
1023	})
1024}
1025
1026func TestCcLibrarySpacesInCopts(t *testing.T) {
1027	runCcLibraryTestCase(t, bp2buildTestCase{
1028		description:                "cc_library spaces in copts",
1029		moduleTypeUnderTest:        "cc_library",
1030		moduleTypeUnderTestFactory: cc.LibraryFactory,
1031		blueprint: soongCcLibraryPreamble + `
1032cc_library {
1033    name: "a",
1034    cflags: ["-include header.h",],
1035    include_build_directory: false,
1036}
1037`,
1038		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
1039			"copts": `[
1040        "-include",
1041        "header.h",
1042    ]`,
1043		}),
1044	},
1045	)
1046}
1047
1048func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) {
1049	runCcLibraryTestCase(t, bp2buildTestCase{
1050		description:                "cc_library cppflags usage",
1051		moduleTypeUnderTest:        "cc_library",
1052		moduleTypeUnderTestFactory: cc.LibraryFactory,
1053		blueprint: soongCcLibraryPreamble + `cc_library {
1054    name: "a",
1055    srcs: ["a.cpp"],
1056    cflags: ["-Wall"],
1057    cppflags: [
1058        "-fsigned-char",
1059        "-pedantic",
1060    ],
1061    arch: {
1062        arm64: {
1063            cppflags: ["-DARM64=1"],
1064        },
1065    },
1066    target: {
1067        android: {
1068            cppflags: ["-DANDROID=1"],
1069        },
1070    },
1071    include_build_directory: false,
1072}
1073`,
1074		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
1075			"copts": `["-Wall"]`,
1076			"cppflags": `[
1077        "-fsigned-char",
1078        "-pedantic",
1079    ] + select({
1080        "//build/bazel/platforms/arch:arm64": ["-DARM64=1"],
1081        "//conditions:default": [],
1082    }) + select({
1083        "//build/bazel/platforms/os:android": ["-DANDROID=1"],
1084        "//conditions:default": [],
1085    })`,
1086			"srcs": `["a.cpp"]`,
1087		}),
1088	},
1089	)
1090}
1091
1092func TestCcLibraryExcludeLibs(t *testing.T) {
1093	runCcLibraryTestCase(t, bp2buildTestCase{
1094		moduleTypeUnderTest:        "cc_library",
1095		moduleTypeUnderTestFactory: cc.LibraryFactory,
1096		filesystem:                 map[string]string{},
1097		blueprint: soongCcLibraryStaticPreamble + `
1098cc_library {
1099    name: "foo_static",
1100    srcs: ["common.c"],
1101    whole_static_libs: [
1102        "arm_whole_static_lib_excludes",
1103        "malloc_not_svelte_whole_static_lib_excludes"
1104    ],
1105    static_libs: [
1106        "arm_static_lib_excludes",
1107        "malloc_not_svelte_static_lib_excludes"
1108    ],
1109    shared_libs: [
1110        "arm_shared_lib_excludes",
1111    ],
1112    arch: {
1113        arm: {
1114            exclude_shared_libs: [
1115                 "arm_shared_lib_excludes",
1116            ],
1117            exclude_static_libs: [
1118                "arm_static_lib_excludes",
1119                "arm_whole_static_lib_excludes",
1120            ],
1121        },
1122    },
1123    product_variables: {
1124        malloc_not_svelte: {
1125            shared_libs: ["malloc_not_svelte_shared_lib"],
1126            whole_static_libs: ["malloc_not_svelte_whole_static_lib"],
1127            exclude_static_libs: [
1128                "malloc_not_svelte_static_lib_excludes",
1129                "malloc_not_svelte_whole_static_lib_excludes",
1130            ],
1131        },
1132    },
1133    include_build_directory: false,
1134}
1135
1136cc_library {
1137    name: "arm_whole_static_lib_excludes",
1138    bazel_module: { bp2build_available: false },
1139}
1140
1141cc_library {
1142    name: "malloc_not_svelte_whole_static_lib",
1143    bazel_module: { bp2build_available: false },
1144}
1145
1146cc_library {
1147    name: "malloc_not_svelte_whole_static_lib_excludes",
1148    bazel_module: { bp2build_available: false },
1149}
1150
1151cc_library {
1152    name: "arm_static_lib_excludes",
1153    bazel_module: { bp2build_available: false },
1154}
1155
1156cc_library {
1157    name: "malloc_not_svelte_static_lib_excludes",
1158    bazel_module: { bp2build_available: false },
1159}
1160
1161cc_library {
1162    name: "arm_shared_lib_excludes",
1163    bazel_module: { bp2build_available: false },
1164}
1165
1166cc_library {
1167    name: "malloc_not_svelte_shared_lib",
1168    bazel_module: { bp2build_available: false },
1169}
1170`,
1171		expectedBazelTargets: makeCcLibraryTargets("foo_static", attrNameToString{
1172			"implementation_deps": `select({
1173        "//build/bazel/platforms/arch:arm": [],
1174        "//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
1175    }) + select({
1176        "//build/bazel/product_variables:malloc_not_svelte": [],
1177        "//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
1178    })`,
1179			"implementation_dynamic_deps": `select({
1180        "//build/bazel/platforms/arch:arm": [],
1181        "//conditions:default": [":arm_shared_lib_excludes"],
1182    }) + select({
1183        "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
1184        "//conditions:default": [],
1185    })`,
1186			"srcs_c": `["common.c"]`,
1187			"whole_archive_deps": `select({
1188        "//build/bazel/platforms/arch:arm": [],
1189        "//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
1190    }) + select({
1191        "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
1192        "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
1193    })`,
1194		}),
1195	},
1196	)
1197}
1198
1199func TestCCLibraryNoCrtTrue(t *testing.T) {
1200	runCcLibraryTestCase(t, bp2buildTestCase{
1201		description:                "cc_library - nocrt: true emits attribute",
1202		moduleTypeUnderTest:        "cc_library",
1203		moduleTypeUnderTestFactory: cc.LibraryFactory,
1204		filesystem: map[string]string{
1205			"impl.cpp": "",
1206		},
1207		blueprint: soongCcLibraryPreamble + `
1208cc_library {
1209    name: "foo-lib",
1210    srcs: ["impl.cpp"],
1211    nocrt: true,
1212    include_build_directory: false,
1213}
1214`,
1215		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1216			"link_crt": `False`,
1217			"srcs":     `["impl.cpp"]`,
1218		}),
1219	},
1220	)
1221}
1222
1223func TestCCLibraryNoCrtFalse(t *testing.T) {
1224	runCcLibraryTestCase(t, bp2buildTestCase{
1225		description:                "cc_library - nocrt: false - does not emit attribute",
1226		moduleTypeUnderTest:        "cc_library",
1227		moduleTypeUnderTestFactory: cc.LibraryFactory,
1228		filesystem: map[string]string{
1229			"impl.cpp": "",
1230		},
1231		blueprint: soongCcLibraryPreamble + `
1232cc_library {
1233    name: "foo-lib",
1234    srcs: ["impl.cpp"],
1235    nocrt: false,
1236    include_build_directory: false,
1237}
1238`,
1239		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1240			"srcs": `["impl.cpp"]`,
1241		}),
1242	})
1243}
1244
1245func TestCCLibraryNoCrtArchVariant(t *testing.T) {
1246	runCcLibraryTestCase(t, bp2buildTestCase{
1247		description:                "cc_library - nocrt in select",
1248		moduleTypeUnderTest:        "cc_library",
1249		moduleTypeUnderTestFactory: cc.LibraryFactory,
1250		filesystem: map[string]string{
1251			"impl.cpp": "",
1252		},
1253		blueprint: soongCcLibraryPreamble + `
1254cc_library {
1255    name: "foo-lib",
1256    srcs: ["impl.cpp"],
1257    arch: {
1258        arm: {
1259            nocrt: true,
1260        },
1261        x86: {
1262            nocrt: false,
1263        },
1264    },
1265    include_build_directory: false,
1266}
1267`,
1268		expectedErr: fmt.Errorf("module \"foo-lib\": nocrt is not supported for arch variants"),
1269	})
1270}
1271
1272func TestCCLibraryNoLibCrtTrue(t *testing.T) {
1273	runCcLibraryTestCase(t, bp2buildTestCase{
1274		moduleTypeUnderTest:        "cc_library",
1275		moduleTypeUnderTestFactory: cc.LibraryFactory,
1276		filesystem: map[string]string{
1277			"impl.cpp": "",
1278		},
1279		blueprint: soongCcLibraryPreamble + `
1280cc_library {
1281    name: "foo-lib",
1282    srcs: ["impl.cpp"],
1283    no_libcrt: true,
1284    include_build_directory: false,
1285}
1286`,
1287		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1288			"srcs":       `["impl.cpp"]`,
1289			"use_libcrt": `False`,
1290		}),
1291	})
1292}
1293
1294func makeCcLibraryTargets(name string, attrs attrNameToString) []string {
1295	STATIC_ONLY_ATTRS := map[string]bool{}
1296	SHARED_ONLY_ATTRS := map[string]bool{
1297		"link_crt":                 true,
1298		"additional_linker_inputs": true,
1299		"linkopts":                 true,
1300		"strip":                    true,
1301		"stubs_symbol_file":        true,
1302		"stubs_versions":           true,
1303		"inject_bssl_hash":         true,
1304	}
1305	sharedAttrs := attrNameToString{}
1306	staticAttrs := attrNameToString{}
1307	for key, val := range attrs {
1308		if _, staticOnly := STATIC_ONLY_ATTRS[key]; !staticOnly {
1309			sharedAttrs[key] = val
1310		}
1311		if _, sharedOnly := SHARED_ONLY_ATTRS[key]; !sharedOnly {
1312			staticAttrs[key] = val
1313		}
1314	}
1315	sharedTarget := makeBazelTarget("cc_library_shared", name, sharedAttrs)
1316	staticTarget := makeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs)
1317
1318	return []string{staticTarget, sharedTarget}
1319}
1320
1321func TestCCLibraryNoLibCrtFalse(t *testing.T) {
1322	runCcLibraryTestCase(t, bp2buildTestCase{
1323		moduleTypeUnderTest:        "cc_library",
1324		moduleTypeUnderTestFactory: cc.LibraryFactory,
1325		filesystem: map[string]string{
1326			"impl.cpp": "",
1327		},
1328		blueprint: soongCcLibraryPreamble + `
1329cc_library {
1330    name: "foo-lib",
1331    srcs: ["impl.cpp"],
1332    no_libcrt: false,
1333    include_build_directory: false,
1334}
1335`,
1336		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1337			"srcs":       `["impl.cpp"]`,
1338			"use_libcrt": `True`,
1339		}),
1340	})
1341}
1342
1343func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
1344	runCcLibraryTestCase(t, bp2buildTestCase{
1345		moduleTypeUnderTest:        "cc_library",
1346		moduleTypeUnderTestFactory: cc.LibraryFactory,
1347		filesystem: map[string]string{
1348			"impl.cpp": "",
1349		},
1350		blueprint: soongCcLibraryPreamble + `
1351cc_library {
1352    name: "foo-lib",
1353    srcs: ["impl.cpp"],
1354    arch: {
1355        arm: {
1356            no_libcrt: true,
1357        },
1358        x86: {
1359            no_libcrt: true,
1360        },
1361    },
1362    include_build_directory: false,
1363}
1364`,
1365		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1366			"srcs": `["impl.cpp"]`,
1367			"use_libcrt": `select({
1368        "//build/bazel/platforms/arch:arm": False,
1369        "//build/bazel/platforms/arch:x86": False,
1370        "//conditions:default": None,
1371    })`,
1372		}),
1373	})
1374}
1375
1376func TestCCLibraryNoLibCrtArchAndTargetVariant(t *testing.T) {
1377	runCcLibraryTestCase(t, bp2buildTestCase{
1378		moduleTypeUnderTest:        "cc_library",
1379		moduleTypeUnderTestFactory: cc.LibraryFactory,
1380		filesystem: map[string]string{
1381			"impl.cpp": "",
1382		},
1383		blueprint: soongCcLibraryPreamble + `
1384cc_library {
1385    name: "foo-lib",
1386    srcs: ["impl.cpp"],
1387    arch: {
1388        arm: {
1389            no_libcrt: true,
1390        },
1391        x86: {
1392            no_libcrt: true,
1393        },
1394    },
1395    target: {
1396        darwin: {
1397            no_libcrt: true,
1398        }
1399    },
1400    include_build_directory: false,
1401}
1402`,
1403		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1404			"srcs": `["impl.cpp"]`,
1405			"use_libcrt": `select({
1406        "//build/bazel/platforms/os_arch:android_arm": False,
1407        "//build/bazel/platforms/os_arch:android_x86": False,
1408        "//build/bazel/platforms/os_arch:darwin_arm64": False,
1409        "//build/bazel/platforms/os_arch:darwin_x86_64": False,
1410        "//build/bazel/platforms/os_arch:linux_glibc_x86": False,
1411        "//build/bazel/platforms/os_arch:linux_musl_x86": False,
1412        "//build/bazel/platforms/os_arch:windows_x86": False,
1413        "//conditions:default": None,
1414    })`,
1415		}),
1416	})
1417}
1418
1419func TestCCLibraryNoLibCrtArchAndTargetVariantConflict(t *testing.T) {
1420	runCcLibraryTestCase(t, bp2buildTestCase{
1421		moduleTypeUnderTest:        "cc_library",
1422		moduleTypeUnderTestFactory: cc.LibraryFactory,
1423		filesystem: map[string]string{
1424			"impl.cpp": "",
1425		},
1426		blueprint: soongCcLibraryPreamble + `
1427cc_library {
1428    name: "foo-lib",
1429    srcs: ["impl.cpp"],
1430    arch: {
1431        arm: {
1432            no_libcrt: true,
1433        },
1434        // This is expected to override the value for darwin_x86_64.
1435        x86_64: {
1436            no_libcrt: true,
1437        },
1438    },
1439    target: {
1440        darwin: {
1441            no_libcrt: false,
1442        }
1443    },
1444    include_build_directory: false,
1445}
1446`,
1447		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1448			"srcs": `["impl.cpp"]`,
1449			"use_libcrt": `select({
1450        "//build/bazel/platforms/os_arch:android_arm": False,
1451        "//build/bazel/platforms/os_arch:android_x86_64": False,
1452        "//build/bazel/platforms/os_arch:darwin_arm64": True,
1453        "//build/bazel/platforms/os_arch:darwin_x86_64": False,
1454        "//build/bazel/platforms/os_arch:linux_bionic_x86_64": False,
1455        "//build/bazel/platforms/os_arch:linux_glibc_x86_64": False,
1456        "//build/bazel/platforms/os_arch:linux_musl_x86_64": False,
1457        "//build/bazel/platforms/os_arch:windows_x86_64": False,
1458        "//conditions:default": None,
1459    })`,
1460		}),
1461	})
1462}
1463
1464func TestCcLibraryStrip(t *testing.T) {
1465	expectedTargets := []string{}
1466	expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{
1467		"strip": `{
1468        "all": True,
1469    }`,
1470	})...)
1471	expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols", attrNameToString{
1472		"strip": `{
1473        "keep_symbols": True,
1474    }`,
1475	})...)
1476	expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_and_debug_frame", attrNameToString{
1477		"strip": `{
1478        "keep_symbols_and_debug_frame": True,
1479    }`,
1480	})...)
1481	expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_list", attrNameToString{
1482		"strip": `{
1483        "keep_symbols_list": ["symbol"],
1484    }`,
1485	})...)
1486	expectedTargets = append(expectedTargets, makeCcLibraryTargets("none", attrNameToString{
1487		"strip": `{
1488        "none": True,
1489    }`,
1490	})...)
1491	expectedTargets = append(expectedTargets, makeCcLibraryTargets("nothing", attrNameToString{})...)
1492
1493	runCcLibraryTestCase(t, bp2buildTestCase{
1494		description:                "cc_library strip args",
1495		moduleTypeUnderTest:        "cc_library",
1496		moduleTypeUnderTestFactory: cc.LibraryFactory,
1497		blueprint: soongCcLibraryPreamble + `
1498cc_library {
1499    name: "nothing",
1500    include_build_directory: false,
1501}
1502cc_library {
1503    name: "keep_symbols",
1504    strip: {
1505        keep_symbols: true,
1506    },
1507    include_build_directory: false,
1508}
1509cc_library {
1510    name: "keep_symbols_and_debug_frame",
1511    strip: {
1512        keep_symbols_and_debug_frame: true,
1513    },
1514    include_build_directory: false,
1515}
1516cc_library {
1517    name: "none",
1518    strip: {
1519        none: true,
1520    },
1521    include_build_directory: false,
1522}
1523cc_library {
1524    name: "keep_symbols_list",
1525    strip: {
1526        keep_symbols_list: ["symbol"],
1527    },
1528    include_build_directory: false,
1529}
1530cc_library {
1531    name: "all",
1532    strip: {
1533        all: true,
1534    },
1535    include_build_directory: false,
1536}
1537`,
1538		expectedBazelTargets: expectedTargets,
1539	})
1540}
1541
1542func TestCcLibraryStripWithArch(t *testing.T) {
1543	runCcLibraryTestCase(t, bp2buildTestCase{
1544		description:                "cc_library strip args",
1545		moduleTypeUnderTest:        "cc_library",
1546		moduleTypeUnderTestFactory: cc.LibraryFactory,
1547		blueprint: soongCcLibraryPreamble + `
1548cc_library {
1549    name: "multi-arch",
1550    target: {
1551        darwin: {
1552            strip: {
1553                keep_symbols_list: ["foo", "bar"]
1554            }
1555        },
1556    },
1557    arch: {
1558        arm: {
1559            strip: {
1560                keep_symbols_and_debug_frame: true,
1561            },
1562        },
1563        arm64: {
1564            strip: {
1565                keep_symbols: true,
1566            },
1567        },
1568    },
1569    include_build_directory: false,
1570}
1571`,
1572		expectedBazelTargets: makeCcLibraryTargets("multi-arch", attrNameToString{
1573			"strip": `{
1574        "keep_symbols": select({
1575            "//build/bazel/platforms/arch:arm64": True,
1576            "//conditions:default": None,
1577        }),
1578        "keep_symbols_and_debug_frame": select({
1579            "//build/bazel/platforms/arch:arm": True,
1580            "//conditions:default": None,
1581        }),
1582        "keep_symbols_list": select({
1583            "//build/bazel/platforms/os:darwin": [
1584                "foo",
1585                "bar",
1586            ],
1587            "//conditions:default": [],
1588        }),
1589    }`,
1590		}),
1591	},
1592	)
1593}
1594
1595func TestCcLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
1596	runCcLibraryTestCase(t, bp2buildTestCase{
1597		description:                "cc_library system_shared_libs empty at root",
1598		moduleTypeUnderTest:        "cc_library",
1599		moduleTypeUnderTestFactory: cc.LibraryFactory,
1600		blueprint: soongCcLibraryPreamble + `
1601cc_library {
1602    name: "root_empty",
1603    system_shared_libs: [],
1604    include_build_directory: false,
1605}
1606`,
1607		expectedBazelTargets: makeCcLibraryTargets("root_empty", attrNameToString{
1608			"system_dynamic_deps": `[]`,
1609		}),
1610	},
1611	)
1612}
1613
1614func TestCcLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
1615	runCcLibraryTestCase(t, bp2buildTestCase{
1616		description:                "cc_library system_shared_libs empty for static variant",
1617		moduleTypeUnderTest:        "cc_library",
1618		moduleTypeUnderTestFactory: cc.LibraryFactory,
1619		blueprint: soongCcLibraryPreamble + `
1620cc_library {
1621    name: "static_empty",
1622    static: {
1623        system_shared_libs: [],
1624    },
1625    include_build_directory: false,
1626}
1627`,
1628		expectedBazelTargets: []string{
1629			makeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", attrNameToString{
1630				"system_dynamic_deps": "[]",
1631			}),
1632			makeBazelTarget("cc_library_shared", "static_empty", attrNameToString{}),
1633		},
1634	})
1635}
1636
1637func TestCcLibrary_SystemSharedLibsSharedEmpty(t *testing.T) {
1638	runCcLibraryTestCase(t, bp2buildTestCase{
1639		description:                "cc_library system_shared_libs empty for shared variant",
1640		moduleTypeUnderTest:        "cc_library",
1641		moduleTypeUnderTestFactory: cc.LibraryFactory,
1642		blueprint: soongCcLibraryPreamble + `
1643cc_library {
1644    name: "shared_empty",
1645    shared: {
1646        system_shared_libs: [],
1647    },
1648    include_build_directory: false,
1649}
1650`,
1651		expectedBazelTargets: []string{
1652			makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}),
1653			makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{
1654				"system_dynamic_deps": "[]",
1655			}),
1656		},
1657	})
1658}
1659
1660func TestCcLibrary_SystemSharedLibsSharedBionicEmpty(t *testing.T) {
1661	runCcLibraryTestCase(t, bp2buildTestCase{
1662		description:                "cc_library system_shared_libs empty for shared, bionic variant",
1663		moduleTypeUnderTest:        "cc_library",
1664		moduleTypeUnderTestFactory: cc.LibraryFactory,
1665		blueprint: soongCcLibraryPreamble + `
1666cc_library {
1667    name: "shared_empty",
1668    target: {
1669        bionic: {
1670            shared: {
1671                system_shared_libs: [],
1672            }
1673        }
1674    },
1675    include_build_directory: false,
1676}
1677`,
1678		expectedBazelTargets: []string{
1679			makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}),
1680			makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{
1681				"system_dynamic_deps": "[]",
1682			}),
1683		},
1684	})
1685}
1686
1687func TestCcLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) {
1688	// Note that this behavior is technically incorrect (it's a simplification).
1689	// The correct behavior would be if bp2build wrote `system_dynamic_deps = []`
1690	// only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
1691	// b/195791252 tracks the fix.
1692	runCcLibraryTestCase(t, bp2buildTestCase{
1693		description:                "cc_library system_shared_libs empty for linux_bionic variant",
1694		moduleTypeUnderTest:        "cc_library",
1695		moduleTypeUnderTestFactory: cc.LibraryFactory,
1696		blueprint: soongCcLibraryPreamble + `
1697cc_library {
1698    name: "target_linux_bionic_empty",
1699    target: {
1700        linux_bionic: {
1701            system_shared_libs: [],
1702        },
1703    },
1704    include_build_directory: false,
1705}
1706`,
1707		expectedBazelTargets: makeCcLibraryTargets("target_linux_bionic_empty", attrNameToString{
1708			"system_dynamic_deps": `[]`,
1709		}),
1710	},
1711	)
1712}
1713
1714func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
1715	runCcLibraryTestCase(t, bp2buildTestCase{
1716		description:                "cc_library system_shared_libs empty for bionic variant",
1717		moduleTypeUnderTest:        "cc_library",
1718		moduleTypeUnderTestFactory: cc.LibraryFactory,
1719		blueprint: soongCcLibraryPreamble + `
1720cc_library {
1721    name: "target_bionic_empty",
1722    target: {
1723        bionic: {
1724            system_shared_libs: [],
1725        },
1726    },
1727    include_build_directory: false,
1728}
1729`,
1730		expectedBazelTargets: makeCcLibraryTargets("target_bionic_empty", attrNameToString{
1731			"system_dynamic_deps": `[]`,
1732		}),
1733	},
1734	)
1735}
1736
1737func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) {
1738	runCcLibraryTestCase(t, bp2buildTestCase{
1739		description:                "cc_library system_shared_libs set for shared and root",
1740		moduleTypeUnderTest:        "cc_library",
1741		moduleTypeUnderTestFactory: cc.LibraryFactory,
1742		blueprint: soongCcLibraryPreamble + `
1743cc_library {
1744    name: "libc",
1745    bazel_module: { bp2build_available: false },
1746}
1747cc_library {
1748    name: "libm",
1749    bazel_module: { bp2build_available: false },
1750}
1751
1752cc_library {
1753    name: "foo",
1754    system_shared_libs: ["libc"],
1755    shared: {
1756        system_shared_libs: ["libm"],
1757    },
1758    include_build_directory: false,
1759}
1760`,
1761		expectedBazelTargets: []string{
1762			makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
1763				"system_dynamic_deps": `[":libc"]`,
1764			}),
1765			makeBazelTarget("cc_library_shared", "foo", attrNameToString{
1766				"system_dynamic_deps": `[
1767        ":libc",
1768        ":libm",
1769    ]`,
1770			}),
1771		},
1772	})
1773}
1774
1775func TestCcLibraryOsSelects(t *testing.T) {
1776	runCcLibraryTestCase(t, bp2buildTestCase{
1777		description:                "cc_library - selects for all os targets",
1778		moduleTypeUnderTest:        "cc_library",
1779		moduleTypeUnderTestFactory: cc.LibraryFactory,
1780		filesystem:                 map[string]string{},
1781		blueprint: soongCcLibraryPreamble + `
1782cc_library {
1783    name: "foo-lib",
1784    srcs: ["base.cpp"],
1785    target: {
1786        android: {
1787            srcs: ["android.cpp"],
1788        },
1789        linux: {
1790            srcs: ["linux.cpp"],
1791        },
1792        linux_glibc: {
1793            srcs: ["linux_glibc.cpp"],
1794        },
1795        darwin: {
1796            srcs: ["darwin.cpp"],
1797        },
1798        bionic: {
1799            srcs: ["bionic.cpp"],
1800        },
1801        linux_musl: {
1802            srcs: ["linux_musl.cpp"],
1803        },
1804        windows: {
1805            srcs: ["windows.cpp"],
1806        },
1807    },
1808    include_build_directory: false,
1809}
1810`,
1811		expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
1812			"srcs": `["base.cpp"] + select({
1813        "//build/bazel/platforms/os:android": [
1814            "linux.cpp",
1815            "bionic.cpp",
1816            "android.cpp",
1817        ],
1818        "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
1819        "//build/bazel/platforms/os:linux": [
1820            "linux.cpp",
1821            "linux_glibc.cpp",
1822        ],
1823        "//build/bazel/platforms/os:linux_bionic": [
1824            "linux.cpp",
1825            "bionic.cpp",
1826        ],
1827        "//build/bazel/platforms/os:linux_musl": [
1828            "linux.cpp",
1829            "linux_musl.cpp",
1830        ],
1831        "//build/bazel/platforms/os:windows": ["windows.cpp"],
1832        "//conditions:default": [],
1833    })`,
1834		}),
1835	},
1836	)
1837}
1838
1839func TestLibcryptoHashInjection(t *testing.T) {
1840	runCcLibraryTestCase(t, bp2buildTestCase{
1841		description:                "cc_library - libcrypto hash injection",
1842		moduleTypeUnderTest:        "cc_library",
1843		moduleTypeUnderTestFactory: cc.LibraryFactory,
1844		filesystem:                 map[string]string{},
1845		blueprint: soongCcLibraryPreamble + `
1846cc_library {
1847    name: "libcrypto",
1848    target: {
1849        android: {
1850            inject_bssl_hash: true,
1851        },
1852    },
1853    include_build_directory: false,
1854}
1855`,
1856		expectedBazelTargets: makeCcLibraryTargets("libcrypto", attrNameToString{
1857			"inject_bssl_hash": `select({
1858        "//build/bazel/platforms/os:android": True,
1859        "//conditions:default": None,
1860    })`,
1861		}),
1862	},
1863	)
1864}
1865
1866func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) {
1867	type testCase struct {
1868		cpp_std        string
1869		c_std          string
1870		gnu_extensions string
1871		bazel_cpp_std  string
1872		bazel_c_std    string
1873	}
1874
1875	testCases := []testCase{
1876		// Existing usages of cpp_std in AOSP are:
1877		// experimental, c++11, c++17, c++2a, c++98, gnu++11, gnu++17
1878		//
1879		// not set, only emit if gnu_extensions is disabled. the default (gnu+17
1880		// is set in the toolchain.)
1881		{cpp_std: "", gnu_extensions: "", bazel_cpp_std: ""},
1882		{cpp_std: "", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
1883		{cpp_std: "", gnu_extensions: "true", bazel_cpp_std: ""},
1884		// experimental defaults to gnu++2a
1885		{cpp_std: "experimental", gnu_extensions: "", bazel_cpp_std: "gnu++2a"},
1886		{cpp_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "c++2a", bazel_c_std: "c99"},
1887		{cpp_std: "experimental", gnu_extensions: "true", bazel_cpp_std: "gnu++2a"},
1888		// Explicitly setting a c++ std does not use replace gnu++ std even if
1889		// gnu_extensions is true.
1890		// "c++11",
1891		{cpp_std: "c++11", gnu_extensions: "", bazel_cpp_std: "c++11"},
1892		{cpp_std: "c++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c99"},
1893		{cpp_std: "c++11", gnu_extensions: "true", bazel_cpp_std: "c++11"},
1894		// "c++17",
1895		{cpp_std: "c++17", gnu_extensions: "", bazel_cpp_std: "c++17"},
1896		{cpp_std: "c++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
1897		{cpp_std: "c++17", gnu_extensions: "true", bazel_cpp_std: "c++17"},
1898		// "c++2a",
1899		{cpp_std: "c++2a", gnu_extensions: "", bazel_cpp_std: "c++2a"},
1900		{cpp_std: "c++2a", gnu_extensions: "false", bazel_cpp_std: "c++2a", bazel_c_std: "c99"},
1901		{cpp_std: "c++2a", gnu_extensions: "true", bazel_cpp_std: "c++2a"},
1902		// "c++98",
1903		{cpp_std: "c++98", gnu_extensions: "", bazel_cpp_std: "c++98"},
1904		{cpp_std: "c++98", gnu_extensions: "false", bazel_cpp_std: "c++98", bazel_c_std: "c99"},
1905		{cpp_std: "c++98", gnu_extensions: "true", bazel_cpp_std: "c++98"},
1906		// gnu++ is replaced with c++ if gnu_extensions is explicitly false.
1907		// "gnu++11",
1908		{cpp_std: "gnu++11", gnu_extensions: "", bazel_cpp_std: "gnu++11"},
1909		{cpp_std: "gnu++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c99"},
1910		{cpp_std: "gnu++11", gnu_extensions: "true", bazel_cpp_std: "gnu++11"},
1911		// "gnu++17",
1912		{cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17"},
1913		{cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
1914		{cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17"},
1915
1916		// some c_std test cases
1917		{c_std: "experimental", gnu_extensions: "", bazel_c_std: "gnu11"},
1918		{c_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c11"},
1919		{c_std: "experimental", gnu_extensions: "true", bazel_c_std: "gnu11"},
1920		{c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
1921		{c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c11"},
1922		{c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
1923	}
1924	for i, tc := range testCases {
1925		name_prefix := fmt.Sprintf("a_%v", i)
1926		cppStdProp := ""
1927		if tc.cpp_std != "" {
1928			cppStdProp = fmt.Sprintf("    cpp_std: \"%s\",", tc.cpp_std)
1929		}
1930		cStdProp := ""
1931		if tc.c_std != "" {
1932			cStdProp = fmt.Sprintf("    c_std: \"%s\",", tc.c_std)
1933		}
1934		gnuExtensionsProp := ""
1935		if tc.gnu_extensions != "" {
1936			gnuExtensionsProp = fmt.Sprintf("    gnu_extensions: %s,", tc.gnu_extensions)
1937		}
1938		attrs := attrNameToString{}
1939		if tc.bazel_cpp_std != "" {
1940			attrs["cpp_std"] = fmt.Sprintf(`"%s"`, tc.bazel_cpp_std)
1941		}
1942		if tc.bazel_c_std != "" {
1943			attrs["c_std"] = fmt.Sprintf(`"%s"`, tc.bazel_c_std)
1944		}
1945
1946		runCcLibraryTestCase(t, bp2buildTestCase{
1947			description: fmt.Sprintf(
1948				"cc_library with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
1949			moduleTypeUnderTest:        "cc_library",
1950			moduleTypeUnderTestFactory: cc.LibraryFactory,
1951			blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
1952cc_library {
1953	name: "%s_full",
1954%s // cpp_std: *string
1955%s // c_std: *string
1956%s // gnu_extensions: *bool
1957	include_build_directory: false,
1958}
1959`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
1960			expectedBazelTargets: makeCcLibraryTargets(name_prefix+"_full", attrs),
1961		})
1962
1963		runCcLibraryStaticTestCase(t, bp2buildTestCase{
1964			description: fmt.Sprintf(
1965				"cc_library_static with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
1966			moduleTypeUnderTest:        "cc_library_static",
1967			moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
1968			blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
1969cc_library_static {
1970	name: "%s_static",
1971%s // cpp_std: *string
1972%s // c_std: *string
1973%s // gnu_extensions: *bool
1974	include_build_directory: false,
1975}
1976`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
1977			expectedBazelTargets: []string{
1978				makeBazelTarget("cc_library_static", name_prefix+"_static", attrs),
1979			},
1980		})
1981
1982		runCcLibrarySharedTestCase(t, bp2buildTestCase{
1983			description: fmt.Sprintf(
1984				"cc_library_shared with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
1985			moduleTypeUnderTest:        "cc_library_shared",
1986			moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
1987			blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
1988cc_library_shared {
1989	name: "%s_shared",
1990%s // cpp_std: *string
1991%s // c_std: *string
1992%s // gnu_extensions: *bool
1993	include_build_directory: false,
1994}
1995`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
1996			expectedBazelTargets: []string{
1997				makeBazelTarget("cc_library_shared", name_prefix+"_shared", attrs),
1998			},
1999		})
2000	}
2001}
2002
2003func TestCcLibraryProtoSimple(t *testing.T) {
2004	runCcLibraryTestCase(t, bp2buildTestCase{
2005		moduleTypeUnderTest:        "cc_library",
2006		moduleTypeUnderTestFactory: cc.LibraryFactory,
2007		blueprint: soongCcProtoPreamble + `cc_library {
2008	name: "foo",
2009	srcs: ["foo.proto"],
2010	include_build_directory: false,
2011}`,
2012		expectedBazelTargets: []string{
2013			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2014				"srcs": `["foo.proto"]`,
2015			}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
2016				"deps": `[":foo_proto"]`,
2017			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2018				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
2019				"deps":                              `[":libprotobuf-cpp-lite"]`,
2020			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2021				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
2022			}),
2023		},
2024	})
2025}
2026
2027func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) {
2028	runCcLibraryTestCase(t, bp2buildTestCase{
2029		moduleTypeUnderTest:        "cc_library",
2030		moduleTypeUnderTestFactory: cc.LibraryFactory,
2031		blueprint: soongCcProtoPreamble + `cc_library {
2032	name: "foo",
2033	srcs: ["foo.proto"],
2034	proto: { canonical_path_from_root: false},
2035	include_build_directory: false,
2036}`,
2037		expectedBazelTargets: []string{
2038			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2039				"srcs":                `["foo.proto"]`,
2040				"strip_import_prefix": `""`,
2041			}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
2042				"deps": `[":foo_proto"]`,
2043			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2044				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
2045				"deps":                              `[":libprotobuf-cpp-lite"]`,
2046			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2047				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
2048			}),
2049		},
2050	})
2051}
2052
2053func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) {
2054	runCcLibraryTestCase(t, bp2buildTestCase{
2055		moduleTypeUnderTest:        "cc_library",
2056		moduleTypeUnderTestFactory: cc.LibraryFactory,
2057		blueprint: soongCcProtoPreamble + `cc_library {
2058	name: "foo",
2059	srcs: ["foo.proto"],
2060	proto: { canonical_path_from_root: true},
2061	include_build_directory: false,
2062}`,
2063		expectedBazelTargets: []string{
2064			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2065				"srcs": `["foo.proto"]`,
2066			}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
2067				"deps": `[":foo_proto"]`,
2068			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2069				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
2070				"deps":                              `[":libprotobuf-cpp-lite"]`,
2071			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2072				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
2073			}),
2074		},
2075	})
2076}
2077
2078func TestCcLibraryProtoFull(t *testing.T) {
2079	runCcLibraryTestCase(t, bp2buildTestCase{
2080		moduleTypeUnderTest:        "cc_library",
2081		moduleTypeUnderTestFactory: cc.LibraryFactory,
2082		blueprint: soongCcProtoPreamble + `cc_library {
2083	name: "foo",
2084	srcs: ["foo.proto"],
2085	proto: {
2086		type: "full",
2087	},
2088	include_build_directory: false,
2089}`,
2090		expectedBazelTargets: []string{
2091			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2092				"srcs": `["foo.proto"]`,
2093			}), makeBazelTarget("cc_proto_library", "foo_cc_proto", attrNameToString{
2094				"deps": `[":foo_proto"]`,
2095			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2096				"implementation_whole_archive_deps": `[":foo_cc_proto"]`,
2097				"deps":                              `[":libprotobuf-cpp-full"]`,
2098			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2099				"dynamic_deps": `[":libprotobuf-cpp-full"]`,
2100			}),
2101		},
2102	})
2103}
2104
2105func TestCcLibraryProtoLite(t *testing.T) {
2106	runCcLibraryTestCase(t, bp2buildTestCase{
2107		moduleTypeUnderTest:        "cc_library",
2108		moduleTypeUnderTestFactory: cc.LibraryFactory,
2109		blueprint: soongCcProtoPreamble + `cc_library {
2110	name: "foo",
2111	srcs: ["foo.proto"],
2112	proto: {
2113		type: "lite",
2114	},
2115	include_build_directory: false,
2116}`,
2117		expectedBazelTargets: []string{
2118			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2119				"srcs": `["foo.proto"]`,
2120			}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
2121				"deps": `[":foo_proto"]`,
2122			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2123				"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
2124				"deps":                              `[":libprotobuf-cpp-lite"]`,
2125			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2126				"dynamic_deps": `[":libprotobuf-cpp-lite"]`,
2127			}),
2128		},
2129	})
2130}
2131
2132func TestCcLibraryProtoExportHeaders(t *testing.T) {
2133	runCcLibraryTestCase(t, bp2buildTestCase{
2134		moduleTypeUnderTest:        "cc_library",
2135		moduleTypeUnderTestFactory: cc.LibraryFactory,
2136		blueprint: soongCcProtoPreamble + `cc_library {
2137	name: "foo",
2138	srcs: ["foo.proto"],
2139	proto: {
2140		export_proto_headers: true,
2141	},
2142	include_build_directory: false,
2143}`,
2144		expectedBazelTargets: []string{
2145			makeBazelTarget("proto_library", "foo_proto", attrNameToString{
2146				"srcs": `["foo.proto"]`,
2147			}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
2148				"deps": `[":foo_proto"]`,
2149			}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2150				"deps":               `[":libprotobuf-cpp-lite"]`,
2151				"whole_archive_deps": `[":foo_cc_proto_lite"]`,
2152			}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2153				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
2154				"whole_archive_deps": `[":foo_cc_proto_lite"]`,
2155			}),
2156		},
2157	})
2158}
2159
2160func TestCcLibraryProtoFilegroups(t *testing.T) {
2161	runCcLibraryTestCase(t, bp2buildTestCase{
2162		moduleTypeUnderTest:        "cc_library",
2163		moduleTypeUnderTestFactory: cc.LibraryFactory,
2164		blueprint: soongCcProtoPreamble +
2165			simpleModuleDoNotConvertBp2build("filegroup", "a_fg_proto") +
2166			simpleModuleDoNotConvertBp2build("filegroup", "b_protos") +
2167			simpleModuleDoNotConvertBp2build("filegroup", "c-proto-srcs") +
2168			simpleModuleDoNotConvertBp2build("filegroup", "proto-srcs-d") + `
2169cc_library {
2170	name: "a",
2171	srcs: [":a_fg_proto"],
2172	proto: {
2173		export_proto_headers: true,
2174	},
2175	include_build_directory: false,
2176}
2177
2178cc_library {
2179	name: "b",
2180	srcs: [":b_protos"],
2181	proto: {
2182		export_proto_headers: true,
2183	},
2184	include_build_directory: false,
2185}
2186
2187cc_library {
2188	name: "c",
2189	srcs: [":c-proto-srcs"],
2190	proto: {
2191		export_proto_headers: true,
2192	},
2193	include_build_directory: false,
2194}
2195
2196cc_library {
2197	name: "d",
2198	srcs: [":proto-srcs-d"],
2199	proto: {
2200		export_proto_headers: true,
2201	},
2202	include_build_directory: false,
2203}`,
2204		expectedBazelTargets: []string{
2205			makeBazelTarget("proto_library", "a_proto", attrNameToString{
2206				"srcs": `[":a_fg_proto"]`,
2207			}), makeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", attrNameToString{
2208				"deps": `[":a_proto"]`,
2209			}), makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
2210				"deps":               `[":libprotobuf-cpp-lite"]`,
2211				"whole_archive_deps": `[":a_cc_proto_lite"]`,
2212				"srcs":               `[":a_fg_proto_cpp_srcs"]`,
2213				"srcs_as":            `[":a_fg_proto_as_srcs"]`,
2214				"srcs_c":             `[":a_fg_proto_c_srcs"]`,
2215			}), makeBazelTarget("cc_library_shared", "a", attrNameToString{
2216				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
2217				"whole_archive_deps": `[":a_cc_proto_lite"]`,
2218				"srcs":               `[":a_fg_proto_cpp_srcs"]`,
2219				"srcs_as":            `[":a_fg_proto_as_srcs"]`,
2220				"srcs_c":             `[":a_fg_proto_c_srcs"]`,
2221			}), makeBazelTarget("proto_library", "b_proto", attrNameToString{
2222				"srcs": `[":b_protos"]`,
2223			}), makeBazelTarget("cc_lite_proto_library", "b_cc_proto_lite", attrNameToString{
2224				"deps": `[":b_proto"]`,
2225			}), makeBazelTarget("cc_library_static", "b_bp2build_cc_library_static", attrNameToString{
2226				"deps":               `[":libprotobuf-cpp-lite"]`,
2227				"whole_archive_deps": `[":b_cc_proto_lite"]`,
2228				"srcs":               `[":b_protos_cpp_srcs"]`,
2229				"srcs_as":            `[":b_protos_as_srcs"]`,
2230				"srcs_c":             `[":b_protos_c_srcs"]`,
2231			}), makeBazelTarget("cc_library_shared", "b", attrNameToString{
2232				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
2233				"whole_archive_deps": `[":b_cc_proto_lite"]`,
2234				"srcs":               `[":b_protos_cpp_srcs"]`,
2235				"srcs_as":            `[":b_protos_as_srcs"]`,
2236				"srcs_c":             `[":b_protos_c_srcs"]`,
2237			}), makeBazelTarget("proto_library", "c_proto", attrNameToString{
2238				"srcs": `[":c-proto-srcs"]`,
2239			}), makeBazelTarget("cc_lite_proto_library", "c_cc_proto_lite", attrNameToString{
2240				"deps": `[":c_proto"]`,
2241			}), makeBazelTarget("cc_library_static", "c_bp2build_cc_library_static", attrNameToString{
2242				"deps":               `[":libprotobuf-cpp-lite"]`,
2243				"whole_archive_deps": `[":c_cc_proto_lite"]`,
2244				"srcs":               `[":c-proto-srcs_cpp_srcs"]`,
2245				"srcs_as":            `[":c-proto-srcs_as_srcs"]`,
2246				"srcs_c":             `[":c-proto-srcs_c_srcs"]`,
2247			}), makeBazelTarget("cc_library_shared", "c", attrNameToString{
2248				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
2249				"whole_archive_deps": `[":c_cc_proto_lite"]`,
2250				"srcs":               `[":c-proto-srcs_cpp_srcs"]`,
2251				"srcs_as":            `[":c-proto-srcs_as_srcs"]`,
2252				"srcs_c":             `[":c-proto-srcs_c_srcs"]`,
2253			}), makeBazelTarget("proto_library", "d_proto", attrNameToString{
2254				"srcs": `[":proto-srcs-d"]`,
2255			}), makeBazelTarget("cc_lite_proto_library", "d_cc_proto_lite", attrNameToString{
2256				"deps": `[":d_proto"]`,
2257			}), makeBazelTarget("cc_library_static", "d_bp2build_cc_library_static", attrNameToString{
2258				"deps":               `[":libprotobuf-cpp-lite"]`,
2259				"whole_archive_deps": `[":d_cc_proto_lite"]`,
2260				"srcs":               `[":proto-srcs-d_cpp_srcs"]`,
2261				"srcs_as":            `[":proto-srcs-d_as_srcs"]`,
2262				"srcs_c":             `[":proto-srcs-d_c_srcs"]`,
2263			}), makeBazelTarget("cc_library_shared", "d", attrNameToString{
2264				"dynamic_deps":       `[":libprotobuf-cpp-lite"]`,
2265				"whole_archive_deps": `[":d_cc_proto_lite"]`,
2266				"srcs":               `[":proto-srcs-d_cpp_srcs"]`,
2267				"srcs_as":            `[":proto-srcs-d_as_srcs"]`,
2268				"srcs_c":             `[":proto-srcs-d_c_srcs"]`,
2269			}),
2270		},
2271	})
2272}
2273
2274func TestCcLibraryDisabledArchAndTarget(t *testing.T) {
2275	runCcLibraryTestCase(t, bp2buildTestCase{
2276		moduleTypeUnderTest:        "cc_library",
2277		moduleTypeUnderTestFactory: cc.LibraryFactory,
2278		blueprint: soongCcProtoPreamble + `cc_library {
2279	name: "foo",
2280	srcs: ["foo.cpp"],
2281	target: {
2282		darwin: {
2283			enabled: false,
2284		},
2285		windows: {
2286			enabled: false,
2287		},
2288		linux_glibc_x86: {
2289			enabled: false,
2290		},
2291	},
2292	include_build_directory: false,
2293}`,
2294		expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
2295			"srcs": `["foo.cpp"]`,
2296			"target_compatible_with": `select({
2297        "//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
2298        "//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
2299        "//build/bazel/platforms/os_arch:linux_glibc_x86": ["@platforms//:incompatible"],
2300        "//build/bazel/platforms/os_arch:windows_x86": ["@platforms//:incompatible"],
2301        "//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
2302        "//conditions:default": [],
2303    })`,
2304		}),
2305	})
2306}
2307
2308func TestCcLibraryDisabledArchAndTargetWithDefault(t *testing.T) {
2309	runCcLibraryTestCase(t, bp2buildTestCase{
2310		moduleTypeUnderTest:        "cc_library",
2311		moduleTypeUnderTestFactory: cc.LibraryFactory,
2312		blueprint: soongCcProtoPreamble + `cc_library {
2313	name: "foo",
2314	srcs: ["foo.cpp"],
2315  enabled: false,
2316	target: {
2317		darwin: {
2318			enabled: true,
2319		},
2320		windows: {
2321			enabled: false,
2322		},
2323		linux_glibc_x86: {
2324			enabled: false,
2325		},
2326	},
2327	include_build_directory: false,
2328}`,
2329		expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
2330			"srcs": `["foo.cpp"]`,
2331			"target_compatible_with": `select({
2332        "//build/bazel/platforms/os_arch:darwin_arm64": [],
2333        "//build/bazel/platforms/os_arch:darwin_x86_64": [],
2334        "//conditions:default": ["@platforms//:incompatible"],
2335    })`,
2336		}),
2337	})
2338}
2339
2340func TestCcLibrarySharedDisabled(t *testing.T) {
2341	runCcLibraryTestCase(t, bp2buildTestCase{
2342		moduleTypeUnderTest:        "cc_library",
2343		moduleTypeUnderTestFactory: cc.LibraryFactory,
2344		blueprint: soongCcProtoPreamble + `cc_library {
2345	name: "foo",
2346	srcs: ["foo.cpp"],
2347	enabled: false,
2348	shared: {
2349		enabled: true,
2350	},
2351	target: {
2352		android: {
2353			shared: {
2354				enabled: false,
2355			},
2356		}
2357  },
2358	include_build_directory: false,
2359}`,
2360		expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2361			"srcs":                   `["foo.cpp"]`,
2362			"target_compatible_with": `["@platforms//:incompatible"]`,
2363		}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2364			"srcs": `["foo.cpp"]`,
2365			"target_compatible_with": `select({
2366        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
2367        "//conditions:default": [],
2368    })`,
2369		}),
2370		},
2371	})
2372}
2373
2374func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) {
2375	runCcLibraryTestCase(t, bp2buildTestCase{
2376		moduleTypeUnderTest:        "cc_library",
2377		moduleTypeUnderTestFactory: cc.LibraryFactory,
2378		blueprint: soongCcProtoPreamble + `cc_library {
2379	name: "foo",
2380	srcs: ["foo.cpp"],
2381	shared: {
2382		enabled: false
2383	},
2384	target: {
2385		darwin: {
2386			enabled: true,
2387		},
2388		windows: {
2389			enabled: false,
2390		},
2391		linux_glibc_x86: {
2392			shared: {
2393				enabled: true,
2394			},
2395		},
2396	},
2397	include_build_directory: false,
2398}`,
2399		expectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
2400			"srcs": `["foo.cpp"]`,
2401			"target_compatible_with": `select({
2402        "//build/bazel/platforms/os:windows": ["@platforms//:incompatible"],
2403        "//conditions:default": [],
2404    })`,
2405		}), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
2406			"srcs": `["foo.cpp"]`,
2407			"target_compatible_with": `select({
2408        "//build/bazel/platforms/os_arch:darwin_arm64": [],
2409        "//build/bazel/platforms/os_arch:darwin_x86_64": [],
2410        "//build/bazel/platforms/os_arch:linux_glibc_x86": [],
2411        "//conditions:default": ["@platforms//:incompatible"],
2412    })`,
2413		}),
2414		}})
2415}
2416
2417func TestCcLibraryStubs(t *testing.T) {
2418	runCcLibraryTestCase(t, bp2buildTestCase{
2419		description:                "cc_library stubs",
2420		moduleTypeUnderTest:        "cc_library",
2421		moduleTypeUnderTestFactory: cc.LibraryFactory,
2422		dir:                        "foo/bar",
2423		filesystem: map[string]string{
2424			"foo/bar/Android.bp": `
2425cc_library {
2426    name: "a",
2427    stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
2428    bazel_module: { bp2build_available: true },
2429    include_build_directory: false,
2430}
2431`,
2432		},
2433		blueprint: soongCcLibraryPreamble,
2434		expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
2435			"stubs_symbol_file": `"a.map.txt"`,
2436			"stubs_versions": `[
2437        "28",
2438        "29",
2439        "current",
2440    ]`,
2441		}),
2442	},
2443	)
2444}
2445
2446func TestCcLibraryEscapeLdflags(t *testing.T) {
2447	runCcLibraryTestCase(t, bp2buildTestCase{
2448		moduleTypeUnderTest:        "cc_library",
2449		moduleTypeUnderTestFactory: cc.LibraryFactory,
2450		blueprint: soongCcProtoPreamble + `cc_library {
2451	name: "foo",
2452	ldflags: ["-Wl,--rpath,${ORIGIN}"],
2453	include_build_directory: false,
2454}`,
2455		expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
2456			"linkopts": `["-Wl,--rpath,$${ORIGIN}"]`,
2457		}),
2458	})
2459}
2460