Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/build-ffmpeg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,42 @@ jobs:
with:
name: output-${{ matrix.os }}
path: output/

cross-build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ "ubuntu-24.04" ]
build: [ "manylinux_", "musllinux_" ]
# arch: [ "loongarch64", "ppc64le", "riscv64", "s390x" ]
arch: [ "ppc64le" ]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- uses: docker/setup-qemu-action@v3
- name: Build FFmpeg
env:
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_BEFORE_ALL_LINUX: ./scripts/install-static-clang.sh
CIBW_BEFORE_BUILD_LINUX: python scripts/build-ffmpeg.py /tmp/vendor --community
CIBW_BUILD: cp311-${{ matrix.build }}${{ matrix.arch }}
CIBW_ENVIRONMENT_LINUX: >
CC="/opt/clang/bin/clang"
CXX="/opt/clang/bin/clang++"
LDFLAGS="-fuse-ld=lld"
CIBW_ENVIRONMENT_PASS_LINUX: RUNNER_ARCH
CIBW_REPAIR_WHEEL_COMMAND_LINUX: LD_LIBRARY_PATH=/tmp/vendor/lib:$LD_LIBRARY_PATH auditwheel repair --exclude libmvec.so.1 --exclude libmvec-2.so --exclude libmvec.so --exclude libmvec -w {dest_dir} {wheel}
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: delvewheel repair --add-path C:\cibw\vendor\bin -w {dest_dir} {wheel}
CIBW_TEST_COMMAND: python -c "import dummy"
run: |
pip install cibuildwheel delvewheel
cibuildwheel --output-dir output
rm -f output/*.whl
- name: Upload FFmpeg
uses: actions/upload-artifact@v6
with:
name: output-${{ matrix.build }}${{ matrix.arch }}
path: output/
25 changes: 19 additions & 6 deletions scripts/build-ffmpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,19 @@ def download_tars(packages: list[Package]) -> None:
raise

def make_tarball_name() -> str:
isArm64 = platform.machine() in {"arm64", "aarch64"}
machine = platform.machine().lower()
isArm64 = machine in {"arm64", "aarch64"}

if sys.platform.startswith("win"):
return "ffmpeg-windows-aarch64" if isArm64 else "ffmpeg-windows-x86_64"
elif sys.platform.startswith("linux"):
if is_musllinux:
return "ffmpeg-musllinux-aarch64" if isArm64 else "ffmpeg-musllinux-x86_64"
else:
return "ffmpeg-manylinux-aarch64" if isArm64 else "ffmpeg-manylinux-x86_64"

elif sys.platform.startswith("darwin"):
return "ffmpeg-macos-arm64" if isArm64 else "ffmpeg-macos-x86_64"

elif sys.platform.startswith("linux"):
prefix = "ffmpeg-musllinux-" if is_musllinux else "ffmpeg-manylinux-"
return prefix + machine

else:
return "ffmpeg-unknown"

Expand Down Expand Up @@ -403,6 +405,17 @@ def main():
]
)

if plat == "Linux" and "RUNNER_ARCH" in os.environ:
ffmpeg_package.build_arguments.extend(
[
"--enable-cross-compile",
"--target-os=linux",
"--arch=" + platform.machine().lower(),
"--cc=/opt/clang/bin/clang",
"--cxx=/opt/clang/bin/clang++",
]
)

ffmpeg_package.build_arguments.extend(
[
"--disable-encoder=avui,dca,mlp,opus,s302m,sonic,sonic_ls,truehd,vorbis",
Expand Down
5 changes: 5 additions & 0 deletions scripts/cibuildpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ def _build_with_autoconf(self, package: Package, for_builder: bool) -> None:
configure_args += ["--target=x86_64-darwin20-gcc"]
elif platform.system() == "Windows":
configure_args += ["--target=x86_64-win64-gcc"]
elif platform.system() == "Linux":
if "RUNNER_ARCH" in os.environ:
prepend_env(env, "CFLAGS", "-pthread")
prepend_env(env, "CXXFLAGS", "-pthread")
prepend_env(env, "LDFLAGS", "-pthread")

if package.name == "ffmpeg" and platform.system() == "Windows":
prepend_env(env, "LDFLAGS", "-LC:/PROGRA~1/OpenSSL/lib")
Expand Down
90 changes: 90 additions & 0 deletions scripts/install-static-clang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/bash

# Stop at any error, show all commands
set -exuo pipefail

TOOLCHAIN_PATH=/opt/clang

# Download static-clang
DEFAULT_ARCH="$(uname -m)"
if [ "${STATIC_CLANG_ARCH:-}" == "" ]; then
STATIC_CLANG_ARCH="${RUNNER_ARCH:-${DEFAULT_ARCH}}"
fi
case "${STATIC_CLANG_ARCH}" in
ARM64|aarch64|arm64|arm64/*) GO_ARCH=arm64;;
ARM|armv7l|armv8l|arm|arm/v7) GO_ARCH=arm;; # assume arm/v7 for arm
X64|x86_64|amd64|amd64/*) GO_ARCH=amd64;;
X86|i686|386) GO_ARCH=386;;
ppc64le) GO_ARCH=ppc64le;;
riscv64) GO_ARCH=riscv64;;
s390x) GO_ARCH=s390x;;
*) echo "No static-clang toolchain for ${CLANG_ARCH}">2; exit 1;;
esac
STATIC_CLANG_VERSION=21.1.8.1
STATIC_CLANG_FILENAME="static-clang-linux-${GO_ARCH}.tar.xz"
STATIC_CLANG_URL="https://github.com/mayeut/static-clang-images/releases/download/v${STATIC_CLANG_VERSION}/${STATIC_CLANG_FILENAME}"
pushd /tmp
cat<<'EOF' | grep "${STATIC_CLANG_FILENAME}" > "${STATIC_CLANG_FILENAME}.sha256"
583980309e73fa753c0791e05deceac7cb06c5444956d61189f1d651941bcd8e static-clang-linux-386.tar.xz
f539f1fd24bcc07ecc220594022907865914236540091fbf189cb496a9a3751c static-clang-linux-amd64.tar.xz
d0c8b7fac4734cc8048fda3b1f33ccdf24d26f81a52df53348e5fa84ab4b203a static-clang-linux-arm.tar.xz
57fb9cf798b3a2c4b0f3c31c0b7fe3803b5319d2af075407e1aef0cd57882f65 static-clang-linux-arm64.tar.xz
5a2b296e9030d0320d9e4eac8859e5db0504cf1d4169981af233cb339292fa4c static-clang-linux-loong64.tar.xz
c8541b2d36f0fd8f13ddabe1292b6fb7550a742e76e0f1f70fb29fcee073be4a static-clang-linux-ppc64le.tar.xz
b311137f955b55139b02e8c1d7ec259628404a0563d136df7a817a33784bd2bf static-clang-linux-riscv64.tar.xz
de74fd8e5de244d36398684b2afa67add2311df6ccfa24f3c08a1d777ca814fa static-clang-linux-s390x.tar.xz
EOF
curl -fsSLO "${STATIC_CLANG_URL}"
sha256sum -c "${STATIC_CLANG_FILENAME}.sha256"
tar -C /opt -xf "${STATIC_CLANG_FILENAME}"
popd

# configure target triple
case "${AUDITWHEEL_POLICY}-${AUDITWHEEL_ARCH}" in
manylinux*-armv7l) TARGET_TRIPLE=armv7-unknown-linux-gnueabihf;;
musllinux*-armv7l) TARGET_TRIPLE=armv7-alpine-linux-musleabihf;;
manylinux*-ppc64le) TARGET_TRIPLE=powerpc64le-unknown-linux-gnu;;
musllinux*-ppc64le) TARGET_TRIPLE=powerpc64le-alpine-linux-musl;;
manylinux*-*) TARGET_TRIPLE=${AUDITWHEEL_ARCH}-unknown-linux-gnu;;
musllinux*-*) TARGET_TRIPLE=${AUDITWHEEL_ARCH}-alpine-linux-musl;;
esac
case "${AUDITWHEEL_POLICY}-${AUDITWHEEL_ARCH}" in
*-riscv64) M_ARCH="-march=rv64gc";;
*-x86_64) M_ARCH="-march=x86-64";;
*-armv7l) M_ARCH="-march=armv7a";;
manylinux*-i686) M_ARCH="-march=k8 -mtune=generic";; # same as gcc manylinux2014 / manylinux_2_28
musllinux*-i686) M_ARCH="-march=pentium-m -mtune=generic";; # same as gcc musllinux_1_2
esac
GCC_TRIPLE=$(gcc -dumpmachine)

cat<<EOF >"${TOOLCHAIN_PATH}/bin/${AUDITWHEEL_PLAT}.cfg"
-target ${TARGET_TRIPLE}
${M_ARCH:-}
--gcc-toolchain=${DEVTOOLSET_ROOTPATH:-}/usr
--gcc-triple=${GCC_TRIPLE}
EOF

cat<<EOF >"${TOOLCHAIN_PATH}/bin/clang.cfg"
@${AUDITWHEEL_PLAT}.cfg
EOF

cat<<EOF >"${TOOLCHAIN_PATH}/bin/clang++.cfg"
@${AUDITWHEEL_PLAT}.cfg
EOF

cat<<EOF >"${TOOLCHAIN_PATH}/bin/clang-cpp.cfg"
@${AUDITWHEEL_PLAT}.cfg
EOF

# override entrypoint to add the toolchain to PATH
mv /usr/local/bin/manylinux-entrypoint /usr/local/bin/manylinux-entrypoint-org
cat<<EOF >/usr/local/bin/manylinux-entrypoint
#!/bin/bash

set -eu

export PATH="${TOOLCHAIN_PATH}/bin:\${PATH}"
exec /usr/local/bin/manylinux-entrypoint-org "\$@"
EOF

chmod +x /usr/local/bin/manylinux-entrypoint