Difficult-Rocket/libs/utils/nuitka.py

219 lines
9.0 KiB
Python
Raw Normal View History

2023-05-14 02:08:31 +08:00
# -------------------------------
# Difficult Rocket
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved
# -------------------------------
# 用于使用 nuitka 构建 DR
import platform
2023-07-08 11:45:18 +08:00
import warnings
2023-05-14 02:08:31 +08:00
import traceback
from pathlib import Path
2023-09-17 21:18:20 +08:00
from typing import List, Tuple, Optional, Union, Any
2023-05-14 02:08:31 +08:00
2023-07-08 11:45:18 +08:00
from Difficult_Rocket.api.types import Options, Version, VersionRequirement
2023-05-14 02:08:31 +08:00
2023-09-17 20:53:21 +08:00
def ensure_cmd_readable(cmd: str) -> str:
"""
保证 参数中 不含空格
:param cmd: 要格式化的命令行参数
:return: 格式化后的命令行参数
"""
2023-09-17 22:21:27 +08:00
if ' ' in str(cmd):
2023-09-17 20:53:21 +08:00
return f'"{cmd}"'
return cmd
def format_cmd(arg_name: Optional[str] = None,
2023-09-17 22:21:27 +08:00
arg_value: Optional[Union[str, List[str]]] = None,
2023-09-17 21:18:20 +08:00
write: Optional[Any] = True) -> List[str]:
2023-09-17 20:53:21 +08:00
"""
用来格式化输出命令行参数
:param arg_name: 类似 --show-memory 之类的主项
:param arg_value: 类似 xxx 类的内容
:param write: 是否写入
2023-09-17 20:53:21 +08:00
:return: 直接拼接好的命令行参数 不带 =
"""
if not write:
return []
2023-09-17 20:53:21 +08:00
if arg_name is None:
return []
if arg_value is None:
return [arg_name]
if isinstance(arg_value, list):
arg_value = ','.join([ensure_cmd_readable(value) for value in arg_value])
return [f'{arg_name}{arg_value}']
arg_value = ensure_cmd_readable(arg_value)
return [f'{arg_name}{arg_value}']
def _add_cmd(cmd: List[str], string: Optional[str]) -> List[str]:
if string is not None and string:
cmd.append(string)
return cmd
2023-06-10 14:45:51 +08:00
class CompilerHelper(Options):
2023-07-08 11:45:18 +08:00
"""
用于帮助生成 nuitka 构建脚本的类
Use to help generate nuitka build script
"""
2023-06-10 14:45:51 +08:00
name = 'Nuitka Compiler Helper'
2023-05-14 02:08:31 +08:00
2023-07-01 00:51:26 +08:00
output_path: Path = Path("./build/nuitka")
2023-05-14 02:08:31 +08:00
src_file: Path = Path('DR.py')
2023-06-09 16:57:26 +08:00
python_cmd: str = 'python'
2023-09-17 22:21:27 +08:00
compat_nuitka_version: VersionRequirement = VersionRequirement("~1.8.1") # STATIC VERSION
2023-06-09 16:57:26 +08:00
2023-05-14 02:08:31 +08:00
# 以下为 nuitka 的参数
2023-05-27 00:55:27 +08:00
use_lto: bool = False # --lto=yes (no is faster)
use_clang: bool = True # --clang
use_msvc: bool = True # --msvc=latest
use_mingw: bool = False # --mingw64
2023-09-20 00:20:48 +08:00
2023-09-19 23:58:12 +08:00
onefile: bool = False # --onefile
2023-09-20 00:20:48 +08:00
onefile_tempdir: Optional[str] = '' # --onefile-tempdir-spec=
2023-05-27 00:55:27 +08:00
standalone: bool = True # --standalone
2023-06-09 17:03:35 +08:00
use_ccache: bool = True # not --disable-ccache
enable_console: bool = True # --enable-console / --disable-console
2023-06-09 15:40:30 +08:00
show_progress: bool = True # --show-progress
show_memory: bool = False # --show-memory
2023-08-19 20:15:35 +08:00
remove_output: bool = True # --remove-output
2023-06-15 00:30:29 +08:00
save_xml: bool = False # --xml
2023-06-14 21:18:04 +08:00
xml_path: Path = Path('build/compile_data.xml')
2023-09-17 23:00:01 +08:00
save_report: bool = False # --report
report_path: Path = Path('build/compile_report.xml')
2023-06-09 15:40:30 +08:00
2023-06-09 17:03:35 +08:00
download_confirm: bool = True # --assume-yes-for-download
2023-07-08 11:45:18 +08:00
run_after_build: bool = False # --run
2023-06-09 17:03:35 +08:00
2023-05-14 02:08:31 +08:00
company_name: str = 'tool-shenjack-workshop'
product_name: str = 'Difficult-Rocket'
file_version: Version
product_version: Version
file_description: str = 'Difficult Rocket' # --file-description
copy_right: str = 'Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com' # --copyright
2023-06-09 15:40:30 +08:00
2023-07-16 00:32:28 +08:00
icon_path: Path = Path('assets/textures/icon.png')
2023-06-09 15:40:30 +08:00
2023-06-09 16:57:26 +08:00
follow_import: List[str] = ['pyglet']
2023-07-15 21:55:46 +08:00
no_follow_import: List[str] = ['objprint', 'pillow', 'PIL', 'cffi', 'pydoc', 'numpy', 'email', 'win32con',
'smtplib', 'win32evtlog', 'win32evtlogutil', 'win32api']
2023-06-09 15:40:30 +08:00
2023-07-16 00:59:24 +08:00
include_data_dir: List[Tuple[str, str]] = [('./config', './config'),
2023-07-16 00:06:17 +08:00
('./assets', './assets')]
2023-06-09 16:57:26 +08:00
include_packages: List[str] = ['Difficult_Rocket.api']
2023-05-14 02:08:31 +08:00
2023-06-16 00:06:43 +08:00
enable_plugin: List[str] = [] # --enable-plugin=xxx,xxx
2023-09-17 22:21:27 +08:00
disable_plugin: List[str] = ['pyqt5', 'tk-inter'] # --disable-plugin=xxx,xxx
2023-06-16 00:06:43 +08:00
2023-05-14 02:08:31 +08:00
def init(self, **kwargs) -> None:
2023-07-08 11:45:18 +08:00
if (compat_version := kwargs.get('compat_nuitka_version')) is not None:
if not self.compat_nuitka_version.accept(compat_version):
warnings.warn(
f"Nuitka version may not compat with {compat_version}\n"
2023-07-15 21:55:46 +08:00
f"requirement: {self.compat_nuitka_version}"
2023-07-08 11:45:18 +08:00
)
2023-05-14 02:08:31 +08:00
# 非 windows 平台不使用 msvc
if platform.system() != 'Windows':
self.use_msvc = False
2023-05-27 00:55:27 +08:00
self.use_mingw = False
else:
self.use_mingw = self.use_mingw and not self.use_msvc
# Windows 平台下使用 msvc 时不使用 mingw
2023-05-14 02:08:31 +08:00
def load_file(self) -> bool:
try:
from Difficult_Rocket import DR_status
self.product_version = DR_status.DR_version
self.file_version = DR_status.Build_version
2023-05-14 02:08:31 +08:00
return True
except ImportError:
traceback.print_exc()
return False
2023-06-09 15:08:08 +08:00
def __str__(self):
return self.as_markdown()
def as_markdown(self, longest: Optional[int] = None) -> str:
2023-07-08 11:45:18 +08:00
"""
输出编译器帮助信息
Output compiler help information
Args:
longest (Optional[int], optional):
输出信息的最大长度限制 The maximum length of output information.
Defaults to None.
Returns:
str: markdown 格式输出的编译器帮助信息
Compile helper information in markdown format
"""
front = super().as_markdown(longest)
gen_cmd = self.gen_subprocess_cmd()
return f"{front}\n\n```bash\n{' '.join(gen_cmd)}\n```"
2023-05-14 02:08:31 +08:00
def gen_subprocess_cmd(self) -> List[str]:
2023-07-17 19:29:33 +08:00
"""
生成 nuitka 构建脚本
2023-07-08 11:45:18 +08:00
Generate nuitka build script
Returns:
List[str]:
生成的 nuitka 构建脚本
Generated nuitka build script
"""
2023-06-09 16:57:26 +08:00
cmd_list = [self.python_cmd, '-m', 'nuitka']
2023-05-14 02:08:31 +08:00
# macos 和 非 macos icon 参数不同
if platform.system() == 'Darwin':
2023-09-17 22:21:45 +08:00
cmd_list += format_cmd('--macos-app-version=', self.product_version, self.product_version) # noqa
cmd_list += format_cmd('--macos-app-icon=', self.icon_path.absolute(), self.icon_path) # noqa
2023-05-14 02:08:31 +08:00
elif platform.system() == 'Windows':
2023-09-17 22:21:45 +08:00
cmd_list += format_cmd('--windows-icon-from-ico=', self.icon_path.absolute(), self.icon_path) # noqa
elif platform.system() == 'Linux':
2023-09-17 22:21:45 +08:00
cmd_list += format_cmd('--linux-icon=', self.icon_path.absolute(), self.icon_path) # noqa
cmd_list += format_cmd('--lto=', 'yes' if self.use_lto else 'no')
cmd_list += format_cmd('--clang' if self.use_clang else None)
cmd_list += format_cmd('--msvc=latest' if self.use_msvc else None)
cmd_list += format_cmd('--mingw64' if self.use_mingw else None)
cmd_list += format_cmd('--standalone' if self.standalone else None)
2023-09-19 23:58:12 +08:00
cmd_list += format_cmd('--onefile' if self.onefile else None)
2023-09-20 00:20:48 +08:00
cmd_list += format_cmd('--onefile-tempdir-spec=', self.onefile_tempdir, self.onefile_tempdir)
2023-09-17 22:21:45 +08:00
cmd_list += format_cmd('--disable-ccache' if not self.use_ccache else None)
cmd_list += format_cmd('--show-progress' if self.show_progress else None)
cmd_list += format_cmd('--show-memory' if self.show_memory else None)
cmd_list += format_cmd('--remove-output' if self.remove_output else None)
cmd_list += format_cmd('--assume-yes-for-download' if self.download_confirm else None)
cmd_list += format_cmd('--run' if self.run_after_build else None)
cmd_list += format_cmd('--enable-console' if self.enable_console else '--disable-console')
cmd_list += format_cmd('--xml=', str(self.xml_path.absolute()), self.save_xml)
2023-09-17 23:00:01 +08:00
cmd_list += format_cmd('--report=', str(self.report_path.absolute()), self.save_report)
2023-09-17 22:21:45 +08:00
cmd_list += format_cmd('--output-dir=', str(self.output_path.absolute()), self.output_path)
cmd_list += format_cmd('--company-name=', self.company_name, self.company_name)
cmd_list += format_cmd('--product-name=', self.product_name, self.product_name)
cmd_list += format_cmd('--file-version=', str(self.file_version), self.file_version)
cmd_list += format_cmd('--product-version=', str(self.product_version), self.product_version)
cmd_list += format_cmd('--file-description=', self.file_description, self.file_description)
cmd_list += format_cmd('--copyright=', self.copy_right, self.copy_right)
cmd_list += format_cmd('--follow-import-to=', self.follow_import, self.follow_import)
cmd_list += format_cmd('--nofollow-import-to=', self.no_follow_import, self.no_follow_import)
cmd_list += format_cmd('--enable-plugin=', self.enable_plugin, self.enable_plugin)
cmd_list += format_cmd('--disable-plugin=', self.disable_plugin, self.disable_plugin)
2023-06-09 15:40:30 +08:00
2023-06-16 00:14:01 +08:00
if self.include_data_dir:
cmd_list += [f"--include-data-dir={src}={dst}" for src, dst in self.include_data_dir]
if self.include_packages:
cmd_list += [f"--include-package={package}" for package in self.include_packages]
2023-07-08 11:45:18 +08:00
cmd_list.append(f"--main={self.src_file}")
2023-05-27 00:50:14 +08:00
return cmd_list