blob: e63d67e88018c2b627968e45cabc80bb453a76a9 [file] [log] [blame]
James Kuszmaul9b8125e2019-09-01 17:42:25 -07001def _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 Schuh8e17be92019-12-24 09:32:11 -080012 output = html_out,
13 template = html_shell,
14 substitutions = {
15 "{{{ SCRIPT }}}": "<script async type=\"text/javascript\" src=\"" + basename +
16 ".js\"></script>",
17 },
18 )
James Kuszmaul9b8125e2019-09-01 17:42:25 -070019 else:
20 tar_outs.append(html_out)
21
22 ctx.actions.run_shell(
Austin Schuh8e17be92019-12-24 09:32:11 -080023 outputs = tar_outs,
24 inputs = [tarfile],
25 command = "tar xf " + tarfile.path + " -C \"" + html_out.dirname + "\"",
26 )
James Kuszmaul9b8125e2019-09-01 17:42:25 -070027
Austin Schuh8e17be92019-12-24 09:32:11 -080028 return [DefaultInfo(files = depset(tar_outs + [html_out]))]
James Kuszmaul9b8125e2019-09-01 17:42:25 -070029
30emcc_expand_files = rule(
Austin Schuh8e17be92019-12-24 09:32:11 -080031 attrs = {
James Kuszmaul9b8125e2019-09-01 17:42:25 -070032 "html_shell": attr.label(
Austin Schuh8e17be92019-12-24 09:32:11 -080033 mandatory = False,
34 allow_single_file = True,
James Kuszmaul9b8125e2019-09-01 17:42:25 -070035 ),
36 "tarfile": attr.label(
Austin Schuh8e17be92019-12-24 09:32:11 -080037 mandatory = True,
38 allow_single_file = True,
James Kuszmaul9b8125e2019-09-01 17:42:25 -070039 ),
40 },
Austin Schuh8e17be92019-12-24 09:32:11 -080041 doc = """
James Kuszmaul9b8125e2019-09-01 17:42:25 -070042 Handles the intermediate processing to extra files from a tarball
43 for emcc_binary. See emcc_binary for more detail.""",
Austin Schuh8e17be92019-12-24 09:32:11 -080044 implementation = _emcc_expand_files_impl,
James Kuszmaul9b8125e2019-09-01 17:42:25 -070045)
46
Austin Schuh8e17be92019-12-24 09:32:11 -080047def emcc_binary(name, srcs = [], linkopts = [], html_shell = None, **kwargs):
James Kuszmaul36816f32019-08-31 16:58:23 -070048 """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 Kuszmaul36816f32019-08-31 16:58:23 -070065
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 Kuszmaul9b8125e2019-09-01 17:42:25 -070068 is the rule that actually outputs the required files.
James Kuszmaul36816f32019-08-31 16:58:23 -070069
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 Kuszmaul9b8125e2019-09-01 17:42:25 -070074 3) [if necessary] Generating the output html from the html shell template.
James Kuszmaul36816f32019-08-31 16:58:23 -070075 """
James Kuszmaul27da8142019-07-21 16:13:55 -070076 includehtml = False
77 linkopts = list(linkopts)
James Kuszmaul36816f32019-08-31 16:58:23 -070078 srcs = list(srcs)
James Kuszmaul27da8142019-07-21 16:13:55 -070079 if name.endswith(".html"):
80 basename = name[:-5]
81 includehtml = True
James Kuszmaul27da8142019-07-21 16:13:55 -070082 elif name.endswith(".js"):
83 basename = name[:-3]
James Kuszmaul27da8142019-07-21 16:13:55 -070084 outputs = []
James Kuszmaul36816f32019-08-31 16:58:23 -070085 outputs.append(basename + ".js")
86 outputs.append(basename + ".wasm")
James Kuszmaul27da8142019-07-21 16:13:55 -070087
James Kuszmaul36816f32019-08-31 16:58:23 -070088 if includehtml and not html_shell:
James Kuszmaul27da8142019-07-21 16:13:55 -070089 outputs.append(basename + ".html")
James Kuszmaul36816f32019-08-31 16:58:23 -070090 tarfile = name + ".tar"
91 if html_shell:
92 tarfile = basename + ".js.tar"
93 native.cc_binary(
Austin Schuh8e17be92019-12-24 09:32:11 -080094 name = tarfile,
95 srcs = srcs,
96 linkopts = linkopts,
97 restricted_to = ["//tools:web"],
98 **kwargs
99 )
James Kuszmaul9b8125e2019-09-01 17:42:25 -0700100 emcc_expand_files(
Austin Schuh8e17be92019-12-24 09:32:11 -0800101 name = basename,
102 html_shell = html_shell,
103 tarfile = tarfile,
104 restricted_to = ["//tools:web"],
James Kuszmaul36816f32019-08-31 16:58:23 -0700105 )