diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 8645e83f3c2..2a94328ca06 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -126,7 +126,7 @@ jobs: with: # This should always match the minimum required version in # our CMakeLists.txt - cmake-version: "3.21.x" + cmake-version: "3.22.x" - name: "[Windows] Set up cmake" uses: jwlawson/actions-setup-cmake@v2.2 @@ -134,10 +134,9 @@ jobs: # On windows-11-arm this action installs the x64 version which has unwanted side effects if: matrix.os == 'windows-2022' with: - # This is a workaround for a SSL false positive in cmake 3.26.4 - # When downloading the manual. 3.21 is required for installing the - # ANGLE Dlls via IMPORTED_RUNTIME_ARTIFACTS - cmake-version: "3.21.x" + # This is a workaround for a SSL false positive in cmake 3.26.4 when downloading the manual. + # 3.22 is required for Qt 6.10 https://doc.qt.io/qt-6.10/cmake-supported-cmake-versions.html + cmake-version: "3.22.x" - name: "[Windows] Set up MSVC Developer Command Prompt" if: runner.os == 'Windows' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7e6220b835..e3b6b3af12d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -236,7 +236,7 @@ jobs: with: # This should always match the minimum required version in # our CMakeLists.txt - cmake-version: "3.21.x" + cmake-version: "3.22.x" - name: "[Windows] Set up cmake" uses: jwlawson/actions-setup-cmake@v2.2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 19cc227a9a2..84ca67b5f08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.21) +# Qt 6.10 requires minimum CMake 3.22: https://doc.qt.io/qt-6.10/cmake-supported-cmake-versions.html +cmake_minimum_required(VERSION 3.22) # lint_cmake: -readability/wonkycase message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}") @@ -2764,11 +2765,11 @@ endif() # FFmpeg support # FFmpeg is multimedia library that can be found http://ffmpeg.org/ -find_package(FFMPEG COMPONENTS libavcodec libavformat libavutil libswresample) -default_option(FFMPEG "FFmpeg support (version 4.1.9 or later)" "FFMPEG_FOUND") +find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE) +default_option(FFMPEG "FFmpeg support (version 4.1.9 or later)" "FFmpeg_FOUND") if(FFMPEG) - if(NOT FFMPEG_FOUND) - message(FATAL_ERROR "FFMPEG was not found") + if(NOT FFmpeg_FOUND) + message(FATAL_ERROR "FFmpeg was not found") endif() # Check minimum required versions @@ -2776,39 +2777,56 @@ if(FFMPEG) # Windows: Version numbers are not available!? # macOS: Untested if( - FFMPEG_libavcodec_VERSION - AND FFMPEG_libavcodec_VERSION VERSION_LESS 58.35.100 + NOT FFmpeg_AVCODEC_VERSION + OR FFmpeg_AVCODEC_VERSION VERSION_LESS 58.35.100 ) message( FATAL_ERROR - "FFmpeg support requires at least version 58.35.100 of libavcodec (found: ${FFMPEG_libavcodec_VERSION})." + "FFmpeg support requires at least version 58.35.100 of libavcodec (found: ${FFmpeg_AVCODEC_VERSION})." + ) + else() + message( + STATUS + "Found FFmpeg AVCODEC: ${FFmpeg_AVCODEC_LIBRARIES} (found version \"${FFmpeg_AVCODEC_VERSION}\")" ) endif() if( - FFMPEG_libavformat_VERSION - AND FFMPEG_libavformat_VERSION VERSION_LESS 58.20.100 + NOT FFmpeg_AVFORMAT_VERSION + OR FFmpeg_AVFORMAT_VERSION VERSION_LESS 58.20.100 ) message( FATAL_ERROR - "FFmpeg support requires at least version 58.20.100 of libavformat (found: ${FFMPEG_libavformat_VERSION})." + "FFmpeg support requires at least version 58.20.100 of libavformat (found: ${FFmpeg_AVFORMAT_VERSION})." + ) + else() + message( + STATUS + "Found FFmpeg AVFORMAT: ${FFmpeg_AVFORMAT_LIBRARIES} (found version \"${FFmpeg_AVFORMAT_VERSION}\")" ) endif() - if( - FFMPEG_libavutil_VERSION - AND FFMPEG_libavutil_VERSION VERSION_LESS 56.22.100 - ) + if(NOT FFmpeg_AVUTIL_VERSION OR FFmpeg_AVUTIL_VERSION VERSION_LESS 56.22.100) message( FATAL_ERROR - "FFmpeg support requires at least version 56.22.100 of libavutil (found: ${FFMPEG_libavutil_VERSION})." + "FFmpeg support requires at least version 56.22.100 of libavutil (found: ${FFmpeg_AVUTIL_VERSION})." + ) + else() + message( + STATUS + "Found FFmpeg AVUTIL: ${FFmpeg_AVUTIL_LIBRARIES} (found version \"${FFmpeg_AVUTIL_VERSION}\")" ) endif() if( - FFMPEG_libswresample_VERSION - AND FFMPEG_libswresample_VERSION VERSION_LESS 3.3.100 + NOT FFmpeg_SWRESAMPLE_VERSION + OR FFmpeg_SWRESAMPLE_VERSION VERSION_LESS 3.3.100 ) message( FATAL_ERROR - "FFmpeg support requires at least version 3.3.100 of libswresample (found: ${FFMPEG_libswresample_VERSION})." + "FFmpeg support requires at least version 3.3.100 of libswresample (found: ${FFmpeg_SWRESAMPLE_VERSION})." + ) + else() + message( + STATUS + "Found FFmpeg SWRESAMPLE: ${FFmpeg_SWRESAMPLE_LIBRARIES} (found version \"${FFmpeg_SWRESAMPLE_VERSION}\")" ) endif() @@ -2822,15 +2840,16 @@ if(FFMPEG) __STDC_LIMIT_MACROS __STDC_FORMAT_MACROS ) - target_link_libraries(mixxx-lib PRIVATE "${FFMPEG_LIBRARIES}") - target_include_directories(mixxx-lib PUBLIC "${FFMPEG_INCLUDE_DIRS}") + + target_link_libraries(mixxx-lib PRIVATE FFmpeg::FFmpeg) + target_include_directories(mixxx-lib PUBLIC "${FFmpeg_INCLUDE_DIRS}") endif() # STEM file support -default_option(STEM "STEM file support" "FFMPEG_FOUND;FFMPEG") +default_option(STEM "STEM file support" "FFmpeg_FOUND;FFMPEG") if(STEM) if(NOT FFMPEG) - message(FATAL_ERROR "STEM requires that also FFMPEG is enabled") + message(FATAL_ERROR "STEM requires that also FFmpeg is enabled") endif() target_compile_definitions(mixxx-lib PUBLIC __STEM__) list(APPEND MIXXX_LIB_PRECOMPILED_HEADER src/track/steminfo.h) @@ -4415,12 +4434,12 @@ if(APPLE) "-weak_framework CoreAudio" "-weak_framework CoreFoundation" "-weak_framework CoreImage" - "-weak_framework CoreMedia" + "-framework CoreMedia" "-weak_framework CoreMidi" "-weak_framework CoreServices" - "-weak_framework CoreVideo" + "-framework CoreVideo" "-weak_framework IOSurface" - "-weak_framework VideoToolbox" + "-framework VideoToolbox" ) if(IOS) target_link_libraries(mixxx-lib PRIVATE "-weak_framework UIKit") @@ -4853,12 +4872,12 @@ endif() # FDK-AAC is loaded dynamically at runtime by EncoderFdkAac using QLibrary, # so copy it into the Windows and macOS packages, but do not link to it. -if(APPLE AND MACOS_BUNDLE) - find_library(FDK_AAC_LIBRARY fdk-aac) - if(FDK_AAC_LIBRARY) - message(STATUS "Found fdk-aac: ${FDK_AAC_LIBRARY}") +find_package(FdkAac QUIET) +if(FdkAac_FOUND) + if(APPLE AND MACOS_BUNDLE) + message(STATUS "Found fdk-aac: ${FdkAac_LIBRARY}") file( - COPY ${FDK_AAC_LIBRARY} + COPY "${FdkAac_LIBRARY}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/lib/fdk-aac-install" FOLLOW_SYMLINK_CHAIN ) @@ -4866,18 +4885,16 @@ if(APPLE AND MACOS_BUNDLE) DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/fdk-aac-install/" DESTINATION "${MIXXX_INSTALL_PREFIX}/Contents/Frameworks" ) - else() - message(STATUS "Could NOT find libfdk-aac.dylib") - endif() -elseif(WIN32) - # On Windows find_library finds the .lib file, but the installer needs the .dll file. - find_file(FDK_AAC_DLL fdk-aac.dll PATH_SUFFIXES ${CMAKE_INSTALL_BINDIR}) - if(FDK_AAC_DLL) - message(STATUS "Found fdk-aac DLL: ${FDK_AAC_DLL}") - install(FILES ${FDK_AAC_DLL} DESTINATION ${MIXXX_INSTALL_BINDIR}) - else() - message(STATUS "Could NOT find fdk-aac.dll") + elseif(WIN32) + if(FdkAac_DLL) + message(STATUS "Found fdk-aac DLL: ${FdkAac_DLL}") + install(FILES "${FdkAac_DLL}" DESTINATION "${MIXXX_INSTALL_BINDIR}") + else() + message(STATUS "Could NOT find fdk-aac.dll (FdkAac_DLL not set)") + endif() endif() +else() + message(STATUS "Could NOT find fdk-aac (FdkAac_FOUND is FALSE)") endif() # Google PerfTools diff --git a/cmake/modules/FindFFMPEG.cmake b/cmake/modules/FindFFMPEG.cmake deleted file mode 100644 index 55255cc30e2..00000000000 --- a/cmake/modules/FindFFMPEG.cmake +++ /dev/null @@ -1,202 +0,0 @@ -#.rst: -# FindFFMPEG -# ---------- -# -# Try to find the required ffmpeg components (default: libavformat, libavutil, libavcodec) -# -# Next variables can be used to hint FFMPEG libs search: -# -# :: -# -# PC__LIBRARY_DIRS -# PC_FFMPEG_LIBRARY_DIRS -# PC__INCLUDE_DIRS -# PC_FFMPEG_INCLUDE_DIRS -# -# Once done this will define -# -# :: -# -# FFMPEG_FOUND - System has the all required components. -# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. -# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. -# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. -# -# For each of the components it will additionally set. -# -# :: -# -# libavcodec -# libavdevice -# libavformat -# libavfilter -# libavutil -# libswscale -# libswresample -# -# the following variables will be defined -# -# :: -# -# _FOUND - System has -# _INCLUDE_DIRS - Include directory necessary for using the headers -# _LIBRARIES - Link these to use -# _DEFINITIONS - Compiler switches required for using -# _VERSION - The components version -# -# the following import targets is created -# -# :: -# -# FFMPEG::FFMPEG - for all components -# FFMPEG:: - where in lower case (FFMPEG::avcodec) for each components -# -# Copyright (c) 2006, Matthias Kretz, -# Copyright (c) 2008, Alexander Neundorf, -# Copyright (c) 2011, Michael Jansen, -# Copyright (c) 2017, Alexander Drozdov, -# Copyright (c) 2019, Jan Holthuis, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -include(FindPackageHandleStandardArgs) - -# The default components were taken from a survey over other FindFFMPEG.cmake files -if(NOT FFMPEG_FIND_COMPONENTS) - set(FFMPEG_FIND_COMPONENTS libavcodec libavformat libavutil) -endif() - -# -### Macro: find_component -# -# Checks for the given component by invoking pkgconfig and then looking up the libraries and -# include directories. -# -macro(find_component component pkgconfig library header) - # use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - find_package(PkgConfig QUIET) - if(PkgConfig_FOUND) - pkg_check_modules(PC_FFMPEG_${component} QUIET ${pkgconfig}) - endif() - - find_path( - FFMPEG_${component}_INCLUDE_DIRS - ${header} - HINTS - ${PC_FFMPEG_${component}_INCLUDEDIR} - ${PC_FFMPEG_${component}_INCLUDE_DIRS} - ${PC_FFMPEG_INCLUDE_DIRS} - PATH_SUFFIXES ffmpeg - ) - - find_library( - FFMPEG_${component}_LIBRARIES - NAMES ${PC_FFMPEG_${component}_LIBRARIES} ${library} - HINTS - ${PC_FFMPEG_${component}_LIBDIR} - ${PC_FFMPEG_${component}_LIBRARY_DIRS} - ${PC_FFMPEG_LIBRARY_DIRS} - ) - - #message(STATUS ${FFMPEG_${component}_LIBRARIES}) - #message(STATUS ${PC_FFMPEG_${component}_LIBRARIES}) - - set( - FFMPEG_${component}_DEFINITIONS - ${PC_FFMPEG_${component}_CFLAGS_OTHER} - CACHE STRING - "The ${component} CFLAGS." - ) - set( - FFMPEG_${component}_VERSION - ${PC_FFMPEG_${component}_VERSION} - CACHE STRING - "The ${component} version number." - ) - - if(FFMPEG_${component}_LIBRARIES AND FFMPEG_${component}_INCLUDE_DIRS) - message(STATUS " - ${component} ${FFMPEG_${component}_VERSION} found.") - set(FFMPEG_${component}_FOUND TRUE) - else() - message(STATUS " - ${component} not found.") - endif() - - mark_as_advanced( - FFMPEG_${component}_INCLUDE_DIRS - FFMPEG_${component}_LIBRARIES - FFMPEG_${component}_DEFINITIONS - FFMPEG_${component}_VERSION - ) -endmacro() - -message(STATUS "Searching for FFMPEG components") -# Check for all possible component. -find_component(libavcodec libavcodec avcodec libavcodec/avcodec.h) -find_component(libavformat libavformat avformat libavformat/avformat.h) -find_component(libavdevice libavdevice avdevice libavdevice/avdevice.h) -find_component(libavutil libavutil avutil libavutil/avutil.h) -find_component(libavfilter libavfilter avfilter libavfilter/avfilter.h) -find_component(libswscale libswscale swscale libswscale/swscale.h) -find_component(libswresample libswresample swresample libswresample/swresample.h) - -set(FFMPEG_LIBRARIES "") -set(FFMPEG_DEFINITIONS "") -# Check if the required components were found and add their stuff to the FFMPEG_* vars. -foreach(component ${FFMPEG_FIND_COMPONENTS}) - if(FFMPEG_${component}_FOUND) - #message(STATUS "Required component ${component} present.") - set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${FFMPEG_${component}_LIBRARIES}) - set( - FFMPEG_DEFINITIONS - ${FFMPEG_DEFINITIONS} - ${FFMPEG_${component}_DEFINITIONS} - ) - list(APPEND FFMPEG_INCLUDE_DIRS ${FFMPEG_${component}_INCLUDE_DIRS}) - endif() -endforeach() - -# Build the include path with duplicates removed. -if(FFMPEG_INCLUDE_DIRS) - list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) -endif() - -# cache the vars. -set( - FFMPEG_INCLUDE_DIRS - ${FFMPEG_INCLUDE_DIRS} - CACHE STRING - "The FFMPEG include directories." - FORCE -) -set( - FFMPEG_LIBRARIES - ${FFMPEG_LIBRARIES} - CACHE STRING - "The FFMPEG libraries." - FORCE -) -set( - FFMPEG_DEFINITIONS - ${FFMPEG_DEFINITIONS} - CACHE STRING - "The FFMPEG cflags." - FORCE -) - -mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS) - -# Compile the list of required vars -set(FFMPEG_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) -foreach(component ${FFMPEG_FIND_COMPONENTS}) - list( - APPEND - FFMPEG_REQUIRED_VARS - FFMPEG_${component}_LIBRARIES - FFMPEG_${component}_INCLUDE_DIRS - ) -endforeach() - -# Give a nice error message if some of the required vars are missing. -find_package_handle_standard_args(FFMPEG DEFAULT_MSG ${FFMPEG_REQUIRED_VARS}) diff --git a/cmake/modules/FindFFmpeg.cmake b/cmake/modules/FindFFmpeg.cmake new file mode 100644 index 00000000000..725d19b8d63 --- /dev/null +++ b/cmake/modules/FindFFmpeg.cmake @@ -0,0 +1,347 @@ +#.rst: +# FindFFmpeg +# ---------- +# +# Try to find the required FFmpeg components (default: AVCODEC, AVFORMAT, AVUTIL) +# +# Next variables can be used to hint FFmpeg libs search: +# +# :: +# +# PC_FFmpeg_LIBRARY_DIRS +# PC_FFmpeg_INCLUDE_DIRS +# +# Once done this will define +# +# :: +# +# FFmpeg_FOUND - System has all required components. +# FFmpeg_INCLUDE_DIRS - Include directories for all required components. +# FFmpeg_LIBRARIES - Libraries to link for all required components. +# FFmpeg_DEFINITIONS - Compiler switches required for using FFmpeg. +# +# For each of the components it will additionally set. +# +# :: +# +# FFmpeg__FOUND - System has +# FFmpeg__INCLUDE_DIRS - Include directories for +# FFmpeg__LIBRARIES - Libraries to link for +# FFmpeg__DEFINITIONS - Compiler switches for +# FFmpeg__VERSION - Version of +# +# The following imported targets are created: +# +# :: +# +# FFmpeg::FFmpeg - interface target aggregating all found components +# FFmpeg::avcodec - libavcodec +# FFmpeg::avformat - libavformat +# FFmpeg::avdevice - libavdevice +# FFmpeg::avutil - libavutil +# FFmpeg::avfilter - libavfilter +# FFmpeg::swscale - libswscale +# FFmpeg::swresample - libswresample +# +# Component names are Qt-compliant uppercase (AVCODEC, AVFORMAT, …) as +# required by Qt6's internal find_dependency() calls in +# Qt6FFmpegMediaPluginImplPrivateDependencies.cmake: +# +# find_dependency(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE SWSCALE) +# +# Imported target names are lowercase (FFmpeg::avcodec, …) as listed in +# Qt6FFmpegMediaPluginImplPrivateDependencies.cmake: +# +# provided_targets "FFmpeg::avcodec;FFmpeg::avformat;FFmpeg::avutil; +# FFmpeg::swresample;FFmpeg::swscale" +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# Copyright (c) 2017, Alexander Drozdov, +# Copyright (c) 2019, Jan Holthuis, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(FindPackageHandleStandardArgs) +include(IsStaticLibrary) + +# Early-return guard: Qt6's find_dependency() chain calls find_package(FFmpeg) +# once per multimedia plugin. Imported targets are global and persistent, so +# if FFmpeg::avcodec already exists the search is done — return silently. +if(TARGET FFmpeg::avcodec) + set(FFmpeg_FOUND TRUE) + return() +endif() + +if(NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) +endif() + +# Component table: UPPERCASE lowercase-stem pkg-config-name primary-header +set( + _FFmpeg_components + "AVCODEC avcodec libavcodec libavcodec/avcodec.h" + "AVFORMAT avformat libavformat libavformat/avformat.h" + "AVDEVICE avdevice libavdevice libavdevice/avdevice.h" + "AVUTIL avutil libavutil libavutil/avutil.h" + "AVFILTER avfilter libavfilter libavfilter/avfilter.h" + "SWSCALE swscale libswscale libswscale/swscale.h" + "SWRESAMPLE swresample libswresample libswresample/swresample.h" +) +foreach(_entry IN LISTS _FFmpeg_components) + separate_arguments(_fields UNIX_COMMAND "${_entry}") + list(GET _fields 0 _uc) + list(GET _fields 1 _lc) + list(GET _fields 2 _pc) + list(GET _fields 3 _hdr) + set(_FFmpeg_${_uc}_lower "${_lc}") + set(_FFmpeg_${_uc}_pkgconfig "${_pc}") + set(_FFmpeg_${_uc}_header "${_hdr}") +endforeach() +unset(_entry) +unset(_fields) +unset(_uc) +unset(_lc) +unset(_pc) +unset(_hdr) + +find_package(PkgConfig QUIET) + +macro(find_component component) + set(_lower "${_FFmpeg_${component}_lower}") + set(_pkgcfg "${_FFmpeg_${component}_pkgconfig}") + set(_header "${_FFmpeg_${component}_header}") + + if(PkgConfig_FOUND) + pkg_check_modules(PC_FFmpeg_${component} QUIET ${_pkgcfg}) + endif() + + find_path( + FFmpeg_${component}_INCLUDE_DIRS + ${_header} + HINTS + ${PC_FFmpeg_${component}_INCLUDEDIR} + ${PC_FFmpeg_${component}_INCLUDE_DIRS} + ${PC_FFmpeg_INCLUDE_DIRS} + PATH_SUFFIXES ffmpeg + ) + find_library( + FFmpeg_${component}_LIBRARIES + NAMES ${PC_FFmpeg_${component}_LIBRARIES} ${_lower} + HINTS + ${PC_FFmpeg_${component}_LIBDIR} + ${PC_FFmpeg_${component}_LIBRARY_DIRS} + ${PC_FFmpeg_LIBRARY_DIRS} + ) + set( + FFmpeg_${component}_DEFINITIONS + ${PC_FFmpeg_${component}_CFLAGS_OTHER} + CACHE STRING + "The ${component} CFLAGS." + ) + set( + FFmpeg_${component}_VERSION + ${PC_FFmpeg_${component}_VERSION} + CACHE STRING + "The ${component} version number." + ) + mark_as_advanced( + FFmpeg_${component}_INCLUDE_DIRS + FFmpeg_${component}_LIBRARIES + FFmpeg_${component}_DEFINITIONS + FFmpeg_${component}_VERSION + ) + + if(FFmpeg_${component}_LIBRARIES AND FFmpeg_${component}_INCLUDE_DIRS) + message(STATUS " - ${component} ${FFmpeg_${component}_VERSION} found.") + set(FFmpeg_${component}_FOUND TRUE) + else() + message(STATUS " - ${component} not found.") + endif() + unset(_lower) + unset(_pkgcfg) + unset(_header) +endmacro() + +message(STATUS "Searching for FFmpeg components") +foreach( + _comp + AVCODEC + AVFORMAT + AVDEVICE + AVUTIL + AVFILTER + SWSCALE + SWRESAMPLE +) + find_component(${_comp}) +endforeach() +unset(_comp) + +# Aggregate results for requested components +set(FFmpeg_LIBRARIES "") +set(FFmpeg_DEFINITIONS "") +set(FFmpeg_INCLUDE_DIRS "") +foreach(component ${FFmpeg_FIND_COMPONENTS}) + if(FFmpeg_${component}_FOUND) + list(APPEND FFmpeg_LIBRARIES ${FFmpeg_${component}_LIBRARIES}) + list(APPEND FFmpeg_DEFINITIONS ${FFmpeg_${component}_DEFINITIONS}) + list(APPEND FFmpeg_INCLUDE_DIRS ${FFmpeg_${component}_INCLUDE_DIRS}) + endif() +endforeach() +list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIRS) + +# Cache aggregates (consumed by CMakeLists.txt via "${FFmpeg_LIBRARIES}") +set( + FFmpeg_LIBRARIES + ${FFmpeg_LIBRARIES} + CACHE STRING + "The FFmpeg libraries." + FORCE +) +set( + FFmpeg_INCLUDE_DIRS + ${FFmpeg_INCLUDE_DIRS} + CACHE STRING + "The FFmpeg include directories." + FORCE +) +set( + FFmpeg_DEFINITIONS + ${FFmpeg_DEFINITIONS} + CACHE STRING + "The FFmpeg cflags." + FORCE +) +mark_as_advanced(FFmpeg_LIBRARIES FFmpeg_INCLUDE_DIRS FFmpeg_DEFINITIONS) + +# Build required-vars list from requested components +set(_FFmpeg_required FFmpeg_LIBRARIES FFmpeg_INCLUDE_DIRS) +foreach(component ${FFmpeg_FIND_COMPONENTS}) + list( + APPEND + _FFmpeg_required + FFmpeg_${component}_LIBRARIES + FFmpeg_${component}_INCLUDE_DIRS + ) +endforeach() +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_required}) +unset(_FFmpeg_required) + +if(FFmpeg_FOUND) + # Create per-component IMPORTED targets + foreach( + component + AVCODEC + AVFORMAT + AVDEVICE + AVUTIL + AVFILTER + SWSCALE + SWRESAMPLE + ) + if(FFmpeg_${component}_FOUND) + set(_target "FFmpeg::${_FFmpeg_${component}_lower}") + if(NOT TARGET ${_target}) + add_library(${_target} UNKNOWN IMPORTED) + set_target_properties( + ${_target} + PROPERTIES + IMPORTED_LOCATION "${FFmpeg_${component}_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${FFmpeg_${component}_INCLUDE_DIRS}" + INTERFACE_COMPILE_OPTIONS "${FFmpeg_${component}_DEFINITIONS}" + ) + endif() + unset(_target) + endif() + endforeach() + + # When libavcodec is static it may have been built with --enable-libfdk-aac. + # Add FdkAac::FdkAac as a transitive dep so the final linker resolves the + # aacEnc*/aacDec* symbols (mirrors FindChromaprint.cmake's FFTW3 pattern). + if(TARGET FFmpeg::avcodec) + is_static_library(_avcodec_static FFmpeg::avcodec) + if(_avcodec_static) + find_package(FdkAac QUIET) + if(FdkAac_FOUND) + set_property( + TARGET FFmpeg::avcodec + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES FdkAac::FdkAac + ) + # Also append to the cached FFmpeg_LIBRARIES variable so any remaining + # consumers that use "${FFmpeg_LIBRARIES}" directly (e.g. legacy call + # sites) also get the dependency resolved. + list(APPEND FFmpeg_LIBRARIES ${FdkAac_LIBRARY}) + set( + FFmpeg_LIBRARIES + ${FFmpeg_LIBRARIES} + CACHE STRING + "The FFmpeg libraries." + FORCE + ) + endif() + endif() + unset(_avcodec_static) + endif() + + # On Apple platforms the static FFmpeg libraries reference VideoToolbox, + # CoreMedia and CoreVideo symbols (e.g. av_map_videotoolbox_format_to_pixfmt + # in libavutil, hardware-accelerated codecs in libavcodec). Add the + # required frameworks as transitive interface deps on the affected targets. + if(APPLE) + foreach(_component_target IN ITEMS FFmpeg::avcodec FFmpeg::avutil) + if(TARGET ${_component_target}) + is_static_library(_is_static ${_component_target}) + if(_is_static) + set_property( + TARGET ${_component_target} + APPEND + PROPERTY + INTERFACE_LINK_LIBRARIES + "-framework VideoToolbox" + "-framework CoreMedia" + "-framework CoreVideo" + ) + endif() + unset(_is_static) + endif() + endforeach() + unset(_component_target) + + # Also append to FFmpeg_LIBRARIES for legacy consumers + is_static_library(_avutil_static FFmpeg::avutil) + if(_avutil_static) + list( + APPEND + FFmpeg_LIBRARIES + "-framework VideoToolbox" + "-framework CoreMedia" + "-framework CoreVideo" + ) + set( + FFmpeg_LIBRARIES + ${FFmpeg_LIBRARIES} + CACHE STRING + "The FFmpeg libraries." + FORCE + ) + endif() + unset(_avutil_static) + endif() + + # Aggregate convenience target + if(NOT TARGET FFmpeg::FFmpeg) + add_library(FFmpeg::FFmpeg INTERFACE IMPORTED) + foreach(component ${FFmpeg_FIND_COMPONENTS}) + if(FFmpeg_${component}_FOUND) + target_link_libraries( + FFmpeg::FFmpeg + INTERFACE "FFmpeg::${_FFmpeg_${component}_lower}" + ) + endif() + endforeach() + endif() +endif() diff --git a/cmake/modules/FindFdkAac.cmake b/cmake/modules/FindFdkAac.cmake new file mode 100644 index 00000000000..463d6944a08 --- /dev/null +++ b/cmake/modules/FindFdkAac.cmake @@ -0,0 +1,118 @@ +#[=======================================================================[.rst: +FindFdkAac +---------- + +Finds the Fraunhofer FDK AAC library (libfdk-aac). + +FDK-AAC is used in two distinct ways in Mixxx: + +1. **Runtime dynamic loading** (``EncoderFdkAac`` via ``QLibrary``) — the + shared library is bundled into the macOS/Windows packages but never + linked at build time. + +2. **Transitive static dependency of FFmpeg** — when FFmpeg's + ``libavcodec.a`` is built with ``--enable-libfdk-aac`` the FDK-AAC + symbols must be satisfied at final link time. ``FindFFmpeg.cmake`` + calls this module and attaches ``FdkAac::FdkAac`` as a transitive + dependency of the ``FFmpeg::avcodec`` imported target whenever + ``libavcodec`` is a static library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +``FdkAac::FdkAac`` + The FDK-AAC library. + +Result Variables +^^^^^^^^^^^^^^^^ + +``FdkAac_FOUND`` + True if the system has the FDK-AAC library. +``FdkAac_INCLUDE_DIRS`` + Include directories needed to use FDK-AAC (may be empty when headers + are absent — only required when compiling against FDK-AAC directly). +``FdkAac_DLL`` + (Windows only) Full path to ``fdk-aac.dll``, suitable for install(). + +Cache Variables +^^^^^^^^^^^^^^^ + +``FdkAac_INCLUDE_DIR`` + The directory containing ``fdk-aac/aacenc_lib.h`` (optional). +``FdkAac_LIBRARY`` + The FDK-AAC link library (``.dylib`` / ``.so`` / ``.a`` / ``.lib``). +``FdkAac_DLL`` + (Windows only) Path to ``fdk-aac.dll``. + +#]=======================================================================] + +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_check_modules(PC_FdkAac QUIET fdk-aac) +endif() + +find_path( + FdkAac_INCLUDE_DIR + NAMES fdk-aac/aacenc_lib.h + HINTS ${PC_FdkAac_INCLUDE_DIRS} + DOC "FDK-AAC include directory (optional)" +) +mark_as_advanced(FdkAac_INCLUDE_DIR) + +find_library( + FdkAac_LIBRARY + NAMES fdk-aac libfdk-aac + HINTS ${PC_FdkAac_LIBRARY_DIRS} + DOC "FDK-AAC link library" +) +mark_as_advanced(FdkAac_LIBRARY) + +# On Windows find_library() returns the .lib import library. +# Locate the companion .dll separately so callers can install it. +if(WIN32) + find_file( + FdkAac_DLL + NAMES fdk-aac.dll + HINTS ${PC_FdkAac_LIBRARY_DIRS} + PATH_SUFFIXES ${CMAKE_INSTALL_BINDIR} bin + DOC "FDK-AAC DLL (Windows runtime)" + ) + mark_as_advanced(FdkAac_DLL) +endif() + +include(FindPackageHandleStandardArgs) +# Only the library is required. Headers are optional: on Android the library +# is a transitive static dep of libavcodec.a and no Mixxx code includes +# FDK-AAC headers directly, so the include dir may legitimately be absent. +find_package_handle_standard_args( + FdkAac + REQUIRED_VARS FdkAac_LIBRARY + VERSION_VAR PC_FdkAac_VERSION +) + +if(FdkAac_FOUND AND NOT TARGET FdkAac::FdkAac) + # FdkAac_INCLUDE_DIRS: empty string when headers not present — callers must + # not assume non-empty (Android links transitively; no headers needed). + set(FdkAac_INCLUDE_DIRS "${FdkAac_INCLUDE_DIR}") + + add_library(FdkAac::FdkAac UNKNOWN IMPORTED) + set_target_properties( + FdkAac::FdkAac + PROPERTIES IMPORTED_LOCATION "${FdkAac_LIBRARY}" + ) + if(FdkAac_INCLUDE_DIR) + set_target_properties( + FdkAac::FdkAac + PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${FdkAac_INCLUDE_DIR}" + ) + endif() + if(WIN32 AND FdkAac_DLL) + # Expose the DLL as the runtime artifact; the .lib is the link artifact. + set_target_properties( + FdkAac::FdkAac + PROPERTIES + IMPORTED_LOCATION "${FdkAac_DLL}" + IMPORTED_IMPLIB "${FdkAac_LIBRARY}" + ) + endif() +endif() diff --git a/src/test/taglibtest.cpp b/src/test/taglibtest.cpp index 5dbe57a7e7c..b32b735e3d8 100644 --- a/src/test/taglibtest.cpp +++ b/src/test/taglibtest.cpp @@ -91,7 +91,9 @@ TEST_F(TagLibTest, WriteID3v2TagViaLink) { auto linkFileInfoBefore = QFileInfo(linkFileName); EXPECT_TRUE(linkFileInfoBefore.exists()); EXPECT_TRUE(linkFileInfoBefore.isSymLink()); - EXPECT_EQ(linkFileInfoBefore.canonicalFilePath().toStdString(), tmpFileName.toStdString()); + auto canonicalTmpFileName = QFileInfo(tmpFileName).canonicalFilePath(); + EXPECT_EQ(linkFileInfoBefore.canonicalFilePath().toStdString(), + canonicalTmpFileName.toStdString()); // Verify that the file has no tags { @@ -127,7 +129,8 @@ TEST_F(TagLibTest, WriteID3v2TagViaLink) { auto linkFileInfoAfter = QFileInfo(linkFileName); EXPECT_TRUE(linkFileInfoAfter.exists()); - EXPECT_EQ(linkFileInfoAfter.canonicalFilePath().toStdString(), tmpFileName.toStdString()); + EXPECT_EQ(linkFileInfoAfter.canonicalFilePath().toStdString(), + canonicalTmpFileName.toStdString()); EXPECT_TRUE(linkFileInfoAfter.isSymLink()); } #endif diff --git a/tools/android_buildenv.sh b/tools/android_buildenv.sh index 98e56bf05db..9eff21db9d7 100755 --- a/tools/android_buildenv.sh +++ b/tools/android_buildenv.sh @@ -31,13 +31,15 @@ HOST_ARCH=$(uname -m) # One of x86_64, arm64, i386, ppc or ppc64 if [ "$HOST_ARCH" == "x86_64" ]; then if [ -n "${BUILDENV_RELEASE}" ]; then - echo "ERROR: No release VCPKG for Android yet!" - exit 1 + VCPKG_TARGET_TRIPLET="arm64-android-rel" + BUILDENV_BRANCH="2.7-rel" + BUILDENV_NAME="mixxx-deps-2.7-arm64-android-rel-6d5a0074" + BUILDENV_SHA256="88eb436f26ab8879a48d509470b63fde679a142ada1748a051980f120d211035" else VCPKG_TARGET_TRIPLET="arm64-android" BUILDENV_BRANCH="2.7" - BUILDENV_NAME="mixxx-deps-2.7-arm64-android-458eeaf4" - BUILDENV_SHA256="77ad7e5e0178bc62f22c458c8d6e0ee5e7482305f18f8099775aa794ac2745b4" + BUILDENV_NAME="mixxx-deps-2.7-arm64-android-5777af9b" + BUILDENV_SHA256="5f12ffc5356a7821f8aa78b976653debf29961ae1e75774eb4ea79e2a0afb356" fi else echo "ERROR: Unsupported architecture detected: $HOST_ARCH" diff --git a/tools/macos_buildenv.sh b/tools/macos_buildenv.sh index 007c1014a58..70c64e55bf7 100755 --- a/tools/macos_buildenv.sh +++ b/tools/macos_buildenv.sh @@ -33,39 +33,39 @@ if [ "$HOST_ARCH" = "x86_64" ]; then if [ -n "${BUILDENV_ARM64_CROSS}" ]; then if [ -n "${BUILDENV_RELEASE}" ]; then VCPKG_TARGET_TRIPLET="arm64-osx-min1100-release" - BUILDENV_BRANCH="2.6-rel" - BUILDENV_NAME="mixxx-deps-2.6-arm64-osx-cross-rel-f46c645" - BUILDENV_SHA256="191fc876dfaaa49854d5a113b4bfe8e35bfa7d7b58118b645f0d2f2830839e51" + BUILDENV_BRANCH="2.7-rel" + BUILDENV_NAME="mixxx-deps-2.7-arm64-osx-cross-rel-6d5a0074" + BUILDENV_SHA256="a9a1c81198b1c2df808550c9304793cb0f71a251e6e50ecc309c643b432cf1f0" else VCPKG_TARGET_TRIPLET="arm64-osx-min1100" - BUILDENV_BRANCH="2.6" - BUILDENV_NAME="mixxx-deps-2.6-arm64-osx-cross-aa78b5a" - BUILDENV_SHA256="75187939a0847c98dd9c0c64a0bb35f7e8878f2288ac2e22ab99635f598bdd9a" + BUILDENV_BRANCH="2.7" + BUILDENV_NAME="mixxx-deps-2.7-arm64-osx-cross-5777af9b" + BUILDENV_SHA256="92cb1fc581d9b9e1cff5810a2c55bbc7e19bc1b5127cc4b542e62d886cdfcbe4" fi else if [ -n "${BUILDENV_RELEASE}" ]; then VCPKG_TARGET_TRIPLET="x64-osx-min1100-release" - BUILDENV_BRANCH="2.6-rel" - BUILDENV_NAME="mixxx-deps-2.6-x64-osx-rel-f46c645" - BUILDENV_SHA256="c28e64727743c126ea56c152a328a442e5bf8bb20705a2b232c1677ed290e0bb" + BUILDENV_BRANCH="2.7-rel" + BUILDENV_NAME="mixxx-deps-2.7-x64-osx-rel-6d5a0074" + BUILDENV_SHA256="d8033a4883f2d9dddea4ffb1a76984c1ecc82439d0aaa7ecac4550d52541b411" else VCPKG_TARGET_TRIPLET="x64-osx-min1100" - BUILDENV_BRANCH="2.6" - BUILDENV_NAME="mixxx-deps-2.6-x64-osx-aa78b5a" - BUILDENV_SHA256="ccb81981c4a45a65453531ac6a5d0d0ea18e0e1383b9c4fd09077125efce8391" + BUILDENV_BRANCH="2.7" + BUILDENV_NAME="mixxx-deps-2.7-x64-osx-5777af9b" + BUILDENV_SHA256="6f16c318c35ea43f2d6e5f18509f21ca0e9173f7a561b6467b3def600494c0d8" fi fi elif [ "$HOST_ARCH" = "arm64" ]; then if [ -n "${BUILDENV_RELEASE}" ]; then VCPKG_TARGET_TRIPLET="arm64-osx-min1100-release" - BUILDENV_BRANCH="2.6-rel" - BUILDENV_NAME="mixxx-deps-2.6-arm64-osx-rel-f46c645" - BUILDENV_SHA256="fd7873545ef564397f505c7f2611a0ab59091636cece7438cd10bf054fb7c950" + BUILDENV_BRANCH="2.7-rel" + BUILDENV_NAME="mixxx-deps-2.7-arm64-osx-rel-6d5a0074" + BUILDENV_SHA256="d5ad04e9273bf0437334b536bdaa81dde637e93feb1b0c18cd2f467d38ce8f33" else VCPKG_TARGET_TRIPLET="arm64-osx-min1100" - BUILDENV_BRANCH="2.6" - BUILDENV_NAME="mixxx-deps-2.6-arm64-osx-aa78b5a" - BUILDENV_SHA256="560b1572d65480a1773f70c320745f3fab8bb4a12380764d31d9547b38069401" + BUILDENV_BRANCH="2.7" + BUILDENV_NAME="mixxx-deps-2.7-arm64-osx-5777af9b" + BUILDENV_SHA256="a575e8d86a14d1e2888f5fd8b3a24c134b7bc6cbcd6805a3567a8ba492241db3" fi else echo "ERROR: Unsupported architecture detected: $HOST_ARCH" diff --git a/tools/update_vcpkg.py b/tools/update_vcpkg.py index 07d1c00c725..02325e11ade 100755 --- a/tools/update_vcpkg.py +++ b/tools/update_vcpkg.py @@ -73,12 +73,12 @@ "release_triplet": "arm64-osx-rel", "file": "tools/macos_buildenv.sh", }, - # { - # "host_os": "Linux", - # "triplet": "arm64-android", - # "release_triplet": "arm64-android-release", - # "file": "tools/android_buildenv.sh", - # }, + { + "host_os": "Linux", + "triplet": "arm64-android", + "release_triplet": "arm64-android-rel", + "file": "tools/android_buildenv.sh", + }, # { # "host_os": "Linux", # "triplet": "x64-linux", diff --git a/tools/windows_buildenv.bat b/tools/windows_buildenv.bat index 4580118dc39..a42c727b64e 100644 --- a/tools/windows_buildenv.bat +++ b/tools/windows_buildenv.bat @@ -34,27 +34,27 @@ IF NOT DEFINED INSTALL_ROOT ( IF /I "%PLATFORM%"=="arm64" ( IF DEFINED BUILDENV_RELEASE ( - SET BUILDENV_BRANCH=2.6-rel + SET BUILDENV_BRANCH=2.7-rel SET VCPKG_TARGET_TRIPLET=arm64-windows-release - SET BUILDENV_NAME=mixxx-deps-2.6-arm64-windows-rel-f46c645 - SET BUILDENV_SHA256=9492dac4bab0f14a48aa00ee1fdbc3c668893eb6b5f13c7442f7fc6ca5ee3145 + SET BUILDENV_NAME=mixxx-deps-2.7-arm64-windows-rel-6d5a0074 + SET BUILDENV_SHA256=43354581fc4d28529f8341dcf22b8191b8bc79368e5a977bc0f6dca7a1dcab16 ) ELSE ( - SET BUILDENV_BRANCH=2.6 + SET BUILDENV_BRANCH=2.7 SET VCPKG_TARGET_TRIPLET=arm64-windows - SET BUILDENV_NAME=mixxx-deps-2.6-arm64-windows-aa78b5a - SET BUILDENV_SHA256=50fd23c4e64b530bca0389e93c9efcbe3d9695ec1274cbccc876e38b966d0726 + SET BUILDENV_NAME=mixxx-deps-2.7-arm64-windows-5777af9b + SET BUILDENV_SHA256=4804ab1004767e3890781efae7e4438bb0330a3a52764490880ef6eb6fb35cfc ) ) ELSE IF /I "%PLATFORM%"=="x64" ( IF DEFINED BUILDENV_RELEASE ( - SET BUILDENV_BRANCH=2.6-rel + SET BUILDENV_BRANCH=2.7-rel SET VCPKG_TARGET_TRIPLET=x64-windows-release - SET BUILDENV_NAME=mixxx-deps-2.6-x64-windows-rel-f46c645 - SET BUILDENV_SHA256=bab7e63f463168df88f6bc0677dd0bf0d160b138696ec5d56b387083033fe2e5 + SET BUILDENV_NAME=mixxx-deps-2.7-x64-windows-rel-6d5a0074 + SET BUILDENV_SHA256=f57f37130e2fb206382cc89973ed62907e773b99de94af658bbef13379e1cc0f ) ELSE ( - SET BUILDENV_BRANCH=2.6 + SET BUILDENV_BRANCH=2.7 SET VCPKG_TARGET_TRIPLET=x64-windows - SET BUILDENV_NAME=mixxx-deps-2.6-x64-windows-aa78b5a - SET BUILDENV_SHA256=2628755773bed4e25233f9b9951c363ccebac23ca917ea91e9a93c70428b6648 + SET BUILDENV_NAME=mixxx-deps-2.7-x64-windows-5777af9b + SET BUILDENV_SHA256=43ae7072a341417da0abb5fc5d893d1ccf38db0f73dd9e1fbd3d402f2d9deecc ) ) ELSE ( ECHO ^ERROR: Unsupported PLATFORM: %PLATFORM%