FindIconv.cmake 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. FindIconv
  5. ---------
  6. .. versionadded:: 3.11
  7. This module finds the ``iconv()`` POSIX.1 functions on the system.
  8. These functions might be provided in the regular C library or externally
  9. in the form of an additional library.
  10. The following variables are provided to indicate iconv support:
  11. .. variable:: Iconv_FOUND
  12. Variable indicating if the iconv support was found.
  13. .. variable:: Iconv_INCLUDE_DIRS
  14. The directories containing the iconv headers.
  15. .. variable:: Iconv_LIBRARIES
  16. The iconv libraries to be linked.
  17. .. variable:: Iconv_VERSION
  18. .. versionadded:: 3.21
  19. The version of iconv found (x.y)
  20. .. variable:: Iconv_VERSION_MAJOR
  21. .. versionadded:: 3.21
  22. The major version of iconv
  23. .. variable:: Iconv_VERSION_MINOR
  24. .. versionadded:: 3.21
  25. The minor version of iconv
  26. .. variable:: Iconv_IS_BUILT_IN
  27. A variable indicating whether iconv support is stemming from the
  28. C library or not. Even if the C library provides `iconv()`, the presence of
  29. an external `libiconv` implementation might lead to this being false.
  30. Additionally, the following :prop_tgt:`IMPORTED` target is being provided:
  31. .. variable:: Iconv::Iconv
  32. Imported target for using iconv.
  33. The following cache variables may also be set:
  34. .. variable:: Iconv_INCLUDE_DIR
  35. The directory containing the iconv headers.
  36. .. variable:: Iconv_LIBRARY
  37. The iconv library (if not implicitly given in the C library).
  38. .. note::
  39. On POSIX platforms, iconv might be part of the C library and the cache
  40. variables ``Iconv_INCLUDE_DIR`` and ``Iconv_LIBRARY`` might be empty.
  41. .. note::
  42. Some libiconv implementations don't embed the version number in their header files.
  43. In this case the variables ``Iconv_VERSION*`` will be empty.
  44. #]=======================================================================]
  45. cmake_policy(PUSH)
  46. cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
  47. include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
  48. if(CMAKE_C_COMPILER_LOADED)
  49. include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake)
  50. elseif(CMAKE_CXX_COMPILER_LOADED)
  51. include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake)
  52. else()
  53. # If neither C nor CXX are loaded, implicit iconv makes no sense.
  54. set(Iconv_IS_BUILT_IN FALSE)
  55. endif()
  56. # iconv can only be provided in libc on a POSIX system.
  57. # If any cache variable is already set, we'll skip this test.
  58. if(NOT DEFINED Iconv_IS_BUILT_IN)
  59. if(UNIX AND NOT DEFINED Iconv_INCLUDE_DIR AND NOT DEFINED Iconv_LIBRARY)
  60. cmake_push_check_state(RESET)
  61. # We always suppress the message here: Otherwise on supported systems
  62. # not having iconv in their C library (e.g. those using libiconv)
  63. # would always display a confusing "Looking for iconv - not found" message
  64. set(CMAKE_FIND_QUIETLY TRUE)
  65. # The following code will not work, but it's sufficient to see if it compiles.
  66. # Note: libiconv will define the iconv functions as macros, so CheckSymbolExists
  67. # will not yield correct results.
  68. set(Iconv_IMPLICIT_TEST_CODE
  69. "
  70. #include <stddef.h>
  71. #include <iconv.h>
  72. int main(void) {
  73. char *a, *b;
  74. size_t i, j;
  75. iconv_t ic;
  76. ic = iconv_open(\"to\", \"from\");
  77. iconv(ic, &a, &i, &b, &j);
  78. iconv_close(ic);
  79. }
  80. "
  81. )
  82. if(CMAKE_C_COMPILER_LOADED)
  83. check_c_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
  84. else()
  85. check_cxx_source_compiles("${Iconv_IMPLICIT_TEST_CODE}" Iconv_IS_BUILT_IN)
  86. endif()
  87. cmake_pop_check_state()
  88. else()
  89. set(Iconv_IS_BUILT_IN FALSE)
  90. endif()
  91. endif()
  92. set(_Iconv_REQUIRED_VARS)
  93. if(Iconv_IS_BUILT_IN)
  94. set(_Iconv_REQUIRED_VARS _Iconv_IS_BUILT_IN_MSG)
  95. set(_Iconv_IS_BUILT_IN_MSG "built in to C library")
  96. else()
  97. set(_Iconv_REQUIRED_VARS Iconv_LIBRARY Iconv_INCLUDE_DIR)
  98. find_path(Iconv_INCLUDE_DIR
  99. NAMES "iconv.h"
  100. PATH_SUFFIXES
  101. gnu-libiconv # GNU libiconv on Alpine Linux has header in a subdirectory.
  102. DOC "iconv include directory")
  103. set(Iconv_LIBRARY_NAMES "iconv" "libiconv")
  104. mark_as_advanced(Iconv_INCLUDE_DIR)
  105. find_library(Iconv_LIBRARY
  106. NAMES iconv libiconv
  107. NAMES_PER_DIR
  108. DOC "iconv library (if not in the C library)")
  109. mark_as_advanced(Iconv_LIBRARY)
  110. endif()
  111. # NOTE: glibc's iconv.h does not define _LIBICONV_VERSION
  112. if(Iconv_INCLUDE_DIR AND EXISTS "${Iconv_INCLUDE_DIR}/iconv.h")
  113. file(STRINGS ${Iconv_INCLUDE_DIR}/iconv.h Iconv_VERSION_DEFINE REGEX "_LIBICONV_VERSION (.*)")
  114. if(Iconv_VERSION_DEFINE MATCHES "(0x[A-Fa-f0-9]+)")
  115. set(Iconv_VERSION_NUMBER "${CMAKE_MATCH_1}")
  116. # encoding -> version number: (major<<8) + minor
  117. math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_NUMBER} >> 8" OUTPUT_FORMAT HEXADECIMAL)
  118. math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_NUMBER} - (${Iconv_VERSION_MAJOR} << 8)" OUTPUT_FORMAT HEXADECIMAL)
  119. math(EXPR Iconv_VERSION_MAJOR "${Iconv_VERSION_MAJOR}" OUTPUT_FORMAT DECIMAL)
  120. math(EXPR Iconv_VERSION_MINOR "${Iconv_VERSION_MINOR}" OUTPUT_FORMAT DECIMAL)
  121. set(Iconv_VERSION "${Iconv_VERSION_MAJOR}.${Iconv_VERSION_MINOR}")
  122. endif()
  123. unset(Iconv_VERSION_DEFINE)
  124. unset(Iconv_VERSION_NUMBER)
  125. endif()
  126. include(FindPackageHandleStandardArgs)
  127. find_package_handle_standard_args(Iconv
  128. REQUIRED_VARS ${_Iconv_REQUIRED_VARS}
  129. VERSION_VAR Iconv_VERSION)
  130. if(Iconv_FOUND)
  131. if(Iconv_IS_BUILT_IN)
  132. set(Iconv_INCLUDE_DIRS "")
  133. set(Iconv_LIBRARIES "")
  134. else()
  135. set(Iconv_INCLUDE_DIRS "${Iconv_INCLUDE_DIR}")
  136. set(Iconv_LIBRARIES "${Iconv_LIBRARY}")
  137. endif()
  138. if(NOT TARGET Iconv::Iconv)
  139. add_library(Iconv::Iconv INTERFACE IMPORTED)
  140. set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Iconv_INCLUDE_DIRS}")
  141. set_property(TARGET Iconv::Iconv PROPERTY INTERFACE_LINK_LIBRARIES "${Iconv_LIBRARIES}")
  142. endif()
  143. endif()
  144. cmake_policy(POP)