# import sys # log_file = open("setup.log", "a", encoding="utf-8") # class LoggerWriter: # def __init__(self, stream, log_file): # self.stream = stream # self.log_file = log_file # def write(self, message): # self.stream.write(message) # self.log_file.write(message) # def flush(self): # self.stream.flush() # self.log_file.flush() # sys.stdout = LoggerWriter(sys.stdout, log_file) # sys.stderr = LoggerWriter(sys.stderr, log_file)# setup.py import sys, os from cx_Freeze import setup, Executable # from PySide6 import QtCore # import ssl from setuptools import find_packages from updateManager.__version__ import ( __title__, __version__, __description__, __author__, __author_email__, __license__, __install_requires__, __exe_name__, __icon_file__, __main_script__, __file_log_level__, __gui_log_level__ ) import subprocess from setuptools.command.build_ext import build_ext from setuptools.command.install import install from cx_Freeze.command.build_exe import build_exe as _build_exe import importlib.util import logging # 패들 코어 패치 적용 (ONNX 사용으로 비활성화) # print("패들 코어 패치 검사 및 적용...") # try: # import patch_paddle_core # patch_paddle_core.patch_paddle_core() # except Exception as e: # print(f"패들 코어 패치 적용 중 오류 발생: {e}") # print("패치 실패, 빌드 계속 진행합니다.") # 필요한 파일 경로 설정 base_dir = os.path.dirname(__file__) browsers_dir = os.path.join(base_dir, 'src', 'browsers') chromium_dir = os.path.join(browsers_dir, 'src', 'browsers', 'chromium-1155') # whale_dir = os.path.join(browsers_dir, 'src', 'browsers', 'whale') extensions_dir = os.path.join(browsers_dir, 'src', 'browsers', 'extensions') # user_data_dir = os.path.join(browsers_dir, 'src', 'browsers', 'user_data') # include_files = [ # os.path.abspath('config.ini'), # os.path.abspath('prompt.json'), # os.path.abspath('userDB.db'), # os.path.abspath('HakgyoansimDunggeunmisoTTFB.ttf'), # (os.path.abspath('src/initialDB.db'), 'src/initialDB.db'), # (os.path.abspath('src/Percenty_SS_Code.json'), 'src/Percenty_SS_Code.json'), # (os.path.abspath(chromium_dir), 'browsers/chromium-1155'), # (os.path.abspath(whale_dir), 'browsers/whale'), # (os.path.abspath(extensions_dir), 'browsers/extensions'), # (os.path.abspath(user_data_dir), 'browsers/user_data'), # ] # PySide6 DLL 경로 추가 # pyside6_path = os.path.join(os.path.dirname(sys.executable), "Lib", "site-packages", "PySide6") # pyside6_plugins_path = os.path.join(pyside6_path, "plugins") # pyside6_bin_path = pyside6_path # 'bin' 폴더가 없으면 기본 경로 사용 dll_files = [ # "LIBPQ.dll", # "MIMAPI64.dll", # "Qt63DQuickScene3D.dll", "api-ms-win-core-com-l1-1-0.dll", "api-ms-win-core-debug-l1-1-0.dll", "api-ms-win-core-errorhandling-l1-1-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-l1-1-0.dll", # "api-ms-win-core-heap-l2-1-0.dll", "api-ms-win-core-interlocked-l1-1-0.dll", # "api-ms-win-core-libraryloader-l1-2-0.dll", # "api-ms-win-core-libraryloader-l1-2-1.dll", "api-ms-win-core-localization-l1-2-0.dll", # "api-ms-win-core-path-l1-1-0.dll", "api-ms-win-core-processthreads-l1-1-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", # "api-ms-win-core-realtime-l1-1-1.dll", "api-ms-win-core-rtlsupport-l1-1-0.dll", "api-ms-win-core-synch-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-1-0.dll", # "api-ms-win-core-winrt-error-l1-1-0.dll", # "api-ms-win-core-winrt-l1-1-0.dll", # "api-ms-win-core-winrt-string-l1-1-0.dll", "api-ms-win-crt-conio-l1-1-0.dll", "api-ms-win-crt-environment-l1-1-0.dll", "api-ms-win-crt-filesystem-l1-1-0.dll", "api-ms-win-crt-multibyte-l1-1-0.dll", "api-ms-win-crt-private-l1-1-0.dll", "api-ms-win-crt-process-l1-1-0.dll", "api-ms-win-crt-time-l1-1-0.dll", "api-ms-win-crt-utility-l1-1-0.dll", # "api-ms-win-power-base-l1-1-0.dll", # "api-ms-win-power-setting-l1-1-0.dll", # "api-ms-win-shcore-scaling-l1-1-1.dll", ] # ✅ DLL 경로 설정 (Windows 10의 System32에서 가져오기) system32_path = "C:/Windows/System32/downlevel" dll_include_files = [(os.path.join(system32_path, dll), dll) for dll in dll_files] dll_include_files = [] # 충돌 가능성으로 인해 빈 리스트로 초기화 # 패들 라이브러리 경로 설정 (ONNX 사용으로 비활성화) # 경로 수정: scripts/Lib -> Lib로 변경 base_path = os.path.dirname(os.path.abspath(__file__)) site_packages = os.path.join(base_path, "Lib", "site-packages") # 올바른 경로 지정 (PaddlePaddle 비활성화) # paddle_path = os.path.join(site_packages, "paddle") # paddleocr_path = os.path.join(site_packages, "paddleocr") paddle_includes = [] # PaddlePaddle 사용 안함 onnxruntime_includes = [] # NumPy .libs 경로 포함 (OpenBLAS 등 의존 DLL 로딩 문제 해결) numpy_includes = [] bin_path_includes_extra = [] numpy_libs_path = os.path.join(site_packages, "numpy.libs") if os.path.exists(numpy_libs_path): numpy_includes.append((numpy_libs_path, 'lib/numpy.libs')) bin_path_includes_extra.append(numpy_libs_path) print(f"numpy .libs 경로 추가: {numpy_libs_path}") # OpenCV(cv2) 패키지 폴더 포함 (config.py 누락 방지) cv2_includes = [] cv2_path = os.path.join(site_packages, 'cv2') if os.path.exists(cv2_path): cv2_includes.append((cv2_path, 'lib/cv2')) bin_path_includes_extra.append(cv2_path) print(f"cv2 경로 추가: {cv2_path}") # Shapely .libs (GEOS) 포함 shapely_includes = [] shapely_libs_path = os.path.join(site_packages, 'shapely.libs') if os.path.exists(shapely_libs_path): shapely_includes.append((shapely_libs_path, 'lib/shapely.libs')) bin_path_includes_extra.append(shapely_libs_path) print(f"shapely.libs 경로 추가: {shapely_libs_path}") # Pandas .libs 포함 pandas_includes = [] pandas_libs_path = os.path.join(site_packages, 'pandas.libs') if os.path.exists(pandas_libs_path): pandas_includes.append((pandas_libs_path, 'lib/pandas.libs')) bin_path_includes_extra.append(pandas_libs_path) print(f"pandas.libs 경로 추가: {pandas_libs_path}") # 경로가 존재하는 경우에만 포함 (PaddlePaddle 비활성화) # if os.path.exists(paddle_path): # paddle_includes.append((paddle_path, 'lib/paddle')) # print(f"paddle 경로 추가: {paddle_path}") # if os.path.exists(paddleocr_path): # paddle_includes.append((paddleocr_path, 'lib/paddleocr')) # print(f"paddleocr 경로 추가: {paddleocr_path}") # ONNXRuntime DirectML 관련 파일들 포함 onnxruntime_path = os.path.join(site_packages, 'onnxruntime') onnxruntime_capi = os.path.join(onnxruntime_path, 'capi') if os.path.exists(onnxruntime_capi): onnxruntime_includes.append((onnxruntime_capi, 'lib/onnxruntime/capi')) print(f"onnxruntime capi 경로 추가: {onnxruntime_capi}") # ONNXRuntime GPU 전체 패키지 포함 if os.path.exists(onnxruntime_path): onnxruntime_includes.append((onnxruntime_path, 'lib/onnxruntime')) print(f"onnxruntime 전체 경로 추가: {onnxruntime_path}") vc_runtime_files = [ ('C:/Windows/System32/vcruntime140.dll', 'vcruntime140.dll'), ('C:/Windows/System32/vcruntime140_1.dll', 'vcruntime140_1.dll'), ('C:/Windows/System32/msvcp140.dll', 'msvcp140.dll'), ('C:/Windows/System32/msvcp140_1.dll', 'msvcp140_1.dll'), ('C:/Windows/System32/msvcp140_2.dll', 'msvcp140_2.dll'), ('C:/Windows/System32/concrt140.dll', 'concrt140.dll'), ('C:/Windows/System32/vcomp140.dll', 'vcomp140.dll'), ] # DirectML 사용: Windows GPU 가속을 위해 DirectML 기반 ONNXRuntime 사용 # ✅ 기존 포함 파일 + DLL 추가 include_files = dll_include_files + paddle_includes + onnxruntime_includes + vc_runtime_files + [ # 나머지 파일들 # ('src/ppocr/PP_Models', 'lib/src/ppocr/PP_Models'), # PaddlePaddle 모델 비활성화 ('src/Edit_PartTimer3.ico', 'lib/src/Edit_PartTimer3.ico'), # 아이콘 파일 경로 수정 ('win.exe.manifest', 'win.exe.manifest'), ('libssl-3-x64.dll', 'libssl-3-x64.dll'), ('libcrypto-3-x64.dll', 'libcrypto-3-x64.dll'), ('kiprisCategories.json', 'kiprisCategories.json'), ('src/keyword/kiprisCategories.json', 'lib/src/keyword/kiprisCategories.json'), ('src/modules/fonts/Cafe24Ohsquare-v2.0.ttf', 'lib/src/fonts/Cafe24Ohsquare-v2.0.ttf'), ('src/modules/fonts/gamtanload.ttf', 'lib/src/fonts/gamtanload.ttf'), ('src/modules/fonts/NanumBarunGothic.ttf', 'lib/src/fonts/NanumBarunGothic.ttf'), ('src/modules/fonts/NanumSquareRoundR.ttf', 'lib/src/fonts/NanumSquareRoundR.ttf'), ('src/modules/fonts/HakgyoansimDunggeunmisoTTFB.ttf', 'lib/src/fonts/HakgyoansimDunggeunmisoTTFB.ttf'), ('src/modules/fonts/Cafe24Ohsquare-v2.0.ttf', 'lib/src/modules/fonts/Cafe24Ohsquare-v2.0.ttf'), ('src/modules/fonts/gamtanload.ttf', 'lib/src/modules/fonts/gamtanload.ttf'), ('src/modules/fonts/NanumBarunGothic.ttf', 'lib/src/modules/fonts/NanumBarunGothic.ttf'), ('src/modules/fonts/NanumSquareRoundR.ttf', 'lib/src/modules/fonts/NanumSquareRoundR.ttf'), ('src/modules/fonts/HakgyoansimDunggeunmisoTTFB.ttf', 'lib/src/modules/fonts/HakgyoansimDunggeunmisoTTFB.ttf'), ('src/modules/migan_onnx/migan_pipeline_v2.onnx', 'lib/src/modules/migan_onnx/migan_onnx/migan_pipeline_v2.onnx'), # ONNX OCR 모듈 파일들 포함 ('src/modules/onnx_ocr_module', 'lib/src/modules/onnx_ocr_module'), ('퍼센티 다양한 카테고리 엑셀 수집(스스 기준).xlsx', '퍼센티 다양한 카테고리 엑셀 수집(스스 기준).xlsx'), ('src/Percenty_SS_Code.json', 'lib/src/Percenty_SS_Code.json'), ('src/browsers/chromium-1155', 'lib/src/browsers/chromium-1155'), # ('src/browsers/whale', 'lib/src/browsers/whale'), ('src/browsers/extensions', 'lib/src/browsers/extensions'), # ('src/browsers/user_data', 'lib/src/browsers/user_data'), # ('src/browsers/whale/user_data', 'lib/src/browsers/whale/user_data'), # (pyside6_bin_path, "PySide6"), # PySide6 DLL 파일 경로 # (pyside6_plugins_path, "PySide6/plugins"), # plugins 경로 추가 ('C:/Windows/System32/vcomp140.dll', 'vcomp140.dll'), ] for src, dest in include_files: if not os.path.exists(src): print(f"경로가 존재하지 않습니다: {src}") # 사용된 패키지 정의 build_exe_options = { 'include_msvcr': True, # VC++ 런타임 자동 포함 'packages': [ 'ctypes', 'asyncio', 'subprocess', 'pyperclip', 'numpy', 'cv2', 'requests', 'pyclipper', 'skimage', 'PIL', 'bs4', 'PySide6', 'psutil', # 'win32api', 'win32file', 'win32pipe', 'win32event', 'pywintypes', 'win32con', 'win32process', 'win32clipboard', 'win32gui', 'pandas', 'supabase', 'translatepy', 'markdown', # supabase 전체 생태계 패키지들 (모든 하위 모듈 자동 포함) 'supabase', 'gotrue', 'storage3', 'postgrest', 'supafunc', 'realtime', # pydantic 생태계 (전체 포함) 'pydantic', 'pydantic_core', # json 모듈 순환 import 문제 해결 'json', 'json.encoder', 'json.decoder', 'json.scanner', # httpx 의존성 모듈들 추가 'httpx', 'httpx.__version__', 'httpx._models', 'httpx._client', 'httpx._config', # idna 모듈 (URL 인코딩) 추가 'idna', 'idna.core', 'idna.idnadata', 'idna.package_data', # 'paddle', 'paddleocr', # paddle 관련 모듈 포함 (ONNX 사용으로 비활성화) 'onnxruntime', # DirectML 지원 ONNXRuntime 추가 # numpy/scipy 관련 패키지 (기본 지원) 'scipy', 'scipy.special', 'scipy.sparse', 'scipy.linalg', 'scipy.ndimage', 'supabase', 'gotrue', 'storage3', 'postgrest', 'supafunc', 'realtime', 'websockets','shapely', 'anyio', 'sniffio', 'h11', 'certifi', 'pydantic_core', # realtime/httpx 계열 런타임 의존성 ], 'includes': [ # 'PySide6.QtWidgets', 'PySide6.QtCore', 'PySide6.QtGui', 'shiboken6','playwright','comtypes.stream', 'win32com.client', 'win32com.server', 'pythoncom', 'loggerModule', 'toggleSwitch', 'src.modules.request_inpaint', 'onnxruntime', 'browser_control', 'locatorManager', 'src.cmdDiag', 'src.inputDiag', 'src.keyword', 'src.priceSetDiag', 'src.modules.image_processor3', 'src.modules.gpu_utils', 'src.modules.migan_module', 'src.modules.background_removal_module', # 새로 추가된 GPU 관련 모듈들 # 'src.modules.ocr_module', # PaddleOCR 모듈 비활성화 (ONNX 사용) 'src.modules.gpu_status_checker', 'src.gpuDiag', # 누락된 중요 모듈들 추가 'src.modules.postImageManager', 'src.modules.mask_module_for_paddle', 'src.modules.text_rendering_module', 'src.modules.onnx_ocr_module', 'src.modules.onnx_ocr_module.src.onnx_ocr_wrapper', # ONNX OCR 모듈 추가 'src.modules.image_worker', # OCR backends는 ONNX 모듈로 대체 # 'src.modules.ocr_backends', 'src.modules.ocr_backends.fastdeploy_ocr', 'src.modules.ocr_backends.onnx_ocr', # 개별 백엔드 비활성화 'translatepy', 'translatepy.translators', 'translatepy.translators.google', # supabase 전체 생태계를 includes에도 추가 'supabase', 'gotrue', 'storage3', 'postgrest', 'supafunc', 'realtime', # pydantic 생태계를 includes에도 추가 'pydantic', 'pydantic_core', # json 순환 import 문제 해결을 위한 명시적 포함 'json', 'json.encoder', 'json.decoder', 'json.scanner', # httpx 의존성 모듈들을 includes에도 추가 'httpx', 'httpx.__version__', 'httpx._models', 'httpx._client', 'httpx._config', # idna 모듈을 includes에도 추가 'idna', 'idna.core', 'idna.idnadata', 'idna.package_data', # pathlib 명시적 포함 (PySide6에서 필요) 'pathlib', 'skimage', 'skimage.morphology', 'skimage.measure', 'skimage.filters', 'skimage.color', 'skimage.util', 'imghdr', 'imgaug', 'rapidfuzz', 'albumentations', 'albumentations', 'cython', 'fire', 'lmdb', 'PIL', 'docx', 'yaml', 'shapely', 'tqdm', # PIL과 관련된 추가 모듈들 'PIL.Image', 'PIL.ImageFont', 'PIL.ImageDraw', 'PIL.features', ], 'include_files': include_files, 'excludes': [ 'tkinter', 'PyQt4', 'PyQt5', 'AppKit', 'Foundation', 'IPython', 'OpenSSL', 'curses', 'test', 'matplotlib', 'asyncpg', # # 순환 import 문제 해결을 위한 주요 모듈들 제외 # 'unittest', 'unittest.case', 'unittest.loader', 'unittest.suite', # 'unittest.runner', 'unittest.signals', 'unittest._log', 'unittest.util', # 'unittest.async_case', # asyncio와 unittest 연결 모듈 제외 # 실제 순환 import 원인인 테스트 관련 모듈들 제외 # 'numpy._pytesttester', 'numpy.testing', 'scipy._lib._testutils', # importlib 관련 - metadata는 pydantic에서 필요하므로 제외하지 않음 'importlib._bootstrap', 'importlib.machinery', # Paddle 계열 완전 제외 (ONNX 전용 실행) 'paddle', 'paddleocr', 'paddlehub', # shiboken6 순환 참조 문제 해결 # 'shiboken6.Shiboken', 'shiboken6.libshiboken', # 기타 순환 참조 관련 모듈들 # 'pkg_resources', 'setuptools', 'wheel', 'pip', # 개발/테스트 도구들 제외 'pytest', 'hypothesis', 'mypy', 'coverage', 'tox', 'sympy', # ★ 가장 중요 'sympy.core', 'sympy.ntheory', 'sympy.external', 'sympy.polys', 'sympy.*', # 와일드카드가 버전에 따라 안 먹을 수 있어도 넣어두면 좋음 'mpmath', 'gmpy2', ], 'zip_include_packages': [], # 아무 패키지도 압축하지 않음 (numpy 관련 문제 해결) 'optimize': 0, # 바이트 코드 최적화 비활성화 (numpy/scipy 호환성 보장) 'silent': True, # 디버그 메시지 활성화 # numpy 바이너리 파일 강제 포함 'include_msvcr': True, # VC++ 런타임 포함 'bin_path_includes': bin_path_includes_extra, } # 애플리케이션 메인 파일 및 설정 base = None if sys.platform == 'win32': base = 'Win32GUI' # ✅ 아이콘 지정: icon='파일경로.ico' executables = [ Executable( 'main.py', base=base, target_name='Edit_PartTimer3.exe', icon="Edit_PartTimer3.ico" ) ] # build_exe 클래스를 확장하여 빌드 전 의존성 체크 및 빌드 후 iss 파일 생성 class build_exe(_build_exe): def run(self): # 빌드 전 의존성 체크 및 수정 print("\n[도구] 빌드 전 의존성 체크 시작...") try: result = subprocess.run([sys.executable, "check_dependencies.py"], capture_output=True, text=True) if result.returncode == 0: print("[성공] 의존성 체크 완료") print(result.stdout) else: print("[실패] 의존성 체크 실패:") print(result.stdout) print(result.stderr) print("\n[경고] 의존성 문제로 인해 빌드를 중단합니다.") return except Exception as e: print(f"[오류] 의존성 체크 중 예외 발생: {e}") print("[경고] 의존성 체크를 건너뛰고 빌드를 계속합니다.") # # 빌드 전에 로그 레벨을 INFO로 변경 # self._set_log_level_for_production() # 원래 빌드 프로세스 실행 _build_exe.run(self) print("\n빌드가 완료되었습니다. 이제 Inno Setup 스크립트 생성을 시작합니다...\n") try: # generate_iss.py 스크립트 실행 result = subprocess.run([sys.executable, "generate_iss.py"], capture_output=True, text=True) if result.returncode == 0: print(result.stdout) print("\nInno Setup 스크립트 생성이 완료되었습니다!") else: print(f"Inno Setup 스크립트 생성 중 오류 발생: {result.stderr}") except Exception as e: print(f"Inno Setup 스크립트 생성 중 예외 발생: {e}") # def _set_log_level_for_production(self): # """패키징 시 로그 레벨을 INFO로 설정합니다""" # version_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'updateManager', '__version__.py') # # 파일 내용 읽기 # with open(version_file_path, 'r', encoding='utf-8') as f: # content = f.read() # # DEBUG를 INFO로 변경 # if 'logging.DEBUG' in content: # content = content.replace('__log_level__ = logging.DEBUG', '__log_level__ = logging.INFO') # # 변경된 내용 저장 # with open(version_file_path, 'w', encoding='utf-8') as f: # f.write(content) # print("로그 레벨이 배포 버전에 맞게 INFO로 변경되었습니다.") if __name__ == '__main__': # Setup 설정 (cmdclass에 build_exe 추가) setup( name=__title__, version=__version__, description=__description__, author=__author__, author_email=__author_email__, license=__license__, packages=find_packages(), install_requires=__install_requires__, python_requires='>=3.11', include_package_data=True, zip_safe=False, options={'build_exe': build_exe_options}, executables=executables, cmdclass={ "build_exe": build_exe, }, )