FindFFmpeg.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #[=======================================================================[.rst
  2. FindFFmpeg
  3. ----------
  4. FindModule for FFmpeg and associated libraries
  5. .. versionchanged:: 3.0
  6. Updated FindModule to CMake standards
  7. Components
  8. ^^^^^^^^^^
  9. .. versionadded:: 1.0
  10. This module contains provides several components:
  11. ``avcodec``
  12. ``avdevice``
  13. ``avfilter``
  14. ``avformat``
  15. ``avutil``
  16. ``postproc``
  17. ``swscale``
  18. ``swresample``
  19. Import targets exist for each component.
  20. Imported Targets
  21. ^^^^^^^^^^^^^^^^
  22. .. versionadded:: 2.0
  23. This module defines the :prop_tgt:`IMPORTED` targets:
  24. ``FFmpeg::avcodec``
  25. AVcodec component
  26. ``FFmpeg::avdevice``
  27. AVdevice component
  28. ``FFmpeg::avfilter``
  29. AVfilter component
  30. ``FFmpeg::avformat``
  31. AVformat component
  32. ``FFmpeg::avutil``
  33. AVutil component
  34. ``FFmpeg::postproc``
  35. postproc component
  36. ``FFmpeg::swscale``
  37. SWscale component
  38. ``FFmpeg::swresample``
  39. SWresample component
  40. Result Variables
  41. ^^^^^^^^^^^^^^^^
  42. This module sets the following variables:
  43. ``FFmpeg_FOUND``
  44. True, if all required components and the core library were found.
  45. ``FFmpeg_VERSION``
  46. Detected version of found FFmpeg libraries.
  47. ``FFmpeg_INCLUDE_DIRS``
  48. Include directories needed for FFmpeg.
  49. ``FFmpeg_LIBRARIES``
  50. Libraries needed to link to FFmpeg.
  51. ``FFmpeg_DEFINITIONS``
  52. Compiler flags required for FFmpeg.
  53. ``FFmpeg_<COMPONENT>_VERSION``
  54. Detected version of found FFmpeg component library.
  55. ``FFmpeg_<COMPONENT>_INCLUDE_DIRS``
  56. Include directories needed for FFmpeg component.
  57. ``FFmpeg_<COMPONENT>_LIBRARIES``
  58. Libraries needed to link to FFmpeg component.
  59. ``FFmpeg_<COMPONENT>_DEFINITIONS``
  60. Compiler flags required for FFmpeg component.
  61. Cache variables
  62. ^^^^^^^^^^^^^^^
  63. The following cache variables may also be set:
  64. ``FFmpeg_<COMPONENT>_LIBRARY``
  65. Path to the library component of FFmpeg.
  66. ``FFmpeg_<COMPONENT>_INCLUDE_DIR``
  67. Directory containing ``<COMPONENT>.h``.
  68. #]=======================================================================]
  69. # cmake-format: off
  70. # cmake-lint: disable=C0103
  71. # cmake-lint: disable=C0307
  72. # cmake-format: on
  73. include(FindPackageHandleStandardArgs)
  74. set(_DEFAULT_COMPONENTS
  75. avcodec
  76. avdevice
  77. avformat
  78. avfilter
  79. avresample
  80. avutil
  81. postproc
  82. swscale
  83. swresample)
  84. set(component_avcodec libavcodec avcodec avcodec.h)
  85. set(component_avdevice libavdevice avdevice avdevice.h)
  86. set(component_avformat libavformat avformat avformat.h)
  87. set(component_avfilter libavfilter avfilter avfilter.h)
  88. set(component_avresample libavresample avresample avresample.h)
  89. set(component_avutil libavutil avutil avutil.h)
  90. set(component_postproc libpostproc postproc postprocess.h)
  91. set(component_swscale libswscale swscale swscale.h)
  92. set(component_swresample libswresample swresample swresample.h)
  93. if(NOT FFmpeg_FIND_COMPONENTS)
  94. set(FFmpeg_FIND_COMPONENTS ${_DEFAULT_COMPONENTS})
  95. endif()
  96. # FFmpeg_find_component: Find and set up requested FFmpeg component
  97. macro(FFmpeg_find_component component)
  98. list(GET component_${component} 0 component_libname)
  99. list(GET component_${component} 1 component_name)
  100. list(GET component_${component} 2 component_header)
  101. if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
  102. find_package(PkgConfig QUIET)
  103. if(PKG_CONFIG_FOUND)
  104. pkg_search_module(PC_FFmpeg_${component} QUIET ${component_libname})
  105. endif()
  106. endif()
  107. find_path(
  108. FFmpeg_${component}_INCLUDE_DIR
  109. NAMES ${component_libname}/${component_header} ${component_libname}/version.h
  110. HINTS ${PC_FFmpeg_${component}_INCLUDE_DIRS}
  111. PATHS /usr/include /usr/local/include
  112. DOC "FFmpeg component ${component_name} include directory")
  113. ffmpeg_check_version()
  114. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
  115. find_library(
  116. FFmpeg_${component}_IMPLIB
  117. NAMES ${component_libname} ${component_name}
  118. DOC "FFmpeg component ${component_name} import library location")
  119. ffmpeg_find_dll()
  120. else()
  121. find_library(
  122. FFmpeg_${component}_LIBRARY
  123. NAMES ${component_libname} ${component_name}
  124. HINTS ${PC_FFmpeg_${component}_LIBRARY_DIRS}
  125. PATHS /usr/lib /usr/local/lib
  126. DOC "FFmpeg component ${component_name} location")
  127. endif()
  128. if(FFmpeg_${component}_LIBRARY AND FFmpeg_${component}_INCLUDE_DIR)
  129. set(FFmpeg_${component}_FOUND TRUE)
  130. set(FFmpeg_${component}_LIBRARIES ${${_library_var}})
  131. set(FFmpeg_${component}_INCLUDE_DIRS ${FFmpeg_${component}_INCLUDE_DIR})
  132. set(FFmpeg_${component}_DEFINITIONS ${PC_FFmpeg_${component}_CFLAGS_OTHER})
  133. mark_as_advanced(FFmpeg_${component}_LIBRARY FFmpeg_${component}_INCLUDE_DIR FFmpeg_${component}_IMPLIB)
  134. endif()
  135. endmacro()
  136. # FFmpeg_find_dll: Macro to find DLL for corresponding import library
  137. macro(FFmpeg_find_dll)
  138. cmake_path(GET FFmpeg_${component}_IMPLIB PARENT_PATH _implib_path)
  139. cmake_path(SET _bin_path NORMALIZE "${_implib_path}/../bin")
  140. string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" _dll_version "${FFmpeg_${component}_VERSION}")
  141. find_program(
  142. FFmpeg_${component}_LIBRARY
  143. NAMES ${component_name}-${_dll_version}.dll
  144. HINTS ${_implib_path} ${_bin_path}
  145. DOC "FFmpeg component ${component_name} DLL location")
  146. if(NOT FFmpeg_${component}_LIBRARY)
  147. set(FFmpeg_${component}_LIBRARY "${FFmpeg_${component}_IMPLIB}")
  148. endif()
  149. unset(_implib_path)
  150. unset(_bin_path)
  151. unset(_dll_version)
  152. endmacro()
  153. # FFmpeg_check_version: Macro to help extract version number from FFmpeg headers
  154. macro(FFmpeg_check_version)
  155. if(PC_FFmpeg_${component}_VERSION)
  156. set(FFmpeg_${component}_VERSION ${PC_FFmpeg_${component}_VERSION})
  157. elseif(EXISTS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h")
  158. if(EXISTS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version_major.h")
  159. file(STRINGS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version_major.h" _version_string
  160. REGEX "^.*VERSION_MAJOR[ \t]+[0-9]+[ \t]*$")
  161. string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _version_major "${_version_string}")
  162. file(STRINGS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h" _version_string
  163. REGEX "^.*VERSION_(MINOR|MICRO)[ \t]+[0-9]+[ \t]*$")
  164. string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _version_minor "${_version_string}")
  165. string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" _version_patch "${_version_string}")
  166. else()
  167. file(STRINGS "${FFmpeg_${component}_INCLUDE_DIR}/${component_libname}/version.h" _version_string
  168. REGEX "^.*VERSION_(MAJOR|MINOR|MICRO)[ \t]+[0-9]+[ \t]*$")
  169. string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _version_major "${_version_string}")
  170. string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _version_minor "${_version_string}")
  171. string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" _version_patch "${_version_string}")
  172. endif()
  173. set(FFmpeg_${component}_VERSION "${_version_major}.${_version_minor}.${_version_patch}")
  174. unset(_version_major)
  175. unset(_version_minor)
  176. unset(_version_patch)
  177. else()
  178. if(NOT FFmpeg_FIND_QUIETLY)
  179. message(AUTHOR_WARNING "Failed to find ${component_name} version.")
  180. endif()
  181. set(FFmpeg_${component}_VERSION 0.0.0)
  182. endif()
  183. endmacro()
  184. # FFmpeg_set_soname: Set SONAME property on imported library targets
  185. macro(FFmpeg_set_soname)
  186. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
  187. execute_process(
  188. COMMAND sh -c "otool -D '${FFmpeg_${component}_LIBRARY}' | grep -v '${FFmpeg_${component}_LIBRARY}'"
  189. OUTPUT_VARIABLE _output
  190. RESULT_VARIABLE _result)
  191. if(_result EQUAL 0 AND _output MATCHES "^@rpath/")
  192. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_SONAME "${_output}")
  193. endif()
  194. elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|FreeBSD")
  195. execute_process(
  196. COMMAND sh -c "objdump -p '${FFmpeg_${component}_LIBRARY}' | grep SONAME"
  197. OUTPUT_VARIABLE _output
  198. RESULT_VARIABLE _result)
  199. if(_result EQUAL 0)
  200. string(REGEX REPLACE "[ \t]+SONAME[ \t]+([^ \t]+)" "\\1" _soname "${_output}")
  201. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_SONAME "${_soname}")
  202. unset(_soname)
  203. endif()
  204. endif()
  205. unset(_output)
  206. unset(_result)
  207. endmacro()
  208. foreach(component IN LISTS FFmpeg_FIND_COMPONENTS)
  209. if(NOT component IN_LIST _DEFAULT_COMPONENTS)
  210. message(FATAL_ERROR "Unknown FFmpeg component specified: ${component}.")
  211. endif()
  212. if(NOT FFmpeg_${component}_FOUND)
  213. ffmpeg_find_component(${component})
  214. endif()
  215. if(FFmpeg_${component}_FOUND)
  216. list(APPEND FFmpeg_LIBRARIES ${FFmpeg_${component}_LIBRARY})
  217. list(APPEND FFmpeg_DEFINITIONS ${FFmpeg_${component}_DEFINITIONS})
  218. list(APPEND FFmpeg_INCLUDE_DIRS ${FFmpeg_${component}_INCLUDE_DIR})
  219. endif()
  220. endforeach()
  221. if(NOT FFmpeg_avutil_FOUND)
  222. ffmpeg_find_component(avutil)
  223. endif()
  224. if(EXISTS "${FFmpeg_avutil_INCLUDE_DIR}/libavutil/ffversion.h")
  225. file(STRINGS "${FFmpeg_avutil_INCLUDE_DIR}/libavutil/ffversion.h" _version_string
  226. REGEX "^.*FFMPEG_VERSION[ \t]+\"n[0-9\\.]+\"[ \t]*$")
  227. string(REGEX REPLACE ".*FFMPEG_VERSION[ \t]+\"n([0-9\\.]+)\".*" "\\1" FFmpeg_VERSION "${_version_string}")
  228. endif()
  229. list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIRS)
  230. list(REMOVE_DUPLICATES FFmpeg_LIBRARIES)
  231. list(REMOVE_DUPLICATES FFmpeg_DEFINITIONS)
  232. if(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin|Windows")
  233. set(FFmpeg_ERROR_REASON "Ensure that obs-deps is provided as part of CMAKE_PREFIX_PATH.")
  234. elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|FreeBSD")
  235. set(FFmpeg_ERROR_REASON "Ensure that required FFmpeg libraries are installed on the system.")
  236. endif()
  237. find_package_handle_standard_args(
  238. FFmpeg
  239. REQUIRED_VARS FFmpeg_LIBRARIES FFmpeg_INCLUDE_DIRS
  240. VERSION_VAR FFmpeg_VERSION
  241. HANDLE_COMPONENTS REASON_FAILURE_MESSAGE "${FFmpeg_ERROR_REASON}")
  242. if(FFmpeg_FOUND AND NOT TARGET FFmpeg::FFmpeg)
  243. add_library(FFmpeg::FFmpeg INTERFACE IMPORTED)
  244. endif()
  245. foreach(component IN LISTS FFmpeg_FIND_COMPONENTS)
  246. if(FFmpeg_${component}_FOUND AND NOT TARGET FFmpeg::${component})
  247. if(IS_ABSOLUTE "${FFmpeg_${component}_LIBRARY}")
  248. if(DEFINED FFmpeg_${component}_IMPLIB)
  249. if(FFmpeg_${component}_IMPLIB STREQUAL FFmpeg_${component}_LIBRARY)
  250. add_library(FFmpeg::${component} STATIC IMPORTED)
  251. else()
  252. add_library(FFmpeg::${component} SHARED IMPORTED)
  253. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_IMPLIB "${FFmpeg_${component}_IMPLIB}")
  254. endif()
  255. else()
  256. add_library(FFmpeg::${component} UNKNOWN IMPORTED)
  257. ffmpeg_set_soname()
  258. endif()
  259. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_LOCATION "${FFmpeg_${component}_LIBRARY}")
  260. else()
  261. add_library(FFmpeg::${component} INTERFACE IMPORTED)
  262. set_property(TARGET FFmpeg::${component} PROPERTY IMPORTED_LIBNAME "${FFmpeg_${component}_LIBRARY}")
  263. endif()
  264. set_target_properties(
  265. FFmpeg::${component}
  266. PROPERTIES INTERFACE_COMPILE_OPTIONS "${PC_FFmpeg_${component}_CFLAGS_OTHER}"
  267. INTERFACE_INCLUDE_DIRECTORIES "${FFmpeg_${component}_INCLUDE_DIR}"
  268. VERSION ${FFmpeg_${component}_VERSION})
  269. get_target_property(_ffmpeg_interface_libraries FFmpeg::FFmpeg INTERFACE_LINK_LIBRARIES)
  270. if(NOT FFmpeg::${component} IN_LIST _ffmpeg_interface_libraries)
  271. set_property(
  272. TARGET FFmpeg::FFmpeg
  273. APPEND
  274. PROPERTY INTERFACE_LINK_LIBRARIES FFmpeg::${component})
  275. endif()
  276. endif()
  277. endforeach()
  278. include(FeatureSummary)
  279. set_package_properties(
  280. FFmpeg PROPERTIES
  281. URL "https://www.ffmpeg.org"
  282. DESCRIPTION "A complete, cross-platform solution to record, convert and stream audio and video.")