]>
Commit | Line | Data |
---|---|---|
cc52de43 | 1 | #!/usr/bin/env python3 |
ff88a05c | 2 | # coding: utf-8 |
733d8e8f | 3 | import os |
ff88a05c | 4 | import platform |
733d8e8f | 5 | import sys |
e36d50c5 | 6 | from PyInstaller.utils.hooks import collect_submodules |
0e5927ee | 7 | |
733d8e8f | 8 | |
9 | OS_NAME = platform.system() | |
10 | if OS_NAME == 'Windows': | |
0e5927ee R |
11 | from PyInstaller.utils.win32.versioninfo import ( |
12 | VarStruct, VarFileInfo, StringStruct, StringTable, | |
13 | StringFileInfo, FixedFileInfo, VSVersionInfo, SetVersion, | |
14 | ) | |
733d8e8f | 15 | elif OS_NAME == 'Darwin': |
16 | pass | |
17 | else: | |
18 | raise Exception('{OS_NAME} is not supported') | |
e38df8f9 | 19 | |
733d8e8f | 20 | ARCH = platform.architecture()[0][:2] |
e38df8f9 | 21 | |
0e5927ee | 22 | |
733d8e8f | 23 | def main(): |
24 | opts = parse_options() | |
25 | version = read_version() | |
5d535b4a | 26 | |
49a57e70 | 27 | suffix = '_macos' if OS_NAME == 'Darwin' else '_x86' if ARCH == '32' else '' |
733d8e8f | 28 | final_file = 'dist/%syt-dlp%s%s' % ( |
29 | 'yt-dlp/' if '--onedir' in opts else '', suffix, '.exe' if OS_NAME == 'Windows' else '') | |
4c88ff87 | 30 | |
733d8e8f | 31 | print(f'Building yt-dlp v{version} {ARCH}bit for {OS_NAME} with options {opts}') |
49a57e70 | 32 | print('Remember to update the version using "devscripts/update-version.py"') |
733d8e8f | 33 | if not os.path.isfile('yt_dlp/extractor/lazy_extractors.py'): |
34 | print('WARNING: Building without lazy_extractors. Run ' | |
49a57e70 | 35 | '"devscripts/make_lazy_extractors.py" to build lazy extractors', file=sys.stderr) |
733d8e8f | 36 | print(f'Destination: {final_file}\n') |
e38df8f9 | 37 | |
733d8e8f | 38 | opts = [ |
39 | f'--name=yt-dlp{suffix}', | |
40 | '--icon=devscripts/logo.ico', | |
41 | '--upx-exclude=vcruntime140.dll', | |
42 | '--noconfirm', | |
e75bb0d6 | 43 | *dependency_options(), |
733d8e8f | 44 | *opts, |
45 | 'yt_dlp/__main__.py', | |
46 | ] | |
47 | print(f'Running PyInstaller with {opts}') | |
e38df8f9 | 48 | |
733d8e8f | 49 | import PyInstaller.__main__ |
e38df8f9 | 50 | |
733d8e8f | 51 | PyInstaller.__main__.run(opts) |
52 | ||
53 | set_version_info(final_file, version) | |
54 | ||
55 | ||
56 | def parse_options(): | |
57 | # Compatability with older arguments | |
58 | opts = sys.argv[1:] | |
59 | if opts[0:1] in (['32'], ['64']): | |
60 | if ARCH != opts[0]: | |
61 | raise Exception(f'{opts[0]}bit executable cannot be built on a {ARCH}bit system') | |
62 | opts = opts[1:] | |
63 | return opts or ['--onefile'] | |
e38df8f9 | 64 | |
733d8e8f | 65 | |
66 | def read_version(): | |
67 | exec(compile(open('yt_dlp/version.py').read(), 'yt_dlp/version.py', 'exec')) | |
68 | return locals()['__version__'] | |
69 | ||
70 | ||
71 | def version_to_list(version): | |
72 | version_list = version.split('.') | |
73 | return list(map(int, version_list)) + [0] * (4 - len(version_list)) | |
74 | ||
75 | ||
e75bb0d6 U |
76 | def dependency_options(): |
77 | dependencies = [pycryptodome_module(), 'mutagen'] + collect_submodules('websockets') | |
733d8e8f | 78 | excluded_modules = ['test', 'ytdlp_plugins', 'youtube-dl', 'youtube-dlc'] |
79 | ||
e75bb0d6 | 80 | yield from (f'--hidden-import={module}' for module in dependencies) |
733d8e8f | 81 | yield from (f'--exclude-module={module}' for module in excluded_modules) |
e38df8f9 | 82 | |
49e7e9c3 | 83 | |
84 | def pycryptodome_module(): | |
85 | try: | |
86 | import Cryptodome # noqa: F401 | |
87 | except ImportError: | |
88 | try: | |
89 | import Crypto # noqa: F401 | |
90 | print('WARNING: Using Crypto since Cryptodome is not available. ' | |
91 | 'Install with: pip install pycryptodomex', file=sys.stderr) | |
92 | return 'Crypto' | |
93 | except ImportError: | |
94 | pass | |
95 | return 'Cryptodome' | |
96 | ||
97 | ||
733d8e8f | 98 | def set_version_info(exe, version): |
99 | if OS_NAME == 'Windows': | |
100 | windows_set_version(exe, version) | |
101 | ||
102 | ||
103 | def windows_set_version(exe, version): | |
104 | version_list = version_to_list(version) | |
105 | suffix = '_x86' if ARCH == '32' else '' | |
106 | SetVersion(exe, VSVersionInfo( | |
107 | ffi=FixedFileInfo( | |
108 | filevers=version_list, | |
109 | prodvers=version_list, | |
110 | mask=0x3F, | |
111 | flags=0x0, | |
112 | OS=0x4, | |
113 | fileType=0x1, | |
114 | subtype=0x0, | |
115 | date=(0, 0), | |
116 | ), | |
117 | kids=[ | |
118 | StringFileInfo([StringTable('040904B0', [ | |
119 | StringStruct('Comments', 'yt-dlp%s Command Line Interface.' % suffix), | |
120 | StringStruct('CompanyName', 'https://github.com/yt-dlp'), | |
121 | StringStruct('FileDescription', 'yt-dlp%s' % (' (32 Bit)' if ARCH == '32' else '')), | |
122 | StringStruct('FileVersion', version), | |
123 | StringStruct('InternalName', f'yt-dlp{suffix}'), | |
124 | StringStruct('LegalCopyright', 'pukkandan.ytdlp@gmail.com | UNLICENSE'), | |
125 | StringStruct('OriginalFilename', f'yt-dlp{suffix}.exe'), | |
126 | StringStruct('ProductName', f'yt-dlp{suffix}'), | |
127 | StringStruct( | |
128 | 'ProductVersion', f'{version}{suffix} on Python {platform.python_version()}'), | |
129 | ])]), VarFileInfo([VarStruct('Translation', [0, 1200])]) | |
130 | ] | |
131 | )) | |
e36d50c5 | 132 | |
0e5927ee | 133 | |
733d8e8f | 134 | if __name__ == '__main__': |
135 | main() |