auto-setup: Add support for conan 2.0

Fixes: QTCREATORBUG-28865
Change-Id: Ifb801a458b4b18de218dee6604f0555cab13ec75
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Cristian Adam
2023-03-17 15:35:44 +01:00
parent a50f2620ec
commit 4d82246ab5
3 changed files with 250 additions and 14 deletions

View File

@@ -46,6 +46,8 @@ macro(qtc_auto_setup_conan)
message(FATAL_ERROR "conan --version failed='${result_code}: ${conan_version_output}") message(FATAL_ERROR "conan --version failed='${result_code}: ${conan_version_output}")
endif() endif()
string(REGEX REPLACE ".*Conan version ([0-9].[0-9]).*" "\\1" conan_version "${conan_version_output}")
set(conanfile_timestamp_file "${CMAKE_BINARY_DIR}/conan-dependencies/conanfile.timestamp") set(conanfile_timestamp_file "${CMAKE_BINARY_DIR}/conan-dependencies/conanfile.timestamp")
file(TIMESTAMP "${conanfile_txt}" conanfile_timestamp) file(TIMESTAMP "${conanfile_txt}" conanfile_timestamp)
@@ -68,6 +70,9 @@ macro(qtc_auto_setup_conan)
if (do_conan_installation) if (do_conan_installation)
message(STATUS "Qt Creator: conan package manager auto-setup. " message(STATUS "Qt Creator: conan package manager auto-setup. "
"Skip this step by setting QT_CREATOR_SKIP_CONAN_SETUP to ON.") "Skip this step by setting QT_CREATOR_SKIP_CONAN_SETUP to ON.")
file(COPY "${conanfile_txt}" DESTINATION "${CMAKE_BINARY_DIR}/conan-dependencies/")
file(WRITE "${CMAKE_BINARY_DIR}/conan-dependencies/toolchain.cmake" " file(WRITE "${CMAKE_BINARY_DIR}/conan-dependencies/toolchain.cmake" "
set(CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\") set(CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\")
set(CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\") set(CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\")
@@ -77,17 +82,39 @@ macro(qtc_auto_setup_conan)
"include(\"${CMAKE_TOOLCHAIN_FILE}\")\n") "include(\"${CMAKE_TOOLCHAIN_FILE}\")\n")
endif() endif()
file(WRITE "${CMAKE_BINARY_DIR}/conan-dependencies/CMakeLists.txt" " file(WRITE "${CMAKE_BINARY_DIR}/conan-dependencies/CMakeLists.txt" "
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
project(conan-setup)
include(\"${CMAKE_CURRENT_LIST_DIR}/conan.cmake\") unset(CMAKE_PROJECT_INCLUDE_BEFORE CACHE)
conan_cmake_run( project(conan-setup)
CONANFILE \"${conanfile_txt}\"
INSTALL_FOLDER \"${CMAKE_BINARY_DIR}/conan-dependencies\" if (${conan_version} VERSION_GREATER_EQUAL 2.0)
GENERATORS cmake_paths json include(\"${CMAKE_CURRENT_LIST_DIR}/conan_support.cmake\")
BUILD ${QT_CREATOR_CONAN_BUILD_POLICY} conan_profile_detect_default()
ENV CONAN_CMAKE_TOOLCHAIN_FILE=\"${CMAKE_BINARY_DIR}/conan-dependencies/toolchain.cmake\" detect_host_profile(\"${CMAKE_BINARY_DIR}/conan-dependencies/conan_host_profile\")
)")
conan_install(
-pr \"${CMAKE_BINARY_DIR}/conan-dependencies/conan_host_profile\"
--build=${QT_CREATOR_CONAN_BUILD_POLICY}
-s build_type=${CMAKE_BUILD_TYPE}
-g CMakeDeps)
if (CONAN_INSTALL_SUCCESS)
file(WRITE \"${CMAKE_BINARY_DIR}/conan-dependencies/conan_paths.cmake\" \"
list(PREPEND CMAKE_PREFIX_PATH \\\"\${CONAN_GENERATORS_FOLDER}\\\")
list(PREPEND CMAKE_MODULE_PATH \\\"\${CONAN_GENERATORS_FOLDER}\\\")
\")
endif()
else()
include(\"${CMAKE_CURRENT_LIST_DIR}/conan.cmake\")
conan_cmake_run(
CONANFILE \"${conanfile_txt}\"
INSTALL_FOLDER \"${CMAKE_BINARY_DIR}/conan-dependencies\"
GENERATORS cmake_paths cmake_find_package json
BUILD ${QT_CREATOR_CONAN_BUILD_POLICY}
ENV CONAN_CMAKE_TOOLCHAIN_FILE=\"${CMAKE_BINARY_DIR}/conan-dependencies/toolchain.cmake\"
)
endif()
")
execute_process(COMMAND ${CMAKE_COMMAND} execute_process(COMMAND ${CMAKE_COMMAND}
-S "${CMAKE_BINARY_DIR}/conan-dependencies/" -S "${CMAKE_BINARY_DIR}/conan-dependencies/"

View File

@@ -0,0 +1,211 @@
# https://github.com/conan-io/cmake-conan/blob/develop2/conan_support.cmake
# commit: 3e088cd3e1d9d69e04b5250d565c1b8b55b0400b
#
# The MIT License (MIT)
#
# Copyright (c) 2019 JFrog
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
function(detect_os OS)
# it could be cross compilation
message(STATUS "Conan-cmake: cmake_system_name=${CMAKE_SYSTEM_NAME}")
if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(${OS} Macos PARENT_SCOPE)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "QNX")
set(${OS} Neutrino PARENT_SCOPE)
else()
set(${OS} ${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
endif()
endif()
endfunction()
function(detect_cxx_standard CXX_STANDARD)
set(${CXX_STANDARD} ${CMAKE_CXX_STANDARD} PARENT_SCOPE)
if (CMAKE_CXX_EXTENSIONS)
set(${CXX_STANDARD} "gnu${CMAKE_CXX_STANDARD}" PARENT_SCOPE)
endif()
endfunction()
function(detect_compiler COMPILER COMPILER_VERSION)
if(DEFINED CMAKE_CXX_COMPILER_ID)
set(_COMPILER ${CMAKE_CXX_COMPILER_ID})
set(_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
else()
if(NOT DEFINED CMAKE_C_COMPILER_ID)
message(FATAL_ERROR "C or C++ compiler not defined")
endif()
set(_COMPILER ${CMAKE_C_COMPILER_ID})
set(_COMPILER_VERSION ${CMAKE_C_COMPILER_VERSION})
endif()
message(STATUS "Conan-cmake: CMake compiler=${_COMPILER}")
message(STATUS "Conan-cmake: CMake cmpiler version=${_COMPILER_VERSION}")
if(_COMPILER MATCHES MSVC)
set(_COMPILER "msvc")
string(SUBSTRING ${MSVC_VERSION} 0 3 _COMPILER_VERSION)
elseif(_COMPILER MATCHES AppleClang)
set(_COMPILER "apple-clang")
string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
list(GET VERSION_LIST 0 _COMPILER_VERSION)
elseif(_COMPILER MATCHES Clang)
set(_COMPILER "clang")
string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
list(GET VERSION_LIST 0 _COMPILER_VERSION)
elseif(_COMPILER MATCHES GNU)
set(_COMPILER "gcc")
string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
list(GET VERSION_LIST 0 _COMPILER_VERSION)
endif()
message(STATUS "Conan-cmake: [settings] compiler=${_COMPILER}")
message(STATUS "Conan-cmake: [settings] compiler.version=${_COMPILER_VERSION}")
set(${COMPILER} ${_COMPILER} PARENT_SCOPE)
set(${COMPILER_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
endfunction()
function(detect_build_type BUILD_TYPE)
if(NOT CMAKE_CONFIGURATION_TYPES)
# Only set when we know we are in a single-configuration generator
# Note: we may want to fail early if `CMAKE_BUILD_TYPE` is not defined
set(${BUILD_TYPE} ${CMAKE_BUILD_TYPE} PARENT_SCOPE)
endif()
endfunction()
function(detect_host_profile output_file)
detect_os(MYOS)
detect_compiler(MYCOMPILER MYCOMPILER_VERSION)
detect_cxx_standard(MYCXX_STANDARD)
detect_build_type(MYBUILD_TYPE)
set(PROFILE "")
string(APPEND PROFILE "include(default)\n")
string(APPEND PROFILE "[settings]\n")
if(MYOS)
string(APPEND PROFILE os=${MYOS} "\n")
endif()
if(MYCOMPILER)
string(APPEND PROFILE compiler=${MYCOMPILER} "\n")
endif()
if(MYCOMPILER_VERSION)
string(APPEND PROFILE compiler.version=${MYCOMPILER_VERSION} "\n")
endif()
if(MYCXX_STANDARD)
string(APPEND PROFILE compiler.cppstd=${MYCXX_STANDARD} "\n")
endif()
if(MYBUILD_TYPE)
string(APPEND PROFILE "build_type=${MYBUILD_TYPE}\n")
endif()
if(NOT DEFINED output_file)
set(_FN "${CMAKE_BINARY_DIR}/profile")
else()
set(_FN ${output_file})
endif()
string(APPEND PROFILE "[conf]\n")
string(APPEND PROFILE "tools.cmake.cmaketoolchain:generator=${CMAKE_GENERATOR}\n")
message(STATUS "Conan-cmake: Creating profile ${_FN}")
file(WRITE ${_FN} ${PROFILE})
message(STATUS "Conan-cmake: Profile: \n${PROFILE}")
endfunction()
function(conan_profile_detect_default)
message(STATUS "Conan-cmake: Checking if a default profile exists")
execute_process(COMMAND conan profile path default
RESULT_VARIABLE return_code
OUTPUT_VARIABLE conan_stdout
ERROR_VARIABLE conan_stderr
ECHO_ERROR_VARIABLE # show the text output regardless
ECHO_OUTPUT_VARIABLE
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(NOT ${return_code} EQUAL "0")
message(STATUS "Conan-cmake: The default profile doesn't exist, detecting it.")
execute_process(COMMAND conan profile detect
RESULT_VARIABLE return_code
OUTPUT_VARIABLE conan_stdout
ERROR_VARIABLE conan_stderr
ECHO_ERROR_VARIABLE # show the text output regardless
ECHO_OUTPUT_VARIABLE
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
endfunction()
function(conan_install)
cmake_parse_arguments(ARGS CONAN_ARGS ${ARGN})
set(CONAN_OUTPUT_FOLDER ${CMAKE_BINARY_DIR}/conan)
# Invoke "conan install" with the provided arguments
set(CONAN_ARGS ${CONAN_ARGS} -of=${CONAN_OUTPUT_FOLDER})
message(STATUS "CMake-conan: conan install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN}")
execute_process(COMMAND conan install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN} --format=json
RESULT_VARIABLE return_code
OUTPUT_VARIABLE conan_stdout
ERROR_VARIABLE conan_stderr
ECHO_ERROR_VARIABLE # show the text output regardless
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
if(NOT "${return_code}" STREQUAL "0")
message(FATAL_ERROR "Conan install failed='${return_code}'")
else()
# the files are generated in a folder that depends on the layout used, if
# one if specified, but we don't know a priori where this is.
# TODO: this can be made more robust if Conan can provide this in the json output
string(JSON CONAN_GENERATORS_FOLDER GET ${conan_stdout} graph nodes 0 generators_folder)
# message("conan stdout: ${conan_stdout}")
message(STATUS "CMake-conan: CONAN_GENERATORS_FOLDER=${CONAN_GENERATORS_FOLDER}")
set(CONAN_GENERATORS_FOLDER "${CONAN_GENERATORS_FOLDER}" PARENT_SCOPE)
set(CONAN_INSTALL_SUCCESS TRUE CACHE BOOL "Conan install has been invoked and was successful")
endif()
endfunction()
function(conan_provide_dependency package_name)
if(NOT CONAN_INSTALL_SUCCESS)
message(STATUS "CMake-conan: first find_package() found. Installing dependencies with Conan")
conan_profile_detect_default()
detect_host_profile(${CMAKE_BINARY_DIR}/conan_host_profile)
if(NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "CMake-conan: Installing single configuration ${CMAKE_BUILD_TYPE}")
conan_install(-pr ${CMAKE_BINARY_DIR}/conan_host_profile --build=missing -g CMakeDeps)
else()
message(STATUS "CMake-conan: Installing both Debug and Release")
conan_install(-pr ${CMAKE_BINARY_DIR}/conan_host_profile -s build_type=Release --build=missing -g CMakeDeps)
conan_install(-pr ${CMAKE_BINARY_DIR}/conan_host_profile -s build_type=Debug --build=missing -g CMakeDeps)
endif()
if (CONAN_INSTALL_SUCCESS)
set(CONAN_GENERATORS_FOLDER "${CONAN_GENERATORS_FOLDER}" CACHE PATH "Conan generators folder")
endif()
else()
message(STATUS "CMake-conan: find_package(${package_name}) found, 'conan install' aready ran")
endif()
if (CONAN_GENERATORS_FOLDER)
list(PREPEND CMAKE_PREFIX_PATH "${CONAN_GENERATORS_FOLDER}")
endif()
find_package(${ARGN} BYPASS_PROVIDER)
endfunction()

View File

@@ -1,4 +1,2 @@
[requires] [requires]
fmt/8.0.0 fmt/9.1.0
[generators]
cmake_find_package