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

Fixing cmake_layout single config #12829

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
32 changes: 14 additions & 18 deletions conan/tools/cmake/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,21 @@ def cmake_layout(conanfile, generator=None, src_folder=".", build_folder="build"
raise ConanException("'build_type' setting not defined, it is necessary for cmake_layout()")

build_folder = build_folder if not subproject else os.path.join(subproject, build_folder)
custom_conf = get_build_folder_custom_vars(conanfile)
if custom_conf:
build_folder = os.path.join(build_folder, custom_conf)
config_build_folder, user_defined_build = get_build_folder_custom_vars(conanfile)

if multi:
conanfile.folders.build = build_folder
if config_build_folder:
conanfile.folders.build = os.path.join(build_folder, config_build_folder)
else:
conanfile.folders.build = os.path.join(build_folder, build_type)
if not multi and not user_defined_build:
conanfile.folders.build = os.path.join(build_folder, build_type)
else:
conanfile.folders.build = build_folder

conanfile.folders.generators = os.path.join(build_folder, "generators")
conanfile.folders.generators = os.path.join(conanfile.folders.build, "generators")

conanfile.cpp.source.includedirs = ["include"]

if multi:
if multi and not user_defined_build:
conanfile.cpp.build.libdirs = ["{}".format(build_type)]
conanfile.cpp.build.bindirs = ["{}".format(build_type)]
else:
Expand All @@ -49,17 +50,11 @@ def get_build_folder_custom_vars(conanfile):
default=[], check_type=list)
ret = []
for s in build_vars:
group, var = s.split(".", 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if it doesn't have a dot, will it raise with a weird exception here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that was already happening before, nothing new, and I didn't want to add extra noise and tests, as this PR is already quite potentially breaking.

tmp = None
if s.startswith("settings."):
_, var = s.split("settings.", 1)
if var == "build_type":
raise ConanException("Error, don't include 'settings.build_type' in the "
"'tools.cmake.cmake_layout:build_folder_vars' conf. It is "
"managed by default because 'CMakeToolchain' and 'CMakeDeps' "
"are multi-config generators.`")
if group == "settings":
tmp = conanfile.settings.get_safe(var)
elif s.startswith("options."):
_, var = s.split("options.", 1)
elif group == "options":
value = conanfile.options.get_safe(var)
if value is not None:
tmp = "{}_{}".format(var, value)
Expand All @@ -69,4 +64,5 @@ def get_build_folder_custom_vars(conanfile):
if tmp:
ret.append(tmp.lower())

return "-".join(ret)
user_defined_build = "settings.build_type" in build_vars
return "-".join(ret), user_defined_build
10 changes: 8 additions & 2 deletions conan/tools/cmake/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ def _build_preset(conanfile, multiconfig):

def _build_preset_name(conanfile):
build_type = conanfile.settings.get_safe("build_type")
custom_conf = get_build_folder_custom_vars(conanfile)
custom_conf, user_defined_build = get_build_folder_custom_vars(conanfile)
if user_defined_build:
return custom_conf

if custom_conf:
if build_type:
return "{}-{}".format(custom_conf, build_type.lower())
Expand All @@ -32,7 +35,10 @@ def _build_preset_name(conanfile):

def _configure_preset_name(conanfile, multiconfig):
build_type = conanfile.settings.get_safe("build_type")
custom_conf = get_build_folder_custom_vars(conanfile)
custom_conf, user_defined_build = get_build_folder_custom_vars(conanfile)

if user_defined_build:
return custom_conf

if multiconfig or not build_type:
return "default" if not custom_conf else custom_conf
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ def package(self):

# Local flow
client.run("install . foo/1.0 -s os=Linux")
assert os.path.exists(os.path.join(client.current_folder, "build", "generators", "generate.txt"))
assert os.path.exists(os.path.join(client.current_folder,
"build", "Release", "generators", "generate.txt"))
client.run("source .")
assert os.path.exists(os.path.join(client.current_folder, "src", "source.txt"))
client.run("build .")
Expand Down Expand Up @@ -294,4 +295,4 @@ def layout(self):
client.save({"conanfile.py": conanfile})
client.run("install .")
assert os.path.exists(os.path.join(client.current_folder,
"mybuild/generators/conan_toolchain.cmake"))
"mybuild/Release/generators/conan_toolchain.cmake"))
6 changes: 5 additions & 1 deletion conans/test/functional/layout/test_local_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,11 @@ def test_start_dir_failure():
c = TestClient()
c.save(pkg_cmake("dep", "0.1"))
c.run("install .")
expected_path = os.path.join(c.current_folder, "build", "generators", "conan_toolchain.cmake")
if platform.system() != "Windows":
gen_folder = os.path.join(c.current_folder, "build", "Release", "generators")
else:
gen_folder = os.path.join(c.current_folder, "build", "generators")
expected_path = os.path.join(gen_folder, "conan_toolchain.cmake")
assert os.path.exists(expected_path)
os.unlink(expected_path)
with c.chdir("build"):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ def package_info(self):
files = pkg_cmake("mylib", "0.1", requires=["zlib/0.1"])
files["CMakeLists.txt"] = files["CMakeLists.txt"].replace("find_package(zlib)",
"find_package(ZLIB)")
files["CMakeLists.txt"] = files["CMakeLists.txt"].replace("zlib::zlib","ZLIB::ZLIB")
files["CMakeLists.txt"] = files["CMakeLists.txt"].replace("zlib::zlib", "ZLIB::ZLIB")
client.save({os.path.join("mylib", name): content for name, content in files.items()})
files = pkg_cmake("consumer", "0.1", requires=["mylib/0.1"])
client.save({os.path.join("consumer", name): content for name, content in files.items()})
Expand All @@ -509,7 +509,7 @@ def package_info(self):
client.run("install consumer")
if platform.system() != "Windows":
host_arch = client.get_default_host_profile().settings['arch']
data = os.path.join(f"consumer/build/generators/mylib-release-{host_arch}-data.cmake")
data = f"consumer/build/Release/generators/mylib-release-{host_arch}-data.cmake"
contents = client.load(data)
assert 'set(ZLIB_FIND_MODE "")' in contents

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ def package_info(self):
client.run("new hello/1.0 -m cmake_lib")
client.save({"conanfile.py": conanfile})
client.run("create .")
t = os.path.join("test_package", "build", "generators", "hello-release-x86_64-data.cmake")
t = os.path.join("test_package", "build", "Release",
"generators", "hello-release-x86_64-data.cmake")
target_data_cmake_content = client.load(t)
assert 'set(hello_SHARED_LINK_FLAGS_RELEASE "-z now;-z relro")' in target_data_cmake_content
assert 'set(hello_EXE_LINK_FLAGS_RELEASE "-z now;-z relro")' in target_data_cmake_content
Expand Down
23 changes: 14 additions & 9 deletions conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,14 @@ def test_install_output_directories():
p_folder = client.cache.package_layout(pref.ref).package(pref)
assert os.path.exists(os.path.join(p_folder, "mylibs"))
assert not os.path.exists(os.path.join(p_folder, "lib"))

