奥特QT DDS 插件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

656 line
27KB

  1. # https://github.com/conan-io/cmake-conan/blob/develop2/conan_provider.cmake
  2. # commit: f6464d1e13ef7a47c569f5061f9607ea63339d39
  3. #
  4. # The MIT License (MIT)
  5. #
  6. # Copyright (c) 2019 JFrog
  7. #
  8. # Permission is hereby granted, free of charge, to any person obtaining a copy
  9. # of this software and associated documentation files (the "Software"), to deal
  10. # in the Software without restriction, including without limitation the rights
  11. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. # copies of the Software, and to permit persons to whom the Software is
  13. # furnished to do so, subject to the following conditions:
  14. #
  15. # The above copyright notice and this permission notice shall be included in all
  16. # copies or substantial portions of the Software.
  17. #
  18. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. # SOFTWARE.
  25. set(CONAN_MINIMUM_VERSION 2.0.5)
  26. function(detect_os OS OS_API_LEVEL OS_SDK OS_SUBSYSTEM OS_VERSION)
  27. # it could be cross compilation
  28. message(STATUS "CMake-Conan: cmake_system_name=${CMAKE_SYSTEM_NAME}")
  29. if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic")
  30. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  31. set(${OS} Macos PARENT_SCOPE)
  32. elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX")
  33. set(${OS} Neutrino PARENT_SCOPE)
  34. elseif(CMAKE_SYSTEM_NAME STREQUAL "CYGWIN")
  35. set(${OS} Windows PARENT_SCOPE)
  36. set(${OS_SUBSYSTEM} cygwin PARENT_SCOPE)
  37. elseif(CMAKE_SYSTEM_NAME MATCHES "^MSYS")
  38. set(${OS} Windows PARENT_SCOPE)
  39. set(${OS_SUBSYSTEM} msys2 PARENT_SCOPE)
  40. else()
  41. set(${OS} ${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
  42. endif()
  43. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  44. if(DEFINED ANDROID_PLATFORM)
  45. string(REGEX MATCH "[0-9]+" _OS_API_LEVEL ${ANDROID_PLATFORM})
  46. elseif(DEFINED CMAKE_SYSTEM_VERSION)
  47. set(_OS_API_LEVEL ${CMAKE_SYSTEM_VERSION})
  48. endif()
  49. message(STATUS "CMake-Conan: android api level=${_OS_API_LEVEL}")
  50. set(${OS_API_LEVEL} ${_OS_API_LEVEL} PARENT_SCOPE)
  51. endif()
  52. if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS")
  53. # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja
  54. # generators, but just has the original input string for Xcode.
  55. if(NOT IS_DIRECTORY ${CMAKE_OSX_SYSROOT})
  56. set(_OS_SDK ${CMAKE_OSX_SYSROOT})
  57. else()
  58. if(CMAKE_OSX_SYSROOT MATCHES Simulator)
  59. set(apple_platform_suffix simulator)
  60. else()
  61. set(apple_platform_suffix os)
  62. endif()
  63. if(CMAKE_OSX_SYSROOT MATCHES AppleTV)
  64. set(_OS_SDK "appletv${apple_platform_suffix}")
  65. elseif(CMAKE_OSX_SYSROOT MATCHES iPhone)
  66. set(_OS_SDK "iphone${apple_platform_suffix}")
  67. elseif(CMAKE_OSX_SYSROOT MATCHES Watch)
  68. set(_OS_SDK "watch${apple_platform_suffix}")
  69. endif()
  70. endif()
  71. if(DEFINED _OS_SDK)
  72. message(STATUS "CMake-Conan: cmake_osx_sysroot=${CMAKE_OSX_SYSROOT}")
  73. set(${OS_SDK} ${_OS_SDK} PARENT_SCOPE)
  74. endif()
  75. if(DEFINED CMAKE_OSX_DEPLOYMENT_TARGET)
  76. message(STATUS "CMake-Conan: cmake_osx_deployment_target=${CMAKE_OSX_DEPLOYMENT_TARGET}")
  77. set(${OS_VERSION} ${CMAKE_OSX_DEPLOYMENT_TARGET} PARENT_SCOPE)
  78. endif()
  79. endif()
  80. endif()
  81. endfunction()
  82. function(detect_arch ARCH)
  83. # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one.
  84. # Therefore this code only finds one. If the recipes support multiple architectures, the
  85. # build will work. Otherwise, there will be a linker error for the missing architecture(s).
  86. if(DEFINED CMAKE_OSX_ARCHITECTURES)
  87. string(REPLACE " " ";" apple_arch_list "${CMAKE_OSX_ARCHITECTURES}")
  88. list(LENGTH apple_arch_list apple_arch_count)
  89. if(apple_arch_count GREATER 1)
  90. message(WARNING "CMake-Conan: Multiple architectures detected, this will only work if Conan recipe(s) produce fat binaries.")
  91. endif()
  92. endif()
  93. if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS" AND NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
  94. set(host_arch ${CMAKE_OSX_ARCHITECTURES})
  95. elseif(MSVC)
  96. set(host_arch ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID})
  97. else()
  98. set(host_arch ${CMAKE_SYSTEM_PROCESSOR})
  99. endif()
  100. if(host_arch MATCHES "aarch64|arm64|ARM64")
  101. set(_ARCH armv8)
  102. elseif(host_arch MATCHES "armv7|armv7-a|armv7l|ARMV7")
  103. set(_ARCH armv7)
  104. elseif(host_arch MATCHES armv7s)
  105. set(_ARCH armv7s)
  106. elseif(host_arch MATCHES "i686|i386|X86")
  107. set(_ARCH x86)
  108. elseif(host_arch MATCHES "AMD64|amd64|x86_64|x64")
  109. set(_ARCH x86_64)
  110. endif()
  111. message(STATUS "CMake-Conan: cmake_system_processor=${_ARCH}")
  112. set(${ARCH} ${_ARCH} PARENT_SCOPE)
  113. endfunction()
  114. function(detect_cxx_standard CXX_STANDARD)
  115. set(${CXX_STANDARD} ${CMAKE_CXX_STANDARD} PARENT_SCOPE)
  116. if(CMAKE_CXX_EXTENSIONS)
  117. set(${CXX_STANDARD} "gnu${CMAKE_CXX_STANDARD}" PARENT_SCOPE)
  118. endif()
  119. endfunction()
  120. macro(detect_gnu_libstdcxx)
  121. # _CONAN_IS_GNU_LIBSTDCXX true if GNU libstdc++
  122. check_cxx_source_compiles("
  123. #include <cstddef>
  124. #if !defined(__GLIBCXX__) && !defined(__GLIBCPP__)
  125. static_assert(false);
  126. #endif
  127. int main(){}" _CONAN_IS_GNU_LIBSTDCXX)
  128. # _CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI true if C++11 ABI
  129. check_cxx_source_compiles("
  130. #include <string>
  131. static_assert(sizeof(std::string) != sizeof(void*), \"using libstdc++\");
  132. int main () {}" _CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI)
  133. set(_CONAN_GNU_LIBSTDCXX_SUFFIX "")
  134. if(_CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI)
  135. set(_CONAN_GNU_LIBSTDCXX_SUFFIX "11")
  136. endif()
  137. unset (_CONAN_GNU_LIBSTDCXX_IS_CXX11_ABI)
  138. endmacro()
  139. macro(detect_libcxx)
  140. # _CONAN_IS_LIBCXX true if LLVM libc++
  141. check_cxx_source_compiles("
  142. #include <cstddef>
  143. #if !defined(_LIBCPP_VERSION)
  144. static_assert(false);
  145. #endif
  146. int main(){}" _CONAN_IS_LIBCXX)
  147. endmacro()
  148. function(detect_lib_cxx LIB_CXX)
  149. if(CMAKE_SYSTEM_NAME STREQUAL "Android")
  150. message(STATUS "CMake-Conan: android_stl=${CMAKE_ANDROID_STL_TYPE}")
  151. set(${LIB_CXX} ${CMAKE_ANDROID_STL_TYPE} PARENT_SCOPE)
  152. return()
  153. endif()
  154. include(CheckCXXSourceCompiles)
  155. if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
  156. detect_gnu_libstdcxx()
  157. set(${LIB_CXX} "libstdc++${_CONAN_GNU_LIBSTDCXX_SUFFIX}" PARENT_SCOPE)
  158. elseif(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
  159. set(${LIB_CXX} "libc++" PARENT_SCOPE)
  160. elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
  161. # Check for libc++
  162. detect_libcxx()
  163. if(_CONAN_IS_LIBCXX)
  164. set(${LIB_CXX} "libc++" PARENT_SCOPE)
  165. return()
  166. endif()
  167. # Check for libstdc++
  168. detect_gnu_libstdcxx()
  169. if(_CONAN_IS_GNU_LIBSTDCXX)
  170. set(${LIB_CXX} "libstdc++${_CONAN_GNU_LIBSTDCXX_SUFFIX}" PARENT_SCOPE)
  171. return()
  172. endif()
  173. # TODO: it would be an error if we reach this point
  174. elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
  175. # Do nothing - compiler.runtime and compiler.runtime_type
  176. # should be handled separately: https://github.com/conan-io/cmake-conan/pull/516
  177. return()
  178. else()
  179. # TODO: unable to determine, ask user to provide a full profile file instead
  180. endif()
  181. endfunction()
  182. function(detect_compiler COMPILER COMPILER_VERSION COMPILER_RUNTIME COMPILER_RUNTIME_TYPE)
  183. if(DEFINED CMAKE_CXX_COMPILER_ID)
  184. set(_COMPILER ${CMAKE_CXX_COMPILER_ID})
  185. set(_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
  186. else()
  187. if(NOT DEFINED CMAKE_C_COMPILER_ID)
  188. message(FATAL_ERROR "C or C++ compiler not defined")
  189. endif()
  190. set(_COMPILER ${CMAKE_C_COMPILER_ID})
  191. set(_COMPILER_VERSION ${CMAKE_C_COMPILER_VERSION})
  192. endif()
  193. message(STATUS "CMake-Conan: CMake compiler=${_COMPILER}")
  194. message(STATUS "CMake-Conan: CMake compiler version=${_COMPILER_VERSION}")
  195. if(_COMPILER MATCHES MSVC)
  196. set(_COMPILER "msvc")
  197. string(SUBSTRING ${MSVC_VERSION} 0 3 _COMPILER_VERSION)
  198. # Configure compiler.runtime and compiler.runtime_type settings for MSVC
  199. if(CMAKE_MSVC_RUNTIME_LIBRARY)
  200. set(_msvc_runtime_library ${CMAKE_MSVC_RUNTIME_LIBRARY})
  201. else()
  202. set(_msvc_runtime_library MultiThreaded$<$<CONFIG:Debug>:Debug>DLL) # default value documented by CMake
  203. endif()
  204. set(_KNOWN_MSVC_RUNTIME_VALUES "")
  205. list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded MultiThreadedDLL)
  206. list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreadedDebug MultiThreadedDebugDLL)
  207. list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded$<$<CONFIG:Debug>:Debug> MultiThreaded$<$<CONFIG:Debug>:Debug>DLL)
  208. # only accept the 6 possible values, otherwise we don't don't know to map this
  209. if(NOT _msvc_runtime_library IN_LIST _KNOWN_MSVC_RUNTIME_VALUES)
  210. message(FATAL_ERROR "CMake-Conan: unable to map MSVC runtime: ${_msvc_runtime_library} to Conan settings")
  211. endif()
  212. # Runtime is "dynamic" in all cases if it ends in DLL
  213. if(_msvc_runtime_library MATCHES ".*DLL$")
  214. set(_COMPILER_RUNTIME "dynamic")
  215. else()
  216. set(_COMPILER_RUNTIME "static")
  217. endif()
  218. message(STATUS "CMake-Conan: CMake compiler.runtime=${_COMPILER_RUNTIME}")
  219. # Only define compiler.runtime_type when explicitly requested
  220. # If a generator expression is used, let Conan handle it conditional on build_type
  221. if(NOT _msvc_runtime_library MATCHES "<CONFIG:Debug>:Debug>")
  222. if(_msvc_runtime_library MATCHES "Debug")
  223. set(_COMPILER_RUNTIME_TYPE "Debug")
  224. else()
  225. set(_COMPILER_RUNTIME_TYPE "Release")
  226. endif()
  227. message(STATUS "CMake-Conan: CMake compiler.runtime_type=${_COMPILER_RUNTIME_TYPE}")
  228. endif()
  229. unset(_KNOWN_MSVC_RUNTIME_VALUES)
  230. elseif(_COMPILER MATCHES AppleClang)
  231. set(_COMPILER "apple-clang")
  232. string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
  233. list(GET VERSION_LIST 0 _COMPILER_VERSION)
  234. elseif(_COMPILER MATCHES Clang)
  235. set(_COMPILER "clang")
  236. string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
  237. list(GET VERSION_LIST 0 _COMPILER_VERSION)
  238. elseif(_COMPILER MATCHES GNU)
  239. set(_COMPILER "gcc")
  240. string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION})
  241. list(GET VERSION_LIST 0 _COMPILER_VERSION)
  242. endif()
  243. message(STATUS "CMake-Conan: [settings] compiler=${_COMPILER}")
  244. message(STATUS "CMake-Conan: [settings] compiler.version=${_COMPILER_VERSION}")
  245. if (_COMPILER_RUNTIME)
  246. message(STATUS "CMake-Conan: [settings] compiler.runtime=${_COMPILER_RUNTIME}")
  247. endif()
  248. if (_COMPILER_RUNTIME_TYPE)
  249. message(STATUS "CMake-Conan: [settings] compiler.runtime_type=${_COMPILER_RUNTIME_TYPE}")
  250. endif()
  251. set(${COMPILER} ${_COMPILER} PARENT_SCOPE)
  252. set(${COMPILER_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
  253. set(${COMPILER_RUNTIME} ${_COMPILER_RUNTIME} PARENT_SCOPE)
  254. set(${COMPILER_RUNTIME_TYPE} ${_COMPILER_RUNTIME_TYPE} PARENT_SCOPE)
  255. endfunction()
  256. function(detect_build_type BUILD_TYPE)
  257. get_property(_MULTICONFIG_GENERATOR GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  258. if(NOT _MULTICONFIG_GENERATOR)
  259. # Only set when we know we are in a single-configuration generator
  260. # Note: we may want to fail early if `CMAKE_BUILD_TYPE` is not defined
  261. set(${BUILD_TYPE} ${CMAKE_BUILD_TYPE} PARENT_SCOPE)
  262. endif()
  263. endfunction()
  264. macro(set_conan_compiler_if_appleclang lang command output_variable)
  265. if(CMAKE_${lang}_COMPILER_ID STREQUAL "AppleClang")
  266. execute_process(COMMAND xcrun --find ${command}
  267. OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE)
  268. cmake_path(GET _xcrun_out PARENT_PATH _xcrun_toolchain_path)
  269. cmake_path(GET CMAKE_${lang}_COMPILER PARENT_PATH _compiler_parent_path)
  270. if ("${_xcrun_toolchain_path}" STREQUAL "${_compiler_parent_path}")
  271. set(${output_variable} "")
  272. endif()
  273. unset(_xcrun_out)
  274. unset(_xcrun_toolchain_path)
  275. unset(_compiler_parent_path)
  276. endif()
  277. endmacro()
  278. macro(append_compiler_executables_configuration)
  279. set(_conan_c_compiler "")
  280. set(_conan_cpp_compiler "")
  281. if(CMAKE_C_COMPILER)
  282. set(_conan_c_compiler "\"c\":\"${CMAKE_C_COMPILER}\",")
  283. set_conan_compiler_if_appleclang(C cc _conan_c_compiler)
  284. else()
  285. message(WARNING "CMake-Conan: The C compiler is not defined. "
  286. "Please define CMAKE_C_COMPILER or enable the C language.")
  287. endif()
  288. if(CMAKE_CXX_COMPILER)
  289. set(_conan_cpp_compiler "\"cpp\":\"${CMAKE_CXX_COMPILER}\"")
  290. set_conan_compiler_if_appleclang(CXX c++ _conan_cpp_compiler)
  291. else()
  292. message(WARNING "CMake-Conan: The C++ compiler is not defined. "
  293. "Please define CMAKE_CXX_COMPILER or enable the C++ language.")
  294. endif()
  295. if(NOT "x${_conan_c_compiler}${_conan_cpp_compiler}" STREQUAL "x")
  296. string(APPEND PROFILE "tools.build:compiler_executables={${_conan_c_compiler}${_conan_cpp_compiler}}\n")
  297. endif()
  298. unset(_conan_c_compiler)
  299. unset(_conan_cpp_compiler)
  300. endmacro()
  301. function(detect_host_profile output_file)
  302. detect_os(MYOS MYOS_API_LEVEL MYOS_SDK MYOS_SUBSYSTEM MYOS_VERSION)
  303. detect_arch(MYARCH)
  304. detect_compiler(MYCOMPILER MYCOMPILER_VERSION MYCOMPILER_RUNTIME MYCOMPILER_RUNTIME_TYPE)
  305. detect_cxx_standard(MYCXX_STANDARD)
  306. detect_lib_cxx(MYLIB_CXX)
  307. detect_build_type(MYBUILD_TYPE)
  308. set(PROFILE "")
  309. string(APPEND PROFILE "[settings]\n")
  310. if(MYARCH)
  311. string(APPEND PROFILE arch=${MYARCH} "\n")
  312. endif()
  313. if(MYOS)
  314. string(APPEND PROFILE os=${MYOS} "\n")
  315. endif()
  316. if(MYOS_API_LEVEL)
  317. string(APPEND PROFILE os.api_level=${MYOS_API_LEVEL} "\n")
  318. endif()
  319. if(MYOS_VERSION)
  320. string(APPEND PROFILE os.version=${MYOS_VERSION} "\n")
  321. endif()
  322. if(MYOS_SDK)
  323. string(APPEND PROFILE os.sdk=${MYOS_SDK} "\n")
  324. endif()
  325. if(MYOS_SUBSYSTEM)
  326. string(APPEND PROFILE os.subsystem=${MYOS_SUBSYSTEM} "\n")
  327. endif()
  328. if(MYCOMPILER)
  329. string(APPEND PROFILE compiler=${MYCOMPILER} "\n")
  330. endif()
  331. if(MYCOMPILER_VERSION)
  332. string(APPEND PROFILE compiler.version=${MYCOMPILER_VERSION} "\n")
  333. endif()
  334. if(MYCOMPILER_RUNTIME)
  335. string(APPEND PROFILE compiler.runtime=${MYCOMPILER_RUNTIME} "\n")
  336. endif()
  337. if(MYCOMPILER_RUNTIME_TYPE)
  338. string(APPEND PROFILE compiler.runtime_type=${MYCOMPILER_RUNTIME_TYPE} "\n")
  339. endif()
  340. if(MYCXX_STANDARD)
  341. string(APPEND PROFILE compiler.cppstd=${MYCXX_STANDARD} "\n")
  342. endif()
  343. if(MYLIB_CXX)
  344. string(APPEND PROFILE compiler.libcxx=${MYLIB_CXX} "\n")
  345. endif()
  346. if(MYBUILD_TYPE)
  347. string(APPEND PROFILE "build_type=${MYBUILD_TYPE}\n")
  348. endif()
  349. if(NOT DEFINED output_file)
  350. set(_FN "${CMAKE_BINARY_DIR}/profile")
  351. else()
  352. set(_FN ${output_file})
  353. endif()
  354. string(APPEND PROFILE "[conf]\n")
  355. string(APPEND PROFILE "tools.cmake.cmaketoolchain:generator=${CMAKE_GENERATOR}\n")
  356. # propagate compilers via profile
  357. append_compiler_executables_configuration()
  358. if(MYOS STREQUAL "Android")
  359. string(APPEND PROFILE "tools.android:ndk_path=${CMAKE_ANDROID_NDK}\n")
  360. endif()
  361. message(STATUS "CMake-Conan: Creating profile ${_FN}")
  362. file(WRITE ${_FN} ${PROFILE})
  363. message(STATUS "CMake-Conan: Profile: \n${PROFILE}")
  364. endfunction()
  365. function(conan_profile_detect_default)
  366. message(STATUS "CMake-Conan: Checking if a default profile exists")
  367. execute_process(COMMAND ${CONAN_COMMAND} profile path default
  368. RESULT_VARIABLE return_code
  369. OUTPUT_VARIABLE conan_stdout
  370. ERROR_VARIABLE conan_stderr
  371. ECHO_ERROR_VARIABLE # show the text output regardless
  372. ECHO_OUTPUT_VARIABLE
  373. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  374. if(NOT ${return_code} EQUAL "0")
  375. message(STATUS "CMake-Conan: The default profile doesn't exist, detecting it.")
  376. execute_process(COMMAND ${CONAN_COMMAND} profile detect
  377. RESULT_VARIABLE return_code
  378. OUTPUT_VARIABLE conan_stdout
  379. ERROR_VARIABLE conan_stderr
  380. ECHO_ERROR_VARIABLE # show the text output regardless
  381. ECHO_OUTPUT_VARIABLE
  382. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  383. endif()
  384. endfunction()
  385. function(conan_install)
  386. cmake_parse_arguments(ARGS CONAN_ARGS ${ARGN})
  387. set(CONAN_OUTPUT_FOLDER ${CMAKE_BINARY_DIR}/conan)
  388. # Invoke "conan install" with the provided arguments
  389. set(CONAN_ARGS ${CONAN_ARGS} -of=${CONAN_OUTPUT_FOLDER})
  390. message(STATUS "CMake-Conan: conan install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN}")
  391. # In case there was not a valid cmake executable in the PATH, we inject the
  392. # same we used to invoke the provider to the PATH
  393. if(DEFINED PATH_TO_CMAKE_BIN)
  394. set(_OLD_PATH $ENV{PATH})
  395. set(ENV{PATH} "$ENV{PATH}:${PATH_TO_CMAKE_BIN}")
  396. endif()
  397. execute_process(COMMAND ${CONAN_COMMAND} install ${CMAKE_SOURCE_DIR} ${CONAN_ARGS} ${ARGN} --format=json
  398. RESULT_VARIABLE return_code
  399. OUTPUT_VARIABLE conan_stdout
  400. ERROR_VARIABLE conan_stderr
  401. ECHO_ERROR_VARIABLE # show the text output regardless
  402. WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  403. if(DEFINED PATH_TO_CMAKE_BIN)
  404. set(ENV{PATH} "${_OLD_PATH}")
  405. endif()
  406. if(NOT "${return_code}" STREQUAL "0")
  407. message(FATAL_ERROR "Conan install failed='${return_code}'")
  408. else()
  409. # the files are generated in a folder that depends on the layout used, if
  410. # one is specified, but we don't know a priori where this is.
  411. # TODO: this can be made more robust if Conan can provide this in the json output
  412. string(JSON CONAN_GENERATORS_FOLDER GET ${conan_stdout} graph nodes 0 generators_folder)
  413. cmake_path(CONVERT ${CONAN_GENERATORS_FOLDER} TO_CMAKE_PATH_LIST CONAN_GENERATORS_FOLDER)
  414. # message("conan stdout: ${conan_stdout}")
  415. message(STATUS "CMake-Conan: CONAN_GENERATORS_FOLDER=${CONAN_GENERATORS_FOLDER}")
  416. set_property(GLOBAL PROPERTY CONAN_GENERATORS_FOLDER "${CONAN_GENERATORS_FOLDER}")
  417. # reconfigure on conanfile changes
  418. string(JSON CONANFILE GET ${conan_stdout} graph nodes 0 label)
  419. message(STATUS "CMake-Conan: CONANFILE=${CMAKE_SOURCE_DIR}/${CONANFILE}")
  420. set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/${CONANFILE}")
  421. # success
  422. set_property(GLOBAL PROPERTY CONAN_INSTALL_SUCCESS TRUE)
  423. endif()
  424. endfunction()
  425. function(conan_get_version conan_command conan_current_version)
  426. execute_process(
  427. COMMAND ${conan_command} --version
  428. OUTPUT_VARIABLE conan_output
  429. RESULT_VARIABLE conan_result
  430. OUTPUT_STRIP_TRAILING_WHITESPACE
  431. )
  432. if(conan_result)
  433. message(FATAL_ERROR "CMake-Conan: Error when trying to run Conan")
  434. endif()
  435. string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" conan_version ${conan_output})
  436. set(${conan_current_version} ${conan_version} PARENT_SCOPE)
  437. endfunction()
  438. function(conan_version_check)
  439. set(options )
  440. set(oneValueArgs MINIMUM CURRENT)
  441. set(multiValueArgs )
  442. cmake_parse_arguments(CONAN_VERSION_CHECK
  443. "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  444. if(NOT CONAN_VERSION_CHECK_MINIMUM)
  445. message(FATAL_ERROR "CMake-Conan: Required parameter MINIMUM not set!")
  446. endif()
  447. if(NOT CONAN_VERSION_CHECK_CURRENT)
  448. message(FATAL_ERROR "CMake-Conan: Required parameter CURRENT not set!")
  449. endif()
  450. if(CONAN_VERSION_CHECK_CURRENT VERSION_LESS CONAN_VERSION_CHECK_MINIMUM)
  451. message(FATAL_ERROR "CMake-Conan: Conan version must be ${CONAN_VERSION_CHECK_MINIMUM} or later")
  452. endif()
  453. endfunction()
  454. macro(construct_profile_argument argument_variable profile_list)
  455. set(${argument_variable} "")
  456. if("${profile_list}" STREQUAL "CONAN_HOST_PROFILE")
  457. set(_arg_flag "--profile:host=")
  458. elseif("${profile_list}" STREQUAL "CONAN_BUILD_PROFILE")
  459. set(_arg_flag "--profile:build=")
  460. endif()
  461. set(_profile_list "${${profile_list}}")
  462. list(TRANSFORM _profile_list REPLACE "auto-cmake" "${CMAKE_BINARY_DIR}/conan_host_profile")
  463. list(TRANSFORM _profile_list PREPEND ${_arg_flag})
  464. set(${argument_variable} ${_profile_list})
  465. unset(_arg_flag)
  466. unset(_profile_list)
  467. endmacro()
  468. macro(conan_provide_dependency method package_name)
  469. set_property(GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED TRUE)
  470. get_property(_conan_install_success GLOBAL PROPERTY CONAN_INSTALL_SUCCESS)
  471. if(NOT _conan_install_success)
  472. find_program(CONAN_COMMAND "conan" REQUIRED)
  473. conan_get_version(${CONAN_COMMAND} CONAN_CURRENT_VERSION)
  474. conan_version_check(MINIMUM ${CONAN_MINIMUM_VERSION} CURRENT ${CONAN_CURRENT_VERSION})
  475. message(STATUS "CMake-Conan: first find_package() found. Installing dependencies with Conan")
  476. if("default" IN_LIST CONAN_HOST_PROFILE OR "default" IN_LIST CONAN_BUILD_PROFILE)
  477. conan_profile_detect_default()
  478. endif()
  479. if("auto-cmake" IN_LIST CONAN_HOST_PROFILE)
  480. detect_host_profile(${CMAKE_BINARY_DIR}/conan_host_profile)
  481. endif()
  482. construct_profile_argument(_host_profile_flags CONAN_HOST_PROFILE)
  483. construct_profile_argument(_build_profile_flags CONAN_BUILD_PROFILE)
  484. if(EXISTS "${CMAKE_SOURCE_DIR}/conanfile.py")
  485. file(READ "${CMAKE_SOURCE_DIR}/conanfile.py" outfile)
  486. if(NOT "${outfile}" MATCHES ".*CMakeDeps.*")
  487. message(WARNING "Cmake-conan: CMakeDeps generator was not defined in the conanfile")
  488. endif()
  489. set(generator "")
  490. elseif (EXISTS "${CMAKE_SOURCE_DIR}/conanfile.txt")
  491. file(READ "${CMAKE_SOURCE_DIR}/conanfile.txt" outfile)
  492. if(NOT "${outfile}" MATCHES ".*CMakeDeps.*")
  493. message(WARNING "Cmake-conan: CMakeDeps generator was not defined in the conanfile. "
  494. "Please define the generator as it will be mandatory in the future")
  495. endif()
  496. set(generator "-g;CMakeDeps")
  497. endif()
  498. get_property(_multiconfig_generator GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  499. if(NOT _multiconfig_generator)
  500. message(STATUS "CMake-Conan: Installing single configuration ${CMAKE_BUILD_TYPE}")
  501. conan_install(${_host_profile_flags} ${_build_profile_flags} ${CONAN_INSTALL_ARGS} ${generator})
  502. else()
  503. message(STATUS "CMake-Conan: Installing both Debug and Release")
  504. conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Release ${CONAN_INSTALL_ARGS} ${generator})
  505. conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Debug ${CONAN_INSTALL_ARGS} ${generator})
  506. endif()
  507. unset(_host_profile_flags)
  508. unset(_build_profile_flags)
  509. unset(_multiconfig_generator)
  510. unset(_conan_install_success)
  511. else()
  512. message(STATUS "CMake-Conan: find_package(${ARGV1}) found, 'conan install' already ran")
  513. unset(_conan_install_success)
  514. endif()
  515. get_property(_conan_generators_folder GLOBAL PROPERTY CONAN_GENERATORS_FOLDER)
  516. # Ensure that we consider Conan-provided packages ahead of any other,
  517. # irrespective of other settings that modify the search order or search paths
  518. # This follows the guidelines from the find_package documentation
  519. # (https://cmake.org/cmake/help/latest/command/find_package.html):
  520. # find_package (<PackageName> PATHS paths... NO_DEFAULT_PATH)
  521. # find_package (<PackageName>)
  522. # Filter out `REQUIRED` from the argument list, as the first call may fail
  523. set(_find_args_${package_name} "${ARGN}")
  524. list(REMOVE_ITEM _find_args_${package_name} "REQUIRED")
  525. if(NOT "MODULE" IN_LIST _find_args_${package_name})
  526. find_package(${package_name} ${_find_args_${package_name}} BYPASS_PROVIDER PATHS "${_conan_generators_folder}" NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
  527. unset(_find_args_${package_name})
  528. endif()
  529. # Invoke find_package a second time - if the first call succeeded,
  530. # this will simply reuse the result. If not, fall back to CMake default search
  531. # behaviour, also allowing modules to be searched.
  532. if(NOT ${package_name}_FOUND)
  533. list(FIND CMAKE_MODULE_PATH "${_conan_generators_folder}" _index)
  534. if(_index EQUAL -1)
  535. list(PREPEND CMAKE_MODULE_PATH "${_conan_generators_folder}")
  536. endif()
  537. unset(_index)
  538. find_package(${package_name} ${ARGN} BYPASS_PROVIDER)
  539. list(REMOVE_ITEM CMAKE_MODULE_PATH "${_conan_generators_folder}")
  540. endif()
  541. endmacro()
  542. #[=[ not needed by Qt Creator, and if not commented it would break the auto-setup feature
  543. cmake_language(
  544. SET_DEPENDENCY_PROVIDER conan_provide_dependency
  545. SUPPORTED_METHODS FIND_PACKAGE
  546. )
  547. macro(conan_provide_dependency_check)
  548. set(_CONAN_PROVIDE_DEPENDENCY_INVOKED FALSE)
  549. get_property(_CONAN_PROVIDE_DEPENDENCY_INVOKED GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED)
  550. if(NOT _CONAN_PROVIDE_DEPENDENCY_INVOKED)
  551. message(WARNING "Conan is correctly configured as dependency provider, "
  552. "but Conan has not been invoked. Please add at least one "
  553. "call to `find_package()`.")
  554. if(DEFINED CONAN_COMMAND)
  555. # supress warning in case `CONAN_COMMAND` was specified but unused.
  556. set(_CONAN_COMMAND ${CONAN_COMMAND})
  557. unset(_CONAN_COMMAND)
  558. endif()
  559. endif()
  560. unset(_CONAN_PROVIDE_DEPENDENCY_INVOKED)
  561. endmacro()
  562. # Add a deferred call at the end of processing the top-level directory
  563. # to check if the dependency provider was invoked at all.
  564. cmake_language(DEFER DIRECTORY "${CMAKE_SOURCE_DIR}" CALL conan_provide_dependency_check)
  565. ]=]
  566. # Configurable variables for Conan profiles
  567. set(CONAN_HOST_PROFILE "default;auto-cmake" CACHE STRING "Conan host profile")
  568. set(CONAN_BUILD_PROFILE "default" CACHE STRING "Conan build profile")
  569. set(CONAN_INSTALL_ARGS "--build=missing" CACHE STRING "Command line arguments for conan install")
  570. find_program(_cmake_program NAMES cmake NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH)
  571. if(NOT _cmake_program)
  572. get_filename_component(PATH_TO_CMAKE_BIN "${CMAKE_COMMAND}" DIRECTORY)
  573. set(PATH_TO_CMAKE_BIN "${PATH_TO_CMAKE_BIN}" CACHE INTERNAL "Path where the CMake executable is")
  574. endif()