FindICU.cmake 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file Copyright.txt or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. FindICU
  5. -------
  6. Find the International Components for Unicode (ICU) libraries and
  7. programs.
  8. This module supports multiple components.
  9. Components can include any of: ``data``, ``i18n``, ``io``, ``le``,
  10. ``lx``, ``test``, ``tu`` and ``uc``.
  11. Note that on Windows ``data`` is named ``dt`` and ``i18n`` is named
  12. ``in``; any of the names may be used, and the appropriate
  13. platform-specific library name will be automatically selected.
  14. This module reports information about the ICU installation in
  15. several variables. General variables::
  16. ICU_VERSION - ICU release version
  17. ICU_FOUND - true if the main programs and libraries were found
  18. ICU_LIBRARIES - component libraries to be linked
  19. ICU_INCLUDE_DIRS - the directories containing the ICU headers
  20. Imported targets::
  21. ICU::<C>
  22. Where ``<C>`` is the name of an ICU component, for example
  23. ``ICU::i18n``.
  24. ICU programs are reported in::
  25. ICU_GENCNVAL_EXECUTABLE - path to gencnval executable
  26. ICU_ICUINFO_EXECUTABLE - path to icuinfo executable
  27. ICU_GENBRK_EXECUTABLE - path to genbrk executable
  28. ICU_ICU-CONFIG_EXECUTABLE - path to icu-config executable
  29. ICU_GENRB_EXECUTABLE - path to genrb executable
  30. ICU_GENDICT_EXECUTABLE - path to gendict executable
  31. ICU_DERB_EXECUTABLE - path to derb executable
  32. ICU_PKGDATA_EXECUTABLE - path to pkgdata executable
  33. ICU_UCONV_EXECUTABLE - path to uconv executable
  34. ICU_GENCFU_EXECUTABLE - path to gencfu executable
  35. ICU_MAKECONV_EXECUTABLE - path to makeconv executable
  36. ICU_GENNORM2_EXECUTABLE - path to gennorm2 executable
  37. ICU_GENCCODE_EXECUTABLE - path to genccode executable
  38. ICU_GENSPREP_EXECUTABLE - path to gensprep executable
  39. ICU_ICUPKG_EXECUTABLE - path to icupkg executable
  40. ICU_GENCMN_EXECUTABLE - path to gencmn executable
  41. ICU component libraries are reported in::
  42. ICU_<C>_FOUND - ON if component was found
  43. ICU_<C>_LIBRARIES - libraries for component
  44. ICU datafiles are reported in::
  45. ICU_MAKEFILE_INC - Makefile.inc
  46. ICU_PKGDATA_INC - pkgdata.inc
  47. Note that ``<C>`` is the uppercased name of the component.
  48. This module reads hints about search results from::
  49. ICU_ROOT - the root of the ICU installation
  50. The environment variable ``ICU_ROOT`` may also be used; the
  51. ICU_ROOT variable takes precedence.
  52. The following cache variables may also be set::
  53. ICU_<P>_EXECUTABLE - the path to executable <P>
  54. ICU_INCLUDE_DIR - the directory containing the ICU headers
  55. ICU_<C>_LIBRARY - the library for component <C>
  56. .. note::
  57. In most cases none of the above variables will require setting,
  58. unless multiple ICU versions are available and a specific version
  59. is required.
  60. Other variables one may set to control this module are::
  61. ICU_DEBUG - Set to ON to enable debug output from FindICU.
  62. #]=======================================================================]
  63. # Written by Roger Leigh <rleigh@codelibre.net>
  64. set(icu_programs
  65. gencnval
  66. icuinfo
  67. genbrk
  68. icu-config
  69. genrb
  70. gendict
  71. derb
  72. pkgdata
  73. uconv
  74. gencfu
  75. makeconv
  76. gennorm2
  77. genccode
  78. gensprep
  79. icupkg
  80. gencmn)
  81. set(icu_data
  82. Makefile.inc
  83. pkgdata.inc)
  84. # The ICU checks are contained in a function due to the large number
  85. # of temporary variables needed.
  86. function(_ICU_FIND)
  87. # Set up search paths, taking compiler into account. Search ICU_ROOT,
  88. # with ICU_ROOT in the environment as a fallback if unset.
  89. if(ICU_ROOT)
  90. list(APPEND icu_roots "${ICU_ROOT}")
  91. else()
  92. if(NOT "$ENV{ICU_ROOT}" STREQUAL "")
  93. file(TO_CMAKE_PATH "$ENV{ICU_ROOT}" NATIVE_PATH)
  94. list(APPEND icu_roots "${NATIVE_PATH}")
  95. set(ICU_ROOT "${NATIVE_PATH}"
  96. CACHE PATH "Location of the ICU installation" FORCE)
  97. endif()
  98. endif()
  99. # Find include directory
  100. list(APPEND icu_include_suffixes "include")
  101. find_path(ICU_INCLUDE_DIR
  102. NAMES "unicode/utypes.h"
  103. HINTS ${icu_roots}
  104. PATH_SUFFIXES ${icu_include_suffixes}
  105. DOC "ICU include directory")
  106. set(ICU_INCLUDE_DIR "${ICU_INCLUDE_DIR}" PARENT_SCOPE)
  107. # Get version
  108. if(ICU_INCLUDE_DIR AND EXISTS "${ICU_INCLUDE_DIR}/unicode/uvernum.h")
  109. file(STRINGS "${ICU_INCLUDE_DIR}/unicode/uvernum.h" icu_header_str
  110. REGEX "^#define[\t ]+U_ICU_VERSION[\t ]+\".*\".*")
  111. string(REGEX REPLACE "^#define[\t ]+U_ICU_VERSION[\t ]+\"([^ \\n]*)\".*"
  112. "\\1" icu_version_string "${icu_header_str}")
  113. set(ICU_VERSION "${icu_version_string}")
  114. set(ICU_VERSION "${icu_version_string}" PARENT_SCOPE)
  115. unset(icu_header_str)
  116. unset(icu_version_string)
  117. endif()
  118. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  119. # 64-bit binary directory
  120. set(_bin64 "bin64")
  121. # 64-bit library directory
  122. set(_lib64 "lib64")
  123. endif()
  124. # Find all ICU programs
  125. list(APPEND icu_binary_suffixes "${_bin64}" "bin" "sbin")
  126. foreach(program ${icu_programs})
  127. string(TOUPPER "${program}" program_upcase)
  128. set(cache_var "ICU_${program_upcase}_EXECUTABLE")
  129. set(program_var "ICU_${program_upcase}_EXECUTABLE")
  130. find_program("${cache_var}"
  131. NAMES "${program}"
  132. HINTS ${icu_roots}
  133. PATH_SUFFIXES ${icu_binary_suffixes}
  134. DOC "ICU ${program} executable"
  135. NO_PACKAGE_ROOT_PATH
  136. )
  137. mark_as_advanced(cache_var)
  138. set("${program_var}" "${${cache_var}}" PARENT_SCOPE)
  139. endforeach()
  140. # Find all ICU libraries
  141. list(APPEND icu_library_suffixes "${_lib64}" "lib")
  142. set(ICU_REQUIRED_LIBS_FOUND ON)
  143. set(static_prefix )
  144. # static icu libraries compiled with MSVC have the prefix 's'
  145. if(MSVC)
  146. set(static_prefix "s")
  147. endif()
  148. foreach(component ${ICU_FIND_COMPONENTS})
  149. string(TOUPPER "${component}" component_upcase)
  150. set(component_cache "ICU_${component_upcase}_LIBRARY")
  151. set(component_cache_release "${component_cache}_RELEASE")
  152. set(component_cache_debug "${component_cache}_DEBUG")
  153. set(component_found "${component_upcase}_FOUND")
  154. set(component_libnames "icu${component}")
  155. set(component_debug_libnames "icu${component}d")
  156. # Special case deliberate library naming mismatches between Unix
  157. # and Windows builds
  158. unset(component_libnames)
  159. unset(component_debug_libnames)
  160. list(APPEND component_libnames "icu${component}")
  161. list(APPEND component_debug_libnames "icu${component}d")
  162. if(component STREQUAL "data")
  163. list(APPEND component_libnames "icudt")
  164. # Note there is no debug variant at present
  165. list(APPEND component_debug_libnames "icudtd")
  166. endif()
  167. if(component STREQUAL "dt")
  168. list(APPEND component_libnames "icudata")
  169. # Note there is no debug variant at present
  170. list(APPEND component_debug_libnames "icudatad")
  171. endif()
  172. if(component STREQUAL "i18n")
  173. list(APPEND component_libnames "icuin")
  174. list(APPEND component_debug_libnames "icuind")
  175. endif()
  176. if(component STREQUAL "in")
  177. list(APPEND component_libnames "icui18n")
  178. list(APPEND component_debug_libnames "icui18nd")
  179. endif()
  180. if(static_prefix)
  181. unset(static_component_libnames)
  182. unset(static_component_debug_libnames)
  183. foreach(component_libname ${component_libnames})
  184. list(APPEND static_component_libnames
  185. ${static_prefix}${component_libname})
  186. endforeach()
  187. foreach(component_libname ${component_debug_libnames})
  188. list(APPEND static_component_debug_libnames
  189. ${static_prefix}${component_libname})
  190. endforeach()
  191. list(APPEND component_libnames ${static_component_libnames})
  192. list(APPEND component_debug_libnames ${static_component_debug_libnames})
  193. endif()
  194. find_library("${component_cache_release}"
  195. NAMES ${component_libnames}
  196. HINTS ${icu_roots}
  197. PATH_SUFFIXES ${icu_library_suffixes}
  198. DOC "ICU ${component} library (release)"
  199. NO_PACKAGE_ROOT_PATH
  200. )
  201. find_library("${component_cache_debug}"
  202. NAMES ${component_debug_libnames}
  203. HINTS ${icu_roots}
  204. PATH_SUFFIXES ${icu_library_suffixes}
  205. DOC "ICU ${component} library (debug)"
  206. NO_PACKAGE_ROOT_PATH
  207. )
  208. include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
  209. select_library_configurations(ICU_${component_upcase})
  210. mark_as_advanced("${component_cache_release}" "${component_cache_debug}")
  211. if(${component_cache})
  212. set("${component_found}" ON)
  213. list(APPEND ICU_LIBRARY "${${component_cache}}")
  214. endif()
  215. mark_as_advanced("${component_found}")
  216. set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
  217. set("${component_found}" "${${component_found}}" PARENT_SCOPE)
  218. if(${component_found})
  219. if (ICU_FIND_REQUIRED_${component})
  220. list(APPEND ICU_LIBS_FOUND "${component} (required)")
  221. else()
  222. list(APPEND ICU_LIBS_FOUND "${component} (optional)")
  223. endif()
  224. else()
  225. if (ICU_FIND_REQUIRED_${component})
  226. set(ICU_REQUIRED_LIBS_FOUND OFF)
  227. list(APPEND ICU_LIBS_NOTFOUND "${component} (required)")
  228. else()
  229. list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)")
  230. endif()
  231. endif()
  232. endforeach()
  233. set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE)
  234. set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE)
  235. # Find all ICU data files
  236. if(CMAKE_LIBRARY_ARCHITECTURE)
  237. list(APPEND icu_data_suffixes
  238. "${_lib64}/${CMAKE_LIBRARY_ARCHITECTURE}/icu/${ICU_VERSION}"
  239. "lib/${CMAKE_LIBRARY_ARCHITECTURE}/icu/${ICU_VERSION}"
  240. "${_lib64}/${CMAKE_LIBRARY_ARCHITECTURE}/icu"
  241. "lib/${CMAKE_LIBRARY_ARCHITECTURE}/icu")
  242. endif()
  243. list(APPEND icu_data_suffixes
  244. "${_lib64}/icu/${ICU_VERSION}"
  245. "lib/icu/${ICU_VERSION}"
  246. "${_lib64}/icu"
  247. "lib/icu")
  248. foreach(data ${icu_data})
  249. string(TOUPPER "${data}" data_upcase)
  250. string(REPLACE "." "_" data_upcase "${data_upcase}")
  251. set(cache_var "ICU_${data_upcase}")
  252. set(data_var "ICU_${data_upcase}")
  253. find_file("${cache_var}"
  254. NAMES "${data}"
  255. HINTS ${icu_roots}
  256. PATH_SUFFIXES ${icu_data_suffixes}
  257. DOC "ICU ${data} data file")
  258. mark_as_advanced(cache_var)
  259. set("${data_var}" "${${cache_var}}" PARENT_SCOPE)
  260. endforeach()
  261. if(NOT ICU_FIND_QUIETLY)
  262. if(ICU_LIBS_FOUND)
  263. message(STATUS "Found the following ICU libraries:")
  264. foreach(found ${ICU_LIBS_FOUND})
  265. message(STATUS " ${found}")
  266. endforeach()
  267. endif()
  268. if(ICU_LIBS_NOTFOUND)
  269. message(STATUS "The following ICU libraries were not found:")
  270. foreach(notfound ${ICU_LIBS_NOTFOUND})
  271. message(STATUS " ${notfound}")
  272. endforeach()
  273. endif()
  274. endif()
  275. if(ICU_DEBUG)
  276. message(STATUS "--------FindICU.cmake search debug--------")
  277. message(STATUS "ICU binary path search order: ${icu_roots}")
  278. message(STATUS "ICU include path search order: ${icu_roots}")
  279. message(STATUS "ICU library path search order: ${icu_roots}")
  280. message(STATUS "----------------")
  281. endif()
  282. endfunction()
  283. _ICU_FIND()
  284. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
  285. FIND_PACKAGE_HANDLE_STANDARD_ARGS(ICU
  286. FOUND_VAR ICU_FOUND
  287. REQUIRED_VARS ICU_INCLUDE_DIR
  288. ICU_LIBRARY
  289. _ICU_REQUIRED_LIBS_FOUND
  290. VERSION_VAR ICU_VERSION
  291. FAIL_MESSAGE "Failed to find all ICU components")
  292. unset(_ICU_REQUIRED_LIBS_FOUND)
  293. if(ICU_FOUND)
  294. set(ICU_INCLUDE_DIRS "${ICU_INCLUDE_DIR}")
  295. set(ICU_LIBRARIES "${ICU_LIBRARY}")
  296. foreach(_ICU_component ${ICU_FIND_COMPONENTS})
  297. string(TOUPPER "${_ICU_component}" _ICU_component_upcase)
  298. set(_ICU_component_cache "ICU_${_ICU_component_upcase}_LIBRARY")
  299. set(_ICU_component_cache_release "ICU_${_ICU_component_upcase}_LIBRARY_RELEASE")
  300. set(_ICU_component_cache_debug "ICU_${_ICU_component_upcase}_LIBRARY_DEBUG")
  301. set(_ICU_component_lib "ICU_${_ICU_component_upcase}_LIBRARIES")
  302. set(_ICU_component_found "${_ICU_component_upcase}_FOUND")
  303. set(_ICU_imported_target "ICU::${_ICU_component}")
  304. if(${_ICU_component_found})
  305. set("${_ICU_component_lib}" "${${_ICU_component_cache}}")
  306. if(NOT TARGET ${_ICU_imported_target})
  307. add_library(${_ICU_imported_target} UNKNOWN IMPORTED)
  308. if(ICU_INCLUDE_DIR)
  309. set_target_properties(${_ICU_imported_target} PROPERTIES
  310. INTERFACE_INCLUDE_DIRECTORIES "${ICU_INCLUDE_DIR}")
  311. endif()
  312. if(EXISTS "${${_ICU_component_cache}}")
  313. set_target_properties(${_ICU_imported_target} PROPERTIES
  314. IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
  315. IMPORTED_LOCATION "${${_ICU_component_cache}}")
  316. endif()
  317. if(EXISTS "${${_ICU_component_cache_release}}")
  318. set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY
  319. IMPORTED_CONFIGURATIONS RELEASE)
  320. set_target_properties(${_ICU_imported_target} PROPERTIES
  321. IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  322. IMPORTED_LOCATION_RELEASE "${${_ICU_component_cache_release}}")
  323. endif()
  324. if(EXISTS "${${_ICU_component_cache_debug}}")
  325. set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY
  326. IMPORTED_CONFIGURATIONS DEBUG)
  327. set_target_properties(${_ICU_imported_target} PROPERTIES
  328. IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
  329. IMPORTED_LOCATION_DEBUG "${${_ICU_component_cache_debug}}")
  330. endif()
  331. if(CMAKE_DL_LIBS AND _ICU_component STREQUAL "uc")
  332. set_target_properties(${_ICU_imported_target} PROPERTIES
  333. INTERFACE_LINK_LIBRARIES "${CMAKE_DL_LIBS}")
  334. endif()
  335. endif()
  336. endif()
  337. unset(_ICU_component_upcase)
  338. unset(_ICU_component_cache)
  339. unset(_ICU_component_lib)
  340. unset(_ICU_component_found)
  341. unset(_ICU_imported_target)
  342. endforeach()
  343. endif()
  344. if(ICU_DEBUG)
  345. message(STATUS "--------FindICU.cmake results debug--------")
  346. message(STATUS "ICU found: ${ICU_FOUND}")
  347. message(STATUS "ICU_VERSION number: ${ICU_VERSION}")
  348. message(STATUS "ICU_ROOT directory: ${ICU_ROOT}")
  349. message(STATUS "ICU_INCLUDE_DIR directory: ${ICU_INCLUDE_DIR}")
  350. message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}")
  351. foreach(program IN LISTS icu_programs)
  352. string(TOUPPER "${program}" program_upcase)
  353. set(program_lib "ICU_${program_upcase}_EXECUTABLE")
  354. message(STATUS "${program} program: ${${program_lib}}")
  355. unset(program_upcase)
  356. unset(program_lib)
  357. endforeach()
  358. foreach(data IN LISTS icu_data)
  359. string(TOUPPER "${data}" data_upcase)
  360. string(REPLACE "." "_" data_upcase "${data_upcase}")
  361. set(data_lib "ICU_${data_upcase}")
  362. message(STATUS "${data} data: ${${data_lib}}")
  363. unset(data_upcase)
  364. unset(data_lib)
  365. endforeach()
  366. foreach(component IN LISTS ICU_FIND_COMPONENTS)
  367. string(TOUPPER "${component}" component_upcase)
  368. set(component_lib "ICU_${component_upcase}_LIBRARIES")
  369. set(component_found "${component_upcase}_FOUND")
  370. message(STATUS "${component} library found: ${${component_found}}")
  371. message(STATUS "${component} library: ${${component_lib}}")
  372. unset(component_upcase)
  373. unset(component_lib)
  374. unset(component_found)
  375. endforeach()
  376. message(STATUS "----------------")
  377. endif()
  378. unset(icu_programs)