Repository: conan-io/conan

Issue:
[bug] Can't create generators folder if a source file is named after the generator folder
### Describe the bug

Discovered by @davidsanfal 

I have a source for a library that contains a `BUILD` file with instructions.
If in the `cmake_layout` I do not specify a `src_folder`, so that the layout is `<cache_internals>/b/BUILD`, the generators folder can't be created because Macos understands that a folder with that name exists (And running `mkdir build` reports the same error)

The fix is easy because you just put the source folders in a subfolder, but right now we're throwing a stacktrace when we have not been able to create the folder, but the error is not clear at all.

At the very least the makedirs function should return a cleaned up error, marking as bug until we clean it up, but we probably can't fix this

```
ERROR: Traceback (most recent call last):
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/cli/cli.py", line 308, in main
  cli.run(args)
  ~~~~~~~^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/cli/cli.py", line 193, in run
  command.run(self._conan_api, args[0][1:])
  ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/cli/command.py", line 182, in run
  info = self._method(conan_api, parser, *args)
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/cli/commands/create.py", line 101, in create
  conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/api/subapi/install.py", line 30, in install_binaries
  installer.install(deps_graph, remotes, install_order=install_order)
  ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/graph/installer.py", line 257, in install
  self._handle_package(package, install_reference, handled_count, package_count)
  ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/graph/installer.py", line 316, in _handle_package
  self._handle_node_build(package, package_layout)
  ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/graph/installer.py", line 394, in _handle_node_build
  pref = builder.build_package(node, pkg_layout)
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/graph/installer.py", line 151, in build_package
  self._build(conanfile, pref)
  ~~~~~~~~~~~^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/graph/installer.py", line 90, in _build
  write_generators(conanfile, self._hook_manager, self._home_folder)
  ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/api/install/generators.py", line 124, in write_generators
  mkdir(new_gen_folder)
  ~~~~~^^^^^^^^^^^^^^^^
 File "/Users/davidsanfal/repos/github/conan-center-index/venv/lib/python3.13/site-packages/conan/internal/util/files.py", line 256, in mkdir
  os.makedirs(path)
  ~~~~~~~~~~~^^^^^^
 File "<frozen os>", line 217, in makedirs
 File "<frozen os>", line 227, in makedirs
NotADirectoryError: [Errno 20] Not a directory: '/Users/davidsanfal/.conan2/p/b/kuber88099a8a7dd8d/b/build/Release'

ERROR: [Errno 20] Not a directory: '/Users/davidsanfal/.conan2/p/b/kuber88099a8a7dd8d/b/build/Release'
```

### How to reproduce it

Have a source folder that contains a `BUILD` **file**, use `cmake_layout` _without_ a `src_folder`, and try to write the generators for this recipe.


Discussion:

Patch:
diff --git a/conan/internal/methods.py b/conan/internal/methods.py
index 841330e1713..82c392e6552 100644
--- a/conan/internal/methods.py
+++ b/conan/internal/methods.py
@@ -24,6 +24,9 @@ def run_source_method(conanfile, hook_manager):
 
 
 def run_build_method(conanfile, hook_manager):
+    if os.path.isfile(conanfile.build_folder):
+        raise ConanException(f"{conanfile}: Failed to create build folder, there is already a file "
+                             f"named: {conanfile.build_folder}")
     mkdir(conanfile.build_folder)
     mkdir(conanfile.package_metadata_folder)
     with chdir(conanfile.build_folder):


Test patch:
diff --git a/test/integration/layout/devflow_test.py b/test/integration/layout/devflow_test.py
index 86841f7a38d..8f231e59c20 100644
--- a/test/integration/layout/devflow_test.py
+++ b/test/integration/layout/devflow_test.py
@@ -1,4 +1,5 @@
 import os
+import textwrap
 
 from conan.test.utils.tools import TestClient
 from conan.internal.util.files import load, mkdir
@@ -31,17 +32,15 @@ def package(self):
 
 class TestDevInSourceFlow:
 
-    def _assert_pkg(self, folder):
+    @staticmethod
+    def _assert_pkg(folder):
         assert sorted(['file.h', 'myartifact.lib', 'subdir', 'conaninfo.txt',
-                                 'conanmanifest.txt']) == \
-                         sorted(os.listdir(folder))
-        assert load(os.path.join(folder, "myartifact.lib")) == \
-                         "artifact contents!"
-        assert load(os.path.join(folder, "subdir/myartifact2.lib")) == \
-                         "artifact2 contents!"
+                       'conanmanifest.txt']) == sorted(os.listdir(folder))
+        assert load(os.path.join(folder, "myartifact.lib")) == "artifact contents!"
+        assert load(os.path.join(folder, "subdir/myartifact2.lib")) == "artifact2 contents!"
 
     def test_parallel_folders(self):
-        client = TestClient()
+        client = TestClient(light=True)
         repo_folder = os.path.join(client.current_folder, "recipe")
         build_folder = os.path.join(client.current_folder, "build")
         mkdir(repo_folder)
@@ -62,7 +61,7 @@ def test_parallel_folders(self):
         self._assert_pkg(cache_package_folder)
 
     def test_insource_build(self):
-        client = TestClient()
+        client = TestClient(light=True)
         repo_folder = client.current_folder
         package_folder = os.path.join(client.current_folder, "pkg")
         mkdir(package_folder)
@@ -79,7 +78,7 @@ def test_insource_build(self):
         self._assert_pkg(cache_package_folder)
 
     def test_child_build(self):
-        client = TestClient()
+        client = TestClient(light=True)
         build_folder = os.path.join(client.current_folder, "build")
         mkdir(build_folder)
         package_folder = os.path.join(build_folder, "package")
@@ -121,12 +120,13 @@ def package(self):
 
 class TestDevOutSourceFlow:
 
-    def _assert_pkg(self, folder):
+    @staticmethod
+    def _assert_pkg(folder):
         assert sorted(['file.h', 'myartifact.lib', 'conaninfo.txt', 'conanmanifest.txt']) == \
                          sorted(os.listdir(folder))
 
     def test_parallel_folders(self):
-        client = TestClient()
+        client = TestClient(light=True)
         repo_folder = os.path.join(client.current_folder, "recipe")
         src_folder = os.path.join(client.current_folder, "src")
         build_folder = os.path.join(client.current_folder, "build")
@@ -156,7 +156,7 @@ def layout(self):
         self._assert_pkg(cache_package_folder)
 
     def test_insource_build(self):
-        client = TestClient()
+        client = TestClient(light=True)
         repo_folder = client.current_folder
         client.save({"conanfile.py": conanfile_out})
 
@@ -172,7 +172,7 @@ def test_insource_build(self):
         self._assert_pkg(cache_package_folder)
 
     def test_child_build(self):
-        client = TestClient()
+        client = TestClient(light=True)
         repo_folder = client.current_folder
         build_folder = os.path.join(client.current_folder, "build")
         mkdir(build_folder)
@@ -194,3 +194,18 @@ def layout(self):
 
         cache_package_folder = client.created_layout().package()
         self._assert_pkg(cache_package_folder)
+
+
+def test_error_build_file():
+    c = TestClient(light=True)
+    conanfile_error = textwrap.dedent(r"""
+        from conan import ConanFile
+        class Test(ConanFile):
+            def layout(self):
+                self.folders.build = "build"
+        """)
+
+    c.save({"conanfile.py": conanfile_error,
+            "build": "# Some existing BUILD file like bazel"})
+    c.run("build . ", assert_error=True)
+    assert "ERROR: conanfile.py: Failed to create build folder, there is already a file" in c.out