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 "android/soong/bazel/cquery" 23) 24 25func TestLibraryReuse(t *testing.T) { 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 bp := ` 195 cc_library { 196 name: "libfoo", 197 srcs: ["foo.c"], 198 stubs: { 199 versions: ["29", "R", "current"], 200 }, 201 } 202 ` 203 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 204 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 205 ctx := testCcWithConfig(t, config) 206 207 variants := ctx.ModuleVariantsForTests("libfoo") 208 for _, expectedVer := range []string{"29", "R", "current"} { 209 expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer 210 if !inList(expectedVariant, variants) { 211 t.Errorf("missing expected variant: %q", expectedVariant) 212 } 213 } 214} 215 216func TestStubsVersions_NotSorted(t *testing.T) { 217 bp := ` 218 cc_library { 219 name: "libfoo", 220 srcs: ["foo.c"], 221 stubs: { 222 versions: ["29", "current", "R"], 223 }, 224 } 225 ` 226 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 227 config.TestProductVariables.Platform_version_active_codenames = []string{"R"} 228 testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config) 229} 230 231func TestStubsVersions_ParseError(t *testing.T) { 232 bp := ` 233 cc_library { 234 name: "libfoo", 235 srcs: ["foo.c"], 236 stubs: { 237 versions: ["29", "current", "X"], 238 }, 239 } 240 ` 241 242 testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp) 243} 244 245func TestCcLibraryWithBazel(t *testing.T) { 246 bp := ` 247cc_library { 248 name: "foo", 249 srcs: ["foo.cc"], 250 bazel_module: { label: "//foo/bar:bar" }, 251}` 252 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 253 config.BazelContext = android.MockBazelContext{ 254 OutputBaseDir: "outputbase", 255 LabelToCcInfo: map[string]cquery.CcInfo{ 256 "//foo/bar:bar": cquery.CcInfo{ 257 CcObjectFiles: []string{"foo.o"}, 258 Includes: []string{"include"}, 259 SystemIncludes: []string{"system_include"}, 260 Headers: []string{"foo.h"}, 261 RootDynamicLibraries: []string{"foo.so"}, 262 }, 263 "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{ 264 CcObjectFiles: []string{"foo.o"}, 265 Includes: []string{"include"}, 266 SystemIncludes: []string{"system_include"}, 267 Headers: []string{"foo.h"}, 268 RootStaticArchives: []string{"foo.a"}, 269 }, 270 }, 271 } 272 ctx := testCcWithConfig(t, config) 273 274 staticFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module() 275 outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("") 276 if err != nil { 277 t.Errorf("Unexpected error getting cc_object outputfiles %s", err) 278 } 279 280 expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"} 281 android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) 282 283 flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo) 284 android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) 285 android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) 286 android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) 287 android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) 288 289 sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() 290 outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("") 291 if err != nil { 292 t.Errorf("Unexpected error getting cc_library outputfiles %s", err) 293 } 294 expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"} 295 android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) 296 297 flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo) 298 android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs) 299 android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs) 300 android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders) 301 android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps) 302} 303 304func TestLibraryVersionScript(t *testing.T) { 305 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 306 cc_library { 307 name: "libfoo", 308 srcs: ["foo.c"], 309 version_script: "foo.map.txt", 310 }`) 311 312 libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") 313 314 android.AssertStringListContains(t, "missing dependency on version_script", 315 libfoo.Implicits.Strings(), "foo.map.txt") 316 android.AssertStringDoesContain(t, "missing flag for version_script", 317 libfoo.Args["ldFlags"], "-Wl,--version-script,foo.map.txt") 318 319} 320 321func TestLibraryDynamicList(t *testing.T) { 322 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 323 cc_library { 324 name: "libfoo", 325 srcs: ["foo.c"], 326 dynamic_list: "foo.dynamic.txt", 327 }`) 328 329 libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") 330 331 android.AssertStringListContains(t, "missing dependency on dynamic_list", 332 libfoo.Implicits.Strings(), "foo.dynamic.txt") 333 android.AssertStringDoesContain(t, "missing flag for dynamic_list", 334 libfoo.Args["ldFlags"], "-Wl,--dynamic-list,foo.dynamic.txt") 335 336} 337 338func TestCcLibrarySharedWithBazel(t *testing.T) { 339 bp := ` 340cc_library_shared { 341 name: "foo", 342 srcs: ["foo.cc"], 343 bazel_module: { label: "//foo/bar:bar" }, 344}` 345 config := TestConfig(t.TempDir(), android.Android, nil, bp, nil) 346 config.BazelContext = android.MockBazelContext{ 347 OutputBaseDir: "outputbase", 348 LabelToCcInfo: map[string]cquery.CcInfo{ 349 "//foo/bar:bar": cquery.CcInfo{ 350 CcObjectFiles: []string{"foo.o"}, 351 Includes: []string{"include"}, 352 SystemIncludes: []string{"system_include"}, 353 RootDynamicLibraries: []string{"foo.so"}, 354 TocFile: "foo.so.toc", 355 }, 356 }, 357 } 358 ctx := testCcWithConfig(t, config) 359 360 sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module() 361 producer := sharedFoo.(android.OutputFileProducer) 362 outputFiles, err := producer.OutputFiles("") 363 if err != nil { 364 t.Errorf("Unexpected error getting cc_object outputfiles %s", err) 365 } 366 expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.so"} 367 android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings()) 368 369 tocFilePath := sharedFoo.(*Module).Toc() 370 if !tocFilePath.Valid() { 371 t.Errorf("Invalid tocFilePath: %s", tocFilePath) 372 } 373 tocFile := tocFilePath.Path() 374 expectedToc := "outputbase/execroot/__main__/foo.so.toc" 375 android.AssertStringEquals(t, "toc file", expectedToc, tocFile.String()) 376 377 entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0] 378 expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"} 379 gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"] 380 android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags) 381} 382 383func TestWholeStaticLibPrebuilts(t *testing.T) { 384 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, ` 385 cc_prebuilt_library_static { 386 name: "libprebuilt", 387 srcs: ["foo.a"], 388 } 389 390 cc_library_static { 391 name: "libdirect", 392 whole_static_libs: ["libprebuilt"], 393 } 394 395 cc_library_static { 396 name: "libtransitive", 397 whole_static_libs: ["libdirect"], 398 } 399 400 cc_library_static { 401 name: "libdirect_with_srcs", 402 srcs: ["bar.c"], 403 whole_static_libs: ["libprebuilt"], 404 } 405 406 cc_library_static { 407 name: "libtransitive_with_srcs", 408 srcs: ["baz.c"], 409 whole_static_libs: ["libdirect_with_srcs"], 410 } 411 `) 412 413 libdirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static").Rule("arWithLibs") 414 libtransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static").Rule("arWithLibs") 415 416 libdirectWithSrcs := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs") 417 libtransitiveWithSrcs := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs") 418 419 barObj := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("cc") 420 bazObj := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("cc") 421 422 android.AssertStringListContains(t, "missing dependency on foo.a", 423 libdirect.Inputs.Strings(), "foo.a") 424 android.AssertStringDoesContain(t, "missing flag for foo.a", 425 libdirect.Args["arLibs"], "foo.a") 426 427 android.AssertStringListContains(t, "missing dependency on foo.a", 428 libtransitive.Inputs.Strings(), "foo.a") 429 android.AssertStringDoesContain(t, "missing flag for foo.a", 430 libtransitive.Args["arLibs"], "foo.a") 431 432 android.AssertStringListContains(t, "missing dependency on foo.a", 433 libdirectWithSrcs.Inputs.Strings(), "foo.a") 434 android.AssertStringDoesContain(t, "missing flag for foo.a", 435 libdirectWithSrcs.Args["arLibs"], "foo.a") 436 android.AssertStringListContains(t, "missing dependency on bar.o", 437 libdirectWithSrcs.Inputs.Strings(), barObj.Output.String()) 438 android.AssertStringDoesContain(t, "missing flag for bar.o", 439 libdirectWithSrcs.Args["arObjs"], barObj.Output.String()) 440 441 android.AssertStringListContains(t, "missing dependency on foo.a", 442 libtransitiveWithSrcs.Inputs.Strings(), "foo.a") 443 android.AssertStringDoesContain(t, "missing flag for foo.a", 444 libtransitiveWithSrcs.Args["arLibs"], "foo.a") 445 446 android.AssertStringListContains(t, "missing dependency on bar.o", 447 libtransitiveWithSrcs.Inputs.Strings(), barObj.Output.String()) 448 android.AssertStringDoesContain(t, "missing flag for bar.o", 449 libtransitiveWithSrcs.Args["arObjs"], barObj.Output.String()) 450 451 android.AssertStringListContains(t, "missing dependency on baz.o", 452 libtransitiveWithSrcs.Inputs.Strings(), bazObj.Output.String()) 453 android.AssertStringDoesContain(t, "missing flag for baz.o", 454 libtransitiveWithSrcs.Args["arObjs"], bazObj.Output.String()) 455} 456