101 lines
4.0 KiB
Python
101 lines
4.0 KiB
Python
import os
|
|
import sys
|
|
import subprocess
|
|
import shutil
|
|
|
|
def run_command(command, env=None):
|
|
"""Helper to run system commands and stream the output to the console"""
|
|
process = subprocess.Popen(
|
|
command,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
shell=True,
|
|
text=True,
|
|
env=env
|
|
)
|
|
while True:
|
|
output = process.stdout.readline()
|
|
if output == '' and process.poll() is not None:
|
|
break
|
|
if output:
|
|
print(output.strip())
|
|
return process.poll()
|
|
|
|
if __name__ == "__main__":
|
|
current_dir = os.path.dirname(os.path.realpath(__file__))
|
|
venv_dir = os.path.join(current_dir, "builder_env")
|
|
|
|
# Calculate the root folder path (my_universal_dropdowns)
|
|
# Moving up two levels from: .../my_universal_dropdowns/generator/build.py
|
|
root_dir = os.path.abspath(os.path.join(current_dir, ".."))
|
|
final_exe_path = os.path.join(root_dir, "Node Builder Assistant.exe")
|
|
|
|
print("🚀 Starting One-Click Standalone Executable Builder...\n")
|
|
|
|
# 1. Create Virtual Environment
|
|
if not os.path.exists(venv_dir):
|
|
print("📦 Step 1: Creating isolated virtual environment...")
|
|
if run_command(f'"{sys.executable}" -m venv builder_env') != 0:
|
|
print("❌ Failed to create virtual environment.")
|
|
sys.exit(1)
|
|
else:
|
|
print("✨ Virtual environment already exists, skipping creation.")
|
|
|
|
# Determine paths inside venv based on OS
|
|
if os.name == 'nt': # Windows
|
|
pip_path = os.path.join(venv_dir, "Scripts", "pip.exe")
|
|
pyinstaller_path = os.path.join(venv_dir, "Scripts", "pyinstaller.exe")
|
|
else: # Mac/Linux fallback
|
|
pip_path = os.path.join(venv_dir, "bin", "pip")
|
|
pyinstaller_path = os.path.join(venv_dir, "bin", "pyinstaller")
|
|
|
|
# 2. Upgrade pip and install requirements
|
|
print("\n📥 Step 2: Installing requirements into isolated environment...")
|
|
run_command(f'"{pip_path}" install --upgrade pip')
|
|
|
|
req_file = os.path.join(current_dir, "requirements.txt")
|
|
if os.path.exists(req_file):
|
|
if run_command(f'"{pip_path}" install -r "{req_file}"') != 0:
|
|
print("❌ Failed to install dependencies.")
|
|
sys.exit(1)
|
|
else:
|
|
print("❌ requirements.txt not found! Please create it first.")
|
|
sys.exit(1)
|
|
|
|
# 3. Compile with PyInstaller
|
|
print("\n🛠️ Step 3: Compiling hyper-lean executable via PyInstaller...")
|
|
build_cmd = f'"{pyinstaller_path}" --clean --noconsole --onefile --add-data "generator.html;." app.py'
|
|
|
|
if run_command(build_cmd) == 0:
|
|
print("\n✅ Compilation successful!")
|
|
|
|
# 4. Relocate and Rename the Executable
|
|
print("\n🚚 Step 4: Moving and renaming executable to root directory...")
|
|
compiled_exe = os.path.join(current_dir, "dist", "app.exe")
|
|
|
|
try:
|
|
# Overwrite if it already exists from a previous build
|
|
if os.path.exists(final_exe_path):
|
|
os.remove(final_exe_path)
|
|
|
|
shutil.move(compiled_exe, final_exe_path)
|
|
print(f"✨ Successfully deployed to: {final_exe_path}")
|
|
except Exception as e:
|
|
print(f"❌ Failed to move or rename executable: {e}")
|
|
|
|
# 5. Clean up temporary build clutter
|
|
print("\n扫 Step 5: Cleaning up temporary build clutter...")
|
|
build_folder = os.path.join(current_dir, "build")
|
|
dist_folder = os.path.join(current_dir, "dist")
|
|
spec_file = os.path.join(current_dir, "app.spec")
|
|
|
|
if os.path.exists(build_folder):
|
|
shutil.rmtree(build_folder)
|
|
if os.path.exists(dist_folder):
|
|
shutil.rmtree(dist_folder)
|
|
if os.path.exists(spec_file):
|
|
os.remove(spec_file)
|
|
|
|
print("✨ Temporary build cache deleted. Process complete!")
|
|
else:
|
|
print("\n❌ PyInstaller compilation failed.") |