diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000..19b860c --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +6.4.0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5eb0b2f..aaf8b73 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,10 +19,13 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - name: Install bazel - run: tools/install_deps.sh + - name: Mount bazel cache + uses: actions/cache@v3 + with: + path: "~/.cache/bazel" + key: bazel - name: Run tests run: tools/run_tests.sh diff --git a/README.md b/README.md index 3cf460c..665332b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,12 @@ with [Bazel](https://bazel.build). Setup ----- +Make sure Bazel is installed on your system. See the [Bazel +documentation](https://docs.bazel.build/versions/master/install.html) for +platform-specific instructions. We recommend using [Bazelisk]( +https://bazel.build/install/bazelisk.html) to ensure you are using a supported +version. + To use the Dart rules, add the following to your `WORKSPACE` file to add the external repositories for the Dart toolchain: @@ -70,3 +76,9 @@ load("@io_bazel_rules_dart//dart/build_rules:web.bzl", RULE_NAME) `dart_web_application`: Compiles the specified script to JavaScript. `dart_web_test`: Builds a test that will be executed in the browser. + + +Protocol Buffer rules +--------------------- + +`dart_proto_library`: Generates Dart implementations of `.proto` dependencies. diff --git a/WORKSPACE b/WORKSPACE index 9554e52..1e073ea 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -2,3 +2,9 @@ workspace(name = "io_bazel_rules_dart") load("//dart/build_rules:repositories.bzl", "dart_repositories") dart_repositories() + +load("//dart/build_rules:repositories.bzl", "proto_repositories") +proto_repositories() + +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") +protobuf_deps() diff --git a/dart/build_rules/internal.bzl b/dart/build_rules/internal.bzl index 0f581c3..e3eb62d 100644 --- a/dart/build_rules/internal.bzl +++ b/dart/build_rules/internal.bzl @@ -21,238 +21,235 @@ a mechanism for enforcing limitied visibility of Skylark rules. This code makes no gurantees of API stability and is intended solely for use by the Dart rules. """ - _third_party_prefix = "third_party/dart/" - def assert_third_party_licenses(ctx): - """Asserts license attr on non-testonly third-party packages.""" - if (not ctx.attr.testonly - and not ctx.attr.license_files - and ctx.label.package.startswith(_third_party_prefix)): - fail("%s lacks license_files attribute, " % ctx.label + - "required for all non-testonly third-party Dart library rules") - + """Asserts license attr on non-testonly third-party packages.""" + if (not ctx.attr.testonly and + not ctx.attr.license_files and + ctx.label.package.startswith(_third_party_prefix)): + fail("%s lacks license_files attribute, " % ctx.label + + "required for all non-testonly third-party Dart library rules") def collect_files(dart_ctx): - srcs = dart_ctx.srcs - data = dart_ctx.data - for d in dart_ctx.transitive_deps.values(): - srcs = srcs + d.dart.srcs - data = srcs + d.dart.data - return (srcs, data) - + srcs = dart_ctx.srcs + data = dart_ctx.data + for d in dart_ctx.transitive_deps.values(): + srcs = srcs + d.dart.srcs + data = srcs + d.dart.data + return (srcs, data) def _collect_transitive_deps(deps): - """Collects transitive closure of deps. - - Args: - deps: input deps Target collection. All targets must have a 'dart' provider. + """Collects transitive closure of deps. - Returns: - Transitive closure of deps. - """ - transitive_deps = {} - for dep in deps: - transitive_deps.update(dep.dart.transitive_deps) - transitive_deps["%s" % dep.dart.label] = dep - return transitive_deps + Args: + deps: input deps Target collection. All targets must have a 'dart' provider. + Returns: + Transitive closure of deps. + """ + transitive_deps = {} + for dep in deps: + transitive_deps.update(dep.dart.transitive_deps) + transitive_deps["%s" % dep.dart.label] = dep + return transitive_deps def _label_to_dart_package_name(label): - """Returns the Dart package name for the specified label. - - Packages under //third_party/dart resolve to their external Pub package names. - All other packages resolve to a unique identifier based on their repo path. - - Examples: - //foo/bar/baz: foo.bar.baz - //third_party/dart/args: args - //third_party/guice: third_party.guice - - Restrictions: - Since packages outside of //third_party/dart are identified by their path - components joined by periods, it is an error for the label package to - contain periods. - - Args: - label: the label whose package name is to be returned. - - Returns: - The Dart package name associated with the label. - """ - package_name = label.package - if label.package.startswith(_third_party_prefix): - third_party_path = label.package[len(_third_party_prefix):] - if "/" not in third_party_path: - package_name = third_party_path - if "." in package_name: - fail("Dart package paths may not contain '.': " + label.package) - return package_name.replace("/", ".") - - -def _new_dart_context(label, - package, - lib_root, - srcs=None, - data=None, - deps=None, - transitive_deps=None): - return struct( - label=label, - package=package, - lib_root=lib_root, - srcs=srcs or [], - data=data or [], - deps=deps or [], - transitive_deps=dict(transitive_deps or {}), - ) - - -def make_dart_context(label, - package=None, - lib_root=None, - srcs=None, - data=None, - deps=None): - if not package: - package = _label_to_dart_package_name(label) - if not lib_root: - lib_root = "%s/lib/" % label.package - srcs = srcs or [] - data = data or [] - deps = deps or [] - transitive_deps = _collect_transitive_deps(deps) - return struct( - label=label, - package=package, - lib_root=lib_root, - srcs=srcs, - data=data, - deps=deps, - transitive_deps=transitive_deps, - ) - + """Returns the Dart package name for the specified label. + + Packages under //third_party/dart resolve to their external Pub package names. + All other packages resolve to a unique identifier based on their repo path. + + Examples: + //foo/bar/baz: foo.bar.baz + //third_party/dart/args: args + //third_party/guice: third_party.guice + + Restrictions: + Since packages outside of //third_party/dart are identified by their path + components joined by periods, it is an error for the label package to + contain periods. + + Args: + label: the label whose package name is to be returned. + + Returns: + The Dart package name associated with the label. + """ + package_name = label.package + if label.package.startswith(_third_party_prefix): + third_party_path = label.package[len(_third_party_prefix):] + if "/" not in third_party_path: + package_name = third_party_path + if "." in package_name: + fail("Dart package paths may not contain '.': " + label.package) + return package_name.replace("/", ".") + +def _new_dart_context( + label, + package, + lib_root, + srcs = None, + data = None, + deps = None, + transitive_deps = None): + return struct( + label = label, + package = package, + lib_root = lib_root, + srcs = srcs or [], + data = data or [], + deps = deps or [], + transitive_deps = dict(transitive_deps or {}), + ) + +def make_dart_context( + label, + package = None, + lib_root = None, + srcs = None, + data = None, + deps = None): + if not package: + package = _label_to_dart_package_name(label) + if not lib_root: + lib_root = "%s/lib/" % label.package + srcs = srcs or [] + data = data or [] + deps = deps or [] + transitive_deps = _collect_transitive_deps(deps) + return struct( + label = label, + package = package, + lib_root = lib_root, + srcs = srcs, + data = data, + deps = deps, + transitive_deps = transitive_deps, + ) def _merge_dart_context(dart_ctx1, dart_ctx2): - """Merges two dart contexts whose package and lib_root must be identical.""" - if dart_ctx1.package != dart_ctx2.package: - fail("Incompatible packages: %s and %s" % (dart_ctx1.package, - dart_ctx2.package)) - if dart_ctx1.lib_root != dart_ctx2.lib_root: - fail("Incompatible lib_roots for package %s:\n" % dart_ctx1.package + - " %s declares: %s\n" % (dart_ctx1.label, dart_ctx1.lib_root) + - " %s declares: %s\n" % (dart_ctx2.label, dart_ctx2.lib_root) + - "Targets in the same package must declare the same lib_root") - - transitive_deps = {} - transitive_deps.update(dart_ctx1.transitive_deps) - transitive_deps.update(dart_ctx2.transitive_deps) - return _new_dart_context( - label=dart_ctx1.label, - package=dart_ctx1.package, - lib_root=dart_ctx1.lib_root, - srcs=dart_ctx1.srcs + dart_ctx2.srcs, - data=dart_ctx1.data + dart_ctx2.data, - deps=dart_ctx1.deps + dart_ctx2.deps, - transitive_deps=transitive_deps, - ) - - -def _collect_dart_context(dart_ctx, transitive=True, include_self=True): - """Collects and returns dart contexts.""" - # Collect direct or transitive deps. - dart_ctxs = [dart_ctx] - if transitive: - dart_ctxs += [d.dart for d in dart_ctx.transitive_deps.values()] - else: - dart_ctxs += [d.dart for d in dart_ctx.deps] - - # Optionally, exclude all self-packages. - if not include_self: - dart_ctxs = [c for c in dart_ctxs if c.package != dart_ctx.package] - - # Merge Dart context by package. - ctx_map = {} - for dc in dart_ctxs: - if dc.package in ctx_map: - dc = _merge_dart_context(ctx_map[dc.package], dc) - ctx_map[dc.package] = dc - return ctx_map - + """Merges two dart contexts whose package and lib_root must be identical.""" + if dart_ctx1.package != dart_ctx2.package: + fail("Incompatible packages: %s and %s" % ( + dart_ctx1.package, + dart_ctx2.package, + )) + if dart_ctx1.lib_root != dart_ctx2.lib_root: + fail("Incompatible lib_roots for package %s:\n" % dart_ctx1.package + + " %s declares: %s\n" % (dart_ctx1.label, dart_ctx1.lib_root) + + " %s declares: %s\n" % (dart_ctx2.label, dart_ctx2.lib_root) + + "Targets in the same package must declare the same lib_root") + + transitive_deps = {} + transitive_deps.update(dart_ctx1.transitive_deps) + transitive_deps.update(dart_ctx2.transitive_deps) + return _new_dart_context( + label = dart_ctx1.label, + package = dart_ctx1.package, + lib_root = dart_ctx1.lib_root, + srcs = dart_ctx1.srcs + dart_ctx2.srcs, + data = dart_ctx1.data + dart_ctx2.data, + deps = dart_ctx1.deps + dart_ctx2.deps, + transitive_deps = transitive_deps, + ) + +def collect_dart_context(dart_ctx, transitive = True, include_self = True): + """Collects and returns dart contexts.""" + + # Collect direct or transitive deps. + dart_ctxs = [dart_ctx] + if transitive: + dart_ctxs += [d.dart for d in dart_ctx.transitive_deps.values()] + else: + dart_ctxs += [d.dart for d in dart_ctx.deps] + + # Optionally, exclude all self-packages. + if not include_self: + dart_ctxs = [c for c in dart_ctxs if c.package != dart_ctx.package] + + # Merge Dart context by package. + ctx_map = {} + for dc in dart_ctxs: + if dc.package in ctx_map: + dc = _merge_dart_context(ctx_map[dc.package], dc) + ctx_map[dc.package] = dc + return ctx_map def package_spec_action(ctx, dart_ctx, output): - """Creates an action that generates a Dart package spec. - - Arguments: - ctx: The rule context. - dart_ctx: The Dart context. - output: The output package_spec file. - """ - # There's a 1-to-many relationship between packages and targets, but - # collect_transitive_packages() asserts that their lib_roots are the same. - dart_ctxs = _collect_dart_context(dart_ctx, - transitive=True, - include_self=True).values() - - # Generate the content. - content = "# Generated by Bazel\n" - for dc in dart_ctxs: - relative_lib_root = _relative_path(dart_ctx.label.package, dc.lib_root) - content += "%s:%s\n" % (dc.package, relative_lib_root) - - # Emit the package spec. - ctx.actions.write( - output=output, - content=content, - ) - + """Creates an action that generates a Dart package spec. + + Arguments: + ctx: The rule context. + dart_ctx: The Dart context. + output: The output package_spec file. + """ + + # There's a 1-to-many relationship between packages and targets, but + # collect_transitive_packages() asserts that their lib_roots are the same. + dart_ctxs = collect_dart_context( + dart_ctx, + transitive = True, + include_self = True, + ).values() + + # Generate the content. + content = "# Generated by Bazel\n" + for dc in dart_ctxs: + relative_lib_root = _relative_path(dart_ctx.label.package, dc.lib_root) + content += "%s:%s\n" % (dc.package, relative_lib_root) + + # Emit the package spec. + ctx.actions.write( + output = output, + content = content, + ) def _relative_path(from_dir, to_path): - """Returns the relative path from a directory to a path via the repo root.""" - return "../" * (from_dir.count("/") + 1) + to_path - + """Returns the relative path from a directory to a path via the repo root.""" + return "../" * (from_dir.count("/") + 1) + to_path def layout_action(ctx, srcs, output_dir): - """Generates a flattened directory of sources. - - For each file f in srcs, a file is emitted at output_dir/f.short_path. - Returns a dict mapping short_path to the emitted file. - - Args: - ctx: the build context. - srcs: the set of input srcs to be flattened. - output_dir: the full output directory path into which the files are emitted. - - Returns: - A map from input file short_path to File in output_dir. - """ - commands = [] - output_files = {} - # TODO(cbracken) extract next two lines to func - if not output_dir.endswith("/"): - output_dir += "/" - for src_file in srcs: - dest_file = ctx.actions.declare_file(output_dir + src_file.short_path) - dest_dir = dest_file.path[:dest_file.path.rfind("/")] - link_target = _relative_path(dest_dir, src_file.path) - commands += ["ln -s '%s' '%s'" % (link_target, dest_file.path)] - output_files[src_file.short_path] = dest_file - - # Emit layout script. - layout_cmd = ctx.actions.declare_file(ctx.label.name + "_layout.sh") - ctx.actions.write( - output=layout_cmd, - content="#!/bin/bash\n" + "\n".join(commands), - is_executable=True, - ) - - # Invoke the layout action. - ctx.actions.run( - inputs=list(srcs), - outputs=output_files.values(), - executable=layout_cmd, - progress_message="Building flattened source layout for %s" % ctx, - mnemonic="DartLayout", - ) - return output_files + """Generates a flattened directory of sources. + + For each file f in srcs, a file is emitted at output_dir/f.short_path. + Returns a dict mapping short_path to the emitted file. + + Args: + ctx: the build context. + srcs: the set of input srcs to be flattened. + output_dir: the full output directory path into which the files are emitted. + + Returns: + A map from input file short_path to File in output_dir. + """ + commands = [] + output_files = {} + + # TODO(cbracken) extract next two lines to func + if not output_dir.endswith("/"): + output_dir += "/" + for src_file in srcs: + dest_file = ctx.actions.declare_file(output_dir + src_file.short_path) + dest_dir = dest_file.path[:dest_file.path.rfind("/")] + link_target = _relative_path(dest_dir, src_file.path) + commands += ["ln -s '%s' '%s'" % (link_target, dest_file.path)] + output_files[src_file.short_path] = dest_file + + # Emit layout script. + layout_cmd = ctx.actions.declare_file(ctx.label.name + "_layout.sh") + ctx.actions.write( + output = layout_cmd, + content = "#!/bin/bash\n" + "\n".join(commands), + is_executable = True, + ) + + # Invoke the layout action. + ctx.actions.run( + inputs = list(srcs), + outputs = output_files.values(), + executable = layout_cmd, + progress_message = "Building flattened source layout for %s" % ctx, + mnemonic = "DartLayout", + ) + return output_files diff --git a/dart/build_rules/proto.bzl b/dart/build_rules/proto.bzl new file mode 100644 index 0000000..9644e40 --- /dev/null +++ b/dart/build_rules/proto.bzl @@ -0,0 +1,131 @@ +# Copyright 2016 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. + +"""Dart rules for protocol buffers""" + +load("//dart/build_rules:internal.bzl", "make_dart_context", "collect_dart_context") +load("@rules_proto//proto:defs.bzl", "ProtoInfo") + +def _generate_protoc_config(dart_ctx): + dart_ctxs = collect_dart_context(dart_ctx, + transitive=True, + include_self=True).values() + + entries = [] + for dc in dart_ctxs: + entries += ["|".join([dc.package, dc.label.package, dc.lib_root])] + return "BazelPackages=" + ";".join(entries) + + +def protoc_gen_action(ctx, + dart_ctx, + direct_sources, + transitive_sources, + outputs): + cmd_inputs, _, cmd_input_manifests = ctx.resolve_command(tools=[ctx.attr._protoc_gen_dart]) + + # Protoc arguments. + inputs = cmd_inputs + transitive_sources.to_list() + plugin = "protoc-gen-dart=" + ctx.executable._protoc_gen_dart.path + bazel_options = _generate_protoc_config(dart_ctx) + genfiles_path = ctx.configuration.genfiles_dir.path + ctx.actions.run( + inputs=inputs, + outputs=outputs, + executable=ctx.executable._protocol_compiler, + arguments=[ + "--plugin=" + plugin, + "--dart_out=" + bazel_options + ":" + genfiles_path, + ] + [s.path for s in direct_sources], + progress_message="Generating Dart proto files %s" % ctx, + mnemonic="DartProtoGen", + input_manifests=cmd_input_manifests, + ) + + +def _dart_proto_aspect_impl(target, ctx): + # Compute the generated outputs. + direct_sources = target[ProtoInfo].direct_sources + generated_outputs = [] + for s in direct_sources: + gen_path = "lib/" + s.basename[:-len(".proto")] + ".pb.dart" + out_file = ctx.actions.declare_file(gen_path) + generated_outputs += [out_file] + + # Create the package. + dart_ctx = make_dart_context( + label = target.label, + srcs = generated_outputs, + data = ctx.rule.attr.data, + deps = ctx.rule.attr.deps + ctx.attr._proto_libs_dart, + ) + + # Generate the Dart outputs. + protoc_gen_action(ctx, + dart_ctx, + direct_sources, + target[ProtoInfo].transitive_sources, + generated_outputs) + + return struct( + dart=dart_ctx, + ) + + +_dart_proto_aspect_attrs = { + "_protocol_compiler": attr.label( + executable=True, + cfg="host", + default=Label("@com_google_protobuf//:protoc"), + ), + "_protoc_gen_dart": attr.label( + # TODO: FIX + default=Label( + "@dart_protobuf_protoc_plugin//:protoc_gen_dart"), + executable=True, + cfg="host", + ), + "_proto_libs_dart": attr.label_list(default=[ + Label("@dart_fixnum//:fixnum_lib"), + Label("@dart_protobuf_protobuf//:protobuf_lib"), + ]) +} + + +dart_proto_aspect = aspect( + implementation=_dart_proto_aspect_impl, + attr_aspects=["deps"], + attrs=_dart_proto_aspect_attrs, +) + + +def _dart_proto_library_impl(ctx): + dart_ctx = make_dart_context(ctx.label, deps=ctx.attr.deps) + return struct( + dart=dart_ctx, + ) + + +_dart_proto_library_attrs = { + "deps": attr.label_list( + providers=[ProtoInfo], + aspects=[dart_proto_aspect], + ), +} + + +dart_proto_library = rule( + implementation=_dart_proto_library_impl, + attrs=_dart_proto_library_attrs, +) diff --git a/dart/build_rules/repositories.bzl b/dart/build_rules/repositories.bzl index 3c7c338..4fd8292 100644 --- a/dart/build_rules/repositories.bzl +++ b/dart/build_rules/repositories.bzl @@ -14,6 +14,8 @@ """Repositories for Dart.""" +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository") + load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") @@ -85,3 +87,86 @@ def dart_repositories(): sha256 = macos_x64_sha, build_file_content = _DART_SDK_BUILD_FILE, ) + + +_FIXNUM_BUILD_FILE = """ +load("@//dart/build_rules:core.bzl", "dart_library") +load("@//dart/build_rules:vm.bzl", "dart_vm_test") + +package(default_visibility = ["//visibility:public"]) + +dart_library( + name = "fixnum_lib", + srcs = glob(["lib/**/*.dart"]), +) +""" + +_PROTOBUF_BUILD_FILE = """ +load("@//dart/build_rules:core.bzl", "dart_library") +load("@//dart/build_rules:vm.bzl", "dart_vm_binary") + +package(default_visibility = ["//visibility:public"]) + +dart_library( + name = "protobuf_lib", + srcs = glob(["lib/**/*.dart"]), +) +""" + +_PROTOC_PLUGIN_BUILD_FILE = """ +load("@//dart/build_rules:core.bzl", "dart_library") +load("@//dart/build_rules:vm.bzl", "dart_vm_binary") + +package(default_visibility = ["//visibility:public"]) + +dart_library( + name = "protoc_plugin_lib", + srcs = glob(["lib/**/*.dart"]), +) + +dart_vm_binary( + name = "protoc_gen_dart", + srcs = ["bin/protoc_plugin.dart"], + script_file = "bin/protoc_plugin.dart", + deps = [":protoc_plugin_lib"], +) +""" + +def proto_repositories(): + + new_git_repository( + name = "dart_fixnum", + # tag = "1.0.0", + commit = "762b74f61696d414d0090c5dfc430572f5b4be0f", + shallow_since = "1612551835 -0800", + remote = "https://github.com/dart-lang/fixnum", + build_file_content = _FIXNUM_BUILD_FILE + ) + + new_git_repository( + name = "dart_protobuf_protobuf", + # tag = "protobuf-v2.0.1", + commit = "23136dc01cf3daccf66ebb7f5a7578ec7c0dc7e6", + shallow_since = "1638456183 +0100", + remote = "https://github.com/google/protobuf.dart", + build_file_content = _PROTOBUF_BUILD_FILE, + strip_prefix = "protobuf" + ) + + new_git_repository( + name = "dart_protobuf_protoc_plugin", + # tag = "protobuf-v2.0.1", + commit = "23136dc01cf3daccf66ebb7f5a7578ec7c0dc7e6", + shallow_since = "1638456183 +0100", + remote = "https://github.com/google/protobuf.dart", + build_file_content = _PROTOC_PLUGIN_BUILD_FILE, + strip_prefix = "protoc_plugin" + ) + + git_repository( + name = "com_google_protobuf", + # tag = "v3.19.1", + commit = "7c40b2df1fdf6f414c1c18c789715a9c948a0725", + shallow_since = "1635455273 -0700", + remote = "https://github.com/protocolbuffers/protobuf", + ) diff --git a/examples/proto_bin/BUILD b/examples/proto_bin/BUILD new file mode 100644 index 0000000..f27acdb --- /dev/null +++ b/examples/proto_bin/BUILD @@ -0,0 +1,25 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("//dart/build_rules:proto.bzl", "dart_proto_library") +load("//dart/build_rules:vm.bzl", "dart_vm_binary") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "review_proto", + srcs = ["review.proto"], + deps = [ + "//examples/proto_lib:person_proto", + ], +) + +dart_proto_library( + name = "review_proto_dart", + deps = [":review_proto"], +) + +dart_vm_binary( + name = "proto_bin", + srcs = ["bin/hello_proto.dart"], + script_file = "bin/hello_proto.dart", + deps = [":review_proto_dart"], +) diff --git a/examples/proto_bin/bin/hello_proto.dart b/examples/proto_bin/bin/hello_proto.dart new file mode 100644 index 0000000..69e519c --- /dev/null +++ b/examples/proto_bin/bin/hello_proto.dart @@ -0,0 +1,34 @@ +import 'package:examples.proto_lib/device.pb.dart'; +import 'package:examples.proto_lib/person.pb.dart'; +import 'package:examples.proto_bin/review.pb.dart'; + +String format(Review review) { + var date = new DateTime.fromMillisecondsSinceEpoch(review.date); + + var buf = new StringBuffer(); + buf.writeln('Review of ${review.device.brand} ${review.device.model}'); + buf.writeln('by ${review.person.firstname} ${review.person.lastname}, $date'); + buf.writeln('\n${review.text}'); + return buf.toString(); +} + +Review fetchReview() { + var fred = new Person() + ..firstname = 'Fred' + ..lastname = 'Fhqwhgads'; + var motoX = new Device() + ..brand = 'Motorola' + ..model = 'Moto X'; + var review = new Review() + ..person = fred + ..device = motoX + ..date = new DateTime(2016, 01, 31).millisecondsSinceEpoch + ..text = 'Hello, proto!'; + return review; +} + +main() { + var review = fetchReview(); + var displayText = format(review); + print(displayText); +} diff --git a/examples/proto_bin/review.proto b/examples/proto_bin/review.proto new file mode 100644 index 0000000..edb6d1f --- /dev/null +++ b/examples/proto_bin/review.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; + +import 'examples/proto_lib/person.proto'; +import 'examples/proto_lib/device.proto'; + +package ex; + +message Review { + required ex.Person person = 1; + required ex.Device device = 2; + required int64 date = 3; + required string text = 4; +} diff --git a/examples/proto_lib/BUILD b/examples/proto_lib/BUILD new file mode 100644 index 0000000..83ac6f1 --- /dev/null +++ b/examples/proto_lib/BUILD @@ -0,0 +1,11 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "person_proto", + srcs = [ + "person.proto", + "device.proto", + ], +) diff --git a/examples/proto_lib/device.proto b/examples/proto_lib/device.proto new file mode 100644 index 0000000..eb23752 --- /dev/null +++ b/examples/proto_lib/device.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package ex; + +message Device { + required string brand = 1; + required string model = 2; +} + diff --git a/examples/proto_lib/person.proto b/examples/proto_lib/person.proto new file mode 100644 index 0000000..9afcfdd --- /dev/null +++ b/examples/proto_lib/person.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; + +package ex; + +message Person { + required string firstname = 1; + required string lastname = 2; +} diff --git a/tools/install_deps.sh b/tools/install_deps.sh deleted file mode 100755 index 2ff7f21..0000000 --- a/tools/install_deps.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -BAZEL_VERSION=4.0.0 - -linux_install() { - echo "============================================================" - echo "Installing Bazel $BAZEL_VERSION on Linux" - echo "============================================================" - - sudo apt -y update - sudo apt -y install apt-transport-https curl gnupg - curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg - sudo mv bazel.gpg /etc/apt/trusted.gpg.d/ - echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list - sudo apt update - sudo apt -y install bazel-$BAZEL_VERSION - exit 0 -} - -macos_install() { - echo "============================================================" - echo "Installing Bazel $BAZEL_VERSION on macOS" - echo "============================================================" - - curl -fLO "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh" - chmod +x "bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh" - sudo ./bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh - exit 0 -} - -# Main entry point. -case "`uname -s`" in - Linux*) linux_install;; - Darwin*) macos_install;; -esac - -echo "ERROR: unknown operating system" -exit 1