• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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