Files
ffmpeg-builder/lib/build.sh
2025-12-04 17:21:51 -06:00

924 lines
24 KiB
Bash

#!/usr/bin/env bash
set_compile_opts() {
test "$FB_COMPILE_OPTS_SET" == 1 && return 0
EXPORTED_ENV_NAMES=(
LDFLAGS
C_FLAGS
CXX_FLAGS
CPP_FLAGS
RUSTFLAGS
PKG_CONFIG_PATH
)
BUILD_ENV_NAMES=(
"${EXPORTED_ENV_NAMES[@]}"
CONFIGURE_FLAGS
MESON_FLAGS
CMAKE_FLAGS
FFMPEG_EXTRA_FLAGS
CARGO_CINSTALL_FLAGS
LTO_FLAG
LIB_SUFF
)
unset "${BUILD_ENV_NAMES[@]}"
export "${EXPORTED_ENV_NAMES[@]}"
# set job count for all builds
JOBS="$(nproc)"
# local vs system prefix
test "${PREFIX}" == 'local' && PREFIX="${IGN_DIR}/$(print_os)_sysroot"
# check if we need to handle PREFIX with sudo
local testfile=''
if [[ -d ${PREFIX} ]]; then
testfile="${PREFIX}/ffmpeg-build-testfile"
else
# try creating in parent path
testfile="$(bash_dirname "${PREFIX}")/ffmpeg-build-testfile"
fi
unset SUDO_MODIFY
if touch "${testfile}" 2>/dev/null; then
SUDO_MODIFY=''
else
SUDO_MODIFY="${SUDO}"
echo_warn "using ${SUDO}to install"
${SUDO_MODIFY} mkdir -p "${PREFIX}/bin/" || return 1
fi
test -f "${testfile}" && ${SUDO_MODIFY} rm "${testfile}"
test -d "${PREFIX}" || { ${SUDO_MODIFY} mkdir -p "${PREFIX}" || return 1; }
# set library/pkgconfig directory
LIBDIR="${PREFIX}/lib"
LDFLAGS=("-L${LIBDIR}")
# HACK rope in libm
if is_android; then
test -f "${LIBDIR}/libm.so" || ln -s /system/lib64/libm.so "${LIBDIR}/libm.so"
fi
# set prefix flags and basic flags
CONFIGURE_FLAGS+=(
"--prefix=${PREFIX}"
"--libdir=${LIBDIR}"
"--disable-debug"
)
MESON_FLAGS+=(
"--prefix" "${PREFIX}"
"--libdir" "lib"
"--bindir" "bin"
"--buildtype" "release"
)
CMAKE_FLAGS+=(
"-DCMAKE_PREFIX_PATH=${PREFIX}"
"-DCMAKE_INSTALL_PREFIX=${PREFIX}"
"-DCMAKE_INSTALL_LIBDIR=lib"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_C_COMPILER_LAUNCHER=ccache"
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
)
CARGO_CINSTALL_FLAGS=(
"--release"
"--prefix" "${PREFIX}"
"--libdir" "${LIBDIR}"
)
PKG_CONFIG_PATH="${LIBDIR}/pkgconfig"
# add prefix include
C_FLAGS+=("-I${PREFIX}/include")
# enabling link-time optimization
if [[ ${LTO} == 'ON' ]]; then
LTO_FLAG='-flto'
C_FLAGS+=("${LTO_FLAG}")
if ! is_darwin; then
CONFIGURE_FLAGS+=('--enable-lto')
fi
MESON_FLAGS+=("-Db_lto=true")
RUSTFLAGS+=("-C lto=yes" "-C inline-threshold=1000" "-C codegen-units=1")
else
LTO_FLAG=' '
MESON_FLAGS+=("-Db_lto=false")
RUSTFLAGS+=("-C lto=no")
fi
# setting optimization level
if [[ ${OPT} == '' ]]; then
OPT='0'
fi
C_FLAGS+=("-O${OPT}")
RUSTFLAGS+=("-C opt-level=${OPT}")
MESON_FLAGS+=("--optimization=${OPT}")
STATIC_LIB_SUFF='a'
# darwin has different suffix for dynamic libraries
if is_darwin; then
SHARED_LIB_SUFF='dylib'
else
SHARED_LIB_SUFF='so'
fi
# static/shared linking
if [[ ${STATIC} == 'ON' ]]; then
CONFIGURE_FLAGS+=(
'--enable-static'
'--disable-shared'
)
MESON_FLAGS+=('--default-library=static')
CMAKE_FLAGS+=(
"-DENABLE_STATIC=${STATIC}"
"-DENABLE_SHARED=OFF"
"-DBUILD_SHARED_LIBS=OFF"
)
RUSTFLAGS+=("-C target-feature=+crt-static")
FFMPEG_EXTRA_FLAGS+=("--pkg-config-flags=--static")
# darwin does not support static linkage
if ! is_darwin; then
LDFLAGS+=('-static')
CMAKE_FLAGS+=("-DCMAKE_EXE_LINKER_FLAGS=-static")
fi
FFMPEG_EXTRA_FLAGS+=(--extra-ldflags="${LDFLAGS[*]}")
# remove shared libraries for static builds
USE_LIB_SUFF="${STATIC_LIB_SUFF}"
DEL_LIB_SUFF="${SHARED_LIB_SUFF}"
else
FFMPEG_EXTRA_FLAGS+=(--extra-ldflags="${LDFLAGS[*]}")
LDFLAGS+=("-Wl,-rpath,${LIBDIR}" "-Wl,-rpath-link,${LIBDIR}")
CONFIGURE_FLAGS+=(
'--enable-shared'
'--disable-static'
)
CMAKE_FLAGS+=(
"-DENABLE_STATIC=${STATIC}"
"-DENABLE_SHARED=ON"
"-DBUILD_SHARED_LIBS=ON"
"-DCMAKE_INSTALL_RPATH=${LIBDIR}"
)
FFMPEG_EXTRA_FLAGS+=('--enable-rpath')
# remove static libraries for shared builds
USE_LIB_SUFF="${SHARED_LIB_SUFF}"
DEL_LIB_SUFF="${STATIC_LIB_SUFF}"
fi
# architecture/cpu compile flags
# arm prefers -mcpu over -march for native builds
# https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu
local arch_flags=()
if [[ ${HOSTTYPE} == "aarch64" && ${ARCH} == 'native' ]]; then
arch_flags+=("-mcpu=${ARCH}")
else
arch_flags+=("-march=${ARCH}")
fi
# can fail static builds with -fpic
# warning: too many GOT entries for -fpic, please recompile with -fPIC
C_FLAGS+=("${arch_flags[@]}" "-fPIC")
CXX_FLAGS=("${C_FLAGS[@]}")
CPP_FLAGS=("${C_FLAGS[@]}")
RUSTFLAGS+=("-C target-cpu=${ARCH}")
CMAKE_FLAGS+=("-DCMAKE_C_FLAGS=${C_FLAGS[*]}")
CMAKE_FLAGS+=("-DCMAKE_CXX_FLAGS=${CXX_FLAGS[*]}")
MESON_FLAGS+=("-Dc_args=${C_FLAGS[*]}" "-Dcpp_args=${CPP_FLAGS[*]}")
dump_arr CONFIGURE_FLAGS
dump_arr C_FLAGS
dump_arr RUSTFLAGS
dump_arr CARGO_CINSTALL_FLAGS
dump_arr CMAKE_FLAGS
dump_arr MESON_FLAGS
echo_info "PKG_CONFIG_PATH=${PKG_CONFIG_PATH}"
# extra ffmpeg flags
FFMPEG_EXTRA_FLAGS+=(
--extra-cflags="${C_FLAGS[*]}"
--extra-cxxflags="${CXX_FLAGS[*]}"
--pkg-config='pkg-config'
)
dump_arr FFMPEG_EXTRA_FLAGS
# shellcheck disable=SC2178
RUSTFLAGS="${RUSTFLAGS[*]}"
FB_COMPILE_OPTS_SET=1
echo
}
get_remote_head() {
local url="$1"
local remoteHEAD=''
IFS=$' \t' read -r remoteHEAD _ <<< \
"$(git ls-remote "${url}" HEAD)"
echo "${remoteHEAD}"
}
get_build_conf() {
local getBuild="${1}"
# name version file-extension url dep1,dep2
# shellcheck disable=SC2016
local BUILDS_CONF='
ffmpeg 8.0 tar.gz https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n${ver}.${ext}
libsvtav1_psy 3.0.2-B tar.gz https://github.com/BlueSwordM/svt-av1-psyex/archive/refs/tags/v${ver}.${ext} dovi_tool,hdr10plus_tool,cpuinfo
hdr10plus_tool 1.7.1 tar.gz https://github.com/quietvoid/hdr10plus_tool/archive/refs/tags/${ver}.${ext}
dovi_tool 2.3.1 tar.gz https://github.com/quietvoid/dovi_tool/archive/refs/tags/${ver}.${ext}
cpuinfo latest git https://github.com/pytorch/cpuinfo/
libsvtav1 3.1.2 tar.gz https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v${ver}/SVT-AV1-v${ver}.${ext}
librav1e 0.8.1 tar.gz https://github.com/xiph/rav1e/archive/refs/tags/v${ver}.${ext}
libaom 3.13.1 tar.gz https://storage.googleapis.com/aom-releases/libaom-${ver}.${ext}
libvmaf 3.0.0 tar.gz https://github.com/Netflix/vmaf/archive/refs/tags/v${ver}.${ext}
libopus 1.5.2 tar.gz https://github.com/xiph/opus/releases/download/v${ver}/opus-${ver}.${ext}
libdav1d 1.5.1 tar.xz http://downloads.videolan.org/videolan/dav1d/${ver}/dav1d-${ver}.${ext}
libx264 latest git https://code.videolan.org/videolan/x264.git
libmp3lame 3.100 tar.gz https://pilotfiber.dl.sourceforge.net/project/lame/lame/${ver}/lame-${ver}.${ext}
libwebp 1.6.0 tar.gz https://github.com/webmproject/libwebp/archive/refs/tags/v${ver}.${ext} libpng,libjpeg
libjpeg 3.0.3 tar.gz https://github.com/winlibs/libjpeg/archive/refs/tags/libjpeg-turbo-${ver}.${ext}
libpng 1.6.50 tar.gz https://github.com/pnggroup/libpng/archive/refs/tags/v${ver}.${ext} zlib
zlib 1.3.1 tar.gz https://github.com/madler/zlib/archive/refs/tags/v${ver}.${ext}
libplacebo 7.351.0 tar.gz https://github.com/haasn/libplacebo/archive/refs/tags/v${ver}.${ext} glslang,vulkan_loader,glad
glslang 16.0.0 tar.gz https://github.com/KhronosGroup/glslang/archive/refs/tags/${ver}.${ext} spirv_tools
spirv_tools 2025.4 tar.gz https://github.com/KhronosGroup/SPIRV-Tools/archive/refs/tags/v${ver}.${ext} spirv_headers
spirv_headers 1.4.328.1 tar.gz https://github.com/KhronosGroup/SPIRV-Headers/archive/refs/tags/vulkan-sdk-${ver}.${ext}
glad 2.0.8 tar.gz https://github.com/Dav1dde/glad/archive/refs/tags/v${ver}.${ext}
libx265 4.1 tar.gz https://bitbucket.org/multicoreware/x265_git/downloads/x265_${ver}.${ext} libnuma,cmake
libnuma 2.0.19 tar.gz https://github.com/numactl/numactl/archive/refs/tags/v${ver}.${ext}
cmake 3.31.8 tar.gz https://github.com/Kitware/CMake/archive/refs/tags/v${ver}.${ext}
'
local supported_builds=()
unset ver ext url deps extractedDir
while read -r line; do
test "${line}" == '' && continue
IFS=$' \t' read -r build ver ext url deps <<<"${line}"
supported_builds+=("${build}")
if [[ ${getBuild} != "${build}" ]]; then
build=''
continue
fi
break
done <<<"${BUILDS_CONF}"
if [[ ${getBuild} == 'supported' ]]; then
echo "${supported_builds[@]}"
return 0
fi
if [[ ${build} == '' ]]; then
echo_fail "build ${getBuild} is not supported"
return 1
fi
# url uses ver and extension
eval "url=\"$url\""
# set dependencies array
# shellcheck disable=SC2206
deps=(${deps//,/ })
# set version based off of remote head
# and set extracted directory
if [[ ${ext} == 'git' ]]; then
ver="$(get_remote_head "${url}")"
extractedDir="${BUILD_DIR}/${build}-${ext}"
else
extractedDir="${BUILD_DIR}/${build}-v${ver}"
fi
return 0
}
download_release() {
local basename="$(bash_basename "${extractedDir}")"
local download="${DL_DIR}/${basename}"
# remove other versions of a download
for alreadyDownloaded in "${DL_DIR}/${build}-"*; do
if line_contains "${alreadyDownloaded}" "${basename}"; then
continue
fi
if [[ ! -d ${alreadyDownloaded} && ! -f ${alreadyDownloaded} ]]; then
continue
fi
echo_warn "removing wrong version: ${alreadyDownloaded}"
rm -rf "${alreadyDownloaded}"
done
# remove other versions of a build
for alreadyBuilt in "${BUILD_DIR}/${build}-"*; do
if line_contains "${alreadyBuilt}" "${basename}"; then
continue
fi
test -d "${alreadyBuilt}" || continue
echo_warn "removing wrong version: ${extractedDir}"
rm -rf "${alreadyBuilt}"
done
# enabling a clean build
if [[ ${CLEAN} == 'ON' ]]; then
DO_CLEAN="rm -rf"
else
DO_CLEAN='void'
fi
# create new build dir for clean builds
test -d "${extractedDir}" &&
{ ${DO_CLEAN} "${extractedDir}" || return 1; }
if test "${ext}" != "git"; then
wgetOut="${download}.${ext}"
# download archive if not present
if ! test -f "${wgetOut}"; then
echo_info "downloading ${build}"
echo_if_fail wget "${url}" -O "${wgetOut}"
fi
# create new build directory
test -d "${extractedDir}" ||
{
mkdir "${extractedDir}"
tar -xf "${wgetOut}" \
--strip-components=1 \
--no-same-permissions \
-C "${extractedDir}"
}
else
# for git downloads
test -d "${download}" ||
git clone --recursive "${url}" "${download}" || return 1
(
cd "${download}" || exit 1
local localHEAD remoteHEAD
localHEAD="$(git rev-parse HEAD)"
remoteHEAD="$(get_remote_head "$(git config --get remote.origin.url)")"
if [[ ${localHEAD} != "${remoteHEAD}" ]]; then
git pull --ff-only
git submodule update --init --recursive
fi
localHEAD="$(git rev-parse HEAD)"
if [[ ${localHEAD} != "${remoteHEAD}" ]]; then
echo_exit "could not update git for ${build}"
fi
) || return 1
# create new build directory
test -d "${extractedDir}" ||
cp -r "${download}" "${extractedDir}" || return 1
fi
}
FB_FUNC_NAMES+=('do_build')
# shellcheck disable=SC2034
FB_FUNC_DESCS['do_build']='build a specific project'
# shellcheck disable=SC2034
FB_FUNC_COMPLETION['do_build']="$(get_build_conf supported)"
do_build() {
local build="${1:-''}"
get_build_conf "${build}" || return 1
download_release || return 1
set_compile_opts || return 1
for dep in "${deps[@]}"; do
do_build "${dep}" || return 1
done
get_build_conf "${build}" || return 1
download_release || return 1
# save the metadata for a build to skip re-building identical builds
local oldMetadataFile="${TMP_DIR}/${build}-old-metadata"
local newMetadataFile="${TMP_DIR}/${build}-new-metadata"
local ffmpegOldMetadataFile="${TMP_DIR}/ffmpeg-old-metadata"
# add build function, version, url, and top-level env to metadata
type "build_${build}" >"${newMetadataFile}"
echo "ver: ${ver}" >>"${newMetadataFile}"
echo "url: ${url}" >>"${newMetadataFile}"
for envName in "${BUILD_ENV_NAMES[@]}"; do
COLOR=OFF dump_arr "${envName}" >>"${newMetadataFile}"
done
# only ffmpeg cares about ENABLE and has special function
if [[ ${build} == 'ffmpeg' ]]; then
# shellcheck disable=SC2153
echo "ENABLE=${ENABLE}" >>"${newMetadataFile}"
type add_project_versioning_to_ffmpeg >>"${newMetadataFile}"
fi
# prepare build
pushd "${extractedDir}" >/dev/null || return 1
# check for any patches
for patch in "${PATCHES_DIR}/${build}"/*.patch; do
test -f "${patch}" || continue
echo_if_fail patch -p1 -i "${patch}" || return 1
echo "patch:${patch}" >>"${newMetadataFile}"
done
# rebuild if new metadata is different
local newMetadata="$(<"${newMetadataFile}")"
local oldMetadata=''
test -f "${oldMetadataFile}" && oldMetadata="$(<"${oldMetadataFile}")"
if [[ ${oldMetadata} != "${newMetadata}" || -n ${REQUIRES_REBUILD} ]]; then
echo_info -n "building ${build} "
# build in background
local timeBefore=${EPOCHSECONDS}
LOGNAME="${build}" echo_if_fail "build_${build}" &
local buildPid=$!
# start spinner
spinner &
local spinPid=$!
# get build return code
wait ${buildPid}
local retval=$?
# stop spinner
kill ${spinPid}
spinner reset
popd >/dev/null || return 1
test ${retval} -eq 0 || return ${retval}
echo_pass "built ${build} in $((EPOCHSECONDS - timeBefore)) seconds"
# set new to old for later builds
cp "${newMetadataFile}" "${oldMetadataFile}"
# force ffmpeg to rebuild since one of the libraries has changed
if [[ ${build} != 'ffmpeg' && -f ${ffmpegOldMetadataFile} ]]; then
rm "${ffmpegOldMetadataFile}"
fi
# indicate that build chain will require rebuild
REQUIRES_REBUILD=1
else
popd >/dev/null || return 1
echo_info "re-using identical previous build for ${build}"
fi
}
FB_FUNC_NAMES+=('build')
# shellcheck disable=SC2034
FB_FUNC_DESCS['build']='build ffmpeg with the desired configuration'
build() {
set_compile_opts || return 1
for build in ${ENABLE}; do
do_build "${build}" || return 1
# reset whether build chain requires a rebuild
unset REQUIRES_REBUILD
done
do_build ffmpeg || return 1
local ffmpegBin="${PREFIX}/bin/ffmpeg"
# run ffmpeg to show completion
"${ffmpegBin}" -version
# suggestion for path
hash -r
local ffmpeg="$(command -v ffmpeg 2>/dev/null)"
if [[ ${ffmpeg} != "${ffmpegBin}" ]]; then
echo
echo_warn "ffmpeg in path (${ffmpeg}) is not the built one (${ffmpegBin})"
echo_info "consider adding ${PREFIX}/bin to \$PATH"
echo "echo 'export PATH=\"${PREFIX}/bin:\$PATH\"' >> ~/.bashrc"
fi
package || return 1
return 0
}
# make sure the sysroot has the appropriate library type
# darwin will always link dynamically if a dylib is present
# so they must be remove for static builds
sanitize_sysroot_libs() {
# do nothing for windows
if is_windows; then return ; fi
local libs=("$@")
for lib in "${libs[@]}"; do
local libPath="${LIBDIR}/${lib}"
local useLib="${libPath}.${USE_LIB_SUFF}"
if [[ ! -f ${useLib} ]]; then
echo_fail "could not find ${useLib}, something is wrong"
return 1
fi
${SUDO_MODIFY} rm "${libPath}"*".${DEL_LIB_SUFF}"*
done
return 0
}
del_pkgconfig_gcc_s() {
# HACK PATCH
# remove '-lgcc_s' from pkgconfig for static builds
if [[ ${STATIC} == 'ON' ]]; then
local fname="$1"
local cfg="${PKG_CONFIG_PATH}/${fname}"
local newCfg="${TMP_DIR}/${fname}"
test -f "${cfg}" || return 1
local del='-lgcc_s'
test -f "${newCfg}" && rm "${newCfg}"
while read -r line; do
if line_contains "${line}" "${del}"; then
line="${line//${del} /}"
fi
echo "${line}" >>"${newCfg}"
done <"${cfg}"
# overwrite the pkgconfig
${SUDO_MODIFY} cp "${newCfg}" "${cfg}"
fi
}
### RUST ###
cargo_cbuild() {
cargo cinstall \
--destdir "${PWD}/local-install" \
"${CARGO_CINSTALL_FLAGS[@]}"
# cargo cinstall destdir prepends with entire prefix
# this breaks windows with msys path augmentation
# so recurse into directories until sysroot is there
cd ./local-install || return 1
local sysrootDir="$(bash_basename "${PREFIX}")"
while ! test -d "${sysrootDir}"; do
cd ./* || return 1
done
# final cd
cd "${sysrootDir}" || return 1
${SUDO_MODIFY} cp -r ./* "${PREFIX}/"
}
build_hdr10plus_tool() {
# build libhdr10plus
cd hdr10plus || return 1
cargo_cbuild || return 1
sanitize_sysroot_libs libhdr10plus-rs || return 1
}
build_dovi_tool() {
# build libdovi
cd dolby_vision || return 1
cargo_cbuild || return 1
sanitize_sysroot_libs libdovi || return 1
}
build_librav1e() {
cargo_cbuild || return 1
sanitize_sysroot_libs librav1e || return 1
del_pkgconfig_gcc_s rav1e.pc || return 1
}
### CMAKE ###
cmake_build() {
local addFlags=("$@")
# configure
cmake \
-B fb-build \
"${CMAKE_FLAGS[@]}" \
"${addFlags[@]}" || return 1
# build
cmake \
--build fb-build \
--config Release \
-j "${JOBS}" || return 1
# install
${SUDO_MODIFY} cmake \
--install fb-build || return 1
}
build_cpuinfo() {
cmake_build \
-DCPUINFO_BUILD_UNIT_TESTS=OFF \
-DCPUINFO_BUILD_MOCK_TESTS=OFF \
-DCPUINFO_BUILD_BENCHMARKS=OFF \
-DUSE_SYSTEM_LIBS=ON || return 1
sanitize_sysroot_libs libcpuinfo || return 1
}
build_libsvtav1() {
cmake_build \
-DENABLE_AVX512=ON \
-DBUILD_TESTING=OFF \
-DCOVERAGE=OFF || return 1
sanitize_sysroot_libs libSvtAv1Enc || return 1
}
build_libsvtav1_psy() {
cmake_build \
-DBUILD_TESTING=OFF \
-DENABLE_AVX512=ON \
-DCOVERAGE=OFF \
-DLIBDOVI_FOUND=1 \
-DLIBHDR10PLUS_RS_FOUND=1 || return 1
sanitize_sysroot_libs libSvtAv1Enc || return 1
}
build_libaom() {
cmake_build \
-DENABLE_TESTS=OFF || return 1
sanitize_sysroot_libs libaom || return 1
}
build_libopus() {
cmake_build || return 1
sanitize_sysroot_libs libopus || return 1
}
build_libwebp() {
cmake_build || return 1
sanitize_sysroot_libs libwebp libsharpyuv || return 1
}
build_libjpeg() {
cmake_build || return 1
sanitize_sysroot_libs libjpeg libturbojpeg || return 1
}
build_libpng() {
cmake_build \
-DPNG_TESTS=OFF \
-DPNG_TOOLS=OFF || return 1
sanitize_sysroot_libs libpng || return 1
}
build_zlib() {
cmake_build \
-DZLIB_BUILD_EXAMPLES=OFF || return 1
sanitize_sysroot_libs libz || return 1
}
build_glslang() {
cmake_build \
-DALLOW_EXTERNAL_SPIRV_TOOLS=ON || return 1
sanitize_sysroot_libs libglslang || return 1
}
build_spirv_tools() {
cmake_build \
-DSPIRV-Headers_SOURCE_DIR="${PREFIX}" \
-DSPIRV_WERROR=OFF \
-DSPIRV_SKIP_TESTS=ON \
-G Ninja || return 1
}
build_spirv_headers() {
cmake_build \
-G Ninja || return 1
}
# libx265 does not support cmake >= 4
build_cmake() {
local cmakeVersion verMajor
# don't need to build if system version is below 4
IFS=$' \t' read -r _ _ cmakeVersion <<<"$(cmake --version)"
IFS='.' read -r verMajor _ _ <<<"${cmakeVersion}"
if [[ ${verMajor} -lt 4 ]]; then
return 0
fi
# don't need to rebuild if already built
local cmake="${PREFIX}/bin/cmake"
if [[ -f ${cmake} ]]; then
IFS=$' \t' read -r _ _ cmakeVersion <<<"$("${cmake}" --version)"
IFS='.' read -r verMajor _ _ <<<"${cmakeVersion}"
if [[ ${verMajor} -lt 4 ]]; then
return 0
fi
fi
cmake \
-DCMAKE_PREFIX_PATH="${PREFIX}" \
-DCMAKE_INSTALL_PREFIX="${PREFIX}" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=Release || return 1
ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1
}
build_libx265() {
PATH="${PREFIX}/bin:${PATH}" cmake_build \
-G "Unix Makefiles" \
-DHIGH_BIT_DEPTH=ON \
-DENABLE_HDR10_PLUS=OFF \
-S source || return 1
sanitize_sysroot_libs libx265 || return 1
del_pkgconfig_gcc_s x265.pc || return 1
}
### MESON ###
meson_build() {
local addFlags=("$@")
meson setup \
"${MESON_FLAGS[@]}" \
"${addFlags[@]}" \
. fb-build || return 1
meson compile \
-C fb-build \
-j "${JOBS}" || return 1
${SUDO_MODIFY} meson install \
-C fb-build || return 1
}
build_libdav1d() {
local enableAsm=true
# arm64 will fail the build at 0 optimization
if [[ "${HOSTTYPE}:${OPT}" == "aarch64:0" ]]; then
enableAsm=false
fi
meson_build \
-D enable_asm=${enableAsm} || return 1
sanitize_sysroot_libs libdav1d || return 1
}
build_libplacebo() {
# copy downloaded glad release as "submodule"
(
installDir="${PWD}/3rdparty/glad"
get_build_conf glad
CLEAN=OFF download_release
cd "${extractedDir}" || exit 1
cp -r ./* "${installDir}"
) || return 1
meson_build \
-D tests=false \
-D demos=false || return 1
sanitize_sysroot_libs libplacebo || return 1
}
build_libvmaf() {
cd libvmaf || return 1
python3 -m virtualenv .venv
(
source .venv/bin/activate
meson_build \
-D enable_float=true || exit 1
) || return 1
sanitize_sysroot_libs libvmaf || return 1
# HACK PATCH
# add '-lstdc++' to pkgconfig for static builds
if [[ ${STATIC} == 'ON' ]]; then
local fname='libvmaf.pc'
local cfg="${PKG_CONFIG_PATH}/${fname}"
local newCfg="${TMP_DIR}/${fname}"
test -f "${cfg}" || return 1
local search='Libs: '
test -f "${newCfg}" && rm "${newCfg}"
while read -r line; do
if line_contains "${line}" "${search}"; then
line+=" -lstdc++"
fi
echo "${line}" >>"${newCfg}"
done <"${cfg}"
# overwrite the pkgconfig
${SUDO_MODIFY} cp "${newCfg}" "${cfg}"
fi
}
### PYTHON ###
build_glad() {
true
}
### AUTOTOOLS ###
build_libx264() {
# libx264 does not support LTO
local configureFlags=()
for flag in "${CONFIGURE_FLAGS[@]}"; do
test "${flag}" == '--enable-lto' && continue
configureFlags+=("${flag}")
done
./configure \
"${configureFlags[@]}" \
--disable-cli || return 1
ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1
sanitize_sysroot_libs libx264 || return 1
}
build_libmp3lame() {
# https://sourceforge.net/p/lame/mailman/message/36081038/
if is_darwin; then
remove_line \
'include/libmp3lame.sym' \
'lame_init_old' || return 1
fi
./configure \
"${CONFIGURE_FLAGS[@]}" \
--enable-nasm || return 1
ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1
sanitize_sysroot_libs libmp3lame || return 1
}
build_libnuma() {
# darwin does not have numa
if is_darwin; then return 0; fi
if is_android; then return 0; fi
./autogen.sh || return 1
./configure \
"${CONFIGURE_FLAGS[@]}" || return 1
ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1
sanitize_sysroot_libs libnuma || return 1
}
add_project_versioning_to_ffmpeg() {
# embed this project's enables/versions
# into ffmpeg with FFMPEG_BUILDER_INFO
local FFMPEG_BUILDER_INFO=(
'' # pad with empty line
"ffmpeg-builder=$(git -C "${REPO_DIR}" rev-parse HEAD)"
)
for build in ${ENABLE}; do
get_build_conf "${build}" || return 1
# add build configuration info
FFMPEG_BUILDER_INFO+=("${build}=${ver}")
done
# and finally for ffmpeg itself
get_build_conf ffmpeg || return 1
FFMPEG_BUILDER_INFO+=("${build}=${ver}")
local fname='opt_common.c'
local optFile="fftools/${fname}"
if [[ ! -f ${optFile} ]]; then
echo_fail "could not find ${fname} to add project versioning"
fi
local searchFor='static void print_all_libs_info'
local foundUsageStart=0
local newOptFile="${TMP_DIR}/${fname}"
test -f "${newOptFile}" && rm "${newOptFile}"
while read -r line; do
# if we found the line previously, add the versioning
if [[ ${foundUsageStart} -eq 1 ]]; then
if line_starts_with "${line}" '}'; then
echo_info "found ${line} on ${lineNum}"
for info in "${FFMPEG_BUILDER_INFO[@]}"; do
local newline="av_log(NULL, AV_LOG_INFO, \"${info}\n\");"
echo "${newline}" >>"${newOptFile}"
lineNum=$((lineNum + 1))
done
newline="av_log(NULL, AV_LOG_INFO, \"\n\");"
echo "${newline}" >>"${newOptFile}"
foundUsageStart=0
fi
fi
# find the line we are searching for
if line_contains "${line}" "${searchFor}"; then
foundUsageStart=1
fi
# start building the new file
echo "${line}" >>"${newOptFile}"
done <"${optFile}"
cp "${newOptFile}" "${optFile}" || return 1
return 0
}
build_ffmpeg() {
add_project_versioning_to_ffmpeg || return 1
# libsvtav1_psy real name is libsvtav1
for enable in ${ENABLE}; do
test "${enable}" == 'libsvtav1_psy' && enable='libsvtav1'
CONFIGURE_FLAGS+=("--enable-${enable}")
done
# lto is broken on darwin for ffmpeg only
# https://trac.ffmpeg.org/ticket/11479
local ffmpegFlags=()
if is_darwin; then
for flag in "${CONFIGURE_FLAGS[@]}"; do
test "${flag}" == '--enable-lto' && continue
ffmpegFlags+=("${flag}")
done
for flag in "${FFMPEG_EXTRA_FLAGS[@]}"; do
ffmpegFlags+=("${flag// ${LTO_FLAG}/}")
done
else
ffmpegFlags=("${CONFIGURE_FLAGS[@]}" "${FFMPEG_EXTRA_FLAGS[@]}")
fi
./configure \
"${ffmpegFlags[@]}" \
--enable-gpl \
--enable-version3 \
--disable-htmlpages \
--disable-podpages \
--disable-txtpages \
--disable-ffplay \
--disable-autodetect \
--extra-version="${ver}" \
--enable-runtime-cpudetect || return 1
ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1
${SUDO_MODIFY} cp ff*_g "${PREFIX}/bin"
sanitize_sysroot_libs \
libavcodec libavdevice libavfilter libswscale \
libavformat libavutil libswresample || return 1
}