Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bugfix] BazelDeps in the build context #16025

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions conan/tools/google/bazeldeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ def _get_package_reference_name(dep):
return dep.ref.name


def _get_repository_name(dep):
def _get_repository_name(dep, is_build_context=False):
pkg_name = dep.cpp_info.get_property("bazel_repository_name") or _get_package_reference_name(dep)
return f"build-{pkg_name}" if dep.context == "build" else pkg_name
return f"build-{pkg_name}" if is_build_context else pkg_name


def _get_target_name(dep):
Expand Down Expand Up @@ -60,7 +60,7 @@ def _get_requirements(conanfile, build_context_activated):
"""
# All the requirements
host_req = conanfile.dependencies.host
build_req = conanfile.dependencies.direct_build # tool_requires
build_req = conanfile.dependencies.build # tool_requires
franramirez688 marked this conversation as resolved.
Show resolved Hide resolved
test_req = conanfile.dependencies.test

for require, dep in list(host_req.items()) + list(build_req.items()) + list(test_req.items()):
Expand Down Expand Up @@ -456,9 +456,11 @@ def generate(self):

class _InfoGenerator:

def __init__(self, conanfile, dep):
def __init__(self, conanfile, dep, require):
self._conanfile = conanfile
self._dep = dep
self._req = require
self._is_build_context = require.build
self._transitive_reqs = get_transitive_requires(self._conanfile, dep)

def _get_cpp_info_requires_names(self, cpp_info):
Expand Down Expand Up @@ -491,7 +493,7 @@ def package_info(self):
try:
req_conanfile = self._transitive_reqs[pkg_ref_name]
# Requirements declared in another dependency BUILD file
prefix = f"@{_get_repository_name(req_conanfile)}//:"
prefix = f"@{_get_repository_name(req_conanfile, is_build_context=self._is_build_context)}//:"
except KeyError:
continue # If the dependency is not in the transitive, might be skipped
else: # For instance, dep == "hello/1.0" and req == "hello::cmp1" -> hello == hello
Expand Down Expand Up @@ -527,16 +529,18 @@ def root_package_info(self):

:return: `_BazelTargetInfo` object with the package information
"""
repository_name = _get_repository_name(self._dep)
repository_name = _get_repository_name(self._dep, is_build_context=self._is_build_context)
pkg_name = _get_target_name(self._dep)
# At first, let's check if we have defined some global requires, e.g., "other::cmp1"
requires = self._get_cpp_info_requires_names(self._dep.cpp_info)
# If we have found some component requires it would be enough
if not requires:
# If no requires were found, let's try to get all the direct dependencies,
# e.g., requires = "other_pkg/1.0"
requires = [f"@{_get_repository_name(req)}//:{_get_target_name(req)}"
for req in self._transitive_reqs.values()]
requires = [
f"@{_get_repository_name(req, is_build_context=self._is_build_context)}//:{_get_target_name(req)}"
for req in self._transitive_reqs.values()
]
cpp_info = self._dep.cpp_info
return _BazelTargetInfo(repository_name, pkg_name, requires, cpp_info)

Expand Down Expand Up @@ -567,7 +571,7 @@ def generate(self):
deps_info = []
for require, dep in requirements:
# Bazel info generator
info_generator = _InfoGenerator(self._conanfile, dep)
info_generator = _InfoGenerator(self._conanfile, dep, require)
root_package_info = info_generator.root_package_info
components_info = info_generator.components_info
# Generating single BUILD files per dependency
Expand Down
87 changes: 87 additions & 0 deletions conans/test/integration/toolchains/google/test_bazeldeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,3 +880,90 @@ def build(self):
"--build=example")
c.assert_listed_require({"example/1.0": "Cache"})
c.assert_listed_require({"example/1.0": "Cache"}, build=True)


class TestBazelGenerationBuildContext:
"""
https://github.com/conan-io/conan/issues/15764
"""
def test_bazel_generate(self):
c = TestClient()
tool = textwrap.dedent("""
import os
from conan import ConanFile
from conan.tools.google import BazelDeps
class Example(ConanFile):
name = "tool"
version = "1.0"
requires = "wayland/1.0"
tool_requires = "wayland/1.0"
def generate(self):
tc = BazelDeps(self)
tc.build_context_activated = ["wayland", "dep"]
tc.generate()
def build(self):
# Build context
assert os.path.exists(os.path.join("build-wayland", "BUILD.bazel"))
assert os.path.exists(os.path.join("build-dep", "BUILD.bazel"))
# Host context
assert os.path.exists(os.path.join("wayland", "BUILD.bazel"))
assert os.path.exists(os.path.join("dep", "BUILD.bazel"))
""")
c.save({"dep/conanfile.py": GenConanfile("dep", "1.0").with_package_type("shared-library"),
"wayland/conanfile.py": GenConanfile("wayland", "1.0").with_requires("dep/1.0"),
"tool/conanfile.py": tool,
"app/conanfile.py": GenConanfile().with_tool_requires("tool/1.0")})
c.run("export dep")
c.run("export wayland")
c.run("export tool")
c.run("install app --build=missing")
franramirez688 marked this conversation as resolved.
Show resolved Hide resolved
assert "Install finished successfully" in c.out # the asserts in build() didn't fail
# Now make sure we can actually build with build!=host context
c.run("install app -s:h build_type=Debug --build=missing")
assert "Install finished successfully" in c.out # the asserts in build() didn't fail

def test_bazel_generate_components(self):
c = TestClient()
tool = textwrap.dedent("""
import os
from conan import ConanFile
from conan.tools.google import BazelDeps
class Example(ConanFile):
name = "tool"
version = "1.0"
requires = "wayland/1.0"
tool_requires = "wayland/1.0"
def generate(self):
tc = BazelDeps(self)
tc.build_context_activated = ["wayland", "dep"]
tc.generate()
def build(self):
# Build context
assert os.path.exists(os.path.join("build-wayland", "BUILD.bazel"))
assert os.path.exists(os.path.join("build-dep", "BUILD.bazel"))
# Host context
assert os.path.exists(os.path.join("wayland", "BUILD.bazel"))
assert os.path.exists(os.path.join("dep", "BUILD.bazel"))
franramirez688 marked this conversation as resolved.
Show resolved Hide resolved
""")
wayland = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
name = "wayland"
version = "1.0"
requires = "dep/1.0"
def package_info(self):
self.cpp_info.components["client"].libs = []
self.cpp_info.components["server"].libs = []
""")
c.save({"dep/conanfile.py": GenConanfile("dep", "1.0").with_package_type("shared-library"),
"wayland/conanfile.py": wayland,
"tool/conanfile.py": tool,
"app/conanfile.py": GenConanfile().with_tool_requires("tool/1.0")})
c.run("export dep")
c.run("export wayland")
c.run("export tool")
c.run("install app --build=missing")
assert "Install finished successfully" in c.out # the asserts in build() didn't fail
# Now make sure we can actually build with build!=host context
c.run("install app -s:h build_type=Debug --build=missing")
assert "Install finished successfully" in c.out # the asserts in build() didn't fail