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.Parallel() 26 t.Run("simple", func(t *testing.T) { 27 ctx := testCc(t, ` 28 cc_library { 29 name: "libfoo", 30 srcs: ["foo.c", "baz.o"], 31 }`) 32 33 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 34 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 35 36 if len(libfooShared.Inputs) != 2 { 37 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 38 } 39 40 if len(libfooStatic.Inputs) != 2 { 41 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 42 } 43 44 if libfooShared.Inputs[0] != libfooStatic.Inputs[0] { 45 t.Errorf("static object not reused for shared library") 46 } 47 if libfooShared.Inputs[1] != libfooStatic.Inputs[1] { 48 t.Errorf("static object not reused for shared library") 49 } 50 }) 51 52 t.Run("extra static source", func(t *testing.T) { 53 ctx := testCc(t, ` 54 cc_library { 55 name: "libfoo", 56 srcs: ["foo.c"], 57 static: { 58 srcs: ["bar.c"] 59 }, 60 }`) 61 62 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 63 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 64 65 if len(libfooShared.Inputs) != 1 { 66 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 67 } 68 69 if len(libfooStatic.Inputs) != 2 { 70 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 71 } 72 73 if libfooShared.Inputs[0] != libfooStatic.Inputs[0] { 74 t.Errorf("static object not reused for shared library") 75 } 76 }) 77 78 t.Run("extra shared source", func(t *testing.T) { 79 ctx := testCc(t, ` 80 cc_library { 81 name: "libfoo", 82 srcs: ["foo.c"], 83 shared: { 84 srcs: ["bar.c"] 85 }, 86 }`) 87 88 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 89 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 90 91 if len(libfooShared.Inputs) != 2 { 92 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 93 } 94 95 if len(libfooStatic.Inputs) != 1 { 96 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 97 } 98 99 if libfooShared.Inputs[0] != libfooStatic.Inputs[0] { 100 t.Errorf("static object not reused for shared library") 101 } 102 }) 103 104 t.Run("extra static cflags", func(t *testing.T) { 105 ctx := testCc(t, ` 106 cc_library { 107 name: "libfoo", 108 srcs: ["foo.c"], 109 static: { 110 cflags: ["-DFOO"], 111 }, 112 }`) 113 114 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 115 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 116 117 if len(libfooShared.Inputs) != 1 { 118 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 119 } 120 121 if len(libfooStatic.Inputs) != 1 { 122 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 123 } 124 125 if libfooShared.Inputs[0] == libfooStatic.Inputs[0] { 126 t.Errorf("static object reused for shared library when it shouldn't be") 127 } 128 }) 129 130 t.Run("extra shared cflags", func(t *testing.T) { 131 ctx := testCc(t, ` 132 cc_library { 133 name: "libfoo", 134 srcs: ["foo.c"], 135 shared: { 136 cflags: ["-DFOO"], 137 }, 138 }`) 139 140 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 141 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 142 143 if len(libfooShared.Inputs) != 1 { 144 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 145 } 146 147 if len(libfooStatic.Inputs) != 1 { 148 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 149 } 150 151 if libfooShared.Inputs[0] == libfooStatic.Inputs[0] { 152 t.Errorf("static object reused for shared library when it shouldn't be") 153 } 154 }) 155 156 t.Run("global cflags for reused generated sources", func(t *testing.T) { 157 ctx := testCc(t, ` 158 cc_library { 159 name: "libfoo", 160 srcs: [ 161 "foo.c", 162 "a.proto", 163 ], 164 shared: { 165 srcs: [ 166 "bar.c", 167 ], 168 }, 169 }`) 170 171 libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 172 libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a") 173 174 if len(libfooShared.Inputs) != 3 { 175 t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings()) 176 } 177 178 if len(libfooStatic.Inputs) != 2 { 179 t.Fatalf("unexpected inputs to libfoo static: %#v", libfooStatic.Inputs.Strings()) 180 } 181 182 if !reflect.DeepEqual(libfooShared.Inputs[0:2].Strings(), libfooStatic.Inputs.Strings()) { 183 t.Errorf("static objects not reused for shared library") 184 } 185 186 libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module) 187 if !inList("-DGOOGLE_PROTOBUF_NO_RTTI", libfoo.flags.Local.CFlags) { 188 t.Errorf("missing protobuf cflags") 189 } 190 }) 191} 192 193func TestStubsVersions(t *testing.T) { 194 t.Parallel() 195 bp := ` 196 cc_library { 197 name: "libfoo", 198 srcs: ["foo.c"], 199 stubs: { 200 versions: ["29", "R", "current"], 201 }, 202 } 203 ` 204 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 205 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 206 ctx := testCcWithConfig(t, config) 207 208 variants := ctx.ModuleVariantsForTests("libfoo") 209 for _, expectedVer := range []string{"29", "R", "current"} { 210 expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer 211 if !inList(expectedVariant, variants) { 212 t.Errorf("missing expected variant: %q", expectedVariant) 213 } 214 } 215} 216 217func TestStubsVersions_NotSorted(t *testing.T) { 218 t.Parallel() 219 bp := ` 220 cc_library { 221 name: "libfoo", 222 srcs: ["foo.c"], 223 stubs: { 224 versions: ["29", "current", "R"], 225 }, 226 } 227 ` 228 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 229 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 230 testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config) 231} 232 233func TestStubsVersions_ParseError(t *testing.T) { 234 t.Parallel() 235 bp := ` 236 cc_library { 237 name: "libfoo", 238 srcs: ["foo.c"], 239 stubs: { 240 versions: ["29", "current", "X"], 241 }, 242 } 243 ` 244 245 testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp) 246} 247 248func TestLibraryVersionScript(t *testing.T) { 249 t.Parallel() 250 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 251 cc_library { 252 name: "libfoo", 253 srcs: ["foo.c"], 254 version_script: "foo.map.txt", 255 }`) 256 257 libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") 258 259 android.AssertStringListContains(t, "missing dependency on version_script", 260 libfoo.Implicits.Strings(), "foo.map.txt") 261 android.AssertStringDoesContain(t, "missing flag for version_script", 262 libfoo.Args["ldFlags"], "-Wl,--version-script,foo.map.txt") 263 264} 265 266func TestLibraryDynamicList(t *testing.T) { 267 t.Parallel() 268 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 269 cc_library { 270 name: "libfoo", 271 srcs: ["foo.c"], 272 dynamic_list: "foo.dynamic.txt", 273 }`) 274 275 libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") 276 277 android.AssertStringListContains(t, "missing dependency on dynamic_list", 278 libfoo.Implicits.Strings(), "foo.dynamic.txt") 279 android.AssertStringDoesContain(t, "missing flag for dynamic_list", 280 libfoo.Args["ldFlags"], "-Wl,--dynamic-list,foo.dynamic.txt") 281 282} 283 284func TestWholeStaticLibPrebuilts(t *testing.T) { 285 t.Parallel() 286 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 287 cc_prebuilt_library_static { 288 name: "libprebuilt", 289 srcs: ["foo.a"], 290 } 291 292 cc_library_static { 293 name: "libdirect", 294 whole_static_libs: ["libprebuilt"], 295 } 296 297 cc_library_static { 298 name: "libtransitive", 299 whole_static_libs: ["libdirect"], 300 } 301 302 cc_library_static { 303 name: "libdirect_with_srcs", 304 srcs: ["bar.c"], 305 whole_static_libs: ["libprebuilt"], 306 } 307 308 cc_library_static { 309 name: "libtransitive_with_srcs", 310 srcs: ["baz.c"], 311 whole_static_libs: ["libdirect_with_srcs"], 312 } 313 `) 314 315 libdirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static").Rule("arWithLibs") 316 libtransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static").Rule("arWithLibs") 317 318 libdirectWithSrcs := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs") 319 libtransitiveWithSrcs := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs") 320 321 barObj := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("cc") 322 bazObj := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("cc") 323 324 android.AssertStringListContains(t, "missing dependency on foo.a", 325 libdirect.Inputs.Strings(), "foo.a") 326 android.AssertStringDoesContain(t, "missing flag for foo.a", 327 libdirect.Args["arLibs"], "foo.a") 328 329 android.AssertStringListContains(t, "missing dependency on foo.a", 330 libtransitive.Inputs.Strings(), "foo.a") 331 android.AssertStringDoesContain(t, "missing flag for foo.a", 332 libtransitive.Args["arLibs"], "foo.a") 333 334 android.AssertStringListContains(t, "missing dependency on foo.a", 335 libdirectWithSrcs.Inputs.Strings(), "foo.a") 336 android.AssertStringDoesContain(t, "missing flag for foo.a", 337 libdirectWithSrcs.Args["arLibs"], "foo.a") 338 android.AssertStringListContains(t, "missing dependency on bar.o", 339 libdirectWithSrcs.Inputs.Strings(), barObj.Output.String()) 340 android.AssertStringDoesContain(t, "missing flag for bar.o", 341 libdirectWithSrcs.Args["arObjs"], barObj.Output.String()) 342 343 android.AssertStringListContains(t, "missing dependency on foo.a", 344 libtransitiveWithSrcs.Inputs.Strings(), "foo.a") 345 android.AssertStringDoesContain(t, "missing flag for foo.a", 346 libtransitiveWithSrcs.Args["arLibs"], "foo.a") 347 348 android.AssertStringListContains(t, "missing dependency on bar.o", 349 libtransitiveWithSrcs.Inputs.Strings(), barObj.Output.String()) 350 android.AssertStringDoesContain(t, "missing flag for bar.o", 351 libtransitiveWithSrcs.Args["arObjs"], barObj.Output.String()) 352 353 android.AssertStringListContains(t, "missing dependency on baz.o", 354 libtransitiveWithSrcs.Inputs.Strings(), bazObj.Output.String()) 355 android.AssertStringDoesContain(t, "missing flag for baz.o", 356 libtransitiveWithSrcs.Args["arObjs"], bazObj.Output.String()) 357} 358