pyinstaller.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/usr/bin/env python3
  2. # Allow direct execution
  3. import os
  4. import sys
  5. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  6. import platform
  7. from PyInstaller.__main__ import run as run_pyinstaller
  8. from devscripts.utils import read_version
  9. OS_NAME, MACHINE, ARCH = sys.platform, platform.machine().lower(), platform.architecture()[0][:2]
  10. if MACHINE in ('x86', 'x86_64', 'amd64', 'i386', 'i686'):
  11. MACHINE = 'x86' if ARCH == '32' else ''
  12. def main():
  13. opts, version = parse_options(), read_version()
  14. onedir = '--onedir' in opts or '-D' in opts
  15. if not onedir and '-F' not in opts and '--onefile' not in opts:
  16. opts.append('--onefile')
  17. name, final_file = exe(onedir)
  18. print(f'Building yt-dlp v{version} for {OS_NAME} {platform.machine()} with options {opts}')
  19. print('Remember to update the version using "devscripts/update-version.py"')
  20. if not os.path.isfile('yt_dlp/extractor/lazy_extractors.py'):
  21. print('WARNING: Building without lazy_extractors. Run '
  22. '"devscripts/make_lazy_extractors.py" to build lazy extractors', file=sys.stderr)
  23. print(f'Destination: {final_file}\n')
  24. opts = [
  25. f'--name={name}',
  26. '--icon=devscripts/logo.ico',
  27. '--upx-exclude=vcruntime140.dll',
  28. '--noconfirm',
  29. '--additional-hooks-dir=yt_dlp/__pyinstaller',
  30. *opts,
  31. 'yt_dlp/__main__.py',
  32. ]
  33. print(f'Running PyInstaller with {opts}')
  34. run_pyinstaller(opts)
  35. set_version_info(final_file, version)
  36. def parse_options():
  37. # Compatibility with older arguments
  38. opts = sys.argv[1:]
  39. if opts[0:1] in (['32'], ['64']):
  40. if ARCH != opts[0]:
  41. raise Exception(f'{opts[0]}bit executable cannot be built on a {ARCH}bit system')
  42. opts = opts[1:]
  43. return opts
  44. def exe(onedir):
  45. """@returns (name, path)"""
  46. name = '_'.join(filter(None, (
  47. 'yt-dlp',
  48. {'win32': '', 'darwin': 'macos'}.get(OS_NAME, OS_NAME),
  49. MACHINE,
  50. )))
  51. return name, ''.join(filter(None, (
  52. 'dist/',
  53. onedir and f'{name}/',
  54. name,
  55. OS_NAME == 'win32' and '.exe',
  56. )))
  57. def version_to_list(version):
  58. version_list = version.split('.')
  59. return list(map(int, version_list)) + [0] * (4 - len(version_list))
  60. def set_version_info(exe, version):
  61. if OS_NAME == 'win32':
  62. windows_set_version(exe, version)
  63. def windows_set_version(exe, version):
  64. from PyInstaller.utils.win32.versioninfo import (
  65. FixedFileInfo,
  66. StringFileInfo,
  67. StringStruct,
  68. StringTable,
  69. VarFileInfo,
  70. VarStruct,
  71. VSVersionInfo,
  72. )
  73. try:
  74. from PyInstaller.utils.win32.versioninfo import SetVersion
  75. except ImportError: # Pyinstaller >= 5.8
  76. from PyInstaller.utils.win32.versioninfo import write_version_info_to_executable as SetVersion
  77. version_list = version_to_list(version)
  78. suffix = MACHINE and f'_{MACHINE}'
  79. SetVersion(exe, VSVersionInfo(
  80. ffi=FixedFileInfo(
  81. filevers=version_list,
  82. prodvers=version_list,
  83. mask=0x3F,
  84. flags=0x0,
  85. OS=0x4,
  86. fileType=0x1,
  87. subtype=0x0,
  88. date=(0, 0),
  89. ),
  90. kids=[
  91. StringFileInfo([StringTable('040904B0', [
  92. StringStruct('Comments', f'yt-dlp{suffix} Command Line Interface'),
  93. StringStruct('CompanyName', 'https://github.com/yt-dlp'),
  94. StringStruct('FileDescription', 'yt-dlp%s' % (MACHINE and f' ({MACHINE})')),
  95. StringStruct('FileVersion', version),
  96. StringStruct('InternalName', f'yt-dlp{suffix}'),
  97. StringStruct('LegalCopyright', 'pukkandan.ytdlp@gmail.com | UNLICENSE'),
  98. StringStruct('OriginalFilename', f'yt-dlp{suffix}.exe'),
  99. StringStruct('ProductName', f'yt-dlp{suffix}'),
  100. StringStruct(
  101. 'ProductVersion', f'{version}{suffix} on Python {platform.python_version()}'),
  102. ])]), VarFileInfo([VarStruct('Translation', [0, 1200])]),
  103. ],
  104. ))
  105. if __name__ == '__main__':
  106. main()