1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
10 Find the International Components for Unicode (ICU) libraries and
13 This module supports multiple components.
14 Components can include any of: ``data``, ``i18n``, ``io``, ``le``,
15 ``lx``, ``test``, ``tu`` and ``uc``.
17 Note that on Windows ``data`` is named ``dt`` and ``i18n`` is named
18 ``in``; any of the names may be used, and the appropriate
19 platform-specific library name will be automatically selected.
21 .. versionadded:: 3.11
22 Added support for static libraries on Windows.
24 This module reports information about the ICU installation in
25 several variables. General variables::
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
36 Where ``<C>`` is the name of an ICU component, for example
37 ``ICU::i18n``; ``<C>`` is lower-case.
39 ICU programs are reported in::
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
58 ICU component libraries are reported in::
60 ICU_<C>_FOUND - ON if component was found; ``<C>`` is upper-case.
61 ICU_<C>_LIBRARIES - libraries for component; ``<C>`` is upper-case.
63 ICU datafiles are reported in::
65 ICU_MAKEFILE_INC - Makefile.inc
66 ICU_PKGDATA_INC - pkgdata.inc
68 This module reads hints about search results from::
70 ICU_ROOT - the root of the ICU installation
72 The environment variable ``ICU_ROOT`` may also be used; the
73 ICU_ROOT variable takes precedence.
75 The following cache variables may also be set::
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.
83 In most cases none of the above variables will require setting,
84 unless multiple ICU versions are available and a specific version
87 Other variables one may set to control this module are::
89 ICU_DEBUG - Set to ON to enable debug output from FindICU.
90 #]=======================================================================]
92 # Written by Roger Leigh <rleigh@codelibre.net>
116 # The ICU checks are contained in a function due to the large number
117 # of temporary variables needed.
119 # Set up search paths, taking compiler into account. Search ICU_ROOT,
120 # with ICU_ROOT in the environment as a fallback if unset.
122 list(APPEND icu_roots "${ICU_ROOT}")
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)
132 # Find include directory
133 list(APPEND icu_include_suffixes "include")
134 find_path(ICU_INCLUDE_DIR
135 NAMES "unicode/utypes.h"
137 PATH_SUFFIXES ${icu_include_suffixes}
138 DOC "ICU include directory")
139 set(ICU_INCLUDE_DIR "${ICU_INCLUDE_DIR}" PARENT_SCOPE)
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 ]+\".*\".*")
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)
154 if(CMAKE_SIZEOF_VOID_P EQUAL 8)
155 # 64-bit binary directory
157 # 64-bit library directory
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}"
171 PATH_SUFFIXES ${icu_binary_suffixes}
172 DOC "ICU ${program} executable"
175 mark_as_advanced("${cache_var}")
176 set("${program_var}" "${${cache_var}}" PARENT_SCOPE)
179 # Find all ICU libraries
180 list(APPEND icu_library_suffixes "${_lib64}" "lib")
181 set(ICU_REQUIRED_LIBS_FOUND ON)
183 # static icu libraries compiled with MSVC have the prefix 's'
185 set(static_prefix "s")
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")
197 # Special case deliberate library naming mismatches between Unix
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")
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")
213 if(component STREQUAL "i18n")
214 list(APPEND component_libnames "icuin")
215 list(APPEND component_debug_libnames "icuind")
217 if(component STREQUAL "in")
218 list(APPEND component_libnames "icui18n")
219 list(APPEND component_debug_libnames "icui18nd")
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})
229 foreach(component_libname ${component_debug_libnames})
230 list(APPEND static_component_debug_libnames
231 ${static_prefix}${component_libname})
233 list(APPEND component_libnames ${static_component_libnames})
234 list(APPEND component_debug_libnames ${static_component_debug_libnames})
236 find_library("${component_cache_release}"
237 NAMES ${component_libnames}
239 PATH_SUFFIXES ${icu_library_suffixes}
240 DOC "ICU ${component} library (release)"
243 find_library("${component_cache_debug}"
244 NAMES ${component_debug_libnames}
246 PATH_SUFFIXES ${icu_library_suffixes}
247 DOC "ICU ${component} library (debug)"
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}}")
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): ${${component_cache}}")
267 list(APPEND ICU_LIBS_FOUND "${component} (optional): ${${component_cache}}")
270 if (ICU_FIND_REQUIRED_${component})
271 set(ICU_REQUIRED_LIBS_FOUND OFF)
272 list(APPEND ICU_LIBS_NOTFOUND "${component} (required)")
274 list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)")
278 set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE)
279 set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE)
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")
289 list(APPEND icu_data_suffixes
290 "${_lib64}/icu/${ICU_VERSION}"
291 "lib/icu/${ICU_VERSION}"
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}"
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)
308 if(NOT ICU_FIND_QUIETLY)
310 message(STATUS "Found the following ICU libraries:")
311 foreach(found ${ICU_LIBS_FOUND})
312 message(STATUS " ${found}")
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}")
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 "----------------")
334 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
335 FIND_PACKAGE_HANDLE_STANDARD_ARGS(ICU
337 REQUIRED_VARS ICU_INCLUDE_DIR
339 _ICU_REQUIRED_LIBS_FOUND
340 VERSION_VAR ICU_VERSION
341 FAIL_MESSAGE "Failed to find all ICU components")
343 unset(_ICU_REQUIRED_LIBS_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)
361 set_target_properties(${_ICU_imported_target} PROPERTIES
362 INTERFACE_INCLUDE_DIRECTORIES "${ICU_INCLUDE_DIR}")
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}}")
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}}")
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}}")
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}")
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)
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}")
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)
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}}")
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)
432 unset(component_found)
433 unset(component_found_compat)
435 message(STATUS "----------------")