diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b35c35047..46a775b4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -114,6 +114,49 @@ jobs: git -C taps/ push + build_linux_arm: + permissions: + packages: write # for Creating cache + runs-on: ubuntu-latest + needs: prepare + strategy: + matrix: + architecture: + - armv7 + - aarch64 + + steps: + - uses: actions/checkout@v3 + with: + path: ./repo + - name: Virtualized Install, Prepare & Build + uses: yt-dlp/run-on-arch-action@v2 + with: + githubToken: ${{ github.token }} # To cache image + arch: ${{ matrix.architecture }} + distro: ubuntu18.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 python3.8 python3.8-dev python3.8-distutils python3-pip + python3.8 -m pip install -U pip setuptools wheel + # Cannot access requirements.txt from the repo directory at this stage + python3.8 -m pip install -U Pyinstaller mutagen pycryptodomex websockets brotli certifi + + run: | + cd repo + python3.8 -m pip install -U Pyinstaller -r requirements.txt # Cached version may be out of date + python3.8 devscripts/update-version.py ${{ needs.prepare.outputs.version_suffix }} + python3.8 devscripts/make_lazy_extractors.py + python3.8 pyinst.py + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + path: | # run-on-arch-action designates armv7l as armv7 + repo/dist/yt-dlp_linux_${{ (matrix.architecture == 'armv7' && 'armv7l') || matrix.architecture }} + + build_macos: runs-on: macos-11 needs: prepare @@ -194,8 +237,8 @@ jobs: python-version: '3.8' - name: Install Requirements run: | # Custom pyinstaller built with https://github.com/yt-dlp/pyinstaller-builds - python -m pip install --upgrade pip setuptools wheel py2exe - pip install "https://yt-dlp.github.io/Pyinstaller-Builds/x86_64/pyinstaller-5.3-py3-none-any.whl" -r requirements.txt + python -m pip install -U pip setuptools wheel py2exe + pip install -U "https://yt-dlp.github.io/Pyinstaller-Builds/x86_64/pyinstaller-5.3-py3-none-any.whl" -r requirements.txt - name: Prepare run: | @@ -230,8 +273,8 @@ jobs: architecture: 'x86' - name: Install Requirements run: | - python -m pip install --upgrade pip setuptools wheel - pip install "https://yt-dlp.github.io/Pyinstaller-Builds/i686/pyinstaller-5.3-py3-none-any.whl" -r requirements.txt + python -m pip install -U pip setuptools wheel + pip install -U "https://yt-dlp.github.io/Pyinstaller-Builds/i686/pyinstaller-5.3-py3-none-any.whl" -r requirements.txt - name: Prepare run: | @@ -252,7 +295,7 @@ jobs: permissions: contents: write # for action-gh-release runs-on: ubuntu-latest - needs: [prepare, build_unix, build_windows, build_windows32, build_macos, build_macos_legacy] + needs: [prepare, build_unix, build_linux_arm, build_windows, build_windows32, build_macos, build_macos_legacy] steps: - uses: actions/checkout@v3 @@ -279,6 +322,8 @@ jobs: sha256sum artifact/yt-dlp_macos | awk '{print $1 " yt-dlp_macos"}' >> SHA2-256SUMS sha256sum artifact/yt-dlp_macos.zip | awk '{print $1 " yt-dlp_macos.zip"}' >> SHA2-256SUMS sha256sum artifact/yt-dlp_macos_legacy | awk '{print $1 " yt-dlp_macos_legacy"}' >> SHA2-256SUMS + sha256sum artifact/yt-dlp_linux_armv7l | awk '{print $1 " yt-dlp_linux_armv7l"}' >> SHA2-256SUMS + sha256sum artifact/yt-dlp_linux_aarch64 | awk '{print $1 " yt-dlp_linux_aarch64"}' >> SHA2-256SUMS sha256sum artifact/dist/yt-dlp_linux | awk '{print $1 " yt-dlp_linux"}' >> SHA2-256SUMS sha256sum artifact/dist/yt-dlp_linux.zip | awk '{print $1 " yt-dlp_linux.zip"}' >> SHA2-256SUMS sha512sum artifact/yt-dlp | awk '{print $1 " yt-dlp"}' >> SHA2-512SUMS @@ -290,6 +335,8 @@ jobs: sha512sum artifact/yt-dlp_macos | awk '{print $1 " yt-dlp_macos"}' >> SHA2-512SUMS sha512sum artifact/yt-dlp_macos.zip | awk '{print $1 " yt-dlp_macos.zip"}' >> SHA2-512SUMS sha512sum artifact/yt-dlp_macos_legacy | awk '{print $1 " yt-dlp_macos_legacy"}' >> SHA2-512SUMS + sha512sum artifact/yt-dlp_linux_armv7l | awk '{print $1 " yt-dlp_linux_armv7l"}' >> SHA2-512SUMS + sha512sum artifact/yt-dlp_linux_aarch64 | awk '{print $1 " yt-dlp_linux_aarch64"}' >> SHA2-512SUMS sha512sum artifact/dist/yt-dlp_linux | awk '{print $1 " yt-dlp_linux"}' >> SHA2-512SUMS sha512sum artifact/dist/yt-dlp_linux.zip | awk '{print $1 " yt-dlp_linux.zip"}' >> SHA2-512SUMS @@ -322,6 +369,8 @@ jobs: artifact/yt-dlp_macos artifact/yt-dlp_macos.zip artifact/yt-dlp_macos_legacy + artifact/yt-dlp_linux_armv7l + artifact/yt-dlp_linux_aarch64 artifact/dist/yt-dlp_linux artifact/dist/yt-dlp_linux.zip _update_spec diff --git a/README.md b/README.md index e9ea99ebf..aac359ab9 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,8 @@ File|Description [yt-dlp_min.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_min.exe)|Windows (Win7 SP1+) standalone x64 binary built with `py2exe`
([Not recommended](#standalone-py2exe-builds-windows)) [yt-dlp_linux](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux)|Linux standalone x64 binary [yt-dlp_linux.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux.zip)|Unpackaged Linux executable (no auto-update) +[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_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 diff --git a/pyinst.py b/pyinst.py index 0b7c66a30..17c950563 100644 --- a/pyinst.py +++ b/pyinst.py @@ -12,9 +12,8 @@ from PyInstaller.__main__ import run as run_pyinstaller from devscripts.utils import read_version -OS_NAME, MACHINE, ARCH = sys.platform, platform.machine(), platform.architecture()[0][:2] -if MACHINE in ('x86_64', 'AMD64') or ('i' in MACHINE and '86' in MACHINE): - # NB: Windows x86 has MACHINE = AMD64 irrespective of bitness +OS_NAME, MACHINE, ARCH = sys.platform, platform.machine().lower(), platform.architecture()[0][:2] +if MACHINE in ('x86', 'x86_64', 'amd64', 'i386', 'i686'): MACHINE = 'x86' if ARCH == '32' else '' @@ -63,7 +62,7 @@ def exe(onedir): name = '_'.join(filter(None, ( 'yt-dlp', {'win32': '', 'darwin': 'macos'}.get(OS_NAME, OS_NAME), - MACHINE + MACHINE, ))) return name, ''.join(filter(None, ( 'dist/', diff --git a/yt_dlp/update.py b/yt_dlp/update.py index 70a1d6f7f..6208aad8a 100644 --- a/yt_dlp/update.py +++ b/yt_dlp/update.py @@ -15,6 +15,7 @@ from .utils import ( Popen, cached_method, deprecation_warning, + remove_end, shell_quote, system_identifier, traverse_obj, @@ -35,9 +36,14 @@ def _get_variant_and_executable_path(): return 'py2exe', path if sys._MEIPASS == os.path.dirname(path): return f'{sys.platform}_dir', path - if sys.platform == 'darwin' and version_tuple(platform.mac_ver()[0]) < (10, 15): - return 'darwin_legacy_exe', path - return f'{sys.platform}_exe', path + if sys.platform == 'darwin': + machine = '_legacy' if version_tuple(platform.mac_ver()[0]) < (10, 15) else '' + else: + machine = f'_{platform.machine().lower()}' + # Ref: https://en.wikipedia.org/wiki/Uname#Examples + if machine[1:] in ('x86', 'x86_64', 'amd64', 'i386', 'i686'): + machine = '_x86' if platform.architecture()[0][:2] == '32' else '' + return f'{remove_end(sys.platform, "32")}{machine}_exe', path path = os.path.dirname(__file__) if isinstance(__loader__, zipimporter): @@ -68,10 +74,13 @@ def current_git_head(): _FILE_SUFFIXES = { 'zip': '', 'py2exe': '_min.exe', - 'win32_exe': '.exe', + '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 = { @@ -161,10 +170,7 @@ class Updater: @functools.cached_property def release_name(self): """The release filename""" - label = _FILE_SUFFIXES[detect_variant()] - if label and platform.architecture()[0][:2] == '32': - label = f'_x86{label}' - return f'yt-dlp{label}' + return f'yt-dlp{_FILE_SUFFIXES[detect_variant()]}' @functools.cached_property def release_hash(self): diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py index b7e7cb7d7..4c44f4845 100644 --- a/yt_dlp/utils.py +++ b/yt_dlp/utils.py @@ -2006,9 +2006,10 @@ def system_identifier(): with contextlib.suppress(OSError): # We may not have access to the executable libc_ver = platform.libc_ver() - return 'Python %s (%s %s) - %s (%s%s)' % ( + return 'Python %s (%s %s %s) - %s (%s%s)' % ( platform.python_version(), python_implementation, + platform.machine(), platform.architecture()[0], platform.platform(), ssl.OPENSSL_VERSION,