| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- # main.spec
- import sys
- import os
- import pkgutil
- import glob # 新增:匹配所有 module_* 目录
- from pathlib import Path
- # 1. 动态获取项目根目录(无需手动写死)
- PROJECT_ROOT = Path('/root/.hd/hd-crane-gs/backend').absolute() # spec文件所在目录 = 项目根目录
- # 修复:扫描所有 module_* 目录并构建 datas 配置
- def get_module_datas():
- """获取所有 module_* 目录的打包配置"""
- api_v1_dir = PROJECT_ROOT / "app" / "api" / "v1"
- module_datas = []
- if api_v1_dir.exists():
- # 匹配所有 module_* 目录(兼容所有系统)
- module_dirs = glob.glob(str(api_v1_dir / "module_*"))
- for mod_dir in module_dirs:
- mod_dir_path = Path(mod_dir)
- if mod_dir_path.is_dir():
- # 格式:(源目录, 目标目录) → 保持原结构 app/api/v1/module_xxx
- target_path = str(mod_dir_path.relative_to(PROJECT_ROOT))
- module_datas.append((str(mod_dir_path), target_path))
- return module_datas
- def get_all_needed_modules():
- all_modules = []
- # 扫描 app 目录下所有 .py 文件(排除 __init__.py)
- all_py_files = PROJECT_ROOT / "app"
- for file in all_py_files.rglob("*.py"):
- if file.name == "__init__.py":
- continue
- rel_path = file.relative_to(PROJECT_ROOT)
- mod_name = rel_path.with_suffix("").as_posix().replace("/", ".")
- all_modules.append(mod_name)
- all_modules = list(set(all_modules))
- print(f"✅ 扫描到 {len(all_modules)} 个模块")
- return all_modules
- # 执行扫描,获取所有模块
- hidden_imports = get_all_needed_modules()
- # 获取 module_* 目录的 datas 配置
- module_datas = get_module_datas()
- # 2. 导入PyInstaller核心模块
- from PyInstaller.utils.hooks import collect_all
- from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT
- # 基础配置
- block_cipher = None
- # 3. 收集第三方依赖(asyncmy)
- asyncmy_datas, asyncmy_binaries, asyncmy_hiddenimports = collect_all('asyncmy')
- # 4. 分析项目代码(核心修复:添加 module_datas)
- a = Analysis(
- ['main.py'], # 主文件(确保在 PROJECT_ROOT 下)
- pathex=[str(PROJECT_ROOT)], # 项目根目录
- binaries=asyncmy_binaries,
- datas=[
- *asyncmy_datas,
- *module_datas, # 关键:添加所有 module_* 目录的打包配置
- # 新增:打包所有 __init__.py(确保包目录被识别)
- (str(PROJECT_ROOT / "app"), "app"),
- (os.path.join(PROJECT_ROOT, "env"), "env"),
- (os.path.join(PROJECT_ROOT, "static"), "static"),
- (os.path.join(PROJECT_ROOT, "banner.txt"), "."),
- (os.path.join(PROJECT_ROOT, "app/api/v1/module_generator/gencode/templates"), "app/api/v1/module_generator/gencode/templates"),
- (os.path.join(PROJECT_ROOT, "app/scripts/data"), "app/scripts/data"),
- ],
- hiddenimports=[
- # 第三方依赖
- *asyncmy_hiddenimports,
- 'asyncmy.auth',
- 'asyncmy.connection',
- 'asyncmy.cursors',
- 'asyncmy.protocol',
- 'asyncmy.utils',
- 'passlib',
- 'passlib.context',
- 'passlib.handlers',
- 'passlib.handlers.bcrypt',
- 'passlib.handlers.md5_crypt',
- # 项目模块
- *hidden_imports,
- ],
- hookspath=[],
- hooksconfig={},
- runtime_hooks=[],
- excludes=[],
- noarchive=False, # 关键:不归档,保留目录结构
- )
- # 5. 打包为PYZ归档
- pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
- # 6. 生成可执行文件
- exe = EXE(
- pyz,
- a.scripts,
- a.binaries,
- a.zipfiles,
- a.datas,
- [],
- name='main',
- debug=False,
- bootloader_ignore_signals=False,
- strip=False,
- upx=False, # 欧拉系统禁用UPX
- runtime_tmpdir=None,
- console=True,
- disable_windowed_traceback=False,
- argv_emulation=False,
- target_arch=None,
- )
|