blob: e63d67e88018c2b627968e45cabc80bb453a76a9 [file] [log] [blame]
def _emcc_expand_files_impl(ctx):
tarfile = ctx.file.tarfile
html_shell = ctx.file.html_shell
basename = ctx.attr.name
html_out = ctx.actions.declare_file(basename + ".html")
tar_outs = [
ctx.actions.declare_file(basename + "." + extension)
for extension in ["js", "wasm"]
]
if html_shell:
ctx.actions.expand_template(
output = html_out,
template = html_shell,
substitutions = {
"{{{ SCRIPT }}}": "<script async type=\"text/javascript\" src=\"" + basename +
".js\"></script>",
},
)
else:
tar_outs.append(html_out)
ctx.actions.run_shell(
outputs = tar_outs,
inputs = [tarfile],
command = "tar xf " + tarfile.path + " -C \"" + html_out.dirname + "\"",
)
return [DefaultInfo(files = depset(tar_outs + [html_out]))]
emcc_expand_files = rule(
attrs = {
"html_shell": attr.label(
mandatory = False,
allow_single_file = True,
),
"tarfile": attr.label(
mandatory = True,
allow_single_file = True,
),
},
doc = """
Handles the intermediate processing to extra files from a tarball
for emcc_binary. See emcc_binary for more detail.""",
implementation = _emcc_expand_files_impl,
)
def emcc_binary(name, srcs = [], linkopts = [], html_shell = None, **kwargs):
"""Produces a deployable set of WebAssembly files.
Depending on the settings, the exact format of the output varies.
The output will be a a .js, .wasm, and optional .html file, all sharing the
same basename. The .js file is the script that should be included in any
webpage, and will handle calling the code compiled to the .wasm file.
The optional .html file uses some existing template html file and adds the
necessary <script> statement to import the .js script. This html file will
be generated if the name of the rule ends with ".html"; if the html_shell
argument is specified, then the provided html file is used to generate the
output html. The only change made to the template html is to replace any
instances of "{{{ SCRIPT }}}" with the appropriate <script> tags. This is
consistent with how the "--shell-file" flag works in emscripten. However, we
can't use the builtin flag with the script in its current form, because
that would require making an html file an input to a cc_library rule,
which bazel gets obnoxious about.
This macro also defines a rule with a name equal to the basename of
the name argument (e.g., if name = "foo.html", basename = "foo"). This rule
is the rule that actually outputs the required files.
Internally, this rule works by:
1) Generating a tarball that contains the .js and .wasm files, using
a cc_binary that calls the emscripten compiler.
2) Extracting said tarball.
3) [if necessary] Generating the output html from the html shell template.
"""
includehtml = False
linkopts = list(linkopts)
srcs = list(srcs)
if name.endswith(".html"):
basename = name[:-5]
includehtml = True
elif name.endswith(".js"):
basename = name[:-3]
outputs = []
outputs.append(basename + ".js")
outputs.append(basename + ".wasm")
if includehtml and not html_shell:
outputs.append(basename + ".html")
tarfile = name + ".tar"
if html_shell:
tarfile = basename + ".js.tar"
native.cc_binary(
name = tarfile,
srcs = srcs,
linkopts = linkopts,
restricted_to = ["//tools:web"],
**kwargs
)
emcc_expand_files(
name = basename,
html_shell = html_shell,
tarfile = tarfile,
restricted_to = ["//tools:web"],
)