Edouard Veyrier
Edouard Veyrier

Reputation: 61

Generated header not found

I'm trying to use Bazel to build a cpp project that use Flatbuffers. But my map_schema_generated.h generated with flatc is not found.

My tree:

|
|_ data
|  |_ maps
|     |_ BUILD
|     |_ map_schema.fbs
|
|_ src
|  |_ map
|     |_ BUILD
|     |_ map.hpp
|     |_ map.cpp
|
|_ tools
|  |_ BUILD
|  |_ generate_fbs.bzl
|
|_ WORKSPACE

tools/generate_fbs.bzl:

def _impl(ctx):
  output = ctx.outputs.out
  input = ctx.files.srcs
  print("generating", output.basename)
  ctx.action(
      use_default_shell_env = True,
      outputs = [output],
      inputs = input,
      progress_message="Generating %s with %s" % (output.path, input[0].path),
      command="flatc -o %s --cpp %s" % (output.dirname, input[0].path)
  )

generate_fbs = rule(
  implementation=_impl,
  output_to_genfiles = True,
  attrs={
       "srcs": attr.label_list(allow_files=True, allow_empty=False),
       "out": attr.output()
       },
)

data/maps/BUILD:

load("//tools:generate_fbs.bzl", "generate_fbs")

generate_fbs(
  name = "schema",
  srcs = ["map_schema.fbs"],
  out = "map_schema_generated.h",
  visibility = ["//visibility:public"]
)

src/map/BUILD:

cc_library(
  name = "map",
  srcs = [
    "//data/maps:map_schema_generated.h",
    "map.hpp",
    "map.cpp"
  ]
)

src/map/map.cc has #include "map_schema_generated.h".

The command line I use to build: bazel build //src/map.

If I find in bazel-*, I got:

bazel-genfiles/data/maps/map_schema_generated.h
bazel-out/k8-fastbuild/genfiles/data/maps/map_schema_generated.h
bazel-my-workspace-name/bazel-out/k8-fastbuild/genfiles/data/maps/map_schema_generated.h

And if I cat these files, I can see that they are well generated.

All the information that I found are about Tensorflow, and are not really helpful.

Best regards,

Upvotes: 3

Views: 1941

Answers (2)

Ondrej K.
Ondrej K.

Reputation: 9664

The problem is that your cc_library actually doesn't really recognize your generated header as requiring any special action (like adding -I flag for the location it's in). It gets generate and lives in the build tree, but not anywhere the compiler (preprocessor) would look for it working on map.cpp. (Run build with -s for a bit more insight about what and how happened).

Now about how to address this, there might be a better way, but this would appear to work. I guess this functionality could also be rolled into generate_fbs rule.

In data/maps/BUILD I've added "header only" library as follows:

cc_library(
  name = "map_schema_hdr",
  hdrs = [":map_schema_generated.h"],
  include_prefix = ".",  # to manipulate -I of dependenices
  visibility = ["//visibility:public"]
)

In src/map/BUILD I would then use this header only library as dependency of map:

cc_library(
  name = "map",
  srcs = [
    "map.cpp"
    "map.hpp"
  ],
  deps = [
     "//data/maps:map_schema_hdr",
  ]
)

To play a bit more with the idea of having a single rule (macro) for convenience, I've made the following changes:

tools/generate_fbs.bzl now reads:

def _impl(ctx):
  output = ctx.outputs.out
  input = ctx.files.srcs
  print("generating", output.basename)
  ctx.action(
      use_default_shell_env = True,
      outputs = [output],
      inputs = input,
      progress_message="Generating %s with %s" % (output.path, input[0].path),
      command="/bin/cp %s %s" % (input[0].path, output.path)
  )

_generate_fbs = rule(
  implementation=_impl,
  output_to_genfiles = True,
  attrs={
       "srcs": attr.label_list(allow_files=True, allow_empty=False),
       "out": attr.output()
       },
)


def generate_fbs(name, srcs, out):
  _generate_fbs(
    name = "_%s" % name,
     srcs = srcs,
     out = out
  )

  native.cc_library(
    name = name,
    hdrs = [out],
    include_prefix = ".",
    visibility = ["//visibility:public"],
  )

With that, I could have data/maps/BUILD:

load("//tools:generate_fbs.bzl", "generate_fbs")

generate_fbs(
  name = "schema",
  srcs = ["map_schema.fbs"],
  out = "map_schema_generated.h",
)

And src/map/BUILD contains:

cc_library(
  name = "map",
  srcs = [
    "map.cpp",
    "map.hpp",
  ],
  deps = [
     "//data/maps:schema",
  ]
)

And bazel build //src/map builds bazel-bin/src/map/libmap.a and bazel-bin/src/map/libmap.so.

Upvotes: 3

Edouard Veyrier
Edouard Veyrier

Reputation: 61

Instead of #include "map_schema_generated.h" in src/map/map.cpp, I could have write `#include "data/maps/map_schema_generated.h".

I think it is the cleanest way to make it works.

Upvotes: 2

Related Questions