View on GitHub


0 mins
Test Coverage
import os

from import build_jobs
from import load_cmake_presets
from import is_multi_configuration
from import chdir, mkdir
from import msbuild_verbosity_cmd_line_arg
from import args_to_string
from conans.errors import ConanException

def _validate_recipe(conanfile):
    forbidden_generators = ["cmake", "cmake_multi"]
    if any(it in conanfile.generators for it in forbidden_generators):
        raise ConanException("Usage of toolchain is only supported with 'cmake_find_package'"
                             " or 'cmake_find_package_multi' generators")

def _cmake_cmd_line_args(conanfile, generator):
    args = []
    if not generator:
        return args

    # Arguments related to parallel
    njobs = build_jobs(conanfile)
    if njobs and ("Makefiles" in generator or "Ninja" in generator) and "NMake" not in generator:

    maxcpucount = conanfile.conf.get("", check_type=int)
    if maxcpucount and "Visual Studio" in generator:

    # Arguments for verbosity
    if "Visual Studio" in generator:
        verbosity = msbuild_verbosity_cmd_line_arg(conanfile)
        if verbosity:

    return args

class CMake(object):
    """ CMake helper to use together with the toolchain feature. It implements a very simple
    wrapper to call the cmake executable, but without passing compile flags, preprocessor
    definitions... all that is set by the toolchain. Only the generator and the CMAKE_TOOLCHAIN_FILE
    are passed to the command line, plus the ``--config Release`` for builds in multi-config

    def __init__(self, conanfile):

        # Store a reference to useful data
        self._conanfile = conanfile

        cmake_presets = load_cmake_presets(conanfile.generators_folder)
        # Conan generated presets will have exactly 1 configurePresets, no more
        configure_preset = cmake_presets["configurePresets"][0]

        self._generator = configure_preset["generator"]
        self._toolchain_file = configure_preset.get("toolchainFile")
        self._cache_variables = configure_preset["cacheVariables"]

        self._cmake_program = "cmake"  # Path to CMake should be handled by environment

    def configure(self, variables=None, build_script_folder=None, cli_args=None):
        cmakelist_folder = self._conanfile.source_folder
        if build_script_folder:
            cmakelist_folder = os.path.join(self._conanfile.source_folder, build_script_folder)

        build_folder = self._conanfile.build_folder
        generator_folder = self._conanfile.generators_folder

        mkdir(self._conanfile, build_folder)

        arg_list = [self._cmake_program]
        if self._generator:
            arg_list.append('-G "{}"'.format(self._generator))
        if self._toolchain_file:
            if os.path.isabs(self._toolchain_file):
                toolpath = self._toolchain_file
                toolpath = os.path.join(generator_folder, self._toolchain_file)
            arg_list.append('-DCMAKE_TOOLCHAIN_FILE="{}"'.format(toolpath.replace("\\", "/")))
        if self._conanfile.package_folder:
            pkg_folder = self._conanfile.package_folder.replace("\\", "/")

        if not variables:
            variables = {}

        arg_list.extend(['-D{}="{}"'.format(k, v) for k, v in self._cache_variables.items()])

        if cli_args:

        command = " ".join(arg_list)"CMake command: %s" % command)
        with chdir(self, build_folder):

    def _build(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env=""):
        bf = self._conanfile.build_folder
        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")

        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 ""

        args = []
        if target is not None:
            args = ["--target", target]
        if cli_args:

        cmd_line_args = _cmake_cmd_line_args(self._conanfile, self._generator)
        if build_tool_args:
        if cmd_line_args:
            args += ['--'] + cmd_line_args

        arg_list = ['"{}"'.format(bf), build_config, args_to_string(args)]
        arg_list = " ".join(filter(None, arg_list))
        command = "%s --build %s" % (self._cmake_program, arg_list)"CMake command: %s" % command), env=env)

    def build(self, build_type=None, target=None, cli_args=None, build_tool_args=None):
        self._build(build_type, target, cli_args, build_tool_args)

    def install(self, build_type=None, component=None):
        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 ""

        pkg_folder = '"{}"'.format(self._conanfile.package_folder.replace("\\", "/"))
        build_folder = '"{}"'.format(self._conanfile.build_folder)
        arg_list = ["--install", build_folder, build_config, "--prefix", pkg_folder]
        if component:
            arg_list.extend(["--component", component])

        do_strip = self._conanfile.conf.get("tools.cmake:install_strip", check_type=bool)
        if do_strip:
        arg_list = " ".join(filter(None, arg_list))
        command = "%s %s" % (self._cmake_program, arg_list)"CMake command: %s" % command)

    def test(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env=""):
        if self._conanfile.conf.get("", check_type=bool):
        if not target:
            is_multi = is_multi_configuration(self._generator)
            is_ninja = "Ninja" in self._generator
            target = "RUN_TESTS" if is_multi and not is_ninja else "test"

        # The default for ``test()`` is both the buildenv and the runenv
        env = ["conanbuild", "conanrun"] if env == "" else env
        self._build(build_type=build_type, target=target, cli_args=cli_args,
                    build_tool_args=build_tool_args, env=env)