BazelDepsΒΆ
Warning
This feature is experimental and subject to breaking changes. See the Conan stability section for more information.
The BazelDeps is the dependencies generator for Bazel. Generates a <REPOSITORY>/BUILD.bazel file per dependency,
where the <REPOSITORY>/ folder is the Conan recipe reference name by default, e.g., mypkg/BUILD.bazel. Apart from
that, it also generates Bazel 6.x compatible file like dependencies.bzl, and other Bazel >= 7.1 compatible ones
like conan_deps_module_extension.bzl and conan_deps_repo_rules.bzl. All of them contain the logic to load
all your Conan dependencies through your WORKSPACE | MODULE.bazel.
The BazelDeps generator can be used by name in conanfiles:
class Pkg(ConanFile):
    generators = "BazelDeps"
[generators]
BazelDeps
And it can also be fully instantiated in the conanfile generate() method:
from conan import ConanFile
from conan.tools.google import BazelDeps
class App(ConanFile):
    settings = "os", "arch", "compiler", "build_type"
    requires = "zlib/1.2.11"
    def generate(self):
        bz = BazelDeps(self)
        bz.generate()
Generated filesΒΆ
When the BazelDeps generator is used, every invocation of conan install will
generate several bazel files. For the conanfile.py
above, for example:
$ conan install .
.
βββ BUILD.bazel
βββ conanfile.py
βββ dependencies.bzl
βββ zlib
    βββ BUILD.bazel
Every conan install generates these files:
- BUILD.bazel: An empty file aimed to be alongside the dependencies.bzl one. More information here. 
- zlib/BUILD.bazel: contains all the targets that you can load from any of your BUILD files. More information in Customization. 
- dependencies.bzl: (Bazel 6.x compatible) this file tells your Bazel WORKSPACE how to load the dependencies. 
- conan_deps_module_extension.bzl: (since Conan 2.4.0)(Bazel >= 7.1 compatible) This file is used to load each dependency as repository. 
- conan_deps_repo_rules.bzl: (since Conan 2.4.0)(Bazel >= 7.1 compatible) The rule provided by this file is used to create a repository. It is not intended to be used by consumers but by conan_deps_module_extension.bzl. 
Letβs check the content of the files created:
Bazel 6.x compatible
# This Bazel module should be loaded by your WORKSPACE file.
# Add these lines to your WORKSPACE one (assuming that you're using the "bazel_layout"):
# load("@//conan:dependencies.bzl", "load_conan_dependencies")
# load_conan_dependencies()
def load_conan_dependencies():
    native.new_local_repository(
        name="zlib",
        path="/path/to/conan/package/folder/",
        build_file="/your/current/working/directory/zlib/BUILD.bazel",
    )
Bazel >= 7.1 compatible
# This bazel repository rule is used to load Conan dependencies into the Bazel workspace.
# It's used by a generated module file that provides information about the conan packages.
# Each conan package is loaded into a bazel repository rule, with having the name of the
# package. The whole method is based on symlinks to not copy the whole package into the
# Bazel workspace, which is expensive.
def _conan_dependency_repo(rctx):
    package_path = rctx.workspace_root.get_child(rctx.attr.package_path)
    child_packages = package_path.readdir()
    for child in child_packages:
        rctx.symlink(child, child.basename)
    rctx.symlink(rctx.attr.build_file_path, "BUILD.bazel")
conan_dependency_repo = repository_rule(
    implementation = _conan_dependency_repo,
    attrs = {
        "package_path": attr.string(
            mandatory = True,
            doc = "The path to the Conan package in conan cache.",
        ),
        "build_file_path": attr.string(
            mandatory = True,
            doc = "The path to the BUILD file.",
        ),
    },
)
# This module provides a repo for each requires-dependency in your conanfile.
# It's generated by the BazelDeps, and should be used in your Module.bazel file.
load(":conan_deps_repo_rules.bzl", "conan_dependency_repo")
def _load_dependenies_impl(mctx):
    conan_dependency_repo(
        name = "zlib",
        package_path = "/path/to/conan/package/folder/",
        build_file_path = "/your/current/working/directory/zlib/BUILD.bazel",
    )
    return mctx.extension_metadata(
        # It will only warn you if any direct
        # dependency is not imported by the 'use_repo' or even it is imported
        # but not created. Notice that root_module_direct_dev_deps can not be None as we
        # are giving 'all' value to root_module_direct_deps.
        # Fix the 'use_repo' calls by running 'bazel mod tidy'
        root_module_direct_deps = 'all',
        root_module_direct_dev_deps = [],
        # Prevent writing function content to lockfiles:
        # - https://bazel.build/rules/lib/builtins/module_ctx#extension_metadata
        # Important for remote build. Actually it's not reproducible, as local paths will
        # be different on different machines. But we assume that conan works correctly here.
        # IMPORTANT: Not compatible with bazel < 7.1
        reproducible = True,
    )
