From a2bd965dca8c08d00b8d742cb372254dfa4f802a Mon Sep 17 00:00:00 2001 From: System-Arch <33330183+System-Arch@users.noreply.github.com> Date: Sat, 14 Jan 2023 09:06:09 -0500 Subject: [PATCH] (#13739) CMake Conan 2.0 compatibility * CMake Conan 2.0 compatibility * Fix lint errors * Avoid lint error with Conan 2.0 argument name * Avoid lint error with Conan 2.0 argument name * Removed unused imports * Handle Conan version disparities * Use basic_layout with Autotools Co-authored-by: Uilian Ries * Call AutotoolsDeps generate Co-authored-by: Uilian Ries * Call CMakeDeps generate Co-authored-by: Uilian Ries * Update imports per suggestioned changes * Removed extra space * Remove extraneous items * Determine require_version in a version-agnostic manner * Use Conan 1.53 * Handle @ in ref * Fix lint errors * Bigger hammer * Remove PATH addition in package_id Co-authored-by: Chris Mc * Use validate_build instead of validate * Moved Mac x86 check to validate() method. * Bump openssl version Co-authored-by: Chris Mc * Add blank line to trigger CI build * Eliminate use of validate_build() * Restore use of validate_build() * Removed blank line to trigger CI * Add blank line to trigger CI * Added boostrap options and removed unneeded env. vars * Deal with Conan 1.x vs 2.0 inconsistencies * Fixed lint issue * Placate linter * Apply suggestions from code review Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com> * Use save & load for bootstrap args; Use tool_requires in test packages * Eliminate use of validate_build; Add more settings to test recipes * Set PATH in package_info() for v1.x; Lower req. ver. to 1.50 * Apply suggestions from code review Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com> * Added AutotoolsDeps generator; Eliminated can_run() from tests * Correct msvc version Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com> * Use f-strings * Replace VirtualRunEnv with VirtualBuildEnv Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com> Co-authored-by: Uilian Ries Co-authored-by: Chris Mc Co-authored-by: SpaceIm <30052553+SpaceIm@users.noreply.github.com> --- recipes/cmake/3.x.x/conanfile.py | 136 ++++++++++-------- recipes/cmake/3.x.x/test_package/conanfile.py | 31 ++-- .../cmake/3.x.x/test_v1_package/conanfile.py | 26 ++-- 3 files changed, 102 insertions(+), 91 deletions(-) diff --git a/recipes/cmake/3.x.x/conanfile.py b/recipes/cmake/3.x.x/conanfile.py index e0d41c4a94794..96b67934a6d19 100644 --- a/recipes/cmake/3.x.x/conanfile.py +++ b/recipes/cmake/3.x.x/conanfile.py @@ -1,20 +1,24 @@ -import os from conan import ConanFile +from conan.tools.files import chdir, copy, rmdir, get, save, load +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps +from conan.tools.layout import basic_layout +from conan.tools.build import build_jobs, cross_building, check_min_cppstd from conan.tools.scm import Version -from conan.tools.files import rmdir, get -from conans import tools, AutoToolsBuildEnvironment, CMake -from conan.errors import ConanInvalidConfiguration, ConanException +from conan.errors import ConanInvalidConfiguration +import os +import json -required_conan_version = ">=1.49.0" +required_conan_version = ">=1.50.0" class CMakeConan(ConanFile): name = "cmake" + package_type = "application" description = "Conan installer for CMake" topics = ("cmake", "build", "installer") url = "https://github.com/conan-io/conan-center-index" homepage = "https://github.com/Kitware/CMake" license = "BSD-3-Clause" - generators = "cmake" settings = "os", "arch", "compiler", "build_type" options = { @@ -26,9 +30,6 @@ class CMakeConan(ConanFile): "bootstrap": False, } - _source_subfolder = "source_subfolder" - _cmake = None - def config_options(self): if self.settings.os == "Windows": self.options.with_openssl = False @@ -38,103 +39,112 @@ def requirements(self): self.requires("openssl/1.1.1s") def validate(self): - if self.settings.os == "Macos" and self.settings.arch == "x86": - raise ConanInvalidConfiguration("CMake does not support x86 for macOS") - if self.settings.os == "Windows" and self.options.bootstrap: raise ConanInvalidConfiguration("CMake does not support bootstrapping on Windows") + if self.settings.os == "Macos" and self.settings.arch == "x86": + raise ConanInvalidConfiguration("CMake does not support x86 for macOS") + minimal_cpp_standard = "11" - if self.settings.compiler.cppstd: - tools.check_min_cppstd(self, minimal_cpp_standard) + if self.settings.get_safe("compiler.cppstd"): + check_min_cppstd(self, minimal_cpp_standard) minimal_version = { "gcc": "4.8", "clang": "3.3", "apple-clang": "9", "Visual Studio": "14", + "msvc": "190", } compiler = str(self.settings.compiler) if compiler not in minimal_version: - self.output.warn( - "{} recipe lacks information about the {} compiler standard version support".format(self.name, compiler)) - self.output.warn( - "{} requires a compiler that supports at least C++{}".format(self.name, minimal_cpp_standard)) + self.output.warning( + f"{self.name} recipe lacks information about the {compiler} compiler standard version support") + self.output.warning( + f"{self.name} requires a compiler that supports at least C++{minimal_cpp_standard}") return version = Version(self.settings.compiler.version) if version < minimal_version[compiler]: raise ConanInvalidConfiguration( - "{} requires a compiler that supports at least C++{}".format(self.name, minimal_cpp_standard)) + f"{self.name} requires a compiler that supports at least C++{minimal_cpp_standard}") + + def layout(self): + if self.options.bootstrap: + basic_layout(self, src_folder="src") + else: + cmake_layout(self, src_folder="src") def source(self): - get(self, **self.conan_data["sources"][self.version], strip_root=True, destination=self._source_subfolder) - rmdir(self, os.path.join(self._source_subfolder, "Tests", "RunCMake", "find_package")) + get(self, **self.conan_data["sources"][self.version], + destination=self.source_folder, strip_root=True) + rmdir(self, os.path.join(self.source_folder, "Tests", "RunCMake", "find_package")) - def _configure_cmake(self): - if not self._cmake: - self._cmake = CMake(self) + def generate(self): + if self.options.bootstrap: + tc = AutotoolsToolchain(self) + tc.generate() + tc = AutotoolsDeps(self) + tc.generate() + bootstrap_cmake_options = ["--"] + bootstrap_cmake_options.append(f'-DCMAKE_CXX_STANDARD={"11" if not self.settings.compiler.cppstd else self.settings.compiler.cppstd}') + if self.settings.os == "Linux": + if self.options.with_openssl: + openssl = self.dependencies["openssl"] + bootstrap_cmake_options.append("-DCMAKE_USE_OPENSSL=ON") + bootstrap_cmake_options.append(f'-DOPENSSL_USE_STATIC_LIBS={"FALSE" if openssl.options.shared else "TRUE"}') + else: + bootstrap_cmake_options.append("-DCMAKE_USE_OPENSSL=OFF") + save(self, "bootstrap_args", json.dumps({"bootstrap_cmake_options": ' '.join(arg for arg in bootstrap_cmake_options)})) + else: + tc = CMakeToolchain(self) if not self.settings.compiler.cppstd: - self._cmake.definitions["CMAKE_CXX_STANDARD"] = 11 - self._cmake.definitions["CMAKE_BOOTSTRAP"] = False + tc.variables["CMAKE_CXX_STANDARD"] = 11 + tc.variables["CMAKE_BOOTSTRAP"] = False if self.settings.os == "Linux": - self._cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.with_openssl + tc.variables["CMAKE_USE_OPENSSL"] = self.options.with_openssl if self.options.with_openssl: - self._cmake.definitions["OPENSSL_USE_STATIC_LIBS"] = not self.options["openssl"].shared - if tools.cross_building(self): - self._cmake.definitions["HAVE_POLL_FINE_EXITCODE"] = '' - self._cmake.definitions["HAVE_POLL_FINE_EXITCODE__TRYRUN_OUTPUT"] = '' - self._cmake.configure(source_folder=self._source_subfolder) - - return self._cmake + openssl = self.dependencies["openssl"] + tc.variables["OPENSSL_USE_STATIC_LIBS"] = not openssl.options.shared + if cross_building(self): + tc.variables["HAVE_POLL_FINE_EXITCODE"] = '' + tc.variables["HAVE_POLL_FINE_EXITCODE__TRYRUN_OUTPUT"] = '' + tc.generate() def build(self): if self.options.bootstrap: - with tools.chdir(self._source_subfolder): - self.run(['./bootstrap', '--prefix={}'.format(self.package_folder), '--parallel={}'.format(tools.cpu_count())]) - autotools = AutoToolsBuildEnvironment(self) + toolchain_file_content = json.loads(load(self, os.path.join(self.generators_folder, "bootstrap_args"))) + bootstrap_cmake_options = toolchain_file_content.get("bootstrap_cmake_options") + with chdir(self, self.source_folder): + self.run(f'./bootstrap --prefix="" --parallel={build_jobs(self)} {bootstrap_cmake_options}') + autotools = Autotools(self) autotools.make() else: - tools.replace_in_file(os.path.join(self._source_subfolder, "CMakeLists.txt"), - "project(CMake)", - "project(CMake)\ninclude(\"{}/conanbuildinfo.cmake\")\nconan_basic_setup(NO_OUTPUT_DIRS)".format( - self.install_folder.replace("\\", "/"))) - if self.settings.os == "Linux": - tools.replace_in_file(os.path.join(self._source_subfolder, "Utilities", "cmcurl", "CMakeLists.txt"), - "list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})", - "list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS} pthread)") - - cmake = self._configure_cmake() + cmake = CMake(self) + cmake.configure() cmake.build() def package(self): - self.copy("Copyright.txt", dst="licenses", src=self._source_subfolder) + copy(self, "Copyright.txt", self.source_folder, os.path.join(self.package_folder, "licenses"), keep_path=False) if self.options.bootstrap: - with tools.chdir(self._source_subfolder): - autotools = AutoToolsBuildEnvironment(self) + with chdir(self, self.source_folder): + autotools = Autotools(self) autotools.install() else: - cmake = self._configure_cmake() + cmake = CMake(self) cmake.install() rmdir(self, os.path.join(self.package_folder, "doc")) def package_id(self): del self.info.settings.compiler + del self.info.options.bootstrap def package_info(self): - module_version = "{}.{}".format(Version(self.version).major, Version(self.version).minor) + self.cpp_info.includedirs = [] + self.cpp_info.libdirs = [] + # Needed for compatibility with v1.x - Remove when 2.0 becomes the default bindir = os.path.join(self.package_folder, "bin") - self.output.info("Appending PATH environment variable: {}".format(bindir)) + self.output.info(f"Appending PATH environment variable: {bindir}") self.env_info.PATH.append(bindir) - - self.buildenv_info.prepend_path("CMAKE_ROOT", self.package_folder) - self.env_info.CMAKE_ROOT = self.package_folder - mod_path = os.path.join(self.package_folder, "share", f"cmake-{module_version}", "Modules") - self.buildenv_info.prepend_path("CMAKE_MODULE_PATH", mod_path) - self.env_info.CMAKE_MODULE_PATH = mod_path - if not os.path.exists(mod_path): - raise ConanException("Module path not found: %s" % mod_path) - - self.cpp_info.includedirs = [] diff --git a/recipes/cmake/3.x.x/test_package/conanfile.py b/recipes/cmake/3.x.x/test_package/conanfile.py index 0b0c4858e1c60..df50a01c37d6f 100644 --- a/recipes/cmake/3.x.x/test_package/conanfile.py +++ b/recipes/cmake/3.x.x/test_package/conanfile.py @@ -1,23 +1,24 @@ -import os from six import StringIO from conan import ConanFile -from conan.tools.build import can_run +import re class TestPackageConan(ConanFile): - settings = "os", "arch" - generators = "VirtualRunEnv" + settings = "os", "arch", "compiler", "build_type" + generators = "VirtualBuildEnv" + test_type = "explicit" - def requirements(self): - self.requires(self.tested_reference_str) + def build_requirements(self): + self.tool_requires(self.tested_reference_str) def test(self): - if can_run(self): - output = StringIO() - self.run("cmake --version", env="conanrun", output=output) - output_str = str(output.getvalue()) - self.output.info("Installed version: {}".format(output_str)) - require_version = str(self.deps_cpp_info["cmake"].version) - self.output.info("Expected version: {}".format(require_version)) - assert_cmake_version = "cmake version %s" % require_version - assert(assert_cmake_version in output_str) + output = StringIO() + # Third arg to self.run renamed "stdout" in Conan 2.0 but 1.x linter doesn't like it + self.run("cmake --version", output) + output_str = str(output.getvalue()) + self.output.info("Installed version: {}".format(output_str)) + tokens = re.split('[@#]', self.tested_reference_str) + require_version = tokens[0].split("/", 1)[1] + self.output.info("Expected version: {}".format(require_version)) + assert_cmake_version = "cmake version %s" % require_version + assert(assert_cmake_version in output_str) diff --git a/recipes/cmake/3.x.x/test_v1_package/conanfile.py b/recipes/cmake/3.x.x/test_v1_package/conanfile.py index efb629f7d5725..df9415b7cf880 100644 --- a/recipes/cmake/3.x.x/test_v1_package/conanfile.py +++ b/recipes/cmake/3.x.x/test_v1_package/conanfile.py @@ -1,23 +1,23 @@ import os from six import StringIO from conan import ConanFile -from conan.tools.build import can_run +import re class TestPackageConan(ConanFile): - settings = "os", "arch" + settings = "os", "arch", "compiler", "build_type" test_type = "explicit" - def requirements(self): - self.requires(self.tested_reference_str) + def build_requirements(self): + self.tool_requires(self.tested_reference_str) def test(self): - if can_run(self): - output = StringIO() - self.run("cmake --version", output=output, run_environment=True) - output_str = str(output.getvalue()) - self.output.info("Installed version: {}".format(output_str)) - require_version = str(self.deps_cpp_info["cmake"].version) - self.output.info("Expected version: {}".format(require_version)) - assert_cmake_version = "cmake version %s" % require_version - assert(assert_cmake_version in output_str) + output = StringIO() + self.run("cmake --version", output=output, run_environment=False) + output_str = str(output.getvalue()) + self.output.info("Installed version: {}".format(output_str)) + tokens = re.split('[@#]', self.tested_reference_str) + require_version = tokens[0].split("/", 1)[1] + self.output.info("Expected version: {}".format(require_version)) + assert_cmake_version = "cmake version %s" % require_version + assert(assert_cmake_version in output_str)