I am new to bazel and am playing around with monorepo and multirepo builds with dependencies.
I successfully setup the monorepo but am unable to get the multrepo to work.
For the multirepo I created two C++ repositories where repo app2 depends on repo lib2 When I build app2 I would like bazel to fetch lib2. To achieve this I have added a git_repository definition to my WORKSPACE. My issue is that when I run bazel build //app2:app bazel complains that it can not find the lib2 headers
INFO: Analyzed target //app2:app2 (0 packages loaded, 0 targets configured).
ERROR: /home/bazel/.cache/bazel/_bazel_bazel/36a4e7d3b3c11620f7fa4375ad21cf55/external/lib2/BUILD.bazel:6:11: Compiling time_util.cpp failed: (Exit 1): gcc failed: error executing CppCompile command (from target @@lib2//:time_util) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++11' -MD -MF ... (remaining 21 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
external/lib2/time_util.cpp:1:10: fatal error: lib2/time_util.h: No such file or directory
1 | #include "lib2/time_util.h"
| ^~~~~~~~~~~~~~~~~~
compilation terminated.
ERROR: /home/bazel/testing/app2/BUILD.bazel:7:10: Compiling app2/app.cpp failed: (Exit 1): gcc failed: error executing CppCompile command (from target //app2:app2) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++11' -MD -MF ... (remaining 32 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
app2/app.cpp:1:10: fatal error: lib2/time_util.h: No such file or directory
1 | #include "lib2/time_util.h"
| ^~~~~~~~~~~~~~~~~~
compilation terminated.
My bazel files are as follows
WORKSPACE.bazel
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "lib2",
remote = "https://[email protected]/szarmach/lib2.git",
branch = "main", # branch, tag, commit, hash
)
app2/BUILD.bazel
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "app",
srcs = ["app.cpp"],
#deps = ["//lib2:time_util"],
deps = ["@lib2//:time_util"],
visibility = ["//visibility:public"],
)
lib2/BUILD.bazel
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "time_util",
srcs = ["time_util.cpp"],
hdrs = ["time_util.h"],
#hdrs = glob(["**/*.h"]),
copts = ["-Ilib1"],
includes = ["."],
visibility = ["//visibility:public"],
)
Searching stack overflow I have seen various solutions to almost identical issues but I have not been able to apply them successfully.
What am I missing for the multi repo case to have bazel build?
It seems like you have a single
WORKSPACE.bazelfile, which means you would have a single repository — to have two repos, you'd need twoWORKSPACE.bazelfiles. If I clone both of your repos (app2andlib2), and I put theWORKSPACE.bazelfile you mentioned in the root, and run abazel query //..., I get the two targets:As a side note, since you're using Bazel 7, you might want to switch to using
MODULE.bazelinstead ofWORKSPACE.bazelfiles. So here is how you'd do something like this with Bazel modules, which is the modern way of managing dependencies.Create a file
app2/MODULE.bazel:Then create the
app2/extensions.bzlfile:The
name = lib2in thegit_repositoryarg is what you need to add in theuse_repocall inMODULE.bazel, to make it available as a module dependency.You also need
rules_cc, which comes straight from the BCR.Now that you have your dependencies set up, you need to change your
app2/BUILD.bazelas follows:Note that now we're using
@lib2//:time_utilinstead of//lib2:time_util.You no longer need the
WORKSPACE.bazelfile in the root directory, since you don't have a package root there. Each repo has its own package root.After setting this all up, you'll notice that the build will still fail. This is because in
app.cpp, you reference the library like this:You need to change this to be:
This is because, while previously you needed the full paths from the workspace root, now each workspace has its own root, and in
lib2,time_util.his actually at the root, not under a sub-package.When you invoke
bazel build //:appand it fails, you can see that Bazel adds the C compiler flag-iquote external/_main~non_module_dependencies~lib2, among others. This essentially means anything under thelib2repo can be#included using quotes, without any prefix.Note that, in
lib2, you also need to change the#includeintime_util.cpp, and don't forget to commit & push the change, or use a local override while developing on multiple modules locally.