Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Custom Bazel rule #84

Merged
merged 6 commits into from
Jun 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
package(default_visibility = ["//visibility:public"])


exports_files(["tsconfig.json"])

filegroup(
name = "generate_ts",
srcs = [
"//proto:generate",
"//proto/examplecom:generate",
"//proto/othercom:generate",
],
)
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ also output service definitions as both `.js` and `.d.ts` files in the structure
This plugin is tested and written using TypeScript 2.7.

## Installation

### npm
As a prerequisite, download or install `protoc` (the protocol buffer compiler) for your platform from the [github releases page](https://github.com/google/protobuf/releases) or via a package manager (ie: [brew](http://brewformulas.org/Protobuf), [apt](https://www.ubuntuupdates.org/pm/protobuf-compiler)).

For the latest stable version of the ts-protoc-gen plugin:
Expand All @@ -26,6 +28,74 @@ For our latest build straight from master:
```bash
npm install ts-protoc-gen@next
```
### bazel
Include the following in your `WORKSPACE`:
```python
git_repository(
name = "io_bazel_rules_go",
commit = "6bee898391a42971289a7989c0f459ab5a4a84dd", # master as of May 10th, 2018
remote = "https://github.com/bazelbuild/rules_go.git",
)
load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains()

http_archive(
name = "io_bazel_rules_webtesting",
strip_prefix = "rules_webtesting-master",
urls = [
"https://github.com/bazelbuild/rules_webtesting/archive/master.tar.gz",
],
)
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
web_test_repositories()

git_repository(
name = "build_bazel_rules_nodejs",
remote = "https://github.com/bazelbuild/rules_nodejs.git",
commit = "d334fd8e2274fb939cf447106dced97472534e80",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(package_json = ["//:package.json"])

load("@ts_protoc_gen//:defs.bzl", "typescript_proto_dependencies")
typescript_proto_dependencies()

git_repository(
name = "build_bazel_rules_typescript",
remote = "https://github.com/bazelbuild/rules_typescript.git",
commit = "3488d4fb89c6a02d79875d217d1029182fbcd797",
)
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
ts_setup_workspace()
```

Now in your `BUILD.bazel`:
```python
load("@ts_protoc_gen//:defs.bzl", "typescript_proto_library")

filegroup(
name = "proto_files",
srcs = glob(["*.proto"]),
)

proto_library(
name = "proto",
srcs = [
":proto_files",
],
)

typescript_proto_library(
name = "generate",
proto = ":proto",
)

typescript_proto_library(
name = "generate",
proto = ":proto",
)
```

## Contributing
Contributions are welcome! Please refer to [CONTRIBUTING.md](https://github.com/improbable-eng/ts-protoc-gen/blob/master/CONTRIBUTING.md) for more information.
Expand Down
18 changes: 7 additions & 11 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,25 @@ http_archive(
urls = [
"https://github.com/bazelbuild/rules_webtesting/archive/master.tar.gz",
],
)
)
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
web_test_repositories()

git_repository(
name = "build_bazel_rules_nodejs",
remote = "https://github.com/bazelbuild/rules_nodejs.git",
tag = "0.9.1",
commit = "d334fd8e2274fb939cf447106dced97472534e80",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "npm_install")
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(package_json = ["//:package.json"])

# installs our node_modules
npm_install(
name = "deps",
package_json = "//:package.json",
package_lock_json = "//:package-lock.json",
)
load("@ts_protoc_gen//:defs.bzl", "typescript_proto_dependencies")
typescript_proto_dependencies()

git_repository(
name = "build_bazel_rules_typescript",
remote = "https://github.com/bazelbuild/rules_typescript.git",
tag = "0.14.0",
)
commit = "3488d4fb89c6a02d79875d217d1029182fbcd797",
)
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
ts_setup_workspace()
121 changes: 121 additions & 0 deletions defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
load("@build_bazel_rules_nodejs//:defs.bzl", "npm_install")


def declare_file(ctx, filename, file_modifications):
f = ctx.actions.declare_file(filename)