b_folder = client.cache.package_layout(pref.ref).build(pref)
toolchain = client.load(os.path.join(b_folder, "build", "generators", "conan_toolchain.cmake"))
if platform.system() != "Windows":
gen_folder = os.path.join(b_folder, "build", "Release", "generators")
else:
gen_folder = os.path.join(b_folder, "build", "generators")

toolchain = client.load(os.path.join(gen_folder, "conan_toolchain.cmake"))
assert 'set(CMAKE_INSTALL_LIBDIR "mylibs")' in toolchain


Expand Down Expand Up @@ -962,15 +968,15 @@ def test_cmake_presets_with_conanfile_txt():
assert "Hello World Release!" in c.out


def test_cmake_presets_forbidden_build_type():
def test_cmake_presets_not_forbidden_build_type():
client = TestClient(path_with_spaces=False)
client.run("new hello/0.1 --template cmake_exe")
# client.run("new cmake_exe -d name=hello -d version=0.1")
settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=' \
'\'["options.missing", "settings.build_type"]\''
client.run("install . {}".format(settings_layout), assert_error=True)
assert "Error, don't include 'settings.build_type' in the " \
"'tools.cmake.cmake_layout:build_folder_vars' conf" in client.out
client.run("install . {}".format(settings_layout))
assert os.path.exists(os.path.join(client.current_folder,
"build/release/generators/conan_toolchain.cmake"))


