Search code examples
c++boostbazelgoogletest

Bazel: Tests cannot see library headers but app can


I have a pretty simple C++ project with Bazel that I am trying to implement gtest in and it has 3 BUILD files when including the test one. The problem I am having is that my headers in my library are visible to the app directory but not the test one and when I try to build my simple test it fails. My project structure is:

- WORKSPACE
- app
  |- BUILD
  |- main.cpp
- lib
  |- BUILD
  |- foo
     |- foo.hpp
     |- foo.cpp
  |- bar
     |- bar.hpp
     |- bar.cpp
- test
  |- BUILD
  |- lib_test.cpp

WORKSPACE contains the following to enable boost and gtest:

workspace(name = "my-app")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "com_github_nelhage_rules_boost",
    commit = "fce83babe3f6287bccb45d2df013a309fa3194b8",
    remote = "https://github.com/nelhage/rules_boost",
    shallow_since = "1591047380 -0700",
)
load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps")
boost_deps()

git_repository(
    name = "gtest",
    remote = "https://github.com/google/googletest",
    branch = "v1.10.x",
)

lib/BUILD contains rules for the library:

load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
    name = "app-lib",
    srcs = glob(["*/*.cpp"]),
    hdrs = glob(["*/*.hpp"]),
    deps = [
        "@boost//:log",
        "@boost//:date_time",
        "@boost//:filesystem",
        "@boost//:program_options",
    ],
    visibility = [
        "//app:__pkg__",
        "//test:__pkg__",
    ],
)

app/BUILD has the following to build the main binary:

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

cc_binary(
    name = "my-app",
    srcs = ["main.cpp"],
    deps = [
        "//lib:app-lib",
    ],
    copts = ["-Ilib"],
)

test/BUILD has the following in my attempts to get gtest working

cc_test(
    name = "lib-test",
    srcs = [
        "lib_test.cpp",
    ],
    copts = ["-Ilib"],
    deps = [
        "//lib:app-lib",
        "@gtest//:gtest",
        "@gtest//:gtest_main",
    ],
)

Now in my main.cpp I have included my library with the following includes:

#include "foo/foo.hpp"
#include "bar/bar.hpp"

and this builds my binary without issue however in my lib_test.cpp I have tried the same includes as well as full relative path include:

#include "lib/foo/foo.hpp"
#include "lib/bar/bar.hpp"

however when I try to run bazel test test:lib-test I get the following error:

lib/foo/foo.hpp: No such file or directory

Edit 1:

I'm using VSCode and have the following c_cpp_properties.json for include paths:

    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/lib/",
                "/home/user/Projects/my-app/bazel-my-app/external/boost"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

Solution

  • Instead of copts = ["-Ilib"], use includes = ["."] on the cc_library. That tells Bazel that anything which depends on that cc_library should get that directory on the include path, regardless of the relative path to get there.

    Specifically, remove all the copts = ["-Ilib"], and change lib/BUILD to this:

    load("@rules_cc//cc:defs.bzl", "cc_library")
    cc_library(
        name = "app-lib",
        srcs = glob(["*/*.cpp"]),
        hdrs = glob(["*/*.hpp"]),
        includes = ["."],
        deps = [
            "@boost//:log",
            "@boost//:date_time",
            "@boost//:filesystem",
            "@boost//:program_options",
        ],
        visibility = [
            "//app:__pkg__",
            "//test:__pkg__",
        ],
    )