I'm a Bazel newbie and am working through the C guide here, trying to include an external testing library (gtest): https://bazel.build/tutorials/cpp-use-cases#include-external-libraries
This is my file structure and WORKSPACE and BUILD file contents:
$ tree
.
├── gtest.BUILD
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
├── main
│ ├── BUILD
│ ├── hello-greet.cc
│ ├── hello-greet.h
│ └── hello-world.cc
├── README.md
├── test
│ ├── BUILD
│ └── hello-test.cc
└── WORKSPACE
Contents of WORKSPACE:
$ cat WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "gtest",
build_file = "@//:gtest.BUILD",
url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
)
Contents of gtest.BUILD:
$ cat gtest.BUILD
cc_library(
name = "main",
srcs = glob(
["src/*.cc"],
exclude = ["src/gtest-all.cc"]
),
hdrs = glob([
"include/**/*.h",
"src/*.h"
]),
copts = ["-Iexternal/gtest/include"],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
Contents of test/BUILD:
$ cat test/BUILD
cc_test(
name = "hello-test",
srcs = ["hello-test.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
"@gtest//:main",
"//main:hello-greet",
],
)
I then try to run "bazel test test:hello-test" but it throws an issue complaining about a missing "BUILD" file:
ERROR: An error occurred during the fetch of repository 'gtest':
Traceback (most recent call last):
...
Error in read: Unable to load package for //:gtest.BUILD: BUILD file not found in any of the following directories. Add a BUILD file to a directory to mark it as a package.
- /home/user/code/bazelbuild_examples/cpp-tutorial/stage4
I then ran "touch BUILD" in the top level directory, after finding a GitHub issue with a similar error message, which got rid of that error.
Bazel is now downloading gtest library (can see it under "bazel-stage4/external/gtest") but it doesn't seem to be making it available to the test target:
ERROR: /home/user/code/bazelbuild_examples/cpp-tutorial/stage4/test/BUILD:1:8: Compiling test/hello-test.cc failed: (Exit 1): gcc failed: error executing command /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c 0x' -MD -MF ... (remaining 25 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox
test/hello-test.cc:1:10: fatal error: gtest/gtest.h: No such file or directory
1 | #include "gtest/gtest.h"
| ^~~~~~~~~~~~~~~
compilation terminated.
Why is it unable to find the gtest headers/library? How does the directory layout work when you're running "bazel test"? (i.e. where is the test code directory relative to the 3rd party library directory?)
CodePudding user response:
I think the problem has to do with your gtest build file. First, google test comes with a supported Bazel BUILD file already, so why write your own instead of using theirs?
Second:
cc_library(
name = "main",
srcs = glob(
["src/*.cc"],
exclude = ["src/gtest-all.cc"]
),
hdrs = glob([
"include/**/*.h",
"src/*.h"
]),
copts = ["-Iexternal/gtest/include"],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
The path that c source code would have to #include for headers in this rule is "include/.../*.h". That's not proper. For one, copts
affects this rule, but not other targets that depend on it. In general, compiler options should be part of the toolchain, not the rule like this. Second, cc_library rules have an includes = []
argument specifically for fixing include paths to strip leading prefixes. Instead of copts
you should use includes
to fix the path-------BUT you should use the official google test BUILD file instead of writing your own and not have to deal with problems like this.