FindBrotli.cmake 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. # A simple FindBrotli package for Cmake's find_package function.
  2. # Note: This find package doesn't have version support, as the version file doesn't seem to be installed on most systems.
  3. #
  4. # If you want to find the static packages instead of shared (the default), define BROTLI_USE_STATIC_LIBS as TRUE.
  5. # The targets will have the same names, but it will use the static libs.
  6. #
  7. # Valid find_package COMPONENTS names: "decoder", "encoder", and "common"
  8. #
  9. # Defines the libraries (if found): Brotli::decoder, Brotli::encoder, Brotli::common
  10. # and the includes path variable: Brotli_INCLUDE_DIR
  11. function(brotli_err_msg _err_msg)
  12. # If the package is required, throw a fatal error
  13. # Otherwise, if not running quietly, we throw a warning
  14. if(Brotli_FIND_REQUIRED)
  15. message(FATAL_ERROR "${_err_msg}")
  16. elseif(NOT Brotli_FIND_QUIETLY)
  17. message(WARNING "${_err_msg}")
  18. endif()
  19. endfunction()
  20. # If they asked for a specific version, warn/fail since we don't support it.
  21. if(Brotli_FIND_VERSION)
  22. brotli_err_msg("FindBrotli.cmake doesn't have version support!")
  23. endif()
  24. # Since both decoder & encoder require the common lib (I think), force its requirement..
  25. # if the user is requiring either of those other libs.
  26. if(Brotli_FIND_REQUIRED_decoder OR Brotli_FIND_REQUIRED_encoder)
  27. set(Brotli_FIND_REQUIRED_common TRUE)
  28. endif()
  29. # Make PkgConfig optional, since some users (mainly Windows) don't have it.
  30. # But it's a lot more clean than manually using find_library.
  31. find_package(PkgConfig QUIET)
  32. if(PKG_CONFIG_FOUND)
  33. if(BROTLI_USE_STATIC_LIBS)
  34. # Have to use _STATIC to tell PkgConfig to find the static libs.
  35. pkg_check_modules(Brotli_common_STATIC QUIET IMPORTED_TARGET libbrotlicommon)
  36. pkg_check_modules(Brotli_decoder_STATIC QUIET IMPORTED_TARGET libbrotlidec)
  37. pkg_check_modules(Brotli_encoder_STATIC QUIET IMPORTED_TARGET libbrotlienc)
  38. else()
  39. pkg_check_modules(Brotli_common QUIET IMPORTED_TARGET libbrotlicommon)
  40. pkg_check_modules(Brotli_decoder QUIET IMPORTED_TARGET libbrotlidec)
  41. pkg_check_modules(Brotli_encoder QUIET IMPORTED_TARGET libbrotlienc)
  42. endif()
  43. endif()
  44. # Only used if the PkgConfig libraries aren't used.
  45. find_path(Brotli_INCLUDE_DIR
  46. NAMES "brotli/decode.h" "brotli/encode.h"
  47. PATH_SUFFIXES "include" "includes"
  48. DOC "The path to Brotli's include directory."
  49. )
  50. # Also check if Brotli_decoder was defined, as it can be passed by the end-user
  51. if(NOT TARGET PkgConfig::Brotli_decoder AND NOT Brotli_decoder AND NOT TARGET PkgConfig::Brotli_decoder_STATIC)
  52. if(BROTLI_USE_STATIC_LIBS)
  53. list(APPEND _brotli_decoder_lib_names
  54. "brotlidec-static"
  55. "libbrotlidec-static"
  56. )
  57. else()
  58. list(APPEND _brotli_decoder_lib_names
  59. "brotlidec"
  60. "libbrotlidec"
  61. )
  62. endif()
  63. find_library(Brotli_decoder
  64. NAMES ${_brotli_decoder_lib_names}
  65. PATH_SUFFIXES
  66. "lib"
  67. "lib64"
  68. "libs"
  69. "libs64"
  70. "lib/x86_64-linux-gnu"
  71. )
  72. endif()
  73. # Also check if Brotli_encoder was defined, as it can be passed by the end-user
  74. if(NOT TARGET PkgConfig::Brotli_encoder AND NOT Brotli_encoder AND NOT TARGET PkgConfig::Brotli_encoder_STATIC)
  75. if(BROTLI_USE_STATIC_LIBS)
  76. list(APPEND _brotli_encoder_lib_names
  77. "brotlienc-static"
  78. "libbrotlienc-static"
  79. )
  80. else()
  81. list(APPEND _brotli_encoder_lib_names
  82. "brotlienc"
  83. "libbrotlienc"
  84. )
  85. endif()
  86. find_library(Brotli_encoder
  87. NAMES ${_brotli_encoder_lib_names}
  88. PATH_SUFFIXES
  89. "lib"
  90. "lib64"
  91. "libs"
  92. "libs64"
  93. "lib/x86_64-linux-gnu"
  94. )
  95. endif()
  96. # Also check if Brotli_common was defined, as it can be passed by the end-user
  97. if(NOT TARGET PkgConfig::Brotli_common AND NOT Brotli_common AND NOT TARGET PkgConfig::Brotli_common_STATIC)
  98. if(BROTLI_USE_STATIC_LIBS)
  99. list(APPEND _brotli_common_lib_names
  100. "brotlicommon-static"
  101. "libbrotlicommon-static"
  102. )
  103. else()
  104. list(APPEND _brotli_common_lib_names
  105. "brotlicommon"
  106. "libbrotlicommon"
  107. )
  108. endif()
  109. find_library(Brotli_common
  110. NAMES ${_brotli_common_lib_names}
  111. PATH_SUFFIXES
  112. "lib"
  113. "lib64"
  114. "libs"
  115. "libs64"
  116. "lib/x86_64-linux-gnu"
  117. )
  118. endif()
  119. set(_brotli_req_vars "")
  120. # Generic loop to either create all the aliases for the end-user, or throw errors/warnings.
  121. # Note that the case here needs to match the case we used elsewhere in this file.
  122. foreach(_target_name "common" "decoder" "encoder")
  123. # The PkgConfig IMPORTED_TARGET has PkgConfig:: prefixed to it.
  124. if(TARGET PkgConfig::Brotli_${_target_name} OR TARGET PkgConfig::Brotli_${_target_name}_STATIC)
  125. set(_stat_str "")
  126. if(BROTLI_USE_STATIC_LIBS)
  127. set(_stat_str "_STATIC")
  128. endif()
  129. # Can't use generators for ALIAS targets, so you get this jank
  130. add_library(Brotli::${_target_name} ALIAS PkgConfig::Brotli_${_target_name}${_stat_str})
  131. # The PkgConfig version of the library has a slightly different path to its lib.
  132. if(Brotli_FIND_REQUIRED_${_target_name})
  133. if(BROTLI_USE_STATIC_LIBS)
  134. list(APPEND _brotli_req_vars "Brotli_${_target_name}_STATIC_LIBRARIES")
  135. else()
  136. list(APPEND _brotli_req_vars "Brotli_${_target_name}_LINK_LIBRARIES")
  137. endif()
  138. endif()
  139. # This will only trigger for libraries we found using find_library
  140. elseif(Brotli_${_target_name})
  141. add_library("Brotli::${_target_name}" UNKNOWN IMPORTED)
  142. # Safety-check the includes dir
  143. if(NOT Brotli_INCLUDE_DIR)
  144. brotli_err_msg("Failed to find Brotli's includes directory. Try manually defining \"Brotli_INCLUDE_DIR\" to Brotli's header path on your system.")
  145. endif()
  146. # Attach the literal library and include dir to the IMPORTED target for the end-user
  147. set_target_properties("Brotli::${_target_name}" PROPERTIES
  148. INTERFACE_INCLUDE_DIRECTORIES "${Brotli_INCLUDE_DIR}"
  149. IMPORTED_LOCATION "${Brotli_${_target_name}}"
  150. )
  151. # Attach the library from find_library to our required vars (if it's required)
  152. if(Brotli_FIND_REQUIRED_${_target_name})
  153. list(APPEND _brotli_req_vars "Brotli_${_target_name}")
  154. endif()
  155. # This will only happen if it's a required library but we didn't find it.
  156. elseif(Brotli_FIND_REQUIRED_${_target_name})
  157. # Only bother with an error/failure if they actually required the lib.
  158. brotli_err_msg("Failed to find Brotli's ${_target_name} library. Try manually defining \"Brotli_${_target_name}\" to its path on your system.")
  159. # If the compnent was required but not found, you set XXX_FOUND to false to signify failure to find component(s)
  160. # This is used in find_package_handle_standard_args's HANDLE_COMPONENTS (I think)
  161. set(Brotli_FOUND FALSE)
  162. endif()
  163. endforeach()
  164. include(FindPackageHandleStandardArgs)
  165. find_package_handle_standard_args(Brotli
  166. FOUND_VAR Brotli_FOUND
  167. REQUIRED_VARS ${_brotli_req_vars}
  168. HANDLE_COMPONENTS
  169. )
  170. if(Brotli_FOUND)
  171. include(FindPackageMessage)
  172. foreach(_lib_name ${_brotli_req_vars})
  173. # TODO: remove this if/when The Cmake PkgConfig file fixes the non-quiet message about libbrotlicommon being found.
  174. if(${_lib_name} MATCHES "common")
  175. # This avoids a duplicate "Found Brotli: /usr/lib/libbrotlicommon.so" type message.
  176. continue()
  177. endif()
  178. # Double-expand the var to get the actual path instead of the variable's name.
  179. find_package_message(Brotli "Found Brotli: ${${_lib_name}}"
  180. "[${${_lib_name}}][${Brotli_INCLUDE_DIR}]"
  181. )
  182. endforeach()
  183. endif()