Repository: conan-io/conan

Issue:
Default ``cmake_layout()`` source folder
This layout is assuming that the main library ``CMakeLists.txt`` is inside a ``src`` subfolder in the repo.

This is probably not the most common user layout, in which they will have a CMakeLists.txt in the root of the folder:

- How to model this?
- Should we change the ``cmake_layout()`` default to ``folders.source = "."``?
- Check implications of defining the root as source folder.


Discussion:
A good reason for having a `CMakeLists.txt` file in the project root is that is used as an entry point for most IDEs. Having it in the `src` subdirectory could be problematic for some IDEs.

Resolving patch:
diff --git a/conan/tools/layout/__init__.py b/conan/tools/layout/__init__.py
--- a/conan/tools/layout/__init__.py
+++ b/conan/tools/layout/__init__.py
@@ -14,7 +14,7 @@ def cmake_layout(conanfile, generator=None):
     else:
         multi = False
 
-    conanfile.folders.source = "src"
+    conanfile.folders.source = "."
     if multi:
         conanfile.folders.build = "build"
         conanfile.folders.generators = "build/conan"
@@ -23,7 +23,7 @@ def cmake_layout(conanfile, generator=None):
         conanfile.folders.build = "cmake-build-{}".format(build_type)
         conanfile.folders.generators = os.path.join(conanfile.folders.build, "conan")
 
-    conanfile.cpp.source.includedirs = ["."]
+    conanfile.cpp.source.includedirs = ["src"]
     if multi:
         conanfile.cpp.build.libdirs = ["{}".format(conanfile.settings.build_type)]
         conanfile.cpp.build.bindirs = ["{}".format(conanfile.settings.build_type)]
diff --git a/conans/assets/templates/new_v2_cmake.py b/conans/assets/templates/new_v2_cmake.py
--- a/conans/assets/templates/new_v2_cmake.py
+++ b/conans/assets/templates/new_v2_cmake.py
@@ -20,7 +20,7 @@ class {package_name}Conan(ConanFile):
     default_options = {{"shared": False, "fPIC": True}}
 
     # Sources are located in the same place as this recipe, copy them to the recipe
-    exports_sources = "src/*"
+    exports_sources = "CMakeLists.txt", "src/*"
 
     def config_options(self):
         if self.settings.os == "Windows":
@@ -81,7 +81,7 @@ def test(self):
 
 find_package({name} CONFIG REQUIRED)
 
-add_executable(example example.cpp)
+add_executable(example src/example.cpp)
 target_link_libraries(example {name}::{name})
 """
 
@@ -89,9 +89,9 @@ def test(self):
 cmake_v2 = """cmake_minimum_required(VERSION 3.15)
 project({name} CXX)
 
-add_library({name} {name}.cpp)
+add_library({name} src/{name}.cpp)
 
-set_target_properties({name} PROPERTIES PUBLIC_HEADER "{name}.h")
+set_target_properties({name} PROPERTIES PUBLIC_HEADER "src/{name}.h")
 install(TARGETS {name} DESTINATION "."
         PUBLIC_HEADER DESTINATION include
         RUNTIME DESTINATION bin
@@ -216,12 +216,12 @@ def get_cmake_lib_files(name, version, package_name="Pkg"):
                                                          package_name=package_name),
              "src/{}.cpp".format(name): source_cpp.format(name=name, version=version),
              "src/{}.h".format(name): source_h.format(name=name, version=version),
-             "src/CMakeLists.txt": cmake_v2.format(name=name, version=version),
+             "CMakeLists.txt": cmake_v2.format(name=name, version=version),
              "test_package/conanfile.py": test_conanfile_v2.format(name=name,
                                                                    version=version,
                                                                    package_name=package_name),
              "test_package/src/example.cpp": test_main.format(name=name),
-             "test_package/src/CMakeLists.txt": test_cmake_v2.format(name=name)}
+             "test_package/CMakeLists.txt": test_cmake_v2.format(name=name)}
     return files
 
 
@@ -245,7 +245,7 @@ class {package_name}Conan(ConanFile):
     settings = "os", "compiler", "build_type", "arch"
 
     # Sources are located in the same place as this recipe, copy them to the recipe
