diff --git a/conans/client/build/cmake.py b/conans/client/build/cmake.py index 1371e003768..557935ff082 100644 --- a/conans/client/build/cmake.py +++ b/conans/client/build/cmake.py @@ -22,18 +22,33 @@ from conans.util.runners import version_runner -def CMake(conanfile, *args, **kwargs): - from conans import ConanFile - if not isinstance(conanfile, ConanFile): - raise ConanException("First argument of CMake() has to be ConanFile. Use CMake(self)") - - # If there is a toolchain, then use the toolchain helper one - toolchain = getattr(conanfile, "toolchain", None) - if toolchain: +class CMake(object): + def __new__(cls, conanfile, *args, **kwargs): + """ Inject the proper CMake base class in the hierarchy """ + from conans import ConanFile + if not isinstance(conanfile, ConanFile): + raise ConanException("First argument of CMake() has to be ConanFile. Use CMake(self)") + + # If already injected, create and return from conans.client.build.cmake_toolchain_build_helper import CMakeToolchainBuildHelper - return CMakeToolchainBuildHelper(conanfile, *args, **kwargs) - else: - return CMakeBuildHelper(conanfile, *args, **kwargs) + if CMakeToolchainBuildHelper in cls.__bases__ or CMakeBuildHelper in cls.__bases__: + return super(CMake, cls).__new__(cls) + + # If not, add the proper CMake implementation + if hasattr(conanfile, "toolchain"): + CustomCMakeClass = type("CustomCMakeClass", (cls, CMakeToolchainBuildHelper), {}) + else: + CustomCMakeClass = type("CustomCMakeClass", (cls, CMakeBuildHelper), {}) + + return CustomCMakeClass.__new__(CustomCMakeClass, conanfile, *args, **kwargs) + + def __init__(self, *args, **kwargs): + super(CMake, self).__init__(*args, **kwargs) + + @staticmethod + def get_version(): + # FIXME: Conan 2.0 This function is require for python2 + return CMakeBuildHelper.get_version() class CMakeBuildHelper(object): @@ -446,6 +461,3 @@ def get_version(): return Version(version_str) except Exception as e: raise ConanException("Error retrieving CMake version: '{}'".format(e)) - - -CMake.get_version = CMakeBuildHelper.get_version diff --git a/conans/test/functional/build_helpers/cmake_test.py b/conans/test/functional/build_helpers/cmake_test.py index 7e27f1ee6a8..7bf7ce63d7d 100644 --- a/conans/test/functional/build_helpers/cmake_test.py +++ b/conans/test/functional/build_helpers/cmake_test.py @@ -1,19 +1,79 @@ import textwrap import unittest - from conans.test.utils.tools import TestClient class CMakeBuildHelper(unittest.TestCase): - def get_version_test(self): + def test_get_version_no_toolchain(self): client = TestClient() conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class Pkg(ConanFile): def build(self): self.output.info("CMAKE_VERSION: %s" % CMake.get_version()) + cmake = CMake(self) + self.output.info("CMAKE_VERSION (obj): %s" % cmake.get_version()) """) client.save({"conanfile.py": conanfile}) client.run("create . pkg/0.1@user/testing") self.assertIn("CMAKE_VERSION: 3", client.out) + self.assertIn("CMAKE_VERSION (obj): 3", client.out) + + def test_get_version_toolchain(self): + client = TestClient() + conanfile = textwrap.dedent(""" + from conans import ConanFile, CMake + class Pkg(ConanFile): + toolchain = "cmake" + + def build(self): + self.output.info("CMAKE_VERSION: %s" % CMake.get_version()) + cmake = CMake(self) + self.output.info("CMAKE_VERSION (obj): %s" % cmake.get_version()) + """) + client.save({"conanfile.py": conanfile}) + client.run("create . pkg/0.1@user/testing") + self.assertIn("CMAKE_VERSION: 3", client.out) + self.assertIn("CMAKE_VERSION (obj): 3", client.out) + + def test_inheriting_cmake_build_helper_no_toolchain(self): + # https://github.com/conan-io/conan/issues/7196 + base = textwrap.dedent(""" + import conans + class CMake(conans.CMake): + pass + class BaseConanFile(conans.ConanFile): + def build(self): + self.output.info("CMAKE_VERSION: %s" % conans.CMake.get_version()) + cmake = CMake(self) + self.output.info("CMAKE_VERSION (obj): %s" % cmake.get_version()) + """) + + client = TestClient() + client.save({"conanfile.py": base}) + client.run("create . pkg/0.1@") + self.assertIn("pkg/0.1: Exported revision", client.out) + self.assertIn("CMAKE_VERSION: 3", client.out) + self.assertIn("CMAKE_VERSION (obj): 3", client.out) + + def test_inheriting_cmake_build_helper_toolchain(self): + # https://github.com/conan-io/conan/issues/7196 + base = textwrap.dedent(""" + import conans + class CMake(conans.CMake): + pass + class BaseConanFile(conans.ConanFile): + toolchain = "cmake" + def build(self): + self.output.info("CMAKE_VERSION: %s" % conans.CMake.get_version()) + cmake = CMake(self) + self.output.info("CMAKE_VERSION (obj): %s" % cmake.get_version()) + """) + + client = TestClient() + client.save({"conanfile.py": base}) + client.run("create . pkg/0.1@") + self.assertIn("pkg/0.1: Exported revision", client.out) + self.assertIn("CMAKE_VERSION: 3", client.out) + self.assertIn("CMAKE_VERSION (obj): 3", client.out)