def test_resdirs_cmake_install():
Expand Down Expand Up @@ -1116,7 +1122,8 @@ def test_cmake_toolchain_vars_when_option_declared():
# the CMakeLists
fpic_option = "-o mylib:fPIC=False" if platform.system() != "Windows" else ""
t.run(f"install . -o mylib:shared=False {fpic_option}")
t.run_command("cmake -S . -B build/ -DCMAKE_TOOLCHAIN_FILE=build/generators/conan_toolchain.cmake")
folder = "build/generators" if platform.system() == "Windows" else "build/Release/generators"
t.run_command(f"cmake -S . -B build/ -DCMAKE_TOOLCHAIN_FILE={folder}/conan_toolchain.cmake")
assert "mylib target type: STATIC_LIBRARY" in t.out
assert f"mylib position independent code: OFF" in t.out

Expand Down Expand Up @@ -1185,8 +1192,6 @@ def package(self):
"build_profile": build_profile
})

xxx = client.get_default_build_profile()

client.run("create . -pr:b build_profile -pr:h build_profile")
client.run("create . -pr:b build_profile -pr:h host_profile")

Expand Down Expand Up @@ -1226,7 +1231,7 @@ def build_requirements(self):
host_context_package_id = "bf544cd3bc20b82121fd76b82eacbb36d75fa167"