-    exports_sources = "src/*"
+    exports_sources = "CMakeLists.txt", "src/*"
 
     def layout(self):
         cmake_layout(self)
@@ -267,7 +267,7 @@ def package(self):
 cmake_exe_v2 = """cmake_minimum_required(VERSION 3.15)
 project({name} CXX)
 
-add_executable({name} {name}.cpp main.cpp)
+add_executable({name} src/{name}.cpp src/main.cpp)
 
 install(TARGETS {name} DESTINATION "."
         RUNTIME DESTINATION bin
@@ -299,7 +299,7 @@ def get_cmake_exe_files(name, version, package_name="Pkg"):
              "src/{}.cpp".format(name): source_cpp.format(name=name, version=version),
              "src/{}.h".format(name): source_h.format(name=name, version=version),
              "src/main.cpp": test_main.format(name=name),
-             "src/CMakeLists.txt": cmake_exe_v2.format(name=name, version=version),
+             "CMakeLists.txt": cmake_exe_v2.format(name=name, version=version),
              "test_package/conanfile.py": test_conanfile_exe_v2.format(name=name,
                                                                        version=version,
                                                                        package_name=package_name)


Test patch:
diff --git a/conans/test/assets/pkg_cmake.py b/conans/test/assets/pkg_cmake.py
--- a/conans/test/assets/pkg_cmake.py
+++ b/conans/test/assets/pkg_cmake.py
@@ -18,7 +18,7 @@ def pkg_cmake(name, version, requires=None, exe=False):
         class Pkg(ConanFile):
             name = "{pkg_name}"
             version = "{version}"
-            exports_sources = "src/*"
+            exports_sources = "CMakeLists.txt", "src/*"
             {deps}
             settings = "os", "compiler", "arch", "build_type"
             options = {{"shared": [True, False]}}
@@ -34,7 +34,7 @@ def build(self):
                 cmake.build()
 
             def package(self):
-                self.copy("*.h", dst="include")
+                self.copy("*.h", dst="include", src="src")
                 self.copy("*.lib", dst="lib", keep_path=False)
                 self.copy("*.dll", dst="bin", keep_path=False)
                 self.copy("*.dylib*", dst="lib", keep_path=False)
@@ -60,11 +60,11 @@ def package_info(self):
     if exe:
         src_app = gen_function_cpp(name="main", includes=[name], calls=[name])
         files["src/{}_app.cpp".format(name)] = src_app
-        cmake = gen_cmakelists(appname="{}_app".format(name), appsources=["{}_app.cpp".format(name)],
-                               libname=name, libsources=["{}.cpp".format(name)], find_package=deps)
+        cmake = gen_cmakelists(appname="{}_app".format(name), appsources=["src/{}_app.cpp".format(name)],
+                               libname=name, libsources=["src/{}.cpp".format(name)], find_package=deps)
     else:
-        cmake = gen_cmakelists(libname=name, libsources=["{}.cpp".format(name)], find_package=deps)
-    files["src/CMakeLists.txt"] = cmake
+        cmake = gen_cmakelists(libname=name, libsources=["src/{}.cpp".format(name)], find_package=deps)
+    files["CMakeLists.txt"] = cmake
     return files
 
 
@@ -94,10 +94,10 @@ def test(self):
 
     deps = [require_name]
     src = gen_function_cpp(name="main", includes=deps, calls=deps)
-    cmake = gen_cmakelists(appname="test", appsources=["test.cpp"], find_package=deps)
+    cmake = gen_cmakelists(appname="test", appsources=["src/test.cpp"], find_package=deps)
 
     return {"test_package/src/test.cpp": src,
-            "test_package/src/CMakeLists.txt": cmake,
+            "test_package/CMakeLists.txt": cmake,
             "test_package/conanfile.py": conanfile}
 
 
@@ -114,7 +114,7 @@ def pkg_cmake_app(name, version, requires=None):
         class Pkg(ConanFile):
             name = "{pkg_name}"
             version = "{version}"
-            exports_sources = "src/*"
+            exports_sources = "CMakeLists.txt", "src/*"
             {deps}
             settings = "os", "compiler", "arch", "build_type"
             generators = "CMakeToolchain", "CMakeDeps"
@@ -137,8 +137,8 @@ def package(self):
     deps = [r.name.replace(".", "_") for r in refs]
     src = gen_function_cpp(name="main", includes=deps, calls=deps)
     deps = [r.name for r in refs]
-    cmake = gen_cmakelists(appname=name, appsources=["{}.cpp".format(name)], find_package=deps)
+    cmake = gen_cmakelists(appname=name, appsources=["src/{}.cpp".format(name)], find_package=deps)
 
     return {"src/{}.cpp".format(name): src,
-            "src/CMakeLists.txt": cmake,
+            "CMakeLists.txt": cmake,
             "conanfile.py": conanfile}
diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_weird_library_names.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_weird_library_names.py
--- a/conans/test/functional/toolchains/cmake/cmakedeps/test_weird_library_names.py
+++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_weird_library_names.py
@@ -18,7 +18,7 @@ def client_weird_lib_name():
         from conan.tools.layout import cmake_layout
 
         class Pkg(ConanFile):
-            exports_sources = "src/*"
+            exports_sources = "CMakeLists.txt", "src/*"
             settings = "os", "compiler", "arch", "build_type"
             generators = "CMakeToolchain", "CMakeDeps"
 
@@ -31,7 +31,7 @@ def build(self):
                 cmake.build()
 
             def package(self):
-                self.copy("*.h", dst="include")
+                self.copy("*.h", dst="include", src="src")
                 self.copy("*.lib", dst="lib", keep_path=False)
                 self.copy("*.a", dst="lib", keep_path=False)
                 ext = "a" if platform.system() != "Windows" else "lib"
@@ -46,11 +46,11 @@ def package_info(self):
 
     hdr = gen_function_h(name="hello")
     src = gen_function_cpp(name="hello")
-    cmake = gen_cmakelists(libname="hello_0.1", libsources=["hello.cpp"])
+    cmake = gen_cmakelists(libname="hello_0.1", libsources=["src/hello.cpp"])
 
     c.save({"src/hello.h": hdr,
             "src/hello.cpp": src,
-            "src/CMakeLists.txt": cmake,
+            "CMakeLists.txt": cmake,
             "conanfile.py": conanfile})
     c.run("create . hello/0.1@")
     return c
@@ -74,14 +74,14 @@ def test_cmake_find_package(client_weird_lib_name):
         from conans import ConanFile, CMake
 
         class Pkg(ConanFile):
-            exports_sources = "src/*"
+            exports_sources = "CMakeLists.txt", "src/*"
             settings = "os", "compiler", "arch", "build_type"
             generators = "cmake_find_package"
             requires = "hello/0.1"
 
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure()
                 cmake.build()
         """)
     files["conanfile.py"] = conanfile
@@ -100,14 +100,14 @@ def test_cmake_find_package_multi(client_weird_lib_name):
         from conans import ConanFile, CMake
 
         class Pkg(ConanFile):
-            exports_sources = "src/*"
+            exports_sources = "CMakeLists.txt", "src/*"
             settings = "os", "compiler", "arch", "build_type"
             generators = "cmake_find_package_multi"
             requires = "hello/0.1"
 
             def build(self):
                 cmake = CMake(self)
-                cmake.configure(source_folder="src")
+                cmake.configure()
                 cmake.build()
         """)
     files["conanfile.py"] = conanfile
diff --git a/conans/test/integration/command/new_test.py b/conans/test/integration/command/new_test.py
--- a/conans/test/integration/command/new_test.py
+++ b/conans/test/integration/command/new_test.py
@@ -384,7 +384,7 @@ def test_new_cmake_lib(self):
         self.assertIn("CMakeToolchain", conanfile)
         conanfile = client.load("test_package/conanfile.py")
         self.assertIn("CMakeToolchain", conanfile)
-        cmake = client.load("test_package/src/CMakeLists.txt")
+        cmake = client.load("test_package/CMakeLists.txt")
         self.assertIn("find_package", cmake)
 
     def test_new_reference(self):