Skip to content

Commit

Permalink
Add support for $(location) in nodejs_binary#entry_point
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeagle authored and rzhw committed Feb 12, 2018
1 parent 4905590 commit afe2c85
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ nodejs_binary(
"@//:node_modules",
"main.js",
],
entry_point = "workspace_name/main.js",
entry_point = "$(location :main.js)",
args = ["--node_options=--expose-gc"],
)
```
Expand Down
60 changes: 52 additions & 8 deletions examples/program/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test", "nodejs_binary")
load("@build_bazel_rules_nodejs//:internal/typescript_mock.bzl", "mock_typescript_lib")

# Make the jasmine library available at runtime by exposing our node_modules
Expand All @@ -13,21 +27,51 @@ filegroup(
visibility = ["//visibility:public"],
)

# Mock out the ts_library rule from rules_typescript
# We want to test that TypeScript outputs can be used in nodejs rules, but
# don't want a cyclical dependency between this repository and rules_typescript.
mock_typescript_lib(
name = "mock_ts_lib",
srcs = ["decrement.js"],
)

# This is like a "js_library", but there are no actions to run on JS files so a
# filegroup is semantically equivalent.
filegroup(
name = "program",
srcs = ["index.js"],
# This binary wraps up our program in a way that can be `bazel run`, and also
# produces a .exe file on Windows.
nodejs_binary(
name = "bin",
# The script we'll ask node to run
# Note: the label given here must exactly match an entry in "data"
entry_point = "$(location :index.js)",
# Runtime dependencies, in our case the script is standalone.
data = [":index.js"],
# Only needed because we'll typically run this binary from the workspace
# in the parent directory. The default value for `node_modules` is
# @//:node_modules, where the leading @ means "the workspace where the user
# runs the target"
node_modules = "//:node_modules",
)

# Unit tests for the files in the package.
# Convenient to use with `ibazel test`
jasmine_node_test(
name = "test",
# The typical Bazel idiom is for srcs to be the files directly consumed.
# In the case of a unit test, that's the spec files.
# See https://docs.bazel.build/versions/master/build-ref.html#types_of_dependencies
srcs = glob(["*.spec.js"]),
deps = [":program", ":mock_ts_lib"],
node_modules = "//:node_modules"
# The deps is the runtime dependencies. These can point to compiled files
# such as the TypeScript library we mocked out.
deps = [":index.js", ":mock_ts_lib"],
# See comment about node_modules above.
node_modules = "//:node_modules",
)

# An end-to-end test for the program.
# It's written in Python just because this is convenient and cross-platform.
# See https://docs.bazel.build/versions/master/be/python.html#py_test
py_test(
name = "bin_test",
srcs = ["bin_test.py"],
deps = ["@build_bazel_rules_nodejs//internal:runfiles"],
data = [":bin"],
)
23 changes: 23 additions & 0 deletions examples/program/bin_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""End-to-end test for a nodejs_binary
Simply find the binary and run it, asserting that it produces correct output.
"""

from subprocess import check_output
from sys import platform
import unittest

from build_bazel_rules_nodejs.internal.runfiles import resolve_runfile

class BinTest(unittest.TestCase):

def testRuns(self):
if platform == "win32" or platform == "win64":
program = 'program_example/bin.exe'
else:
program = 'program_example/bin'
actual = check_output([resolve_runfile(program)])
self.assertEqual(actual, '2\n')

if __name__ == '__main__':
unittest.main()
4 changes: 4 additions & 0 deletions examples/program/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ function increment(n) {
}

exports.increment = increment;

if (require.main === module) {
console.log(increment(1));
}
6 changes: 6 additions & 0 deletions internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ package(default_visibility = ["//visibility:public"])

exports_files(["node_launcher.sh", "node_loader.js", "jasmine_runner.js"])

py_library(
name = "runfiles",
srcs = ["runfiles.py"],
)

py_test(
name = "check_bazel_version_test",
srcs = ["check_bazel_version_test.py"],
deps = [":runfiles"],
data = [":check_bazel_version.bzl"],
size = "small",
)
14 changes: 1 addition & 13 deletions internal/check_bazel_version_test.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import os
import unittest

def resolve_runfile(path):
if os.getenv('RUNFILES_MANIFEST_ONLY') != "1":
return os.path.join(os.environ['TEST_SRCDIR'], path)

manifest = os.getenv('RUNFILES_MANIFEST_FILE')
with open(manifest) as f:
for line in f.readlines():
if line.split()[0] == path:
return line.split()[1]
raise "Cannot find %s in manifest %s" % (path, manifest)

from runfiles import resolve_runfile

class MockSkylark:
"""A class that returns mocked bazel version and fail().
Expand Down
11 changes: 6 additions & 5 deletions internal/jasmine_node_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ def jasmine_node_test(name, srcs = [], data = [], deps = [], **kwargs):
testonly = 1,
)

all_data = data + srcs + deps
all_data += [Label("//internal:jasmine_runner.js")]
all_data += [":%s_devmode_srcs.MF" % name]
entry_point = "build_bazel_rules_nodejs/internal/jasmine_runner.js"
runner_js = "@build_bazel_rules_nodejs//internal:jasmine_runner.js"
all_data = data + srcs + deps + [
runner_js,
":%s_devmode_srcs.MF" % name,
]

nodejs_test(
name = name,
data = all_data,
entry_point = entry_point,
entry_point = "$(location %s)" % runner_js,
templated_args = ["$(location :%s_devmode_srcs.MF)" % name],
testonly = 1,
**kwargs
Expand Down
2 changes: 1 addition & 1 deletion internal/node.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def _write_loader_script(ctx):
"TEMPLATED_module_roots": "\n " + ",\n ".join(module_mappings),
"TEMPLATED_bootstrap": "\n " + ",\n ".join(
["\"" + d + "\"" for d in ctx.attr.bootstrap]),
"TEMPLATED_entry_point": ctx.attr.entry_point,
"TEMPLATED_entry_point": expand_location_into_runfiles(ctx, ctx.attr.entry_point),
"TEMPLATED_label_package": ctx.attr.node_modules.label.package,
# There are two workspaces in general:
# A) The user's workspace is the one where the bazel command is run
Expand Down
12 changes: 12 additions & 0 deletions internal/runfiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import os

def resolve_runfile(path):
if os.getenv('RUNFILES_MANIFEST_ONLY') != "1":
return os.path.join(os.environ['TEST_SRCDIR'], path)

manifest = os.getenv('RUNFILES_MANIFEST_FILE')
with open(manifest) as f:
for line in f.readlines():
if line.split()[0] == path:
return line.split()[1]
raise "Cannot find %s in manifest %s" % (path, manifest)

0 comments on commit afe2c85

Please sign in to comment.