Repository: conan-io/conan

Issue:
Fix BazelDeps in the build context
              Good catch 👏 

It has to be solved for BazelDeps too.

_Originally posted by @franramirez688 in https://github.com/conan-io/conan/pull/15763#discussion_r1504355537_
            


Discussion:

Patch:
diff --git a/conan/tools/google/bazeldeps.py b/conan/tools/google/bazeldeps.py
index 4dffc1c4db7..b2d64f985c5 100644
--- a/conan/tools/google/bazeldeps.py
+++ b/conan/tools/google/bazeldeps.py
@@ -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_require=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_require else pkg_name
 
 
 def _get_target_name(dep):
@@ -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_require = require.build
         self._transitive_reqs = get_transitive_requires(self._conanfile, dep)
 
     def _get_cpp_info_requires_names(self, cpp_info):
@@ -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_require=self._is_build_require)}//:"
                 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
@@ -527,7 +529,7 @@ 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_require=self._is_build_require)
         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)
@@ -535,8 +537,10 @@ def root_package_info(self):
         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_require=self._is_build_require)}//:{_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)
 
@@ -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


Test patch:
diff --git a/conans/test/integration/toolchains/google/test_bazeldeps.py b/conans/test/integration/toolchains/google/test_bazeldeps.py
index 62b6059495d..92ccd008d7d 100644
--- a/conans/test/integration/toolchains/google/test_bazeldeps.py
+++ b/conans/test/integration/toolchains/google/test_bazeldeps.py
@@ -880,3 +880,92 @@ 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"))
+                    # Revisit this after investigation -> build_req = conanfile.dependencies.direct_build
+                    # 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")
+        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"))
+                    # Revisit this after investigation -> build_req = conanfile.dependencies.direct_build
+                    # 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"))
+                """)
+        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