]> jfr.im git - yt-dlp.git/blame - pyinst.py
[extractor/naver] Treat fan subtitles as separate language
[yt-dlp.git] / pyinst.py
CommitLineData
cc52de43 1#!/usr/bin/env python3
54007a45 2
115add43 3# Allow direct execution
733d8e8f 4import os
733d8e8f 5import sys
0e5927ee 6
115add43 7sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
8
9import platform
10
c1714454 11from PyInstaller.__main__ import run as run_pyinstaller
733d8e8f 12
115add43 13from devscripts.utils import read_version
14
17fc3dc4
M
15OS_NAME, MACHINE, ARCH = sys.platform, platform.machine().lower(), platform.architecture()[0][:2]
16if MACHINE in ('x86', 'x86_64', 'amd64', 'i386', 'i686'):
d08e1e68 17 MACHINE = 'x86' if ARCH == '32' else ''
e38df8f9 18
0e5927ee 19
733d8e8f 20def main():
115add43 21 opts, version = parse_options(), read_version()
c1714454 22
23 onedir = '--onedir' in opts or '-D' in opts
24 if not onedir and '-F' not in opts and '--onefile' not in opts:
25 opts.append('--onefile')
5d535b4a 26
b5899f4f 27 name, final_file = exe(onedir)
52009769 28 print(f'Building yt-dlp v{version} for {OS_NAME} {platform.machine()} with options {opts}')
49a57e70 29 print('Remember to update the version using "devscripts/update-version.py"')
733d8e8f 30 if not os.path.isfile('yt_dlp/extractor/lazy_extractors.py'):
31 print('WARNING: Building without lazy_extractors. Run '
49a57e70 32 '"devscripts/make_lazy_extractors.py" to build lazy extractors', file=sys.stderr)
733d8e8f 33 print(f'Destination: {final_file}\n')
e38df8f9 34
733d8e8f 35 opts = [
e1e1ea54 36 f'--name={name}',
733d8e8f 37 '--icon=devscripts/logo.ico',
38 '--upx-exclude=vcruntime140.dll',
39 '--noconfirm',
e75bb0d6 40 *dependency_options(),
733d8e8f 41 *opts,
42 'yt_dlp/__main__.py',
43 ]
733d8e8f 44
c1714454 45 print(f'Running PyInstaller with {opts}')
46 run_pyinstaller(opts)
733d8e8f 47 set_version_info(final_file, version)
48
49
50def parse_options():
962ffcf8 51 # Compatibility with older arguments
733d8e8f 52 opts = sys.argv[1:]
53 if opts[0:1] in (['32'], ['64']):
54 if ARCH != opts[0]:
55 raise Exception(f'{opts[0]}bit executable cannot be built on a {ARCH}bit system')
56 opts = opts[1:]
c1714454 57 return opts
e38df8f9 58
733d8e8f 59
b5899f4f 60def exe(onedir):
61 """@returns (name, path)"""
62 name = '_'.join(filter(None, (
63 'yt-dlp',
e4afcfde 64 {'win32': '', 'darwin': 'macos'}.get(OS_NAME, OS_NAME),
17fc3dc4 65 MACHINE,
b5899f4f 66 )))
67 return name, ''.join(filter(None, (
68 'dist/',
69 onedir and f'{name}/',
70 name,
71 OS_NAME == 'win32' and '.exe'
72 )))
73
74
733d8e8f 75def version_to_list(version):
76 version_list = version.split('.')
77 return list(map(int, version_list)) + [0] * (4 - len(version_list))
78
79
e75bb0d6 80def dependency_options():
c1714454 81 # Due to the current implementation, these are auto-detected, but explicitly add them just in case
82 dependencies = [pycryptodome_module(), 'mutagen', 'brotli', 'certifi', 'websockets']
460eb9c5 83 excluded_modules = ('youtube_dl', 'youtube_dlc', 'test', 'ytdlp_plugins', 'devscripts')
733d8e8f 84
e75bb0d6 85 yield from (f'--hidden-import={module}' for module in dependencies)
c1714454 86 yield '--collect-submodules=websockets'
733d8e8f 87 yield from (f'--exclude-module={module}' for module in excluded_modules)
e38df8f9 88
49e7e9c3 89
90def pycryptodome_module():
91 try:
92 import Cryptodome # noqa: F401
93 except ImportError:
94 try:
95 import Crypto # noqa: F401
96 print('WARNING: Using Crypto since Cryptodome is not available. '
97 'Install with: pip install pycryptodomex', file=sys.stderr)
98 return 'Crypto'
99 except ImportError:
100 pass
101 return 'Cryptodome'
102
103
733d8e8f 104def set_version_info(exe, version):
1890fc63 105 if OS_NAME == 'win32':
733d8e8f 106 windows_set_version(exe, version)
107
108
109def windows_set_version(exe, version):
b5899f4f 110 from PyInstaller.utils.win32.versioninfo import (
111 FixedFileInfo,
112 SetVersion,
113 StringFileInfo,
114 StringStruct,
115 StringTable,
116 VarFileInfo,
117 VarStruct,
118 VSVersionInfo,
119 )
120
733d8e8f 121 version_list = version_to_list(version)
52009769 122 suffix = MACHINE and f'_{MACHINE}'
733d8e8f 123 SetVersion(exe, VSVersionInfo(
124 ffi=FixedFileInfo(
125 filevers=version_list,
126 prodvers=version_list,
127 mask=0x3F,
128 flags=0x0,
129 OS=0x4,
130 fileType=0x1,
131 subtype=0x0,
132 date=(0, 0),
133 ),
134 kids=[
135 StringFileInfo([StringTable('040904B0', [
52009769 136 StringStruct('Comments', 'yt-dlp%s Command Line Interface' % suffix),
733d8e8f 137 StringStruct('CompanyName', 'https://github.com/yt-dlp'),
52009769 138 StringStruct('FileDescription', 'yt-dlp%s' % (MACHINE and f' ({MACHINE})')),
733d8e8f 139 StringStruct('FileVersion', version),
140 StringStruct('InternalName', f'yt-dlp{suffix}'),
141 StringStruct('LegalCopyright', 'pukkandan.ytdlp@gmail.com | UNLICENSE'),
142 StringStruct('OriginalFilename', f'yt-dlp{suffix}.exe'),
143 StringStruct('ProductName', f'yt-dlp{suffix}'),
144 StringStruct(
145 'ProductVersion', f'{version}{suffix} on Python {platform.python_version()}'),
146 ])]), VarFileInfo([VarStruct('Translation', [0, 1200])])
147 ]
148 ))
e36d50c5 149
0e5927ee 150
733d8e8f 151if __name__ == '__main__':
152 main()