1# Copyright (C) 2022 The Android Open Source Project 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 15load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 16load(":cc_binary.bzl", "cc_binary") 17load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test") 18load(":cc_library_shared.bzl", "cc_library_shared") 19load(":cc_library_static.bzl", "cc_library_static") 20 21def strip_test_assert_flags(env, strip_action, strip_flags): 22 # Extract these flags from strip_action (for example): 23 # build/soong/scripts/strip.sh --keep-symbols --add-gnu-debuglink -i <in> -o <out> -d <out>.d 24 # ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ 25 flag_start_idx = 1 # starts after the strip.sh executable 26 flag_end_idx = strip_action.argv.index("-i") # end of the flags 27 asserts.equals( 28 env, 29 strip_action.argv[flag_start_idx:flag_end_idx], 30 strip_flags, 31 ) 32 33def _cc_binary_strip_test(ctx): 34 env = analysistest.begin(ctx) 35 actions = analysistest.target_actions(env) 36 filtered_actions = [a for a in actions if a.mnemonic == "CcStrip"] 37 on_target = ctx.target_platform_has_constraint( 38 ctx.attr._android_constraint[platform_common.ConstraintValueInfo], 39 ) 40 if ctx.attr.strip_flags or on_target: 41 # expected to find strip flags, so look for a CcStrip action. 42 asserts.true( 43 env, 44 len(filtered_actions) == 1, 45 "expected to find an action with CcStrip mnemonic in %s" % actions, 46 ) 47 if ctx.attr.strip_flags or not on_target: 48 strip_test_assert_flags(env, filtered_actions[0], ctx.attr.strip_flags) 49 return analysistest.end(env) 50 else: 51 asserts.true( 52 env, 53 len(filtered_actions) == 0, 54 "expected to not find an action with CcStrip mnemonic in %s" % actions, 55 ) 56 return analysistest.end(env) 57 58cc_binary_strip_test = analysistest.make( 59 _cc_binary_strip_test, 60 attrs = { 61 "strip_flags": attr.string_list(), 62 "_android_constraint": attr.label(default = Label("//build/bazel/platforms/os:android")), 63 }, 64) 65 66def _cc_binary_strip_default(): 67 name = "cc_binary_strip_default" 68 test_name = name + "_test" 69 70 cc_binary( 71 name = name, 72 srcs = ["main.cc"], 73 tags = ["manual"], 74 ) 75 76 cc_binary_strip_test( 77 name = test_name, 78 target_under_test = name, 79 strip_flags = [], 80 ) 81 82 return test_name 83 84def _cc_binary_strip_keep_symbols(): 85 name = "cc_binary_strip_keep_symbols" 86 test_name = name + "_test" 87 88 cc_binary( 89 name = name, 90 srcs = ["main.cc"], 91 tags = ["manual"], 92 strip = {"keep_symbols": True}, 93 ) 94 95 cc_binary_strip_test( 96 name = test_name, 97 target_under_test = name, 98 strip_flags = [ 99 "--keep-symbols", 100 "--add-gnu-debuglink", 101 ], 102 ) 103 104 return test_name 105 106def _cc_binary_strip_keep_symbols_and_debug_frame(): 107 name = "cc_binary_strip_keep_symbols_and_debug_frame" 108 test_name = name + "_test" 109 110 cc_binary( 111 name = name, 112 srcs = ["main.cc"], 113 tags = ["manual"], 114 strip = {"keep_symbols_and_debug_frame": True}, 115 ) 116 117 cc_binary_strip_test( 118 name = test_name, 119 target_under_test = name, 120 strip_flags = [ 121 "--keep-symbols-and-debug-frame", 122 "--add-gnu-debuglink", 123 ], 124 ) 125 126 return test_name 127 128def _cc_binary_strip_keep_symbols_list(): 129 name = "cc_binary_strip_keep_symbols_list" 130 test_name = name + "_test" 131 132 cc_binary( 133 name = name, 134 srcs = ["main.cc"], 135 tags = ["manual"], 136 strip = {"keep_symbols_list": ["foo", "bar"]}, 137 ) 138 139 cc_binary_strip_test( 140 name = test_name, 141 target_under_test = name, 142 strip_flags = [ 143 "-kfoo,bar", 144 "--add-gnu-debuglink", 145 ], 146 ) 147 148 return test_name 149 150def _cc_binary_strip_all(): 151 name = "cc_binary_strip_all" 152 test_name = name + "_test" 153 154 cc_binary( 155 name = name, 156 srcs = ["main.cc"], 157 tags = ["manual"], 158 strip = {"all": True}, 159 ) 160 161 cc_binary_strip_test( 162 name = test_name, 163 target_under_test = name, 164 strip_flags = [ 165 "--add-gnu-debuglink", 166 ], 167 ) 168 169 return test_name 170 171def _cc_binary_suffix_test_impl(ctx): 172 env = analysistest.begin(ctx) 173 target = analysistest.target_under_test(env) 174 info = target[DefaultInfo] 175 suffix = ctx.attr.suffix 176 177 outputs = info.files.to_list() 178 asserts.true( 179 env, 180 len(outputs) == 1, 181 "Expected 1 output file; got %s" % outputs, 182 ) 183 out = outputs[0].path 184 asserts.true( 185 env, 186 out.endswith(suffix), 187 "Expected output filename to end in `%s`; it was instead %s" % (suffix, out), 188 ) 189 190 return analysistest.end(env) 191 192cc_binary_suffix_test = analysistest.make( 193 _cc_binary_suffix_test_impl, 194 attrs = {"suffix": attr.string()}, 195) 196 197def _cc_binary_suffix(): 198 name = "cc_binary_suffix" 199 test_name = name + "_test" 200 suffix = "-suf" 201 202 cc_binary( 203 name, 204 srcs = ["src.cc"], 205 tags = ["manual"], 206 suffix = suffix, 207 ) 208 cc_binary_suffix_test( 209 name = test_name, 210 target_under_test = name, 211 suffix = suffix, 212 ) 213 return test_name 214 215def _cc_binary_empty_suffix(): 216 name = "cc_binary_empty_suffix" 217 test_name = name + "_test" 218 219 cc_binary( 220 name, 221 srcs = ["src.cc"], 222 tags = ["manual"], 223 ) 224 cc_binary_suffix_test( 225 name = test_name, 226 target_under_test = name, 227 ) 228 return test_name 229 230def _cc_binary_provides_androidmk_info(): 231 name = "cc_binary_provides_androidmk_info" 232 dep_name = name + "_static_dep" 233 whole_archive_dep_name = name + "_whole_archive_dep" 234 dynamic_dep_name = name + "_dynamic_dep" 235 test_name = name + "_test" 236 237 cc_library_static( 238 name = dep_name, 239 srcs = ["foo.c"], 240 tags = ["manual"], 241 ) 242 cc_library_static( 243 name = whole_archive_dep_name, 244 srcs = ["foo.c"], 245 tags = ["manual"], 246 ) 247 cc_library_shared( 248 name = dynamic_dep_name, 249 srcs = ["foo.c"], 250 tags = ["manual"], 251 ) 252 cc_binary( 253 name = name, 254 srcs = ["foo.cc"], 255 deps = [dep_name], 256 whole_archive_deps = [whole_archive_dep_name], 257 dynamic_deps = [dynamic_dep_name], 258 tags = ["manual"], 259 ) 260 android_test_name = test_name + "_android" 261 linux_test_name = test_name + "_linux" 262 target_provides_androidmk_info_test( 263 name = android_test_name, 264 target_under_test = name, 265 expected_static_libs = [dep_name, "libc++demangle", "libunwind"], 266 expected_whole_static_libs = [whole_archive_dep_name], 267 expected_shared_libs = [dynamic_dep_name, "libc++", "libc", "libdl", "libm"], 268 target_compatible_with = ["//build/bazel/platforms/os:android"], 269 ) 270 target_provides_androidmk_info_test( 271 name = linux_test_name, 272 target_under_test = name, 273 expected_static_libs = [dep_name], 274 expected_whole_static_libs = [whole_archive_dep_name], 275 expected_shared_libs = [dynamic_dep_name, "libc++"], 276 target_compatible_with = ["//build/bazel/platforms/os:linux"], 277 ) 278 return [ 279 android_test_name, 280 linux_test_name, 281 ] 282 283def cc_binary_test_suite(name): 284 native.test_suite( 285 name = name, 286 tests = [ 287 _cc_binary_strip_default(), 288 _cc_binary_strip_keep_symbols(), 289 _cc_binary_strip_keep_symbols_and_debug_frame(), 290 _cc_binary_strip_keep_symbols_list(), 291 _cc_binary_strip_all(), 292 _cc_binary_suffix(), 293 _cc_binary_empty_suffix(), 294 ] + _cc_binary_provides_androidmk_info(), 295 ) 296