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