From be184c27033579e9409d455c309a6f9aa04cc13d Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Thu, 8 Apr 2021 18:03:59 -0400 Subject: [PATCH] fix(esbuild): use run_node to invoke linker before running esuild --- examples/esbuild/WORKSPACE | 8 ++-- packages/esbuild/BUILD.bazel | 7 ++- packages/esbuild/_README.md | 8 ++-- packages/esbuild/esbuild.bzl | 44 ++++++++++++------- packages/esbuild/esbuild_repo.bzl | 8 ++-- packages/esbuild/launcher.js | 25 +++++++++++ packages/esbuild/test/vanilla_js/BUILD.bazel | 3 ++ packages/esbuild/test/vanilla_js/main.js | 3 ++ .../esbuild/test/vanilla_js/output.golden.txt | 1 + 9 files changed, 78 insertions(+), 29 deletions(-) create mode 100755 packages/esbuild/launcher.js diff --git a/examples/esbuild/WORKSPACE b/examples/esbuild/WORKSPACE index b016d05190..2505df0e38 100644 --- a/examples/esbuild/WORKSPACE +++ b/examples/esbuild/WORKSPACE @@ -25,12 +25,12 @@ http_archive( urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/3.3.0/rules_nodejs-3.3.0.tar.gz"], ) -_ESBUILD_VERSION = "0.11.5" +_ESBUILD_VERSION = "0.11.6" http_archive( name = "esbuild_darwin", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "98436890727bdb0d4beddd9c9e07d0aeff0e8dfe0169f85e568eca0dd43f665e", + sha256 = "2b06365b075b854654fc9ed26fcd48a0c38947e1c8d5151ce400cd1e173bb138", strip_prefix = "package", urls = [ "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-%s.tgz" % _ESBUILD_VERSION, @@ -40,7 +40,7 @@ http_archive( http_archive( name = "esbuild_windows", build_file_content = """exports_files(["esbuild.exe"])""", - sha256 = "589c8ff97210bd41de106e6317ce88f9e88d2cacfd8178ae1217f2b857ff6c3a", + sha256 = "ddab1121833f0a12ca4fb3e288231e058f5526310671e84c0a9aa575340bb20b", strip_prefix = "package", urls = [ "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-%s.tgz" % _ESBUILD_VERSION, @@ -50,7 +50,7 @@ http_archive( http_archive( name = "esbuild_linux", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "113c2e84895f4422a3676db4e15d9f01b2b4fac041edab25284fdb9574ba58a0", + sha256 = "34612e3e15e6c31d9d742d3fd677bd5208b7e5c0ee9c93809999138c6c5c1039", strip_prefix = "package", urls = [ "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-%s.tgz" % _ESBUILD_VERSION, diff --git a/packages/esbuild/BUILD.bazel b/packages/esbuild/BUILD.bazel index 214350dbc4..2e511ed724 100644 --- a/packages/esbuild/BUILD.bazel +++ b/packages/esbuild/BUILD.bazel @@ -19,6 +19,8 @@ load("//third_party/github.com/bazelbuild/bazel-skylib:rules/copy_file.bzl", "co package(default_visibility = ["//visibility:public"]) +exports_files(["launcher.js"]) + codeowners( teams = ["@mattem"], ) @@ -67,11 +69,14 @@ pkg_npm( "esbuild.bzl", "helpers.bzl", "index.bzl", + "launcher.js", "package.json", ], - build_file_content = " ", + build_file_content = """exports_files(["launcher.js"]) + """, substitutions = dict({ "@build_bazel_rules_nodejs//packages/esbuild:esbuild.bzl": "//@bazel/esbuild:esbuild.bzl", + "@build_bazel_rules_nodejs//packages/esbuild:launcher.js": "//@bazel/esbuild:launcher.js", }), deps = [ ":npm_version_check", diff --git a/packages/esbuild/_README.md b/packages/esbuild/_README.md index 05e0f6e19e..375dababfe 100644 --- a/packages/esbuild/_README.md +++ b/packages/esbuild/_README.md @@ -18,7 +18,7 @@ yarn add -D @bazel/esbuild Add an `http_archive` fetching the esbuild binary for each platform that you need to support. ```python -_ESBUILD_VERSION = "0.11.5" # reminder: update SHAs below when changing this value +_ESBUILD_VERSION = "0.11.6" # reminder: update SHAs below when changing this value http_archive( name = "esbuild_darwin", urls = [ @@ -26,7 +26,7 @@ http_archive( ], strip_prefix = "package", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "98436890727bdb0d4beddd9c9e07d0aeff0e8dfe0169f85e568eca0dd43f665e", + sha256 = "2b06365b075b854654fc9ed26fcd48a0c38947e1c8d5151ce400cd1e173bb138", ) http_archive( @@ -36,7 +36,7 @@ http_archive( ], strip_prefix = "package", build_file_content = """exports_files(["esbuild.exe"])""", - sha256 = "589c8ff97210bd41de106e6317ce88f9e88d2cacfd8178ae1217f2b857ff6c3a", + sha256 = "ddab1121833f0a12ca4fb3e288231e058f5526310671e84c0a9aa575340bb20b", ) http_archive( @@ -46,7 +46,7 @@ http_archive( ], strip_prefix = "package", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "113c2e84895f4422a3676db4e15d9f01b2b4fac041edab25284fdb9574ba58a0", + sha256 = "34612e3e15e6c31d9d742d3fd677bd5208b7e5c0ee9c93809999138c6c5c1039", ) ``` diff --git a/packages/esbuild/esbuild.bzl b/packages/esbuild/esbuild.bzl index 071915a068..3b1ae063b6 100644 --- a/packages/esbuild/esbuild.bzl +++ b/packages/esbuild/esbuild.bzl @@ -2,7 +2,8 @@ esbuild rule """ -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSModuleInfo", "NpmPackageInfo", "node_modules_aspect") +load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSModuleInfo", "NpmPackageInfo", "node_modules_aspect", "run_node") 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_entry_point", "write_jsconfig_file") @@ -14,10 +15,6 @@ def _esbuild_impl(ctx): # 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: @@ -33,19 +30,12 @@ def _esbuild_impl(ctx): 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) + ctx.files.srcs + deps_inputs @@ -55,6 +45,7 @@ def _esbuild_impl(ctx): entry_point = resolve_entry_point(ctx.file.entry_point, inputs, ctx.files.srcs) args = ctx.actions.args() + args.use_param_file(param_file_arg = "--esbuild_flags=%s", use_always = True) args.add("--bundle", entry_point.path) @@ -125,19 +116,25 @@ def _esbuild_impl(ctx): if "no-remote-exec" in ctx.attr.tags: execution_requirements = {"no-remote-exec": "1"} - ctx.actions.run( + launcher_args = ctx.actions.args() + launcher_args.add("--esbuild=%s" % ctx.executable.tool.path) + + run_node( + ctx = ctx, inputs = depset(inputs), outputs = outputs, - executable = ctx.executable.tool, - arguments = [args], + arguments = [launcher_args, 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, + executable = "launcher", + link_workspace_root = ctx.attr.link_workspace_root, + tools = [ctx.executable.tool], ) return [ - DefaultInfo(files = depset(outputs + [jsconfig_file])), + DefaultInfo(files = depset(outputs)), ] esbuild = rule( @@ -189,6 +186,12 @@ and cjs when platform is node. If performing code splitting, defaults to esm. See https://esbuild.github.io/api/#format for more details """, ), + "launcher": attr.label( + mandatory = True, + executable = True, + doc = "Internal use only", + cfg = "exec", + ), "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.""", @@ -296,10 +299,18 @@ def esbuild_macro(name, output_dir = False, **kwargs): **kwargs: All other args from `esbuild_bundle` """ + kwargs.pop("launcher", None) + _launcher = "_%s_esbuild_launcher" % name + nodejs_binary( + name = _launcher, + entry_point = Label("@build_bazel_rules_nodejs//packages/esbuild:launcher.js"), + ) + if output_dir == True: esbuild( name = name, output_dir = True, + launcher = _launcher, **kwargs ) else: @@ -316,5 +327,6 @@ def esbuild_macro(name, output_dir = False, **kwargs): name = name, output = output, output_map = output_map, + launcher = _launcher, **kwargs ) diff --git a/packages/esbuild/esbuild_repo.bzl b/packages/esbuild/esbuild_repo.bzl index 1bad45a7dc..ab60b5991a 100644 --- a/packages/esbuild/esbuild_repo.bzl +++ b/packages/esbuild/esbuild_repo.bzl @@ -6,7 +6,7 @@ Helper macro for fetching esbuild versions for internal tests and examples in ru load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -_VERSION = "0.11.5" +_VERSION = "0.11.6" def esbuild_dependencies(): """Helper to install required dependencies for the esbuild rules""" @@ -20,7 +20,7 @@ def esbuild_dependencies(): ], strip_prefix = "package", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "98436890727bdb0d4beddd9c9e07d0aeff0e8dfe0169f85e568eca0dd43f665e", + sha256 = "2b06365b075b854654fc9ed26fcd48a0c38947e1c8d5151ce400cd1e173bb138", ) http_archive( name = "esbuild_windows", @@ -29,7 +29,7 @@ def esbuild_dependencies(): ], strip_prefix = "package", build_file_content = """exports_files(["esbuild.exe"])""", - sha256 = "589c8ff97210bd41de106e6317ce88f9e88d2cacfd8178ae1217f2b857ff6c3a", + sha256 = "ddab1121833f0a12ca4fb3e288231e058f5526310671e84c0a9aa575340bb20b", ) http_archive( name = "esbuild_linux", @@ -38,5 +38,5 @@ def esbuild_dependencies(): ], strip_prefix = "package", build_file_content = """exports_files(["bin/esbuild"])""", - sha256 = "113c2e84895f4422a3676db4e15d9f01b2b4fac041edab25284fdb9574ba58a0", + sha256 = "34612e3e15e6c31d9d742d3fd677bd5208b7e5c0ee9c93809999138c6c5c1039", ) diff --git a/packages/esbuild/launcher.js b/packages/esbuild/launcher.js new file mode 100755 index 0000000000..892fd9fa55 --- /dev/null +++ b/packages/esbuild/launcher.js @@ -0,0 +1,25 @@ +const {spawn} = require('child_process'); +const {readFileSync} = require('fs'); + +function getFlag(flag, required = true) { + const argvFlag = process.argv.find(arg => arg.startsWith(`${flag}=`)); + if (required && !argvFlag) { + console.error(`Expected flag '${flag}' passed to launcher, but not found`); + process.exit(1); + } + + return argvFlag.split('=')[1]; +} + +const esbuild = getFlag('--esbuild'); +const params_file_path = getFlag('--esbuild_flags'); + +let flags = []; +try { + flags = readFileSync(params_file_path, {encoding: 'utf8'}).trim().replace(/'/gm, '').split('\n'); +} catch (e) { + console.error('Error while reading esbuild flags param file', e); + process.exit(1); +} + +spawn(esbuild, flags, {detached: true, stdio: 'inherit'}); diff --git a/packages/esbuild/test/vanilla_js/BUILD.bazel b/packages/esbuild/test/vanilla_js/BUILD.bazel index 06e059db6d..664112bfc8 100644 --- a/packages/esbuild/test/vanilla_js/BUILD.bazel +++ b/packages/esbuild/test/vanilla_js/BUILD.bazel @@ -8,6 +8,9 @@ esbuild( "name.js", ], entry_point = "main.js", + deps = [ + "@npm//date-fns", + ], ) nodejs_binary( diff --git a/packages/esbuild/test/vanilla_js/main.js b/packages/esbuild/test/vanilla_js/main.js index f93024a5f4..0bf26e9fe8 100644 --- a/packages/esbuild/test/vanilla_js/main.js +++ b/packages/esbuild/test/vanilla_js/main.js @@ -1,2 +1,5 @@ const NAME = require('./name').NAME; +const {isDate} = require('date-fns'); + +console.log(isDate(NAME)); console.log(NAME); diff --git a/packages/esbuild/test/vanilla_js/output.golden.txt b/packages/esbuild/test/vanilla_js/output.golden.txt index 0c23e83a65..15db08431c 100644 --- a/packages/esbuild/test/vanilla_js/output.golden.txt +++ b/packages/esbuild/test/vanilla_js/output.golden.txt @@ -1 +1,2 @@ +false rules_nodejs