From 1d19eac415199bd4c768f1cbebc9f23298734545 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Fri, 5 Feb 2021 15:39:19 -0500 Subject: [PATCH] CMake: Port citra-emu/citra FindFFmpeg.cmake Also renames related CMake variables to match both the Find*FFmpeg* and variables defined within the file. Fixes odd errors produced by the old FindFFmpeg. Citra's FindFFmpeg is slightly modified here: adds Citra's copyright at the beginning, renames FFmpeg_INCLUDES to FFmpeg_INCLUDE_DIR, disables a few components in _FFmpeg_ALL_COMPONENTS, and adds the missing avutil component to the comment above. --- CMakeLists.txt | 82 ++++---- externals/find-modules/FindFFmpeg.cmake | 256 ++++++++++++++++-------- src/video_core/CMakeLists.txt | 4 +- 3 files changed, 214 insertions(+), 128 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aafe73c442..fc3e93f80b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,45 +391,45 @@ if (YUZU_USE_BUNDLED_FFMPEG) # Build FFmpeg from externals message(STATUS "Using FFmpeg from externals") - set(FFMPEG_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) - set(FFMPEG_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) - set(FFMPEG_MAKEFILE ${FFMPEG_BUILD_DIR}/Makefile) - make_directory(${FFMPEG_BUILD_DIR}) + set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg) + set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg) + set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile) + make_directory(${FFmpeg_BUILD_DIR}) # Read version string from external - file(READ ${FFMPEG_PREFIX}/RELEASE FFMPEG_VERSION) - set(FFMPEG_FOUND NO) - if (NOT FFMPEG_VERSION STREQUAL "") - set(FFMPEG_FOUND YES) + file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION) + set(FFmpeg_FOUND NO) + if (NOT FFmpeg_VERSION STREQUAL "") + set(FFmpeg_FOUND YES) endif() - set(FFMPEG_COMPONENTS + set(FFmpeg_COMPONENTS avcodec avutil swscale) - foreach(COMPONENT ${FFMPEG_COMPONENTS}) - set(FFMPEG_${COMPONENT}_PREFIX "${FFMPEG_BUILD_DIR}/lib${COMPONENT}") - set(FFMPEG_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") - set(FFMPEG_${COMPONENT}_LIBRARY "${FFMPEG_${COMPONENT}_PREFIX}/${FFMPEG_${COMPONENT}_LIB_NAME}") + foreach(COMPONENT ${FFmpeg_COMPONENTS}) + set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}") + set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a") + set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}") - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBRARIES} - ${FFMPEG_${COMPONENT}_LIBRARY} + set(FFmpeg_LIBRARIES + ${FFmpeg_LIBRARIES} + ${FFmpeg_${COMPONENT}_LIBRARY} CACHE PATH "Paths to FFmpeg libraries" FORCE) endforeach() - set(FFMPEG_INCLUDE_DIR - ${FFMPEG_PREFIX} + set(FFmpeg_INCLUDE_DIR + ${FFmpeg_PREFIX} CACHE PATH "Path to FFmpeg headers" FORCE) # `configure` parameters builds only exactly what yuzu needs from FFmpeg # `--disable-{vaapi,vdpau}` is needed to avoid linking issues add_custom_command( OUTPUT - ${FFMPEG_MAKEFILE} + ${FFmpeg_MAKEFILE} COMMAND - /bin/bash ${FFMPEG_PREFIX}/configure + /bin/bash ${FFmpeg_PREFIX}/configure --disable-avdevice --disable-avfilter --disable-avformat @@ -445,25 +445,25 @@ if (YUZU_USE_BUNDLED_FFMPEG) --enable-decoder=h264 --enable-decoder=vp9 WORKING_DIRECTORY - ${FFMPEG_BUILD_DIR} + ${FFmpeg_BUILD_DIR} ) add_custom_command( OUTPUT - ${FFMPEG_LIBRARIES} + ${FFmpeg_LIBRARIES} COMMAND make WORKING_DIRECTORY - ${FFMPEG_BUILD_DIR} + ${FFmpeg_BUILD_DIR} ) # ALL makes this custom target build every time # but it won't actually build if the DEPENDS parameter is up to date - add_custom_target(ffmpeg-build ALL DEPENDS ${FFMPEG_LIBRARIES}) - add_custom_target(ffmpeg-configure ALL DEPENDS ${FFMPEG_MAKEFILE}) + add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_LIBRARIES}) + add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE}) - if (FFMPEG_FOUND) - message(STATUS "Found FFmpeg version ${FFMPEG_VERSION}") + if (FFmpeg_FOUND) + message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}") add_dependencies(ffmpeg-build ffmpeg-configure) else() @@ -471,22 +471,26 @@ if (YUZU_USE_BUNDLED_FFMPEG) endif() else() # WIN32 # Use yuzu FFmpeg binaries - set(FFMPEG_EXT_NAME "ffmpeg-4.2.1") - set(FFMPEG_PATH "${CMAKE_BINARY_DIR}/externals/${FFMPEG_EXT_NAME}") - download_bundled_external("ffmpeg/" ${FFMPEG_EXT_NAME} "") - set(FFMPEG_FOUND YES) - set(FFMPEG_INCLUDE_DIR "${FFMPEG_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) - set(FFMPEG_LIBRARY_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE) - set(FFMPEG_DLL_DIR "${FFMPEG_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBRARY_DIR}/swscale.lib - ${FFMPEG_LIBRARY_DIR}/avcodec.lib - ${FFMPEG_LIBRARY_DIR}/avutil.lib + set(FFmpeg_EXT_NAME "ffmpeg-4.2.1") + set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}") + download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "") + set(FFmpeg_FOUND YES) + set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE) + set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE) + set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE) + set(FFmpeg_LIBRARIES + ${FFmpeg_LIBRARY_DIR}/swscale.lib + ${FFmpeg_LIBRARY_DIR}/avcodec.lib + ${FFmpeg_LIBRARY_DIR}/avutil.lib CACHE PATH "Paths to FFmpeg libraries" FORCE) endif() else() # Use system installed FFmpeg - find_package(FFmpeg REQUIRED VERSION 4.0) + find_package(FFmpeg REQUIRED) + + if (NOT FFmpeg_FOUND) + message(FATAL_ERROR "FFmpeg not found") + endif() endif() # Prefer the -pthread flag on Linux. diff --git a/externals/find-modules/FindFFmpeg.cmake b/externals/find-modules/FindFFmpeg.cmake index 77b331e008..86a3f5a5a2 100644 --- a/externals/find-modules/FindFFmpeg.cmake +++ b/externals/find-modules/FindFFmpeg.cmake @@ -1,100 +1,182 @@ -# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) -# Once done this will define +# FindFFmpeg +# ---------- # -# FFMPEG_FOUND - system has ffmpeg or libav -# FFMPEG_INCLUDE_DIR - the ffmpeg include directory -# FFMPEG_LIBRARIES - Link these to use ffmpeg -# FFMPEG_LIBAVCODEC -# FFMPEG_LIBAVFORMAT -# FFMPEG_LIBAVUTIL +# Copyright 2019 Citra Emulator Project +# Licensed under GPLv2 or any later version # -# Copyright (c) 2008 Andreas Schneider -# Modified for other libraries by Lasse Kärkkäinen -# Modified for Hedgewars by Stepik777 -# Modified for FFmpeg-example Tuukka Pasanen 2018 -# Modified for yuzu toastUnlimted 2020 +# Find the native FFmpeg includes and libraries # -# Redistribution and use is allowed according to the terms of the New -# BSD license. +# This module defines the following variables: +# +# FFmpeg_INCLUDE_: where to find .h +# FFmpeg_LIBRARY_: where to find the library +# FFmpeg_INCLUDE_DIR: aggregate all the include paths +# FFmpeg_LIBRARIES: aggregate all the paths to the libraries +# FFmpeg_FOUND: True if all components have been found +# +# This module defines the following targets, which are prefered over variables: +# +# FFmpeg::: Target to use directly, with include path, +# library and dependencies set up. If you are using a static build, you are +# responsible for adding any external dependencies (such as zlib, bzlib...). +# +# can be one of: +# avcodec +# avdevice # Disabled +# avfilter # Disabled +# avformat # Disabled +# avutil +# postproc # Disabled +# swresample # Disabled +# swscale # -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(FFMPEG - FOUND_VAR FFMPEG_FOUND - REQUIRED_VARS - FFMPEG_LIBRARY - FFMPEG_INCLUDE_DIR - VERSION_VAR FFMPEG_VERSION +set(_FFmpeg_ALL_COMPONENTS + avcodec + avutil + swscale ) -if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) - # in cache already - set(FFMPEG_FOUND TRUE) -else() - # use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - find_package(PkgConfig) - if(PKG_CONFIG_FOUND) - pkg_check_modules(_FFMPEG_AVCODEC libavcodec) - pkg_check_modules(_FFMPEG_AVUTIL libavutil) - pkg_check_modules(_FFMPEG_SWSCALE libswscale) +set(_FFmpeg_DEPS_avcodec avutil) +set(_FFmpeg_DEPS_avdevice avcodec avformat avutil) +set(_FFmpeg_DEPS_avfilter avutil) +set(_FFmpeg_DEPS_avformat avcodec avutil) +set(_FFmpeg_DEPS_postproc avutil) +set(_FFmpeg_DEPS_swresample avutil) +set(_FFmpeg_DEPS_swscale avutil) + +function(find_ffmpeg LIBNAME) + if(DEFINED ENV{FFMPEG_DIR}) + set(FFMPEG_DIR $ENV{FFMPEG_DIR}) endif() - find_path(FFMPEG_AVCODEC_INCLUDE_DIR - NAMES libavcodec/avcodec.h - PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} - /usr/include - /usr/local/include - /opt/local/include - /sw/include - PATH_SUFFIXES ffmpeg libav) - - find_library(FFMPEG_LIBAVCODEC - NAMES avcodec - PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - find_library(FFMPEG_LIBAVUTIL - NAMES avutil - PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - find_library(FFMPEG_LIBSWSCALE - NAMES swscale - PATHS ${_FFMPEG_SWSCALE_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib) - - if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVUTIL AND FFMPEG_LIBSWSCALE) - set(FFMPEG_FOUND TRUE) - endif() - - if(FFMPEG_FOUND) - set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) - set(FFMPEG_LIBRARIES - ${FFMPEG_LIBAVCODEC} - ${FFMPEG_LIBAVUTIL} - ${FFMPEG_LIBSWSCALE}) - endif() - - if(FFMPEG_FOUND) - if(NOT FFMPEG_FIND_QUIETLY) - message(STATUS - "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") - endif() + if(FFMPEG_DIR) + list(APPEND INCLUDE_PATHS + ${FFMPEG_DIR} + ${FFMPEG_DIR}/ffmpeg + ${FFMPEG_DIR}/lib${LIBNAME} + ${FFMPEG_DIR}/include/lib${LIBNAME} + ${FFMPEG_DIR}/include/ffmpeg + ${FFMPEG_DIR}/include + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + list(APPEND LIB_PATHS + ${FFMPEG_DIR} + ${FFMPEG_DIR}/lib + ${FFMPEG_DIR}/lib${LIBNAME} + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH + ) else() - if(FFMPEG_FIND_REQUIRED) - message(FATAL_ERROR - "Could not find libavcodec or libavutil or libswscale") + list(APPEND INCLUDE_PATHS + /usr/local/include/ffmpeg + /usr/local/include/lib${LIBNAME} + /usr/include/ffmpeg + /usr/include/lib${LIBNAME} + /usr/include/ffmpeg/lib${LIBNAME} + ) + + list(APPEND LIB_PATHS + /usr/local/lib + /usr/lib + ) + endif() + + find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h + HINTS ${INCLUDE_PATHS} + ) + + find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME} + HINTS ${LIB_PATHS} + ) + + if(NOT FFMPEG_DIR AND (NOT FFmpeg_LIBRARY_${LIBNAME} OR NOT FFmpeg_INCLUDE_${LIBNAME})) + # Didn't find it in the usual paths, try pkg-config + find_package(PkgConfig QUIET) + pkg_check_modules(FFmpeg_PKGCONFIG_${LIBNAME} QUIET lib${LIBNAME}) + + find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h + ${FFmpeg_PKGCONFIG_${LIBNAME}_INCLUDE_DIRS} + ) + + find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME} + ${FFmpeg_PKGCONFIG_${LIBNAME}_LIBRARY_DIRS} + ) + endif() + + if(FFmpeg_INCLUDE_${LIBNAME} AND FFmpeg_LIBRARY_${LIBNAME}) + set(FFmpeg_INCLUDE_${LIBNAME} "${FFmpeg_INCLUDE_${LIBNAME}}" PARENT_SCOPE) + set(FFmpeg_LIBRARY_${LIBNAME} "${FFmpeg_LIBRARY_${LIBNAME}}" PARENT_SCOPE) + + # Extract FFmpeg version from version.h + foreach(v MAJOR MINOR MICRO) + set(FFmpeg_${LIBNAME}_VERSION_${v} 0) + endforeach() + string(TOUPPER ${LIBNAME} LIBNAME_UPPER) + file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version.h" _FFmpeg_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_(MAJOR|MINOR|MICRO) ") + set(_FFmpeg_VERSION_REGEX "([0-9]+)") + foreach(v MAJOR MINOR MICRO) + if("${_FFmpeg_VERSION_H_CONTENTS}" MATCHES "#define LIB${LIBNAME_UPPER}_VERSION_${v}[\\t ]+${_FFmpeg_VERSION_REGEX}") + set(FFmpeg_${LIBNAME}_VERSION_${v} "${CMAKE_MATCH_1}") + endif() + endforeach() + set(FFmpeg_${LIBNAME}_VERSION "${FFmpeg_${LIBNAME}_VERSION_MAJOR}.${FFmpeg_${LIBNAME}_VERSION_MINOR}.${FFmpeg_${LIBNAME}_VERSION_MICRO}") + set(FFmpeg_${c}_VERSION "${FFmpeg_${LIBNAME}_VERSION}" PARENT_SCOPE) + unset(_FFmpeg_VERSION_REGEX) + unset(_FFmpeg_VERSION_H_CONTENTS) + + set(FFmpeg_${c}_FOUND TRUE PARENT_SCOPE) + if(NOT FFmpeg_FIND_QUIETLY) + message("-- Found ${LIBNAME}: ${FFmpeg_INCLUDE_${LIBNAME}} ${FFmpeg_LIBRARY_${LIBNAME}} (version: ${FFmpeg_${LIBNAME}_VERSION})") endif() endif() +endfunction() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + find_ffmpeg(${c}) +endforeach() + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + if(FFmpeg_${c}_FOUND) + list(APPEND FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_${c}}) + list(APPEND FFmpeg_LIBRARIES ${FFmpeg_LIBRARY_${c}}) + + add_library(FFmpeg::${c} IMPORTED UNKNOWN) + set_target_properties(FFmpeg::${c} PROPERTIES + IMPORTED_LOCATION ${FFmpeg_LIBRARY_${c}} + INTERFACE_INCLUDE_DIRECTORIES ${FFmpeg_INCLUDE_${c}} + ) + if(_FFmpeg_DEPS_${c}) + set(deps) + foreach(dep ${_FFmpeg_DEPS_${c}}) + list(APPEND deps FFmpeg::${dep}) + endforeach() + + set_target_properties(FFmpeg::${c} PROPERTIES + INTERFACE_LINK_LIBRARIES "${deps}" + ) + unset(deps) + endif() + endif() +endforeach() + +if(FFmpeg_INCLUDE_DIR) + list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIR) endif() + +foreach(c ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_INCLUDE_${c} FFmpeg_LIBRARY_${c}) +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FFmpeg + REQUIRED_VARS ${_FFmpeg_REQUIRED_VARS} + HANDLE_COMPONENTS +) + +foreach(c ${_FFmpeg_ALL_COMPONENTS}) + unset(_FFmpeg_DEPS_${c}) +endforeach() +unset(_FFmpeg_ALL_COMPONENTS) +unset(_FFmpeg_REQUIRED_VARS) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 01e284d8c8..1434d02609 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -277,8 +277,8 @@ if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) add_dependencies(video_core ffmpeg-build) endif() -target_include_directories(video_core PRIVATE ${FFMPEG_INCLUDE_DIR}) -target_link_libraries(video_core PRIVATE ${FFMPEG_LIBRARIES}) +target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) +target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})