1*333d2b36SAndroid Build Coastguard Worker// Copyright 2021 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage cc 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "strings" 19*333d2b36SAndroid Build Coastguard Worker "testing" 20*333d2b36SAndroid Build Coastguard Worker 21*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 24*333d2b36SAndroid Build Coastguard Worker) 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Workervar LTOPreparer = android.GroupFixturePreparers( 27*333d2b36SAndroid Build Coastguard Worker prepareForCcTest, 28*333d2b36SAndroid Build Coastguard Worker) 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Workerfunc hasDep(result *android.TestResult, m android.Module, wantDep android.Module) bool { 31*333d2b36SAndroid Build Coastguard Worker var found bool 32*333d2b36SAndroid Build Coastguard Worker result.VisitDirectDeps(m, func(dep blueprint.Module) { 33*333d2b36SAndroid Build Coastguard Worker if dep == wantDep { 34*333d2b36SAndroid Build Coastguard Worker found = true 35*333d2b36SAndroid Build Coastguard Worker } 36*333d2b36SAndroid Build Coastguard Worker }) 37*333d2b36SAndroid Build Coastguard Worker return found 38*333d2b36SAndroid Build Coastguard Worker} 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Workerfunc TestThinLtoDeps(t *testing.T) { 41*333d2b36SAndroid Build Coastguard Worker t.Parallel() 42*333d2b36SAndroid Build Coastguard Worker bp := ` 43*333d2b36SAndroid Build Coastguard Worker cc_library_shared { 44*333d2b36SAndroid Build Coastguard Worker name: "lto_enabled", 45*333d2b36SAndroid Build Coastguard Worker srcs: ["src.c"], 46*333d2b36SAndroid Build Coastguard Worker static_libs: ["foo", "lib_never_lto"], 47*333d2b36SAndroid Build Coastguard Worker shared_libs: ["bar"], 48*333d2b36SAndroid Build Coastguard Worker } 49*333d2b36SAndroid Build Coastguard Worker cc_library_static { 50*333d2b36SAndroid Build Coastguard Worker name: "foo", 51*333d2b36SAndroid Build Coastguard Worker static_libs: ["baz"], 52*333d2b36SAndroid Build Coastguard Worker } 53*333d2b36SAndroid Build Coastguard Worker cc_library_shared { 54*333d2b36SAndroid Build Coastguard Worker name: "bar", 55*333d2b36SAndroid Build Coastguard Worker static_libs: ["qux"], 56*333d2b36SAndroid Build Coastguard Worker } 57*333d2b36SAndroid Build Coastguard Worker cc_library_static { 58*333d2b36SAndroid Build Coastguard Worker name: "baz", 59*333d2b36SAndroid Build Coastguard Worker } 60*333d2b36SAndroid Build Coastguard Worker cc_library_static { 61*333d2b36SAndroid Build Coastguard Worker name: "qux", 62*333d2b36SAndroid Build Coastguard Worker } 63*333d2b36SAndroid Build Coastguard Worker cc_library_static { 64*333d2b36SAndroid Build Coastguard Worker name: "lib_never_lto", 65*333d2b36SAndroid Build Coastguard Worker lto: { 66*333d2b36SAndroid Build Coastguard Worker never: true, 67*333d2b36SAndroid Build Coastguard Worker }, 68*333d2b36SAndroid Build Coastguard Worker } 69*333d2b36SAndroid Build Coastguard Worker` 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker result := LTOPreparer.RunTestWithBp(t, bp) 72*333d2b36SAndroid Build Coastguard Worker 73*333d2b36SAndroid Build Coastguard Worker libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module() 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static").Module() 76*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libLto, libFoo) { 77*333d2b36SAndroid Build Coastguard Worker t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'") 78*333d2b36SAndroid Build Coastguard Worker } 79*333d2b36SAndroid Build Coastguard Worker 80*333d2b36SAndroid Build Coastguard Worker libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static").Module() 81*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libFoo, libBaz) { 82*333d2b36SAndroid Build Coastguard Worker t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'") 83*333d2b36SAndroid Build Coastguard Worker } 84*333d2b36SAndroid Build Coastguard Worker 85*333d2b36SAndroid Build Coastguard Worker libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static").Module() 86*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libLto, libNeverLto) { 87*333d2b36SAndroid Build Coastguard Worker t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'") 88*333d2b36SAndroid Build Coastguard Worker } 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Worker libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module() 91*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libLto, libBar) { 92*333d2b36SAndroid Build Coastguard Worker t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'") 93*333d2b36SAndroid Build Coastguard Worker } 94*333d2b36SAndroid Build Coastguard Worker 95*333d2b36SAndroid Build Coastguard Worker barVariants := result.ModuleVariantsForTests("bar") 96*333d2b36SAndroid Build Coastguard Worker for _, v := range barVariants { 97*333d2b36SAndroid Build Coastguard Worker if strings.Contains(v, "lto-none") { 98*333d2b36SAndroid Build Coastguard Worker t.Errorf("Expected variants for 'bar' to not contain 'lto-none', but found %q", v) 99*333d2b36SAndroid Build Coastguard Worker } 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker quxVariants := result.ModuleVariantsForTests("qux") 102*333d2b36SAndroid Build Coastguard Worker for _, v := range quxVariants { 103*333d2b36SAndroid Build Coastguard Worker if strings.Contains(v, "lto-none") { 104*333d2b36SAndroid Build Coastguard Worker t.Errorf("Expected variants for 'qux' to not contain 'lto-none', but found %q", v) 105*333d2b36SAndroid Build Coastguard Worker } 106*333d2b36SAndroid Build Coastguard Worker } 107*333d2b36SAndroid Build Coastguard Worker} 108*333d2b36SAndroid Build Coastguard Worker 109*333d2b36SAndroid Build Coastguard Workerfunc TestThinLtoOnlyOnStaticDep(t *testing.T) { 110*333d2b36SAndroid Build Coastguard Worker t.Parallel() 111*333d2b36SAndroid Build Coastguard Worker bp := ` 112*333d2b36SAndroid Build Coastguard Worker cc_library_shared { 113*333d2b36SAndroid Build Coastguard Worker name: "root", 114*333d2b36SAndroid Build Coastguard Worker srcs: ["src.c"], 115*333d2b36SAndroid Build Coastguard Worker static_libs: ["foo"], 116*333d2b36SAndroid Build Coastguard Worker } 117*333d2b36SAndroid Build Coastguard Worker cc_library_shared { 118*333d2b36SAndroid Build Coastguard Worker name: "root_no_lto", 119*333d2b36SAndroid Build Coastguard Worker srcs: ["src.c"], 120*333d2b36SAndroid Build Coastguard Worker static_libs: ["foo"], 121*333d2b36SAndroid Build Coastguard Worker lto: { 122*333d2b36SAndroid Build Coastguard Worker never: true, 123*333d2b36SAndroid Build Coastguard Worker } 124*333d2b36SAndroid Build Coastguard Worker } 125*333d2b36SAndroid Build Coastguard Worker cc_library_static { 126*333d2b36SAndroid Build Coastguard Worker name: "foo", 127*333d2b36SAndroid Build Coastguard Worker srcs: ["foo.c"], 128*333d2b36SAndroid Build Coastguard Worker static_libs: ["baz"], 129*333d2b36SAndroid Build Coastguard Worker lto: { 130*333d2b36SAndroid Build Coastguard Worker thin: true, 131*333d2b36SAndroid Build Coastguard Worker } 132*333d2b36SAndroid Build Coastguard Worker } 133*333d2b36SAndroid Build Coastguard Worker cc_library_static { 134*333d2b36SAndroid Build Coastguard Worker name: "baz", 135*333d2b36SAndroid Build Coastguard Worker srcs: ["baz.c"], 136*333d2b36SAndroid Build Coastguard Worker } 137*333d2b36SAndroid Build Coastguard Worker` 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Worker result := LTOPreparer.RunTestWithBp(t, bp) 140*333d2b36SAndroid Build Coastguard Worker 141*333d2b36SAndroid Build Coastguard Worker libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module() 142*333d2b36SAndroid Build Coastguard Worker libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module() 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Worker libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static") 145*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libRoot, libFoo.Module()) { 146*333d2b36SAndroid Build Coastguard Worker t.Errorf("'root' missing dependency on the default variant of 'foo'") 147*333d2b36SAndroid Build Coastguard Worker } 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Worker libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none") 150*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) { 151*333d2b36SAndroid Build Coastguard Worker t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'") 152*333d2b36SAndroid Build Coastguard Worker } 153*333d2b36SAndroid Build Coastguard Worker 154*333d2b36SAndroid Build Coastguard Worker libFooCFlags := libFoo.Rule("cc").Args["cFlags"] 155*333d2b36SAndroid Build Coastguard Worker if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libFooCFlags, w) { 156*333d2b36SAndroid Build Coastguard Worker t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags) 157*333d2b36SAndroid Build Coastguard Worker } 158*333d2b36SAndroid Build Coastguard Worker 159*333d2b36SAndroid Build Coastguard Worker libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static") 160*333d2b36SAndroid Build Coastguard Worker if !hasDep(result, libFoo.Module(), libBaz.Module()) { 161*333d2b36SAndroid Build Coastguard Worker t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'") 162*333d2b36SAndroid Build Coastguard Worker } 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Worker libBazCFlags := libFoo.Rule("cc").Args["cFlags"] 165*333d2b36SAndroid Build Coastguard Worker if w := "-flto=thin -fsplit-lto-unit"; !strings.Contains(libBazCFlags, w) { 166*333d2b36SAndroid Build Coastguard Worker t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags) 167*333d2b36SAndroid Build Coastguard Worker } 168*333d2b36SAndroid Build Coastguard Worker} 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Workerfunc TestLtoDisabledButEnabledForArch(t *testing.T) { 171*333d2b36SAndroid Build Coastguard Worker t.Parallel() 172*333d2b36SAndroid Build Coastguard Worker bp := ` 173*333d2b36SAndroid Build Coastguard Worker cc_library { 174*333d2b36SAndroid Build Coastguard Worker name: "libfoo", 175*333d2b36SAndroid Build Coastguard Worker srcs: ["foo.c"], 176*333d2b36SAndroid Build Coastguard Worker lto: { 177*333d2b36SAndroid Build Coastguard Worker never: true, 178*333d2b36SAndroid Build Coastguard Worker }, 179*333d2b36SAndroid Build Coastguard Worker target: { 180*333d2b36SAndroid Build Coastguard Worker android_arm: { 181*333d2b36SAndroid Build Coastguard Worker lto: { 182*333d2b36SAndroid Build Coastguard Worker never: false, 183*333d2b36SAndroid Build Coastguard Worker thin: true, 184*333d2b36SAndroid Build Coastguard Worker }, 185*333d2b36SAndroid Build Coastguard Worker }, 186*333d2b36SAndroid Build Coastguard Worker }, 187*333d2b36SAndroid Build Coastguard Worker }` 188*333d2b36SAndroid Build Coastguard Worker result := LTOPreparer.RunTestWithBp(t, bp) 189*333d2b36SAndroid Build Coastguard Worker 190*333d2b36SAndroid Build Coastguard Worker libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 191*333d2b36SAndroid Build Coastguard Worker libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld") 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Worker android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it", 194*333d2b36SAndroid Build Coastguard Worker libFooWithLto.Args["ldFlags"], "-flto=thin") 195*333d2b36SAndroid Build Coastguard Worker android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it", 196*333d2b36SAndroid Build Coastguard Worker libFooWithoutLto.Args["ldFlags"], "-flto=thin") 197*333d2b36SAndroid Build Coastguard Worker} 198*333d2b36SAndroid Build Coastguard Worker 199*333d2b36SAndroid Build Coastguard Workerfunc TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) { 200*333d2b36SAndroid Build Coastguard Worker t.Parallel() 201*333d2b36SAndroid Build Coastguard Worker bp := ` 202*333d2b36SAndroid Build Coastguard Worker cc_library { 203*333d2b36SAndroid Build Coastguard Worker name: "runtime_libbar", 204*333d2b36SAndroid Build Coastguard Worker srcs: ["bar.c"], 205*333d2b36SAndroid Build Coastguard Worker } 206*333d2b36SAndroid Build Coastguard Worker 207*333d2b36SAndroid Build Coastguard Worker cc_library { 208*333d2b36SAndroid Build Coastguard Worker name: "libfoo", 209*333d2b36SAndroid Build Coastguard Worker srcs: ["foo.c"], 210*333d2b36SAndroid Build Coastguard Worker runtime_libs: ["runtime_libbar"], 211*333d2b36SAndroid Build Coastguard Worker lto: { 212*333d2b36SAndroid Build Coastguard Worker thin: true, 213*333d2b36SAndroid Build Coastguard Worker }, 214*333d2b36SAndroid Build Coastguard Worker }` 215*333d2b36SAndroid Build Coastguard Worker 216*333d2b36SAndroid Build Coastguard Worker result := LTOPreparer.RunTestWithBp(t, bp) 217*333d2b36SAndroid Build Coastguard Worker 218*333d2b36SAndroid Build Coastguard Worker libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld") 219*333d2b36SAndroid Build Coastguard Worker libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld") 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library", 222*333d2b36SAndroid Build Coastguard Worker libFoo.Args["ldFlags"], "-flto=thin") 223*333d2b36SAndroid Build Coastguard Worker android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib", 224*333d2b36SAndroid Build Coastguard Worker libBar.Args["ldFlags"], "-flto=thin") 225*333d2b36SAndroid Build Coastguard Worker} 226