agents/skills/gn-deps-debugging/references/dependency-patterns.md
Use this reference to choose the narrowest correct dependency fix.
deps vs public_depsUse deps when the dependency is needed only by implementation files:
source_set("impl") {
sources = [ "foo.cc" ]
deps = [
":foo",
"//components/prefs",
]
}
Use public_deps only when consumers of this target's public headers also need
the dependency to compile:
source_set("foo") {
sources = [ "foo.h" ]
public_deps = [
"//chrome/browser/profiles:profile",
]
}
public_deps is transitive. Every downstream target inherits it, so adding
entries there widens the dependency graph. Treat public_deps as part of the
API contract.
If a header only mentions a type by pointer or reference, prefer a forward declaration:
class PrefService;
class Foo {
public:
explicit Foo(PrefService* prefs);
};
Move the concrete include to the .cc file:
#include "components/prefs/pref_service.h"
This keeps implementation dependencies private and avoids leaking them through public headers.
Forward declarations are not enough when the header:
Edit the smallest target that owns the failing source file. Avoid fixing a small include failure by adding dependencies to:
//chrome/browser:browser//chrome/test:unit_tests:all targetsIf the source file is in a source_set() that is consumed by a larger test or
executable target, add the dependency to the source_set() that owns the file,
not the final executable, unless the final executable owns the file directly.
If the failing include is in a platform-specific file, keep the dependency under
the same platform condition whenever possible. For example, an include used only
by icon_loader_win.cc should usually produce a Windows-only dependency:
source_set("icons") {
sources = [
"icon_loader.cc",
]
if (is_win) {
sources += [
"icon_loader_win.cc",
]
deps += [
"//ui/gfx:win",
]
}
}
Do not add platform-only targets unconditionally unless the target is already unconditional and valid on every supported platform:
deps += [ "//ui/gfx:win" ]
Common file suffixes include _win.cc, _mac.mm, _linux.cc, _android.cc,
_ios.mm, _chromeos.cc, and _posix.cc. Match the existing conditions in the
nearest BUILD.gn, such as is_win, is_mac, is_linux, is_android,
is_ios, is_chromeos, or is_posix.
DEPS rules enforce source-level layering. A BUILD.gn dep does not override a
blocked include path.
When changing DEPS:
specific_include_rules entry.DEPS file.Generated headers are often owned by generated targets rather than the directory where the include path appears to live. Search for existing includes of the same generated header and inspect their dependencies before adding a new dep.
If adding a direct dependency creates a cycle, the first fix is usually not a
broader dep. Use gn path to print the dependency chain between the two targets
and identify the boundary where the cycle should be broken:
gn path out/Default //target_a //target_b
Use the relevant generated output directory instead of hard-coding out/Default
when another out dir is known. After locating the dependency chain, consider:
:public / :<feature> headers from :impl..cc files.Only use allow_circular_includes_from when the surrounding component already
uses that pattern and the dependency cycle is intentional and documented.