-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.py
More file actions
97 lines (83 loc) · 2.93 KB
/
Copy pathbuild.py
File metadata and controls
97 lines (83 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""PyInstaller 단일 exe 빌드.
`python build.py` → dist\\Classroom공지관리자.exe
--windowed로 만들면 콘솔 창이 뜨지 않는다. 대신 stdout/stderr가 없어지므로
로그는 %LOCALAPPDATA%\\gcrmanager\\gcrmanager.log 파일로만 남는다
(__main__.setup_logging이 이 경우를 처리한다).
"""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).parent
NAME = "Classroom공지관리자"
def main() -> int:
for stale in ("build", "dist"):
target = ROOT / stale
if not target.exists():
continue
print(f"이전 빌드 정리: {target}")
try:
shutil.rmtree(target)
except PermissionError:
# --onefile 부트로더는 자식 프로세스를 띄우므로, 창을 닫아도
# 프로세스가 남아 exe 파일이 잠겨 있을 수 있다.
print(
f"\n'{target}' 를 지울 수 없습니다. 이전에 빌드한 앱이 아직 "
"실행 중일 수 있습니다.\n"
f"작업 관리자에서 '{NAME}' 프로세스를 종료한 뒤 다시 실행하세요.\n"
f" PowerShell: Get-Process '{NAME}' | Stop-Process -Force",
file=sys.stderr,
)
return 1
args = [
sys.executable,
"-m",
"PyInstaller",
"--noconfirm",
"--clean",
"--onefile",
"--windowed",
"--name",
NAME,
# google-api-python-client가 런타임에 동적으로 불러오는 모듈들.
# 이게 없으면 번들에서 "No module named ..."로 죽는다.
"--hidden-import",
"googleapiclient.discovery",
"--hidden-import",
"google.auth.transport.requests",
# keyring은 백엔드를 entry point로 찾으므로 명시해야 한다.
"--hidden-import",
"keyring.backends.Windows",
"--collect-submodules",
"keyring.backends",
# 쓰지 않는 Qt 모듈을 빼서 용량을 줄인다.
"--exclude-module",
"PySide6.QtQml",
"--exclude-module",
"PySide6.QtQuick",
"--exclude-module",
"PySide6.Qt3DCore",
"--exclude-module",
"PySide6.QtWebEngineCore",
"--exclude-module",
"PySide6.QtMultimedia",
"--exclude-module",
"tkinter",
]
icon = ROOT / "assets" / "app.ico"
if icon.exists():
args += ["--icon", str(icon)]
args.append("run.py")
print("빌드 시작…")
result = subprocess.run(args, cwd=ROOT)
if result.returncode != 0:
print("빌드 실패", file=sys.stderr)
return result.returncode
exe = ROOT / "dist" / f"{NAME}.exe"
if exe.exists():
size_mb = exe.stat().st_size / 1_048_576
print(f"\n완료: {exe} ({size_mb:.0f} MB)")
return 0
if __name__ == "__main__":
raise SystemExit(main())