It is considered by many that it is better to avoid circular dependencies in the first place.
Suppose you have two files, where a.cc #includes b.h and b.cc #includes a.h:
cc_library(
name="a",
srcs=["a.cc"],
hdrs=["a.h"],
deps=[":b"], # a.cc #includes b.h
)
cc_library(
name="b",
srcs=["b.cc"],
hdrs=["b.h"],
deps=[":a"], # b.cc #includes a.h
)
bazel will complain about a circular dependency.
If you own all the code in question, the more straightforward way to avoid these circular dependencies is to reshuffle your source code and bazel packages to avoid the dependency in the first place.
One strategy here would be to refactor out the common stuff into a third "core" library c that depends on neither a nor b:
cc_library(
name="a",
srcs=["a.cc"],
hdrs=["a.h"],
deps=[":c"], # a.cc #includes c.h
)
cc_library(
name="b",
srcs=["b.cc"],
hdrs=["b.h"],
deps=[":c"], # b.cc #includes c.h
)
cc_library(
name="c",
srcs=["c.cc"],
hdrs=["c.h"],
)
Another strategy is to have some kind of build step to copy a.h and b.h to some "public headers" folder (which itself doesn't depend on anything else). This removes the file-level circular dependency, but semantically, the source code still has a circular dependency between a and b.