protocol-buffersbazelbazel-rulesbazel-cppbazel-protobuf

How to reference bazel c++ protobuf output headers in a different workspace/package


I just started using Bazel a couple days ago in hopes of something better than CMake. I have a small library that contains only protobuf definitions in its own repository. I've gotten bazel building the proto types and see them in the bazel-bin/proto directory, but am unsure of how to proceed to make this directory an include in dependent workspaces/packages so that I can utilize the output header files?

proto-repo: BUILD

load("@rules_cc//cc:defs.bzl", "cc_proto_library")
load("@rules_proto//proto:defs.bzl", "proto_library")

cc_library(
    name = "my-protobuf-common",
    hdrs = [
        ":my-proto-lib",
    ],
    copts = ["--std=c++17"],
    includes = [
        ":my-proto-lib",
    ],
    linkstatic = True,
    visibility = ["//visibility:public"],
    deps = [":my-proto-lib"],
)

cc_proto_library(
    name = "my-proto-lib",
    visibility = ["//visibility:public"],
    deps = [":my-proto"],
)

proto_library(
    name = "my-proto",
    srcs = [
        "proto/point.proto",
        "proto/point-geodetic.proto",
        "proto/point-ned.proto",
    ],
    visibility = ["//visibility:public"],
)

dependent repo (workspace correctly pulls as external and i see proto build output): BUILD

load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
    name = "my-service",
    srcs = [
        "app/bazel-test.cpp",
    ],
    hdrs = [
        "@mpc//:my-protobuf-common",
    ],
    copts = ["--std=c++17"],
    deps = [        
        "@mpc//:my-protobuf-common",
    ],
)

bazel-test.cpp

#include <iostream>
#include <proto/point.pb.h>

int main() {
    MyProtobufCommon::Point p;
}

build error:

app/bazel-test.cpp:2:10: fatal error: proto/point.pb.h: No such file or directory
    2 | #include <proto/point.pb.h>
      |          ^~~~~~~~~~~~~~~~~~

Solution

  • In general, you should be able to depend on the cc_proto_library directly, so the intermediate cc_library my-protobuf-common isn't needed generally. The cc toolchain uses -iquote to add the proto deps, so I believe #include "proto/point.pb.h" has to be used.

    proto-repo/WORKSPACE:

    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    
    http_archive(
        name = "rules_proto",
        sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
        strip_prefix = "rules_proto-4.0.0",
        urls = [
            "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
            "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
        ],
    )
    load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
    rules_proto_dependencies()
    rules_proto_toolchains()
    

    proto-repo/BUILD:

    cc_proto_library(
      name = "point_cc_proto",
      deps = [":point"],
      visibility = ["//visibility:public"],
    )
    
    proto_library(
      name = "point",
      srcs = ["proto/point.proto"],
    )
    

    proto-repo/proto/point.proto:

    syntax = "proto3";
    
    package my_protos.point;
    
    message Point {
      optional int32 x = 1;
      optional int32 y = 2;
    }
    

    main-repo/WORKSPACE:

    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    
    local_repository(
      name = "my_protos",
      path = "../proto-repo",
    )
    
    http_archive(
        name = "rules_proto",
        sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
        strip_prefix = "rules_proto-4.0.0",
        urls = [
            "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
            "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
        ],
    )
    load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
    rules_proto_dependencies()
    rules_proto_toolchains()
    

    main-repo/BUILD:

    cc_binary(
      name = "main",
      srcs = ["main.cc"],
      deps = ["@my_protos//:point_cc_proto"],
    )
    

    main-repo/main.cc:

    #include <iostream>
    #include "proto/point.pb.h"
    
    int main() {
    
      my_protos::point::Point p;
      p.set_x(123);
      p.set_y(456);
      std::cout << p.DebugString();
    
      return 0;
    }
    

    Usage:

    main-repo$ bazel run main
    INFO: Analyzed target //:main (43 packages loaded, 570 targets configured).
    INFO: Found 1 target...
    Target //:main up-to-date:
      bazel-bin/main
    INFO: Elapsed time: 6.166s, Critical Path: 5.33s
    INFO: 106 processes: 4 internal, 102 linux-sandbox.
    INFO: Build completed successfully, 106 total actions
    INFO: Build completed successfully, 106 total actions
    x: 123
    y: 456