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

[develop2] improve build_folder_vars, only affecting in user space #13109

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 18 additions & 5 deletions conan/tools/cmake/layout.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os

from conans.client.graph.graph import RECIPE_CONSUMER
from conans.errors import ConanException


Expand Down Expand Up @@ -50,13 +51,22 @@ def cmake_layout(conanfile, generator=None, src_folder=".", build_folder="build"


def get_build_folder_custom_vars(conanfile):

conanfile_vars = conanfile.folders.build_folder_vars
build_vars = conanfile.conf.get("tools.cmake.cmake_layout:build_folder_vars", check_type=list)
if conanfile.tested_reference_str:
build_vars = ["settings.compiler", "settings.compiler.version", "settings.arch",
build_vars = build_vars or conanfile_vars or \
["settings.compiler", "settings.compiler.version", "settings.arch",
"settings.compiler.cppstd", "settings.build_type", "options.shared"]
else:
build_vars = conanfile.conf.get("tools.cmake.cmake_layout:build_folder_vars",
default=[], check_type=list)
try:
is_consumer = conanfile._conan_node.recipe == RECIPE_CONSUMER
except AttributeError:
is_consumer = False
if is_consumer:
build_vars = build_vars or conanfile_vars or []
else:
build_vars = conanfile_vars or []

ret = []
for s in build_vars:
group, var = s.split(".", 1)
Expand All @@ -66,7 +76,10 @@ def get_build_folder_custom_vars(conanfile):
elif group == "options":
value = conanfile.options.get_safe(var)
if value is not None:
tmp = "{}_{}".format(var, value)
if var == "shared":
tmp = "shared" if value else "static"
else:
tmp = "{}_{}".format(var, value)
else:
raise ConanException("Invalid 'tools.cmake.cmake_layout:build_folder_vars' value, it has"
" to start with 'settings.' or 'options.': {}".format(s))
Expand Down
1 change: 1 addition & 0 deletions conans/model/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(self):
# conanfile.py, that makes most of the output folders defined in layouts (cmake_layout, etc)
# start from the subproject again
self.subproject = None
self.build_folder_vars = None

def __repr__(self):
return str(self.__dict__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,14 +744,14 @@ def test_cmake_presets_options_single_config():

for shared in (True, False):
client.run("install . {} -o shared={}".format(conf_layout, shared))
shared_str = "shared_true" if shared else "shared_false"
shared_str = "shared" if shared else "static"
assert os.path.exists(os.path.join(client.current_folder,
"build", "{}-release-{}".format(default_compiler, shared_str),
"generators"))

client.run("install . {}".format(conf_layout))
assert os.path.exists(os.path.join(client.current_folder,
"build", "{}-release-shared_false".format(default_compiler),
"build", "{}-release-static".format(default_compiler),
"generators"))

user_presets_path = os.path.join(client.current_folder, "CMakeUserPresets.json")
Expand All @@ -760,7 +760,7 @@ def test_cmake_presets_options_single_config():
# We can build with cmake manually
if platform.system() == "Darwin":
for shared in (True, False):
shared_str = "shared_true" if shared else "shared_false"
shared_str = "shared" if shared else "static"
client.run_command("cmake . --preset conan-apple-clang-release-{}".format(shared_str))
client.run_command("cmake --build --preset conan-apple-clang-release-{}".format(shared_str))
client.run_command("ctest --preset conan-apple-clang-release-{}".format(shared_str))
Expand Down
71 changes: 56 additions & 15 deletions conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from conan.tools.cmake.presets import load_cmake_presets
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient
from conans.util.files import rmdir
from conans.util.files import rmdir, load


def test_cross_build():
Expand Down Expand Up @@ -957,7 +957,6 @@ def test_test_package_layout():
class Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain"
test_type = "explicit"

def requirements(self):
self.requires(self.tested_reference_str)
Expand All @@ -982,27 +981,69 @@ def test(self):

def test_presets_not_found_error_msg():
client = TestClient()
test_conanfile = textwrap.dedent("""
conanfile = textwrap.dedent("""
from conan import ConanFile
from conan.tools.cmake import cmake_layout, CMake
from conan.tools.cmake import CMake

class Conan(ConanFile):
settings = "build_type"
generators = "CMakeDeps"
test_type = "explicit"

def requirements(self):
self.requires(self.tested_reference_str)

def build(self):
CMake(self).configure()

def test(self):
pass
""")
client.save({"conanfile.py": GenConanfile("pkg", "0.1"),
"test_package/conanfile.py": test_conanfile})
client.run("create .", assert_error=True)
client.save({"conanfile.py": conanfile})
client.run("build .", assert_error=True)
assert "CMakePresets.json was not found" in client.out
assert "Check that you are using CMakeToolchain as generator " \
"to ensure its correct initialization." in client.out


def test_recipe_build_folders_vars():
client = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
from conan.tools.cmake import cmake_layout

class Conan(ConanFile):
name = "pkg"
version = "0.1"
settings = "os", "arch", "build_type"
options = {"shared": [True, False]}
generators = "CMakeToolchain"

def layout(self):
self.folders.build_folder_vars = ["settings.os", "options.shared"]
cmake_layout(self)
""")
client.save({"conanfile.py": conanfile})
client.run("install . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True")
presets = client.load("build/windows-shared/Debug/generators/CMakePresets.json")
assert "conan-windows-shared-debug" in presets
client.run("install . -s os=Linux -s arch=x86 -s build_type=Release -o shared=False")
presets = client.load("build/linux-static/Release/generators/CMakePresets.json")
assert "linux-static-release" in presets

# CLI override has priority
client.run("install . -s os=Linux -s arch=x86 -s build_type=Release -o shared=False "
"-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.os\"]'")
presets = client.load("build/linux/Release/generators/CMakePresets.json")
assert "conan-linux-release" in presets

# Now we do the build in the cache, the recipe folders are still used
client.run("create . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True")
ref = client.created_package_reference("pkg/0.1")
layout = client.get_latest_pkg_layout(ref)
build_folder = layout.build()
presets = load(os.path.join(build_folder,
"build/windows-shared/Debug/generators/CMakePresets.json"))
assert "conan-windows-shared-debug" in presets

# If we change the conf ``build_folder_vars``, it doesn't affect the cache build
client.run("create . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True "
"-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.os\"]'")
ref = client.created_package_reference("pkg/0.1")
layout = client.get_latest_pkg_layout(ref)
build_folder = layout.build()
presets = load(os.path.join(build_folder,
"build/windows-shared/Debug/generators/CMakePresets.json"))
assert "conan-windows-shared-debug" in presets