James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 1 | def _emcc_expand_files_impl(ctx): |
| 2 | tarfile = ctx.file.tarfile |
| 3 | html_shell = ctx.file.html_shell |
| 4 | basename = ctx.attr.name |
| 5 | html_out = ctx.actions.declare_file(basename + ".html") |
| 6 | tar_outs = [ |
| 7 | ctx.actions.declare_file(basename + "." + extension) |
| 8 | for extension in ["js", "wasm"] |
| 9 | ] |
| 10 | if html_shell: |
| 11 | ctx.actions.expand_template( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 12 | output = html_out, |
| 13 | template = html_shell, |
| 14 | substitutions = { |
| 15 | "{{{ SCRIPT }}}": "<script async type=\"text/javascript\" src=\"" + basename + |
| 16 | ".js\"></script>", |
| 17 | }, |
| 18 | ) |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 19 | else: |
| 20 | tar_outs.append(html_out) |
| 21 | |
| 22 | ctx.actions.run_shell( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 23 | outputs = tar_outs, |
| 24 | inputs = [tarfile], |
| 25 | command = "tar xf " + tarfile.path + " -C \"" + html_out.dirname + "\"", |
| 26 | ) |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 27 | |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 28 | return [DefaultInfo(files = depset(tar_outs + [html_out]))] |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 29 | |
| 30 | emcc_expand_files = rule( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 31 | attrs = { |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 32 | "html_shell": attr.label( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 33 | mandatory = False, |
| 34 | allow_single_file = True, |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 35 | ), |
| 36 | "tarfile": attr.label( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 37 | mandatory = True, |
| 38 | allow_single_file = True, |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 39 | ), |
| 40 | }, |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 41 | doc = """ |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 42 | Handles the intermediate processing to extra files from a tarball |
| 43 | for emcc_binary. See emcc_binary for more detail.""", |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 44 | implementation = _emcc_expand_files_impl, |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 45 | ) |
| 46 | |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 47 | def emcc_binary(name, srcs = [], linkopts = [], html_shell = None, **kwargs): |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 48 | """Produces a deployable set of WebAssembly files. |
| 49 | |
| 50 | Depending on the settings, the exact format of the output varies. |
| 51 | The output will be a a .js, .wasm, and optional .html file, all sharing the |
| 52 | same basename. The .js file is the script that should be included in any |
| 53 | webpage, and will handle calling the code compiled to the .wasm file. |
| 54 | |
| 55 | The optional .html file uses some existing template html file and adds the |
| 56 | necessary <script> statement to import the .js script. This html file will |
| 57 | be generated if the name of the rule ends with ".html"; if the html_shell |
| 58 | argument is specified, then the provided html file is used to generate the |
| 59 | output html. The only change made to the template html is to replace any |
| 60 | instances of "{{{ SCRIPT }}}" with the appropriate <script> tags. This is |
| 61 | consistent with how the "--shell-file" flag works in emscripten. However, we |
| 62 | can't use the builtin flag with the script in its current form, because |
| 63 | that would require making an html file an input to a cc_library rule, |
| 64 | which bazel gets obnoxious about. |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 65 | |
| 66 | This macro also defines a rule with a name equal to the basename of |
| 67 | the name argument (e.g., if name = "foo.html", basename = "foo"). This rule |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 68 | is the rule that actually outputs the required files. |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 69 | |
| 70 | Internally, this rule works by: |
| 71 | 1) Generating a tarball that contains the .js and .wasm files, using |
| 72 | a cc_binary that calls the emscripten compiler. |
| 73 | 2) Extracting said tarball. |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 74 | 3) [if necessary] Generating the output html from the html shell template. |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 75 | """ |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 76 | includehtml = False |
| 77 | linkopts = list(linkopts) |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 78 | srcs = list(srcs) |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 79 | if name.endswith(".html"): |
| 80 | basename = name[:-5] |
| 81 | includehtml = True |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 82 | elif name.endswith(".js"): |
| 83 | basename = name[:-3] |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 84 | outputs = [] |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 85 | outputs.append(basename + ".js") |
| 86 | outputs.append(basename + ".wasm") |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 87 | |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 88 | if includehtml and not html_shell: |
James Kuszmaul | 27da814 | 2019-07-21 16:13:55 -0700 | [diff] [blame] | 89 | outputs.append(basename + ".html") |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 90 | tarfile = name + ".tar" |
| 91 | if html_shell: |
| 92 | tarfile = basename + ".js.tar" |
| 93 | native.cc_binary( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 94 | name = tarfile, |
| 95 | srcs = srcs, |
| 96 | linkopts = linkopts, |
| 97 | restricted_to = ["//tools:web"], |
| 98 | **kwargs |
| 99 | ) |
James Kuszmaul | 9b8125e | 2019-09-01 17:42:25 -0700 | [diff] [blame] | 100 | emcc_expand_files( |
Austin Schuh | 8e17be9 | 2019-12-24 09:32:11 -0800 | [diff] [blame] | 101 | name = basename, |
| 102 | html_shell = html_shell, |
| 103 | tarfile = tarfile, |
| 104 | restricted_to = ["//tools:web"], |
James Kuszmaul | 36816f3 | 2019-08-31 16:58:23 -0700 | [diff] [blame] | 105 | ) |