1// Copyright 2018 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 "slices" 20 "testing" 21 22 "android/soong/android" 23) 24 25func testGenruleContext(config android.Config) *android.TestContext { 26 ctx := android.NewTestArchContext(config) 27 ctx.RegisterModuleType("cc_genrule", GenRuleFactory) 28 ctx.Register() 29 30 return ctx 31} 32 33func TestArchGenruleCmd(t *testing.T) { 34 fs := map[string][]byte{ 35 "tool": nil, 36 "foo": nil, 37 "bar": nil, 38 } 39 bp := ` 40 cc_genrule { 41 name: "gen", 42 tool_files: ["tool"], 43 cmd: "$(location tool) $(in) $(out)", 44 out: ["out_arm"], 45 arch: { 46 arm: { 47 srcs: ["foo"], 48 }, 49 arm64: { 50 srcs: ["bar"], 51 }, 52 }, 53 } 54 ` 55 config := android.TestArchConfig(t.TempDir(), nil, bp, fs) 56 57 ctx := testGenruleContext(config) 58 59 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 60 if errs == nil { 61 _, errs = ctx.PrepareBuildActions(config) 62 } 63 if errs != nil { 64 t.Fatal(errs) 65 } 66 67 gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out_arm") 68 expected := []string{"foo"} 69 if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) { 70 t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings()) 71 } 72 73 gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm") 74 expected = []string{"bar"} 75 if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) { 76 t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Implicits.Strings()) 77 } 78} 79 80func TestLibraryGenruleCmd(t *testing.T) { 81 bp := ` 82 cc_library { 83 name: "libboth", 84 } 85 86 cc_library_shared { 87 name: "libshared", 88 } 89 90 cc_library_static { 91 name: "libstatic", 92 } 93 94 cc_genrule { 95 name: "gen", 96 tool_files: ["tool"], 97 srcs: [ 98 ":libboth", 99 ":libshared", 100 ":libstatic", 101 ], 102 cmd: "$(location tool) $(in) $(out)", 103 out: ["out"], 104 } 105 ` 106 ctx := testCc(t, bp) 107 108 gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out") 109 expected := []string{"libboth.so", "libshared.so", "libstatic.a"} 110 var got []string 111 for _, input := range gen.Implicits { 112 got = append(got, input.Base()) 113 } 114 if !reflect.DeepEqual(expected, got[:len(expected)]) { 115 t.Errorf(`want inputs %v, got %v`, expected, got) 116 } 117} 118 119func TestCmdPrefix(t *testing.T) { 120 bp := ` 121 cc_genrule { 122 name: "gen", 123 cmd: "echo foo", 124 out: ["out"], 125 native_bridge_supported: true, 126 } 127 ` 128 129 testCases := []struct { 130 name string 131 variant string 132 preparer android.FixturePreparer 133 134 arch string 135 nativeBridge string 136 multilib string 137 }{ 138 { 139 name: "arm", 140 variant: "android_arm_armv7-a-neon", 141 arch: "arm", 142 multilib: "lib32", 143 }, 144 { 145 name: "arm64", 146 variant: "android_arm64_armv8-a", 147 arch: "arm64", 148 multilib: "lib64", 149 }, 150 { 151 name: "nativebridge", 152 variant: "android_native_bridge_arm_armv7-a-neon", 153 preparer: android.FixtureModifyConfig(func(config android.Config) { 154 config.Targets[android.Android] = []android.Target{ 155 { 156 Os: android.Android, 157 Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, 158 NativeBridge: android.NativeBridgeDisabled, 159 }, 160 { 161 Os: android.Android, 162 Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, 163 NativeBridge: android.NativeBridgeEnabled, 164 NativeBridgeHostArchName: "x86", 165 NativeBridgeRelativePath: "arm", 166 }, 167 } 168 }), 169 arch: "arm", 170 multilib: "lib32", 171 nativeBridge: "arm", 172 }, 173 } 174 175 for _, tt := range testCases { 176 t.Run(tt.name, func(t *testing.T) { 177 result := android.GroupFixturePreparers( 178 PrepareForIntegrationTestWithCc, 179 android.OptionalFixturePreparer(tt.preparer), 180 ).RunTestWithBp(t, bp) 181 gen := result.ModuleForTests("gen", tt.variant) 182 sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto")) 183 cmd := *sboxProto.Commands[0].Command 184 android.AssertStringDoesContain(t, "incorrect CC_ARCH", cmd, "CC_ARCH="+tt.arch+" ") 185 android.AssertStringDoesContain(t, "incorrect CC_NATIVE_BRIDGE", cmd, "CC_NATIVE_BRIDGE="+tt.nativeBridge+" ") 186 android.AssertStringDoesContain(t, "incorrect CC_MULTILIB", cmd, "CC_MULTILIB="+tt.multilib+" ") 187 }) 188 } 189} 190 191func TestVendorProductVariantGenrule(t *testing.T) { 192 bp := ` 193 cc_genrule { 194 name: "gen", 195 tool_files: ["tool"], 196 cmd: "$(location tool) $(in) $(out)", 197 out: ["out"], 198 vendor_available: true, 199 product_available: true, 200 } 201 ` 202 t.Helper() 203 ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp) 204 205 variants := ctx.ModuleVariantsForTests("gen") 206 if !slices.Contains(variants, "android_vendor_arm64_armv8-a") { 207 t.Errorf(`expected vendor variant, but does not exist in %v`, variants) 208 } 209 if !slices.Contains(variants, "android_product_arm64_armv8-a") { 210 t.Errorf(`expected product variant, but does not exist in %v`, variants) 211 } 212} 213 214// cc_genrule is initialized to android.InitAndroidArchModule 215// that is an architecture-specific Android module. 216// So testing properties tagged with `android:"arch_variant"` 217// for cc_genrule. 218func TestMultilibGenruleOut(t *testing.T) { 219 bp := ` 220 cc_genrule { 221 name: "gen", 222 cmd: "cp $(in) $(out)", 223 srcs: ["foo"], 224 multilib: { 225 lib32: { 226 out: [ 227 "subdir32/external-module32", 228 ], 229 }, 230 lib64: { 231 out: [ 232 "subdir64/external-module64", 233 ], 234 }, 235 }, 236 } 237 ` 238 result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp) 239 gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(result.TestContext, t, "") 240 android.AssertPathsEndWith(t, 241 "genrule_out", 242 []string{ 243 "subdir32/external-module32", 244 }, 245 gen_32bit, 246 ) 247 248 gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(result.TestContext, t, "") 249 android.AssertPathsEndWith(t, 250 "genrule_out", 251 []string{ 252 "subdir64/external-module64", 253 }, 254 gen_64bit, 255 ) 256} 257