1+ # -*- mode: python ; coding: utf-8 -*-
2+ #
3+ # Licensed to the Apache Software Foundation (ASF) under one
4+ # or more contributor license agreements. See the NOTICE file
5+ # distributed with this work for additional information
6+ # regarding copyright ownership. The ASF licenses this file
7+ # to you under the Apache License, Version 2.0 (the
8+ # "License"); you may not use this file except in compliance
9+ # with the License. You may obtain a copy of the License at
10+ #
11+ # http://www.apache.org/licenses/LICENSE-2.0
12+ #
13+ # Unless required by applicable law or agreed to in writing,
14+ # software distributed under this License is distributed on an
15+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+ # KIND, either express or implied. See the License for the
17+ # specific language governing permissions and limitations
18+ # under the License.
19+ #
20+
21+ from pathlib import Path
22+
23+ # Get project root directory
24+ project_root = Path (SPECPATH ).parent
25+
26+ block_cipher = None
27+
28+ # Auto-collect all submodules of large dependency libraries
29+ # Using collect_all automatically includes all dependencies and avoids manual maintenance of hiddenimports
30+ from PyInstaller .utils .hooks import collect_all , collect_submodules , collect_data_files
31+
32+ # Collect only essential data files and binaries for large libraries
33+ # Using collect_all for all submodules slows down startup significantly
34+ # Instead, we collect only what's needed and rely on PyInstaller's dependency analysis
35+ all_datas = []
36+ all_binaries = []
37+ all_hiddenimports = []
38+
39+ # Only collect essential data files and binaries for critical libraries
40+ # This reduces startup time by avoiding unnecessary module imports
41+ essential_libraries = {
42+ 'torch' : True , # Keep collect_all for torch as it has many dynamic imports
43+ 'transformers' : True , # Keep collect_all for transformers
44+ 'safetensors' : True , # Keep collect_all for safetensors
45+ }
46+
47+ # For other libraries, use selective collection to speed up startup
48+ other_libraries = ['sktime' , 'scipy' , 'pandas' , 'sklearn' , 'statsmodels' , 'optuna' ]
49+
50+ for lib in essential_libraries :
51+ try :
52+ lib_datas , lib_binaries , lib_hiddenimports = collect_all (lib )
53+ all_datas .extend (lib_datas )
54+ all_binaries .extend (lib_binaries )
55+ all_hiddenimports .extend (lib_hiddenimports )
56+ except Exception :
57+ pass
58+
59+ # For other libraries, only collect submodules (lighter weight)
60+ # This relies on PyInstaller's dependency analysis to include what's actually used
61+ for lib in other_libraries :
62+ try :
63+ submodules = collect_submodules (lib )
64+ all_hiddenimports .extend (submodules )
65+ # Only collect essential data files and binaries, not all submodules
66+ # This significantly reduces startup time
67+ try :
68+ lib_datas , lib_binaries , _ = collect_all (lib )
69+ all_datas .extend (lib_datas )
70+ all_binaries .extend (lib_binaries )
71+ except Exception :
72+ # If collect_all fails, try collect_data_files for essential data only
73+ try :
74+ lib_datas = collect_data_files (lib )
75+ all_datas .extend (lib_datas )
76+ except Exception :
77+ pass
78+ except Exception :
79+ pass
80+
81+ # Project-specific packages that need their submodules collected
82+ # Only list top-level packages - collect_submodules will recursively collect all submodules
83+ TOP_LEVEL_PACKAGES = [
84+ 'iotdb.ainode.core' , # This will include all sub-packages: manager, model, inference, etc.
85+ 'iotdb.thrift' , # This will include all thrift sub-packages
86+ ]
87+
88+ # Collect all submodules for project packages automatically
89+ # Using top-level packages avoids duplicate collection
90+ for package in TOP_LEVEL_PACKAGES :
91+ try :
92+ submodules = collect_submodules (package )
93+ all_hiddenimports .extend (submodules )
94+ except Exception :
95+ # If package doesn't exist or collection fails, add the package itself
96+ all_hiddenimports .append (package )
97+
98+ # Add parent packages to ensure they are included
99+ all_hiddenimports .extend (['iotdb' , 'iotdb.ainode' ])
100+
101+ # Multiprocessing support for PyInstaller
102+ # When using multiprocessing with PyInstaller, we need to ensure proper handling
103+ multiprocessing_modules = [
104+ 'multiprocessing' ,
105+ 'multiprocessing.spawn' ,
106+ 'multiprocessing.popen_spawn_posix' ,
107+ 'multiprocessing.popen_spawn_win32' ,
108+ 'multiprocessing.popen_fork' ,
109+ 'multiprocessing.popen_forkserver' ,
110+ 'multiprocessing.context' ,
111+ 'multiprocessing.reduction' ,
112+ 'multiprocessing.util' ,
113+ 'torch.multiprocessing' ,
114+ 'torch.multiprocessing.spawn' ,
115+ ]
116+
117+ # Additional dependencies that may need explicit import
118+ # These are external libraries that might use dynamic imports
119+ external_dependencies = [
120+ 'huggingface_hub' ,
121+ 'tokenizers' ,
122+ 'hf_xet' ,
123+ 'einops' ,
124+ 'dynaconf' ,
125+ 'tzlocal' ,
126+ 'thrift' ,
127+ 'psutil' ,
128+ 'requests' ,
129+ ]
130+
131+ all_hiddenimports .extend (multiprocessing_modules )
132+ all_hiddenimports .extend (external_dependencies )
133+
134+ # Analyze main entry file
135+ a = Analysis (
136+ ['iotdb/ainode/core/script.py' ],
137+ pathex = [str (project_root )],
138+ binaries = all_binaries ,
139+ datas = all_datas ,
140+ hiddenimports = all_hiddenimports ,
141+ hookspath = [],
142+ hooksconfig = {},
143+ runtime_hooks = [],
144+ excludes = [
145+ # Exclude unnecessary modules to reduce size and improve startup time
146+ # Note: Do not exclude unittest, as torch and other libraries require it
147+ # Only exclude modules that are definitely not used and not required by dependencies
148+ 'matplotlib' ,
149+ 'IPython' ,
150+ 'jupyter' ,
151+ 'notebook' ,
152+ 'pytest' ,
153+ 'test' ,
154+ 'tests'
155+ ],
156+ win_no_prefer_redirects = False ,
157+ win_private_assemblies = False ,
158+ cipher = block_cipher ,
159+ noarchive = True , # Set to True to speed up startup - files are not archived into PYZ
160+ )
161+
162+ # Package all PYZ files
163+ pyz = PYZ (a .pure , a .zipped_data , cipher = block_cipher )
164+
165+ # Create executable (onedir mode for faster startup)
166+ exe = EXE (
167+ pyz ,
168+ a .scripts ,
169+ [],
170+ exclude_binaries = True ,
171+ name = 'ainode' ,
172+ debug = False ,
173+ bootloader_ignore_signals = False ,
174+ strip = False ,
175+ upx = True ,
176+ console = True ,
177+ disable_windowed_traceback = False ,
178+ argv_emulation = False ,
179+ target_arch = None ,
180+ codesign_identity = None ,
181+ entitlements_file = None ,
182+ )
183+
184+ # Collect all files into a directory (onedir mode)
185+ coll = COLLECT (
186+ exe ,
187+ a .binaries ,
188+ a .zipfiles ,
189+ a .datas ,
190+ strip = False ,
191+ upx = True ,
192+ upx_exclude = [],
193+ name = 'ainode' ,
194+ )
0 commit comments