diff --git a/defs.bzl b/defs.bzl index c6aca6f0f..6232464b8 100644 --- a/defs.bzl +++ b/defs.bzl @@ -9,7 +9,7 @@ load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install load("@io_bazel_rules_sass//:defs.bzl", "sass_repositories") load("@com_github_ali5h_rules_pip//:defs.bzl", "pip_import") load("//pip/pyqt5:defs.bzl", "install_pyqt5") -load("//ts/esbuild:esbuild_repo.bzl", "esbuild_dependencies") +load("@esbuild_toolchain//:esbuild_repo.bzl", "esbuild_dependencies") anki_version = "2.1.44" diff --git a/repos.bzl b/repos.bzl index 8e2ca5c60..104ba8ada 100644 --- a/repos.bzl +++ b/repos.bzl @@ -85,12 +85,26 @@ def register_repos(): # ], # ) - http_archive( + maybe( + http_archive, name = "build_bazel_rules_nodejs", sha256 = "1134ec9b7baee008f1d54f0483049a97e53a57cd3913ec9d6db625549c98395a", urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.4.0/rules_nodejs-3.4.0.tar.gz"], ) + # native.local_repository( + # name = "esbuild_toolchain", + # path = "../esbuild_toolchain", + # ) + + maybe( + http_archive, + name = "esbuild_toolchain", + sha256 = "ac530f935b10e2e45f009ef0a8a2e3f4c95172c2548932fb7ca0d37ad95b6e9e", + urls = ["https://github.com/ankitects/esbuild_toolchain/archive/refs/tags/anki-2021-04-15.tar.gz"], + strip_prefix = "esbuild_toolchain-anki-2021-04-15", + ) + # sass ############ diff --git a/ts/congrats/BUILD.bazel b/ts/congrats/BUILD.bazel index 8e41624f2..1148e3ae0 100644 --- a/ts/congrats/BUILD.bazel +++ b/ts/congrats/BUILD.bazel @@ -6,13 +6,13 @@ load("//ts:esbuild.bzl", "esbuild") load("//ts:compile_sass.bzl", "compile_sass") compile_sass( - group = "base_css", srcs = ["congrats-base.scss"], + group = "base_css", + visibility = ["//visibility:public"], deps = [ "//ts/sass:base_lib", "//ts/sass:scrollbar_lib", ], - visibility = ["//visibility:public"], ) svelte( @@ -20,7 +20,6 @@ svelte( entry_point = "CongratsPage.svelte", ) - ts_library( name = "index", srcs = ["index.ts"], @@ -57,14 +56,14 @@ esbuild( external = [ "protobufjs/light", ], - output_css = True, + output_css = "congrats.css", visibility = ["//visibility:public"], deps = [ + "CongratsPage", + ":base_css", + ":index", "//ts/lib", "//ts/lib:backend_proto", - "CongratsPage", - ":index", - ":base_css", ], ) diff --git a/ts/deckconfig/BUILD.bazel b/ts/deckconfig/BUILD.bazel index c1d29e812..b53e6d0a6 100644 --- a/ts/deckconfig/BUILD.bazel +++ b/ts/deckconfig/BUILD.bazel @@ -75,7 +75,7 @@ esbuild( external = [ "protobufjs/light", ], - output_css = True, + output_css = "deckconfig.css", visibility = ["//visibility:public"], deps = [ "index", diff --git a/ts/esbuild.bzl b/ts/esbuild.bzl index 3de24a8f5..d03eabe3e 100644 --- a/ts/esbuild.bzl +++ b/ts/esbuild.bzl @@ -1,4 +1,4 @@ -load("//ts/esbuild:upstream.bzl", _esbuild = "esbuild_macro") +load("@esbuild_toolchain//:esbuild.bzl", _esbuild = "esbuild_macro") def esbuild(name, **kwargs): _esbuild( diff --git a/ts/esbuild/BUILD.bazel b/ts/esbuild/BUILD.bazel deleted file mode 100644 index 59a42b85e..000000000 --- a/ts/esbuild/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -load(":toolchain.bzl", "define_default_toolchains", "esbuild_toolchain") - -toolchain_type( - name = "toolchain_type", - visibility = ["//visibility:public"], -) - -define_default_toolchains() diff --git a/ts/esbuild/README.md b/ts/esbuild/README.md deleted file mode 100644 index 4afa25887..000000000 --- a/ts/esbuild/README.md +++ /dev/null @@ -1,4 +0,0 @@ -This folder vendors the esbuild support in rules_nodejs while we wait -for some upstream changes to be applied: - -- https://github.com/bazelbuild/rules_nodejs/pull/2545 diff --git a/ts/esbuild/esbuild_repo.bzl b/ts/esbuild/esbuild_repo.bzl deleted file mode 100644 index c507d9809..000000000 --- a/ts/esbuild/esbuild_repo.bzl +++ /dev/null @@ -1,45 +0,0 @@ -""" Generated code; do not edit -Update by running yarn update-esbuild-versions - -Helper macro for fetching esbuild versions for internal tests and examples in rules_nodejs -""" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load(":toolchain.bzl", "register_default_toolchains") - -_VERSION = "0.11.5" - -def esbuild_dependencies(): - """Helper to install required dependencies for the esbuild rules""" - - version = _VERSION - - http_archive( - name = "esbuild_darwin", - urls = [ - "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-%s.tgz" % version, - ], - strip_prefix = "package", - build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "98436890727bdb0d4beddd9c9e07d0aeff0e8dfe0169f85e568eca0dd43f665e", - ) - http_archive( - name = "esbuild_windows", - urls = [ - "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-%s.tgz" % version, - ], - strip_prefix = "package", - build_file_content = """exports_files(["esbuild.exe"])""", - sha256 = "589c8ff97210bd41de106e6317ce88f9e88d2cacfd8178ae1217f2b857ff6c3a", - ) - http_archive( - name = "esbuild_linux", - urls = [ - "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-%s.tgz" % version, - ], - strip_prefix = "package", - build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "113c2e84895f4422a3676db4e15d9f01b2b4fac041edab25284fdb9574ba58a0", - ) - - register_default_toolchains() diff --git a/ts/esbuild/helpers.bzl b/ts/esbuild/helpers.bzl deleted file mode 100644 index e18999951..000000000 --- a/ts/esbuild/helpers.bzl +++ /dev/null @@ -1,120 +0,0 @@ -""" -NOTE: this file was forked from the following repo (Apache2) -https://github.com/bazelbuild/rules_nodejs/blob/c47b770a122e9614516df2e3fdca6fe0bf6e3420/packages/esbuild/helpers.bzl - -Local changes not in upstream: -https://github.com/bazelbuild/rules_nodejs/pull/2563 - -Utility helper functions for the esbuild rule -""" - -load("@build_bazel_rules_nodejs//third_party/github.com/bazelbuild/bazel-skylib:lib/paths.bzl", "paths") - -def strip_ext(f): - "Strips the extension of a file." - return f.short_path[:-len(f.extension) - 1] - -def resolve_js_input(f, inputs): - """Find a corresponding javascript entrypoint for a provided file - - Args: - f: The file where its basename is used to match the entrypoint - inputs: The list of files where it should take a look at - - Returns: - Returns the file that is the corresponding entrypoint - """ - if f.extension == "js" or f.extension == "mjs": - return f - - no_ext = strip_ext(f) - for i in inputs: - if i.extension == "js" or i.extension == "mjs": - if strip_ext(i) == no_ext: - return i - fail("Could not find corresponding javascript entry point for %s. Add the %s.js to your deps." % (f.path, no_ext)) - -def filter_files(input, endings = [".js"]): - """Filters a list of files for specific endings - - Args: - input: The depset or list of files - endings: The list of endings that should be filtered for - - Returns: - Returns the filtered list of files - """ - - # Convert input into list regardles of being a depset or list - input_list = input.to_list() if type(input) == "depset" else input - filtered = [] - - for file in input_list: - for ending in endings: - if file.path.endswith(ending): - filtered.append(file) - continue - - return filtered - -def generate_path_mapping(package_name, path): - """Generate a path alias mapping for a jsconfig.json - - For example: {"@my-alias/*": [ "path/to/my-alias/*" ]}, - - Args: - package_name: The module name - path: The base path of the package - """ - - pkg = {} - - # entry for the barrel files favor mjs over normal as it results - # in smaller bundles - pkg[package_name] = [ - path + "/index.mjs", - path, - ] - - # A glob import for deep package imports - pkg[package_name + "/*"] = [path + "/*"] - - return pkg - -def write_jsconfig_file(ctx, path_alias_mappings): - """Writes the js config file for the path alias mappings. - - Args: - ctx: The rule context - path_alias_mappings: Dict with the mappings - - Returns: - File object reference for the jsconfig file - """ - - # The package path, including an "external/repo_name/" prefix if the package is in - # an external repo. - rule_path = paths.join(ctx.label.workspace_root, paths.dirname(ctx.build_file_path)) - - # Replace all segments in the path with .. join them with "/" and postfix - # it with another / to get a relative path from the build file dir - # to the workspace root. - if len(rule_path) == 0: - base_url_path = "." - else: - base_url_path = "/".join([".." for segment in rule_path.split("/")]) + "/" - - # declare the jsconfig_file - jsconfig_file = ctx.actions.declare_file("%s.config.json" % ctx.attr.name) - - # write the config file - ctx.actions.write( - output = jsconfig_file, - content = struct(compilerOptions = struct( - rootDirs = ["."], - baseUrl = base_url_path, - paths = path_alias_mappings, - )).to_json(), - ) - - return jsconfig_file diff --git a/ts/esbuild/toolchain.bzl b/ts/esbuild/toolchain.bzl deleted file mode 100644 index dfd6d5898..000000000 --- a/ts/esbuild/toolchain.bzl +++ /dev/null @@ -1,42 +0,0 @@ -def _esbuild_toolchain_impl(ctx): - return [platform_common.ToolchainInfo( - binary = ctx.executable.binary, - )] - -esbuild_toolchain = rule( - implementation = _esbuild_toolchain_impl, - attrs = { - "binary": attr.label(allow_single_file = True, executable = True, cfg = "exec"), - }, -) - -_package_path = "@net_ankiweb_anki//ts/esbuild" - -TOOLCHAIN = _package_path + ":toolchain_type" - -_default_toolchains = [ - ["@esbuild_darwin//:bin/esbuild", "macos"], - ["@esbuild_linux//:bin/esbuild", "linux"], - ["@esbuild_windows//:esbuild.exe", "windows"], -] - -def define_default_toolchains(): - for repo_path, platform in _default_toolchains: - esbuild_toolchain( - name = "esbuild_" + platform, - binary = repo_path, - ) - - native.toolchain( - name = "esbuild_{}_toolchain".format(platform), - exec_compatible_with = [ - "@platforms//os:" + platform, - "@platforms//cpu:x86_64", - ], - toolchain = ":esbuild_" + platform, - toolchain_type = ":toolchain_type", - ) - -def register_default_toolchains(): - for _, platform in _default_toolchains: - native.register_toolchains(_package_path + ":esbuild_{}_toolchain".format(platform)) diff --git a/ts/esbuild/upstream.bzl b/ts/esbuild/upstream.bzl deleted file mode 100644 index 190addaee..000000000 --- a/ts/esbuild/upstream.bzl +++ /dev/null @@ -1,318 +0,0 @@ -""" -esbuild rule -""" - -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSModuleInfo", "NpmPackageInfo", "node_modules_aspect") -load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "MODULE_MAPPINGS_ASPECT_RESULTS_NAME", "module_mappings_aspect") -load(":helpers.bzl", "filter_files", "generate_path_mapping", "resolve_js_input", "write_jsconfig_file") -load(":toolchain.bzl", "TOOLCHAIN") - -def _esbuild_impl(ctx): - # For each dep, JSEcmaScriptModuleInfo is used if found, then JSModuleInfo and finally - # the DefaultInfo files are used if the former providers are not found. - deps_depsets = [] - - # Path alias mapings are used to create a jsconfig with mappings so that esbuild - # how to resolve custom package or module names - path_alias_mappings = dict() - npm_workspaces = [] - - if (ctx.attr.link_workspace_root): - path_alias_mappings.update(generate_path_mapping(ctx.workspace_name, ".")) - - for dep in ctx.attr.deps: - if JSEcmaScriptModuleInfo in dep: - deps_depsets.append(dep[JSEcmaScriptModuleInfo].sources) - - if JSModuleInfo in dep: - deps_depsets.append(dep[JSModuleInfo].sources) - elif hasattr(dep, "files"): - deps_depsets.append(dep.files) - - if DefaultInfo in dep: - deps_depsets.append(dep[DefaultInfo].data_runfiles.files) - - if NpmPackageInfo in dep: - deps_depsets.append(dep[NpmPackageInfo].sources) - npm_workspaces.append(dep[NpmPackageInfo].workspace) - - # Collect the path alias mapping to resolve packages correctly - if hasattr(dep, MODULE_MAPPINGS_ASPECT_RESULTS_NAME): - for key, value in getattr(dep, MODULE_MAPPINGS_ASPECT_RESULTS_NAME).items(): - path_alias_mappings.update(generate_path_mapping(key, value[1].replace(ctx.bin_dir.path + "/", ""))) - - node_modules_mappings = [ - "../../../external/%s/node_modules/*" % workspace - for workspace in depset(npm_workspaces).to_list() - ] - path_alias_mappings.update({"*": node_modules_mappings}) - - deps_inputs = depset(transitive = deps_depsets).to_list() - inputs = filter_files(ctx.files.entry_point, [".mjs", ".js"]) + ctx.files.srcs + deps_inputs - - metafile = ctx.actions.declare_file("%s_metadata.json" % ctx.attr.name) - outputs = [metafile] - - entry_point = resolve_js_input(ctx.file.entry_point, inputs) - - args = ctx.actions.args() - - args.add("--bundle", entry_point.path) - - if len(ctx.attr.sourcemap) > 0: - args.add_joined(["--sourcemap", ctx.attr.sourcemap], join_with = "=") - else: - args.add("--sourcemap") - - args.add("--preserve-symlinks") - args.add_joined(["--platform", ctx.attr.platform], join_with = "=") - args.add_joined(["--target", ctx.attr.target], join_with = "=") - args.add_joined(["--log-level", "info"], join_with = "=") - args.add_joined(["--metafile", metafile.path], join_with = "=") - args.add_all(ctx.attr.define, format_each = "--define:%s") - args.add_all(ctx.attr.external, format_each = "--external:%s") - - # disable the log limit and show all logs - args.add_joined(["--log-limit", "0"], join_with = "=") - - if ctx.attr.minify: - args.add("--minify") - else: - # by default, esbuild will tree-shake 'pure' functions - # disable this unless also minifying - args.add_joined(["--tree-shaking", "ignore-annotations"], join_with = "=") - - if ctx.attr.sources_content: - args.add("--sources-content=true") - else: - args.add("--sources-content=false") - - if ctx.attr.output_dir: - js_out = ctx.actions.declare_directory("%s" % ctx.attr.name) - outputs.append(js_out) - - args.add("--splitting") - args.add_joined(["--format", "esm"], join_with = "=") - args.add_joined(["--outdir", js_out.path], join_with = "=") - else: - js_out = ctx.outputs.output - outputs.append(js_out) - - js_out_map = ctx.outputs.output_map - if ctx.attr.sourcemap != "inline": - if js_out_map == None: - fail("output_map must be specified if sourcemap is not set to 'inline'") - outputs.append(js_out_map) - - if ctx.outputs.output_css: - outputs.append(ctx.outputs.output_css) - - if ctx.attr.format: - args.add_joined(["--format", ctx.attr.format], join_with = "=") - - args.add_joined(["--outfile", js_out.path], join_with = "=") - - jsconfig_file = write_jsconfig_file(ctx, path_alias_mappings) - args.add_joined(["--tsconfig", jsconfig_file.path], join_with = "=") - inputs.append(jsconfig_file) - - args.add_all([ctx.expand_location(arg) for arg in ctx.attr.args]) - - env = {} - if ctx.attr.max_threads > 0: - env["GOMAXPROCS"] = str(ctx.attr.max_threads) - - execution_requirements = {} - if "no-remote-exec" in ctx.attr.tags: - execution_requirements = {"no-remote-exec": "1"} - - ctx.actions.run( - inputs = inputs, - outputs = outputs, - executable = ctx.toolchains[TOOLCHAIN].binary, - arguments = [args], - progress_message = "%s Javascript %s [esbuild]" % ("Bundling" if not ctx.attr.output_dir else "Splitting", entry_point.short_path), - execution_requirements = execution_requirements, - mnemonic = "esbuild", - env = env, - ) - - return [ - DefaultInfo(files = depset(outputs + [jsconfig_file])), - ] - -esbuild = rule( - attrs = { - "args": attr.string_list( - default = [], - doc = """A list of extra arguments that are included in the call to esbuild. - $(location ...) can be used to resolve the path to a Bazel target.""", - ), - "define": attr.string_list( - default = [], - doc = """A list of global identifier replacements. -Example: -```python -esbuild( - name = "bundle", - define = [ - "process.env.NODE_ENV=\\"production\\"" - ], -) -``` - -See https://esbuild.github.io/api/#define for more details - """, - ), - "deps": attr.label_list( - default = [], - aspects = [module_mappings_aspect, node_modules_aspect], - doc = "A list of direct dependencies that are required to build the bundle", - ), - "entry_point": attr.label( - mandatory = True, - allow_single_file = True, - doc = "The bundle's entry point (e.g. your main.js or app.js or index.js)", - ), - "external": attr.string_list( - default = [], - doc = """A list of module names that are treated as external and not included in the resulting bundle - -See https://esbuild.github.io/api/#external for more details - """, - ), - "format": attr.string( - values = ["iife", "cjs", "esm", ""], - mandatory = False, - doc = """The output format of the bundle, defaults to iife when platform is browser -and cjs when platform is node. If performing code splitting, defaults to esm. - -See https://esbuild.github.io/api/#format for more details - """, - ), - "link_workspace_root": attr.bool( - doc = """Link the workspace root to the bin_dir to support absolute requires like 'my_wksp/path/to/file'. - If source files need to be required then they can be copied to the bin_dir with copy_to_bin.""", - ), - "max_threads": attr.int( - mandatory = False, - doc = """Sets the `GOMAXPROCS` variable to limit the number of threads that esbuild can run with. -This can be useful if running many esbuild rule invocations in parallel, which has the potential to cause slowdown. -For general use, leave this attribute unset. - """, - ), - "minify": attr.bool( - default = False, - doc = """Minifies the bundle with the built in minification. -Removes whitespace, shortens identifieres and uses equivalent but shorter syntax. - -Sets all --minify-* flags - -See https://esbuild.github.io/api/#minify for more details - """, - ), - "output": attr.output( - mandatory = False, - doc = "Name of the output file when bundling", - ), - "output_dir": attr.bool( - default = False, - doc = """If true, esbuild produces an output directory containing all the output files from code splitting - -See https://esbuild.github.io/api/#splitting for more details - """, - ), - "output_map": attr.output( - mandatory = False, - doc = "Name of the output source map when bundling", - ), - "output_css": attr.output( - mandatory = False, - doc = "Name of the output css file when bundling", - ), - "platform": attr.string( - default = "browser", - values = ["node", "browser", "neutral", ""], - doc = """The platform to bundle for. - -See https://esbuild.github.io/api/#platform for more details - """, - ), - "sourcemap": attr.string( - values = ["external", "inline", "both", ""], - mandatory = False, - doc = """Defines where sourcemaps are output and how they are included in the bundle. By default, a separate `.js.map` file is generated and referenced by the bundle. If 'external', a separate `.js.map` file is generated but not referenced by the bundle. If 'inline', a sourcemap is generated and its contents are inlined into the bundle (and no external sourcemap file is created). If 'both', a sourcemap is inlined and a `.js.map` file is created. - -See https://esbuild.github.io/api/#sourcemap for more details - """, - ), - "sources_content": attr.bool( - mandatory = False, - default = False, - doc = """If False, omits the `sourcesContent` field from generated source maps - -See https://esbuild.github.io/api/#sources-content for more details - """, - ), - "srcs": attr.label_list( - allow_files = True, - default = [], - doc = """Non-entry point JavaScript source files from the workspace. - -You must not repeat file(s) passed to entry_point""", - ), - "target": attr.string( - default = "es2015", - doc = """Environment target (e.g. es2017, chrome58, firefox57, safari11, -edge16, node10, default esnext) - -See https://esbuild.github.io/api/#target for more details - """, - ), - }, - implementation = _esbuild_impl, - doc = """Runs the esbuild bundler under Bazel - -For further information about esbuild, see https://esbuild.github.io/ - """, - toolchains = [ - TOOLCHAIN, - ], -) - -def esbuild_macro(name, output_dir = False, output_css = False, **kwargs): - """esbuild helper macro around the `esbuild_bundle` rule - - For a full list of attributes, see the `esbuild_bundle` rule - - Args: - name: The name used for this rule and output files - output_dir: If `True`, produce a code split bundle in an output directory - output_css: If `True`, declare name.css as an output, which is the - case when your code imports a css file. - **kwargs: All other args from `esbuild_bundle` - """ - - if output_dir == True: - esbuild( - name = name, - output_dir = True, - **kwargs - ) - else: - output = "%s.js" % name - if "output" in kwargs: - output = kwargs.pop("output") - - output_map = None - sourcemap = kwargs.get("sourcemap", None) - if sourcemap != "inline": - output_map = "%s.map" % output - - esbuild( - name = name, - output = output, - output_map = output_map, - output_css = None if not output_css else "%s.css" % name, - **kwargs - ) diff --git a/ts/graphs/BUILD.bazel b/ts/graphs/BUILD.bazel index 05775e211..ee60204fd 100644 --- a/ts/graphs/BUILD.bazel +++ b/ts/graphs/BUILD.bazel @@ -6,13 +6,13 @@ load("//ts:esbuild.bzl", "esbuild") load("//ts:compile_sass.bzl", "compile_sass") compile_sass( - group = "base_css", srcs = ["graphs-base.scss"], + group = "base_css", + visibility = ["//visibility:public"], deps = [ "//ts/sass:base_lib", "//ts/sass:scrollbar_lib", ], - visibility = ["//visibility:public"], ) svelte_files = glob(["*.svelte"]) @@ -71,7 +71,7 @@ esbuild( external = [ "protobufjs/light", ], - output_css = True, + output_css = "graphs.css", visibility = ["//visibility:public"], deps = [ "//ts/sveltelib",