mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-12-28 01:41:06 +00:00
[build] Allow building with py2exe (and misc fixes)
py2exe config is copied from youtube-dl Closes #1160
This commit is contained in:
parent
a1c3967307
commit
5d535b4a55
5 changed files with 100 additions and 47 deletions
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
@ -161,7 +161,7 @@ jobs:
|
|||
- name: Print version
|
||||
run: echo "${{ steps.bump_version.outputs.ytdlp_version }}"
|
||||
- name: Run PyInstaller Script
|
||||
run: python pyinst.py 64
|
||||
run: python pyinst.py
|
||||
- name: Upload yt-dlp.exe Windows binary
|
||||
id: upload-release-windows
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
@ -179,7 +179,7 @@ jobs:
|
|||
id: sha512_win
|
||||
run: echo "::set-output name=sha512_win::$((Get-FileHash dist\yt-dlp.exe -Algorithm SHA512).Hash.ToLower())"
|
||||
- name: Run PyInstaller Script with --onedir
|
||||
run: python pyinst.py 64 --onedir
|
||||
run: python pyinst.py --onedir
|
||||
- uses: papeloto/action-zip@v1
|
||||
with:
|
||||
files: ./dist/yt-dlp
|
||||
|
@ -227,7 +227,7 @@ jobs:
|
|||
- name: Print version
|
||||
run: echo "${{ steps.bump_version.outputs.ytdlp_version }}"
|
||||
- name: Run PyInstaller Script for 32 Bit
|
||||
run: python pyinst.py 32
|
||||
run: python pyinst.py
|
||||
- name: Upload Executable yt-dlp_x86.exe
|
||||
id: upload-release-windows32
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
|
13
pyinst.py
13
pyinst.py
|
@ -13,11 +13,18 @@
|
|||
)
|
||||
import PyInstaller.__main__
|
||||
|
||||
arch = sys.argv[1] if len(sys.argv) > 1 else platform.architecture()[0][:2]
|
||||
arch = platform.architecture()[0][:2]
|
||||
assert arch in ('32', '64')
|
||||
_x86 = '_x86' if arch == '32' else ''
|
||||
|
||||
opts = sys.argv[2:] or ['--onefile']
|
||||
# Compatability with older arguments
|
||||
opts = sys.argv[1:]
|
||||
if opts[0:1] in (['32'], ['64']):
|
||||
if arch != opts[0]:
|
||||
raise Exception(f'{opts[0]}bit executable cannot be built on a {arch}bit system')
|
||||
opts = opts[1:]
|
||||
opts = opts or ['--onefile']
|
||||
|
||||
print(f'Building {arch}bit version with options {opts}')
|
||||
|
||||
FILE_DESCRIPTION = 'yt-dlp%s' % (' (32 Bit)' if _x86 else '')
|
||||
|
@ -82,4 +89,4 @@
|
|||
*opts,
|
||||
'yt_dlp/__main__.py',
|
||||
])
|
||||
SetVersion('dist/yt-dlp%s.exe' % _x86, VERSION_FILE)
|
||||
SetVersion('dist/%syt-dlp%s.exe' % ('yt-dlp/' if '--onedir' in opts else '', _x86), VERSION_FILE)
|
||||
|
|
90
setup.py
90
setup.py
|
@ -1,12 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
|
||||
from setuptools import setup, Command, find_packages
|
||||
import os.path
|
||||
import warnings
|
||||
import sys
|
||||
from distutils.spawn import spawn
|
||||
|
||||
try:
|
||||
from setuptools import setup, Command, find_packages
|
||||
setuptools_available = True
|
||||
except ImportError:
|
||||
from distutils.core import setup, Command
|
||||
setuptools_available = False
|
||||
from distutils.spawn import spawn
|
||||
|
||||
# Get the version from yt_dlp/version.py without importing the package
|
||||
exec(compile(open('yt_dlp/version.py').read(), 'yt_dlp/version.py', 'exec'))
|
||||
|
@ -21,32 +25,62 @@
|
|||
|
||||
REQUIREMENTS = ['mutagen', 'pycryptodome', 'websockets']
|
||||
|
||||
|
||||
if sys.argv[1:2] == ['py2exe']:
|
||||
raise NotImplementedError('py2exe is not currently supported; instead, use "pyinst.py" to build with pyinstaller')
|
||||
import py2exe
|
||||
warnings.warn(
|
||||
'Building with py2exe is not officially supported. '
|
||||
'The recommended way is to use "pyinst.py" to build using pyinstaller')
|
||||
params = {
|
||||
'console': [{
|
||||
'script': './yt_dlp/__main__.py',
|
||||
'dest_base': 'yt-dlp',
|
||||
'version': __version__,
|
||||
'description': DESCRIPTION,
|
||||
'comments': LONG_DESCRIPTION.split('\n')[0],
|
||||
'product_name': 'yt-dlp',
|
||||
'product_version': __version__,
|
||||
}],
|
||||
'options': {
|
||||
'py2exe': {
|
||||
'bundle_files': 0,
|
||||
'compressed': 1,
|
||||
'optimize': 2,
|
||||
'dist_dir': './dist',
|
||||
'excludes': ['Crypto', 'Cryptodome'], # py2exe cannot import Crypto
|
||||
'dll_excludes': ['w9xpopen.exe', 'crypt32.dll'],
|
||||
}
|
||||
},
|
||||
'zipfile': None
|
||||
}
|
||||
|
||||
else:
|
||||
files_spec = [
|
||||
('share/bash-completion/completions', ['completions/bash/yt-dlp']),
|
||||
('share/zsh/site-functions', ['completions/zsh/_yt-dlp']),
|
||||
('share/fish/vendor_completions.d', ['completions/fish/yt-dlp.fish']),
|
||||
('share/doc/yt_dlp', ['README.txt']),
|
||||
('share/man/man1', ['yt-dlp.1'])
|
||||
]
|
||||
root = os.path.dirname(os.path.abspath(__file__))
|
||||
data_files = []
|
||||
for dirname, files in files_spec:
|
||||
resfiles = []
|
||||
for fn in files:
|
||||
if not os.path.exists(fn):
|
||||
warnings.warn('Skipping file %s since it is not present. Try running `make pypi-files` first' % fn)
|
||||
else:
|
||||
resfiles.append(fn)
|
||||
data_files.append((dirname, resfiles))
|
||||
|
||||
files_spec = [
|
||||
('share/bash-completion/completions', ['completions/bash/yt-dlp']),
|
||||
('share/zsh/site-functions', ['completions/zsh/_yt-dlp']),
|
||||
('share/fish/vendor_completions.d', ['completions/fish/yt-dlp.fish']),
|
||||
('share/doc/yt_dlp', ['README.txt']),
|
||||
('share/man/man1', ['yt-dlp.1'])
|
||||
]
|
||||
root = os.path.dirname(os.path.abspath(__file__))
|
||||
data_files = []
|
||||
for dirname, files in files_spec:
|
||||
resfiles = []
|
||||
for fn in files:
|
||||
if not os.path.exists(fn):
|
||||
warnings.warn('Skipping file %s since it is not present. Try running `make pypi-files` first' % fn)
|
||||
else:
|
||||
resfiles.append(fn)
|
||||
data_files.append((dirname, resfiles))
|
||||
params = {
|
||||
'data_files': data_files,
|
||||
}
|
||||
|
||||
params = {
|
||||
'data_files': data_files,
|
||||
}
|
||||
params['entry_points'] = {'console_scripts': ['yt-dlp = yt_dlp:main']}
|
||||
if setuptools_available:
|
||||
params['entry_points'] = {'console_scripts': ['yt-dlp = yt_dlp:main']}
|
||||
else:
|
||||
params['scripts'] = ['yt-dlp']
|
||||
|
||||
|
||||
class build_lazy_extractors(Command):
|
||||
|
@ -64,7 +98,11 @@ def run(self):
|
|||
dry_run=self.dry_run)
|
||||
|
||||
|
||||
packages = find_packages(exclude=('youtube_dl', 'test', 'ytdlp_plugins'))
|
||||
if setuptools_available:
|
||||
packages = find_packages(exclude=('youtube_dl', 'youtube_dlc', 'test', 'ytdlp_plugins'))
|
||||
else:
|
||||
packages = ['yt_dlp', 'yt_dlp.downloader', 'yt_dlp.extractor', 'yt_dlp.postprocessor']
|
||||
|
||||
|
||||
setup(
|
||||
name='yt-dlp',
|
||||
|
|
|
@ -32,10 +32,12 @@ def rsa_verify(message, signature, key):
|
|||
|
||||
|
||||
def detect_variant():
|
||||
if hasattr(sys, 'frozen') and getattr(sys, '_MEIPASS', None):
|
||||
if sys._MEIPASS == os.path.dirname(sys.executable):
|
||||
return 'dir'
|
||||
return 'exe'
|
||||
if hasattr(sys, 'frozen'):
|
||||
if getattr(sys, '_MEIPASS', None):
|
||||
if sys._MEIPASS == os.path.dirname(sys.executable):
|
||||
return 'dir'
|
||||
return 'exe'
|
||||
return 'py2exe'
|
||||
elif isinstance(globals().get('__loader__'), zipimporter):
|
||||
return 'zip'
|
||||
elif os.path.basename(sys.argv[0]) == '__main__.py':
|
||||
|
@ -43,6 +45,20 @@ def detect_variant():
|
|||
return 'unknown'
|
||||
|
||||
|
||||
_NON_UPDATEABLE_REASONS = {
|
||||
'exe': None,
|
||||
'zip': None,
|
||||
'dir': 'Auto-update is not supported for unpackaged windows executable. Re-download the latest release',
|
||||
'py2exe': 'There is no official release for py2exe executable. Build it again with the latest source code',
|
||||
'source': 'You cannot update when running from source code',
|
||||
'unknown': 'It looks like you installed yt-dlp with a package manager, pip, setup.py or a tarball. Use that to update',
|
||||
}
|
||||
|
||||
|
||||
def is_non_updateable():
|
||||
return _NON_UPDATEABLE_REASONS.get(detect_variant(), _NON_UPDATEABLE_REASONS['unknown'])
|
||||
|
||||
|
||||
def update_self(to_screen, verbose, opener):
|
||||
''' Exists for backward compatibility. Use run_update(ydl) instead '''
|
||||
|
||||
|
@ -114,14 +130,7 @@ def version_tuple(version_str):
|
|||
ydl.to_screen(f'yt-dlp is up to date ({__version__})')
|
||||
return
|
||||
|
||||
ERRORS = {
|
||||
'exe': None,
|
||||
'zip': None,
|
||||
'dir': 'Auto-update is not supported for unpackaged windows executable. Re-download the latest release',
|
||||
'source': 'You cannot update when running from source code',
|
||||
'unknown': 'It looks like you installed yt-dlp with a package manager, pip, setup.py or a tarball. Use that to update',
|
||||
}
|
||||
err = ERRORS.get(detect_variant(), ERRORS['unknown'])
|
||||
err = is_non_updateable()
|
||||
if err:
|
||||
ydl.to_screen(f'Latest version: {version_id}, Current version: {__version__}')
|
||||
return report_error(err, expected=True)
|
||||
|
|
|
@ -4521,11 +4521,10 @@ def is_outdated_version(version, limit, assume_new=True):
|
|||
|
||||
def ytdl_is_updateable():
|
||||
""" Returns if yt-dlp can be updated with -U """
|
||||
return False
|
||||
|
||||
from zipimport import zipimporter
|
||||
from .update import is_non_updateable
|
||||
|
||||
return isinstance(globals().get('__loader__'), zipimporter) or hasattr(sys, 'frozen')
|
||||
return not is_non_updateable()
|
||||
|
||||
|
||||
def args_to_str(args):
|
||||
|
|
Loading…
Reference in a new issue