Skip to content

Commit 81cc693

Browse files
committed
feat: Add PyInstaller build script with debug mode handling and update gitignore to exclude build artifacts.
1 parent 654bcbe commit 81cc693

2 files changed

Lines changed: 121 additions & 1 deletion

File tree

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,10 @@ __pycache__/
33
implementation_plan.md
44
task.md
55
walkthrough.md
6-
config.ini
6+
config.ini
7+
8+
9+
# Build artifacts
10+
build/
11+
dist/
12+
*.spec

build.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import configparser
2+
import os
3+
import shutil
4+
import subprocess
5+
import sys
6+
7+
CONFIG_FILES = ['config.ini', 'config.cfg']
8+
OUTPUT_DIR = 'dist'
9+
BUILD_DIR = 'build'
10+
EXECUTABLE_NAME = 'RainingKeysPython'
11+
MAIN_SCRIPT = 'main.py'
12+
13+
def read_config():
14+
"""
15+
Reads debug_mode from config.ini or config.cfg.
16+
Returns boolean: True (Debug), False (Release).
17+
Defaults to False if not specified.
18+
"""
19+
config = configparser.ConfigParser()
20+
21+
# Try to read config files
22+
found_files = config.read(CONFIG_FILES)
23+
if not found_files:
24+
print(f"Warning: No config file found ({'/'.join(CONFIG_FILES)}). Defaulting to Release mode.")
25+
return False
26+
27+
# Check for debug_mode in [General] section (or others if widely used)
28+
# We prioritize [General] > [Debug] > global search if needed, but [General] is standard.
29+
if config.has_section('General'):
30+
if config.has_option('General', 'debug_mode'):
31+
return config.getboolean('General', 'debug_mode')
32+
33+
# Fallback: check if it's in a [Debug] section
34+
if config.has_section('Debug'):
35+
if config.has_option('Debug', 'debug_mode'):
36+
return config.getboolean('Debug', 'debug_mode')
37+
38+
print("Info: 'debug_mode' not found in config. Defaulting to Release mode.")
39+
return False
40+
41+
def clean_directories():
42+
"""Removes build and dist directories."""
43+
dirs_to_clean = [OUTPUT_DIR, BUILD_DIR]
44+
for d in dirs_to_clean:
45+
if os.path.exists(d):
46+
print(f"Cleaning {d}...")
47+
shutil.rmtree(d)
48+
49+
def build(debug_mode):
50+
"""Invokes PyInstaller to build the executable."""
51+
print(f"Building {EXECUTABLE_NAME} (Debug Mode: {debug_mode})...")
52+
53+
cmd = [
54+
'pyinstaller',
55+
'--onedir',
56+
'--clean',
57+
'--name', EXECUTABLE_NAME,
58+
MAIN_SCRIPT
59+
]
60+
61+
if not debug_mode:
62+
cmd.extend(['--noconsole', '--windowed'])
63+
# Else: keep console (default behavior for pyinstaller without --noconsole)
64+
65+
# Note: We don't explicitly add --add-data here because we copy config manually after build.
66+
# If hidden imports are needed (e.g. pynput, PySide6), PyInstaller usually finds them.
67+
# If issues arise, we can add --hidden-import.
68+
69+
# Run PyInstaller
70+
subprocess.check_call(cmd)
71+
72+
def copy_config_to_dist():
73+
"""Copies the existing config file to the dist directory."""
74+
target_dir = os.path.join(OUTPUT_DIR, EXECUTABLE_NAME)
75+
if not os.path.exists(target_dir):
76+
os.makedirs(target_dir)
77+
78+
copied = False
79+
for cfg in CONFIG_FILES:
80+
if os.path.exists(cfg):
81+
input_config = cfg
82+
shutil.copy2(input_config, target_dir)
83+
print(f"Copied {input_config} to {target_dir}")
84+
copied = True
85+
break
86+
87+
if not copied:
88+
print("Warning: No config file found to copy.")
89+
90+
def main():
91+
# 1. Clean previous builds
92+
clean_directories()
93+
94+
# 2. Determine mode
95+
debug_mode = read_config()
96+
97+
# 3. Build
98+
try:
99+
build(debug_mode)
100+
except subprocess.CalledProcessError as e:
101+
print(f"Error during build: {e}")
102+
sys.exit(1)
103+
except FileNotFoundError:
104+
print("Error: 'pyinstaller' not found. Please install it via 'pip install pyinstaller'.")
105+
sys.exit(1)
106+
107+
# 4. Copy config
108+
copy_config_to_dist()
109+
110+
print("\nBuild complete!")
111+
print(f"Output: {os.path.join(OUTPUT_DIR, EXECUTABLE_NAME)}")
112+
113+
if __name__ == "__main__":
114+
main()

0 commit comments

Comments
 (0)