# Removes an import that protoc-gen-ts adds that is not needed
for removal in ctx.attr.remove_dependencies:
file_modifications.append("echo \"$(grep -v \"%s\" %s)\" > %s" % (removal, f.path, f.path))

return f

def proto_path(proto):
"""
The proto path is not really a file path
It's the path to the proto that was seen when the descriptor file was generated.
"""
path = proto.path
root = proto.root.path
ws = proto.owner.workspace_root
if path.startswith(root): path = path[len(root):]
if path.startswith("/"): path = path[1:]
if path.startswith(ws): path = path[len(ws):]
if path.startswith("/"): path = path[1:]
return path

def append_to_outputs(ctx, file_name, outputs, file_modifications):
generated_filenames = ["_pb.d.ts", "_pb.js", "_pb_service.js", "_pb_service.d.ts"]

for f in generated_filenames:
outputs.append(declare_file(ctx, file_name + f, file_modifications))

def _typescript_proto_library_impl(ctx):
outputs = []
proto_inputs = []
file_modifications = []

for src in ctx.attr.proto.proto.direct_sources:
if src.extension != "proto":
fail("Input must be a proto file")

file_name = src.basename[:-len(src.extension) - 1]
normalized_file = proto_path(src)
proto_inputs.append(normalized_file)
append_to_outputs(ctx, file_name, outputs, file_modifications)

if not file_modifications:
file_modifications.append("echo \"No services generated\"")

inputs = depset([ctx.file._protoc])
inputs += ctx.files._ts_protoc_gen
inputs += ctx.attr.proto.proto.transitive_descriptor_sets

descriptor_sets = [desc.path for desc in ctx.attr.proto.proto.transitive_descriptor_sets]

ts_out = "service=true:"

protoc_command = "%s --plugin=protoc-gen-ts=%s --ts_out=%s%s --js_out=import_style=commonjs,binary:%s --descriptor_set_in=%s %s" % (ctx.file._protoc.path, ctx.files._ts_protoc_gen[1].path, ts_out, ctx.var["BINDIR"], ctx.var["BINDIR"], ":".join(descriptor_sets), " ".join(proto_inputs))

ctx.actions.run_shell(
inputs = inputs,
outputs = outputs,
progress_message = "Creating Typescript pb files %s" % ctx.label,
command = "%s && %s" % (protoc_command, " && ".join(file_modifications)),
)

if ctx.attr.debug:
print("protoc command: ", protoc_command)
print("service file modification: ", file_modifications)
print("ctx.var['BINDIR']: ", ctx.var["BINDIR"])
print("normalized_file: ", normalized_file)

return DefaultInfo(
files = depset(outputs),
)

typescript_proto_library = rule(
attrs = {
"proto": attr.label(
mandatory = True,
allow_files = True,
single_file = True,
providers = ["proto"],
),
"remove_dependencies": attr.string_list(
doc = "Each string given will be grepped and removed from the generated files. This can be useful if your proto files are importing a dependency that the generated Typescript does not use.",
default = [],
allow_empty = True,
),
"debug": attr.bool(
doc="Set for additional logging",
mandatory = False,
default = False,
),
"_ts_protoc_gen": attr.label(
allow_files = True,
executable = True,
cfg = "host",
default = Label("@ts_protoc_gen//bin:protoc-gen-ts"),
),
"_protoc": attr.label(
allow_files = True,
single_file = True,
executable = True,
cfg = "host",
default = Label("@com_google_protobuf//:protoc"),
),
},
implementation = _typescript_proto_library_impl,
)

def typescript_proto_dependencies():
"""To be run in user's WORKSPACE to install ts-protoc-gen dependencies.
"""

npm_install(
name = "deps",
package_json = "@ts_protoc_gen//:package.json",
package_lock_json = "@ts_protoc_gen//:package-lock.json",
)
77 changes: 0 additions & 77 deletions examples/generated/examplecom/simple_service_pb_service.d.ts

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading