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

Fix cmake build --config XXXX for multi-config with hardcoded configurations #14780

Merged
merged 6 commits into from
Feb 15, 2024
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
34 changes: 22 additions & 12 deletions conan/tools/cmake/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def __init__(self, conanfile):

self._cmake_program = conanfile.conf.get("tools.cmake:cmake_program", default="cmake")

@property
def is_multi_configuration(self):
return is_multi_configuration(self._generator)

def configure(self, variables=None, build_script_folder=None, cli_args=None,
stdout=None, stderr=None):
"""
Expand Down Expand Up @@ -117,18 +121,28 @@ def configure(self, variables=None, build_script_folder=None, cli_args=None,
with chdir(self, build_folder):
self._conanfile.run(command, stdout=stdout, stderr=stderr)

def _build(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env="",
stdout=None, stderr=None):
bf = self._conanfile.build_folder
def _config_arg(self, build_type):
""" computes the '--config Release' arg when necessary, or warn or error if wrong
"""
is_multi = is_multi_configuration(self._generator)
if build_type and not is_multi:
self._conanfile.output.error("Don't specify 'build_type' at build time for "
"single-config build systems")
if not build_type:
try:
build_type = self._conanfile.settings.build_type # declared, but can be None
if not build_type:
raise ConanException("CMake: build_type setting should be defined.")
except ConanException:
if is_multi:
raise ConanException("CMake: build_type setting should be defined.")
build_config = "--config {}".format(build_type) if build_type and is_multi else ""
return build_config

bt = build_type or self._conanfile.settings.get_safe("build_type")
if not bt:
raise ConanException("build_type setting should be defined.")
build_config = "--config {}".format(bt) if bt and is_multi else ""
def _build(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env="",
stdout=None, stderr=None):
bf = self._conanfile.build_folder
build_config = self._config_arg(build_type)

args = []
if target is not None:
Expand Down Expand Up @@ -191,11 +205,7 @@ def install(self, build_type=None, component=None, cli_args=None, stdout=None, s
self._conanfile.output.info("Running CMake.install()")
mkdir(self._conanfile, self._conanfile.package_folder)

bt = build_type or self._conanfile.settings.get_safe("build_type")
if not bt:
raise ConanException("build_type setting should be defined.")
is_multi = is_multi_configuration(self._generator)
build_config = "--config {}".format(bt) if bt and is_multi else ""
build_config = self._config_arg(build_type)

pkg_folder = '"{}"'.format(self._conanfile.package_folder.replace("\\", "/"))
build_folder = '"{}"'.format(self._conanfile.build_folder)
Expand Down
5 changes: 5 additions & 0 deletions conan/tools/cmake/toolchain/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
AndroidSystemBlock, AppleSystemBlock, FPicBlock, ArchitectureBlock, GLibCXXBlock, VSRuntimeBlock, \
CppStdBlock, ParallelBlock, CMakeFlagsInitBlock, TryCompileBlock, FindFiles, PkgConfigBlock, \
SkipRPath, SharedLibBock, OutputDirsBlock, ExtraFlagsBlock, CompilersBlock, LinkerScriptsBlock
from conan.tools.cmake.utils import is_multi_configuration
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
from conan.tools.intel import IntelCC
from conan.tools.microsoft import VCVars
Expand Down Expand Up @@ -190,6 +191,10 @@ def content(self):
content = relativize_generated_file(content, self._conanfile, "${CMAKE_CURRENT_LIST_DIR}")
return content

@property
def is_multi_configuration(self):
return is_multi_configuration(self.generator)

def _find_cmake_exe(self):
for req in self._conanfile.dependencies.direct_build.values():
if req.ref.name == "cmake":
Expand Down
45 changes: 45 additions & 0 deletions conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,51 @@ def build(self):
assert "-- MYVAR1 MYVALUE1!!" in client.out


def test_no_build_type():
client = TestClient()

conanfile = textwrap.dedent("""
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain

class AppConan(ConanFile):
name = "pkg"
version = "1.0"
settings = "os", "compiler", "arch"
exports_sources = "CMakeLists.txt"

def layout(self):
self.folders.build = "build"

def generate(self):
tc = CMakeToolchain(self)
if not tc.is_multi_configuration:
tc.cache_variables["CMAKE_BUILD_TYPE"] = "Release"
tc.generate()

def build(self):
cmake = CMake(self)
cmake.configure()
build_type = "Release" if cmake.is_multi_configuration else None
cmake.build(build_type=build_type)

def package(self):
cmake = CMake(self)
build_type = "Release" if cmake.is_multi_configuration else None
cmake.install(build_type=build_type)
""")

cmake = """
cmake_minimum_required(VERSION 3.15)
project(pkg LANGUAGES NONE)
"""

client.save({"conanfile.py": conanfile,
"CMakeLists.txt": cmake})
client.run("create .")
assert "Don't specify 'build_type' at build time" not in client.out


@pytest.mark.tool("cmake", "3.19")
def test_redirect_stdout():
client = TestClient()
Expand Down