Add Linux x64 FFmpeg native bundle
This commit is contained in:
65
native/age_movie_ffmpeg/bootstrap-linux-x64.sh
Executable file
65
native/age_movie_ffmpeg/bootstrap-linux-x64.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd -- "$script_dir/../.." && pwd)"
|
||||
destination="${1:-$repo_root/build/ffmpeg-sdk}"
|
||||
manifest="$script_dir/dependency-linux-x64.json"
|
||||
|
||||
manifest_value() {
|
||||
python3 -c 'import json, sys; print(json.load(open(sys.argv[1], encoding="utf-8"))[sys.argv[2]])' \
|
||||
"$manifest" "$1"
|
||||
}
|
||||
|
||||
for command in python3 curl sha256sum tar awk; do
|
||||
command -v "$command" >/dev/null 2>&1 || {
|
||||
echo "required command was not found: $command" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
archive="$(manifest_value archive)"
|
||||
url="$(manifest_value url)"
|
||||
expected_hash="$(manifest_value sha256)"
|
||||
expected_version="$(manifest_value ffmpeg_version)"
|
||||
archive_root="${archive%.tar.xz}"
|
||||
download_dir="$repo_root/build/downloads"
|
||||
archive_path="$download_dir/$archive"
|
||||
sdk_root="$destination/$archive_root"
|
||||
|
||||
mkdir -p -- "$download_dir" "$destination"
|
||||
if [[ ! -f "$archive_path" ]]; then
|
||||
curl --fail --location --retry 3 --output "$archive_path" "$url"
|
||||
fi
|
||||
|
||||
actual_hash="$(sha256sum "$archive_path" | awk '{ print $1 }')"
|
||||
if [[ "$actual_hash" != "$expected_hash" ]]; then
|
||||
echo "FFmpeg archive SHA-256 mismatch: expected $expected_hash, got $actual_hash" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$sdk_root" ]]; then
|
||||
tar -xJf "$archive_path" -C "$destination"
|
||||
fi
|
||||
|
||||
for required in \
|
||||
"$sdk_root/include/libavformat/avformat.h" \
|
||||
"$sdk_root/lib/libavformat.so" \
|
||||
"$sdk_root/bin/ffmpeg" \
|
||||
"$sdk_root/LICENSE.txt"; do
|
||||
if [[ ! -e "$required" ]]; then
|
||||
echo "FFmpeg SDK file was not found after extraction: $required" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
reported="$(LD_LIBRARY_PATH="$sdk_root/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" \
|
||||
"$sdk_root/bin/ffmpeg" -version)"
|
||||
reported="${reported%%$'\n'*}"
|
||||
version_without_date="${expected_version%-????????}"
|
||||
if [[ "$reported" != *"$version_without_date"* ]]; then
|
||||
echo "unexpected FFmpeg build: $reported" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$sdk_root"
|
||||
131
native/age_movie_ffmpeg/build-linux-x64.sh
Executable file
131
native/age_movie_ffmpeg/build-linux-x64.sh
Executable file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
||||
echo "usage: $0 <ffmpeg-sdk-root> [output-directory]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd -- "$script_dir/../.." && pwd)"
|
||||
sdk_root="$(cd -- "$1" && pwd)"
|
||||
output_directory_input="${2:-$repo_root/build/native/linux-x64}"
|
||||
mkdir -p -- "$output_directory_input"
|
||||
output_directory="$(cd -- "$output_directory_input" && pwd)"
|
||||
include_directory="$sdk_root/include"
|
||||
library_directory="$sdk_root/lib"
|
||||
shim="$output_directory/libage_movie_ffmpeg.so"
|
||||
manifest="$script_dir/dependency-linux-x64.json"
|
||||
|
||||
for command in cc readelf ldd python3 sort; do
|
||||
command -v "$command" >/dev/null 2>&1 || {
|
||||
echo "required command was not found: $command" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
for required in \
|
||||
"$include_directory/libavformat/avformat.h" \
|
||||
"$library_directory/libavformat.so" \
|
||||
"$library_directory/libavcodec.so" \
|
||||
"$library_directory/libavutil.so" \
|
||||
"$library_directory/libswscale.so" \
|
||||
"$library_directory/libswresample.so" \
|
||||
"$sdk_root/LICENSE.txt"; do
|
||||
if [[ ! -e "$required" ]]; then
|
||||
echo "missing FFmpeg SDK file: $required" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
cc \
|
||||
-std=c11 -fPIC -fvisibility=hidden -O2 -Wall -Wextra \
|
||||
-I "$include_directory" \
|
||||
-shared -Wl,-z,defs -Wl,-z,origin -Wl,--enable-new-dtags -Wl,-rpath,'$ORIGIN' \
|
||||
-o "$shim" "$script_dir/age_movie.c" \
|
||||
-L "$library_directory" \
|
||||
-lavformat -lavcodec -lavutil -lswscale -lswresample
|
||||
|
||||
runtime_libraries=(
|
||||
libavformat.so.62
|
||||
libavcodec.so.62
|
||||
libavutil.so.60
|
||||
libswscale.so.9
|
||||
libswresample.so.6
|
||||
)
|
||||
for runtime in "${runtime_libraries[@]}"; do
|
||||
source_library="$library_directory/$runtime"
|
||||
if [[ ! -e "$source_library" ]]; then
|
||||
echo "missing FFmpeg runtime library: $source_library" >&2
|
||||
exit 1
|
||||
fi
|
||||
cp --dereference -- "$source_library" "$output_directory/$runtime"
|
||||
done
|
||||
cp -- "$sdk_root/LICENSE.txt" "$output_directory/FFmpeg-LICENSE.txt"
|
||||
|
||||
expected_outputs=(libage_movie_ffmpeg.so "${runtime_libraries[@]}")
|
||||
shopt -s nullglob
|
||||
for existing in "$output_directory"/*.so*; do
|
||||
existing_name="$(basename -- "$existing")"
|
||||
expected=false
|
||||
for expected_name in "${expected_outputs[@]}"; do
|
||||
if [[ "$existing_name" == "$expected_name" ]]; then
|
||||
expected=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$expected" != true ]]; then
|
||||
echo "unexpected stale shared library in output directory: $existing" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! readelf -h "$shim" | grep -Eq 'Class:[[:space:]]+ELF64'; then
|
||||
echo "native movie shim is not an ELF64 binary: $shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! readelf -h "$shim" | grep -Eq 'Machine:[[:space:]]+Advanced Micro Devices X86-64'; then
|
||||
echo "native movie shim is not an x86-64 binary: $shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! readelf -d "$shim" | grep -Fq '$ORIGIN'; then
|
||||
echo "native movie shim does not have an \$ORIGIN runtime search path: $shim" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ldd_output="$(ldd "$shim")"
|
||||
if [[ "$ldd_output" == *"not found"* ]]; then
|
||||
printf '%s\n' "$ldd_output" >&2
|
||||
echo "native movie bundle has unresolved shared-library dependencies" >&2
|
||||
exit 1
|
||||
fi
|
||||
for runtime in "${runtime_libraries[@]}"; do
|
||||
resolution="$(printf '%s\n' "$ldd_output" | grep -F "$runtime =>" || true)"
|
||||
if [[ "$resolution" != *"=> $output_directory/$runtime "* ]]; then
|
||||
printf '%s\n' "$ldd_output" >&2
|
||||
echo "$runtime did not resolve from the bundle directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
minimum_glibc="$(python3 -c \
|
||||
'import json, sys; print(json.load(open(sys.argv[1], encoding="utf-8"))["minimum_glibc"])' \
|
||||
"$manifest")"
|
||||
versioned_outputs=("$shim")
|
||||
for runtime in "${runtime_libraries[@]}"; do
|
||||
versioned_outputs+=("$output_directory/$runtime")
|
||||
done
|
||||
highest_glibc="$(readelf --version-info "${versioned_outputs[@]}" \
|
||||
| grep -Eo 'GLIBC_[0-9]+(\.[0-9]+)*' | sort -Vu | tail -n 1 || true)"
|
||||
if [[ -z "$highest_glibc" ]]; then
|
||||
echo "could not determine the bundle's glibc symbol-version requirement" >&2
|
||||
exit 1
|
||||
fi
|
||||
highest_glibc="${highest_glibc#GLIBC_}"
|
||||
newest_glibc="$(printf '%s\n%s\n' "$minimum_glibc" "$highest_glibc" | sort -Vu | tail -n 1)"
|
||||
if [[ "$newest_glibc" != "$minimum_glibc" ]]; then
|
||||
echo "bundle requires glibc $highest_glibc, newer than the pinned $minimum_glibc baseline" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$shim"
|
||||
12
native/age_movie_ffmpeg/dependency-linux-x64.json
Normal file
12
native/age_movie_ffmpeg/dependency-linux-x64.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"provider": "BtbN/FFmpeg-Builds",
|
||||
"release_tag": "autobuild-2026-07-21-13-38",
|
||||
"archive": "ffmpeg-n8.1.2-29-g703dcc25b9-linux64-lgpl-shared-8.1.tar.xz",
|
||||
"url": "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2026-07-21-13-38/ffmpeg-n8.1.2-29-g703dcc25b9-linux64-lgpl-shared-8.1.tar.xz",
|
||||
"sha256": "d0026954f10d303d1fc6517ed6b2290c42323b3958f11baafb1b330dfc564b36",
|
||||
"ffmpeg_version": "n8.1.2-29-g703dcc25b9-20260721",
|
||||
"ffmpeg_commit": "703dcc25b9",
|
||||
"variant": "linux64 LGPL shared 8.1",
|
||||
"minimum_glibc": "2.28",
|
||||
"minimum_linux_kernel": "4.18"
|
||||
}
|
||||
Reference in New Issue
Block a user