blob: a131b2bcff21715a548390b3b83c393d355d8fad [file] [log] [blame]
# -*- mode: python ; coding: utf-8 -*-
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under this License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
from pathlib import Path
# Get project root directory
project_root = Path(SPECPATH).parent
block_cipher = None
# Auto-collect all submodules of large dependency libraries
# Using collect_all automatically includes all dependencies and avoids manual maintenance of hiddenimports
from PyInstaller.utils.hooks import collect_all, collect_submodules, collect_data_files
# Collect only essential data files and binaries for large libraries
# Using collect_all for all submodules slows down startup significantly.
# However, for certain libraries with many dynamic imports (e.g., torch, transformers, safetensors),
# collect_all is necessary to ensure all required modules are included.
# For other libraries, we use lighter-weight collection methods to improve startup time.
all_datas = []
all_binaries = []
all_hiddenimports = []
# Only collect essential data files and binaries for critical libraries
# This reduces startup time by avoiding unnecessary module imports
essential_libraries = {
'torch': True, # Keep collect_all for torch as it has many dynamic imports
'transformers': True, # Keep collect_all for transformers
'safetensors': True, # Keep collect_all for safetensors
}
# For other libraries, use selective collection to speed up startup
other_libraries = ['sktime', 'scipy', 'pandas', 'sklearn', 'statsmodels', 'optuna']
for lib in essential_libraries:
try:
lib_datas, lib_binaries, lib_hiddenimports = collect_all(lib)
all_datas.extend(lib_datas)
all_binaries.extend(lib_binaries)
all_hiddenimports.extend(lib_hiddenimports)
except Exception:
pass
# For other libraries, only collect submodules (lighter weight)
# This relies on PyInstaller's dependency analysis to include what's actually used
for lib in other_libraries:
try:
submodules = collect_submodules(lib)
all_hiddenimports.extend(submodules)
# Only collect essential data files and binaries, not all submodules
# This significantly reduces startup time
try:
lib_datas, lib_binaries, _ = collect_all(lib)
all_datas.extend(lib_datas)
all_binaries.extend(lib_binaries)
except Exception:
# If collect_all fails, try collect_data_files for essential data only
try:
lib_datas = collect_data_files(lib)
all_datas.extend(lib_datas)
except Exception:
pass
except Exception:
pass
# Project-specific packages that need their submodules collected
# Only list top-level packages - collect_submodules will recursively collect all submodules
TOP_LEVEL_PACKAGES = [
'iotdb.ainode.core', # This will include all sub-packages: manager, model, inference, etc.
'iotdb.thrift', # This will include all thrift sub-packages
]
# Collect all submodules for project packages automatically
# Using top-level packages avoids duplicate collection
for package in TOP_LEVEL_PACKAGES:
try:
submodules = collect_submodules(package)
all_hiddenimports.extend(submodules)
except Exception:
# If package doesn't exist or collection fails, add the package itself
all_hiddenimports.append(package)
# Add parent packages to ensure they are included
all_hiddenimports.extend(['iotdb', 'iotdb.ainode'])
# Multiprocessing support for PyInstaller
# When using multiprocessing with PyInstaller, we need to ensure proper handling
multiprocessing_modules = [
'multiprocessing',
'multiprocessing.spawn',
'multiprocessing.popen_spawn_posix',
'multiprocessing.popen_spawn_win32',
'multiprocessing.popen_fork',
'multiprocessing.popen_forkserver',
'multiprocessing.context',
'multiprocessing.reduction',
'multiprocessing.util',
'torch.multiprocessing',
'torch.multiprocessing.spawn',
]
# Additional dependencies that may need explicit import
# These are external libraries that might use dynamic imports
external_dependencies = [
'huggingface_hub',
'tokenizers',
'hf_xet',
'einops',
'dynaconf',
'tzlocal',
'thrift',
'psutil',
'requests',
]
all_hiddenimports.extend(multiprocessing_modules)
all_hiddenimports.extend(external_dependencies)
# Analyze main entry file
# Note: Do NOT add virtual environment site-packages to pathex manually.
# When PyInstaller is run from the virtual environment's Python, it automatically
# detects and uses the virtual environment's site-packages.
a = Analysis(
['iotdb/ainode/core/script.py'],
pathex=[str(project_root)],
binaries=all_binaries,
datas=all_datas,
hiddenimports=all_hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
# Exclude unnecessary modules to reduce size and improve startup time
# Note: Do not exclude unittest, as torch and other libraries require it
# Only exclude modules that are definitely not used and not required by dependencies
'matplotlib',
'IPython',
'jupyter',
'notebook',
'pytest',
'test',
'tests'
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=True, # Set to True to speed up startup - files are not archived into PYZ
)
# Package all PYZ files
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
# Create executable (onedir mode for faster startup)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='ainode',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
# Collect all files into a directory (onedir mode)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='ainode',
)