diff --git a/conan/tools/cmake/layout.py b/conan/tools/cmake/layout.py index e792280c2f0..ac6145258ac 100644 --- a/conan/tools/cmake/layout.py +++ b/conan/tools/cmake/layout.py @@ -20,17 +20,17 @@ def cmake_layout(conanfile, generator=None, src_folder="."): except ConanException: raise ConanException("'build_type' setting not defined, it is necessary for cmake_layout()") - suffix = get_build_folder_vars_suffix(conanfile) + build_folder = "build" + custom_conf = get_build_folder_custom_vars(conanfile) + if custom_conf: + build_folder = "{}/{}".format(build_folder, custom_conf) + if multi: - conanfile.folders.build = "build" + conanfile.folders.build = build_folder else: - conanfile.folders.build = "cmake-build-{}".format(str(build_type).lower()) - - if suffix: - conanfile.folders.build += "-{}".format(suffix) + conanfile.folders.build = "{}/{}".format(build_folder, build_type) - conanfile.folders.generators = os.path.join("build" if not suffix else "build-{}".format(suffix), - "generators") + conanfile.folders.generators = "{}/{}".format(build_folder, "generators") conanfile.cpp.source.includedirs = ["include"] @@ -42,7 +42,7 @@ def cmake_layout(conanfile, generator=None, src_folder="."): conanfile.cpp.build.bindirs = ["."] -def get_build_folder_vars_suffix(conanfile): +def get_build_folder_custom_vars(conanfile): build_vars = conanfile.conf.get("tools.cmake.cmake_layout:build_folder_vars", default=[], check_type=list) diff --git a/conan/tools/cmake/presets.py b/conan/tools/cmake/presets.py index f76323a3050..81461199df5 100644 --- a/conan/tools/cmake/presets.py +++ b/conan/tools/cmake/presets.py @@ -2,7 +2,7 @@ import os import platform -from conan.tools.cmake.layout import get_build_folder_vars_suffix +from conan.tools.cmake.layout import get_build_folder_custom_vars from conan.tools.cmake.utils import is_multi_configuration from conans.errors import ConanException from conans.util.files import save, load @@ -20,22 +20,27 @@ def _add_build_preset(conanfile, multiconfig): def _build_preset_name(conanfile): build_type = conanfile.settings.get_safe("build_type") - suffix = get_build_folder_vars_suffix(conanfile) - if suffix: + custom_conf = get_build_folder_custom_vars(conanfile) + if custom_conf: if build_type: - return "{}-{}".format(build_type, suffix) + return "{}-{}".format(custom_conf, build_type.lower()) else: - return suffix - return build_type or "default" + return custom_conf + return build_type.lower() if build_type else "default" def _configure_preset_name(conanfile, multiconfig): build_type = conanfile.settings.get_safe("build_type") - suffix = get_build_folder_vars_suffix(conanfile) - base = "default" if multiconfig or not build_type else build_type - if suffix: - return "{}-{}".format(base, suffix) - return base + custom_conf = get_build_folder_custom_vars(conanfile) + + if multiconfig or not build_type: + return "default" if not custom_conf else custom_conf + + if custom_conf: + return "{}-{}".format(custom_conf, str(build_type).lower()) + else: + return str(build_type).lower() + def _add_configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig): diff --git a/conans/test/functional/layout/test_build_system_layout_helpers.py b/conans/test/functional/layout/test_build_system_layout_helpers.py index 93e6b485945..25fb7f73d7a 100644 --- a/conans/test/functional/layout/test_build_system_layout_helpers.py +++ b/conans/test/functional/layout/test_build_system_layout_helpers.py @@ -172,7 +172,7 @@ def package(self): client.run("source .") assert os.path.exists(os.path.join(client.current_folder, "src", "source.txt")) client.run("build .") - contents = load(os.path.join(client.current_folder, "cmake-build-release", "build.txt")) + contents = load(os.path.join(client.current_folder, "build", "Release", "build.txt")) assert contents == "fooexported_contents" client.run("export-pkg . foo/1.0@ --force") assert "Packaged 1 '.txt' file: build.txt" in client.out diff --git a/conans/test/functional/layout/test_editable_cmake.py b/conans/test/functional/layout/test_editable_cmake.py index 8845f281640..a7e01b4e155 100644 --- a/conans/test/functional/layout/test_editable_cmake.py +++ b/conans/test/functional/layout/test_editable_cmake.py @@ -11,8 +11,6 @@ def editable_cmake(generator, build_folder=None): - multi = (generator is None and platform.system() == "Windows") or \ - generator in ("Ninja Multi-Config", "Xcode") c = TestClient() if generator is not None: c.save({"global.conf": "tools.cmake.cmaketoolchain:generator={}".format(generator)}, @@ -36,12 +34,12 @@ def build_dep(): def build_pkg(msg): c.run("build . -if=install_release") - folder = os.path.join("build", "Release") if multi else "cmake-build-release" + folder = os.path.join("build", "Release") c.run_command(os.sep.join([".", folder, "pkg"])) assert "main: Release!" in c.out assert "{}: Release!".format(msg) in c.out c.run("build . -if=install_debug") - folder = os.path.join("build", "Debug") if multi else "cmake-build-debug" + folder = os.path.join("build", "Debug") c.run_command(os.sep.join([".", folder, "pkg"])) assert "main: Debug!" in c.out assert "{}: Debug!".format(msg) in c.out diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py index 61bd524ca08..8b1311a599e 100644 --- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py +++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py @@ -109,9 +109,9 @@ def layout(self): t.run("install . -s:h build_type=Debug -g CMakeToolchain") t.run("install . -s:h build_type=Release -g CMakeToolchain") assert os.path.exists(os.path.join(t.current_folder, "CMakeUserPresets.json")) - t.run_command("cmake . --preset Release") + t.run_command("cmake . --preset release") assert 'CMAKE_BUILD_TYPE="Release"' in t.out - t.run_command("cmake . --preset Debug") + t.run_command("cmake . --preset debug") assert 'CMAKE_BUILD_TYPE="Debug"' in t.out @@ -362,7 +362,7 @@ def build(self): "CMakeLists.txt": cmakelists}, clean_first=True) client.run("install . -pr=./profile -if=install") client.run("build . -if=install") - exe = "cmake-build-release/example" if platform.system() != "Windows" else r"build\Release\example.exe" + exe = "build/Release/example" if platform.system() != "Windows" else r"build\Release\example.exe" client.run_command(exe) assert 'escape=partially "escaped"' in client.out assert 'spaces=me you' in client.out @@ -379,7 +379,7 @@ def build(self): client.run("install . -pr=./profile -if=install -s build_type=Debug") client.run("build . -if=install -s build_type=Debug") - exe = "cmake-build-debug/example" if platform.system() != "Windows" else r"build\Debug\example.exe" + exe = "build/Debug/example" if platform.system() != "Windows" else r"build\Debug\example.exe" client.run_command(exe) assert 'escape_debug=debug partially "escaped"' in client.out assert 'spaces_debug=debug me you' in client.out @@ -554,7 +554,7 @@ def test_cmake_presets_multiple_settings_single_config(): settings = "-s compiler=apple-clang -s compiler.libcxx=libc++ " \ "-s compiler.version=12.0 -s compiler.cppstd=gnu17" client.run("install . {} {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-apple-clang-12.0-gnu17", + assert os.path.exists(os.path.join(client.current_folder, "build", "apple-clang-12.0-gnu17", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) @@ -562,33 +562,33 @@ def test_cmake_presets_multiple_settings_single_config(): presets = json.loads(load(user_presets["include"][0])) assert len(presets["configurePresets"]) == 1 assert len(presets["buildPresets"]) == 1 - assert presets["configurePresets"][0]["name"] == "Release-apple-clang-12.0-gnu17" - assert presets["buildPresets"][0]["name"] == "Release-apple-clang-12.0-gnu17" - assert presets["buildPresets"][0]["configurePreset"] == "Release-apple-clang-12.0-gnu17" + assert presets["configurePresets"][0]["name"] == "apple-clang-12.0-gnu17-release" + assert presets["buildPresets"][0]["name"] == "apple-clang-12.0-gnu17-release" + assert presets["buildPresets"][0]["configurePreset"] == "apple-clang-12.0-gnu17-release" # If we create the "Debug" one, it has the same toolchain and preset file, that is # always multiconfig client.run("install . {} -s build_type=Debug {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-apple-clang-12.0-gnu17", "generators")) + assert os.path.exists(os.path.join(client.current_folder, "build", "apple-clang-12.0-gnu17", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) assert len(user_presets["include"]) == 1 presets = json.loads(load(user_presets["include"][0])) assert len(presets["configurePresets"]) == 2 assert len(presets["buildPresets"]) == 2 - assert presets["configurePresets"][0]["name"] == "Release-apple-clang-12.0-gnu17" - assert presets["configurePresets"][1]["name"] == "Debug-apple-clang-12.0-gnu17" - assert presets["buildPresets"][0]["name"] == "Release-apple-clang-12.0-gnu17" - assert presets["buildPresets"][1]["name"] == "Debug-apple-clang-12.0-gnu17" - assert presets["buildPresets"][0]["configurePreset"] == "Release-apple-clang-12.0-gnu17" - assert presets["buildPresets"][1]["configurePreset"] == "Debug-apple-clang-12.0-gnu17" + assert presets["configurePresets"][0]["name"] == "apple-clang-12.0-gnu17-release" + assert presets["configurePresets"][1]["name"] == "apple-clang-12.0-gnu17-debug" + assert presets["buildPresets"][0]["name"] == "apple-clang-12.0-gnu17-release" + assert presets["buildPresets"][1]["name"] == "apple-clang-12.0-gnu17-debug" + assert presets["buildPresets"][0]["configurePreset"] == "apple-clang-12.0-gnu17-release" + assert presets["buildPresets"][1]["configurePreset"] == "apple-clang-12.0-gnu17-debug" # But If we change, for example, the cppstd and the compiler version, the toolchain # and presets will be different, but it will be appended to the UserPresets.json settings = "-s compiler=apple-clang -s compiler.libcxx=libc++ " \ "-s compiler.version=13 -s compiler.cppstd=gnu20" client.run("install . {} {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-apple-clang-13-gnu20", + assert os.path.exists(os.path.join(client.current_folder, "build", "apple-clang-13-gnu20", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) @@ -597,27 +597,27 @@ def test_cmake_presets_multiple_settings_single_config(): presets = json.loads(load(user_presets["include"][1])) assert len(presets["configurePresets"]) == 1 assert len(presets["buildPresets"]) == 1 - assert presets["configurePresets"][0]["name"] == "Release-apple-clang-13-gnu20" - assert presets["buildPresets"][0]["name"] == "Release-apple-clang-13-gnu20" - assert presets["buildPresets"][0]["configurePreset"] == "Release-apple-clang-13-gnu20" + assert presets["configurePresets"][0]["name"] == "apple-clang-13-gnu20-release" + assert presets["buildPresets"][0]["name"] == "apple-clang-13-gnu20-release" + assert presets["buildPresets"][0]["configurePreset"] == "apple-clang-13-gnu20-release" # We can build with cmake manually if platform.system() == "Darwin": - client.run_command("cmake . --preset Release-apple-clang-12.0-gnu17") - client.run_command("cmake --build --preset Release-apple-clang-12.0-gnu17") - client.run_command("./cmake-build-release-apple-clang-12.0-gnu17/hello") + client.run_command("cmake . --preset apple-clang-12.0-gnu17-release") + client.run_command("cmake --build --preset apple-clang-12.0-gnu17-release") + client.run_command("./build/apple-clang-12.0-gnu17/Release/hello") assert "Hello World Release!" in client.out assert "__cplusplus2017" in client.out - client.run_command("cmake . --preset Debug-apple-clang-12.0-gnu17") - client.run_command("cmake --build --preset Debug-apple-clang-12.0-gnu17") - client.run_command("./cmake-build-debug-apple-clang-12.0-gnu17/hello") + client.run_command("cmake . --preset apple-clang-12.0-gnu17-debug") + client.run_command("cmake --build --preset apple-clang-12.0-gnu17-debug") + client.run_command("./build/apple-clang-12.0-gnu17/Debug/hello") assert "Hello World Debug!" in client.out assert "__cplusplus2017" in client.out - client.run_command("cmake . --preset Release-apple-clang-13-gnu20") - client.run_command("cmake --build --preset Release-apple-clang-13-gnu20") - client.run_command("./cmake-build-release-apple-clang-13-gnu20/hello") + client.run_command("cmake . --preset apple-clang-13-gnu20-release") + client.run_command("cmake --build --preset apple-clang-13-gnu20-release") + client.run_command("./build/apple-clang-13-gnu20/Release/hello") assert "Hello World Release!" in client.out assert "__cplusplus2020" in client.out @@ -637,12 +637,12 @@ def test_cmake_presets_options_single_config(): client.run("install . {} -o shared={}".format(conf_layout, shared)) shared_str = "shared_true" if shared else "shared_false" assert os.path.exists(os.path.join(client.current_folder, - "build-{}-{}".format(default_compiler, shared_str), + "build", "{}-{}".format(default_compiler, shared_str), "generators")) client.run("install . {}".format(conf_layout)) assert os.path.exists(os.path.join(client.current_folder, - "build-{}-shared_false".format(default_compiler), + "build", "{}-shared_false".format(default_compiler), "generators")) user_presets_path = os.path.join(client.current_folder, "CMakeUserPresets.json") @@ -652,12 +652,11 @@ def test_cmake_presets_options_single_config(): if platform.system() == "Darwin": for shared in (True, False): shared_str = "shared_true" if shared else "shared_false" - client.run_command("cmake . --preset Release-apple-clang-{}".format(shared_str)) - client.run_command("cmake --build --preset Release-apple-clang-{}".format(shared_str)) + client.run_command("cmake . --preset apple-clang-{}-release".format(shared_str)) + client.run_command("cmake --build --preset apple-clang-{}-release".format(shared_str)) the_lib = "libhello.a" if not shared else "libhello.dylib" path = os.path.join(client.current_folder, - "cmake-build-release-apple-clang-{}".format(shared_str), - the_lib) + "build", "apple-clang-{}".format(shared_str), "release", the_lib) assert os.path.exists(path) @@ -675,39 +674,39 @@ def test_cmake_presets_multiple_settings_multi_config(): settings = "-s compiler=msvc -s compiler.version=191 -s compiler.runtime=dynamic " \ "-s compiler.cppstd=14" client.run("install . {} {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-dynamic-14", "generators")) + assert os.path.exists(os.path.join(client.current_folder, "build", "dynamic-14", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) assert len(user_presets["include"]) == 1 presets = json.loads(load(user_presets["include"][0])) assert len(presets["configurePresets"]) == 1 assert len(presets["buildPresets"]) == 1 - assert presets["configurePresets"][0]["name"] == "default-dynamic-14" - assert presets["buildPresets"][0]["name"] == "Release-dynamic-14" - assert presets["buildPresets"][0]["configurePreset"] == "default-dynamic-14" + assert presets["configurePresets"][0]["name"] == "dynamic-14" + assert presets["buildPresets"][0]["name"] == "dynamic-14-release" + assert presets["buildPresets"][0]["configurePreset"] == "dynamic-14" # If we create the "Debug" one, it has the same toolchain and preset file, that is # always multiconfig client.run("install . {} -s build_type=Debug {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-dynamic-14", "generators")) + assert os.path.exists(os.path.join(client.current_folder, "build", "dynamic-14", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) assert len(user_presets["include"]) == 1 presets = json.loads(load(user_presets["include"][0])) assert len(presets["configurePresets"]) == 1 assert len(presets["buildPresets"]) == 2 - assert presets["configurePresets"][0]["name"] == "default-dynamic-14" - assert presets["buildPresets"][0]["name"] == "Release-dynamic-14" - assert presets["buildPresets"][1]["name"] == "Debug-dynamic-14" - assert presets["buildPresets"][0]["configurePreset"] == "default-dynamic-14" - assert presets["buildPresets"][1]["configurePreset"] == "default-dynamic-14" + assert presets["configurePresets"][0]["name"] == "dynamic-14" + assert presets["buildPresets"][0]["name"] == "dynamic-14-release" + assert presets["buildPresets"][1]["name"] == "dynamic-14-debug" + assert presets["buildPresets"][0]["configurePreset"] == "dynamic-14" + assert presets["buildPresets"][1]["configurePreset"] == "dynamic-14" # But If we change, for example, the cppstd and the compiler version, the toolchain # and presets will be different, but it will be appended to the UserPresets.json settings = "-s compiler=msvc -s compiler.version=191 -s compiler.runtime=static " \ "-s compiler.cppstd=17" client.run("install . {} {}".format(settings, settings_layout)) - assert os.path.exists(os.path.join(client.current_folder, "build-static-17", "generators")) + assert os.path.exists(os.path.join(client.current_folder, "build", "static-17", "generators")) assert os.path.exists(user_presets_path) user_presets = json.loads(load(user_presets_path)) # The [0] is the msvc dynamic/14 the [1] is the static/17 @@ -715,27 +714,27 @@ def test_cmake_presets_multiple_settings_multi_config(): presets = json.loads(load(user_presets["include"][1])) assert len(presets["configurePresets"]) == 1 assert len(presets["buildPresets"]) == 1 - assert presets["configurePresets"][0]["name"] == "default-static-17" - assert presets["buildPresets"][0]["name"] == "Release-static-17" - assert presets["buildPresets"][0]["configurePreset"] == "default-static-17" + assert presets["configurePresets"][0]["name"] == "static-17" + assert presets["buildPresets"][0]["name"] == "static-17-release" + assert presets["buildPresets"][0]["configurePreset"] == "static-17" # We can build with cmake manually - client.run_command("cmake . --preset default-dynamic-14") + client.run_command("cmake . --preset dynamic-14") - client.run_command("cmake --build --preset Release-dynamic-14") - client.run_command("build-dynamic-14\\Release\\hello") + client.run_command("cmake --build --preset dynamic-14-release") + client.run_command("build\\dynamic-14\\Release\\hello") assert "Hello World Release!" in client.out assert "MSVC_LANG2014" in client.out - client.run_command("cmake --build --preset Debug-dynamic-14") - client.run_command("build-dynamic-14\\Debug\\hello") + client.run_command("cmake --build --preset dynamic-14-debug") + client.run_command("build\\dynamic-14\\Debug\\hello") assert "Hello World Debug!" in client.out assert "MSVC_LANG2014" in client.out - client.run_command("cmake . --preset default-static-17") + client.run_command("cmake . --preset static-17") - client.run_command("cmake --build --preset Release-static-17") - client.run_command("build-static-17\\Release\\hello") + client.run_command("cmake --build --preset static-17-release") + client.run_command("build\\static-17\\Release\\hello") assert "Hello World Release!" in client.out assert "MSVC_LANG2017" in client.out @@ -815,22 +814,22 @@ def test_cmake_presets_with_conanfile_txt(): assert os.path.exists(presets_path) if platform.system() != "Windows": - c.run_command("cmake --preset Debug") - c.run_command("cmake --build --preset Debug") - c.run_command("./cmake-build-debug/foo") + c.run_command("cmake --preset debug") + c.run_command("cmake --build --preset debug") + c.run_command("./build/Debug/foo") else: c.run_command("cmake --preset default") - c.run_command("cmake --build --preset Debug") + c.run_command("cmake --build --preset debug") c.run_command("build\\Debug\\foo") assert "Hello World Debug!" in c.out if platform.system() != "Windows": - c.run_command("cmake --preset Release") - c.run_command("cmake --build --preset Release") - c.run_command("./cmake-build-release/foo") + c.run_command("cmake --preset release") + c.run_command("cmake --build --preset release") + c.run_command("./build/Release/foo") else: - c.run_command("cmake --build --preset Release") + c.run_command("cmake --build --preset release") c.run_command("build\\Release\\foo") assert "Hello World Release!" in c.out diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py index 51e390e0ff4..615bd76deeb 100644 --- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py +++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain_m1.py @@ -62,8 +62,8 @@ def build(self): system_name = 'Darwin' if op_system == 'Macos' else 'iOS' assert "CMAKE_SYSTEM_NAME: {}".format(system_name) in client.out assert "CMAKE_SYSTEM_PROCESSOR: arm64" in client.out - main_path = "./cmake-build-release/main.app/main" if op_system == "iOS" \ - else "./cmake-build-release/main" + main_path = "./build/Release/main.app/main" if op_system == "iOS" \ + else "./build/Release/main" client.run_command(main_path, assert_error=True) assert "Bad CPU type in executable" in client.out client.run_command("lipo -info {}".format(main_path)) diff --git a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py index 41ea9472475..41a46681e8e 100644 --- a/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py +++ b/conans/test/integration/toolchains/cmake/test_cmaketoolchain.py @@ -349,7 +349,7 @@ def layout(self): client.save({"conanfile.py": conanfile}) client.run("install .") if platform.system() != "Windows": - build_dir = os.path.join(client.current_folder, "cmake-build-release") + build_dir = os.path.join(client.current_folder, "build", "Release") else: build_dir = os.path.join(client.current_folder, "build") @@ -421,19 +421,19 @@ def test_cmake_presets_singleconfig(): client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=Release --profile:h=profile") presets = json.loads(client.load("CMakePresets.json")) assert len(presets["configurePresets"]) == 1 - assert presets["configurePresets"][0]["name"] == "Release" + assert presets["configurePresets"][0]["name"] == "release" assert len(presets["buildPresets"]) == 1 - assert presets["buildPresets"][0]["configurePreset"] == "Release" + assert presets["buildPresets"][0]["configurePreset"] == "release" # Now two configurePreset, but named correctly client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=Debug --profile:h=profile") presets = json.loads(client.load("CMakePresets.json")) assert len(presets["configurePresets"]) == 2 - assert presets["configurePresets"][1]["name"] == "Debug" + assert presets["configurePresets"][1]["name"] == "debug" assert len(presets["buildPresets"]) == 2 - assert presets["buildPresets"][1]["configurePreset"] == "Debug" + assert presets["buildPresets"][1]["configurePreset"] == "debug" # Repeat configuration, it shouldn't add a new one client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=Debug --profile:h=profile")