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:
5FindIntl
6--------
7
8.. versionadded:: 3.2
9
10Find the Gettext libintl headers and libraries.
11
12This module reports information about the Gettext libintl
13installation in several variables.
14
15.. variable:: Intl_FOUND
16
17  True if libintl is found.
18
19.. variable:: Intl_INCLUDE_DIRS
20
21  The directory containing the libintl headers.
22
23.. variable:: Intl_LIBRARIES
24
25  The intl libraries to be linked.
26
27.. variable:: Intl_VERSION
28
29  .. versionadded:: 3.21
30
31  The version of intl found (x.y.z)
32
33.. variable:: Intl_VERSION_MAJOR
34
35  .. versionadded:: 3.21
36
37  The major version of intl
38
39.. variable:: Intl_VERSION_MINOR
40
41  .. versionadded:: 3.21
42
43  The minor version of intl
44
45.. variable:: Intl_VERSION_PATCH
46
47  .. versionadded:: 3.21
48
49  The patch version of intl
50
51.. versionadded:: 3.20
52  This module defines :prop_tgt:`IMPORTED` target ``Intl::Intl``.
53
54The following cache variables may also be set:
55
56.. variable:: Intl_INCLUDE_DIR
57
58  The directory containing the libintl headers
59
60.. variable:: Intl_LIBRARY
61
62  The libintl library (if any)
63
64.. variable:: Intl_IS_BUILT_IN
65
66  .. versionadded:: 3.20
67
68  whether ``intl`` is a part of the C library.
69
70.. note::
71  On some platforms, such as Linux with GNU libc, the gettext
72  functions are present in the C standard library and libintl
73  is not required.  ``Intl_LIBRARIES`` will be empty in this
74  case.
75
76.. note::
77  Some libintl implementations don't embed the version number in their header files.
78  In this case the variables ``Intl_VERSION*`` will be empty.
79
80.. note::
81  If you wish to use the Gettext tools (``msgmerge``,
82  ``msgfmt``, etc.), use :module:`FindGettext`.
83#]=======================================================================]
84
85include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
86if(CMAKE_C_COMPILER_LOADED)
87  include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake)
88elseif(CMAKE_CXX_COMPILER_LOADED)
89  include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake)
90else()
91  # If neither C nor CXX are loaded, implicit intl makes no sense.
92  set(Intl_IS_BUILT_IN FALSE)
93endif()
94
95# Check if Intl is built in to the C library.
96if(NOT DEFINED Intl_IS_BUILT_IN)
97  if(NOT DEFINED Intl_INCLUDE_DIR AND NOT DEFINED Intl_LIBRARY)
98    cmake_push_check_state(RESET)
99    set(CMAKE_REQUIRED_QUIET TRUE)
100    set(Intl_IMPLICIT_TEST_CODE [[
101#include <libintl.h>
102int main(void) {
103  gettext("");
104  dgettext("", "");
105  dcgettext("", "", 0);
106  return 0;
107}
108]])
109    if(CMAKE_C_COMPILER_LOADED)
110      check_c_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN)
111    else()
112      check_cxx_source_compiles("${Intl_IMPLICIT_TEST_CODE}" Intl_IS_BUILT_IN)
113    endif()
114    cmake_pop_check_state()
115  else()
116    set(Intl_IS_BUILT_IN FALSE)
117  endif()
118endif()
119
120set(_Intl_REQUIRED_VARS)
121if(Intl_IS_BUILT_IN)
122  set(_Intl_REQUIRED_VARS _Intl_IS_BUILT_IN_MSG)
123  set(_Intl_IS_BUILT_IN_MSG "built in to C library")
124else()
125  set(_Intl_REQUIRED_VARS Intl_LIBRARY Intl_INCLUDE_DIR)
126
127  find_path(Intl_INCLUDE_DIR
128            NAMES "libintl.h"
129            DOC "libintl include directory")
130  mark_as_advanced(Intl_INCLUDE_DIR)
131
132  find_library(Intl_LIBRARY
133    NAMES "intl" "libintl"
134    NAMES_PER_DIR
135    DOC "libintl libraries (if not in the C library)")
136  mark_as_advanced(Intl_LIBRARY)
137endif()
138
139# NOTE: glibc's libintl.h does not define LIBINTL_VERSION
140if(Intl_INCLUDE_DIR AND EXISTS "${Intl_INCLUDE_DIR}/libintl.h")
141  file(STRINGS ${Intl_INCLUDE_DIR}/libintl.h Intl_VERSION_DEFINE REGEX "LIBINTL_VERSION (.*)")
142
143  if(Intl_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)")
144    set(Intl_VERSION_NUMBER "${CMAKE_MATCH_1}")
145    # encoding -> version number: (major<<16) + (minor<<8) + patch
146    math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_NUMBER} >> 16" OUTPUT_FORMAT HEXADECIMAL)
147    math(EXPR Intl_VERSION_MINOR "(${Intl_VERSION_NUMBER} - (${Intl_VERSION_MAJOR} << 16)) >> 8" OUTPUT_FORMAT HEXADECIMAL)
148    math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_NUMBER} - ((${Intl_VERSION_MAJOR} << 16) + (${Intl_VERSION_MINOR} << 8))" OUTPUT_FORMAT HEXADECIMAL)
149
150    math(EXPR Intl_VERSION_MAJOR "${Intl_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL)
151    math(EXPR Intl_VERSION_MINOR "${Intl_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL)
152    math(EXPR Intl_VERSION_PATCH "${Intl_VERSION_PATCH}" OUTPUT_FORMAT DECIMAL)
153    set(Intl_VERSION "${Intl_VERSION_MAJOR}.${Intl_VERSION_MINOR}.${Intl_VERSION_PATCH}")
154  endif()
155
156  unset(Intl_VERSION_DEFINE)
157  unset(Intl_VERSION_NUMBER)
158endif()
159
160include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
161FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
162                                  FOUND_VAR Intl_FOUND
163                                  REQUIRED_VARS ${_Intl_REQUIRED_VARS}
164                                  VERSION_VAR Intl_VERSION
165                                  FAIL_MESSAGE "Failed to find Gettext libintl")
166unset(_Intl_REQUIRED_VARS)
167unset(_Intl_IS_BUILT_IN_MSG)
168
169if(Intl_FOUND)
170  if(Intl_IS_BUILT_IN)
171    set(Intl_INCLUDE_DIRS "")
172    set(Intl_LIBRARIES "")
173  else()
174    set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}")
175    set(Intl_LIBRARIES "${Intl_LIBRARY}")
176  endif()
177  if(NOT TARGET Intl::Intl)
178    add_library(Intl::Intl INTERFACE IMPORTED)
179    set_target_properties(Intl::Intl PROPERTIES
180      INTERFACE_INCLUDE_DIRECTORIES "${Intl_INCLUDE_DIRS}"
181      INTERFACE_LINK_LIBRARIES "${Intl_LIBRARIES}")
182  endif()
183endif()
184