Search code examples
bazelbazel-rules

Bazel - What is the relation between hdrs vs includes on a cc_library to generate gcc command with -I instead of -isystem or -iquote?


Looks like there is a relation between creating a cc_library on a BUILD file using hdrs and includes to generate the gcc command with -isystem, -iquote and -I.

Official Bazel doc

To explain my problem better, I have this example.

I have a Bazel project with the following files:

  • main.cpp
  • WORKSPACE
  • BUILD

The dependencies are:

  1. main.cpp needs foo.hpp
  2. foo.hpp needs access to #include "bar.h", so a library hdrs-bar is provided
  3. bar.h needs access to #include <system_bar.h>, so a library hdrs-system-bar is provided. (Note that <> on the include is needed.)
  4. A binary called demo is created with all these dependencies

As described on (1), the main.cpp contains:

#include "foo.hpp"

int main()
{
    // ...something which uses foo.hpp
    return 0;
}

As described on (2), to be able to access foo.hpp from main.cpp I need to create a Bazel project out of a git repository and create a BUILD file for for it using the build_file_content where it contains a library that will expose all the *.h files I need (including the bar.h).

Therefore the WORKSPACE file contains:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")

new_git_repository(
    name = "bar-utils",
    remote = "https://github.com/someGitRepo/bar-utils.git",
    branch = "master",
    build_file_content = """

       package(default_visibility = ["//visibility:public"])
       cc_library(
           name = "hdrs-bar",
           hdrs = glob(["bar/*.h"], allow_empty=False),
           strip_include_prefix = "bar",
      )

""",
)

As described on (3), the WORKSPACE file also contains a creation of a library called hdrs-system-bar which contains the system headers needed from bar.h:

new_local_repository(
    name = "bar-system",
    path = "/usr/local/bar/include",
    build_file_content = """
        cc_library(
          name = "hdrs-system-bar",
          hdrs = glob(["*.h"], allow_empty=False),
          visibility = ["//visibility:public"],
        )    
""",    
)

As described in (4), the BUILD file contains a binary which gets all the dependencies in deps:

cc_binary(
    name = "demo",
    srcs = ["main.cpp"],
    deps = ["@bar-utils//:hdrs-bar", "@bar-system//:hdrs-system-bar"],
)

If I compile:

$ bazel build //... --sandbox_debug

I get the following build ERROR:

bazel-out/aarch64-fastbuild/bin/external/bar-utils/_virtual_includes/hdrs-bar/barUtils.h:7:10: fatal error: bar_runtime.h: No such file or directory #include <bar_runtime.h>

The file bar_runtime.h should be inside the library hdrs-system-bar. So if I see my sandbox folder on .../sandbox/linux-sandbox/4/execroot/__main__/ I get the following directories:

  • main.cpp
  • bazel-out
  • external

On the external, I have these two folder, where each contains all the header files I need:

  • bar-utils
  • bar-system

On the bazel-out, I have the following:

aarch64-fastbuild/bin/external/bar-utils/_virtual_includes/hdrs-bar/bar.h

I was expecting inside this bazel-out external to have also the bar-system, but there is only bar-utils. Why is that?

To add more info the gcc command generated was like this (removed all the non-necessary arguments for sake of simplicity):

/usr/bin/gcc -iquote external/bar-utils -iquote external/bar-system -c main.cpp 

If I simply use includes instead of hdrs on all the libraries creation, I get a lot of -isystem instead of the -iquote. But what I need is actually the -I<folder where the headers are>.

If I manually change my gcc command to:

/usr/bin/gcc -iquote external/bar-utils -Iexternal/bar-system -c main.cpp 

Then it works.

How can I force it to use -I? Changing the cc_libraries to srcs or includes instead of hdrs is not working.


Solution

  • Solution is to also use the includes flag, besides the hdrs. This way it will show up on the sandbox and be accessible by adding the -isystem argument for gcc with the folder you need.

        cc_library(
          name = "hdrs-system-bar",
          hdrs = glob(["*.h"], allow_empty=False),
          includes = ["."],
          visibility = ["//visibility:public"],
        )