Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Modules / FindICU.cmake
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:
5 FindICU
6 -------
7
8 .. versionadded:: 3.7
9
10 Find the International Components for Unicode (ICU) libraries and
11 programs.
12
13 This module supports multiple components.
14 Components can include any of: ``data``, ``i18n``, ``io``, ``le``,
15 ``lx``, ``test``, ``tu`` and ``uc``.
16
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.
20
21 .. versionadded:: 3.11
22   Added support for static libraries on Windows.
23
24 This module reports information about the ICU installation in
25 several 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
32 Imported targets::
33
34   ICU::<C>
35
36 Where ``<C>`` is the name of an ICU component, for example
37 ``ICU::i18n``; ``<C>`` is lower-case.
38
39 ICU 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
58 ICU 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
63 ICU datafiles are reported in::
64
65   ICU_MAKEFILE_INC - Makefile.inc
66   ICU_PKGDATA_INC - pkgdata.inc
67
68 This module reads hints about search results from::
69
70   ICU_ROOT - the root of the ICU installation
71
72 The environment variable ``ICU_ROOT`` may also be used; the
73 ICU_ROOT variable takes precedence.
74
75 The 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
87 Other 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 <rleigh@codelibre.net>
93
94 set(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
112 set(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.
118 function(_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       if (ICU_FIND_REQUIRED_${component})
258         list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}")
259       else()
260         list(APPEND ICU_LIBS_FOUND "${component} (optional): ${${component_cache}}")
261       endif()
262     else()
263       if (ICU_FIND_REQUIRED_${component})
264         set(ICU_REQUIRED_LIBS_FOUND OFF)
265         list(APPEND ICU_LIBS_NOTFOUND "${component} (required)")
266       else()
267         list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)")
268       endif()
269     endif()
270     mark_as_advanced("${component_found}")
271     mark_as_advanced("${component_found_compat}")
272     set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
273     set("${component_found}" "${${component_found}}" PARENT_SCOPE)
274     set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
275   endforeach()
276   set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE)
277   set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE)
278
279   # Find all ICU data files
280   if(CMAKE_LIBRARY_ARCHITECTURE)
281     list(APPEND icu_data_suffixes
282       "${_lib64}/${CMAKE_LIBRARY_ARCHITECTURE}/icu/${ICU_VERSION}"
283       "lib/${CMAKE_LIBRARY_ARCHITECTURE}/icu/${ICU_VERSION}"
284       "${_lib64}/${CMAKE_LIBRARY_ARCHITECTURE}/icu"
285       "lib/${CMAKE_LIBRARY_ARCHITECTURE}/icu")
286   endif()
287   list(APPEND icu_data_suffixes
288     "${_lib64}/icu/${ICU_VERSION}"
289     "lib/icu/${ICU_VERSION}"
290     "${_lib64}/icu"
291     "lib/icu")
292   foreach(data ${icu_data})
293     string(TOUPPER "${data}" data_upcase)
294     string(REPLACE "." "_" data_upcase "${data_upcase}")
295     set(cache_var "ICU_${data_upcase}")
296     set(data_var "ICU_${data_upcase}")
297     find_file("${cache_var}"
298       NAMES "${data}"
299       HINTS ${icu_roots}
300       PATH_SUFFIXES ${icu_data_suffixes}
301       DOC "ICU ${data} data file")
302     mark_as_advanced("${cache_var}")
303     set("${data_var}" "${${cache_var}}" PARENT_SCOPE)
304   endforeach()
305
306   if(NOT ICU_FIND_QUIETLY)
307     if(ICU_LIBS_FOUND)
308       message(STATUS "Found the following ICU libraries:")
309       foreach(found ${ICU_LIBS_FOUND})
310         message(STATUS "  ${found}")
311       endforeach()
312     endif()
313     if(ICU_LIBS_NOTFOUND)
314       message(STATUS "The following ICU libraries were not found:")
315       foreach(notfound ${ICU_LIBS_NOTFOUND})
316         message(STATUS "  ${notfound}")
317       endforeach()
318     endif()
319   endif()
320
321   if(ICU_DEBUG)
322     message(STATUS "--------FindICU.cmake search debug--------")
323     message(STATUS "ICU binary path search order: ${icu_roots}")
324     message(STATUS "ICU include path search order: ${icu_roots}")
325     message(STATUS "ICU library path search order: ${icu_roots}")
326     message(STATUS "----------------")
327   endif()
328 endfunction()
329
330 _ICU_FIND()
331
332 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
333 FIND_PACKAGE_HANDLE_STANDARD_ARGS(ICU
334                                   FOUND_VAR ICU_FOUND
335                                   REQUIRED_VARS ICU_INCLUDE_DIR
336                                                 ICU_LIBRARY
337                                                 _ICU_REQUIRED_LIBS_FOUND
338                                   VERSION_VAR ICU_VERSION
339                                   FAIL_MESSAGE "Failed to find all ICU components")
340
341 unset(_ICU_REQUIRED_LIBS_FOUND)
342
343 if(ICU_FOUND)
344   set(ICU_INCLUDE_DIRS "${ICU_INCLUDE_DIR}")
345   set(ICU_LIBRARIES "${ICU_LIBRARY}")
346   foreach(_ICU_component ${ICU_FIND_COMPONENTS})
347     string(TOUPPER "${_ICU_component}" _ICU_component_upcase)
348     set(_ICU_component_cache "ICU_${_ICU_component_upcase}_LIBRARY")
349     set(_ICU_component_cache_release "ICU_${_ICU_component_upcase}_LIBRARY_RELEASE")
350     set(_ICU_component_cache_debug "ICU_${_ICU_component_upcase}_LIBRARY_DEBUG")
351     set(_ICU_component_lib "ICU_${_ICU_component_upcase}_LIBRARIES")
352     set(_ICU_component_found "ICU_${_ICU_component_upcase}_FOUND")
353     set(_ICU_imported_target "ICU::${_ICU_component}")
354     if(${_ICU_component_found})
355       set("${_ICU_component_lib}" "${${_ICU_component_cache}}")
356       if(NOT TARGET ${_ICU_imported_target})
357         add_library(${_ICU_imported_target} UNKNOWN IMPORTED)
358         if(ICU_INCLUDE_DIR)
359           set_target_properties(${_ICU_imported_target} PROPERTIES
360             INTERFACE_INCLUDE_DIRECTORIES "${ICU_INCLUDE_DIR}")
361         endif()
362         if(EXISTS "${${_ICU_component_cache}}")
363           set_target_properties(${_ICU_imported_target} PROPERTIES
364             IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
365             IMPORTED_LOCATION "${${_ICU_component_cache}}")
366         endif()
367         if(EXISTS "${${_ICU_component_cache_release}}")
368           set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY
369             IMPORTED_CONFIGURATIONS RELEASE)
370           set_target_properties(${_ICU_imported_target} PROPERTIES
371             IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
372             IMPORTED_LOCATION_RELEASE "${${_ICU_component_cache_release}}")
373         endif()
374         if(EXISTS "${${_ICU_component_cache_debug}}")
375           set_property(TARGET ${_ICU_imported_target} APPEND PROPERTY
376             IMPORTED_CONFIGURATIONS DEBUG)
377           set_target_properties(${_ICU_imported_target} PROPERTIES
378             IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
379             IMPORTED_LOCATION_DEBUG "${${_ICU_component_cache_debug}}")
380         endif()
381         if(CMAKE_DL_LIBS AND _ICU_component STREQUAL "uc")
382           set_target_properties(${_ICU_imported_target} PROPERTIES
383             INTERFACE_LINK_LIBRARIES "${CMAKE_DL_LIBS}")
384         endif()
385       endif()
386     endif()
387     unset(_ICU_component_upcase)
388     unset(_ICU_component_cache)
389     unset(_ICU_component_lib)
390     unset(_ICU_component_found)
391     unset(_ICU_imported_target)
392   endforeach()
393 endif()
394
395 if(ICU_DEBUG)
396   message(STATUS "--------FindICU.cmake results debug--------")
397   message(STATUS "ICU found: ${ICU_FOUND}")
398   message(STATUS "ICU_VERSION number: ${ICU_VERSION}")
399   message(STATUS "ICU_ROOT directory: ${ICU_ROOT}")
400   message(STATUS "ICU_INCLUDE_DIR directory: ${ICU_INCLUDE_DIR}")
401   message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}")
402
403   foreach(program IN LISTS icu_programs)
404     string(TOUPPER "${program}" program_upcase)
405     set(program_lib "ICU_${program_upcase}_EXECUTABLE")
406     message(STATUS "${program} program: ${program_lib}=${${program_lib}}")
407     unset(program_upcase)
408     unset(program_lib)
409   endforeach()
410
411   foreach(data IN LISTS icu_data)
412     string(TOUPPER "${data}" data_upcase)
413     string(REPLACE "." "_" data_upcase "${data_upcase}")
414     set(data_lib "ICU_${data_upcase}")
415     message(STATUS "${data} data: ${data_lib}=${${data_lib}}")
416     unset(data_upcase)
417     unset(data_lib)
418   endforeach()
419
420   foreach(component IN LISTS ICU_FIND_COMPONENTS)
421     string(TOUPPER "${component}" component_upcase)
422     set(component_lib "ICU_${component_upcase}_LIBRARIES")
423     set(component_found "ICU_${component_upcase}_FOUND")
424     set(component_found_compat "${component_upcase}_FOUND")
425     message(STATUS "${component} library found: ${component_found}=${${component_found}}")
426     message(STATUS "${component} library found (compat name): ${component_found_compat}=${${component_found_compat}}")
427     message(STATUS "${component} library: ${component_lib}=${${component_lib}}")
428     unset(component_upcase)
429     unset(component_lib)
430     unset(component_found)
431     unset(component_found_compat)
432   endforeach()
433   message(STATUS "----------------")
434 endif()
435
436 unset(icu_programs)