diff --git a/.github/actions/build-deps/action.yml b/.github/actions/build-deps/action.yml index 4762fb853a..64e0a8fed6 100644 --- a/.github/actions/build-deps/action.yml +++ b/.github/actions/build-deps/action.yml @@ -56,6 +56,10 @@ inputs: description: Commit of libx264 to build default: '31e19f92f00c7003fa115047ce50978bc98c3a0d' type: string + libvpx: + description: Version of libvpx to build + default: '1.14.1' + type: string ffmpeg: description: Version of ffmpeg to build default: '7.0.1' @@ -117,13 +121,14 @@ runs: - uses: ./.github/actions/build-and-cache with: name: ffmpeg dependencies - cache_key: ffmpeg-${{ inputs.cache_key }}-${{ inputs.libx264 }}-${{ inputs.ffmpeg }} + cache_key: ffmpeg-${{ inputs.cache_key }}-${{ inputs.libx264 }}-${{ inputs.libvpx }}-${{ inputs.ffmpeg }} path: ${{ inputs.path }}/ffmpeg pre_build: ${{ inputs.ffmpeg_pre_build }} build: > cmake -DBUILD_TYPE=${{ inputs.build_type }} "-DLIBX264=${{ inputs.libx264 }}" + "-DLIBVPX=${{ inputs.libvpx }}" "-DFFMPEG=${{ inputs.ffmpeg }}" "-DCMAKE_PREFIX_PATH=${{ github.workspace }}/${{ inputs.path }}/qt" "-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/${{ inputs.path }}/ffmpeg" diff --git a/.github/scripts/build-ffmpeg.cmake b/.github/scripts/build-ffmpeg.cmake index e6c61b002b..11329b321f 100644 --- a/.github/scripts/build-ffmpeg.cmake +++ b/.github/scripts/build-ffmpeg.cmake @@ -8,6 +8,8 @@ list(APPEND CMAKE_MODULE_PATH set(LIBX264 "31e19f92f00c7003fa115047ce50978bc98c3a0d" CACHE STRING "The commit of libx264 to build") +set(LIBVPX "1.14.1" CACHE STRING + "The version of libvpx to build") set(FFMPEG "7.0.1" CACHE STRING "The version of ffmpeg to build") option(KEEP_ARCHIVES "Keep downloaded archives instead of deleting them" OFF) @@ -18,6 +20,105 @@ set(TARGET_ARCH "x86_64" CACHE STRING include(BuildDependency) +if(LIBVPX) + set(libvpx_configure_args + --disable-debug + --disable-debug-libs + --disable-dependency-tracking + --disable-docs + --disable-examples + --disable-tools + --disable-unit-tests + --disable-vp8-decoder + --disable-vp9 + --enable-pic + --enable-vp8-encoder + ) + + if(APPLE) + if(TARGET_ARCH STREQUAL "arm64") + list(PREPEND libvpx_configure_args --target=arm64-darwin20-gcc) + elseif(TARGET_ARCH STREQUAL "x86_64") + list(PREPEND libvpx_configure_args --target=x86_64-darwin20-gcc) + else() + message(FATAL_ERROR "Unhandled TARGET_ARCH '${TARGET_ARCH}'") + endif() + elseif(ANDROID) + if(TARGET_ARCH STREQUAL "arm32") + list(PREPEND libvpx_configure_args --target=armv7-android-gcc) + elseif(TARGET_ARCH STREQUAL "arm64") + list(PREPEND libvpx_configure_args --target=arm64-android-gcc) + else() + message(FATAL_ERROR "Unhandled TARGET_ARCH '${TARGET_ARCH}'") + endif() + elseif(WIN32) + if(TARGET_ARCH STREQUAL "x86") + list(PREPEND libvpx_configure_args --target=x86-win32-vs17) + set(libvpx_arch_dir Win32) + elseif(TARGET_ARCH STREQUAL "x86_64") + list(PREPEND libvpx_configure_args --target=x86_64-win64-vs17) + set(libvpx_arch_dir x64) + else() + message(FATAL_ERROR "Unhandled TARGET_ARCH '${TARGET_ARCH}'") + endif() + elseif(UNIX) + if(TARGET_ARCH STREQUAL "x86") + list(PREPEND libvpx_configure_args --target=x86-linux-gcc) + elseif(TARGET_ARCH STREQUAL "x86_64") + list(PREPEND libvpx_configure_args --target=x86_64-linux-gcc) + else() + message(FATAL_ERROR "Unhandled TARGET_ARCH '${TARGET_ARCH}'") + endif() + else() + message(FATAL_ERROR "Unknown platform") + endif() + + build_dependency(libvpx ${LIBVPX} ${BUILD_TYPE} + URL https://github.com/webmproject/libvpx/archive/refs/tags/v@version@.tar.gz + TARGET_ARCH "${TARGET_ARCH}" + VERSIONS + 1.14.1 + SHA384=42392dcae787ac556e66776a03bd064e0bb5795e7d763a6459edd2127e7ffae4aafe5c755d16ec4a4ab6e9785c27684c + ALL_PLATFORMS + AUTOMAKE + ASSIGN_PREFIX BROKEN_INSTALL + QUIRKS libvpx + ALL + ${libvpx_configure_args} + PATCHES + ALL + patches/libvpx_configure.diff + ) + + # libvpx doesn't generate a pkg-config file on Windows and puts the library + # into a nested directory that ffmpeg can't deal with. + if(WIN32) + file(RENAME + "${CMAKE_INSTALL_PREFIX}/lib/${libvpx_arch_dir}/vpxmd.lib" + "${CMAKE_INSTALL_PREFIX}/lib/vpxmd.lib" + ) + file(REMOVE "${CMAKE_INSTALL_PREFIX}/lib/${libvpx_arch_dir}") + file(TO_CMAKE_PATH "${CMAKE_INSTALL_PREFIX}" libvpx_prefix) + file(WRITE "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig/vpx.pc" + "prefix=${libvpx_prefix}\n" + "exec_prefix=\${prefix}\n" + "libdir=\${prefix}/lib\n" + "includedir=\${prefix}/include\n" + "\n" + "Name: vpx\n" + "Description: WebM Project VPx codec implementation\n" + "Version: ${LIBVPX}\n" + "Requires:\n" + "Conflicts:\n" + "Libs: -L\${libdir} -lvpxmd\n" + "Libs.private:\n" + # The -MD is bogus here, but ffmpeg fails to configure without it. + # We strip it back out later when fixing up the generated pc files. + "Cflags: -MD -I\${includedir}\n" + ) + endif() +endif() + if(LIBX264) build_dependency(x264 ${LIBX264} ${BUILD_TYPE} URL https://code.videolan.org/videolan/x264/-/archive/@version@/x264-@version@.tar.gz @@ -45,6 +146,11 @@ endif() if(FFMPEG) set(ffmpeg_configure_args + # This referes to warnings in configure, not build warnings. Warnings + # include pretty important stuff like not including a requested encoder, + # so we want this to fail in that case so we actually notice instead of + # being left with an incomplete build. + --fatal-warnings --enable-gpl --enable-version3 --disable-doc @@ -69,6 +175,7 @@ if(FFMPEG) --disable-xlib --disable-zlib --enable-libx264 + --enable-libvpx --disable-encoders --disable-decoders --disable-muxers @@ -81,7 +188,9 @@ if(FFMPEG) --disable-devices --disable-filters --enable-encoder=libx264 + --enable-encoder=libvpx_vp8 --enable-muxer=mp4 + --enable-muxer=webm ) if(ANDROID) @@ -119,7 +228,8 @@ if(FFMPEG) SHA384=25650331f409bf7efc09f0d859ce9a1a8e16fe429e4f9b2593743eb68e723b186559739e8b02aac83c6e5c96137fec7e ALL_PLATFORMS AUTOMAKE - ASSIGN_PREFIX FFMPEG_QUIRKS + ASSIGN_PREFIX + QUIRKS ffmpeg PKG_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig" ALL ${ffmpeg_configure_args} PATCHES diff --git a/.github/scripts/cmake/BuildDependency.cmake b/.github/scripts/cmake/BuildDependency.cmake index 99e8a0130e..32835fc18c 100644 --- a/.github/scripts/cmake/BuildDependency.cmake +++ b/.github/scripts/cmake/BuildDependency.cmake @@ -140,8 +140,8 @@ endfunction() function(_build_automake build_type target_bits source_dir) set(configure "${source_dir}/configure") cmake_parse_arguments( - PARSE_ARGV 2 ARG "ASSIGN_HOST;ASSIGN_PREFIX;BROKEN_INSTALL;FFMPEG_QUIRKS;NEEDS_VC_WIN_TARGET;WIN32_CC_CL" - "INSTALL_TARGET;PKG_CONFIG_PATH;WIN32_CONFIGURE_COMMAND;WIN32_MAKE_COMMAND" "MAKE_FLAGS") + PARSE_ARGV 2 ARG "ASSIGN_HOST;ASSIGN_PREFIX;BROKEN_INSTALL;NEEDS_VC_WIN_TARGET;WIN32_CC_CL" + "INSTALL_TARGET;PKG_CONFIG_PATH;QUIRKS;WIN32_CONFIGURE_COMMAND;WIN32_MAKE_COMMAND" "MAKE_FLAGS") _parse_flags("${build_type}" "${source_dir}" configure configure_flags env ${ARG_UNPARSED_ARGUMENTS}) if(NPROCS EQUAL 0 OR WIN32) @@ -154,6 +154,8 @@ function(_build_automake build_type target_bits source_dir) list(APPEND make_flags ${ARG_MAKE_FLAGS}) endif() + list(APPEND make_flags V=1) + list(APPEND env "MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") # https://developer.android.com/ndk/guides/other_build_systems#autoconf @@ -162,10 +164,18 @@ function(_build_automake build_type target_bits source_dir) android_env android_ffmpeg_flags abi "${CMAKE_ANDROID_NDK}" "${CMAKE_ANDROID_ARCH_ABI}" "${ANDROID_PLATFORM}") list(APPEND env ${android_env}) - # ffmpeg's build system looks like autoconf, but isn't actually - if(ARG_FFMPEG_QUIRKS) - list(APPEND configure_flags ${android_ffmpeg_flags}) - list(APPEND env "AS_FLAGS=--target=${abi}") + if(ARG_QUIRKS) + if(ARG_QUIRKS STREQUAL ffmpeg) + # ffmpeg's build system looks like autoconf, but isn't actually + list(APPEND configure_flags ${android_ffmpeg_flags}) + list(APPEND env "AS_FLAGS=--target=${abi}") + elseif(ARG_QUIRKS STREQUAL libvpx) + # Dito for libvpx, but a different kind of weird. We don't need + # to pass anything extra, it's alread taken care of by + # specifying a target platform in the caller. + else() + message(FATAL_ERROR "Unknown QUIRKS: '${ARG_QUIRKS}'") + endif() else() if(ARG_ASSIGN_HOST) list(APPEND configure_flags "--host=${abi}") diff --git a/.github/scripts/fix-win32-ffmpeg-pkg-config-files.pl b/.github/scripts/fix-win32-ffmpeg-pkg-config-files.pl index 952922cc70..4b55f3019f 100755 --- a/.github/scripts/fix-win32-ffmpeg-pkg-config-files.pl +++ b/.github/scripts/fix-win32-ffmpeg-pkg-config-files.pl @@ -35,6 +35,9 @@ sub fix_libs { for my $path (@paths) { print "Fixing $path\n"; my $content = slurp($path); + # Fix broken stuff that ffmpeg puts into the pc file. $content =~ s/^Libs:\s*(.+?)\s*$/fix_libs($1)/gme; + # Fix broken stuff *we* put into the pc file because ffmpeg is broken. + $content =~ s/^Cflags:\s*-MD\b\s*/CFlags: /g; spew($path, $content); } diff --git a/.github/scripts/patches/libvpx_configure.diff b/.github/scripts/patches/libvpx_configure.diff new file mode 100644 index 0000000000..c2fad24334 --- /dev/null +++ b/.github/scripts/patches/libvpx_configure.diff @@ -0,0 +1,114 @@ +Description: libvpx tries to run some shell scripts directly on Windows, which +in our CI just triggers the brilliant WSL shim binaries that do nothing but +moan about WSL not being installed. We have a working bash in our PATH though, +so we just run them with that instead. + +It also inexplicably builds both debug and release versions on Windows with no +way to turn it off, so we remove the debug configuration since that's a +complete waste of time. + +It also uses pkg-config's Libs.private attribute, which ffmpeg doesn't +understand, so we replace that with the regular Libs version. + +--- a/build/make/gen_msvs_vcxproj.sh ++++ b/build/make/gen_msvs_vcxproj.sh +@@ -90,7 +90,7 @@ + open_tag CustomBuild \ + Include="$f" + for plat in "${platforms[@]}"; do +- for cfg in Debug Release; do ++ for cfg in Release; do + tag_content Message "Assembling %(Filename)%(Extension)" \ + Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'" + tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \ +@@ -295,7 +295,7 @@ + open_tag ItemGroup \ + Label="ProjectConfigurations" + for plat in "${platforms[@]}"; do +- for config in Debug Release; do ++ for config in Release; do + open_tag ProjectConfiguration \ + Include="$config|$plat" + tag_content Configuration $config +@@ -338,7 +338,7 @@ + Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" + + for plat in "${platforms[@]}"; do +- for config in Release Debug; do ++ for config in Release; do + open_tag PropertyGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \ + Label="Configuration" +@@ -389,7 +389,7 @@ + + for plat in "${platforms[@]}"; do + plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'` +- for config in Debug Release; do ++ for config in Release; do + open_tag PropertyGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" + tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\" +@@ -407,7 +407,7 @@ + done + + for plat in "${platforms[@]}"; do +- for config in Debug Release; do ++ for config in Release; do + open_tag ItemDefinitionGroup \ + Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" + if [ "$name" == "vpx" ]; then +--- a/configure ++++ b/configure +@@ -749,7 +749,7 @@ + enable_feature solution + vs_version=${tgt_cc##vs} + VCPROJ_SFX=vcxproj +- gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh ++ gen_vcproj_cmd="bash ${source_path}/build/make/gen_msvs_vcxproj.sh" + enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror" + all_targets="${all_targets} solution" + INLINE="__inline" +--- a/libs.mk ++++ b/libs.mk +@@ -153,7 +153,6 @@ + INSTALL_MAPS += src/% $(SRC_PATH_BARE)/% + ifeq ($(CONFIG_MSVS),yes) + INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Release/%) +-INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/% $(p)/Debug/%) + endif + + CODEC_SRCS-yes += build/make/version.sh +@@ -227,7 +226,7 @@ + + vpx.def: $(call enabled,CODEC_EXPORTS) + @echo " [CREATE] $@" +- $(qexec)$(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\ ++ $(qexec)bash $(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\ + --name=vpx\ + --out=$@ $^ + CLEAN-OBJS += vpx.def +@@ -401,11 +400,10 @@ + $(qexec)echo 'Version: $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)' >> $@ + $(qexec)echo 'Requires:' >> $@ + $(qexec)echo 'Conflicts:' >> $@ +- $(qexec)echo 'Libs: -L$${libdir} -lvpx -lm' >> $@ + ifeq ($(HAVE_PTHREAD_H),yes) +- $(qexec)echo 'Libs.private: -lm -lpthread' >> $@ ++ $(qexec)echo 'Libs: -L$${libdir} -lvpx -lm -lptrhead' >> $@ + else +- $(qexec)echo 'Libs.private: -lm' >> $@ ++ $(qexec)echo 'Libs: -L$${libdir} -lvpx -lm' >> $@ + endif + $(qexec)echo 'Cflags: -I$${includedir}' >> $@ + INSTALL-LIBS-yes += $(LIBSUBDIR)/pkgconfig/vpx.pc +--- a/solution.mk ++++ b/solution.mk +@@ -15,7 +15,7 @@ + + vpx.sln: $(wildcard *.$(VCPROJ_SFX)) + @echo " [CREATE] $@" +- $(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \ ++ bash $(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \ + $(if $(filter vpx.$(VCPROJ_SFX),$^),$(VPX_RDEPS)) \ + --dep=test_libvpx:gtest \ + --ver=$(CONFIG_VS_VERSION)\ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 79597e15a2..7efd22245e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,7 +86,7 @@ jobs: ffmpeg_pre_build: > sudo apt-get update && sudo apt-get install --no-install-recommends - nasm + nasm yasm other_pre_build: > sudo apt-get update && sudo apt-get install --no-install-recommends @@ -257,6 +257,8 @@ jobs: choco install gperf jom winflexbison3 && New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe && New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe + ffmpeg_pre_build: > + choco install yasm # Copying files is a disgusting hack because windeployqt does not # search PATH to find DLLs and it gets confused by QtKeychain having # a Qt prefix and thinks it is part of Qt and tries to process it @@ -279,6 +281,8 @@ jobs: choco install gperf jom winflexbison3 && New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe && New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe + ffmpeg_pre_build: > + choco install yasm # Copying files is a disgusting hack because windeployqt does not # search PATH to find DLLs and it gets confused by QtKeychain having # a Qt prefix and thinks it is part of Qt and tries to process it @@ -299,6 +303,8 @@ jobs: choco install gperf jom winflexbison3 && New-Item -Path C:\ProgramData\Chocolatey\bin\flex.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_flex.exe && New-Item -Path C:\ProgramData\Chocolatey\bin\bison.exe -ItemType SymbolicLink -Value C:\ProgramData\Chocolatey\bin\win_bison.exe + ffmpeg_pre_build: > + choco install yasm # Copying files is a disgusting hack because windeployqt does not # search PATH to find DLLs and it gets confused by QtKeychain having # a Qt prefix and thinks it is part of Qt and tries to process it @@ -338,6 +344,11 @@ jobs: platform: win${{ matrix.arch == 'x86_64' && '64' || '32' }} if: runner.os == 'Windows' + - name: Install YASM for building libvpx in macOS + run: | + brew install yasm + if: runner.os == 'macOS' + - name: Install pkg-config for building and linking to ffmpeg in Windows run: | choco install pkgconfiglite