BUILD_FILE_CONTENT_TEMPLATE = """ package(default_visibility = ['//visibility:public']) exports_files(['emscripten_config']) """ EMBUILDER_CONFIG_TEMPLATE = """ CACHE = '{cache}' BINARYEN_ROOT = '{binaryen_root}' LLVM_ROOT = '{llvm_root}' """ def get_root_and_script_ext(repository_ctx): if repository_ctx.os.name.startswith('linux'): if 'amd64' in repository_ctx.os.arch or 'x86_64' in repository_ctx.os.arch: return (repository_ctx.path(Label("@emscripten_bin_linux//:BUILD.bazel")).dirname, '') elif 'aarch64' in repository_ctx.os.arch: return (repository_ctx.path(Label("@emscripten_bin_linux_arm64//:BUILD.bazel")).dirname, '') else: fail('Unsupported architecture for Linux') elif repository_ctx.os.name.startswith('mac'): if 'amd64' in repository_ctx.os.arch or 'x86_64' in repository_ctx.os.arch: return (repository_ctx.path(Label("@emscripten_bin_mac//:BUILD.bazel")).dirname, '') elif 'aarch64' in repository_ctx.os.arch: return (repository_ctx.path(Label("@emscripten_bin_mac_arm64//:BUILD.bazel")).dirname, '') else: fail('Unsupported architecture for MacOS') elif repository_ctx.os.name.startswith('windows'): return (repository_ctx.path(Label("@emscripten_bin_win//:BUILD.bazel")).dirname, '.bat') else: fail('Unsupported operating system') def _emscripten_cache_impl(repository_ctx): # Read the default emscripten configuration file default_config = repository_ctx.read( repository_ctx.path( Label("@emsdk//emscripten_toolchain:default_config") ) ) if repository_ctx.attr.targets or repository_ctx.attr.configuration: root, script_ext = get_root_and_script_ext(repository_ctx) llvm_root = root.get_child("bin") cache = repository_ctx.path("cache") # Create configuration file embuilder_config_content = EMBUILDER_CONFIG_TEMPLATE.format( cache=cache, binaryen_root=root, llvm_root=llvm_root, ) repository_ctx.file("embuilder_config", embuilder_config_content) embuilder_config_path = repository_ctx.path("embuilder_config") embuilder_path = "{}{}".format(root.get_child("emscripten").get_child("embuilder"), script_ext) # Prepare the command line if repository_ctx.attr.targets: targets = repository_ctx.attr.targets else: # If no targets are requested, build everything targets = ["ALL"] flags = ["--em-config", embuilder_config_path] + repository_ctx.attr.configuration embuilder_args = [embuilder_path] + flags + ["build"] + targets # Run embuilder repository_ctx.report_progress("Building secondary cache") result = repository_ctx.execute( embuilder_args, quiet=True, environment = { "EM_IGNORE_SANITY": "1", "EM_NODE_JS": "empty", } ) if result.return_code != 0: fail("Embuilder exited with a non-zero return code") # Override Emscripten's cache with the secondary cache default_config += "CACHE = '{}'\n".format(cache) # Create the configuration file for the toolchain and export repository_ctx.file('emscripten_config', default_config) repository_ctx.file('BUILD.bazel', BUILD_FILE_CONTENT_TEMPLATE) _emscripten_cache = repository_rule( implementation = _emscripten_cache_impl, attrs = { "configuration": attr.string_list(), "targets": attr.string_list(), }, local = True ) def register_emscripten_toolchains(cache = {}): _emscripten_cache( name = "emscripten_cache", configuration = cache["configuration"] if "configuration" in cache else [], targets = cache["targets"] if "targets" in cache else [], ) native.register_toolchains(str(Label("//emscripten_toolchain:cc-toolchain-wasm")))