1# Copyright 2021 the V8 project authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5FlagInfo = provider(fields = ["value"]) 6 7def _options_impl(ctx): 8 return FlagInfo(value = ctx.build_setting_value) 9 10_create_option_flag = rule( 11 implementation = _options_impl, 12 build_setting = config.bool(flag = True), 13) 14 15_create_option_string = rule( 16 implementation = _options_impl, 17 build_setting = config.string(flag = True), 18) 19 20_create_option_int = rule( 21 implementation = _options_impl, 22 build_setting = config.int(flag = True), 23) 24 25def v8_flag(name, default = False): 26 _create_option_flag(name = name, build_setting_default = default) 27 native.config_setting(name = "is_" + name, flag_values = {name: "True"}) 28 native.config_setting(name = "is_not_" + name, flag_values = {name: "False"}) 29 30def v8_string(name, default = ""): 31 _create_option_string(name = name, build_setting_default = default) 32 33def v8_int(name, default = 0): 34 _create_option_int(name = name, build_setting_default = default) 35 36def _custom_config_impl(ctx): 37 defs = [] 38 defs.append("V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=" + 39 str(ctx.attr._v8_typed_array_max_size_in_heap[FlagInfo].value)) 40 context = cc_common.create_compilation_context(defines = depset(defs)) 41 return [CcInfo(compilation_context = context)] 42 43v8_custom_config = rule( 44 implementation = _custom_config_impl, 45 attrs = { 46 "_v8_typed_array_max_size_in_heap": attr.label(default = ":v8_typed_array_max_size_in_heap"), 47 }, 48) 49 50def _config_impl(ctx): 51 hdrs = [] 52 53 # Add headers 54 for h in ctx.attr.hdrs: 55 hdrs += h[DefaultInfo].files.to_list() 56 defs = [] 57 58 # Add conditional_defines 59 for f, d in ctx.attr.conditional_defines.items(): 60 if f[FlagInfo].value: 61 defs.append(d) 62 63 # Add defines 64 for d in ctx.attr.defines: 65 defs.append(d) 66 context = cc_common.create_compilation_context( 67 defines = depset( 68 defs, 69 transitive = [dep[CcInfo].compilation_context.defines for dep in ctx.attr.deps], 70 ), 71 headers = depset( 72 hdrs, 73 transitive = [dep[CcInfo].compilation_context.headers for dep in ctx.attr.deps], 74 ), 75 ) 76 return [CcInfo(compilation_context = context)] 77 78v8_config = rule( 79 implementation = _config_impl, 80 attrs = { 81 "conditional_defines": attr.label_keyed_string_dict(), 82 "defines": attr.string_list(), 83 "deps": attr.label_list(), 84 "hdrs": attr.label_list(allow_files = True), 85 }, 86) 87 88def _default_args(): 89 return struct( 90 deps = [":define_flags"], 91 defines = select({ 92 "@v8//bazel/config:is_windows": [ 93 "UNICODE", 94 "_UNICODE", 95 "_CRT_RAND_S", 96 "_WIN32_WINNT=0x0602", # Override bazel default to Windows 8 97 ], 98 "//conditions:default": [], 99 }), 100 copts = select({ 101 "@v8//bazel/config:is_posix": [ 102 "-fPIC", 103 "-fno-strict-aliasing", 104 "-Werror", 105 "-Wextra", 106 "-Wno-unknown-warning-option", 107 "-Wno-bitwise-instead-of-logical", 108 "-Wno-builtin-assume-aligned-alignment", 109 "-Wno-unused-parameter", 110 "-Wno-implicit-int-float-conversion", 111 "-Wno-deprecated-copy", 112 "-Wno-non-virtual-dtor", 113 "-isystem .", 114 ], 115 "//conditions:default": [], 116 }) + select({ 117 "@v8//bazel/config:is_clang": [ 118 "-Wno-invalid-offsetof", 119 "-std=c++17", 120 ], 121 "@v8//bazel/config:is_gcc": [ 122 "-Wno-extra", 123 "-Wno-array-bounds", 124 "-Wno-class-memaccess", 125 "-Wno-comments", 126 "-Wno-deprecated-declarations", 127 "-Wno-implicit-fallthrough", 128 "-Wno-int-in-bool-context", 129 "-Wno-maybe-uninitialized", 130 "-Wno-mismatched-new-delete", 131 "-Wno-redundant-move", 132 "-Wno-return-type", 133 "-Wno-stringop-overflow", 134 # Use GNU dialect, because GCC doesn't allow using 135 # ##__VA_ARGS__ when in standards-conforming mode. 136 "-std=gnu++17", 137 ], 138 "@v8//bazel/config:is_windows": [ 139 "/std:c++17", 140 ], 141 "//conditions:default": [], 142 }) + select({ 143 "@v8//bazel/config:is_gcc_fastbuild": [ 144 # Non-debug builds without optimizations fail because 145 # of recursive inlining of "always_inline" functions. 146 "-O1", 147 ], 148 "//conditions:default": [], 149 }) + select({ 150 "@v8//bazel/config:is_clang_s390x": [ 151 "-fno-integrated-as", 152 ], 153 "//conditions:default": [], 154 }), 155 includes = ["include"], 156 linkopts = select({ 157 "@v8//bazel/config:is_windows": [ 158 "Winmm.lib", 159 "DbgHelp.lib", 160 "Advapi32.lib", 161 ], 162 "@v8//bazel/config:is_macos": ["-pthread"], 163 "//conditions:default": ["-Wl,--no-as-needed -ldl -pthread"], 164 }) + select({ 165 ":should_add_rdynamic": ["-rdynamic"], 166 "//conditions:default": [], 167 }), 168 ) 169 170ENABLE_I18N_SUPPORT_DEFINES = [ 171 "-DV8_INTL_SUPPORT", 172 "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC", 173 # src/regexp/regexp-compiler-tonode.cc uses an unsafe ICU method and 174 # access a character implicitly. 175 "-DUNISTR_FROM_CHAR_EXPLICIT=", 176] 177 178def _should_emit_noicu_and_icu(noicu_srcs, noicu_deps, icu_srcs, icu_deps): 179 return noicu_srcs != [] or noicu_deps != [] or icu_srcs != [] or icu_deps != [] 180 181# buildifier: disable=function-docstring 182def v8_binary( 183 name, 184 srcs, 185 deps = [], 186 includes = [], 187 copts = [], 188 linkopts = [], 189 noicu_srcs = [], 190 noicu_deps = [], 191 icu_srcs = [], 192 icu_deps = [], 193 **kwargs): 194 default = _default_args() 195 if _should_emit_noicu_and_icu(noicu_srcs, noicu_deps, icu_srcs, icu_deps): 196 native.cc_binary( 197 name = "noicu/" + name, 198 srcs = srcs + noicu_srcs, 199 deps = deps + noicu_deps + default.deps, 200 includes = includes + default.includes, 201 copts = copts + default.copts, 202 linkopts = linkopts + default.linkopts, 203 **kwargs 204 ) 205 native.cc_binary( 206 name = "icu/" + name, 207 srcs = srcs + icu_srcs, 208 deps = deps + icu_deps + default.deps, 209 includes = includes + default.includes, 210 copts = copts + default.copts + ENABLE_I18N_SUPPORT_DEFINES, 211 linkopts = linkopts + default.linkopts, 212 **kwargs 213 ) 214 else: 215 native.cc_binary( 216 name = name, 217 srcs = srcs, 218 deps = deps + default.deps, 219 includes = includes + default.includes, 220 copts = copts + default.copts, 221 linkopts = linkopts + default.linkopts, 222 **kwargs 223 ) 224 225# buildifier: disable=function-docstring 226def v8_library( 227 name, 228 srcs, 229 deps = [], 230 includes = [], 231 copts = [], 232 linkopts = [], 233 noicu_srcs = [], 234 noicu_deps = [], 235 icu_srcs = [], 236 icu_deps = [], 237 **kwargs): 238 default = _default_args() 239 if _should_emit_noicu_and_icu(noicu_srcs, noicu_deps, icu_srcs, icu_deps): 240 native.cc_library( 241 name = name + "_noicu", 242 srcs = srcs + noicu_srcs, 243 deps = deps + noicu_deps + default.deps, 244 includes = includes + default.includes, 245 copts = copts + default.copts, 246 linkopts = linkopts + default.linkopts, 247 alwayslink = 1, 248 linkstatic = 1, 249 **kwargs 250 ) 251 252 # Alias target used because of cc_library bug in bazel on windows 253 # https://github.com/bazelbuild/bazel/issues/14237 254 # TODO(victorgomes): Remove alias once bug is fixed 255 native.alias( 256 name = "noicu/" + name, 257 actual = name + "_noicu", 258 ) 259 native.cc_library( 260 name = name + "_icu", 261 srcs = srcs + icu_srcs, 262 deps = deps + icu_deps + default.deps, 263 includes = includes + default.includes, 264 copts = copts + default.copts + ENABLE_I18N_SUPPORT_DEFINES, 265 linkopts = linkopts + default.linkopts, 266 alwayslink = 1, 267 linkstatic = 1, 268 **kwargs 269 ) 270 271 # Alias target used because of cc_library bug in bazel on windows 272 # https://github.com/bazelbuild/bazel/issues/14237 273 # TODO(victorgomes): Remove alias once bug is fixed 274 native.alias( 275 name = "icu/" + name, 276 actual = name + "_icu", 277 ) 278 else: 279 native.cc_library( 280 name = name, 281 srcs = srcs, 282 deps = deps + default.deps, 283 includes = includes + default.includes, 284 copts = copts + default.copts, 285 linkopts = linkopts + default.linkopts, 286 alwayslink = 1, 287 linkstatic = 1, 288 **kwargs 289 ) 290 291def _torque_impl(ctx): 292 if ctx.workspace_name == "v8": 293 v8root = "." 294 else: 295 v8root = "external/v8" 296 297 # Arguments 298 args = [] 299 args += ctx.attr.args 300 args.append("-o") 301 args.append(ctx.bin_dir.path + "/" + v8root + "/" + ctx.attr.prefix + "/torque-generated") 302 args.append("-strip-v8-root") 303 args.append("-v8-root") 304 args.append(v8root) 305 306 # Sources 307 args += [f.path for f in ctx.files.srcs] 308 309 # Generate/declare output files 310 outs = [] 311 for src in ctx.files.srcs: 312 root, period, ext = src.path.rpartition(".") 313 314 # Strip v8root 315 if root[:len(v8root)] == v8root: 316 root = root[len(v8root):] 317 file = ctx.attr.prefix + "/torque-generated/" + root 318 outs.append(ctx.actions.declare_file(file + "-tq-csa.cc")) 319 outs.append(ctx.actions.declare_file(file + "-tq-csa.h")) 320 outs.append(ctx.actions.declare_file(file + "-tq-inl.inc")) 321 outs.append(ctx.actions.declare_file(file + "-tq.inc")) 322 outs.append(ctx.actions.declare_file(file + "-tq.cc")) 323 outs += [ctx.actions.declare_file(ctx.attr.prefix + "/torque-generated/" + f) for f in ctx.attr.extras] 324 ctx.actions.run( 325 outputs = outs, 326 inputs = ctx.files.srcs, 327 arguments = args, 328 executable = ctx.executable.tool, 329 mnemonic = "GenTorque", 330 progress_message = "Generating Torque files", 331 ) 332 return [DefaultInfo(files = depset(outs))] 333 334_v8_torque = rule( 335 implementation = _torque_impl, 336 # cfg = v8_target_cpu_transition, 337 attrs = { 338 "prefix": attr.string(mandatory = True), 339 "srcs": attr.label_list(allow_files = True, mandatory = True), 340 "extras": attr.string_list(), 341 "tool": attr.label( 342 allow_files = True, 343 executable = True, 344 cfg = "exec", 345 ), 346 "args": attr.string_list(), 347 }, 348) 349 350def v8_torque(name, noicu_srcs, icu_srcs, args, extras): 351 _v8_torque( 352 name = "noicu/" + name, 353 prefix = "noicu", 354 srcs = noicu_srcs, 355 args = args, 356 extras = extras, 357 tool = select({ 358 "@v8//bazel/config:v8_target_is_32_bits": ":torque_non_pointer_compression", 359 "//conditions:default": ":torque", 360 }), 361 ) 362 _v8_torque( 363 name = "icu/" + name, 364 prefix = "icu", 365 srcs = icu_srcs, 366 args = args, 367 extras = extras, 368 tool = select({ 369 "@v8//bazel/config:v8_target_is_32_bits": ":torque_non_pointer_compression", 370 "//conditions:default": ":torque", 371 }), 372 ) 373 374def _v8_target_cpu_transition_impl(settings, attr): 375 # Check for an existing v8_target_cpu flag. 376 if "@v8//bazel/config:v8_target_cpu" in settings: 377 if settings["@v8//bazel/config:v8_target_cpu"] != "none": 378 return 379 380 # Auto-detect target architecture based on the --cpu flag. 381 mapping = { 382 "haswell": "x64", 383 "k8": "x64", 384 "x86_64": "x64", 385 "darwin": "x64", 386 "darwin_x86_64": "x64", 387 "x64_windows": "x64", 388 "x86": "ia32", 389 "aarch64": "arm64", 390 "arm64-v8a": "arm64", 391 "arm": "arm64", 392 "darwin_arm64": "arm64", 393 "armeabi-v7a": "arm32", 394 "s390x": "s390x", 395 "riscv64": "riscv64", 396 "ppc": "ppc64le", 397 } 398 v8_target_cpu = mapping[settings["//command_line_option:cpu"]] 399 return {"@v8//bazel/config:v8_target_cpu": v8_target_cpu} 400 401# Set the v8_target_cpu to be the correct architecture given the cpu specified 402# on the command line. 403v8_target_cpu_transition = transition( 404 implementation = _v8_target_cpu_transition_impl, 405 inputs = ["@v8//bazel/config:v8_target_cpu", "//command_line_option:cpu"], 406 outputs = ["@v8//bazel/config:v8_target_cpu"], 407) 408 409def _mksnapshot(ctx): 410 outs = [ 411 ctx.actions.declare_file(ctx.attr.prefix + "/snapshot.cc"), 412 ctx.actions.declare_file(ctx.attr.prefix + "/embedded.S"), 413 ] 414 ctx.actions.run( 415 outputs = outs, 416 inputs = [], 417 arguments = [ 418 "--embedded_variant=Default", 419 "--startup_src", 420 outs[0].path, 421 "--embedded_src", 422 outs[1].path, 423 ] + ctx.attr.args, 424 executable = ctx.executable.tool, 425 progress_message = "Running mksnapshot", 426 ) 427 return [DefaultInfo(files = depset(outs))] 428 429_v8_mksnapshot = rule( 430 implementation = _mksnapshot, 431 attrs = { 432 "args": attr.string_list(), 433 "tool": attr.label( 434 mandatory = True, 435 allow_files = True, 436 executable = True, 437 cfg = "exec", 438 ), 439 "_allowlist_function_transition": attr.label( 440 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 441 ), 442 "prefix": attr.string(mandatory = True), 443 }, 444 cfg = v8_target_cpu_transition, 445) 446 447def v8_mksnapshot(name, args): 448 _v8_mksnapshot( 449 name = "noicu/" + name, 450 args = args, 451 prefix = "noicu", 452 tool = ":noicu/mksnapshot", 453 ) 454 _v8_mksnapshot( 455 name = "icu/" + name, 456 args = args, 457 prefix = "icu", 458 tool = ":icu/mksnapshot", 459 ) 460 461def _quote(val): 462 if val[0] == '"' and val[-1] == '"': 463 fail("String", val, "already quoted") 464 return '"' + val + '"' 465 466def _kv_bool_pair(k, v): 467 return _quote(k) + ": " + v 468 469def _json(kv_pairs): 470 content = "{" 471 for (k, v) in kv_pairs[:-1]: 472 content += _kv_bool_pair(k, v) + ", " 473 (k, v) = kv_pairs[-1] 474 content += _kv_bool_pair(k, v) 475 content += "}\n" 476 return content 477 478def build_config_content(cpu, icu): 479 return _json([ 480 ("current_cpu", cpu), 481 ("dcheck_always_on", "false"), 482 ("is_android", "false"), 483 ("is_asan", "false"), 484 ("is_cfi", "false"), 485 ("is_clang", "true"), 486 ("is_component_build", "false"), 487 ("is_debug", "false"), 488 ("is_full_debug", "false"), 489 ("is_gcov_coverage", "false"), 490 ("is_msan", "false"), 491 ("is_tsan", "false"), 492 ("is_ubsan_vptr", "false"), 493 ("target_cpu", cpu), 494 ("v8_current_cpu", cpu), 495 ("v8_dict_property_const_tracking", "false"), 496 ("v8_enable_atomic_marking_state", "false"), 497 ("v8_enable_atomic_object_field_writes", "false"), 498 ("v8_enable_concurrent_marking", "false"), 499 ("v8_enable_i18n_support", icu), 500 ("v8_enable_verify_predictable", "false"), 501 ("v8_enable_verify_csa", "false"), 502 ("v8_enable_lite_mode", "false"), 503 ("v8_enable_runtime_call_stats", "false"), 504 ("v8_enable_pointer_compression", "true"), 505 ("v8_enable_pointer_compression_shared_cage", "false"), 506 ("v8_enable_third_party_heap", "false"), 507 ("v8_enable_webassembly", "false"), 508 ("v8_control_flow_integrity", "false"), 509 ("v8_enable_single_generation", "false"), 510 ("v8_enable_sandbox", "false"), 511 ("v8_enable_shared_ro_heap", "false"), 512 ("v8_target_cpu", cpu), 513 ]) 514 515# TODO(victorgomes): Create a rule (instead of a macro), that can 516# dynamically populate the build config. 517def v8_build_config(name): 518 cpu = _quote("x64") 519 native.genrule( 520 name = "noicu/" + name, 521 outs = ["noicu/" + name + ".json"], 522 cmd = "echo '" + build_config_content(cpu, "false") + "' > \"$@\"", 523 ) 524 native.genrule( 525 name = "icu/" + name, 526 outs = ["icu/" + name + ".json"], 527 cmd = "echo '" + build_config_content(cpu, "true") + "' > \"$@\"", 528 ) 529