with client.chdir("build"):
client.run_command("cmake .. -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release")
client.run_command("cmake .. -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release")
# Verify binary executable is found from build context package,
# and library comes from host context package
assert f"package/{build_context_package_id}/bin/foobin" in client.out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_cmake_apple_bitcode_arc_and_visibility_flags_enabled(op_system, os_vers
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("build", "generators", "conan_toolchain.cmake"))
toolchain = client.load(os.path.join("build", "Release", "generators", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' in toolchain
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_cmake_apple_bitcode_arc_and_visibility_flags_disabled(op_system, os_ver
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("build", "generators", "conan_toolchain.cmake"))
toolchain = client.load(os.path.join("build", "Release", "generators", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' not in toolchain
Expand Down Expand Up @@ -163,7 +163,7 @@ def test_cmake_apple_bitcode_arc_and_visibility_flags_are_none(op_system, os_ver
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("build", "generators", "conan_toolchain.cmake"))
toolchain = client.load(os.path.join("build", "Release", "generators", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")' not in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' not in toolchain
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import platform
import textwrap

from conans.test.assets.genconanfile import GenConanfile
Expand Down Expand Up @@ -225,9 +226,14 @@ def generate(self):

client.save({"foo.py": foo.format(set_find_mode=""), "bar.py": bar}, clean_first=True)

module_file = os.path.join(client.current_folder, "build", "generators", "module-custom_bar_module_file_nameTargets.cmake")
components_module = os.path.join(client.current_folder, "build", "generators", "custom_bar_file_name-Target-release.cmake")
config_file = os.path.join(client.current_folder, "build", "generators", "custom_bar_file_nameTargets.cmake")
if platform.system() != "Windows":
gen_folder = os.path.join(client.current_folder, "build", "Release", "generators")
else:
gen_folder = os.path.join(client.current_folder, "build", "generators")

module_file = os.path.join(gen_folder, "module-custom_bar_module_file_nameTargets.cmake")
components_module = os.path.join(gen_folder, "custom_bar_file_name-Target-release.cmake")
config_file = os.path.join(gen_folder, "custom_bar_file_nameTargets.cmake")

# uses cmake_find_mode set in bar: both
client.run("create bar.py bar/1.0@")
Expand Down Expand Up @@ -311,19 +317,20 @@ def generate(self):

client.save({"foo.py": foo.format(set_find_mode=""), "bar.py": bar}, clean_first=True)

module_file = os.path.join(client.current_folder, "build", "generators",
"module-custom_bar_module_file_nameTargets.cmake")
components_module = os.path.join(client.current_folder, "build", "generators",
"custom_bar_file_name-Target-release.cmake")
config_file = os.path.join(client.current_folder, "build", "generators",
"custom_bar_file_nameTargets.cmake")
if platform.system() != "Windows":
gen_folder = os.path.join(client.current_folder, "build", "Release", "generators")
else:
gen_folder = os.path.join(client.current_folder, "build", "generators")

module_file = os.path.join(gen_folder, "module-custom_bar_module_file_nameTargets.cmake")
components_module = os.path.join(gen_folder, "custom_bar_file_name-Target-release.cmake")
config_file = os.path.join(gen_folder, "custom_bar_file_nameTargets.cmake")

module_file_build = os.path.join(client.current_folder, "build", "generators",
module_file_build = os.path.join(gen_folder,
"module-custom_bar_build_module_file_name_BUILDTargets.cmake")
components_module_build = os.path.join(client.current_folder, "build", "generators",
components_module_build = os.path.join(gen_folder,
"custom_bar_build_file_name_BUILD-Target-release.cmake")
config_file_build = os.path.join(client.current_folder, "build", "generators",
"custom_bar_build_file_name_BUILDTargets.cmake")
config_file_build = os.path.join(gen_folder, "custom_bar_build_file_name_BUILDTargets.cmake")

# uses cmake_find_mode set in bar: both
client.run("create bar.py bar/1.0@ -pr:h=default -pr:b=default")
Expand Down
38 changes: 36 additions & 2 deletions conans/test/integration/toolchains/cmake/test_cmaketoolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from conan.tools.cmake.presets import load_cmake_presets
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.test_files import temp_folder
from conans.test.utils.tools import TestClient
from conans.util.files import rmdir

Expand Down Expand Up @@ -379,7 +378,7 @@ def layout(self):
else:
build_dir = os.path.join(client.current_folder, "build")

presets = load_cmake_presets(os.path.join(client.current_folder, "build", "generators"))
presets = load_cmake_presets(os.path.join(build_dir, "generators"))
assert presets["configurePresets"][0]["binaryDir"] == build_dir


Expand Down Expand Up @@ -422,6 +421,7 @@ def test_cmake_presets_multiconfig():
# Repeat one
client.run("install mylib/1.0@ -g CMakeToolchain -s build_type=Debug --profile:h=profile")
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["buildPresets"]) == 4
assert presets["buildPresets"][0]["configuration"] == "Release"
assert presets["buildPresets"][1]["configuration"] == "Debug"
Expand Down Expand Up @@ -517,6 +517,7 @@ def _format_val(val):
assert "-DCMAKE_TOOLCHAIN_FILE=" in client.out
assert f"-G {_format_val('MinGW Makefiles')}" in client.out


def test_android_c_library():
client = TestClient()
conanfile = textwrap.dedent("""
Expand Down Expand Up @@ -845,3 +846,36 @@ def test_set_cmake_lang_compilers_and_launchers():
assert 'set(CMAKE_C_COMPILER "/my/local/gcc")' in toolchain
assert 'set(CMAKE_CXX_COMPILER "g++")' in toolchain
assert 'set(CMAKE_RC_COMPILER "C:/local/rc.exe")' in toolchain


def test_cmake_layout_toolchain_folder():
""" in single-config generators, the toolchain is a different file per configuration
https://github.com/conan-io/conan/issues/12827
"""
c = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
from conan.tools.cmake import cmake_layout

class Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain"

def layout(self):
cmake_layout(self)
""")
c.save({"conanfile.py": conanfile})
c.run("install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Release "
"-s compiler.libcxx=libstdc++11")
assert os.path.exists(os.path.join(c.current_folder,
"build/Release/generators/conan_toolchain.cmake"))
c.run("install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Debug "
"-s compiler.libcxx=libstdc++11")
assert os.path.exists(os.path.join(c.current_folder,
"build/Debug/generators/conan_toolchain.cmake"))
c.run("install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Debug "
"-s compiler.libcxx=libstdc++11 -s arch=x86 "
"-c tools.cmake.cmake_layout:build_folder_vars='[\"settings.arch\", \"settings.build_type\"]'")
print(c.out)
assert os.path.exists(os.path.join(c.current_folder,
"build/x86-debug/generators/conan_toolchain.cmake"))