James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 1 | # Sourced from https://github.com/ribrdb/rules_emscripten/blob/master/toolchain/defs.bzl |
| 2 | # TODO(james): Specialize this more for our purposes--e.g., |
| 3 | # we probably will only actually use one set of the possible options. |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame^] | 4 | def emcc_binary(name, srcs=[], linkopts=[], html_shell=None, **kwargs): |
| 5 | """Produces a deployable set of WebAssembly files. |
| 6 | |
| 7 | Depending on the settings, the exact format of the output varies. |
| 8 | The output will be a a .js, .wasm, and optional .html file, all sharing the |
| 9 | same basename. The .js file is the script that should be included in any |
| 10 | webpage, and will handle calling the code compiled to the .wasm file. |
| 11 | |
| 12 | The optional .html file uses some existing template html file and adds the |
| 13 | necessary <script> statement to import the .js script. This html file will |
| 14 | be generated if the name of the rule ends with ".html"; if the html_shell |
| 15 | argument is specified, then the provided html file is used to generate the |
| 16 | output html. The only change made to the template html is to replace any |
| 17 | instances of "{{{ SCRIPT }}}" with the appropriate <script> tags. This is |
| 18 | consistent with how the "--shell-file" flag works in emscripten. However, we |
| 19 | can't use the builtin flag with the script in its current form, because |
| 20 | that would require making an html file an input to a cc_library rule, |
| 21 | which bazel gets obnoxious about. |
| 22 | TODO(james): Rewrite this as a rule so that we can do some of this more |
| 23 | cleanly. |
| 24 | |
| 25 | This macro also defines a rule with a name equal to the basename of |
| 26 | the name argument (e.g., if name = "foo.html", basename = "foo"). This rule |
| 27 | is a filegroup containing all the output files of this rule. |
| 28 | |
| 29 | Internally, this rule works by: |
| 30 | 1) Generating a tarball that contains the .js and .wasm files, using |
| 31 | a cc_binary that calls the emscripten compiler. |
| 32 | 2) Extracting said tarball. |
| 33 | 3) Generating the output html from the html shell template. |
| 34 | """ |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 35 | includehtml = False |
| 36 | linkopts = list(linkopts) |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame^] | 37 | srcs = list(srcs) |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 38 | if name.endswith(".html"): |
| 39 | basename = name[:-5] |
| 40 | includehtml = True |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 41 | elif name.endswith(".js"): |
| 42 | basename = name[:-3] |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 43 | outputs = [] |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame^] | 44 | outputs.append(basename + ".js") |
| 45 | outputs.append(basename + ".wasm") |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 46 | |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame^] | 47 | if includehtml and not html_shell: |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 48 | outputs.append(basename + ".html") |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame^] | 49 | tarfile = name + ".tar" |
| 50 | if html_shell: |
| 51 | tarfile = basename + ".js.tar" |
| 52 | native.cc_binary( |
| 53 | name=tarfile, |
| 54 | srcs=srcs, |
| 55 | linkopts=linkopts, |
| 56 | restricted_to = ["//tools:web"], |
| 57 | **kwargs) |
| 58 | native.genrule( |
| 59 | name="emcc_extract_" + tarfile, |
| 60 | srcs=[tarfile], |
| 61 | outs=outputs, |
| 62 | output_to_bindir=1, |
| 63 | testonly=kwargs.get('testonly'), |
| 64 | restricted_to = ["//tools:web"], |
| 65 | cmd="""tar xf $< -C "$(@D)"/$$(dirname "%s")""" % [outputs[0]]) |
| 66 | if html_shell: |
| 67 | native.genrule( |
| 68 | name = "generate_shell_" + name, |
| 69 | srcs = [html_shell], |
| 70 | outs = [basename + ".html"], |
| 71 | restricted_to = ["//tools:web"], |
| 72 | cmd = "sed 's/{{{ SCRIPT }}}/<script async type=\"text\/javascript\" src=\"" + basename + ".js\"><\/script>/' $< > $@", |
| 73 | ) |
| 74 | outputs.append(basename + ".html") |
| 75 | native.filegroup( |
| 76 | name = basename, |
| 77 | srcs = outputs, |
| 78 | restricted_to = ["//tools:web"] |
| 79 | ) |