1// 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
15package cc
16
17import (
18	"reflect"
19	"testing"
20
21	"android/soong/android"
22)
23
24func TestLibraryReuse(t *testing.T) {
25	t.Run("simple", func(t *testing.T) {
26		ctx := testCc(t, `
27		cc_library {
28			name: "libfoo",
29			srcs: ["foo.c", "baz.o"],
30		}`)
31
32		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
33		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
34
35		if len(libfooShared.Inputs) != 2 {
36			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
37		}
38
39		if len(libfooStatic.Inputs) != 2 {
40			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
41		}
42
43		if libfooShared.Inputs[0] != libfooStatic.Inputs[0] {
44			t.Errorf("static object not reused for shared library")
45		}
46		if libfooShared.Inputs[1] != libfooStatic.Inputs[1] {
47			t.Errorf("static object not reused for shared library")
48		}
49	})
50
51	t.Run("extra static source", func(t *testing.T) {
52		ctx := testCc(t, `
53		cc_library {
54			name: "libfoo",
55			srcs: ["foo.c"],
56			static: {
57				srcs: ["bar.c"]
58			},
59		}`)
60
61		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
62		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
63
64		if len(libfooShared.Inputs) != 1 {
65			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
66		}
67
68		if len(libfooStatic.Inputs) != 2 {
69			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
70		}
71
72		if libfooShared.Inputs[0] != libfooStatic.Inputs[0] {
73			t.Errorf("static object not reused for shared library")
74		}
75	})
76
77	t.Run("extra shared source", func(t *testing.T) {
78		ctx := testCc(t, `
79		cc_library {
80			name: "libfoo",
81			srcs: ["foo.c"],
82			shared: {
83				srcs: ["bar.c"]
84			},
85		}`)
86
87		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
88		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
89
90		if len(libfooShared.Inputs) != 2 {
91			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
92		}
93
94		if len(libfooStatic.Inputs) != 1 {
95			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
96		}
97
98		if libfooShared.Inputs[0] != libfooStatic.Inputs[0] {
99			t.Errorf("static object not reused for shared library")
100		}
101	})
102
103	t.Run("extra static cflags", func(t *testing.T) {
104		ctx := testCc(t, `
105		cc_library {
106			name: "libfoo",
107			srcs: ["foo.c"],
108			static: {
109				cflags: ["-DFOO"],
110			},
111		}`)
112
113		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
114		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
115
116		if len(libfooShared.Inputs) != 1 {
117			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
118		}
119
120		if len(libfooStatic.Inputs) != 1 {
121			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
122		}
123
124		if libfooShared.Inputs[0] == libfooStatic.Inputs[0] {
125			t.Errorf("static object reused for shared library when it shouldn't be")
126		}
127	})
128
129	t.Run("extra shared cflags", func(t *testing.T) {
130		ctx := testCc(t, `
131		cc_library {
132			name: "libfoo",
133			srcs: ["foo.c"],
134			shared: {
135				cflags: ["-DFOO"],
136			},
137		}`)
138
139		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
140		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
141
142		if len(libfooShared.Inputs) != 1 {
143			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
144		}
145
146		if len(libfooStatic.Inputs) != 1 {
147			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
148		}
149
150		if libfooShared.Inputs[0] == libfooStatic.Inputs[0] {
151			t.Errorf("static object reused for shared library when it shouldn't be")
152		}
153	})
154
155	t.Run("global cflags for reused generated sources", func(t *testing.T) {
156		ctx := testCc(t, `
157		cc_library {
158			name: "libfoo",
159			srcs: [
160				"foo.c",
161				"a.proto",
162			],
163			shared: {
164				srcs: [
165					"bar.c",
166				],
167			},
168		}`)
169
170		libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
171		libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
172
173		if len(libfooShared.Inputs) != 3 {
174			t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
175		}
176
177		if len(libfooStatic.Inputs) != 2 {
178			t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings())
179		}
180
181		if !reflect.DeepEqual(libfooShared.Inputs[0:2].Strings(), libfooStatic.Inputs.Strings()) {
182			t.Errorf("static objects not reused for shared library")
183		}
184
185		libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
186		if !inList("-DGOOGLE_PROTOBUF_NO_RTTI", libfoo.flags.Local.CFlags) {
187			t.Errorf("missing protobuf cflags")
188		}
189	})
190}
191
192func TestStubsVersions(t *testing.T) {
193	bp := `
194		cc_library {
195			name: "libfoo",
196			srcs: ["foo.c"],
197			stubs: {
198				versions: ["29", "R", "10000"],
199			},
200		}
201	`
202	config := TestConfig(buildDir, android.Android, nil, bp, nil)
203	config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
204	ctx := testCcWithConfig(t, config)
205
206	variants := ctx.ModuleVariantsForTests("libfoo")
207	for _, expectedVer := range []string{"29", "9000", "10000"} {
208		expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer
209		if !inList(expectedVariant, variants) {
210			t.Errorf("missing expected variant: %q", expectedVariant)
211		}
212	}
213}
214
215func TestStubsVersions_NotSorted(t *testing.T) {
216	bp := `
217		cc_library {
218			name: "libfoo",
219			srcs: ["foo.c"],
220			stubs: {
221				versions: ["29", "10000", "R"],
222			},
223		}
224	`
225	config := TestConfig(buildDir, android.Android, nil, bp, nil)
226	config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
227	testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config)
228}
229
230func TestStubsVersions_ParseError(t *testing.T) {
231	bp := `
232		cc_library {
233			name: "libfoo",
234			srcs: ["foo.c"],
235			stubs: {
236				versions: ["29", "10000", "X"],
237			},
238		}
239	`
240
241	testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp)
242}
243