conan_extension = module_extension(
    implementation = _load_dependenies_impl,
    os_dependent = True,
    arch_dependent = True,
)
Given the examples above, and imagining that your WORKSPACE | MODULE.bazel is at the same directory, you would have to add these lines in there:
Bazel 6.x compatible
load("@//:dependencies.bzl", "load_conan_dependencies")
load_conan_dependencies()
Bazel >= 7.1 compatible
load_conan_dependencies = use_extension("//:conan_deps_module_extension.bzl", "conan_extension")
# use_repo(load_conan_dependencies, "dep1", "dep2", ..., "depN")
use_repo(load_conan_dependencies, "zlib")
As you can observe, the zlib/BUILD.bazel defines these global targets:
# Components precompiled libs
# Root package precompiled libs
cc_import(
    name = "z_precompiled",
    static_library = "lib/libz.a",
)
# Components libraries declaration
# Package library declaration
cc_library(
    name = "zlib",
    hdrs = glob([
        "include/**",
    ]),
    includes = [
        "include",
    ],
    visibility = ["//visibility:public"],
    deps = [
        ":z_precompiled",
    ],
)
# Filegroup library declaration
filegroup(
    name = "zlib_binaries",
    srcs = glob([
        "bin/**",
    ]),
    visibility = ["//visibility:public"],
)
- zlib: bazel library target. The label used to depend on it would be- @zlib//:zlib.
- zlib_binaries: bazel filegroup target. The label used to depend on it would be- @zlib//:zlib_binaries.
You can put all the files generated by BazelDeps into another folder using the bazel_layout:
from conan import ConanFile
from conan.tools.google import BazelDeps, bazel_layout
class App(ConanFile):
    settings = "os", "arch", "compiler", "build_type"
    requires = "zlib/1.2.11"
    def layout(self):
        bazel_layout(self)
    def generate(self):
        bz = BazelDeps(self)
        bz.generate()
Running again the conan install command, we now get this structure:
$ conan install .
.
βββ conan
β   βββ BUILD.bazel
β   βββ dependencies.bzl
β   βββ conan_deps_module_extension.bzl
β   βββ conan_deps_repo_rules.bzl
β   βββ zlib
β       βββ BUILD.bazel
βββ conanfile.py
Now your Conan-bazel files were generated in the conan/ folder, your WORKSPACE will look like:
load("@//conan:dependencies.bzl", "load_conan_dependencies")
load_conan_dependencies()
Or your MODULE.bazel:
load_conan_dependencies = use_extension("//conan:conan_deps_module_extension.bzl", "conan_extension")
use_repo(load_conan_dependencies, "zlib")
CustomizationΒΆ
NamingΒΆ
The <REPOSITORY>/BUILD.bazel file contains all the targets declared by the dependency. Both the <REPOSITORY>/ folder and the targets
declared in there will be named following these rules by default:
- For packages, it uses the package name as folder/target name, e.g., package zlib/1.2.11will have:
- Folder: - zlib/BUILD.bazel.
- Global target: - zlib.
- How it can be consumed: - @zlib//:zlib.
 
 
- For packages, it uses the package name as folder/target name, e.g., package 
- For components, the package name + hyphen + component name, e.g., package openssl/3.1.4will have:
- Folder: - openssl/BUILD.bazel.
- Global target: - openssl.
- Components targets: - openssl-ssl, and- openssl-crypto.
- How it can be consumed:
- @openssl//:openssl(global one which includes all the components)
- @openssl//:openssl-ssl(component one)
- @openssl//:openssl-crypto(component one)
 
 
 
 
- For components, the package name + hyphen + component name, e.g., package 
You can change that default behavior with the bazel_target_name and the bazel_repository_name properties.
See Properties section below.
ReferenceΒΆ
- class BazelDeps(conanfile)ΒΆ
- Parameters:
- conanfile β - < ConanFile object >The current recipe object. Always use- self.
 - build_context_activatedΒΆ
- Activates the build context for the specified Conan package names. 
 - generate()ΒΆ
- Generates all the targets <DEP>/BUILD.bazel files, a dependencies.bzl (for bazel<7), a conan_deps_repo_rules.bzl and a conan_deps_module_extension.bzl file (for bazel>=7.1) one in the build folder. - In case of bazel < 7, itβs important to highlight that the - dependencies.bzlfile should be loaded by your WORKSPACE Bazel file:- load("@//[BUILD_FOLDER]:dependencies.bzl", "load_conan_dependencies") load_conan_dependencies() - In case of bazel >= 7.1, the - conan_deps_module_extension.bzlfile should be loaded by your Module.bazel file, e.g. like this:- load_conan_dependencies = use_extension( "//build:conan_deps_module_extension.bzl", "conan_extension" ) use_repo(load_conan_dependencies, "dep-1", "dep-2", ...) 
 
build_context_activatedΒΆ
When you have a build-requirement, by default, the Bazel files are not generated. But you can activate it using the build_context_activated attribute:
def build_requirements(self):
    self.tool_requires("my_tool/0.0.1")
def layout(self):
    bazel_layout(self)
def generate(self):
    bz = BazelDeps(self)
    # generate the build-mytool/BUILD.bazel file for the tool require
    bz.build_context_activated = ["my_tool"]
    bz.generate()
Running the conan install command, the structure created is as follows:
$ conan install . -pr:b default
.
βββ conan
β   βββ BUILD.bazel
β   βββ build-my_tool
β   β   βββ BUILD.bazel
β   βββ conan_deps_module_extension.bzl
β   βββ conan_deps_repo_rules.bzl
β   βββ dependencies.bzl
βββ conanfile.py
Notice that my_tool Bazel folder is prefixed with build- which indicates that itβs being used in the build context.
PropertiesΒΆ
The following properties affect the BazelDeps generator:
- bazel_target_name property will define the name of the target declared in the - <REPOSITORY>/BUILD.bazel. This property can be defined at both global and component- cpp_infolevel.
- bazel_repository_name property will define the name of the folder where the dependency BUILD.bazel will be allocated. This property can only be defined at global - cpp_infolevel.
Example:
def package_info(self):
    self.cpp_info.set_property("bazel_target_name", "my_target")
    self.cpp_info.set_property("bazel_repository_name", "my_repo")
    self.cpp_info.components["mycomponent"].set_property("bazel_target_name", "component_name")