Mercurial
comparison third_party/emsdk/bazel/emscripten_toolchain/wasm_cc_binary.bzl @ 186:8cf4ec5e2191 hg-web
Fixed merge conflict.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 22:38:59 -0800 |
| parents | 8d17f6e6e290 |
| children |
comparison
equal
deleted
inserted
replaced
| 176:fed99fc04e12 | 186:8cf4ec5e2191 |
|---|---|
| 1 """wasm_cc_binary rule for compiling C++ targets to WebAssembly. | |
| 2 """ | |
| 3 | |
| 4 def _wasm_transition_impl(settings, attr): | |
| 5 _ignore = (settings, attr) | |
| 6 | |
| 7 features = list(settings["//command_line_option:features"]) | |
| 8 linkopts = list(settings["//command_line_option:linkopt"]) | |
| 9 | |
| 10 if attr.threads == "emscripten": | |
| 11 # threads enabled | |
| 12 features.append("use_pthreads") | |
| 13 elif attr.threads == "off": | |
| 14 # threads disabled | |
| 15 features.append("-use_pthreads") | |
| 16 | |
| 17 if attr.exit_runtime == True: | |
| 18 features.append("exit_runtime") | |
| 19 | |
| 20 if attr.backend == "llvm": | |
| 21 features.append("llvm_backend") | |
| 22 elif attr.backend == "emscripten": | |
| 23 features.append("-llvm_backend") | |
| 24 | |
| 25 if attr.simd: | |
| 26 features.append("wasm_simd") | |
| 27 | |
| 28 platform = "@emsdk//:platform_wasm" | |
| 29 if attr.standalone: | |
| 30 platform = "@emsdk//:platform_wasi" | |
| 31 features.append("wasm_standalone") | |
| 32 | |
| 33 return { | |
| 34 "//command_line_option:compiler": "emscripten", | |
| 35 "//command_line_option:cpu": "wasm", | |
| 36 "//command_line_option:features": features, | |
| 37 "//command_line_option:dynamic_mode": "off", | |
| 38 "//command_line_option:linkopt": linkopts, | |
| 39 "//command_line_option:platforms": [platform], | |
| 40 # This is hardcoded to an empty cc_library because the malloc library | |
| 41 # is implicitly added by the emscripten toolchain | |
| 42 "//command_line_option:custom_malloc": "@emsdk//emscripten_toolchain:malloc", | |
| 43 } | |
| 44 | |
| 45 _wasm_transition = transition( | |
| 46 implementation = _wasm_transition_impl, | |
| 47 inputs = [ | |
| 48 "//command_line_option:features", | |
| 49 "//command_line_option:linkopt", | |
| 50 ], | |
| 51 outputs = [ | |
| 52 "//command_line_option:compiler", | |
| 53 "//command_line_option:cpu", | |
| 54 "//command_line_option:features", | |
| 55 "//command_line_option:dynamic_mode", | |
| 56 "//command_line_option:linkopt", | |
| 57 "//command_line_option:platforms", | |
| 58 "//command_line_option:custom_malloc", | |
| 59 ], | |
| 60 ) | |
| 61 | |
| 62 _ALLOW_OUTPUT_EXTNAMES = [ | |
| 63 ".js", | |
| 64 ".wasm", | |
| 65 ".wasm.map", | |
| 66 ".data", | |
| 67 ".js.symbols", | |
| 68 ".wasm.debug.wasm", | |
| 69 ".html", | |
| 70 ] | |
| 71 | |
| 72 _WASM_BINARY_COMMON_ATTRS = { | |
| 73 "backend": attr.string( | |
| 74 default = "_default", | |
| 75 values = ["_default", "emscripten", "llvm"], | |
| 76 ), | |
| 77 "cc_target": attr.label( | |
| 78 cfg = _wasm_transition, | |
| 79 mandatory = True, | |
| 80 ), | |
| 81 "exit_runtime": attr.bool( | |
| 82 default = False, | |
| 83 ), | |
| 84 "threads": attr.string( | |
| 85 default = "_default", | |
| 86 values = ["_default", "emscripten", "off"], | |
| 87 ), | |
| 88 "simd": attr.bool( | |
| 89 default = False, | |
| 90 ), | |
| 91 "standalone": attr.bool( | |
| 92 default = False, | |
| 93 ), | |
| 94 "_allowlist_function_transition": attr.label( | |
| 95 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", | |
| 96 ), | |
| 97 "_wasm_binary_extractor": attr.label( | |
| 98 executable = True, | |
| 99 allow_files = True, | |
| 100 cfg = "exec", | |
| 101 default = Label("@emsdk//emscripten_toolchain:wasm_binary"), | |
| 102 ), | |
| 103 } | |
| 104 | |
| 105 def _wasm_cc_binary_impl(ctx): | |
| 106 args = ctx.actions.args() | |
| 107 cc_target = ctx.attr.cc_target[0] | |
| 108 | |
| 109 for output in ctx.outputs.outputs: | |
| 110 valid_extname = False | |
| 111 for allowed_extname in _ALLOW_OUTPUT_EXTNAMES: | |
| 112 if output.path.endswith(allowed_extname): | |
| 113 valid_extname = True | |
| 114 break | |
| 115 if not valid_extname: | |
| 116 fail("Invalid output '{}'. Allowed extnames: {}".format(output.basename, ", ".join(_ALLOW_OUTPUT_EXTNAMES))) | |
| 117 | |
| 118 args.add_all("--archive", ctx.files.cc_target) | |
| 119 args.add_joined("--outputs", ctx.outputs.outputs, join_with = ",") | |
| 120 | |
| 121 ctx.actions.run( | |
| 122 inputs = ctx.files.cc_target, | |
| 123 outputs = ctx.outputs.outputs, | |
| 124 arguments = [args], | |
| 125 executable = ctx.executable._wasm_binary_extractor, | |
| 126 ) | |
| 127 | |
| 128 return [ | |
| 129 DefaultInfo( | |
| 130 files = depset(ctx.outputs.outputs), | |
| 131 # This is needed since rules like web_test usually have a data | |
| 132 # dependency on this target. | |
| 133 data_runfiles = ctx.runfiles(transitive_files = depset(ctx.outputs.outputs)), | |
| 134 ), | |
| 135 OutputGroupInfo(_wasm_tar = cc_target.files), | |
| 136 ] | |
| 137 | |
| 138 def _wasm_cc_binary_legacy_impl(ctx): | |
| 139 cc_target = ctx.attr.cc_target[0] | |
| 140 outputs = [ | |
| 141 ctx.outputs.loader, | |
| 142 ctx.outputs.wasm, | |
| 143 ctx.outputs.map, | |
| 144 ctx.outputs.data, | |
| 145 ctx.outputs.symbols, | |
| 146 ctx.outputs.dwarf, | |
| 147 ctx.outputs.html, | |
| 148 ] | |
| 149 | |
| 150 args = ctx.actions.args() | |
| 151 args.add("--allow_empty_outputs") | |
| 152 args.add_all("--archive", ctx.files.cc_target) | |
| 153 args.add_joined("--outputs", outputs, join_with = ",") | |
| 154 | |
| 155 ctx.actions.run( | |
| 156 inputs = ctx.files.cc_target, | |
| 157 outputs = outputs, | |
| 158 arguments = [args], | |
| 159 executable = ctx.executable._wasm_binary_extractor, | |
| 160 ) | |
| 161 | |
| 162 return [ | |
| 163 DefaultInfo( | |
| 164 executable = ctx.outputs.wasm, | |
| 165 files = depset(outputs), | |
| 166 # This is needed since rules like web_test usually have a data | |
| 167 # dependency on this target. | |
| 168 data_runfiles = ctx.runfiles(transitive_files = depset(outputs)), | |
| 169 ), | |
| 170 OutputGroupInfo(_wasm_tar = cc_target.files), | |
| 171 ] | |
| 172 | |
| 173 _wasm_cc_binary = rule( | |
| 174 implementation = _wasm_cc_binary_impl, | |
| 175 attrs = dict( | |
| 176 _WASM_BINARY_COMMON_ATTRS, | |
| 177 outputs = attr.output_list( | |
| 178 allow_empty = False, | |
| 179 mandatory = True, | |
| 180 ), | |
| 181 ), | |
| 182 ) | |
| 183 | |
| 184 def _wasm_binary_legacy_outputs(name, cc_target): | |
| 185 basename = cc_target.name | |
| 186 basename = basename.split(".")[0] | |
| 187 outputs = { | |
| 188 "loader": "{}/{}.js".format(name, basename), | |
| 189 "wasm": "{}/{}.wasm".format(name, basename), | |
| 190 "map": "{}/{}.wasm.map".format(name, basename), | |
| 191 "data": "{}/{}.data".format(name, basename), | |
| 192 "symbols": "{}/{}.js.symbols".format(name, basename), | |
| 193 "dwarf": "{}/{}.wasm.debug.wasm".format(name, basename), | |
| 194 "html": "{}/{}.html".format(name, basename), | |
| 195 } | |
| 196 | |
| 197 return outputs | |
| 198 | |
| 199 _wasm_cc_binary_legacy = rule( | |
| 200 implementation = _wasm_cc_binary_legacy_impl, | |
| 201 attrs = _WASM_BINARY_COMMON_ATTRS, | |
| 202 outputs = _wasm_binary_legacy_outputs, | |
| 203 ) | |
| 204 | |
| 205 # Wraps a C++ Blaze target, extracting the appropriate files. | |
| 206 # | |
| 207 # This rule will transition to the emscripten toolchain in order | |
| 208 # to build the the cc_target as a WebAssembly binary. | |
| 209 # | |
| 210 # Args: | |
| 211 # name: The name of the rule. | |
| 212 # cc_target: The cc_binary or cc_library to extract files from. | |
| 213 def wasm_cc_binary(outputs = None, **kwargs): | |
| 214 # for backwards compatibility if no outputs are set the deprecated | |
| 215 # implementation is used. | |
| 216 if not outputs: | |
| 217 _wasm_cc_binary_legacy(**kwargs) | |
| 218 else: | |
| 219 _wasm_cc_binary(outputs = outputs, **kwargs) |