123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // Copyright 2021 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package cc
- import (
- "strings"
- "testing"
- "android/soong/android"
- "github.com/google/blueprint"
- )
- var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureModifyEnv(func(env map[string]string) {
- env["GLOBAL_THINLTO"] = "false"
- }))
- func TestThinLtoDeps(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library_shared {
- name: "lto_enabled",
- srcs: ["src.c"],
- static_libs: ["foo", "lib_never_lto"],
- shared_libs: ["bar"],
- lto: {
- thin: true,
- }
- }
- cc_library_static {
- name: "foo",
- static_libs: ["baz"],
- }
- cc_library_shared {
- name: "bar",
- static_libs: ["qux"],
- }
- cc_library_static {
- name: "baz",
- }
- cc_library_static {
- name: "qux",
- }
- cc_library_static {
- name: "lib_never_lto",
- lto: {
- never: true,
- },
- }
- `
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
- libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libFoo) {
- t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
- }
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libFoo, libBaz) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
- }
- libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libNeverLto) {
- t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
- }
- libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
- if !hasDep(libLto, libBar) {
- t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
- }
- barVariants := result.ModuleVariantsForTests("bar")
- for _, v := range barVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
- }
- }
- quxVariants := result.ModuleVariantsForTests("qux")
- for _, v := range quxVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
- }
- }
- }
- func TestThinLtoOnlyOnStaticDep(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library_shared {
- name: "root",
- srcs: ["src.c"],
- static_libs: ["foo"],
- }
- cc_library_shared {
- name: "root_no_lto",
- srcs: ["src.c"],
- static_libs: ["foo"],
- lto: {
- never: true,
- }
- }
- cc_library_static {
- name: "foo",
- srcs: ["foo.c"],
- static_libs: ["baz"],
- lto: {
- thin: true,
- }
- }
- cc_library_static {
- name: "baz",
- srcs: ["baz.c"],
- }
- `
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
- libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
- libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
- if !hasDep(libRoot, libFoo.Module()) {
- t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
- }
- if !hasDep(libRootLtoNever, libFoo.Module()) {
- t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
- }
- libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
- if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) {
- t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
- }
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
- if !hasDep(libFoo.Module(), libBaz.Module()) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
- }
- libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
- if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) {
- t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags)
- }
- }
- func TestLtoDisabledButEnabledForArch(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "libfoo",
- srcs: ["foo.c"],
- lto: {
- never: true,
- },
- target: {
- android_arm: {
- lto: {
- never: false,
- thin: true,
- },
- },
- },
- }`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
- libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
- android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it",
- libFooWithLto.Args["ldFlags"], "-flto=thin")
- android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
- libFooWithoutLto.Args["ldFlags"], "-flto=thin")
- }
- func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "runtime_libbar",
- srcs: ["bar.c"],
- }
- cc_library {
- name: "libfoo",
- srcs: ["foo.c"],
- runtime_libs: ["runtime_libbar"],
- lto: {
- thin: true,
- },
- }`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
- libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
- android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
- libFoo.Args["ldFlags"], "-flto=thin")
- android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
- libBar.Args["ldFlags"], "-flto=thin")
- }
|