diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6679eb0221..063304cebe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,18 +12,12 @@ on: unix: default: true type: boolean - linux_static: - default: true - type: boolean - linux_arm: + linux: default: true type: boolean macos: default: true type: boolean - macos_legacy: - default: true - type: boolean windows: default: true type: boolean @@ -55,22 +49,14 @@ on: description: yt-dlp, yt-dlp.tar.gz default: true type: boolean - linux_static: - description: yt-dlp_linux - default: true - type: boolean - linux_arm: - description: yt-dlp_linux_aarch64, yt-dlp_linux_armv7l + linux: + description: yt-dlp_linux, yt-dlp_linux.zip, yt-dlp_linux_aarch64, yt-dlp_linux_aarch64.zip default: true type: boolean macos: description: yt-dlp_macos, yt-dlp_macos.zip default: true type: boolean - macos_legacy: - description: yt-dlp_macos_legacy - default: true - type: boolean windows: description: yt-dlp.exe, yt-dlp_win.zip default: true @@ -141,99 +127,51 @@ jobs: yt-dlp.tar.gz compression-level: 0 - linux_static: + linux: needs: process - if: inputs.linux_static - runs-on: ubuntu-latest + if: inputs.linux + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - exe: yt-dlp_linux + platform: x86_64 + runner: ubuntu-24.04 + - exe: yt-dlp_linux_aarch64 + platform: aarch64 + runner: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 - - name: Build static executable + - name: Build executable env: - channel: ${{ inputs.channel }} - origin: ${{ needs.process.outputs.origin }} - version: ${{ inputs.version }} + EXE_NAME: ${{ matrix.exe }} + CHANNEL: ${{ inputs.channel }} + ORIGIN: ${{ needs.process.outputs.origin }} + VERSION: ${{ inputs.version }} run: | mkdir ~/build cd bundle/docker - docker compose up --build static - sudo chown "${USER}:docker" ~/build/yt-dlp_linux + docker compose up --build linux_${{ matrix.platform }} + sudo chown "${USER}:docker" ~/build/${{ matrix.exe }} + sudo chown "${USER}:docker" ~/build/${{ matrix.exe }}.zip + chmod +x ~/build/${{ matrix.exe }} + ~/build/${{ matrix.exe }} --version - name: Verify --update-to if: vars.UPDATE_TO_VERIFICATION run: | - chmod +x ~/build/yt-dlp_linux - cp ~/build/yt-dlp_linux ~/build/yt-dlp_linux_downgraded - version="$(~/build/yt-dlp_linux --version)" - ~/build/yt-dlp_linux_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04 - downgraded_version="$(~/build/yt-dlp_linux_downgraded --version)" + cp ~/build/${{ matrix.exe }} ~/build/${{ matrix.exe }}_downgraded + version="$(~/build/${{ matrix.exe }} --version)" + ~/build/${{ matrix.exe }}_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04 + downgraded_version="$(~/build/${{ matrix.exe }}_downgraded --version)" [[ "$version" != "$downgraded_version" ]] - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: build-bin-${{ github.job }} + name: build-bin-${{ github.job }}_${{ matrix.platform }} path: | - ~/build/yt-dlp_linux - compression-level: 0 - - linux_arm: - needs: process - if: inputs.linux_arm - permissions: - contents: read - packages: write # for creating cache - runs-on: ubuntu-latest - strategy: - matrix: - architecture: - - armv7 - - aarch64 - - steps: - - uses: actions/checkout@v4 - with: - path: ./repo - - name: Virtualized Install, Prepare & Build - uses: yt-dlp/run-on-arch-action@v3 - with: - # Ref: https://github.com/uraimo/run-on-arch-action/issues/55 - env: | - GITHUB_WORKFLOW: build - githubToken: ${{ github.token }} # To cache image - arch: ${{ matrix.architecture }} - distro: ubuntu20.04 # Standalone executable should be built on minimum supported OS - dockerRunArgs: --volume "${PWD}/repo:/repo" - install: | # Installing Python 3.10 from the Deadsnakes repo raises errors - apt update - apt -y install zlib1g-dev libffi-dev python3.9 python3.9-dev python3.9-distutils python3-pip \ - python3-secretstorage # Cannot build cryptography wheel in virtual armv7 environment - python3.9 -m pip install -U pip wheel 'setuptools>=71.0.2' - # XXX: Keep this in sync with pyproject.toml (it can't be accessed at this stage) and exclude secretstorage - python3.9 -m pip install -U Pyinstaller mutagen pycryptodomex brotli certifi cffi \ - 'requests>=2.32.2,<3' 'urllib3>=2.0.2,<3' 'websockets>=13.0' - - run: | - cd repo - python3.9 devscripts/install_deps.py -o --include build - python3.9 devscripts/install_deps.py --include pyinstaller # Cached versions may be out of date - python3.9 devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}" - python3.9 devscripts/make_lazy_extractors.py - python3.9 -m bundle.pyinstaller - - if ${{ vars.UPDATE_TO_VERIFICATION && 'true' || 'false' }}; then - arch="${{ (matrix.architecture == 'armv7' && 'armv7l') || matrix.architecture }}" - chmod +x ./dist/yt-dlp_linux_${arch} - cp ./dist/yt-dlp_linux_${arch} ./dist/yt-dlp_linux_${arch}_downgraded - version="$(./dist/yt-dlp_linux_${arch} --version)" - ./dist/yt-dlp_linux_${arch}_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04 - downgraded_version="$(./dist/yt-dlp_linux_${arch}_downgraded --version)" - [[ "$version" != "$downgraded_version" ]] - fi - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: build-bin-linux_${{ matrix.architecture }} - path: | # run-on-arch-action designates armv7l as armv7 - repo/dist/yt-dlp_linux_${{ (matrix.architecture == 'armv7' && 'armv7l') || matrix.architecture }} + ~/build/${{ matrix.exe }} + ~/build/${{ matrix.exe }}.zip compression-level: 0 macos: @@ -344,58 +282,6 @@ jobs: ~/yt-dlp-build-venv key: cache-reqs-${{ github.job }}-${{ github.ref }} - macos_legacy: - needs: process - if: inputs.macos_legacy - runs-on: macos-13 - - steps: - - uses: actions/checkout@v4 - - name: Install Python - # We need the official Python, because the GA ones only support newer macOS versions - env: - PYTHON_VERSION: 3.10.5 - MACOSX_DEPLOYMENT_TARGET: 10.9 # Used up by the Python build tools - run: | - # Hack to get the latest patch version. Uncomment if needed - #brew install python@3.10 - #export PYTHON_VERSION=$( $(brew --prefix)/opt/python@3.10/bin/python3 --version | cut -d ' ' -f 2 ) - curl "https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macos11.pkg" -o "python.pkg" - sudo installer -pkg python.pkg -target / - python3 --version - - name: Install Requirements - run: | - brew install coreutils - python3 devscripts/install_deps.py --user -o --include build - python3 devscripts/install_deps.py --user --include pyinstaller - - - name: Prepare - run: | - python3 devscripts/update-version.py -c "${{ inputs.channel }}" -r "${{ needs.process.outputs.origin }}" "${{ inputs.version }}" - python3 devscripts/make_lazy_extractors.py - - name: Build - run: | - python3 -m bundle.pyinstaller - mv dist/yt-dlp_macos dist/yt-dlp_macos_legacy - - - name: Verify --update-to - if: vars.UPDATE_TO_VERIFICATION - run: | - chmod +x ./dist/yt-dlp_macos_legacy - cp ./dist/yt-dlp_macos_legacy ./dist/yt-dlp_macos_legacy_downgraded - version="$(./dist/yt-dlp_macos_legacy --version)" - ./dist/yt-dlp_macos_legacy_downgraded -v --update-to yt-dlp/yt-dlp@2023.03.04 - downgraded_version="$(./dist/yt-dlp_macos_legacy_downgraded --version)" - [[ "$version" != "$downgraded_version" ]] - - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: build-bin-${{ github.job }} - path: | - dist/yt-dlp_macos_legacy - compression-level: 0 - windows: needs: process if: inputs.windows @@ -495,10 +381,8 @@ jobs: needs: - process - unix - - linux_static - - linux_arm + - linux - macos - - macos_legacy - windows - windows32 runs-on: ubuntu-latest @@ -532,6 +416,7 @@ jobs: lock 2024.10.22 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b lock 2024.10.22 (?!\w+_exe).+ Python 3\.8 lock 2024.10.22 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2) + lock 2025.09.01 darwin_legacy_exe .+ lockV2 yt-dlp/yt-dlp 2022.08.18.36 .+ Python 3\.6 lockV2 yt-dlp/yt-dlp 2023.11.16 (?!win_x86_exe).+ Python 3\.7 lockV2 yt-dlp/yt-dlp 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server) @@ -539,18 +424,21 @@ jobs: lockV2 yt-dlp/yt-dlp 2024.10.22 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b lockV2 yt-dlp/yt-dlp 2024.10.22 (?!\w+_exe).+ Python 3\.8 lockV2 yt-dlp/yt-dlp 2024.10.22 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2) + lockV2 yt-dlp/yt-dlp 2025.09.01 darwin_legacy_exe .+ lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 (?!win_x86_exe).+ Python 3\.7 lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 win_x86_exe .+ Windows-(?:Vista|2008Server) lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 py2exe .+ lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 (?!\w+_exe).+ Python 3\.8 lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2) + lockV2 yt-dlp/yt-dlp-nightly-builds 2025.09.01.234000 darwin_legacy_exe .+ lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 (?!win_x86_exe).+ Python 3\.7 lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 win_x86_exe .+ Windows-(?:Vista|2008Server) lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.045052 py2exe .+ lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 linux_(?:armv7l|aarch64)_exe .+-glibc2\.(?:[12]?\d|30)\b lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 (?!\w+_exe).+ Python 3\.8 lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.060347 win(?:_x86)?_exe Python 3\.[78].+ Windows-(?:7-|2008ServerR2) + lockV2 yt-dlp/yt-dlp-master-builds 2025.09.01.000000 darwin_legacy_exe .+ EOF - name: Sign checksum files diff --git a/README.md b/README.md index 9b28147f2c..624ea19934 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,12 @@ #### Alternatives File|Description :---|:--- [yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows (Win8+) standalone x86 (32-bit) binary -[yt-dlp_linux](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux)|Linux standalone x64 binary -[yt-dlp_linux_armv7l](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l)|Linux standalone armv7l (32-bit) binary -[yt-dlp_linux_aarch64](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_aarch64)|Linux standalone aarch64 (64-bit) binary -[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged Windows executable (no auto-update) +[yt-dlp_linux](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux)|Linux (glibc 2.17+) standalone x86_64 binary +[yt-dlp_linux.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux.zip)|Unpackaged Linux (glibc 2.17+) x86_64 executable (no auto-update) +[yt-dlp_linux_aarch64](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_aarch64)|Linux (glibc 2.17+) standalone aarch64 binary +[yt-dlp_linux_aarch64.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_aarch64.zip)|Unpackaged Linux (glibc 2.17+) aarch64 executable (no auto-update) +[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged Windows (Win8+) executable (no auto-update) [yt-dlp_macos.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos.zip)|Unpackaged MacOS (10.15+) executable (no auto-update) -[yt-dlp_macos_legacy](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos_legacy)|MacOS (10.9+) standalone x64 executable #### Misc diff --git a/bundle/docker/compose.yml b/bundle/docker/compose.yml index 5f89ca6d09..30a28d6664 100644 --- a/bundle/docker/compose.yml +++ b/bundle/docker/compose.yml @@ -1,10 +1,31 @@ services: - static: - build: static + linux_x86_64: + build: + context: linux + platforms: + - "linux/amd64" + args: + BASEIMAGE: ghcr.io/bashonly/manylinux2014_x86_64_builds:latest environment: - channel: ${channel} - origin: ${origin} - version: ${version} + EXE_NAME: ${EXE_NAME} + CHANNEL: ${CHANNEL} + ORIGIN: ${ORIGIN} + VERSION: ${VERSION} + volumes: + - ~/build:/build + - ../..:/yt-dlp + linux_aarch64: + build: + context: linux + platforms: + - "linux/arm64" + args: + BASEIMAGE: ghcr.io/bashonly/manylinux2014_aarch64_builds:latest + environment: + EXE_NAME: ${EXE_NAME} + CHANNEL: ${CHANNEL} + ORIGIN: ${ORIGIN} + VERSION: ${VERSION} volumes: - ~/build:/build - ../..:/yt-dlp diff --git a/bundle/docker/linux/Dockerfile b/bundle/docker/linux/Dockerfile new file mode 100644 index 0000000000..d989390b05 --- /dev/null +++ b/bundle/docker/linux/Dockerfile @@ -0,0 +1,7 @@ +ARG BASEIMAGE=ghcr.io/bashonly/manylinux2014_x86_64_builds:latest + +FROM $BASEIMAGE AS base + +WORKDIR /yt-dlp +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT /entrypoint.sh diff --git a/bundle/docker/linux/entrypoint.sh b/bundle/docker/linux/entrypoint.sh new file mode 100755 index 0000000000..e230c5f8b1 --- /dev/null +++ b/bundle/docker/linux/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -exuo pipefail + +python3 -m venv ~/yt-dlp-build-venv +source ~/yt-dlp-build-venv/bin/activate +python3 -m devscripts.install_deps -o --include build +python3 -m devscripts.install_deps --include secretstorage --include curl-cffi --include pyinstaller +python3 -m devscripts.make_lazy_extractors +python3 devscripts/update-version.py -c "${CHANNEL}" -r "${ORIGIN}" "${VERSION}" +python3 -m bundle.pyinstaller --onedir +pushd "./dist/${EXE_NAME}" +python3 -m zipfile -c "/build/${EXE_NAME}.zip" ./ +popd +python3 -m bundle.pyinstaller +mv "./dist/${EXE_NAME}" /build/ diff --git a/bundle/docker/static/Dockerfile b/bundle/docker/static/Dockerfile deleted file mode 100644 index dae2dff3d8..0000000000 --- a/bundle/docker/static/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM alpine:3.19 as base - -RUN apk --update add --no-cache \ - build-base \ - python3 \ - pipx \ - ; - -RUN pipx install pyinstaller -# Requires above step to prepare the shared venv -RUN ~/.local/share/pipx/shared/bin/python -m pip install -U wheel -RUN apk --update add --no-cache \ - scons \ - patchelf \ - binutils \ - ; -RUN pipx install staticx - -WORKDIR /yt-dlp -COPY entrypoint.sh /entrypoint.sh -ENTRYPOINT /entrypoint.sh diff --git a/bundle/docker/static/entrypoint.sh b/bundle/docker/static/entrypoint.sh deleted file mode 100755 index 8049e68205..0000000000 --- a/bundle/docker/static/entrypoint.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/ash -set -e - -source ~/.local/share/pipx/venvs/pyinstaller/bin/activate -python -m devscripts.install_deps -o --include build -python -m devscripts.install_deps --include secretstorage --include curl-cffi -python -m devscripts.make_lazy_extractors -python devscripts/update-version.py -c "${channel}" -r "${origin}" "${version}" -python -m bundle.pyinstaller -deactivate - -source ~/.local/share/pipx/venvs/staticx/bin/activate -staticx /yt-dlp/dist/yt-dlp_linux /build/yt-dlp_linux -deactivate diff --git a/yt_dlp/update.py b/yt_dlp/update.py index ca69fbbada..6d66256e3b 100644 --- a/yt_dlp/update.py +++ b/yt_dlp/update.py @@ -58,27 +58,31 @@ def _get_variant_and_executable_path(): """@returns (variant, executable_path)""" if getattr(sys, 'frozen', False): path = sys.executable + # py2exe is unsupported but we should still correctly identify it for debugging purposes if not hasattr(sys, '_MEIPASS'): return 'py2exe', path - elif sys._MEIPASS == os.path.dirname(path): - return f'{sys.platform}_dir', path - elif sys.platform == 'darwin': + # We know it's a PyInstaller bundle, but is it "onedir" or "onefile"? + suffix = 'dir' if sys._MEIPASS == os.path.dirname(path) else 'exe' + if sys.platform == 'darwin': + # darwin_legacy_exe is no longer supported, but still identify it to block updates machine = '_legacy' if version_tuple(platform.mac_ver()[0]) < (10, 15) else '' - else: - machine = f'_{platform.machine().lower()}' - is_64bits = sys.maxsize > 2**32 - # Ref: https://en.wikipedia.org/wiki/Uname#Examples - if machine[1:] in ('x86', 'x86_64', 'amd64', 'i386', 'i686'): - machine = '_x86' if not is_64bits else '' - # platform.machine() on 32-bit raspbian OS may return 'aarch64', so check "64-bitness" - # See: https://github.com/yt-dlp/yt-dlp/issues/11813 - elif machine[1:] == 'aarch64' and not is_64bits: - machine = '_armv7l' - # sys.executable returns a /tmp/ path for staticx builds (linux_static) - # Ref: https://staticx.readthedocs.io/en/latest/usage.html#run-time-information - if static_exe_path := os.getenv('STATICX_PROG_PATH'): - path = static_exe_path - return f'{remove_end(sys.platform, "32")}{machine}_exe', path + return f'darwin{machine}_{suffix}', path + + machine = f'_{platform.machine().lower()}' + is_64bits = sys.maxsize > 2**32 + # Ref: https://en.wikipedia.org/wiki/Uname#Examples + if machine[1:] in ('x86', 'x86_64', 'amd64', 'i386', 'i686'): + machine = '_x86' if not is_64bits else '' + # platform.machine() on 32-bit raspbian OS may return 'aarch64', so check "64-bitness" + # See: https://github.com/yt-dlp/yt-dlp/issues/11813 + elif machine[1:] == 'aarch64' and not is_64bits: + machine = '_armv7l' + # sys.executable returns a /tmp/ path for staticx builds (linux_static) + # Ref: https://staticx.readthedocs.io/en/latest/usage.html#run-time-information + if static_exe_path := os.getenv('STATICX_PROG_PATH'): + path = static_exe_path + + return f'{remove_end(sys.platform, "32")}{machine}_{suffix}', path path = os.path.dirname(__file__) if isinstance(__loader__, zipimporter): @@ -111,10 +115,8 @@ def current_git_head(): 'win_exe': '.exe', 'win_x86_exe': '_x86.exe', 'darwin_exe': '_macos', - 'darwin_legacy_exe': '_macos_legacy', 'linux_exe': '_linux', 'linux_aarch64_exe': '_linux_aarch64', - 'linux_armv7l_exe': '_linux_armv7l', } _NON_UPDATEABLE_REASONS = { @@ -142,27 +144,6 @@ def _get_binary_name(): def _get_system_deprecation(): MIN_SUPPORTED, MIN_RECOMMENDED = (3, 9), (3, 10) - EXE_MSG_TMPL = ('Support for {} has been deprecated. ' - 'See https://github.com/yt-dlp/yt-dlp/{} for details.\n{}') - STOP_MSG = 'You may stop receiving updates on this version at any time!' - variant = detect_variant() - - # Temporary until macos_legacy executable builds are discontinued - if variant == 'darwin_legacy_exe': - return EXE_MSG_TMPL.format( - f'{variant} (the PyInstaller-bundled executable for macOS versions older than 10.15)', - 'issues/13856', STOP_MSG) - - # Temporary until linux_armv7l executable builds are discontinued - if variant == 'linux_armv7l_exe': - return EXE_MSG_TMPL.format( - f'{variant} (the PyInstaller-bundled executable for the Linux armv7l platform)', - 'issues/13976', STOP_MSG) - - # Temporary until linux_aarch64_exe is built with Python >=3.10 instead of Python 3.9 - if variant == 'linux_aarch64_exe': - return None - if sys.version_info > MIN_RECOMMENDED: return None